Compare commits
11 Commits
7a5b9471e0
...
feature/ag
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6f5596dc69 | ||
|
|
96e7f36731 | ||
|
|
410328a2af | ||
|
|
9f122566d0 | ||
|
|
c65dc3af47 | ||
|
|
6f395ed1ae | ||
|
|
e6e85564e7 | ||
|
|
c7a090f78a | ||
|
|
8cc2775fe4 | ||
|
|
0b64538754 | ||
|
|
8009ca20ff |
15
.github/workflows/test.yml
vendored
15
.github/workflows/test.yml
vendored
@@ -12,11 +12,8 @@ on:
|
||||
|
||||
|
||||
jobs:
|
||||
# setup is now handled by a composite action used by downstream jobs to keep
|
||||
# the workflow DRY. The composite action performs checkout, cache restore and
|
||||
# toolchain setup.
|
||||
|
||||
test:
|
||||
test-crates:
|
||||
needs: frontend-build
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
@@ -39,7 +36,7 @@ jobs:
|
||||
- name: Run tests
|
||||
run: cargo test --all-features
|
||||
|
||||
lint:
|
||||
lint-crates:
|
||||
needs: frontend-build
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
@@ -83,7 +80,7 @@ jobs:
|
||||
with:
|
||||
node-version: 22
|
||||
cache: 'pnpm'
|
||||
cache-dependency-path: apps/frontend/pnpm-lock.yaml
|
||||
cache-dependency-path: pnpm-lock.yaml
|
||||
|
||||
- name: Install frontend dependencies
|
||||
run: |
|
||||
@@ -114,7 +111,7 @@ jobs:
|
||||
with:
|
||||
node-version: 22
|
||||
cache: 'pnpm'
|
||||
cache-dependency-path: apps/frontend/pnpm-lock.yaml
|
||||
cache-dependency-path: pnpm-lock.yaml
|
||||
|
||||
- name: Install frontend dependencies
|
||||
run: |
|
||||
@@ -142,12 +139,12 @@ jobs:
|
||||
with:
|
||||
node-version: 22
|
||||
cache: 'pnpm'
|
||||
cache-dependency-path: apps/frontend/pnpm-lock.yaml
|
||||
cache-dependency-path: pnpm-lock.yaml
|
||||
|
||||
- name: Install frontend dependencies
|
||||
run: |
|
||||
cd apps/frontend
|
||||
pnpm install
|
||||
pnpm install --frozen-lockfile
|
||||
|
||||
- name: Build frontend
|
||||
run: |
|
||||
|
||||
67
.github/workflows/verify.yml
vendored
67
.github/workflows/verify.yml
vendored
@@ -11,11 +11,8 @@ on:
|
||||
|
||||
|
||||
jobs:
|
||||
# setup is now handled by a composite action used by downstream jobs to keep
|
||||
# the workflow DRY. The composite action performs checkout, cache restore and
|
||||
# toolchain setup.
|
||||
|
||||
verify-generated-code:
|
||||
verify-generated-database-code:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
@@ -32,14 +29,62 @@ jobs:
|
||||
cargo run -- db:migrate_and_generate --output-path ../../public/database/src/generated/entities
|
||||
- name: Check for uncommitted changes in /generated/
|
||||
run: |
|
||||
if [[ -n $(git status --porcelain | grep '^ M .*\/generated\/') ]]; then
|
||||
if [[ -n $(git status --porcelain --untracked-files=all | grep '/generated/') ]]; then
|
||||
echo "Generated code is not up to date. Please run the code generation locally and commit the changes."
|
||||
git status --porcelain | grep '^ M .*\/generated\/'
|
||||
git status --porcelain --untracked-files=all | grep '/generated/'
|
||||
exit 1
|
||||
else
|
||||
echo "Generated code is up to date."
|
||||
fi
|
||||
|
||||
verify-generated-agent-code:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- uses: actions/setup-java@v5
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: '21'
|
||||
|
||||
- name: Setup Rust, checkout and restore caches
|
||||
uses: ./.github/actions/setup-rust
|
||||
|
||||
- name: Setup PNPM
|
||||
uses: pnpm/action-setup@v4
|
||||
with:
|
||||
version: 10
|
||||
run_install: false
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 22
|
||||
cache: 'pnpm'
|
||||
cache-dependency-path: pnpm-lock.yaml
|
||||
|
||||
- name: Install root dependencies
|
||||
run: |
|
||||
pnpm install --frozen-lockfile
|
||||
|
||||
- name: generate agent client code
|
||||
run: |
|
||||
pnpm just generate-agent-client
|
||||
|
||||
|
||||
- name: Check for uncommitted changes in agent client code
|
||||
run: |
|
||||
if [[ -n $(git status --porcelain --untracked-files=all | grep 'public/agent-client/') ]]; then
|
||||
echo "Agent client code is not up to date. Please run the agent client code generation locally and commit the changes."
|
||||
git status --porcelain --untracked-files=all | grep 'public/agent-client/'
|
||||
exit 1
|
||||
else
|
||||
echo "Agent client code is up to date."
|
||||
fi
|
||||
|
||||
verify-openapi-spec:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
@@ -99,9 +144,9 @@ jobs:
|
||||
- name: Check for uncommitted changes in swagger.json
|
||||
if: steps.check_changes.outputs.changed == 'true'
|
||||
run: |
|
||||
if [[ -n $(git status --porcelain | grep '^ M apps/api/swagger.json') ]]; then
|
||||
if [[ -n $(git status --porcelain --untracked-files=all | grep 'apps/api/swagger.json') ]]; then
|
||||
echo "OpenAPI spec is not up to date. Please run the OpenAPI generation locally and commit the changes."
|
||||
git status --porcelain | grep '^ M apps/api/swagger.json'
|
||||
git status --porcelain --untracked-files=all | grep 'apps/api/swagger.json'
|
||||
exit 1
|
||||
else
|
||||
echo "OpenAPI spec is up to date."
|
||||
@@ -165,7 +210,7 @@ jobs:
|
||||
with:
|
||||
node-version: 22
|
||||
cache: 'pnpm'
|
||||
cache-dependency-path: apps/frontend/pnpm-lock.yaml
|
||||
cache-dependency-path: pnpm-lock.yaml
|
||||
|
||||
- name: Install frontend dependencies
|
||||
if: steps.check_swagger_changes.outputs.changed == 'true'
|
||||
@@ -182,9 +227,9 @@ jobs:
|
||||
- name: Check for uncommitted changes in frontend API client
|
||||
if: steps.check_swagger_changes.outputs.changed == 'true'
|
||||
run: |
|
||||
if [[ -n $(git status --porcelain | grep '^ M apps/frontend/app/generated/api-client') ]]; then
|
||||
if [[ -n $(git status --porcelain --untracked-files=all | grep 'apps/frontend/app/generated/api-client') ]]; then
|
||||
echo "Frontend API client is not up to date. Please run the API client generation locally and commit the changes."
|
||||
git status --porcelain | grep '^ M apps/frontend/app/generated/api-client'
|
||||
git status --porcelain --untracked-files=all | grep 'apps/frontend/app/generated/api-client'
|
||||
exit 1
|
||||
else
|
||||
echo "Frontend API client is up to date."
|
||||
|
||||
82
Cargo.lock
generated
82
Cargo.lock
generated
@@ -542,7 +542,7 @@ dependencies = [
|
||||
"num-traits",
|
||||
"serde",
|
||||
"wasm-bindgen",
|
||||
"windows-link",
|
||||
"windows-link 0.2.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1709,9 +1709,11 @@ dependencies = [
|
||||
"percent-encoding",
|
||||
"pin-project-lite",
|
||||
"socket2",
|
||||
"system-configuration",
|
||||
"tokio",
|
||||
"tower-service",
|
||||
"tracing",
|
||||
"windows-registry",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2468,7 +2470,7 @@ dependencies = [
|
||||
"libc",
|
||||
"redox_syscall",
|
||||
"smallvec",
|
||||
"windows-link",
|
||||
"windows-link 0.2.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3073,8 +3075,10 @@ checksum = "eddd3ca559203180a307f12d114c268abf583f59b03cb906fd0b3ff8646c1147"
|
||||
dependencies = [
|
||||
"base64 0.22.1",
|
||||
"bytes",
|
||||
"encoding_rs",
|
||||
"futures-core",
|
||||
"futures-util",
|
||||
"h2",
|
||||
"http",
|
||||
"http-body",
|
||||
"http-body-util",
|
||||
@@ -3084,6 +3088,7 @@ dependencies = [
|
||||
"hyper-util",
|
||||
"js-sys",
|
||||
"log",
|
||||
"mime",
|
||||
"mime_guess",
|
||||
"native-tls",
|
||||
"percent-encoding",
|
||||
@@ -4193,6 +4198,27 @@ dependencies = [
|
||||
"syn 2.0.111",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "system-configuration"
|
||||
version = "0.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"core-foundation 0.9.4",
|
||||
"system-configuration-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "system-configuration-sys"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4"
|
||||
dependencies = [
|
||||
"core-foundation-sys",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tap"
|
||||
version = "1.0.1"
|
||||
@@ -5008,9 +5034,9 @@ checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb"
|
||||
dependencies = [
|
||||
"windows-implement",
|
||||
"windows-interface",
|
||||
"windows-link",
|
||||
"windows-result",
|
||||
"windows-strings",
|
||||
"windows-link 0.2.1",
|
||||
"windows-result 0.4.1",
|
||||
"windows-strings 0.5.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -5035,19 +5061,54 @@ dependencies = [
|
||||
"syn 2.0.111",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-link"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a"
|
||||
|
||||
[[package]]
|
||||
name = "windows-link"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
|
||||
|
||||
[[package]]
|
||||
name = "windows-registry"
|
||||
version = "0.5.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5b8a9ed28765efc97bbc954883f4e6796c33a06546ebafacbabee9696967499e"
|
||||
dependencies = [
|
||||
"windows-link 0.1.3",
|
||||
"windows-result 0.3.4",
|
||||
"windows-strings 0.4.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-result"
|
||||
version = "0.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6"
|
||||
dependencies = [
|
||||
"windows-link 0.1.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-result"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5"
|
||||
dependencies = [
|
||||
"windows-link",
|
||||
"windows-link 0.2.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-strings"
|
||||
version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57"
|
||||
dependencies = [
|
||||
"windows-link 0.1.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -5056,7 +5117,7 @@ version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091"
|
||||
dependencies = [
|
||||
"windows-link",
|
||||
"windows-link 0.2.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -5101,7 +5162,7 @@ version = "0.61.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc"
|
||||
dependencies = [
|
||||
"windows-link",
|
||||
"windows-link 0.2.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -5141,7 +5202,7 @@ version = "0.53.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3"
|
||||
dependencies = [
|
||||
"windows-link",
|
||||
"windows-link 0.2.1",
|
||||
"windows_aarch64_gnullvm 0.53.1",
|
||||
"windows_aarch64_msvc 0.53.1",
|
||||
"windows_i686_gnu 0.53.1",
|
||||
@@ -5367,6 +5428,7 @@ checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049"
|
||||
name = "yet-another-nginx-proxy-manager"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"agent_client",
|
||||
"argon2",
|
||||
"async-trait",
|
||||
"axum",
|
||||
@@ -5380,9 +5442,11 @@ dependencies = [
|
||||
"migration",
|
||||
"mime_guess",
|
||||
"once_cell",
|
||||
"reqwest",
|
||||
"sea-orm",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tempfile",
|
||||
"tokio",
|
||||
"tower",
|
||||
"tower-http",
|
||||
|
||||
@@ -6,6 +6,7 @@ edition = "2024"
|
||||
[dependencies]
|
||||
database = { path = "../../public/database" }
|
||||
migration = { path = "../../public/migration" }
|
||||
agent_client = { path = "../../public/agent-client" }
|
||||
|
||||
axum = { version = "0.8.7", features = ["form", "http1", "http2", "json", "matched-path", "original-uri", "query", "tokio", "tower-log", "tracing", "macros"] }
|
||||
axum-extra = { version = "0.12.2", features = ["cookie"] }
|
||||
@@ -28,4 +29,10 @@ argon2 = { version = "0.5.3", features = ["std"] }
|
||||
jsonwebtoken = { version = "10.2.0", features = ["rust_crypto"] }
|
||||
uuid = { version = "1.19.0", features = ["v4", "serde", "fast-rng"] }
|
||||
tower-http = { version = "0.6.8", features = ["cors"] }
|
||||
reqwest = { version = "^0.12", features = ["json", "multipart", "stream"] }
|
||||
|
||||
[dev-dependencies]
|
||||
tempfile = "3"
|
||||
|
||||
[lints.clippy]
|
||||
unwrap_used = "deny"
|
||||
@@ -28,7 +28,7 @@ fn action(
|
||||
_matches: &clap::ArgMatches,
|
||||
) -> std::pin::Pin<Box<dyn std::future::Future<Output = ()> + Send>> {
|
||||
let output_path = _matches.get_one::<String>("output_path");
|
||||
let output_path = output_path.unwrap().to_string();
|
||||
let output_path = output_path.expect("output_path is required").to_string();
|
||||
|
||||
Box::pin(async move {
|
||||
tracing::subscriber::with_default(log::make_temporary_subscriber(), || {
|
||||
|
||||
@@ -11,15 +11,8 @@ use crate::{
|
||||
cmd::CliCommand,
|
||||
configs::{ProgramSettings, get_program_settings, logging::LoggingSettings},
|
||||
log,
|
||||
routes::{self, AppService, AppState},
|
||||
services::{
|
||||
auth::{
|
||||
authentication::{AuthenticationServiceImpl, strategies::password::PasswordStrategy},
|
||||
user::UserServiceImpl,
|
||||
},
|
||||
server_state::ServerStateService,
|
||||
settings::SettingsService,
|
||||
},
|
||||
routes::{self, AppState},
|
||||
services::get_app_service,
|
||||
tasks,
|
||||
};
|
||||
|
||||
@@ -148,19 +141,7 @@ fn get_app_state(
|
||||
AppState {
|
||||
database_connection: db_connection.clone(),
|
||||
config: Arc::new(settings.clone()),
|
||||
service: Arc::new(AppService {
|
||||
server_state: Arc::new(ServerStateService::new(db_connection.clone())),
|
||||
settings: Arc::new(SettingsService::new(db_connection.clone())),
|
||||
auth_state: routes::AuthState {
|
||||
strategy: routes::AuthStrategy {
|
||||
password: Arc::new(PasswordStrategy::new(db_connection.clone())),
|
||||
},
|
||||
authentication: Arc::new(AuthenticationServiceImpl::new(
|
||||
settings.auth.jwt_secret.clone(),
|
||||
)),
|
||||
},
|
||||
user: Arc::new(UserServiceImpl::new(db_connection.clone())),
|
||||
}),
|
||||
service: Arc::new(get_app_service(db_connection, settings)),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
pub mod agent;
|
||||
pub mod auth;
|
||||
pub mod database;
|
||||
pub mod logging;
|
||||
@@ -21,6 +22,7 @@ pub struct ProgramSettings {
|
||||
pub database: database::DatabaseSettings,
|
||||
pub server: server::ServerSettings,
|
||||
pub auth: auth::AuthSettings,
|
||||
pub agent: agent::AgentSettings,
|
||||
}
|
||||
|
||||
impl FromConfig for ProgramSettings {
|
||||
@@ -30,6 +32,7 @@ impl FromConfig for ProgramSettings {
|
||||
database: database::DatabaseSettings::from_config(_config)?,
|
||||
server: server::ServerSettings::from_config(_config)?,
|
||||
auth: auth::AuthSettings::from_config(_config)?,
|
||||
agent: agent::AgentSettings::from_config(_config)?,
|
||||
};
|
||||
config.validate()?;
|
||||
Ok(config)
|
||||
@@ -50,6 +53,7 @@ impl FromConfig for ProgramSettings {
|
||||
database: database::DatabaseSettings::mock(),
|
||||
server: server::ServerSettings::mock(),
|
||||
auth: auth::AuthSettings::mock(),
|
||||
agent: agent::AgentSettings::mock(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
58
apps/api/src/configs/agent.rs
Normal file
58
apps/api/src/configs/agent.rs
Normal file
@@ -0,0 +1,58 @@
|
||||
use config::Config;
|
||||
use tracing::error;
|
||||
|
||||
use crate::configs::key::AGENT_SOCK_PATH_KEY;
|
||||
|
||||
use super::FromConfig;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct AgentSettings {
|
||||
pub socket_path: String,
|
||||
}
|
||||
|
||||
impl FromConfig for AgentSettings {
|
||||
fn from_config(_config: &Config) -> Result<Self, String> {
|
||||
Ok(AgentSettings {
|
||||
socket_path: _config.get_string(AGENT_SOCK_PATH_KEY).map_err(|err| {
|
||||
format!(
|
||||
"Failed to get {} from configuration. Err: {}",
|
||||
AGENT_SOCK_PATH_KEY, err
|
||||
)
|
||||
})?,
|
||||
})
|
||||
}
|
||||
|
||||
fn validate(&self) -> Result<(), String> {
|
||||
// ensure socket_path exists and is readable and writable
|
||||
if !std::path::Path::new(&self.socket_path).exists() {
|
||||
let msg = format!("Agent socket path '{}' does not exist", self.socket_path);
|
||||
error!("{}", msg);
|
||||
return Err(msg);
|
||||
}
|
||||
if std::path::Path::new(&self.socket_path)
|
||||
.metadata()
|
||||
.map(|meta| {
|
||||
let permissions = meta.permissions();
|
||||
// Check read and write permissions for the owner
|
||||
!permissions.readonly()
|
||||
})
|
||||
.unwrap_or(false)
|
||||
{
|
||||
Ok(())
|
||||
} else {
|
||||
let msg = format!(
|
||||
"Agent socket path '{}' is not readable/writable",
|
||||
self.socket_path
|
||||
);
|
||||
error!("{}", msg);
|
||||
Err(msg)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
fn mock() -> Self {
|
||||
AgentSettings {
|
||||
socket_path: "/tmp/agent.sock".to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -14,3 +14,5 @@ pub(crate) const DATABASE_MIGRATE_ON_STARTUP_KEY: &str = "DATABASE.MIGRATION.MIG
|
||||
pub(crate) const AUTH_JWT_SECRET_KEY: &str = "AUTH.JWT_SECRET";
|
||||
pub(crate) const AUTH_DEFAULT_ADMIN_USERNAME_KEY: &str = "AUTH.DEFAULT_ADMIN_USERNAME";
|
||||
pub(crate) const AUTH_DEFAULT_ADMIN_PASSWORD_KEY: &str = "AUTH.DEFAULT_ADMIN_PASSWORD";
|
||||
//
|
||||
pub(crate) const AGENT_SOCK_PATH_KEY: &str = "AGENT.SOCK.PATH";
|
||||
|
||||
@@ -121,7 +121,7 @@ impl FromConfig for ServerSettings {
|
||||
#[cfg(test)]
|
||||
fn mock() -> Self {
|
||||
ServerSettings {
|
||||
address: "0.0.0.0".parse().unwrap(),
|
||||
address: "0.0.0.0".parse().expect("Failed to parse mock IP address"),
|
||||
port: 8080,
|
||||
serve_openapi: false,
|
||||
cors: CORSSettings {
|
||||
|
||||
@@ -12,12 +12,8 @@ use crate::{
|
||||
configs::{ProgramSettings, server::CORSSettings},
|
||||
middlewares,
|
||||
services::{
|
||||
auth::{
|
||||
authentication::{AuthenticationService, strategies::password::PasswordStrategy},
|
||||
user::UserService,
|
||||
},
|
||||
server_state::ServerStateStore,
|
||||
settings::SettingsStore,
|
||||
AppService, ServiceState,
|
||||
auth::authentication::{AuthenticationService, strategies::password::PasswordStrategy},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -28,8 +24,6 @@ pub struct AppState {
|
||||
pub config: Arc<ProgramSettings>,
|
||||
}
|
||||
|
||||
pub type ServiceState<T> = Arc<T>;
|
||||
|
||||
pub struct AuthStrategy {
|
||||
pub password: ServiceState<PasswordStrategy>,
|
||||
}
|
||||
@@ -39,13 +33,6 @@ pub struct AuthState {
|
||||
pub authentication: ServiceState<dyn AuthenticationService>,
|
||||
}
|
||||
|
||||
pub struct AppService {
|
||||
pub settings: ServiceState<dyn SettingsStore>,
|
||||
pub auth_state: AuthState,
|
||||
pub user: ServiceState<dyn UserService>,
|
||||
pub server_state: ServiceState<dyn ServerStateStore>,
|
||||
}
|
||||
|
||||
pub fn get_root_router(
|
||||
state: impl Into<Arc<AppState>>,
|
||||
cors_settings: Arc<CORSSettings>,
|
||||
|
||||
@@ -79,6 +79,7 @@ pub async fn get_health_info(
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use crate::configs::FromConfig;
|
||||
use crate::services::agent_client::AgentService;
|
||||
use crate::{
|
||||
routes::{AppState, api::health::state::HealthState},
|
||||
services::{
|
||||
@@ -94,6 +95,7 @@ mod test {
|
||||
};
|
||||
|
||||
use super::*;
|
||||
use agent_client::apis::configuration::Configuration;
|
||||
use axum::body::to_bytes;
|
||||
use axum::{
|
||||
Router,
|
||||
@@ -124,6 +126,7 @@ mod test {
|
||||
},
|
||||
user: Arc::new(UserServiceImpl::new(db.clone())),
|
||||
server_state: Arc::new(ServerStateService::new(db.clone())),
|
||||
agent_client: Arc::new(AgentService::new(Configuration::default())),
|
||||
}),
|
||||
});
|
||||
|
||||
@@ -135,13 +138,21 @@ mod test {
|
||||
}));
|
||||
|
||||
let response = app
|
||||
.oneshot(Request::builder().uri("/info").body(Body::empty()).unwrap())
|
||||
.oneshot(
|
||||
Request::builder()
|
||||
.uri("/info")
|
||||
.body(Body::empty())
|
||||
.expect("Failed to build request"),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(response.status(), StatusCode::OK);
|
||||
let body = to_bytes(response.into_body(), 1024 * 1024).await.unwrap(); // Set limit to 1 MB
|
||||
let health_info: HealthInfo = serde_json::from_slice(&body).unwrap();
|
||||
let body = to_bytes(response.into_body(), 1024 * 1024)
|
||||
.await
|
||||
.expect("Failed to read response body"); // Set limit to 1 MB
|
||||
let health_info: HealthInfo =
|
||||
serde_json::from_slice(&body).expect("Failed to deserialize response body");
|
||||
assert_eq!(health_info.status, STATUS_HEALTHY);
|
||||
assert_eq!(health_info.version, env!("CARGO_PKG_VERSION"));
|
||||
assert!(health_info.errors.is_none());
|
||||
|
||||
@@ -1,3 +1,54 @@
|
||||
pub mod agent_client;
|
||||
pub mod auth;
|
||||
pub mod server_state;
|
||||
pub mod settings;
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use ::agent_client::apis::configuration::Configuration;
|
||||
|
||||
use crate::{
|
||||
configs::ProgramSettings,
|
||||
routes::{self, AuthState},
|
||||
services::{
|
||||
auth::{
|
||||
authentication::{AuthenticationServiceImpl, strategies::password::PasswordStrategy},
|
||||
user::{UserService, UserServiceImpl},
|
||||
},
|
||||
server_state::{ServerStateService, ServerStateStore},
|
||||
settings::{SettingsService, SettingsStore},
|
||||
},
|
||||
};
|
||||
|
||||
pub type ServiceState<T> = Arc<T>;
|
||||
|
||||
pub struct AppService {
|
||||
pub settings: ServiceState<dyn SettingsStore>,
|
||||
pub auth_state: AuthState,
|
||||
pub user: ServiceState<dyn UserService>,
|
||||
pub server_state: ServiceState<dyn ServerStateStore>,
|
||||
#[allow(dead_code)]
|
||||
pub agent_client: ServiceState<agent_client::AgentService>,
|
||||
}
|
||||
|
||||
pub fn get_app_service(
|
||||
db_connection: &Arc<sea_orm::DatabaseConnection>,
|
||||
settings: &ProgramSettings,
|
||||
) -> AppService {
|
||||
AppService {
|
||||
server_state: Arc::new(ServerStateService::new(db_connection.clone())),
|
||||
settings: Arc::new(SettingsService::new(db_connection.clone())),
|
||||
auth_state: routes::AuthState {
|
||||
strategy: routes::AuthStrategy {
|
||||
password: Arc::new(PasswordStrategy::new(db_connection.clone())),
|
||||
},
|
||||
authentication: Arc::new(AuthenticationServiceImpl::new(
|
||||
settings.auth.jwt_secret.clone(),
|
||||
)),
|
||||
},
|
||||
user: Arc::new(UserServiceImpl::new(db_connection.clone())),
|
||||
agent_client: Arc::new(agent_client::AgentService::new(Configuration::from(
|
||||
settings.agent.clone(),
|
||||
))),
|
||||
}
|
||||
}
|
||||
|
||||
114
apps/api/src/services/agent_client.rs
Normal file
114
apps/api/src/services/agent_client.rs
Normal file
@@ -0,0 +1,114 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use agent_client::apis::{ApiClient, configuration::Configuration};
|
||||
use tracing::warn;
|
||||
|
||||
use crate::configs::agent::AgentSettings;
|
||||
|
||||
pub struct AgentService {
|
||||
client: Arc<ApiClient>,
|
||||
}
|
||||
|
||||
impl From<AgentSettings> for Configuration {
|
||||
fn from(settings: AgentSettings) -> Self {
|
||||
let mut config = Configuration::default();
|
||||
let mut builder = reqwest::Client::builder();
|
||||
|
||||
let url = settings.socket_path;
|
||||
if url.starts_with("unix://") {
|
||||
builder = builder.unix_socket(url.to_string());
|
||||
config.client = builder.build().expect("Failed to build reqwest client");
|
||||
} else {
|
||||
warn!("AgentSettings contains a non-unix socket path: {}", url);
|
||||
config.base_path = url;
|
||||
}
|
||||
|
||||
config
|
||||
}
|
||||
}
|
||||
|
||||
impl AgentService {
|
||||
pub fn new(config: impl Into<Arc<Configuration>>) -> Self {
|
||||
let client = ApiClient::new(config.into());
|
||||
AgentService {
|
||||
client: Arc::new(client),
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn get_client(&self) -> Arc<ApiClient> {
|
||||
Arc::clone(&self.client)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use agent_client::{
|
||||
apis::{Api, nginx_agent_api::StatusSuccess},
|
||||
models::StatusResp,
|
||||
};
|
||||
use axum::{http::StatusCode, response::Json};
|
||||
use std::time::Duration;
|
||||
use tempfile::tempdir;
|
||||
use tokio::time::sleep;
|
||||
|
||||
#[test]
|
||||
fn test_agent_service_creation() {
|
||||
let config = Configuration::default();
|
||||
let service = AgentService::new(config);
|
||||
let client = service.get_client();
|
||||
assert!(Arc::ptr_eq(&client, &service.client));
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_agent_socket_support() {
|
||||
// create temporary socket path
|
||||
let dir = tempdir().expect("Failed to create temp dir");
|
||||
let socket_path = dir.path().join("agent.sock");
|
||||
|
||||
// create axum app with a simple /status route
|
||||
let app = axum::Router::new().route(
|
||||
"/status",
|
||||
axum::routing::get(|| async {
|
||||
let result: (StatusCode, StatusResp) = (StatusCode::OK, StatusResp { ok: true });
|
||||
|
||||
(result.0, Json(result.1))
|
||||
}),
|
||||
);
|
||||
|
||||
// bind tokio unix listener and serve in background
|
||||
let listener =
|
||||
tokio::net::UnixListener::bind(&socket_path).expect("Failed to bind to unix socket");
|
||||
let server_fut = axum::serve::serve(listener, app);
|
||||
let _srv = tokio::spawn(async move {
|
||||
let _ = server_fut.await;
|
||||
});
|
||||
|
||||
// give server a moment to start
|
||||
sleep(Duration::from_millis(50)).await;
|
||||
|
||||
let client: ApiClient = ApiClient::new(Arc::new(Configuration {
|
||||
base_path: "http://localhost".to_string(),
|
||||
client: reqwest::Client::builder()
|
||||
.unix_socket(socket_path.clone())
|
||||
.build()
|
||||
.expect("Failed to build reqwest client"),
|
||||
..Default::default()
|
||||
}));
|
||||
|
||||
let res = client
|
||||
.nginx_agent_api()
|
||||
.status()
|
||||
.await
|
||||
.expect("Failed to get status");
|
||||
let body = res.entity.expect("Response entity is missing");
|
||||
|
||||
assert!(res.status.is_success());
|
||||
if let StatusSuccess::Status200(body) = body {
|
||||
assert!(body.ok);
|
||||
} else {
|
||||
panic!("Unexpected response body");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -197,14 +197,17 @@ mod tests {
|
||||
let (token, _) = service
|
||||
.generate_jwt(user_id, 60)
|
||||
.await
|
||||
.expect("generate jwt");
|
||||
.expect("Failed to generate jwt");
|
||||
|
||||
let valid = service
|
||||
.is_valid_jwt(&token, None)
|
||||
.await
|
||||
.expect("validate jwt");
|
||||
.expect("Failed to validate jwt");
|
||||
assert!(valid.is_some(), "Generated token should be valid");
|
||||
let claims = service.parse_jwt(&token).await.expect("parse jwt");
|
||||
let claims = service
|
||||
.parse_jwt(&token)
|
||||
.await
|
||||
.expect("Failed to parse jwt");
|
||||
assert_eq!(claims.sub, user_id.to_string());
|
||||
}
|
||||
|
||||
@@ -213,10 +216,16 @@ mod tests {
|
||||
let service = AuthenticationServiceImpl::new(Some("secret".to_string()));
|
||||
|
||||
let user_id = Uuid::new_v4();
|
||||
let (token, _) = service.generate_jwt(user_id, 60).await.unwrap();
|
||||
let (token, _) = service
|
||||
.generate_jwt(user_id, 60)
|
||||
.await
|
||||
.expect("Failed to generate jwt");
|
||||
|
||||
let other_sub = Uuid::new_v4().to_string();
|
||||
let valid = service.is_valid_jwt(&token, Some(other_sub)).await.unwrap();
|
||||
let valid = service
|
||||
.is_valid_jwt(&token, Some(other_sub))
|
||||
.await
|
||||
.expect("jwt is not valid");
|
||||
assert!(
|
||||
valid.is_none(),
|
||||
"Token should be invalid for a different subject"
|
||||
@@ -236,10 +245,19 @@ mod tests {
|
||||
let service = AuthenticationServiceImpl::new(Some("secret".to_string()));
|
||||
|
||||
let user_id = Uuid::new_v4();
|
||||
let (token, _) = service.generate_jwt(user_id, 60).await.unwrap();
|
||||
let new_token = service.refresh_jwt(&token, 120).await.unwrap();
|
||||
let (token, _) = service
|
||||
.generate_jwt(user_id, 60)
|
||||
.await
|
||||
.expect("Failed to generate jwt");
|
||||
let new_token = service
|
||||
.refresh_jwt(&token, 120)
|
||||
.await
|
||||
.expect("Failed to refresh jwt");
|
||||
|
||||
let claims = service.parse_jwt(&new_token).await.unwrap();
|
||||
let claims = service
|
||||
.parse_jwt(&new_token)
|
||||
.await
|
||||
.expect("Failed to parse refreshed jwt");
|
||||
assert_eq!(claims.sub, user_id.to_string());
|
||||
assert_eq!(claims.exp - claims.iat, 120);
|
||||
}
|
||||
@@ -249,10 +267,16 @@ mod tests {
|
||||
let service = AuthenticationServiceImpl::new(Some("secret".to_string()));
|
||||
|
||||
let user_id = Uuid::new_v4();
|
||||
let (token, claims) = service.generate_jwt(user_id, 1).await.unwrap();
|
||||
let (token, claims) = service
|
||||
.generate_jwt(user_id, 1)
|
||||
.await
|
||||
.expect("Failed to generate jwt");
|
||||
sleep(Duration::from_secs(2)).await;
|
||||
|
||||
let valid = service.is_valid_jwt(&token, None).await.unwrap();
|
||||
let valid = service
|
||||
.is_valid_jwt(&token, None)
|
||||
.await
|
||||
.expect("Failed to validate jwt");
|
||||
assert!(
|
||||
valid.is_none(),
|
||||
"Token should be expired and thus invalid. Current time: {:?}. Diff: {}",
|
||||
@@ -266,9 +290,15 @@ mod tests {
|
||||
let service = AuthenticationServiceImpl::new(Some("secret".to_string()));
|
||||
|
||||
let user_id = Uuid::new_v4();
|
||||
let (token, _) = service.generate_jwt(user_id, 1).await.unwrap();
|
||||
let (token, _) = service
|
||||
.generate_jwt(user_id, 1)
|
||||
.await
|
||||
.expect("Failed to generate jwt");
|
||||
|
||||
service.invalidate_jwt(&token).await.unwrap();
|
||||
service
|
||||
.invalidate_jwt(&token)
|
||||
.await
|
||||
.expect("Failed to invalidate jwt");
|
||||
|
||||
// ensure entry is present
|
||||
{
|
||||
|
||||
@@ -236,7 +236,7 @@ mod test {
|
||||
"CorrectPassword".as_bytes(),
|
||||
&SaltString::generate(&mut OsRng),
|
||||
)
|
||||
.unwrap()
|
||||
.expect("Failed to hash password")
|
||||
.to_string();
|
||||
let db = MockDatabase::new(sea_orm::DatabaseBackend::Sqlite)
|
||||
.append_query_results(vec![vec![user::Model {
|
||||
@@ -281,7 +281,7 @@ mod test {
|
||||
"CorrectPassword".as_bytes(),
|
||||
&SaltString::generate(&mut OsRng),
|
||||
)
|
||||
.unwrap()
|
||||
.expect("Failed to hash password")
|
||||
.to_string();
|
||||
let db = MockDatabase::new(sea_orm::DatabaseBackend::Sqlite)
|
||||
.append_query_results(vec![vec![user::Model {
|
||||
|
||||
7021
apps/frontend/pnpm-lock.yaml
generated
7021
apps/frontend/pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
6
justfile
6
justfile
@@ -67,6 +67,12 @@ generate-agent-client:
|
||||
--additional-properties=supportMultipleResponses=true \
|
||||
--additional-properties=topLevelApiClient=true \
|
||||
--additional-properties=useSingleRequestParameter=true
|
||||
# format generated code
|
||||
cd public/agent-client && \
|
||||
cargo fmt
|
||||
# append lint allows/forbids to the end of Cargo.toml to disable warnings in generated code and forbid unsafe code
|
||||
cd public/agent-client && \
|
||||
echo '\n[lints.clippy]\nall = "allow"\n[lints.rust]\nunsafe_code = "forbid"\n' >> Cargo.toml
|
||||
|
||||
generate-all: generate-entity generate-openapi generate-agent-client
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"@openapitools/openapi-generator-cli": "^2.26.0"
|
||||
"devDependencies": {
|
||||
"@openapitools/openapi-generator-cli": "^2.26.0",
|
||||
"rust-just": "^1.44.0"
|
||||
}
|
||||
}
|
||||
6606
pnpm-lock.yaml
generated
6606
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@@ -1,3 +1,7 @@
|
||||
packages:
|
||||
- apps/frontend
|
||||
|
||||
onlyBuiltDependencies:
|
||||
- '@nestjs/core'
|
||||
- '@openapitools/openapi-generator-cli'
|
||||
- esbuild
|
||||
|
||||
@@ -19,3 +19,9 @@ default = ["native-tls"]
|
||||
native-tls = ["reqwest/native-tls"]
|
||||
rustls-tls = ["reqwest/rustls-tls"]
|
||||
mockall = ["dep:mockall"]
|
||||
|
||||
[lints.clippy]
|
||||
all = "allow"
|
||||
[lints.rust]
|
||||
unsafe_code = "forbid"
|
||||
|
||||
|
||||
@@ -8,8 +8,6 @@
|
||||
* Generated by: https://openapi-generator.tech
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Configuration {
|
||||
pub base_path: String,
|
||||
@@ -29,7 +27,6 @@ pub struct ApiKey {
|
||||
pub key: String,
|
||||
}
|
||||
|
||||
|
||||
impl Configuration {
|
||||
pub fn new() -> Configuration {
|
||||
Configuration::default()
|
||||
|
||||
@@ -78,8 +78,10 @@ pub fn parse_deep_object(prefix: &str, value: &serde_json::Value) -> Vec<(String
|
||||
value,
|
||||
));
|
||||
}
|
||||
},
|
||||
serde_json::Value::String(s) => params.push((format!("{}[{}]", prefix, key), s.clone())),
|
||||
}
|
||||
serde_json::Value::String(s) => {
|
||||
params.push((format!("{}[{}]", prefix, key), s.clone()))
|
||||
}
|
||||
_ => params.push((format!("{}[{}]", prefix, key), value.to_string())),
|
||||
}
|
||||
}
|
||||
@@ -96,7 +98,7 @@ pub fn parse_deep_object(prefix: &str, value: &serde_json::Value) -> Vec<(String
|
||||
enum ContentType {
|
||||
Json,
|
||||
Text,
|
||||
Unsupported(String)
|
||||
Unsupported(String),
|
||||
}
|
||||
|
||||
impl From<&str> for ContentType {
|
||||
@@ -128,7 +130,9 @@ pub struct ApiClient {
|
||||
impl ApiClient {
|
||||
pub fn new(configuration: Arc<configuration::Configuration>) -> Self {
|
||||
Self {
|
||||
nginx_agent_api: Box::new(nginx_agent_api::NginxAgentApiClient::new(configuration.clone())),
|
||||
nginx_agent_api: Box::new(nginx_agent_api::NginxAgentApiClient::new(
|
||||
configuration.clone(),
|
||||
)),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -159,4 +163,3 @@ impl Api for MockApiClient {
|
||||
&self.nginx_agent_api_mock
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,44 +8,51 @@
|
||||
* Generated by: https://openapi-generator.tech
|
||||
*/
|
||||
|
||||
|
||||
use super::{configuration, Error};
|
||||
use crate::apis::ContentType;
|
||||
use crate::{apis::ResponseContent, models};
|
||||
use async_trait::async_trait;
|
||||
#[cfg(feature = "mockall")]
|
||||
use mockall::automock;
|
||||
use reqwest;
|
||||
use serde::{de::Error as _, Deserialize, Serialize};
|
||||
use std::sync::Arc;
|
||||
use serde::{Deserialize, Serialize, de::Error as _};
|
||||
use crate::{apis::ResponseContent, models};
|
||||
use super::{Error, configuration};
|
||||
use crate::apis::ContentType;
|
||||
|
||||
#[cfg_attr(feature = "mockall", automock)]
|
||||
#[async_trait]
|
||||
pub trait NginxAgentApi: Send + Sync {
|
||||
|
||||
/// GET /status
|
||||
///
|
||||
///
|
||||
async fn status(&self, ) -> Result<ResponseContent<StatusSuccess>, Error<StatusError>>;
|
||||
async fn status(&self) -> Result<ResponseContent<StatusSuccess>, Error<StatusError>>;
|
||||
|
||||
/// POST /validate
|
||||
///
|
||||
///
|
||||
async fn validate(&self, params: ValidateParams ) -> Result<ResponseContent<ValidateSuccess>, Error<ValidateError>>;
|
||||
async fn validate(
|
||||
&self,
|
||||
params: ValidateParams,
|
||||
) -> Result<ResponseContent<ValidateSuccess>, Error<ValidateError>>;
|
||||
|
||||
/// POST /validate_and_reload
|
||||
///
|
||||
///
|
||||
async fn validate_and_reload(&self, params: ValidateAndReloadParams ) -> Result<ResponseContent<ValidateAndReloadSuccess>, Error<ValidateAndReloadError>>;
|
||||
async fn validate_and_reload(
|
||||
&self,
|
||||
params: ValidateAndReloadParams,
|
||||
) -> Result<ResponseContent<ValidateAndReloadSuccess>, Error<ValidateAndReloadError>>;
|
||||
|
||||
/// POST /write_config
|
||||
///
|
||||
///
|
||||
async fn write_config(&self, params: WriteConfigParams ) -> Result<ResponseContent<WriteConfigSuccess>, Error<WriteConfigError>>;
|
||||
async fn write_config(
|
||||
&self,
|
||||
params: WriteConfigParams,
|
||||
) -> Result<ResponseContent<WriteConfigSuccess>, Error<WriteConfigError>>;
|
||||
}
|
||||
|
||||
pub struct NginxAgentApiClient {
|
||||
configuration: Arc<configuration::Configuration>
|
||||
configuration: Arc<configuration::Configuration>,
|
||||
}
|
||||
|
||||
impl NginxAgentApiClient {
|
||||
@@ -54,40 +61,38 @@ impl NginxAgentApiClient {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// struct for passing parameters to the method [`NginxAgentApi::validate`]
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct ValidateParams {
|
||||
pub validate_body: models::ValidateBody
|
||||
pub validate_body: models::ValidateBody,
|
||||
}
|
||||
|
||||
/// struct for passing parameters to the method [`NginxAgentApi::validate_and_reload`]
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct ValidateAndReloadParams {
|
||||
pub validate_and_reload_body: models::ValidateAndReloadBody
|
||||
pub validate_and_reload_body: models::ValidateAndReloadBody,
|
||||
}
|
||||
|
||||
/// struct for passing parameters to the method [`NginxAgentApi::write_config`]
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct WriteConfigParams {
|
||||
pub write_config_body: models::WriteConfigBody
|
||||
pub write_config_body: models::WriteConfigBody,
|
||||
}
|
||||
|
||||
|
||||
#[async_trait]
|
||||
impl NginxAgentApi for NginxAgentApiClient {
|
||||
async fn status(&self, ) -> Result<ResponseContent<StatusSuccess>, Error<StatusError>> {
|
||||
|
||||
|
||||
async fn status(&self) -> Result<ResponseContent<StatusSuccess>, Error<StatusError>> {
|
||||
let local_var_configuration = &self.configuration;
|
||||
|
||||
let local_var_client = &local_var_configuration.client;
|
||||
|
||||
let local_var_uri_str = format!("{}/status", local_var_configuration.base_path);
|
||||
let mut local_var_req_builder = local_var_client.request(reqwest::Method::GET, local_var_uri_str.as_str());
|
||||
let mut local_var_req_builder =
|
||||
local_var_client.request(reqwest::Method::GET, local_var_uri_str.as_str());
|
||||
|
||||
if let Some(ref local_var_user_agent) = local_var_configuration.user_agent {
|
||||
local_var_req_builder = local_var_req_builder.header(reqwest::header::USER_AGENT, local_var_user_agent.clone());
|
||||
local_var_req_builder = local_var_req_builder
|
||||
.header(reqwest::header::USER_AGENT, local_var_user_agent.clone());
|
||||
}
|
||||
|
||||
let local_var_req = local_var_req_builder.build()?;
|
||||
@@ -97,32 +102,43 @@ impl NginxAgentApi for NginxAgentApiClient {
|
||||
let local_var_content = local_var_resp.text().await?;
|
||||
|
||||
if !local_var_status.is_client_error() && !local_var_status.is_server_error() {
|
||||
let local_var_entity: Option<StatusSuccess> = serde_json::from_str(&local_var_content).ok();
|
||||
let local_var_result = ResponseContent { status: local_var_status, content: local_var_content, entity: local_var_entity };
|
||||
let local_var_entity: Option<StatusSuccess> =
|
||||
serde_json::from_str(&local_var_content).ok();
|
||||
let local_var_result = ResponseContent {
|
||||
status: local_var_status,
|
||||
content: local_var_content,
|
||||
entity: local_var_entity,
|
||||
};
|
||||
Ok(local_var_result)
|
||||
} else {
|
||||
let local_var_entity: Option<StatusError> = serde_json::from_str(&local_var_content).ok();
|
||||
let local_var_error = ResponseContent { status: local_var_status, content: local_var_content, entity: local_var_entity };
|
||||
let local_var_entity: Option<StatusError> =
|
||||
serde_json::from_str(&local_var_content).ok();
|
||||
let local_var_error = ResponseContent {
|
||||
status: local_var_status,
|
||||
content: local_var_content,
|
||||
entity: local_var_entity,
|
||||
};
|
||||
Err(Error::ResponseError(local_var_error))
|
||||
}
|
||||
}
|
||||
|
||||
async fn validate(&self, params: ValidateParams ) -> Result<ResponseContent<ValidateSuccess>, Error<ValidateError>> {
|
||||
|
||||
let ValidateParams {
|
||||
validate_body,
|
||||
} = params;
|
||||
|
||||
async fn validate(
|
||||
&self,
|
||||
params: ValidateParams,
|
||||
) -> Result<ResponseContent<ValidateSuccess>, Error<ValidateError>> {
|
||||
let ValidateParams { validate_body } = params;
|
||||
|
||||
let local_var_configuration = &self.configuration;
|
||||
|
||||
let local_var_client = &local_var_configuration.client;
|
||||
|
||||
let local_var_uri_str = format!("{}/validate", local_var_configuration.base_path);
|
||||
let mut local_var_req_builder = local_var_client.request(reqwest::Method::POST, local_var_uri_str.as_str());
|
||||
let mut local_var_req_builder =
|
||||
local_var_client.request(reqwest::Method::POST, local_var_uri_str.as_str());
|
||||
|
||||
if let Some(ref local_var_user_agent) = local_var_configuration.user_agent {
|
||||
local_var_req_builder = local_var_req_builder.header(reqwest::header::USER_AGENT, local_var_user_agent.clone());
|
||||
local_var_req_builder = local_var_req_builder
|
||||
.header(reqwest::header::USER_AGENT, local_var_user_agent.clone());
|
||||
}
|
||||
local_var_req_builder = local_var_req_builder.json(&validate_body);
|
||||
|
||||
@@ -133,32 +149,46 @@ impl NginxAgentApi for NginxAgentApiClient {
|
||||
let local_var_content = local_var_resp.text().await?;
|
||||
|
||||
if !local_var_status.is_client_error() && !local_var_status.is_server_error() {
|
||||
let local_var_entity: Option<ValidateSuccess> = serde_json::from_str(&local_var_content).ok();
|
||||
let local_var_result = ResponseContent { status: local_var_status, content: local_var_content, entity: local_var_entity };
|
||||
let local_var_entity: Option<ValidateSuccess> =
|
||||
serde_json::from_str(&local_var_content).ok();
|
||||
let local_var_result = ResponseContent {
|
||||
status: local_var_status,
|
||||
content: local_var_content,
|
||||
entity: local_var_entity,
|
||||
};
|
||||
Ok(local_var_result)
|
||||
} else {
|
||||
let local_var_entity: Option<ValidateError> = serde_json::from_str(&local_var_content).ok();
|
||||
let local_var_error = ResponseContent { status: local_var_status, content: local_var_content, entity: local_var_entity };
|
||||
let local_var_entity: Option<ValidateError> =
|
||||
serde_json::from_str(&local_var_content).ok();
|
||||
let local_var_error = ResponseContent {
|
||||
status: local_var_status,
|
||||
content: local_var_content,
|
||||
entity: local_var_entity,
|
||||
};
|
||||
Err(Error::ResponseError(local_var_error))
|
||||
}
|
||||
}
|
||||
|
||||
async fn validate_and_reload(&self, params: ValidateAndReloadParams ) -> Result<ResponseContent<ValidateAndReloadSuccess>, Error<ValidateAndReloadError>> {
|
||||
|
||||
async fn validate_and_reload(
|
||||
&self,
|
||||
params: ValidateAndReloadParams,
|
||||
) -> Result<ResponseContent<ValidateAndReloadSuccess>, Error<ValidateAndReloadError>> {
|
||||
let ValidateAndReloadParams {
|
||||
validate_and_reload_body,
|
||||
} = params;
|
||||
|
||||
|
||||
let local_var_configuration = &self.configuration;
|
||||
|
||||
let local_var_client = &local_var_configuration.client;
|
||||
|
||||
let local_var_uri_str = format!("{}/validate_and_reload", local_var_configuration.base_path);
|
||||
let mut local_var_req_builder = local_var_client.request(reqwest::Method::POST, local_var_uri_str.as_str());
|
||||
let local_var_uri_str =
|
||||
format!("{}/validate_and_reload", local_var_configuration.base_path);
|
||||
let mut local_var_req_builder =
|
||||
local_var_client.request(reqwest::Method::POST, local_var_uri_str.as_str());
|
||||
|
||||
if let Some(ref local_var_user_agent) = local_var_configuration.user_agent {
|
||||
local_var_req_builder = local_var_req_builder.header(reqwest::header::USER_AGENT, local_var_user_agent.clone());
|
||||
local_var_req_builder = local_var_req_builder
|
||||
.header(reqwest::header::USER_AGENT, local_var_user_agent.clone());
|
||||
}
|
||||
local_var_req_builder = local_var_req_builder.json(&validate_and_reload_body);
|
||||
|
||||
@@ -169,32 +199,43 @@ impl NginxAgentApi for NginxAgentApiClient {
|
||||
let local_var_content = local_var_resp.text().await?;
|
||||
|
||||
if !local_var_status.is_client_error() && !local_var_status.is_server_error() {
|
||||
let local_var_entity: Option<ValidateAndReloadSuccess> = serde_json::from_str(&local_var_content).ok();
|
||||
let local_var_result = ResponseContent { status: local_var_status, content: local_var_content, entity: local_var_entity };
|
||||
let local_var_entity: Option<ValidateAndReloadSuccess> =
|
||||
serde_json::from_str(&local_var_content).ok();
|
||||
let local_var_result = ResponseContent {
|
||||
status: local_var_status,
|
||||
content: local_var_content,
|
||||
entity: local_var_entity,
|
||||
};
|
||||
Ok(local_var_result)
|
||||
} else {
|
||||
let local_var_entity: Option<ValidateAndReloadError> = serde_json::from_str(&local_var_content).ok();
|
||||
let local_var_error = ResponseContent { status: local_var_status, content: local_var_content, entity: local_var_entity };
|
||||
let local_var_entity: Option<ValidateAndReloadError> =
|
||||
serde_json::from_str(&local_var_content).ok();
|
||||
let local_var_error = ResponseContent {
|
||||
status: local_var_status,
|
||||
content: local_var_content,
|
||||
entity: local_var_entity,
|
||||
};
|
||||
Err(Error::ResponseError(local_var_error))
|
||||
}
|
||||
}
|
||||
|
||||
async fn write_config(&self, params: WriteConfigParams ) -> Result<ResponseContent<WriteConfigSuccess>, Error<WriteConfigError>> {
|
||||
|
||||
let WriteConfigParams {
|
||||
write_config_body,
|
||||
} = params;
|
||||
|
||||
async fn write_config(
|
||||
&self,
|
||||
params: WriteConfigParams,
|
||||
) -> Result<ResponseContent<WriteConfigSuccess>, Error<WriteConfigError>> {
|
||||
let WriteConfigParams { write_config_body } = params;
|
||||
|
||||
let local_var_configuration = &self.configuration;
|
||||
|
||||
let local_var_client = &local_var_configuration.client;
|
||||
|
||||
let local_var_uri_str = format!("{}/write_config", local_var_configuration.base_path);
|
||||
let mut local_var_req_builder = local_var_client.request(reqwest::Method::POST, local_var_uri_str.as_str());
|
||||
let mut local_var_req_builder =
|
||||
local_var_client.request(reqwest::Method::POST, local_var_uri_str.as_str());
|
||||
|
||||
if let Some(ref local_var_user_agent) = local_var_configuration.user_agent {
|
||||
local_var_req_builder = local_var_req_builder.header(reqwest::header::USER_AGENT, local_var_user_agent.clone());
|
||||
local_var_req_builder = local_var_req_builder
|
||||
.header(reqwest::header::USER_AGENT, local_var_user_agent.clone());
|
||||
}
|
||||
local_var_req_builder = local_var_req_builder.json(&write_config_body);
|
||||
|
||||
@@ -205,16 +246,25 @@ impl NginxAgentApi for NginxAgentApiClient {
|
||||
let local_var_content = local_var_resp.text().await?;
|
||||
|
||||
if !local_var_status.is_client_error() && !local_var_status.is_server_error() {
|
||||
let local_var_entity: Option<WriteConfigSuccess> = serde_json::from_str(&local_var_content).ok();
|
||||
let local_var_result = ResponseContent { status: local_var_status, content: local_var_content, entity: local_var_entity };
|
||||
let local_var_entity: Option<WriteConfigSuccess> =
|
||||
serde_json::from_str(&local_var_content).ok();
|
||||
let local_var_result = ResponseContent {
|
||||
status: local_var_status,
|
||||
content: local_var_content,
|
||||
entity: local_var_entity,
|
||||
};
|
||||
Ok(local_var_result)
|
||||
} else {
|
||||
let local_var_entity: Option<WriteConfigError> = serde_json::from_str(&local_var_content).ok();
|
||||
let local_var_error = ResponseContent { status: local_var_status, content: local_var_content, entity: local_var_entity };
|
||||
let local_var_entity: Option<WriteConfigError> =
|
||||
serde_json::from_str(&local_var_content).ok();
|
||||
let local_var_error = ResponseContent {
|
||||
status: local_var_status,
|
||||
content: local_var_content,
|
||||
entity: local_var_entity,
|
||||
};
|
||||
Err(Error::ResponseError(local_var_error))
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// struct for typed successes of method [`NginxAgentApi::status`]
|
||||
@@ -277,4 +327,3 @@ pub enum WriteConfigError {
|
||||
Status500(serde_json::Value),
|
||||
UnknownValue(serde_json::Value),
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
#![allow(unused_imports)]
|
||||
#![allow(clippy::too_many_arguments)]
|
||||
|
||||
extern crate serde_repr;
|
||||
extern crate serde;
|
||||
extern crate serde_json;
|
||||
extern crate serde_repr;
|
||||
extern crate url;
|
||||
|
||||
pub mod apis;
|
||||
|
||||
@@ -19,9 +19,6 @@ pub struct StatusResp {
|
||||
|
||||
impl StatusResp {
|
||||
pub fn new(ok: bool) -> StatusResp {
|
||||
StatusResp {
|
||||
ok,
|
||||
StatusResp { ok }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -27,4 +27,3 @@ impl ValidateAndReloadBody {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -21,10 +21,6 @@ pub struct ValidateAndReloadResp {
|
||||
|
||||
impl ValidateAndReloadResp {
|
||||
pub fn new(rc: i32, ro: String) -> ValidateAndReloadResp {
|
||||
ValidateAndReloadResp {
|
||||
rc,
|
||||
ro,
|
||||
ValidateAndReloadResp { rc, ro }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -27,4 +27,3 @@ impl ValidateBody {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -30,4 +30,3 @@ impl WriteConfigBody {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user