Compare commits
14
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
de4631fb51
|
||
|
|
2e535d5037 | ||
|
|
f47c40ffbf | ||
|
|
15844af91e | ||
|
|
2b7edc25a5 | ||
|
|
f98d8124f4
|
||
|
|
677f800015 | ||
|
|
56b17b5768
|
||
|
|
ad4a492c31 | ||
|
|
912840a22d
|
||
|
|
db4715c906
|
||
|
|
3fcff49d4f | ||
|
|
ae54611acf
|
||
|
|
7304aaf5dd |
No files matched your search
+11
-57
@@ -1,60 +1,14 @@
|
|||||||
version: 2.1
|
version: 2.1
|
||||||
|
setup: true
|
||||||
orbs:
|
orbs:
|
||||||
qqq-orb: kingsrook/qqq-orb@0.6.9
|
qqq-orb: kingsrook/qqq-orb@0.7.12
|
||||||
|
|
||||||
commands:
|
|
||||||
configure-package-install:
|
|
||||||
steps:
|
|
||||||
- run:
|
|
||||||
name: Keep package installation unattended
|
|
||||||
command: |
|
|
||||||
# These build machines are discarded after the job.
|
|
||||||
sudo install -d /etc/needrestart/conf.d
|
|
||||||
printf '%s\n' '$nrconf{restart} = "l";' | sudo tee /etc/needrestart/conf.d/99-qqq-ci.conf >/dev/null
|
|
||||||
|
|
||||||
workflows:
|
workflows:
|
||||||
test_only:
|
setup:
|
||||||
jobs:
|
jobs:
|
||||||
- qqq-orb/mvn_test_only:
|
- qqq-orb/generate_pipeline:
|
||||||
pre-steps:
|
orb_version: 0.7.12
|
||||||
- configure-package-install
|
filters:
|
||||||
context: [qqq-maven-registry-credentials]
|
branches:
|
||||||
filters:
|
ignore: automation/qbit-rc-pending
|
||||||
branches:
|
tags:
|
||||||
ignore: /(develop|release\/.*)/
|
only: /^v\d+\.\d+\.\d+$/
|
||||||
|
|
||||||
publish_snapshot:
|
|
||||||
jobs:
|
|
||||||
- qqq-orb/mvn_publish:
|
|
||||||
pre-steps:
|
|
||||||
- configure-package-install
|
|
||||||
context: [qqq-maven-registry-credentials]
|
|
||||||
branch_type: snapshot
|
|
||||||
filters:
|
|
||||||
branches:
|
|
||||||
only: [develop]
|
|
||||||
|
|
||||||
publish_release_candidate:
|
|
||||||
jobs:
|
|
||||||
- qqq-orb/mvn_publish:
|
|
||||||
pre-steps:
|
|
||||||
- configure-package-install
|
|
||||||
context: [qqq-maven-registry-credentials]
|
|
||||||
branch_type: release_candidate
|
|
||||||
filters:
|
|
||||||
branches:
|
|
||||||
only: [/release\/.*/]
|
|
||||||
|
|
||||||
publish_release:
|
|
||||||
jobs:
|
|
||||||
- qqq-orb/mvn_publish:
|
|
||||||
pre-steps:
|
|
||||||
- configure-package-install
|
|
||||||
context: [qqq-maven-registry-credentials]
|
|
||||||
branch_type: release
|
|
||||||
filters:
|
|
||||||
branches:
|
|
||||||
ignore: /.*/
|
|
||||||
tags:
|
|
||||||
only: [/^v\d+\.\d+\.\d+$/]
|
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
name: CodeQL
|
||||||
|
'on':
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
- develop
|
||||||
|
- release/**
|
||||||
|
- hotfix/**
|
||||||
|
pull_request: {}
|
||||||
|
schedule:
|
||||||
|
- cron: 41 16 * * 0
|
||||||
|
workflow_dispatch: {}
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
actions: read
|
||||||
|
security-events: write
|
||||||
|
packages: read
|
||||||
|
concurrency:
|
||||||
|
group: codeql-${{ github.event.pull_request.number || github.ref }}
|
||||||
|
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
|
||||||
|
jobs:
|
||||||
|
analyze:
|
||||||
|
uses: QRun-IO/qqq-orb/.github/workflows/qbit-codeql.yml@c288a8864fe9054f68410e1d78f5863aea4c4d22
|
||||||
@@ -1,25 +1,74 @@
|
|||||||
# Cut the next release candidate (QRun-IO/qqq docs/QRUN-QBIT-REPO-STANDARD.md, C6):
|
|
||||||
# run this workflow by hand, or merge a develop PR labelled `release:rc`. It merges develop into
|
|
||||||
# the release line and the release/* push runs CircleCI publish_release_candidate.
|
|
||||||
name: Release candidate
|
name: Release candidate
|
||||||
|
'on':
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
inputs:
|
inputs:
|
||||||
dry_run:
|
dry_run:
|
||||||
description: Print the plan without merging or creating branches
|
description: Plan a cut without changing release state
|
||||||
type: boolean
|
type: boolean
|
||||||
default: false
|
default: false
|
||||||
|
finalize:
|
||||||
|
description: Retry finalization of an existing cut; do not cut another RC
|
||||||
|
type: boolean
|
||||||
|
default: false
|
||||||
|
recover:
|
||||||
|
description: Recover the same published RC after a deployment timeout; never
|
||||||
|
reupload
|
||||||
|
type: boolean
|
||||||
|
default: false
|
||||||
|
circle_build:
|
||||||
|
description: Original Circle publisher build number (recovery only)
|
||||||
|
type: string
|
||||||
|
default: ''
|
||||||
|
merge_sha:
|
||||||
|
description: Existing cut merge_sha (finalize retry only)
|
||||||
|
type: string
|
||||||
|
default: ''
|
||||||
|
bump_sha:
|
||||||
|
description: Existing cut bump_sha (finalize retry only)
|
||||||
|
type: string
|
||||||
|
default: ''
|
||||||
|
branch:
|
||||||
|
description: Existing cut branch (finalize retry only)
|
||||||
|
type: string
|
||||||
|
default: ''
|
||||||
|
version:
|
||||||
|
description: Existing cut version (finalize retry only)
|
||||||
|
type: string
|
||||||
|
default: ''
|
||||||
pull_request:
|
pull_request:
|
||||||
types: [closed]
|
types:
|
||||||
branches: [develop]
|
- closed
|
||||||
|
branches:
|
||||||
|
- develop
|
||||||
|
repository_dispatch:
|
||||||
|
types:
|
||||||
|
- qbit-rc-published
|
||||||
permissions:
|
permissions:
|
||||||
contents: write
|
contents: write
|
||||||
|
actions: read
|
||||||
|
checks: read
|
||||||
jobs:
|
jobs:
|
||||||
release-rc:
|
release-rc:
|
||||||
if: github.event_name == 'workflow_dispatch' || (github.event.pull_request.merged == true && contains(github.event.pull_request.labels.*.name, 'release:rc'))
|
if: github.event_name == 'workflow_dispatch' || github.event_name == 'repository_dispatch'
|
||||||
uses: QRun-IO/.github/.github/workflows/qbit-release-rc.yml@main
|
|| (github.event_name == 'pull_request' && github.event.pull_request.merged
|
||||||
|
== true && github.event.pull_request.base.ref == 'develop' && contains(github.event.pull_request.labels.*.name,
|
||||||
|
'release:rc'))
|
||||||
|
uses: QRun-IO/qqq-orb/.github/workflows/qbit-release-rc.yml@cc30f599e63c8e41629c99d23395bac1adb8bc44
|
||||||
with:
|
with:
|
||||||
dry_run: ${{ github.event_name == 'workflow_dispatch' && inputs.dry_run }}
|
dry_run: ${{ github.event_name == 'workflow_dispatch' && inputs.dry_run || false
|
||||||
|
}}
|
||||||
|
finalize: ${{ github.event_name == 'repository_dispatch' || (github.event_name
|
||||||
|
== 'workflow_dispatch' && inputs.finalize) }}
|
||||||
|
recover: ${{ github.event_name == 'workflow_dispatch' && inputs.recover || false
|
||||||
|
}}
|
||||||
|
circle_build: ${{ github.event_name == 'workflow_dispatch' && inputs.circle_build
|
||||||
|
|| '' }}
|
||||||
|
merge_sha: ${{ github.event_name == 'repository_dispatch' && github.event.client_payload.merge_sha
|
||||||
|
|| inputs.merge_sha || '' }}
|
||||||
|
bump_sha: ${{ github.event_name == 'repository_dispatch' && github.event.client_payload.bump_sha
|
||||||
|
|| inputs.bump_sha || '' }}
|
||||||
|
branch: ${{ github.event_name == 'repository_dispatch' && github.event.client_payload.branch
|
||||||
|
|| inputs.branch || '' }}
|
||||||
|
version: ${{ github.event_name == 'repository_dispatch' && github.event.client_payload.version
|
||||||
|
|| inputs.version || '' }}
|
||||||
|
secrets: inherit
|
||||||
+16
@@ -0,0 +1,16 @@
|
|||||||
|
profile: qbit
|
||||||
|
orb_version: 0.7.12
|
||||||
|
default_branch: develop
|
||||||
|
java_version: '21'
|
||||||
|
browsers: true
|
||||||
|
api_checks: false
|
||||||
|
docs_only: false
|
||||||
|
release_on_main: false
|
||||||
|
release_tag_policy: stable
|
||||||
|
test_branch_policy: non-release
|
||||||
|
publish:
|
||||||
|
snapshot: true
|
||||||
|
release_candidate: true
|
||||||
|
release: true
|
||||||
|
asciidoc: false
|
||||||
|
release_completion: true
|
||||||
@@ -16,6 +16,7 @@ All notable changes to this project are documented here. The format follows Keep
|
|||||||
- **Record developer panel** "SQL Workbench" (`SqlWorkbenchDeveloperPanelProvider`, registered by `SqlWorkbenchDeveloperPanelsMetaDataProducer`): read-only `SELECT`s for the record and its table in the backend's own names, backend details, and links that open them in the Runner as a new cell (`/app/sqlWorkbenchRunner?sql=&backend=`, never run). Requires QQQ 4.1.0-RC.4 (the developer panel contract) and a Next UI with the Runner `?sql=` support.
|
- **Record developer panel** "SQL Workbench" (`SqlWorkbenchDeveloperPanelProvider`, registered by `SqlWorkbenchDeveloperPanelsMetaDataProducer`): read-only `SELECT`s for the record and its table in the backend's own names, backend details, and links that open them in the Runner as a new cell (`/app/sqlWorkbenchRunner?sql=&backend=`, never run). Requires QQQ 4.1.0-RC.4 (the developer panel contract) and a Next UI with the Runner `?sql=` support.
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
- UI API extension sql-workbench 1.1.0 (requires QQQ 4.1.0-RC.15, UI API 1.6.0): operationIds, standard error responses with BasicErrorResponseV1, extension tags, and deprecated SqlWorkbenchErrorV1 retained for compatibility. Existing operationIds, HTTP statuses and success payloads are preserved.
|
||||||
- Require QQQ `4.1.0-RC.6` for the UI API extension contract. Replace the raw Javalin route provider with endpoint specs registered by the qbit producer. `registerRoutes=false` still disables HTTP registration. No existing operation wire changes.
|
- Require QQQ `4.1.0-RC.6` for the UI API extension contract. Replace the raw Javalin route provider with endpoint specs registered by the qbit producer. `registerRoutes=false` still disables HTTP registration. No existing operation wire changes.
|
||||||
- **The nav lists only the main tables**: Notebooks and the execution audit, after the Runner. Cells, versions, pinned results and shares are child lists on a notebook (still standard tables, reachable by URL and API). The app's widget list is now the dashboard, not the `SQL_WORKBENCH` widget; links to `/app/sqlWorkbench` that expected the editor should point at `/app/sqlWorkbenchRunner`.
|
- **The nav lists only the main tables**: Notebooks and the execution audit, after the Runner. Cells, versions, pinned results and shares are child lists on a notebook (still standard tables, reachable by URL and API). The app's widget list is now the dashboard, not the `SQL_WORKBENCH` widget; links to `/app/sqlWorkbench` that expected the editor should point at `/app/sqlWorkbenchRunner`.
|
||||||
- The notebook record's header shows the description.
|
- The notebook record's header shows the description.
|
||||||
|
|||||||
@@ -156,6 +156,7 @@
|
|||||||
<directory>src/main/resources</directory>
|
<directory>src/main/resources</directory>
|
||||||
<filtering>true</filtering>
|
<filtering>true</filtering>
|
||||||
<includes>
|
<includes>
|
||||||
|
<include>help/*.yaml</include>
|
||||||
<include>sql-workbench.properties</include>
|
<include>sql-workbench.properties</include>
|
||||||
</includes>
|
</includes>
|
||||||
</resource>
|
</resource>
|
||||||
@@ -163,6 +164,7 @@
|
|||||||
<directory>src/main/resources</directory>
|
<directory>src/main/resources</directory>
|
||||||
<filtering>false</filtering>
|
<filtering>false</filtering>
|
||||||
<excludes>
|
<excludes>
|
||||||
|
<exclude>help/*.yaml</exclude>
|
||||||
<exclude>sql-workbench.properties</exclude>
|
<exclude>sql-workbench.properties</exclude>
|
||||||
</excludes>
|
</excludes>
|
||||||
</resource>
|
</resource>
|
||||||
@@ -252,9 +254,9 @@
|
|||||||
|
|
||||||
<profiles>
|
<profiles>
|
||||||
<!-- Built against qqq 4.1 (QBitMetaDataProducer, runtime services, Javalin 7 -->
|
<!-- Built against qqq 4.1 (QBitMetaDataProducer, runtime services, Javalin 7 -->
|
||||||
<!-- specs and help bundles require 4.1.0-RC.7). Until -->
|
<!-- specs and help bundles require 4.1.0-RC.15). Until -->
|
||||||
<!-- qbit-build-parent 2.1.0 imports the released 4.1 BOM, this profile is -->
|
<!-- qbit-build-parent 2.1.0 imports the released 4.1 BOM, this profile is -->
|
||||||
<!-- active by default and imports qqq-bom-pom 4.1.0-RC.7 ahead of the -->
|
<!-- active by default and imports qqq-bom-pom 4.1.0-RC.15 ahead of the -->
|
||||||
<!-- parent's 4.0.0 BOM (same as qbit-quick-search, ADR-0007). -->
|
<!-- parent's 4.0.0 BOM (same as qbit-quick-search, ADR-0007). -->
|
||||||
<profile>
|
<profile>
|
||||||
<id>qqq-snapshot</id>
|
<id>qqq-snapshot</id>
|
||||||
@@ -262,7 +264,7 @@
|
|||||||
<activeByDefault>true</activeByDefault>
|
<activeByDefault>true</activeByDefault>
|
||||||
</activation>
|
</activation>
|
||||||
<properties>
|
<properties>
|
||||||
<qqq.snapshot.version>4.1.0-RC.7</qqq.snapshot.version>
|
<qqq.snapshot.version>4.1.0-RC.15</qqq.snapshot.version>
|
||||||
</properties>
|
</properties>
|
||||||
<dependencyManagement>
|
<dependencyManagement>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ public class SqlWorkbenchEndpoints
|
|||||||
public static MiddlewareSpecExtension extension()
|
public static MiddlewareSpecExtension extension()
|
||||||
{
|
{
|
||||||
return (new MiddlewareSpecExtension().withName("sql-workbench").withPathPrefix("/sql-workbench")
|
return (new MiddlewareSpecExtension().withName("sql-workbench").withPathPrefix("/sql-workbench")
|
||||||
.withSemanticVersion("1.0.0").withDescription("Audited SQL execution and notebooks")
|
.withSemanticVersion("1.1.0").withDescription("Audited SQL execution and notebooks")
|
||||||
.withSpec(GetCapabilitiesSpec.class)
|
.withSpec(GetCapabilitiesSpec.class)
|
||||||
.withSpec(GetSchemaSpec.class)
|
.withSpec(GetSchemaSpec.class)
|
||||||
.withSpec(ExecuteSpec.class)
|
.withSpec(ExecuteSpec.class)
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ import com.kingsrook.qqq.middleware.javalin.QJavalinUtils;
|
|||||||
import com.kingsrook.qqq.middleware.javalin.specs.BasicOperation;
|
import com.kingsrook.qqq.middleware.javalin.specs.BasicOperation;
|
||||||
import com.kingsrook.qqq.middleware.javalin.specs.BasicResponse;
|
import com.kingsrook.qqq.middleware.javalin.specs.BasicResponse;
|
||||||
import com.kingsrook.qqq.middleware.javalin.specs.extensions.AbstractJsonEndpointSpec;
|
import com.kingsrook.qqq.middleware.javalin.specs.extensions.AbstractJsonEndpointSpec;
|
||||||
|
import com.kingsrook.qqq.middleware.javalin.specs.v1.responses.BasicErrorResponseV1;
|
||||||
import com.kingsrook.qqq.openapi.model.HttpMethod;
|
import com.kingsrook.qqq.openapi.model.HttpMethod;
|
||||||
import com.kingsrook.qqq.openapi.model.In;
|
import com.kingsrook.qqq.openapi.model.In;
|
||||||
import com.kingsrook.qqq.openapi.model.Method;
|
import com.kingsrook.qqq.openapi.model.Method;
|
||||||
@@ -155,11 +156,11 @@ public abstract class SqlWorkbenchJsonSpec extends AbstractJsonEndpointSpec
|
|||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
static List<BasicResponse> errors()
|
static List<BasicResponse> errors()
|
||||||
{
|
{
|
||||||
return (List.of(new BasicResponse(HttpStatus.BAD_REQUEST, "Invalid input or execution limit exceeded", "SqlWorkbenchErrorV1"),
|
return (List.of(new BasicResponse(HttpStatus.BAD_REQUEST, "Invalid input or execution limit exceeded", BasicErrorResponseV1.class.getSimpleName()),
|
||||||
new BasicResponse(HttpStatus.UNAUTHORIZED, "Sign in required", "SqlWorkbenchErrorV1"),
|
new BasicResponse(HttpStatus.UNAUTHORIZED, "Sign in required", BasicErrorResponseV1.class.getSimpleName()),
|
||||||
new BasicResponse(HttpStatus.FORBIDDEN, "Permission denied", "SqlWorkbenchErrorV1"),
|
new BasicResponse(HttpStatus.FORBIDDEN, "Permission denied", BasicErrorResponseV1.class.getSimpleName()),
|
||||||
new BasicResponse(HttpStatus.NOT_FOUND, "Missing or invisible resource", "SqlWorkbenchErrorV1"),
|
new BasicResponse(HttpStatus.NOT_FOUND, "Missing or invisible resource", BasicErrorResponseV1.class.getSimpleName()),
|
||||||
new BasicResponse(HttpStatus.CONFLICT, "Execution UUID already used", "SqlWorkbenchErrorV1")));
|
new BasicResponse(HttpStatus.CONFLICT, "Execution UUID already used", BasicErrorResponseV1.class.getSimpleName())));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ public class SqlWorkbenchSchemas
|
|||||||
{
|
{
|
||||||
Map<String, Schema> schemas = new LinkedHashMap<>();
|
Map<String, Schema> schemas = new LinkedHashMap<>();
|
||||||
schemas.put("SqlWorkbenchErrorV1", new Schema().withType(Type.OBJECT)
|
schemas.put("SqlWorkbenchErrorV1", new Schema().withType(Type.OBJECT)
|
||||||
|
.withDescription("Deprecated since 1.1.0: errors use BasicErrorResponseV1.")
|
||||||
.withProperty("error", new Schema().withType(Type.STRING)));
|
.withProperty("error", new Schema().withType(Type.STRING)));
|
||||||
schemas.put("SqlWorkbenchEmptyRequestV1", new Schema().withType(Type.OBJECT));
|
schemas.put("SqlWorkbenchEmptyRequestV1", new Schema().withType(Type.OBJECT));
|
||||||
schemas.put("SqlWorkbenchDeletedV1", new Schema().withType(Type.OBJECT)
|
schemas.put("SqlWorkbenchDeletedV1", new Schema().withType(Type.OBJECT)
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
bundle: qbit-sql-workbench
|
bundle: qbit-sql-workbench
|
||||||
version: 1.0.0-SNAPSHOT
|
version: ${project.version}
|
||||||
layer: QBIT
|
layer: QBIT
|
||||||
entries:
|
entries:
|
||||||
- key: app:sqlWorkbench;slot:help
|
- key: app:sqlWorkbench;slot:help
|
||||||
|
|||||||
File diff suppressed because it is too large.
Load diff
@@ -22,6 +22,7 @@ import java.nio.file.Path;
|
|||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import com.kingsrook.qqq.middleware.javalin.specs.v1.MiddlewareVersionV1;
|
import com.kingsrook.qqq.middleware.javalin.specs.v1.MiddlewareVersionV1;
|
||||||
|
import com.kingsrook.qqq.middleware.javalin.specs.v1.responses.BasicErrorResponseV1;
|
||||||
import com.kingsrook.qqq.middleware.javalin.tools.UiApiContract;
|
import com.kingsrook.qqq.middleware.javalin.tools.UiApiContract;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
@@ -50,7 +51,7 @@ class SqlWorkbenchApiContractTest
|
|||||||
assertThat(UiApiContract.check(generated, Files.readString(path), null, 1,
|
assertThat(UiApiContract.check(generated, Files.readString(path), null, 1,
|
||||||
"./mvnw -Dtest=SqlWorkbenchApiContractTest -DsqlWorkbench.openapi.update=true test")).isEmpty();
|
"./mvnw -Dtest=SqlWorkbenchApiContractTest -DsqlWorkbench.openapi.update=true test")).isEmpty();
|
||||||
var model = version.generateExtensionOpenAPIModel("qqq", extension);
|
var model = version.generateExtensionOpenAPIModel("qqq", extension);
|
||||||
assertThat(model.getComponents().getSchemas().keySet()).allMatch(name -> name.startsWith("SqlWorkbench"));
|
assertThat(model.getComponents().getSchemas().keySet()).allMatch(name -> name.startsWith("SqlWorkbench") || name.equals(BasicErrorResponseV1.class.getSimpleName()));
|
||||||
assertThat(model.getPaths().keySet()).allMatch(name -> name.startsWith("/qqq/v1/sql-workbench/"));
|
assertThat(model.getPaths().keySet()).allMatch(name -> name.startsWith("/qqq/v1/sql-workbench/"));
|
||||||
assertThat(extension.getSpecs()).hasSize(21);
|
assertThat(extension.getSpecs()).hasSize(21);
|
||||||
assertThat(extension.getEffectivePathPrefix()).isEqualTo("/sql-workbench");
|
assertThat(extension.getEffectivePathPrefix()).isEqualTo("/sql-workbench");
|
||||||
|
|||||||
+26
-2
@@ -98,7 +98,29 @@ class SqlWorkbenchEndpointSpecTest extends BaseSqlWorkbenchTest
|
|||||||
builder.header("Content-Type", contentType);
|
builder.header("Content-Type", contentType);
|
||||||
}
|
}
|
||||||
builder.method(method, body == null ? HttpRequest.BodyPublishers.noBody() : HttpRequest.BodyPublishers.ofString(body));
|
builder.method(method, body == null ? HttpRequest.BodyPublishers.noBody() : HttpRequest.BodyPublishers.ofString(body));
|
||||||
return (client.send(builder.build(), HttpResponse.BodyHandlers.ofString()));
|
HttpResponse<String> response = client.send(builder.build(), HttpResponse.BodyHandlers.ofString());
|
||||||
|
if(response.statusCode() >= 400)
|
||||||
|
{
|
||||||
|
assertErrorBody(response);
|
||||||
|
}
|
||||||
|
return (response);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** HTTP errors retain their message and include the standard diagnostic fields.
|
||||||
|
*******************************************************************************/
|
||||||
|
private static void assertErrorBody(HttpResponse<String> response) throws Exception
|
||||||
|
{
|
||||||
|
Map<String, Object> body = json(response);
|
||||||
|
assertThat(body).containsKeys("error", "code", "message", "traceId");
|
||||||
|
for(String key : List.of("error", "code", "message", "traceId"))
|
||||||
|
{
|
||||||
|
assertThat(body.get(key)).as(key).isInstanceOf(String.class);
|
||||||
|
assertThat((String) body.get(key)).as(key).isNotBlank();
|
||||||
|
}
|
||||||
|
assertThat(body.get("message")).isEqualTo(body.get("error"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -236,7 +258,9 @@ class SqlWorkbenchEndpointSpecTest extends BaseSqlWorkbenchTest
|
|||||||
HttpRequest unauthenticated = HttpRequest.newBuilder(URI.create(base + path))
|
HttpRequest unauthenticated = HttpRequest.newBuilder(URI.create(base + path))
|
||||||
.header("Authorization", "Bearer Deny")
|
.header("Authorization", "Bearer Deny")
|
||||||
.method(method, HttpRequest.BodyPublishers.noBody()).build();
|
.method(method, HttpRequest.BodyPublishers.noBody()).build();
|
||||||
assertThat(client.send(unauthenticated, HttpResponse.BodyHandlers.ofString()).statusCode()).as(method + " authentication").isEqualTo(401);
|
HttpResponse<String> denied = client.send(unauthenticated, HttpResponse.BodyHandlers.ofString());
|
||||||
|
assertThat(denied.statusCode()).as(method + " authentication").isEqualTo(401);
|
||||||
|
assertErrorBody(denied);
|
||||||
}
|
}
|
||||||
assertThat(json(send("GET", "/history", READER, null, null)).get("executions")).asList().isEmpty();
|
assertThat(json(send("GET", "/history", READER, null, null)).get("executions")).asList().isEmpty();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in new issue
Block a user