1
0
Fork 0
mirror of https://codeberg.org/tyy/aspm synced 2024-12-22 11:19:29 -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",
]
[[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"

View file

@ -1,7 +1,7 @@
[workspace]
members = ["crates/*"]
resolver = "2"
default-members = ["crates/aspm"]
default-members = ["crates/naja-cli"]
[profile.release]
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
## 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]
name = "migrations"
name = "cli-migrations"
version = "0.1.0"
edition = "2021"

View file

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

View file

@ -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"

View file

@ -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")?;

View file

@ -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")?;

View file

@ -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?;

View file

@ -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?;

View file

@ -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?")

View file

@ -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 {

View file

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

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 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 {

View file

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

View file

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

View file

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

View file

@ -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(':')?;

View file

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

View file

@ -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?")]

View file

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

View file

@ -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"

View file

@ -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]