Compare commits

..

12 Commits

  1. 2
      .devcontainer/Dockerfile
  2. 32
      apps/app_api/src/api/v1.rs
  3. 13
      apps/app_api/src/api/v1/auth.rs
  4. 16
      apps/app_cli/src/commands.rs
  5. 2
      apps/app_cli/src/config.rs
  6. 5
      tavern-tests/export.sh
  7. 15
      tavern-tests/tavern-run-all.sh
  8. 7
      tavern-tests/tavern-run-single.sh
  9. 29
      tavern-tests/test_plans/decode_test.tavern.yaml
  10. 30
      tavern-tests/test_plans/dictionary_test.tavern.yaml
  11. 44
      tavern-tests/test_plans/encode_test.tavern.yaml
  12. 1
      tavern-tests/test_plans/includes.yaml
  13. 19
      tavern-tests/test_plans/info_test.tavern.yaml
  14. 20
      tavern-tests/test_plans/version_test.tavern.yaml

2
.devcontainer/Dockerfile

@ -1,4 +1,4 @@
FROM rust:1.94.1-trixie
FROM rust:1.90.0
# Install basic development tools
RUN apt-get update && apt-get install -y \

32
apps/app_api/src/api/v1.rs

@ -5,21 +5,11 @@ pub mod major;
use crate::state::AppState;
use axum::{
Json, Router,
extract::Request,
extract::State,
http::StatusCode,
middleware::Next,
response::{IntoResponse, Response},
Router, extract::Request, extract::State, http::StatusCode, middleware::Next,
response::Response,
};
use serde::Serialize;
use std::sync::Arc;
#[derive(Debug, Serialize)]
struct ErrorResponseBody {
error: String,
}
pub fn routes(state: Arc<AppState>) -> Router<Arc<AppState>> {
Router::new()
.nest("/info", info::routes())
@ -54,10 +44,10 @@ async fn auth_middleware_inner(
} else if let Some(key) = api_key_header {
key.to_string()
} else {
let error = ErrorResponseBody {
error: "Missing authorization header or API key".to_string(),
};
return (StatusCode::UNAUTHORIZED, Json(error)).into_response();
return Response::builder()
.status(StatusCode::UNAUTHORIZED)
.body("Missing authorization header or API key".into())
.unwrap();
};
match state.0.dependencies.auth_service.authenticate(&token).await {
@ -65,11 +55,9 @@ async fn auth_middleware_inner(
request.extensions_mut().insert(claims);
next.run(request).await
}
Err(_) => {
let error = ErrorResponseBody {
error: "Unauthorized".to_string(),
};
(StatusCode::UNAUTHORIZED, Json(error)).into_response()
}
Err(_) => Response::builder()
.status(StatusCode::UNAUTHORIZED)
.body("Unauthorized".into())
.unwrap(),
}
}

13
apps/app_api/src/api/v1/auth.rs

@ -7,7 +7,7 @@ use crate::state::AppState;
#[derive(Debug, Deserialize)]
pub struct LoginRequest {
pub token: Option<String>,
pub token: String,
}
#[derive(Debug, Serialize)]
@ -21,12 +21,11 @@ pub async fn login_handler(
State(state): State<Arc<AppState>>,
Json(req): Json<LoginRequest>,
) -> Result<Json<LoginResponse>, ErrorResponse> {
let token = req.token.ok_or_else(|| ErrorResponse {
error: "Invalid input".to_string(),
message: Some("Token field is required".to_string()),
})?;
let claims = state.dependencies.auth_service.authenticate(&token).await?;
let claims = state
.dependencies
.auth_service
.authenticate(&req.token)
.await?;
Ok(Json(LoginResponse {
user_id: claims.user_id,

16
apps/app_cli/src/commands.rs

@ -39,22 +39,6 @@ impl Command {
}
}
// pub fn resolve_command(command: &Command) -> &dyn AppCommand {
// match command {
// Command::Decode(app_cmd) => app_cmd,
// Command::Encode(app_cmd) => app_cmd,
// Command::ImportDict(app_cmd) => app_cmd,
// }
// }
// pub fn resolve_command_box(command: Command) -> Box<dyn AppCommand> {
// match command {
// Command::Decode(cmd) => Box::new(cmd),
// Command::Encode(cmd) => Box::new(cmd),
// Command::ImportDict(cmd) => Box::new(cmd),
// }
// }
#[derive(Parser, Debug)]
#[command(author, version, about)]
pub struct CliArgs {

2
apps/app_cli/src/config.rs

@ -29,7 +29,7 @@ impl AppConfig {
builder = builder.add_source(File::from(config_path.as_path()).required(!is_default_path));
// Environment Layer (APP_SERVER_PORT)
// Environment Layer (e.g. APP_LISTEN_PORT)
builder = builder.add_source(Environment::with_prefix("APP").separator("_"));
// Global log level override

5
tavern-tests/export.sh

@ -8,8 +8,7 @@ else
fi
export TEST_SERVER_ADDRESS="127.0.0.1:3000"
export TEST_API_BASE="api/v1"
export TEST_API_BASE="/api/v1"
export TEST_API_KEY="test-api-key"
export TEST_USER_ID="test-user-id"
export TEST_VALID_TOKEN="test-api-key"
export TEST_USER_ID="test-user-id"

15
tavern-tests/tavern-run-all.sh

@ -1,20 +1,13 @@
#!/usr/bin/env bash
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
cd "$SCRIPT_DIR"
if [ -z "$TEST_SERVER_ADDRESS" ]; then
source export.sh
fi
tavern-ci --alluredir=reports test_plans/version_test.tavern.yaml
# tavern-ci --alluredir=reports test_plans/auth_test.tavern.yaml
tavern-ci --alluredir=reports test_plans/decode_test.tavern.yaml
tavern-ci --alluredir=reports test_plans/dictionary_test.tavern.yaml
tavern-ci --alluredir=reports test_plans/encode_test.tavern.yaml
tavern-ci --alluredir=reports test_plans/info_test.tavern.yaml
# if command -v allure > /dev/null; then
# allure generate --clean --single-file --output /tmp/vm-allure-report --name index.html reports
# fi
if command -v allure > /dev/null; then
allure generate --clean --single-file --output /tmp/vm-allure-report --name index.html reports
fi
# allure package: https://github.com/allure-framework/allure2/releases/download/2.34.0/allure_2.34.0-1_all.deb

7
tavern-tests/tavern-run-single.sh

@ -1,8 +1,5 @@
#!/usr/bin/env bash
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
cd "$SCRIPT_DIR"
if [ -z "$1" ]; then
echo "Usage: $0 <test plan>"
exit 1
@ -12,8 +9,8 @@ if [ -z "$TEST_SERVER_ADDRESS" ]; then
source export.sh
fi
tavern-ci --log-cli-level=DEBUG --alluredir=reports $1
tavern-ci --alluredir=reports $1
# allure generate --clean --single-file --output /tmp/vm-allure-report --name index.html reports
allure generate --clean --single-file --output /tmp/vm-allure-report --name index.html reports
# allure package: https://github.com/allure-framework/allure2/releases/download/2.34.0/allure_2.34.0-1_all.deb

29
tavern-tests/test_plans/decode_test.tavern.yaml

@ -1,29 +0,0 @@
test_name: "Test major decode endpoint"
includes:
- !include includes.yaml
stages:
- name: "Successful decode with valid encoded input"
request:
url: "http://{server_address}/{api_base}/major/decode/pl/test"
method: GET
headers:
X-API-Key: "{api_key}"
response:
strict: True
status_code: 200
json:
input: "test"
result: "101"
- name: "Missing authentication returns 401 error"
request:
url: "http://{server_address}/{api_base}/major/decode/pl/hello"
method: GET
response:
strict: False
status_code: 401
json:
error: !anystr

30
tavern-tests/test_plans/dictionary_test.tavern.yaml

@ -1,30 +0,0 @@
test_name: "Test dictionary API endpoint"
includes:
- !include includes.yaml
stages:
- name: "Successful list dictionaries with valid authentication"
request:
url: "http://{server_address}/{api_base}/dicts"
method: GET
headers:
X-API-Key: "{api_key}"
response:
strict: False
status_code: 200
json:
dictionaries:
- name: !anystr
entry_count: !anyint
- name: "Missing authentication returns 401 error"
request:
url: "http://{server_address}/{api_base}/dicts"
method: GET
response:
strict: True
status_code: 401
json:
error: !anystr

44
tavern-tests/test_plans/encode_test.tavern.yaml

@ -1,44 +0,0 @@
test_name: "Test major encode endpoint"
includes:
- !include includes.yaml
stages:
- name: "Successful encode with default dictionary"
request:
url: "http://{server_address}/{api_base}/major/encode/pl/hello"
method: GET
headers:
X-API-Key: "{api_key}"
response:
strict: False
status_code: 200
json:
input: "hello"
dict: "demo_pl"
result: !anylist
- name: "Successful encode with custom dictionary"
request:
url: "http://{server_address}/{api_base}/major/encode/pl/test?dict=demo_pl"
method: GET
headers:
X-API-Key: "{api_key}"
response:
strict: False
status_code: 200
json:
input: "test"
dict: "demo_pl"
result: !anylist
- name: "Missing authentication returns 401 error"
request:
url: "http://{server_address}/{api_base}/major/encode/pl/hello"
method: GET
response:
strict: False
status_code: 401
json:
error: !anystr

1
tavern-tests/test_plans/includes.yaml

@ -3,4 +3,3 @@ variables:
api_base: "{tavern.env_vars.TEST_API_BASE}"
api_key: "{tavern.env_vars.TEST_API_KEY}"
user_id: "{tavern.env_vars.TEST_USER_ID}"

19
tavern-tests/test_plans/info_test.tavern.yaml

@ -0,0 +1,19 @@
test_name: "Test server API info endpoint"
includes:
- !include includes.yaml
stages:
- name: "Check version"
request:
url: "http://{server_address}/{api_base}/info/version"
method: GET
headers:
X-API-Key: "{api_key}"
response:
strict: False
status_code: 200
json:
name: !anystr
version: !anystr

20
tavern-tests/test_plans/version_test.tavern.yaml

@ -1,20 +0,0 @@
test_name: "Test version endpoint"
includes:
- !include includes.yaml
stages:
- name: "Successful version test - valid authentication returns version info"
request:
url: "http://{server_address}/api/v1/info/version"
method: GET
headers:
X-API-Key: "{api_key}"
response:
strict: True
status_code: 200
json:
name: "phomnemic-server"
version: !anystr
Loading…
Cancel
Save