mirror of
https://codeberg.org/tyy/aspm
synced 2024-12-22 18:19: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",
|
"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"
|
||||||
|
|
|
@ -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
|
||||||
|
|
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
|
# 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]
|
[package]
|
||||||
name = "migrations"
|
name = "cli-migrations"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
|
@ -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"
|
|
@ -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")?;
|
|
@ -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")?;
|
|
@ -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?;
|
||||||
|
|
|
@ -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?;
|
||||||
|
|
|
@ -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?")
|
|
@ -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 {
|
|
@ -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
|
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 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 {
|
|
@ -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)
|
|
@ -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)
|
|
@ -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()
|
|
@ -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(':')?;
|
|
@ -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)
|
|
@ -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?")]
|
|
@ -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()
|
|
@ -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"
|
|
@ -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]
|
Loading…
Reference in a new issue