Route repository aliases through ServerApi
This commit is contained in:
@@ -98,6 +98,9 @@ pub trait ServerApi {
|
|||||||
#[path] workspace_id: String,
|
#[path] workspace_id: String,
|
||||||
) -> Result<RepositoryListResponse, RepositoryApiError>;
|
) -> Result<RepositoryListResponse, RepositoryApiError>;
|
||||||
|
|
||||||
|
#[get("/api/repositories", status = 200, error_status = 400)]
|
||||||
|
async fn repository_list_alias(&self) -> Result<RepositoryListResponse, RepositoryApiError>;
|
||||||
|
|
||||||
#[get(
|
#[get(
|
||||||
"/api/w/{workspace_id}/repositories/{repository_key}",
|
"/api/w/{workspace_id}/repositories/{repository_key}",
|
||||||
status = 200,
|
status = 200,
|
||||||
@@ -109,6 +112,12 @@ pub trait ServerApi {
|
|||||||
#[path] repository_key: String,
|
#[path] repository_key: String,
|
||||||
) -> Result<RepositoryDetailResponse, RepositoryApiError>;
|
) -> Result<RepositoryDetailResponse, RepositoryApiError>;
|
||||||
|
|
||||||
|
#[get("/api/repositories/{repository_key}", status = 200, error_status = 404)]
|
||||||
|
async fn repository_detail_alias(
|
||||||
|
&self,
|
||||||
|
#[path] repository_key: String,
|
||||||
|
) -> Result<RepositoryDetailResponse, RepositoryApiError>;
|
||||||
|
|
||||||
#[post(
|
#[post(
|
||||||
"/api/w/{workspace_id}/repositories",
|
"/api/w/{workspace_id}/repositories",
|
||||||
status = 201,
|
status = 201,
|
||||||
@@ -3759,7 +3768,7 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn worker_session_contract_and_flattened_availability_are_stable() {
|
fn worker_session_contract_and_flattened_availability_are_stable() {
|
||||||
let operations = ServerApiMetadata::OPERATIONS;
|
let operations = ServerApiMetadata::OPERATIONS;
|
||||||
assert_eq!(operations.len(), 4);
|
assert_eq!(operations.len(), 6);
|
||||||
let operation = operations
|
let operation = operations
|
||||||
.iter()
|
.iter()
|
||||||
.find(|operation| operation.operation_id == "worker_session")
|
.find(|operation| operation.operation_id == "worker_session")
|
||||||
@@ -5143,6 +5152,8 @@ mod openapi_artifact_tests {
|
|||||||
["application/json"]["schema"]["$ref"],
|
["application/json"]["schema"]["$ref"],
|
||||||
"#/components/schemas/RepositoryListResponse"
|
"#/components/schemas/RepositoryListResponse"
|
||||||
);
|
);
|
||||||
|
assert!(value["paths"]["/api/repositories"]["get"].is_object());
|
||||||
|
assert!(value["paths"]["/api/repositories/{repository_key}"]["get"].is_object());
|
||||||
assert!(
|
assert!(
|
||||||
value["paths"]["/api/w/{workspace_id}/repositories"]["post"]["responses"]["200"]
|
value["paths"]["/api/w/{workspace_id}/repositories"]["post"]["responses"]["200"]
|
||||||
.is_object()
|
.is_object()
|
||||||
|
|||||||
@@ -3089,6 +3089,16 @@ impl server_api::ServerApi for WorkspaceApi {
|
|||||||
.map_err(ApiError::into_repository_api_error)
|
.map_err(ApiError::into_repository_api_error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn repository_list_alias(
|
||||||
|
&self,
|
||||||
|
) -> std::result::Result<server_api::RepositoryListResponse, server_api::RepositoryApiError>
|
||||||
|
{
|
||||||
|
list_repositories(State(self.clone()))
|
||||||
|
.await
|
||||||
|
.map(|Json(response)| response)
|
||||||
|
.map_err(ApiError::into_repository_api_error)
|
||||||
|
}
|
||||||
|
|
||||||
async fn repository_detail(
|
async fn repository_detail(
|
||||||
&self,
|
&self,
|
||||||
workspace_id: String,
|
workspace_id: String,
|
||||||
@@ -3107,6 +3117,17 @@ impl server_api::ServerApi for WorkspaceApi {
|
|||||||
.map_err(ApiError::into_repository_api_error)
|
.map_err(ApiError::into_repository_api_error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn repository_detail_alias(
|
||||||
|
&self,
|
||||||
|
repository_key: String,
|
||||||
|
) -> std::result::Result<server_api::RepositoryDetailResponse, server_api::RepositoryApiError>
|
||||||
|
{
|
||||||
|
repository_detail(State(self.clone()), AxumPath(repository_key))
|
||||||
|
.await
|
||||||
|
.map(|Json(response)| response)
|
||||||
|
.map_err(ApiError::into_repository_api_error)
|
||||||
|
}
|
||||||
|
|
||||||
async fn repository_create(
|
async fn repository_create(
|
||||||
&self,
|
&self,
|
||||||
actor: RequestActor,
|
actor: RequestActor,
|
||||||
@@ -3448,8 +3469,6 @@ fn build_inner_router(api: WorkspaceApi) -> Router {
|
|||||||
"/api/w/{workspace_id}/objectives/{objective_id}/ticket-links/{ticket_id}",
|
"/api/w/{workspace_id}/objectives/{objective_id}/ticket-links/{ticket_id}",
|
||||||
delete(scoped_unlink_objective_ticket),
|
delete(scoped_unlink_objective_ticket),
|
||||||
)
|
)
|
||||||
.route("/api/repositories", get(list_repositories))
|
|
||||||
.route("/api/repositories/{repository_key}", get(repository_detail))
|
|
||||||
.route(
|
.route(
|
||||||
"/api/w/{workspace_id}/repositories/{repository_key}/ssh-connection-test",
|
"/api/w/{workspace_id}/repositories/{repository_key}/ssh-connection-test",
|
||||||
post(scoped_probe_repository_ssh_connection)
|
post(scoped_probe_repository_ssh_connection)
|
||||||
@@ -19047,6 +19066,28 @@ mod tests {
|
|||||||
SqliteWorkspaceStore, UserRecord, WorkspaceRecord, WorkspaceRuntimeBinding,
|
SqliteWorkspaceStore, UserRecord, WorkspaceRecord, WorkspaceRuntimeBinding,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
struct TestBearerAuthorizer(&'static str);
|
||||||
|
|
||||||
|
impl server_api::client_support::RequestAuthorizer for TestBearerAuthorizer {
|
||||||
|
fn authorize(
|
||||||
|
&self,
|
||||||
|
_request: server_api::client_support::AuthorizerRequest<'_>,
|
||||||
|
) -> std::result::Result<
|
||||||
|
axum::http::HeaderMap,
|
||||||
|
server_api::client_support::AuthorizationError,
|
||||||
|
> {
|
||||||
|
let mut headers = axum::http::HeaderMap::new();
|
||||||
|
headers.insert(
|
||||||
|
axum::http::header::AUTHORIZATION,
|
||||||
|
format!("Bearer {}", self.0)
|
||||||
|
.parse()
|
||||||
|
.map_err(|_| server_api::client_support::AuthorizationError::new())?,
|
||||||
|
);
|
||||||
|
Ok(headers)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn backend_resource_timeout_maps_to_gateway_timeout() {
|
fn backend_resource_timeout_maps_to_gateway_timeout() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@@ -22968,6 +23009,54 @@ mod tests {
|
|||||||
String::from_utf8_lossy(&missing_body)
|
String::from_utf8_lossy(&missing_body)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let listener = tokio::net::TcpListener::bind("127.0.0.1:0").await.unwrap();
|
||||||
|
let api_base_url = format!("http://{}", listener.local_addr().unwrap());
|
||||||
|
let network_app = app.clone();
|
||||||
|
let server = tokio::spawn(async move {
|
||||||
|
axum::serve(listener, network_app).await.unwrap();
|
||||||
|
});
|
||||||
|
let generated = server_api::ServerApiClient::builder(&api_base_url)
|
||||||
|
.unwrap()
|
||||||
|
.authorizer(TestBearerAuthorizer("api-token-auth"))
|
||||||
|
.build()
|
||||||
|
.unwrap();
|
||||||
|
let generated_workspace_id = workspace.workspace.workspace_id.clone();
|
||||||
|
let generated_list = generated
|
||||||
|
.repository_list(generated_workspace_id.clone())
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
assert!(
|
||||||
|
generated_list
|
||||||
|
.items
|
||||||
|
.iter()
|
||||||
|
.any(|repository| repository.repository_key == "documentation")
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
generated
|
||||||
|
.repository_detail(generated_workspace_id.clone(), "documentation".to_owned())
|
||||||
|
.await
|
||||||
|
.unwrap()
|
||||||
|
.item
|
||||||
|
.repository_key,
|
||||||
|
"documentation"
|
||||||
|
);
|
||||||
|
let generated_request = CreateWorkspaceRepositoryRequest {
|
||||||
|
repository_key: "generated-client".to_owned(),
|
||||||
|
source: "/srv/repos/generated-client".to_owned(),
|
||||||
|
default_ref: Some("main".to_owned()),
|
||||||
|
};
|
||||||
|
let created = generated
|
||||||
|
.repository_create(generated_workspace_id.clone(), generated_request.clone())
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
assert!(!created.replayed);
|
||||||
|
let replayed = generated
|
||||||
|
.repository_create(generated_workspace_id, generated_request)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
assert!(replayed.replayed);
|
||||||
|
server.abort();
|
||||||
|
|
||||||
let identity_uri = format!(
|
let identity_uri = format!(
|
||||||
"/api/w/{}/settings/signing-identity",
|
"/api/w/{}/settings/signing-identity",
|
||||||
workspace.workspace.workspace_id
|
workspace.workspace.workspace_id
|
||||||
|
|||||||
+67
-1
@@ -342,10 +342,76 @@
|
|||||||
"info": {
|
"info": {
|
||||||
"title": "Yoi Server API",
|
"title": "Yoi Server API",
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"x-yoi-source-digest": "sha256:c7a6b25e1a071ab9a6831e6cd53daf51acdf8aaac20746b0b6db35c12428836f"
|
"x-yoi-source-digest": "sha256:317cc65b39674bd229abc364d2daea3e909215471da5828313b3cf3ee2142600"
|
||||||
},
|
},
|
||||||
"openapi": "3.1.0",
|
"openapi": "3.1.0",
|
||||||
"paths": {
|
"paths": {
|
||||||
|
"/api/repositories": {
|
||||||
|
"get": {
|
||||||
|
"operationId": "repository_list_alias",
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/RepositoryListResponse"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"description": "Successful response"
|
||||||
|
},
|
||||||
|
"400": {
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/RepositoryApiError"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"description": "Error response"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/api/repositories/{repository_key}": {
|
||||||
|
"get": {
|
||||||
|
"operationId": "repository_detail_alias",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"explode": false,
|
||||||
|
"in": "path",
|
||||||
|
"name": "repository_key",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/string"
|
||||||
|
},
|
||||||
|
"style": "simple"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/RepositoryDetailResponse"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"description": "Successful response"
|
||||||
|
},
|
||||||
|
"404": {
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/RepositoryApiError"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"description": "Error response"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"/api/w/{workspace_id}/repositories": {
|
"/api/w/{workspace_id}/repositories": {
|
||||||
"get": {
|
"get": {
|
||||||
"operationId": "repository_list",
|
"operationId": "repository_list",
|
||||||
|
|||||||
Reference in New Issue
Block a user