add client for chir.rs

This commit is contained in:
Charlotte 🦝 Delenk 2024-12-03 10:23:07 +01:00
parent ca0b13acb6
commit e768b06116
Signed by: darkkirb
GPG key ID: AB2BD8DAF2E37122
8 changed files with 617 additions and 10 deletions

129
Cargo.lock generated
View file

@ -59,6 +59,55 @@ dependencies = [
"libc",
]
[[package]]
name = "anstream"
version = "0.6.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b"
dependencies = [
"anstyle",
"anstyle-parse",
"anstyle-query",
"anstyle-wincon",
"colorchoice",
"is_terminal_polyfill",
"utf8parse",
]
[[package]]
name = "anstyle"
version = "1.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9"
[[package]]
name = "anstyle-parse"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9"
dependencies = [
"utf8parse",
]
[[package]]
name = "anstyle-query"
version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c"
dependencies = [
"windows-sys 0.59.0",
]
[[package]]
name = "anstyle-wincon"
version = "3.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125"
dependencies = [
"anstyle",
"windows-sys 0.59.0",
]
[[package]]
name = "argon2"
version = "0.5.3"
@ -906,6 +955,20 @@ dependencies = [
"tracing",
]
[[package]]
name = "chir-rs-client"
version = "0.1.0"
dependencies = [
"bincode",
"chir-rs-http-api",
"clap",
"color-eyre",
"eyre",
"reqwest",
"tokio",
"tracing-subscriber",
]
[[package]]
name = "chir-rs-config"
version = "0.1.0"
@ -980,9 +1043,11 @@ version = "0.1.0"
dependencies = [
"async-trait",
"axum-core",
"b64-ct",
"bincode",
"bytes",
"educe",
"eyre",
"http 1.1.0",
"mime",
"serde",
@ -1034,6 +1099,46 @@ dependencies = [
"libloading",
]
[[package]]
name = "clap"
version = "4.5.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fb3b4b9e5a7c7514dfa52869339ee98b3156b0bfb4e8a77c4ff4babb64b1604f"
dependencies = [
"clap_builder",
"clap_derive",
]
[[package]]
name = "clap_builder"
version = "4.5.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b17a95aa67cc7b5ebd32aa5370189aa0d79069ef1c64ce893bd30fb24bff20ec"
dependencies = [
"anstream",
"anstyle",
"clap_lex",
"strsim",
]
[[package]]
name = "clap_derive"
version = "4.5.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab"
dependencies = [
"heck",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "clap_lex"
version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "afb84c814227b90d6895e01398aee0d8033c00e7466aca416fb6a8e0eb19d8a7"
[[package]]
name = "cmake"
version = "0.1.52"
@ -1071,6 +1176,12 @@ dependencies = [
"tracing-error",
]
[[package]]
name = "colorchoice"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990"
[[package]]
name = "concurrent-queue"
version = "2.5.0"
@ -2165,6 +2276,12 @@ version = "2.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708"
[[package]]
name = "is_terminal_polyfill"
version = "1.70.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
[[package]]
name = "iso8601"
version = "0.6.1"
@ -3839,6 +3956,12 @@ dependencies = [
"unicode-properties",
]
[[package]]
name = "strsim"
version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
[[package]]
name = "subtle"
version = "2.6.1"
@ -4385,6 +4508,12 @@ version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be"
[[package]]
name = "utf8parse"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
[[package]]
name = "uuid"
version = "1.11.0"

349
Cargo.nix
View file

@ -7,8 +7,9 @@ args@{
"chir-rs-castore/default"
"chir-rs-config/default"
"chir-rs-misc/default"
"chir-rs-db/default"
"chir-rs-client/default"
"chir-rs-http-api/default"
"chir-rs-db/default"
"chir-rs-gemini/default"
"chir-rs-http/default"
"chir-rs/default"
@ -31,7 +32,7 @@ args@{
ignoreLockHash,
}:
let
nixifiedLockHash = "73ff0a6e5f052a9577d0aac2888498a5a588a21319b04b60f8739765f62dae09";
nixifiedLockHash = "234b56dfc4b59e0b26044b6263573e725aa8e1a11bf1d349c799223f090b8c26";
workspaceSrc = if args.workspaceSrc == null then ./. else args.workspaceSrc;
currentLockHash = builtins.hashFile "sha256" (workspaceSrc + /Cargo.lock);
lockHashIgnored =
@ -94,8 +95,9 @@ else
chir-rs-castore = rustPackages.unknown.chir-rs-castore."0.1.0";
chir-rs-config = rustPackages.unknown.chir-rs-config."0.1.0";
chir-rs-misc = rustPackages.unknown.chir-rs-misc."0.1.0";
chir-rs-db = rustPackages.unknown.chir-rs-db."0.1.0";
chir-rs-client = rustPackages.unknown.chir-rs-client."0.1.0";
chir-rs-http-api = rustPackages.unknown.chir-rs-http-api."0.1.0";
chir-rs-db = rustPackages.unknown.chir-rs-db."0.1.0";
chir-rs-gemini = rustPackages.unknown.chir-rs-gemini."0.1.0";
chir-rs-http = rustPackages.unknown.chir-rs-http."0.1.0";
chir-rs = rustPackages.unknown.chir-rs."0.1.0";
@ -239,6 +241,131 @@ else
};
});
"registry+https://github.com/rust-lang/crates.io-index".anstream."0.6.18" =
overridableMkRustCrate
(profileName: rec {
name = "anstream";
version = "0.6.18";
registry = "registry+https://github.com/rust-lang/crates.io-index";
src = fetchCratesIo {
inherit name version;
sha256 = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b";
};
features = builtins.concatLists [
[ "auto" ]
[ "default" ]
[ "wincon" ]
];
dependencies = {
anstyle =
(rustPackages."registry+https://github.com/rust-lang/crates.io-index".anstyle."1.0.10" {
inherit profileName;
}).out;
anstyle_parse =
(rustPackages."registry+https://github.com/rust-lang/crates.io-index".anstyle-parse."0.2.6" {
inherit profileName;
}).out;
anstyle_query =
(rustPackages."registry+https://github.com/rust-lang/crates.io-index".anstyle-query."1.1.2" {
inherit profileName;
}).out;
${if hostPlatform.isWindows then "anstyle_wincon" else null} =
(rustPackages."registry+https://github.com/rust-lang/crates.io-index".anstyle-wincon."3.0.6" {
inherit profileName;
}).out;
colorchoice =
(rustPackages."registry+https://github.com/rust-lang/crates.io-index".colorchoice."1.0.3" {
inherit profileName;
}).out;
is_terminal_polyfill =
(rustPackages."registry+https://github.com/rust-lang/crates.io-index".is_terminal_polyfill."1.70.1"
{ inherit profileName; }
).out;
utf8parse =
(rustPackages."registry+https://github.com/rust-lang/crates.io-index".utf8parse."0.2.2" {
inherit profileName;
}).out;
};
});
"registry+https://github.com/rust-lang/crates.io-index".anstyle."1.0.10" =
overridableMkRustCrate
(profileName: rec {
name = "anstyle";
version = "1.0.10";
registry = "registry+https://github.com/rust-lang/crates.io-index";
src = fetchCratesIo {
inherit name version;
sha256 = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9";
};
features = builtins.concatLists [
[ "default" ]
[ "std" ]
];
});
"registry+https://github.com/rust-lang/crates.io-index".anstyle-parse."0.2.6" =
overridableMkRustCrate
(profileName: rec {
name = "anstyle-parse";
version = "0.2.6";
registry = "registry+https://github.com/rust-lang/crates.io-index";
src = fetchCratesIo {
inherit name version;
sha256 = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9";
};
features = builtins.concatLists [
[ "default" ]
[ "utf8" ]
];
dependencies = {
utf8parse =
(rustPackages."registry+https://github.com/rust-lang/crates.io-index".utf8parse."0.2.2" {
inherit profileName;
}).out;
};
});
"registry+https://github.com/rust-lang/crates.io-index".anstyle-query."1.1.2" =
overridableMkRustCrate
(profileName: rec {
name = "anstyle-query";
version = "1.1.2";
registry = "registry+https://github.com/rust-lang/crates.io-index";
src = fetchCratesIo {
inherit name version;
sha256 = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c";
};
dependencies = {
${if hostPlatform.isWindows then "windows_sys" else null} =
(rustPackages."registry+https://github.com/rust-lang/crates.io-index".windows-sys."0.59.0" {
inherit profileName;
}).out;
};
});
"registry+https://github.com/rust-lang/crates.io-index".anstyle-wincon."3.0.6" =
overridableMkRustCrate
(profileName: rec {
name = "anstyle-wincon";
version = "3.0.6";
registry = "registry+https://github.com/rust-lang/crates.io-index";
src = fetchCratesIo {
inherit name version;
sha256 = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125";
};
dependencies = {
anstyle =
(rustPackages."registry+https://github.com/rust-lang/crates.io-index".anstyle."1.0.10" {
inherit profileName;
}).out;
${if hostPlatform.isWindows then "windows_sys" else null} =
(rustPackages."registry+https://github.com/rust-lang/crates.io-index".windows-sys."0.59.0" {
inherit profileName;
}).out;
};
});
"registry+https://github.com/rust-lang/crates.io-index".argon2."0.5.3" =
overridableMkRustCrate
(profileName: rec {
@ -2868,6 +2995,44 @@ else
};
});
"unknown".chir-rs-client."0.1.0" = overridableMkRustCrate (profileName: rec {
name = "chir-rs-client";
version = "0.1.0";
registry = "unknown";
src = fetchCrateLocal (workspaceSrc + "/chir-rs-client");
dependencies = {
bincode =
(rustPackages."registry+https://github.com/rust-lang/crates.io-index".bincode."2.0.0-rc.3" {
inherit profileName;
}).out;
chir_rs_http_api = (rustPackages."unknown".chir-rs-http-api."0.1.0" { inherit profileName; }).out;
clap =
(rustPackages."registry+https://github.com/rust-lang/crates.io-index".clap."4.5.21" {
inherit profileName;
}).out;
color_eyre =
(rustPackages."registry+https://github.com/rust-lang/crates.io-index".color-eyre."0.6.3" {
inherit profileName;
}).out;
eyre =
(rustPackages."registry+https://github.com/rust-lang/crates.io-index".eyre."0.6.12" {
inherit profileName;
}).out;
reqwest =
(rustPackages."registry+https://github.com/rust-lang/crates.io-index".reqwest."0.12.9" {
inherit profileName;
}).out;
tokio =
(rustPackages."registry+https://github.com/rust-lang/crates.io-index".tokio."1.41.1" {
inherit profileName;
}).out;
tracing_subscriber =
(rustPackages."registry+https://github.com/rust-lang/crates.io-index".tracing-subscriber."0.3.19" {
inherit profileName;
}).out;
};
});
"unknown".chir-rs-config."0.1.0" = overridableMkRustCrate (profileName: rec {
name = "chir-rs-config";
version = "0.1.0";
@ -3075,6 +3240,10 @@ else
(rustPackages."registry+https://github.com/rust-lang/crates.io-index".axum-core."0.4.5" {
inherit profileName;
}).out;
b64_ct =
(rustPackages."registry+https://github.com/rust-lang/crates.io-index".b64-ct."0.1.2" {
inherit profileName;
}).out;
bincode =
(rustPackages."registry+https://github.com/rust-lang/crates.io-index".bincode."2.0.0-rc.3" {
inherit profileName;
@ -3087,6 +3256,10 @@ else
(buildRustPackages."registry+https://github.com/rust-lang/crates.io-index".educe."0.6.0" {
profileName = "__noProfile";
}).out;
eyre =
(rustPackages."registry+https://github.com/rust-lang/crates.io-index".eyre."0.6.12" {
inherit profileName;
}).out;
http =
(rustPackages."registry+https://github.com/rust-lang/crates.io-index".http."1.1.0" {
inherit profileName;
@ -3272,6 +3445,121 @@ else
};
});
"registry+https://github.com/rust-lang/crates.io-index".clap."4.5.21" =
overridableMkRustCrate
(profileName: rec {
name = "clap";
version = "4.5.21";
registry = "registry+https://github.com/rust-lang/crates.io-index";
src = fetchCratesIo {
inherit name version;
sha256 = "fb3b4b9e5a7c7514dfa52869339ee98b3156b0bfb4e8a77c4ff4babb64b1604f";
};
features = builtins.concatLists [
[ "color" ]
[ "default" ]
[ "derive" ]
[ "error-context" ]
[ "help" ]
[ "std" ]
[ "suggestions" ]
[ "usage" ]
];
dependencies = {
clap_builder =
(rustPackages."registry+https://github.com/rust-lang/crates.io-index".clap_builder."4.5.21" {
inherit profileName;
}).out;
clap_derive =
(buildRustPackages."registry+https://github.com/rust-lang/crates.io-index".clap_derive."4.5.18" {
profileName = "__noProfile";
}).out;
};
});
"registry+https://github.com/rust-lang/crates.io-index".clap_builder."4.5.21" =
overridableMkRustCrate
(profileName: rec {
name = "clap_builder";
version = "4.5.21";
registry = "registry+https://github.com/rust-lang/crates.io-index";
src = fetchCratesIo {
inherit name version;
sha256 = "b17a95aa67cc7b5ebd32aa5370189aa0d79069ef1c64ce893bd30fb24bff20ec";
};
features = builtins.concatLists [
[ "color" ]
[ "error-context" ]
[ "help" ]
[ "std" ]
[ "suggestions" ]
[ "usage" ]
];
dependencies = {
anstream =
(rustPackages."registry+https://github.com/rust-lang/crates.io-index".anstream."0.6.18" {
inherit profileName;
}).out;
anstyle =
(rustPackages."registry+https://github.com/rust-lang/crates.io-index".anstyle."1.0.10" {
inherit profileName;
}).out;
clap_lex =
(rustPackages."registry+https://github.com/rust-lang/crates.io-index".clap_lex."0.7.3" {
inherit profileName;
}).out;
strsim =
(rustPackages."registry+https://github.com/rust-lang/crates.io-index".strsim."0.11.1" {
inherit profileName;
}).out;
};
});
"registry+https://github.com/rust-lang/crates.io-index".clap_derive."4.5.18" =
overridableMkRustCrate
(profileName: rec {
name = "clap_derive";
version = "4.5.18";
registry = "registry+https://github.com/rust-lang/crates.io-index";
src = fetchCratesIo {
inherit name version;
sha256 = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab";
};
features = builtins.concatLists [
[ "default" ]
];
dependencies = {
heck =
(rustPackages."registry+https://github.com/rust-lang/crates.io-index".heck."0.5.0" {
inherit profileName;
}).out;
proc_macro2 =
(rustPackages."registry+https://github.com/rust-lang/crates.io-index".proc-macro2."1.0.92" {
inherit profileName;
}).out;
quote =
(rustPackages."registry+https://github.com/rust-lang/crates.io-index".quote."1.0.37" {
inherit profileName;
}).out;
syn =
(rustPackages."registry+https://github.com/rust-lang/crates.io-index".syn."2.0.90" {
inherit profileName;
}).out;
};
});
"registry+https://github.com/rust-lang/crates.io-index".clap_lex."0.7.3" =
overridableMkRustCrate
(profileName: rec {
name = "clap_lex";
version = "0.7.3";
registry = "registry+https://github.com/rust-lang/crates.io-index";
src = fetchCratesIo {
inherit name version;
sha256 = "afb84c814227b90d6895e01398aee0d8033c00e7466aca416fb6a8e0eb19d8a7";
};
});
"registry+https://github.com/rust-lang/crates.io-index".cmake."0.1.52" =
overridableMkRustCrate
(profileName: rec {
@ -3375,6 +3663,18 @@ else
};
});
"registry+https://github.com/rust-lang/crates.io-index".colorchoice."1.0.3" =
overridableMkRustCrate
(profileName: rec {
name = "colorchoice";
version = "1.0.3";
registry = "registry+https://github.com/rust-lang/crates.io-index";
src = fetchCratesIo {
inherit name version;
sha256 = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990";
};
});
"registry+https://github.com/rust-lang/crates.io-index".concurrent-queue."2.5.0" =
overridableMkRustCrate
(profileName: rec {
@ -6420,6 +6720,21 @@ else
];
});
"registry+https://github.com/rust-lang/crates.io-index".is_terminal_polyfill."1.70.1" =
overridableMkRustCrate
(profileName: rec {
name = "is_terminal_polyfill";
version = "1.70.1";
registry = "registry+https://github.com/rust-lang/crates.io-index";
src = fetchCratesIo {
inherit name version;
sha256 = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf";
};
features = builtins.concatLists [
[ "default" ]
];
});
"registry+https://github.com/rust-lang/crates.io-index".iso8601."0.6.1" =
overridableMkRustCrate
(profileName: rec {
@ -11451,6 +11766,18 @@ else
};
});
"registry+https://github.com/rust-lang/crates.io-index".strsim."0.11.1" =
overridableMkRustCrate
(profileName: rec {
name = "strsim";
version = "0.11.1";
registry = "registry+https://github.com/rust-lang/crates.io-index";
src = fetchCratesIo {
inherit name version;
sha256 = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f";
};
});
"registry+https://github.com/rust-lang/crates.io-index".subtle."2.6.1" =
overridableMkRustCrate
(profileName: rec {
@ -12947,6 +13274,21 @@ else
};
});
"registry+https://github.com/rust-lang/crates.io-index".utf8parse."0.2.2" =
overridableMkRustCrate
(profileName: rec {
name = "utf8parse";
version = "0.2.2";
registry = "registry+https://github.com/rust-lang/crates.io-index";
src = fetchCratesIo {
inherit name version;
sha256 = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821";
};
features = builtins.concatLists [
[ "default" ]
];
});
"registry+https://github.com/rust-lang/crates.io-index".uuid."1.11.0" =
overridableMkRustCrate
(profileName: rec {
@ -13766,6 +14108,7 @@ else
[ "Win32_Storage" ]
[ "Win32_Storage_FileSystem" ]
[ "Win32_System" ]
[ "Win32_System_Console" ]
[ "Win32_System_Diagnostics" ]
[ "Win32_System_Diagnostics_Debug" ]
[ "Win32_System_IO" ]

View file

@ -1,6 +1,6 @@
[workspace]
members = [
"chir-rs-castore",
"chir-rs-castore", "chir-rs-client",
"chir-rs-config",
"chir-rs-db",
"chir-rs-gemini",

16
chir-rs-client/Cargo.toml Normal file
View file

@ -0,0 +1,16 @@
[package]
name = "chir-rs-client"
version = "0.1.0"
edition = "2021"
[dependencies]
bincode = "2.0.0-rc.3"
chir-rs-http-api = { version = "0.1.0", path = "../chir-rs-http-api" }
clap = { version = "4.5.21", features = ["derive"] }
color-eyre = "0.6.3"
eyre = "0.6.12"
reqwest = { version = "0.12.9", default-features = false, features = [
"rustls-tls",
] }
tokio = { version = "1.41.1", features = ["macros", "rt-multi-thread"] }
tracing-subscriber = "0.3.19"

View file

@ -0,0 +1,72 @@
use std::collections::HashSet;
use chir_rs_http_api::{
auth::{LoginRequest, PasetoToken, Scope},
errors::APIError,
};
use clap::{arg, Parser, Subcommand};
use eyre::Result;
#[derive(Parser, Debug)]
#[command(version, about, long_about = None)]
struct Args {
#[arg(short, long, default_value = "http://localhost:5621/")]
url: String,
#[command(subcommand)]
command: Command,
}
#[derive(Subcommand, Debug)]
enum Command {
Login {
#[arg(short, long)]
username: String,
#[arg(short, long)]
password: String,
},
}
async fn login(url: String, username: String, password: String) -> Result<()> {
let request = LoginRequest {
username,
password,
scopes: HashSet::from([Scope::Full]),
};
let request = bincode::encode_to_vec(request, bincode::config::standard())?;
let client = reqwest::Client::new();
let res = client
.post(format!("{url}.api/auth/login"))
.header("Content-Type", "application/x+bincode")
.header("Accept", "application/x+bincode")
.body(request)
.send()
.await?;
let status = res.status();
let response = res.bytes().await?;
if status.is_success() {
let response: PasetoToken =
bincode::decode_from_slice(&response, bincode::config::standard())?.0;
println!("{}", response.to_paseto()?);
} else {
let response: APIError =
bincode::decode_from_slice(&response, bincode::config::standard())?.0;
println!("{:?}", response);
}
Ok(())
}
#[tokio::main]
async fn main() -> Result<()> {
color_eyre::install().ok();
tracing_subscriber::fmt::init();
let matches = Args::parse();
match matches.command {
Command::Login { username, password } => login(matches.url, username, password).await?,
}
Ok(())
}

View file

@ -9,9 +9,11 @@ axum = ["axum-core", "async-trait", "bytes", "mime", "tracing"]
[dependencies]
async-trait = { version = "0.1.83", optional = true }
axum-core = { version = "0.4.5", optional = true }
b64-ct = "0.1.2"
bincode = "2.0.0-rc.3"
bytes = { version = "1.8.0", optional = true }
educe = { version = "0.6.0", default-features = false, features = ["Debug"] }
eyre = "0.6.12"
http = "1.1.0"
mime = { version = "0.3.17", optional = true }
serde = { version = "1.0.215", features = ["derive"] }

View file

@ -1,9 +1,10 @@
use std::collections::HashSet;
/// Authentication APIs
//! Authentication APIs
use b64_ct::{FromBase64, ToBase64, URL_SAFE};
use bincode::{Decode, Encode};
use educe::Educe;
use eyre::{bail, eyre, Result};
use serde::{Deserialize, Serialize};
use std::{collections::HashSet, fmt::Debug};
/// List of supported scopes for authentication
#[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Encode, Decode, Hash)]
@ -34,3 +35,41 @@ pub struct LoginRequest {
/// Scopes
pub scopes: HashSet<Scope>,
}
/// Compacted PASETO v4.local token
#[derive(Clone, Serialize, Deserialize, Encode, Decode)]
pub struct PasetoToken {
/// The encoded token
pub token: Vec<u8>,
}
impl Debug for PasetoToken {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("PasetoToken").finish_non_exhaustive()
}
}
impl PasetoToken {
/// Parses a compressed `PasetoToken` from string
///
/// # Errors
/// This function returns an error if the paseto token passed is invalid
pub fn from_paseto(text: &str) -> Result<Self> {
if !text.starts_with("v4.local.") {
bail!("Invalid paseto token!");
}
Ok(Self {
token: text
.trim_start_matches("v4.local.")
.from_base64()
.map_err(|e| eyre!("{e:?}"))?,
})
}
/// Converts a compressed `PasetoToken` to string
pub fn to_paseto(&self) -> Result<String> {
let res = self.token.to_base64(URL_SAFE);
Ok(format!("v4.local.{res}"))
}
}

View file

@ -3,7 +3,11 @@
use argon2::{Argon2, PasswordHash, PasswordVerifier};
use axum::extract::State;
use chir_rs_db::user::User;
use chir_rs_http_api::{auth::LoginRequest, axum::bincode::Bincode, errors::APIError};
use chir_rs_http_api::{
auth::{LoginRequest, PasetoToken},
axum::bincode::Bincode,
errors::APIError,
};
use chrono::{Days, Utc};
use eyre::{Context as _, OptionExt};
use rusty_paseto::{
@ -24,7 +28,7 @@ use crate::AppState;
pub async fn login(
State(state): State<AppState>,
Bincode(login_request): Bincode<LoginRequest>,
) -> Result<Bincode<String>, APIError> {
) -> Result<Bincode<PasetoToken>, APIError> {
let Some(user_info) = User::get(&state.db, &login_request.username)
.await
.with_context(|| format!("Fetching user info for {}", login_request.username))
@ -78,5 +82,7 @@ pub async fn login(
.context("Signing paseto key")
.map_err(|e| APIError::Unknown(format!("{e:?}")))?;
Ok(Bincode(token))
Ok(Bincode(
PasetoToken::from_paseto(&token).map_err(|e| APIError::Unknown(format!("{e:?}")))?,
))
}