1
0
Fork 0
mirror of https://codeberg.org/tyy/aspm synced 2024-12-22 18:19:28 -07:00

Rename to naja

This commit is contained in:
Tyler Beckman 2024-07-11 20:38:57 -06:00
parent 29c940c623
commit 76d0dbc41d
Signed by: Ty
GPG key ID: 2813440C772555A4
46 changed files with 217 additions and 233 deletions

View file

@ -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
View 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
View file

@ -206,56 +206,6 @@ dependencies = [
"term", "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]] [[package]]
name = "assert_cmd" name = "assert_cmd"
version = "2.0.14" version = "2.0.14"
@ -691,6 +641,14 @@ version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4b82cf0babdbd58558212896d1a4272303a57bdb245c2bf1147185fb45640e70" checksum = "4b82cf0babdbd58558212896d1a4272303a57bdb245c2bf1147185fb45640e70"
[[package]]
name = "cli-migrations"
version = "0.1.0"
dependencies = [
"sea-orm-migration",
"tokio",
]
[[package]] [[package]]
name = "colorchoice" name = "colorchoice"
version = "1.0.1" version = "1.0.1"
@ -1962,14 +1920,6 @@ version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c797b9d6bb23aab2fc369c65f871be49214f5c759af65bde26ffaaa2b646b492" checksum = "c797b9d6bb23aab2fc369c65f871be49214f5c759af65bde26ffaaa2b646b492"
[[package]]
name = "migrations"
version = "0.1.0"
dependencies = [
"sea-orm-migration",
"tokio",
]
[[package]] [[package]]
name = "mime" name = "mime"
version = "0.3.17" version = "0.3.17"
@ -2002,6 +1952,56 @@ dependencies = [
"windows-sys 0.48.0", "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]] [[package]]
name = "native-tls" name = "native-tls"
version = "0.2.12" version = "0.2.12"

View file

@ -1,7 +1,7 @@
[workspace] [workspace]
members = ["crates/*"] members = ["crates/*"]
resolver = "2" resolver = "2"
default-members = ["crates/aspm"] default-members = ["crates/naja-cli"]
[profile.release] [profile.release]
strip = true strip = true

View file

@ -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 # 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.

View file

@ -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))
}
}

View file

@ -1,5 +1,5 @@
[package] [package]
name = "migrations" name = "cli-migrations"
version = "0.1.0" version = "0.1.0"
edition = "2021" edition = "2021"

View file

@ -2,5 +2,5 @@ use sea_orm_migration::cli;
#[tokio::main] #[tokio::main]
async fn main() { async fn main() {
cli::run_cli(migrations::Migrator).await; cli::run_cli(cli_migrations::Migrator).await;
} }

View file

@ -1,13 +1,13 @@
[package] [package]
name = "aspm-cli" name = "naja-cli"
authors = ["Ty"] authors = ["Ty"]
description = "A tool to manage ariadne signature profiles, implementing v0 of the specification" 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" version = "0.1.0"
edition = "2021" edition = "2021"
[[bin]] [[bin]]
name = "aspm" name = "naja"
path = "src/main.rs" path = "src/main.rs"
[dependencies] [dependencies]
@ -15,7 +15,7 @@ anyhow = "1.0.86"
app_dirs2 = "2.5.5" app_dirs2 = "2.5.5"
clap = { version = "4.5.8", features = ["derive", "unstable-styles", "env"] } clap = { version = "4.5.8", features = ["derive", "unstable-styles", "env"] }
thiserror = "1.0.61" thiserror = "1.0.61"
asp = { path = "../asp" } naja-lib = { path = "../naja-lib" }
indoc = "2.0.5" indoc = "2.0.5"
anstyle = "1.0.7" anstyle = "1.0.7"
dialoguer = { version = "0.11.0", features = ["password"] } 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 } sequoia-openpgp = { version = "1.21.1", optional = true }
josekit = { version = "0.8.6" } josekit = { version = "0.8.6" }
aes-gcm = "0.10.3" aes-gcm = "0.10.3"
migrations = { path = "../migrations" } migrations = { path = "../cli-migrations", package = "cli-migrations" }
scrypt = "0.11.0" scrypt = "0.11.0"
serde = { version = "1.0.204", features = ["derive"] } serde = { version = "1.0.204", features = ["derive"] }
serde_json = "1.0.120" serde_json = "1.0.120"

View file

@ -1,7 +1,7 @@
use aes_gcm::{aead::Aead, Aes256Gcm, Key, KeyInit as _}; use aes_gcm::{aead::Aead, Aes256Gcm, Key, KeyInit as _};
use anyhow::{anyhow, bail, Context}; use anyhow::{anyhow, bail, Context};
use argon2::{password_hash::SaltString, Argon2, PasswordHasher as _}; use argon2::{password_hash::SaltString, Argon2, PasswordHasher as _};
use asp::{ use naja_lib::{
aspe::{ aspe::{
requests::{AspeRequest, AspeRequestType, AspeRequestVariant}, requests::{AspeRequest, AspeRequestType, AspeRequestVariant},
AspeRequestFailure, AspeServer, AspeRequestFailure, AspeServer,
@ -17,7 +17,7 @@ use josekit::jwk::Jwk;
use sea_orm::{ColumnTrait, Condition, EntityTrait, QueryFilter}; use sea_orm::{ColumnTrait, Condition, EntityTrait, QueryFilter};
use crate::{ use crate::{
commands::AspmSubcommand, commands::NajaSubcommand,
entities::{keys, prelude::*}, entities::{keys, prelude::*},
}; };
@ -32,8 +32,8 @@ pub struct AspeDeleteCommand {
} }
#[async_trait::async_trait] #[async_trait::async_trait]
impl AspmSubcommand for AspeDeleteCommand { impl NajaSubcommand for AspeDeleteCommand {
async fn execute(self, state: crate::AspmState) -> Result<(), anyhow::Error> { async fn execute(self, state: crate::CliState) -> Result<(), anyhow::Error> {
let server = AspeServer::new(self.server) let server = AspeServer::new(self.server)
.await .await
.context("Unable to parse provided server into ASPE server, please verify that it is a valid ASPE server")?; .context("Unable to parse provided server into ASPE server, please verify that it is a valid ASPE server")?;

View file

@ -1,7 +1,7 @@
use aes_gcm::{aead::Aead, Aes256Gcm, Key, KeyInit as _}; use aes_gcm::{aead::Aead, Aes256Gcm, Key, KeyInit as _};
use anyhow::{anyhow, bail, Context}; use anyhow::{anyhow, bail, Context};
use argon2::{password_hash::SaltString, Argon2, PasswordHasher as _}; use argon2::{password_hash::SaltString, Argon2, PasswordHasher as _};
use asp::{ use naja_lib::{
aspe::{ aspe::{
requests::{AspeRequest, AspeRequestType, AspeRequestVariant}, requests::{AspeRequest, AspeRequestType, AspeRequestVariant},
AspeFetchFailure, AspeRequestFailure, AspeServer, AspeFetchFailure, AspeRequestFailure, AspeServer,
@ -20,7 +20,7 @@ use josekit::jwk::Jwk;
use sea_orm::{ColumnTrait, Condition, EntityTrait, ModelTrait, QueryFilter}; use sea_orm::{ColumnTrait, Condition, EntityTrait, ModelTrait, QueryFilter};
use crate::{ use crate::{
commands::AspmSubcommand, commands::NajaSubcommand,
entities::{prelude::*, profiles}, entities::{prelude::*, profiles},
}; };
@ -41,8 +41,8 @@ pub struct AspeUploadCommand {
} }
#[async_trait::async_trait] #[async_trait::async_trait]
impl AspmSubcommand for AspeUploadCommand { impl NajaSubcommand for AspeUploadCommand {
async fn execute(self, state: crate::AspmState) -> Result<(), anyhow::Error> { async fn execute(self, state: crate::CliState) -> Result<(), anyhow::Error> {
let server = AspeServer::new(self.server) let server = AspeServer::new(self.server)
.await .await
.context("Unable to parse provided server into ASPE server, please verify that it is a valid ASPE server")?; .context("Unable to parse provided server into ASPE server, please verify that it is a valid ASPE server")?;

View file

@ -1,6 +1,6 @@
use anstyle::{AnsiColor, Reset, Style as Anstyle}; use anstyle::{AnsiColor, Reset, Style as Anstyle};
use anyhow::Context; use anyhow::Context;
use asp::keys::AspKeyType; use naja_lib::keys::AspKeyType;
use clap::Parser; use clap::Parser;
use dialoguer::{console::Term, theme::ColorfulTheme, Confirm}; use dialoguer::{console::Term, theme::ColorfulTheme, Confirm};
use indoc::writedoc; use indoc::writedoc;
@ -8,7 +8,7 @@ use sea_orm::ModelTrait as _;
use std::io::Write; use std::io::Write;
use crate::{commands::AspmSubcommand, utils}; use crate::{commands::NajaSubcommand, utils};
/// Deletes a saved key, after asking for confirmation. /// Deletes a saved key, after asking for confirmation.
#[derive(Parser, Debug)] #[derive(Parser, Debug)]
@ -21,8 +21,8 @@ pub struct KeysDeleteCommand {
} }
#[async_trait::async_trait] #[async_trait::async_trait]
impl AspmSubcommand for KeysDeleteCommand { impl NajaSubcommand for KeysDeleteCommand {
async fn execute(self, state: crate::AspmState) -> Result<(), anyhow::Error> { async fn execute(self, state: crate::CliState) -> Result<(), anyhow::Error> {
// Fetch key from db // Fetch key from db
let key = utils::keys::query_key(&state.db, self.key).await?; let key = utils::keys::query_key(&state.db, self.key).await?;

View file

@ -4,14 +4,14 @@ use aes_gcm::{
}; };
use anstyle::{AnsiColor, Color as AnstyleColor, Reset, Style as Anstyle}; use anstyle::{AnsiColor, Color as AnstyleColor, Reset, Style as Anstyle};
use anyhow::Context as _; use anyhow::Context as _;
use asp::keys::AspKey; use naja_lib::keys::AspKey;
use clap::{Parser, ValueEnum}; use clap::{Parser, ValueEnum};
use data_encoding::{BASE64, BASE64_NOPAD}; use data_encoding::{BASE64, BASE64_NOPAD};
use dialoguer::{theme::ColorfulTheme, Password}; use dialoguer::{theme::ColorfulTheme, Password};
use josekit::jwk::Jwk; use josekit::jwk::Jwk;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::{commands::AspmSubcommand, utils}; use crate::{commands::NajaSubcommand, utils};
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
#[serde(tag = "alg", rename = "scrypt")] #[serde(tag = "alg", rename = "scrypt")]
@ -39,7 +39,7 @@ pub enum KeyExportFormat {
/// An unencrypted PKCS#8 format. /// An unencrypted PKCS#8 format.
#[clap(alias = "PKCS#8")] #[clap(alias = "PKCS#8")]
PKCS8, 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, ASPTool,
/// An unencrypted raw JSON Web Key (JWK) format. /// An unencrypted raw JSON Web Key (JWK) format.
Jwk, Jwk,
@ -56,8 +56,8 @@ pub struct KeysExportCommand {
} }
#[async_trait::async_trait] #[async_trait::async_trait]
impl AspmSubcommand for KeysExportCommand { impl NajaSubcommand for KeysExportCommand {
async fn execute(self, state: crate::AspmState) -> Result<(), anyhow::Error> { async fn execute(self, state: crate::CliState) -> Result<(), anyhow::Error> {
// Fetch key from db // Fetch key from db
let key = utils::keys::query_key(&state.db, self.key).await?; let key = utils::keys::query_key(&state.db, self.key).await?;

View file

@ -4,14 +4,14 @@ use aes_gcm::{
}; };
use anyhow::{anyhow, bail, Context}; use anyhow::{anyhow, bail, Context};
use argon2::{password_hash::SaltString, Argon2, PasswordHasher}; use argon2::{password_hash::SaltString, Argon2, PasswordHasher};
use asp::keys::{AspKey, AspKeyType}; use naja_lib::keys::{AspKey, AspKeyType};
use clap::{Parser, ValueEnum}; use clap::{Parser, ValueEnum};
use data_encoding::BASE64_NOPAD; use data_encoding::BASE64_NOPAD;
use dialoguer::{theme::ColorfulTheme, Confirm, Input, Password}; use dialoguer::{theme::ColorfulTheme, Confirm, Input, Password};
use indoc::printdoc; use indoc::printdoc;
use sea_orm::{ActiveValue, EntityTrait}; 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)] #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, ValueEnum, Debug)]
pub enum KeyGenerationType { pub enum KeyGenerationType {
@ -19,7 +19,7 @@ pub enum KeyGenerationType {
ES256, 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. /// 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)] #[derive(Parser, Debug)]
pub struct KeysGenerateCommand { pub struct KeysGenerateCommand {
@ -33,8 +33,8 @@ pub struct KeysGenerateCommand {
} }
#[async_trait::async_trait] #[async_trait::async_trait]
impl AspmSubcommand for KeysGenerateCommand { impl NajaSubcommand for KeysGenerateCommand {
async fn execute(self, state: crate::AspmState) -> Result<(), anyhow::Error> { async fn execute(self, state: crate::CliState) -> Result<(), anyhow::Error> {
if self.key_type == KeyGenerationType::Ed25519 { if self.key_type == KeyGenerationType::Ed25519 {
let confirmation = Confirm::with_theme(&ColorfulTheme::default()) 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?") .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?")

View file

@ -1,6 +1,6 @@
use anyhow::{anyhow, bail, Context}; use anyhow::{anyhow, bail, Context};
use argon2::{password_hash::SaltString, Argon2, PasswordHasher}; use argon2::{password_hash::SaltString, Argon2, PasswordHasher};
use asp::keys::AspKey; use naja_lib::keys::AspKey;
use clap::{Parser, ValueEnum}; use clap::{Parser, ValueEnum};
use data_encoding::{BASE64, BASE64URL_NOPAD, BASE64_NOPAD}; use data_encoding::{BASE64, BASE64URL_NOPAD, BASE64_NOPAD};
use dialoguer::{theme::ColorfulTheme, Input, Password}; use dialoguer::{theme::ColorfulTheme, Input, Password};
@ -14,7 +14,7 @@ use josekit::jwk::Jwk;
use sea_orm::{ActiveValue, EntityTrait}; use sea_orm::{ActiveValue, EntityTrait};
use crate::{ use crate::{
commands::{keys::export::ASPToolScryptExport, AspmSubcommand}, commands::{keys::export::ASPToolScryptExport, NajaSubcommand},
entities::keys, entities::keys,
}; };
@ -45,8 +45,8 @@ pub struct KeysImportCommand {
} }
#[async_trait::async_trait] #[async_trait::async_trait]
impl AspmSubcommand for KeysImportCommand { impl NajaSubcommand for KeysImportCommand {
async fn execute(self, state: crate::AspmState) -> Result<(), anyhow::Error> { async fn execute(self, state: crate::CliState) -> Result<(), anyhow::Error> {
let alias = if let Some(alias) = &self.key_alias { let alias = if let Some(alias) = &self.key_alias {
alias.clone() alias.clone()
} else { } else {

View file

@ -1,21 +1,21 @@
use anstyle::{AnsiColor, Reset, Style as Anstyle}; use anstyle::{AnsiColor, Reset, Style as Anstyle};
use anyhow::Context; use anyhow::Context;
use asp::keys::AspKeyType; use naja_lib::keys::AspKeyType;
use clap::Parser; use clap::Parser;
use indoc::writedoc; use indoc::writedoc;
use sea_orm::EntityTrait; use sea_orm::EntityTrait;
use std::io::Write; 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 /// A command to list all saved keys, along with their fingerprints and types
#[derive(Parser, Debug)] #[derive(Parser, Debug)]
pub struct KeysListCommand; pub struct KeysListCommand;
#[async_trait::async_trait] #[async_trait::async_trait]
impl AspmSubcommand for KeysListCommand { impl NajaSubcommand for KeysListCommand {
async fn execute(self, state: crate::AspmState) -> Result<(), anyhow::Error> { async fn execute(self, state: crate::CliState) -> Result<(), anyhow::Error> {
let entries = Keys::find() let entries = Keys::find()
.all(&state.db) .all(&state.db)
.await .await

View 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))
}
}

View file

@ -1,7 +1,7 @@
use std::str::FromStr; use std::str::FromStr;
use anyhow::Context; use anyhow::Context;
use asp::{ use naja_lib::{
hex_color::HexColor, keys::AspKeyType, profiles::*, serde_email::Email, url::Url, hex_color::HexColor, keys::AspKeyType, profiles::*, serde_email::Email, url::Url,
utils::jwt::AspJwsType, utils::jwt::AspJwsType,
}; };
@ -10,7 +10,7 @@ use dialoguer::{theme::ColorfulTheme, Input, Select};
use sea_orm::{ActiveValue, EntityTrait}; use sea_orm::{ActiveValue, EntityTrait};
use crate::{ use crate::{
commands::AspmSubcommand, commands::NajaSubcommand,
entities::{ entities::{
claims::{self, Entity as Claims}, claims::{self, Entity as Claims},
keys::Entity as Keys, keys::Entity as Keys,
@ -29,8 +29,8 @@ pub struct ProfilesCreateCommand {
} }
#[async_trait::async_trait] #[async_trait::async_trait]
impl AspmSubcommand for ProfilesCreateCommand { impl NajaSubcommand for ProfilesCreateCommand {
async fn execute(self, state: crate::AspmState) -> Result<(), anyhow::Error> { async fn execute(self, state: crate::CliState) -> Result<(), anyhow::Error> {
let theme = ColorfulTheme::default(); let theme = ColorfulTheme::default();
let alias = if let Some(alias) = &self.profile_alias { let alias = if let Some(alias) = &self.profile_alias {

View file

@ -7,7 +7,7 @@ use sea_orm::{EntityTrait, ModelTrait};
use std::io::Write; use std::io::Write;
use crate::{commands::AspmSubcommand, entities::prelude::*}; use crate::{commands::NajaSubcommand, entities::prelude::*};
/// Deletes a saved profile /// Deletes a saved profile
#[derive(Parser, Debug)] #[derive(Parser, Debug)]
@ -20,8 +20,8 @@ pub struct ProfilesDeleteCommand {
} }
#[async_trait::async_trait] #[async_trait::async_trait]
impl AspmSubcommand for ProfilesDeleteCommand { impl NajaSubcommand for ProfilesDeleteCommand {
async fn execute(self, state: crate::AspmState) -> Result<(), anyhow::Error> { async fn execute(self, state: crate::CliState) -> Result<(), anyhow::Error> {
let profile = match &self.profile { let profile = match &self.profile {
Some(key) => Profiles::find_by_id(key) Some(key) => Profiles::find_by_id(key)
.one(&state.db) .one(&state.db)

View file

@ -1,6 +1,6 @@
use anstyle::{AnsiColor, Reset, Style as Anstyle}; use anstyle::{AnsiColor, Reset, Style as Anstyle};
use anyhow::{bail, Context}; 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 clap::Parser;
use dialoguer::{theme::ColorfulTheme, Input, Select}; use dialoguer::{theme::ColorfulTheme, Input, Select};
use indoc::writedoc; use indoc::writedoc;
@ -9,7 +9,7 @@ use sea_orm::{ActiveModelTrait, ActiveValue, EntityTrait, IntoActiveModel, IntoA
use std::{io::Write, str::FromStr}; use std::{io::Write, str::FromStr};
use crate::{ use crate::{
commands::AspmSubcommand, commands::NajaSubcommand,
entities::{claims::ActiveModel as ClaimActiveModel, prelude::*}, entities::{claims::ActiveModel as ClaimActiveModel, prelude::*},
}; };
@ -21,8 +21,8 @@ pub struct ProfilesEditCommand {
} }
#[async_trait::async_trait] #[async_trait::async_trait]
impl AspmSubcommand for ProfilesEditCommand { impl NajaSubcommand for ProfilesEditCommand {
async fn execute(self, state: crate::AspmState) -> Result<(), anyhow::Error> { async fn execute(self, state: crate::CliState) -> Result<(), anyhow::Error> {
let (profile, claims) = match &self.profile { let (profile, claims) = match &self.profile {
Some(fingerprint) => { Some(fingerprint) => {
let mut profiles = Profiles::find_by_id(fingerprint) let mut profiles = Profiles::find_by_id(fingerprint)

View file

@ -1,7 +1,7 @@
use aes_gcm::{aead::Aead, Aes256Gcm, Key, KeyInit as _}; use aes_gcm::{aead::Aead, Aes256Gcm, Key, KeyInit as _};
use anyhow::{anyhow, bail, Context}; use anyhow::{anyhow, bail, Context};
use argon2::{password_hash::SaltString, Argon2, PasswordHasher as _}; use argon2::{password_hash::SaltString, Argon2, PasswordHasher as _};
use asp::{ use naja_lib::{
hex_color::HexColor, hex_color::HexColor,
keys::AspKey, keys::AspKey,
profiles::AriadneSignatureProfile, profiles::AriadneSignatureProfile,
@ -16,7 +16,7 @@ use josekit::jwk::Jwk;
use sea_orm::{ColumnTrait, Condition, EntityTrait, ModelTrait, QueryFilter}; use sea_orm::{ColumnTrait, Condition, EntityTrait, ModelTrait, QueryFilter};
use crate::{ use crate::{
commands::AspmSubcommand, commands::NajaSubcommand,
entities::{prelude::*, profiles}, entities::{prelude::*, profiles},
}; };
@ -31,8 +31,8 @@ pub struct ProfilesExportCommand {
} }
#[async_trait::async_trait] #[async_trait::async_trait]
impl AspmSubcommand for ProfilesExportCommand { impl NajaSubcommand for ProfilesExportCommand {
async fn execute(self, state: crate::AspmState) -> Result<(), anyhow::Error> { async fn execute(self, state: crate::CliState) -> Result<(), anyhow::Error> {
let Some(profile) = Profiles::find() let Some(profile) = Profiles::find()
.filter( .filter(
Condition::any() Condition::any()

View file

@ -1,5 +1,5 @@
use anyhow::Context; use anyhow::Context;
use asp::{ use naja_lib::{
aspe::{self, AspeFetchFailure}, aspe::{self, AspeFetchFailure},
profiles::AriadneSignatureProfile, profiles::AriadneSignatureProfile,
url::{Host, Url}, url::{Host, Url},
@ -9,7 +9,7 @@ use clap::Parser;
use sea_orm::{EntityTrait, IntoActiveValue, SqlErr, TransactionTrait as _}; use sea_orm::{EntityTrait, IntoActiveValue, SqlErr, TransactionTrait as _};
use crate::{ use crate::{
commands::AspmSubcommand, commands::NajaSubcommand,
entities::{claims, prelude::*, profiles}, entities::{claims, prelude::*, profiles},
}; };
@ -24,8 +24,8 @@ pub struct ProfilesImportCommand {
} }
#[async_trait::async_trait] #[async_trait::async_trait]
impl AspmSubcommand for ProfilesImportCommand { impl NajaSubcommand for ProfilesImportCommand {
async fn execute(self, state: crate::AspmState) -> Result<(), anyhow::Error> { async fn execute(self, state: crate::CliState) -> Result<(), anyhow::Error> {
let (profile, fingerprint) = match Url::parse(&self.profile).ok().and_then(|url| { let (profile, fingerprint) = match Url::parse(&self.profile).ok().and_then(|url| {
Some({ Some({
let (host, fingerprint) = url.path().split_once(':')?; let (host, fingerprint) = url.path().split_once(':')?;

View file

@ -6,15 +6,15 @@ use sea_orm::EntityTrait;
use std::io::Write; 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 /// Lists all of the saved profiles, along with their stored data
#[derive(Parser, Debug)] #[derive(Parser, Debug)]
pub struct ProfilesListCommand {} pub struct ProfilesListCommand {}
#[async_trait::async_trait] #[async_trait::async_trait]
impl AspmSubcommand for ProfilesListCommand { impl NajaSubcommand for ProfilesListCommand {
async fn execute(self, state: crate::AspmState) -> Result<(), anyhow::Error> { async fn execute(self, state: crate::CliState) -> Result<(), anyhow::Error> {
// Fetch data // Fetch data
let profiles = Profiles::find() let profiles = Profiles::find()
.find_with_related(Claims) .find_with_related(Claims)

View file

@ -8,7 +8,7 @@ use anyhow::Context;
use app_dirs2::{AppDataType, AppInfo}; use app_dirs2::{AppDataType, AppInfo};
use clap::{Parser, Subcommand}; use clap::{Parser, Subcommand};
use commands::{ use commands::{
aspe::AspeSubcommands, keys::KeysSubcommands, profiles::ProfilesSubcommands, AspmSubcommand, aspe::AspeSubcommands, keys::KeysSubcommands, profiles::ProfilesSubcommands, NajaSubcommand,
}; };
use migrations::{Migrator, MigratorTrait, SchemaManager}; use migrations::{Migrator, MigratorTrait, SchemaManager};
use sea_orm::{Database, DatabaseConnection}; use sea_orm::{Database, DatabaseConnection};
@ -23,7 +23,7 @@ const APP_INFO: AppInfo = AppInfo {
const DATABASE_URL: &str = "sqlite://DB_PATH?mode=rwc"; const DATABASE_URL: &str = "sqlite://DB_PATH?mode=rwc";
#[derive(Debug)] #[derive(Debug)]
pub struct AspmState { pub struct CliState {
pub data_dir: PathBuf, pub data_dir: PathBuf,
pub db: DatabaseConnection, pub db: DatabaseConnection,
pub verbose: bool, pub verbose: bool,
@ -34,12 +34,12 @@ pub struct AspmState {
version, version,
about, about,
long_about, long_about,
styles = AspmCommand::styles() styles = NajaCommand::styles()
)] )]
struct AspmCommand { struct NajaCommand {
#[clap(long_about)] #[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: /// The order of precedence is:
/// 1. Command line flag /// 1. Command line flag
/// 2. Environment variable /// 2. Environment variable
@ -51,10 +51,10 @@ struct AspmCommand {
verbose: bool, verbose: bool,
/// The subcommand to use /// The subcommand to use
#[command(subcommand)] #[command(subcommand)]
subcommand: AspmSubcommands, subcommand: NajaSubcommands,
} }
impl AspmCommand { impl NajaCommand {
fn styles() -> clap::builder::Styles { fn styles() -> clap::builder::Styles {
clap::builder::Styles::styled() clap::builder::Styles::styled()
.header( .header(
@ -79,14 +79,14 @@ impl AspmCommand {
} }
#[derive(Subcommand)] #[derive(Subcommand)]
pub enum AspmSubcommands { pub enum NajaSubcommands {
Keys(commands::keys::KeysSubcommand), Keys(commands::keys::KeysSubcommand),
Profiles(commands::profiles::ProfilesSubcommand), Profiles(commands::profiles::ProfilesSubcommand),
Aspe(commands::aspe::AspeSubcommand), Aspe(commands::aspe::AspeSubcommand),
} }
fn main() { fn main() {
let parsed = AspmCommand::parse(); let parsed = NajaCommand::parse();
let verbose = parsed.verbose; let verbose = parsed.verbose;
if 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() let runtime = tokio::runtime::Builder::new_multi_thread()
.enable_all() .enable_all()
.build() .build()
@ -120,13 +120,13 @@ fn cli(parsed: AspmCommand) -> Result<(), anyhow::Error> {
let state = runtime.block_on(async { let state = runtime.block_on(async {
// Check the data dir (read and write) // Check the data dir (read and write)
let data_dir = parsed.data_dir.unwrap_or( 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) 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::create_dir_all(&data_dir).or(Err(NajaError::DataDirCreate))?;
std::fs::read_dir(&data_dir).or(Err(AspmError::DataDirRead))?; std::fs::read_dir(&data_dir).or(Err(NajaError::DataDirRead))?;
// Construct the database in the dir // Construct the database in the dir
let db = Database::connect(DATABASE_URL.replace("DB_PATH", &{ let db = Database::connect(DATABASE_URL.replace("DB_PATH", &{
let mut new = data_dir.clone(); 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")?); .context("Unable to check database for keys table")?);
// Make the state // Make the state
let state = AspmState { let state = CliState {
data_dir, data_dir,
db, db,
verbose: parsed.verbose, verbose: parsed.verbose,
}; };
Ok::<AspmState, anyhow::Error>(state) Ok::<CliState, anyhow::Error>(state)
})?; })?;
// Call the subcommand // Call the subcommand
match parsed.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::Generate(subcommand) => subcommand.execute_sync(state, runtime),
KeysSubcommands::List(subcommand) => subcommand.execute_sync(state, runtime), KeysSubcommands::List(subcommand) => subcommand.execute_sync(state, runtime),
KeysSubcommands::Export(subcommand) => subcommand.execute_sync(state, runtime), KeysSubcommands::Export(subcommand) => subcommand.execute_sync(state, runtime),
KeysSubcommands::Delete(subcommand) => subcommand.execute_sync(state, runtime), KeysSubcommands::Delete(subcommand) => subcommand.execute_sync(state, runtime),
KeysSubcommands::Import(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::Create(subcommand) => subcommand.execute_sync(state, runtime),
ProfilesSubcommands::Export(subcommand) => subcommand.execute_sync(state, runtime), ProfilesSubcommands::Export(subcommand) => subcommand.execute_sync(state, runtime),
ProfilesSubcommands::List(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::Delete(subcommand) => subcommand.execute_sync(state, runtime),
ProfilesSubcommands::Import(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::Upload(subcommand) => subcommand.execute_sync(state, runtime),
AspeSubcommands::Delete(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)] #[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?")] #[error("The data directory was unable to be created, is it correct, and does the current user have permission to create it?")]
DataDirCreate, DataDirCreate,
#[error("The data directory was unable to be read, is it correct, and does the current user have permission to read it?")] #[error("The data directory was unable to be read, is it correct, and does the current user have permission to read it?")]

View file

@ -12,8 +12,8 @@ static KEY_PASSWORD: &str = "TESTKEYPASSWORD";
// TODO: Also test ed25519 key generation // TODO: Also test ed25519 key generation
fn assert_key_generated(datadir: &str) -> Result<(), anyhow::Error> { fn assert_key_generated(datadir: &str) -> Result<(), anyhow::Error> {
Command::cargo_bin("aspm")? Command::cargo_bin("naja")?
.env("ASPM_DATA_DIR", datadir) .env("NAJA_DATA_DIR", datadir)
.arg("keys") .arg("keys")
.arg("generate") .arg("generate")
.env("KEY_PASSWORD", KEY_PASSWORD) .env("KEY_PASSWORD", KEY_PASSWORD)
@ -37,29 +37,29 @@ fn help_works() -> Result<(), anyhow::Error> {
.to_str() .to_str()
.context("Tempdir path was not valid utf8")?; .context("Tempdir path was not valid utf8")?;
Command::cargo_bin("aspm")? Command::cargo_bin("naja")?
.env("ASPM_DATA_DIR", datadir) .env("NAJA_DATA_DIR", datadir)
.arg("--help") .arg("--help")
.assert() .assert()
.success() .success()
.stdout(predicate::str::starts_with(env!("CARGO_PKG_DESCRIPTION"))); .stdout(predicate::str::starts_with(env!("CARGO_PKG_DESCRIPTION")));
Command::cargo_bin("aspm")? Command::cargo_bin("naja")?
.env("ASPM_DATA_DIR", datadir) .env("NAJA_DATA_DIR", datadir)
.arg("-h") .arg("-h")
.assert() .assert()
.success() .success()
.stdout(predicate::str::starts_with(env!("CARGO_PKG_DESCRIPTION"))); .stdout(predicate::str::starts_with(env!("CARGO_PKG_DESCRIPTION")));
Command::cargo_bin("aspm")? Command::cargo_bin("naja")?
.env("ASPM_DATA_DIR", datadir) .env("NAJA_DATA_DIR", datadir)
.arg("help") .arg("help")
.assert() .assert()
.success() .success()
.stdout(predicate::str::starts_with(env!("CARGO_PKG_DESCRIPTION"))); .stdout(predicate::str::starts_with(env!("CARGO_PKG_DESCRIPTION")));
Command::cargo_bin("aspm")? Command::cargo_bin("naja")?
.env("ASPM_DATA_DIR", datadir) .env("NAJA_DATA_DIR", datadir)
.assert() .assert()
.code(2) .code(2)
.stderr(predicate::str::starts_with(env!("CARGO_PKG_DESCRIPTION"))); .stderr(predicate::str::starts_with(env!("CARGO_PKG_DESCRIPTION")));
@ -88,8 +88,8 @@ fn keys_list_works() -> Result<(), anyhow::Error> {
assert_key_generated(datadir)?; assert_key_generated(datadir)?;
Command::cargo_bin("aspm")? Command::cargo_bin("naja")?
.env("ASPM_DATA_DIR", datadir) .env("NAJA_DATA_DIR", datadir)
.arg("keys") .arg("keys")
.arg("list") .arg("list")
.assert() .assert()
@ -111,8 +111,8 @@ fn keys_export_works() -> Result<(), anyhow::Error> {
assert_key_generated(datadir)?; assert_key_generated(datadir)?;
for export_format in ["pkcs8", "asp-tool", "jwk"] { for export_format in ["pkcs8", "asp-tool", "jwk"] {
Command::cargo_bin("aspm")? Command::cargo_bin("naja")?
.env("ASPM_DATA_DIR", datadir) .env("NAJA_DATA_DIR", datadir)
.arg("keys") .arg("keys")
.arg("export") .arg("export")
.env("KEY_PASSWORD", KEY_PASSWORD) .env("KEY_PASSWORD", KEY_PASSWORD)
@ -139,8 +139,8 @@ fn keys_import_works() -> Result<(), anyhow::Error> {
("asp-tool", TEST_KEY_ASPTOOL), ("asp-tool", TEST_KEY_ASPTOOL),
("jwk", TEST_KEY_JWK), ("jwk", TEST_KEY_JWK),
] { ] {
Command::cargo_bin("aspm")? Command::cargo_bin("naja")?
.env("ASPM_DATA_DIR", datadir) .env("NAJA_DATA_DIR", datadir)
.arg("keys") .arg("keys")
.arg("import") .arg("import")
.env("KEY_PASSWORD", TEST_KEY_PASSWORD) .env("KEY_PASSWORD", TEST_KEY_PASSWORD)
@ -155,16 +155,16 @@ fn keys_import_works() -> Result<(), anyhow::Error> {
.and(predicate::str::contains(TEST_FINGERPRINT)), .and(predicate::str::contains(TEST_FINGERPRINT)),
); );
Command::cargo_bin("aspm")? Command::cargo_bin("naja")?
.env("ASPM_DATA_DIR", datadir) .env("NAJA_DATA_DIR", datadir)
.arg("keys") .arg("keys")
.arg("list") .arg("list")
.assert() .assert()
.success() .success()
.stdout(predicate::str::contains(TEST_FINGERPRINT)); .stdout(predicate::str::contains(TEST_FINGERPRINT));
Command::cargo_bin("aspm")? Command::cargo_bin("naja")?
.env("ASPM_DATA_DIR", datadir) .env("NAJA_DATA_DIR", datadir)
.arg("keys") .arg("keys")
.arg("delete") .arg("delete")
.arg("--no-confirm") .arg("--no-confirm")
@ -189,8 +189,8 @@ fn keys_delete_works() -> Result<(), anyhow::Error> {
assert_key_generated(datadir)?; assert_key_generated(datadir)?;
Command::cargo_bin("aspm")? Command::cargo_bin("naja")?
.env("ASPM_DATA_DIR", datadir) .env("NAJA_DATA_DIR", datadir)
.arg("keys") .arg("keys")
.arg("delete") .arg("delete")
.arg("--no-confirm") .arg("--no-confirm")
@ -201,8 +201,8 @@ fn keys_delete_works() -> Result<(), anyhow::Error> {
"Successfully deleted key with fingerprint ", "Successfully deleted key with fingerprint ",
)); ));
Command::cargo_bin("aspm")? Command::cargo_bin("naja")?
.env("ASPM_DATA_DIR", datadir) .env("NAJA_DATA_DIR", datadir)
.arg("keys") .arg("keys")
.arg("list") .arg("list")
.assert() .assert()

View file

@ -1,5 +1,5 @@
[package] [package]
name = "asp" name = "naja-lib"
description = "A library implementation of the ariadne signature profile specification v0" description = "A library implementation of the ariadne signature profile specification v0"
version = "0.1.0" version = "0.1.0"
edition = "2021" edition = "2021"

View file

@ -17,6 +17,7 @@ pub struct AspeVersion {
} }
/// An ASPE-compatible server /// An ASPE-compatible server
#[derive(Clone)]
pub struct AspeServer { pub struct AspeServer {
pub host: Host, pub host: Host,
client: reqwest::Client, client: reqwest::Client,
@ -82,7 +83,7 @@ impl AspeServer {
host, host,
client: reqwest::Client::builder() client: reqwest::Client::builder()
.user_agent(format!( .user_agent(format!(
"asp-rs/{version} ({repo})", "naja-lib/{version} ({repo})",
version = env!("CARGO_PKG_VERSION"), version = env!("CARGO_PKG_VERSION"),
repo = env!("CARGO_PKG_REPOSITORY") repo = env!("CARGO_PKG_REPOSITORY")
)) ))
@ -166,8 +167,7 @@ mod tests {
#[tokio::test] #[tokio::test]
async fn building_aspe_server_succeeds() { async fn building_aspe_server_succeeds() {
let result = AspeServer::new(Host::Domain(String::from("keyoxide.org"))).await; AspeServer::new(Host::Domain(String::from("keyoxide.org"))).await.expect("Contructing an AspeServer should succeed");
assert!(result.is_ok(), "Constructing an AspeServer should succeed")
} }
#[tokio::test] #[tokio::test]