Skip to content

Commit

Permalink
docs: makes IdentityHub API Swagger-UI compliant
Browse files Browse the repository at this point in the history
  • Loading branch information
bscholtes1A committed Feb 29, 2024
1 parent a411560 commit 3193166
Show file tree
Hide file tree
Showing 15 changed files with 93 additions and 33 deletions.
17 changes: 9 additions & 8 deletions .github/workflows/apidoc.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,14 @@ jobs:
# Disable temporarily, because we can only have 3 APIs in the SwaggerHub free tier
if: github.repository == 'eclipse-edc/IdentityHub' && false
runs-on: ubuntu-latest
strategy:
matrix:
apiGroup: [ 'ih-resolution-api', 'ih-management-api' ]
env:
rootDir: resources/openapi/yaml
rootDir: resources/openapi/yaml/${{ matrix.apiGroup }}
SWAGGERHUB_API_KEY: ${{ secrets.SWAGGERHUB_TOKEN }}
SWAGGERHUB_USER: ${{ secrets.SWAGGERHUB_USER }}
VERSION: ${{ github.event.inputs.version || inputs.version }}
API_NAME: 'ih-api'
OUTPUT_FILE_NAME: 'ihapi.yaml'
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/setup-build
Expand All @@ -49,7 +50,7 @@ jobs:
cmd="-Pversion=$VERSION"
fi
./gradlew resolve
./gradlew ${cmd} -PapiTitle="IdentityHub REST API" -PapiDescription="REST API documentation for the IdentityHub" :mergeApiSpec --input=${{ env.rootDir }} --output=${{ env.OUTPUT_FILE_NAME }}
./gradlew ${cmd} -PapiTitle="${{ matrix.apiGroup }}" -PapiDescription="REST API documentation for the ${{ matrix.apiGroup }}" :mergeApiSpec --input=${{ env.rootDir }} --output=${{ matrix.apiGroup }}.yaml
# install swaggerhub CLI
- name: Install SwaggerHub CLI
Expand All @@ -59,7 +60,7 @@ jobs:
- name: Create API
continue-on-error: true
run: |
swaggerhub api:create ${{ env.SWAGGERHUB_USER }}/${{ env.API_NAME }} -f ${{ env.OUTPUT_FILE_NAME }} --visibility=public --published=unpublish
swaggerhub api:create ${{ env.SWAGGERHUB_USER }}/${{ matrix.apiGroup }} -f ${{ matrix.apiGroup }}.yaml --visibility=public --published=unpublish
# Post snapshots of the API to SwaggerHub as "unpublished", because published APIs cannot be overwritten
- name: Publish API Specs to SwaggerHub
Expand All @@ -69,9 +70,9 @@ jobs:
if [[ $vers != *-SNAPSHOT ]]; then
echo "no snapshot, will set the API to 'published'";
swaggerhub api:update ${{ env.SWAGGERHUB_USER }}/${{ env.API_NAME }} -f ${{ env.OUTPUT_FILE_NAME }} --visibility=public --published=publish
swaggerhub api:setdefault ${{ env.SWAGGERHUB_USER }}/${{ env.API_NAME }}/$vers
swaggerhub api:update ${{ env.SWAGGERHUB_USER }}/${{ matrix.apiGroup }} -f ${{ matrix.apiGroup }}.yaml --visibility=public --published=publish
swaggerhub api:setdefault ${{ env.SWAGGERHUB_USER }}/${{ matrix.apiGroup }}/$vers
else
echo "snapshot, will set the API to 'unpublished'";
swaggerhub api:update ${{ env.SWAGGERHUB_USER }}/${{ env.API_NAME }} -f ${{ env.OUTPUT_FILE_NAME }} --visibility=public --published=unpublish
swaggerhub api:update ${{ env.SWAGGERHUB_USER }}/${{ matrix.apiGroup }} -f ${{ matrix.apiGroup }}.yaml --visibility=public --published=unpublish
fi
6 changes: 6 additions & 0 deletions core/identity-hub-api/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,9 @@ dependencies {
testImplementation(testFixtures(project(":spi:identity-hub-spi")))
testImplementation(libs.nimbus.jwt)
}

edcBuild {
swagger {
apiGroup.set("ih-resolution-api")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,9 @@ record PresentationQuerySchema(
"@type": "PresentationQueryMessage",
"presentationDefinition": null,
"scope": [
"org.eclipse.edc.vc.type:SomeCredential_0.3.5:write,
"org.eclipse.edc.vc.type:SomeOtherCredential:read,
"org.eclipse.edc.vc.type:ThirdCredential:*,
"org.eclipse.edc.vc.type:SomeCredential_0.3.5:write",
"org.eclipse.edc.vc.type:SomeOtherCredential:read",
"org.eclipse.edc.vc.type:ThirdCredential:*"
]
}
""";
Expand All @@ -75,7 +75,7 @@ record PresentationQuerySchema(
record PresentationResponseSchema(
@Schema(name = CONTEXT, requiredMode = REQUIRED)
Object context,
@Schema(name = "presentation", requiredMode = REQUIRED, anyOf = { String.class, JsonObject.class })
@Schema(name = "presentation", requiredMode = REQUIRED, anyOf = {String.class, JsonObject.class})
List<Object> presentation
) {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,19 +41,19 @@ public interface PresentationApi {

@Tag(name = "Resolution API")
@Operation(description = "Issues a new presentation query, that contains either a DIF presentation definition, or a list of scopes",
requestBody = @RequestBody(content = @Content(schema = @Schema(implementation = ApiSchema.PresentationQuerySchema.class), mediaType = "application/ld+json")),
requestBody = @RequestBody(content = @Content(schema = @Schema(implementation = ApiSchema.PresentationQuerySchema.class))),
responses = {
@ApiResponse(responseCode = "200", description = "The query was successfully processed, the response contains the VerifiablePresentation",
content = @Content(schema = @Schema(implementation = ApiSchema.PresentationResponseSchema.class), mediaType = "application/ld+json")),
content = @Content(schema = @Schema(implementation = ApiSchema.PresentationResponseSchema.class))),
@ApiResponse(responseCode = "400", description = "Request body was malformed, for example when both scope and presentationDefinition are given",
content = @Content(array = @ArraySchema(schema = @Schema(implementation = ApiSchema.ApiErrorDetailSchema.class)), mediaType = "application/json")),
content = @Content(array = @ArraySchema(schema = @Schema(implementation = ApiSchema.ApiErrorDetailSchema.class)))),
@ApiResponse(responseCode = "401", description = "No Authorization header was given.",
content = @Content(array = @ArraySchema(schema = @Schema(implementation = ApiSchema.ApiErrorDetailSchema.class)), mediaType = "application/json")),
content = @Content(array = @ArraySchema(schema = @Schema(implementation = ApiSchema.ApiErrorDetailSchema.class)))),
@ApiResponse(responseCode = "403", description = "The given authentication token could not be validated. This can happen, when the request body " +
"calls for a broader query scope than the granted scope in the auth token",
content = @Content(array = @ArraySchema(schema = @Schema(implementation = ApiSchema.ApiErrorDetailSchema.class)), mediaType = "application/json")),
"calls for a broader query scope than the granted scope in the auth token",
content = @Content(array = @ArraySchema(schema = @Schema(implementation = ApiSchema.ApiErrorDetailSchema.class)))),
@ApiResponse(responseCode = "501", description = "When the request contained a presentationDefinition object, but the implementation does not support it.",
content = @Content(array = @ArraySchema(schema = @Schema(implementation = ApiSchema.ApiErrorDetailSchema.class)), mediaType = "application/json"))
content = @Content(array = @ArraySchema(schema = @Schema(implementation = ApiSchema.ApiErrorDetailSchema.class))))
}
)
Response queryPresentation(String participantContextId, JsonObject query, String authHeader);
Expand Down
6 changes: 6 additions & 0 deletions extensions/api/did-mgmt-api/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,9 @@ dependencies {
testImplementation(libs.nimbus.jwt)
testImplementation(libs.restAssured)
}

edcBuild {
swagger {
apiGroup.set("ih-management-api")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import io.swagger.v3.oas.annotations.OpenAPIDefinition;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.enums.ParameterIn;
import io.swagger.v3.oas.annotations.info.Info;
import io.swagger.v3.oas.annotations.media.ArraySchema;
import io.swagger.v3.oas.annotations.media.Content;
Expand All @@ -39,6 +40,7 @@ public interface DidManagementApi {

@Tag(name = "DID Management API")
@Operation(description = "Publish an (existing) DID document. The DID is expected to exist in the database.",
parameters = {@Parameter(name = "participantId", description = "Base64-Url encode Participant Context ID", required = true, in = ParameterIn.PATH)},
requestBody = @RequestBody(content = @Content(schema = @Schema(implementation = DidRequestPayload.class), mediaType = "application/json")),
responses = {
@ApiResponse(responseCode = "200", description = "The DID document was successfully published."),
Expand All @@ -52,6 +54,7 @@ public interface DidManagementApi {

@Tag(name = "DID Management API")
@Operation(description = "Un-Publish an (existing) DID document. The DID is expected to exist in the database.",
parameters = {@Parameter(name = "participantId", description = "Base64-Url encode Participant Context ID", required = true, in = ParameterIn.PATH)},
requestBody = @RequestBody(content = @Content(schema = @Schema(implementation = DidRequestPayload.class), mediaType = "application/json")),
responses = {
@ApiResponse(responseCode = "200", description = "The DID document was successfully un-published."),
Expand All @@ -67,6 +70,7 @@ public interface DidManagementApi {

@Tag(name = "DID Management API")
@Operation(description = "Query for DID documents..",
parameters = {@Parameter(name = "participantId", description = "Base64-Url encode Participant Context ID", required = true, in = ParameterIn.PATH)},
requestBody = @RequestBody(content = @Content(schema = @Schema(implementation = QuerySpec.class), mediaType = "application/json")),
responses = {
@ApiResponse(responseCode = "200", description = "The list of DID Documents.",
Expand All @@ -81,6 +85,7 @@ public interface DidManagementApi {

@Tag(name = "DID Management API")
@Operation(description = "Get state of a DID document",
parameters = {@Parameter(name = "participantId", description = "Base64-Url encode Participant Context ID", required = true, in = ParameterIn.PATH)},
requestBody = @RequestBody(content = @Content(schema = @Schema(implementation = DidRequestPayload.class), mediaType = "application/json")),
responses = {
@ApiResponse(responseCode = "200", description = "The DID state was successfully obtained"),
Expand All @@ -95,7 +100,10 @@ public interface DidManagementApi {
@Tag(name = "DID Management API")
@Operation(description = "Adds a service endpoint to a particular DID document.",
requestBody = @RequestBody(content = @Content(schema = @Schema(implementation = Service.class), mediaType = "application/json")),
parameters = {@Parameter(name = "autoPublish", description = "Whether the DID should get republished after the removal. Defaults to false.")},
parameters = {
@Parameter(name = "autoPublish", description = "Whether the DID should get republished after the removal. Defaults to false."),
@Parameter(name = "participantId", description = "Base64-Url encode Participant Context ID", required = true, in = ParameterIn.PATH)
},
responses = {
@ApiResponse(responseCode = "200", description = "The DID document was successfully updated."),
@ApiResponse(responseCode = "401", description = "The request could not be completed, because either the authentication was missing or was not valid.",
Expand All @@ -111,7 +119,10 @@ public interface DidManagementApi {
@Tag(name = "DID Management API")
@Operation(description = "Replaces a service endpoint of a particular DID document.",
requestBody = @RequestBody(content = @Content(schema = @Schema(implementation = Service.class), mediaType = "application/json")),
parameters = {@Parameter(name = "autoPublish", description = "Whether the DID should get republished after the removal. Defaults to false.")},
parameters = {
@Parameter(name = "autoPublish", description = "Whether the DID should get republished after the removal. Defaults to false."),
@Parameter(name = "participantId", description = "Base64-Url encode Participant Context ID", required = true, in = ParameterIn.PATH)
},
responses = {
@ApiResponse(responseCode = "200", description = "The DID document was successfully updated."),
@ApiResponse(responseCode = "401", description = "The request could not be completed, because either the authentication was missing or was not valid.",
Expand All @@ -126,9 +137,11 @@ public interface DidManagementApi {

@Tag(name = "DID Management API")
@Operation(description = "Removes a service endpoint from a particular DID document.",
requestBody = @RequestBody(content = @Content(schema = @Schema(implementation = Service.class), mediaType = "application/json")),
parameters = {@Parameter(name = "serviceId", description = "The ID of the service that should get removed"), @Parameter(name = "autoPublish", description = "Whether the DID should " +
"get republished after the removal. Defaults to false.")},
parameters = {
@Parameter(name = "serviceId", description = "The ID of the service that should get removed"),
@Parameter(name = "autoPublish", description = "Whether the DID should " + "get republished after the removal. Defaults to false."),
@Parameter(name = "participantId", description = "Base64-Url encode Participant Context ID", required = true, in = ParameterIn.PATH)
},
responses = {
@ApiResponse(responseCode = "200", description = "The DID document was successfully updated."),
@ApiResponse(responseCode = "401", description = "The request could not be completed, because either the authentication was missing or was not valid.",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
plugins {
`java-library`
`maven-publish`
id("io.swagger.core.v3.swagger-gradle-plugin")
}

dependencies {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
plugins {
`java-library`
`maven-publish`
id("io.swagger.core.v3.swagger-gradle-plugin")
}

dependencies {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
plugins {
`java-library`
`maven-publish`
id("io.swagger.core.v3.swagger-gradle-plugin")
}

dependencies {
Expand Down
6 changes: 6 additions & 0 deletions extensions/api/keypair-mgmt-api/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,9 @@ dependencies {
testImplementation(libs.restAssured)
testImplementation(testFixtures(libs.edc.core.jersey))
}

edcBuild {
swagger {
apiGroup.set("ih-management-api")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import io.swagger.v3.oas.annotations.OpenAPIDefinition;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.enums.ParameterIn;
import io.swagger.v3.oas.annotations.info.Info;
import io.swagger.v3.oas.annotations.media.ArraySchema;
import io.swagger.v3.oas.annotations.media.Content;
Expand All @@ -37,6 +38,9 @@ public interface KeyPairResourceApi {

@Tag(name = "KeyPairResources Management API")
@Operation(description = "Finds a KeyPairResource by ID.",
parameters = {
@Parameter(name = "participantId", description = "Base64-Url encode Participant Context ID", required = true, in = ParameterIn.PATH)
},
responses = {
@ApiResponse(responseCode = "200", description = "The KeyPairResource.",
content = @Content(schema = @Schema(implementation = ParticipantContext.class))),
Expand Down Expand Up @@ -85,6 +89,9 @@ public interface KeyPairResourceApi {

@Tag(name = "KeyPairResources Management API")
@Operation(description = "Sets a KeyPairResource to the ACTIVE state. Will fail if the current state is anything other than ACTIVE or CREATED.",
parameters = {
@Parameter(name = "participantId", description = "Base64-Url encode Participant Context ID", required = true, in = ParameterIn.PATH)
},
responses = {
@ApiResponse(responseCode = "200", description = "The KeyPairResource.",
content = @Content(schema = @Schema(implementation = ParticipantContext.class))),
Expand All @@ -101,7 +108,10 @@ public interface KeyPairResourceApi {
@Tag(name = "KeyPairResources Management API")
@Operation(description = "Rotates (=retires) a particular key pair, identified by their ID and optionally create a new successor key.",
requestBody = @RequestBody(content = @Content(schema = @Schema(implementation = KeyDescriptor.class), mediaType = "application/json")),
parameters = @Parameter(name = "duration", description = "Indicates for how long the public key of the rotated/retired key pair should still be available "),
parameters = {
@Parameter(name = "duration", description = "Indicates for how long the public key of the rotated/retired key pair should still be available "),
@Parameter(name = "participantId", description = "Base64-Url encode Participant Context ID", required = true, in = ParameterIn.PATH)
},
responses = {
@ApiResponse(responseCode = "200", description = "The KeyPairResource was successfully rotated and linked to the participant.",
content = @Content(schema = @Schema(implementation = ParticipantContext.class))),
Expand All @@ -117,6 +127,9 @@ public interface KeyPairResourceApi {

@Tag(name = "KeyPairResources Management API")
@Operation(description = "Revokes (=removes) a particular key pair, identified by their ID and create a new successor key.",
parameters = {
@Parameter(name = "participantId", description = "Base64-Url encode Participant Context ID", required = true, in = ParameterIn.PATH)
},
requestBody = @RequestBody(content = @Content(schema = @Schema(implementation = KeyDescriptor.class), mediaType = "application/json")),
responses = {
@ApiResponse(responseCode = "200", description = "The KeyPairResource was successfully rotated and linked to the participant.",
Expand Down
6 changes: 6 additions & 0 deletions extensions/api/participant-context-mgmt-api/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,9 @@ dependencies {
testImplementation(libs.nimbus.jwt)
testImplementation(libs.restAssured)
}

edcBuild {
swagger {
apiGroup.set("ih-management-api")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@ public interface ParticipantContextApi {

@Tag(name = "ParticipantContext Management API")
@Operation(description = "Gets ParticipantContexts by ID.",
requestBody = @RequestBody(content = @Content(schema = @Schema(implementation = ParticipantManifest.class), mediaType = "application/json")),
responses = {
@ApiResponse(responseCode = "200", description = "The list of ParticipantContexts.",
content = @Content(schema = @Schema(implementation = ParticipantContext.class))),
Expand Down Expand Up @@ -100,7 +99,6 @@ public interface ParticipantContextApi {

@Tag(name = "ParticipantContext Management API")
@Operation(description = "Delete a ParticipantContext.",
requestBody = @RequestBody(content = @Content(schema = @Schema(implementation = ParticipantManifest.class), mediaType = "application/json")),
responses = {
@ApiResponse(responseCode = "200", description = "The ParticipantContext was deleted successfully", content = {@Content(schema = @Schema(implementation = String.class))}),
@ApiResponse(responseCode = "400", description = "Request body was malformed, or the request could not be processed",
Expand Down
Loading

0 comments on commit 3193166

Please sign in to comment.