Skip to content

Commit

Permalink
Feature/Query attribute versions (#132)
Browse files Browse the repository at this point in the history
* docu: new route definitions

* chore: fist implementation of some use cases

* feat: add all missing routes for the new usecases

* chore: remove added ts files

* chore: improve test speed

* chore: improve imports of types

* chore: add missing files

* chore: add change log

* chore: move new routes to Attributes section

* chore: remove todo

* chore: add mongodb as dev dependency

* chore: refactor to use QueryParam Injection

* chore: bump version

* fix: test typing

* chore: move client metadata up

* chore: fix tests

* chore: remove global context

* chore: move to jssoft db client and remove warning log from transport lib

* chore: improve error for bad config

* chore: remove math.random

* chore: use default values of use cases

* chore: improve query extraction

* chore: change log level

* chore: move private functions

* chore: add console log for ci tests

* chore: add second event to wait for with succession

* chore: fix tests by waiting for succeeded event

---------

Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
  • Loading branch information
sebbi08 and mergify[bot] authored Feb 20, 2024
1 parent b88b19d commit d8a15c9
Show file tree
Hide file tree
Showing 18 changed files with 843 additions and 51 deletions.
3 changes: 1 addition & 2 deletions .dev/Dockerfile.debug
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
FROM node:20.11.0
WORKDIR /usr/app
RUN npm install nodemon -g

# Webserver, Debugger
EXPOSE 80 9229

ENTRYPOINT ["nodemon", "-e", "js,json,yml", "--watch", "./dist", "--watch", "./config", "--inspect=0.0.0.0:9229", "--nolazy", "./dist/index.js"]
ENTRYPOINT ["npx", "nodemon", "-e", "js,json,yml", "--watch", "./dist", "--watch", "./config", "--inspect=0.0.0.0:9229", "--nolazy", "./dist/index.js"]
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
# Changelog

## 3.8.0

-> SDK 4.1.0

- add routes for querying versions of attrbutes
- `GET /api/v2/Attributes/Own/Repository` Get all the repository attributes
- `GET /api/v2/Attributes/Own/Shared/Identity` Get all own shared indentity attributes
- `GET /api/v2/Attributes/Peer/Shared/Identity` Get all peer shared identity attributes
- `GET /api/v2/Attributes/{id}/Versions` Get all versions of one repository attribute
- `GET /api/v2/Attributes/{id}/Versions/Shared` Get all shard versions of one repository attribute

## 3.7.3

- the webhooksV2 module is now named webhooks
Expand Down
9 changes: 5 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@nmshd/connector",
"version": "3.7.3",
"version": "3.8.0",
"private": true,
"description": "The Enmeshed Connector",
"homepage": "https://enmeshed.eu/integrate",
Expand Down
2 changes: 1 addition & 1 deletion packages/sdk/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@nmshd/connector-sdk",
"version": "4.0.0",
"version": "4.1.0",
"description": "the enmeshed connector sdk",
"keywords": [
"enmeshed",
Expand Down
23 changes: 23 additions & 0 deletions packages/sdk/src/endpoints/AttributesEndpoint.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ import {
ExecuteRelationshipAttributeQueryRequest,
ExecuteThirdPartyRelationshipAttributeQueryRequest,
GetAttributesRequest,
GetOwnRepositoryAttributesRequest,
GetOwnSharedIdentityAttributesRequest,
GetPeerSharedIdentityAttributesRequest,
GetSharedVersionsOfRepositoryAttributeRequest,
GetValidAttributesRequest,
NotifyPeerAboutRepositoryAttributeSuccessionRequest,
NotifyPeerAboutRepositoryAttributeSuccessionResponse,
Expand Down Expand Up @@ -44,6 +48,25 @@ export class AttributesEndpoint extends Endpoint {
return await this.get("/api/v2/Attributes/Valid", request);
}

public async getOwnRepositoryAttributes(request?: GetOwnRepositoryAttributesRequest): Promise<ConnectorResponse<ConnectorAttributes>> {
return await this.get("/api/v2/Attributes/Own/Repository", request);
}
public async getOwnSharedIdentityAttributes(request?: GetOwnSharedIdentityAttributesRequest): Promise<ConnectorResponse<ConnectorAttributes>> {
return await this.get("/api/v2/Attributes/Own/Shared/Identity", request);
}
public async getPeerSharedIdentityAttributes(request?: GetPeerSharedIdentityAttributesRequest): Promise<ConnectorResponse<ConnectorAttributes>> {
return await this.get("/api/v2/Attributes/Peer/Shared/Identity", request);
}
public async getVersionsOfAttribute(attributeId: string): Promise<ConnectorResponse<ConnectorAttributes>> {
return await this.get(`/api/v2/Attributes/${attributeId}/Versions`);
}
public async getSharedVersionsOfRepositoryAttribute(
attributeId: string,
request: GetSharedVersionsOfRepositoryAttributeRequest
): Promise<ConnectorResponse<ConnectorAttributes>> {
return await this.get(`/api/v2/Attributes/${attributeId}/Versions/Shared`, request);
}

public async executeIdentityAttributeQuery(request: ExecuteIdentityAttributeQueryRequest): Promise<ConnectorResponse<ConnectorAttributes>> {
return await this.post("/api/v2/Attributes/ExecuteIdentityAttributeQuery", request, 200);
}
Expand Down
4 changes: 4 additions & 0 deletions packages/sdk/src/types/attributes/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ export * from "./requests/ExecuteIdentityAttributeQueryRequest";
export * from "./requests/ExecuteRelationshipAttributeQueryRequest";
export * from "./requests/ExecuteThirdPartyRelationshipAttributeQueryRequest";
export * from "./requests/GetAttributesRequest";
export * from "./requests/GetOwnRepositoryAttributesRequest";
export * from "./requests/GetOwnSharedIdentityAttributesRequest";
export * from "./requests/GetPeerSharedIdentityAttributesRequest";
export * from "./requests/GetSharedVersionsOfRepositoryAttributeRequest";
export * from "./requests/GetValidAttributesRequest";
export * from "./requests/NotifyPeerAboutRepositoryAttributeSuccessionRequest";
export * from "./requests/NotifyPeerAboutRepositoryAttributeSuccessionResponse";
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export interface GetOwnRepositoryAttributesRequest {
onlyLatestVersions?: boolean;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
export interface GetOwnSharedIdentityAttributesRequest {
peer: string;
onlyValid?: boolean;
"query.createdAt"?: string;
"query.content.@type"?: string | string[];
"query.content.tags"?: string | string[];
"query.content.validFrom"?: string | string[];
"query.content.validTo"?: string | string[];
"query.content.key"?: string | string[];
"query.content.isTechnical"?: string | string[];
"query.content.confidentiality"?: string | string[];
"query.content.value.@type"?: string | string[];
"query.shareInfo"?: string | string[];
"query.shareInfo.requestReference"?: string | string[];
"query.shareInfo.notificationReference"?: string | string[];
"query.shareInfo.sourceAttribute"?: string | string[];
hideTechnical?: boolean;
onlyLatestVersions?: boolean;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
export interface GetPeerSharedIdentityAttributesRequest {
peer: string;
onlyValid?: boolean;
"query.createdAt"?: string;
"query.content.@type"?: string | string[];
"query.content.tags"?: string | string[];
"query.content.validFrom"?: string | string[];
"query.content.validTo"?: string | string[];
"query.content.key"?: string | string[];
"query.content.isTechnical"?: string | string[];
"query.content.confidentiality"?: string | string[];
"query.content.value.@type"?: string | string[];
"query.shareInfo"?: string | string[];
"query.shareInfo.requestReference"?: string | string[];
"query.shareInfo.notificationReference"?: string | string[];
hideTechnical?: boolean;
onlyLatestVersions?: boolean;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export interface GetSharedVersionsOfRepositoryAttributeRequest {
peers?: string[];
onlyLatestVersions?: boolean;
}
6 changes: 3 additions & 3 deletions packages/sdk/src/types/index.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
export * from "./ConnectorError";
export * from "./ConnectorResponse";
export * from "./account";
export * from "./attributes";
export * from "./challenges";
export * from "./ConnectorError";
export * from "./ConnectorResponse";
export * from "./files";
export * from "./messages";
export * from "./relationships";
export * from "./relationshipTemplates";
export * from "./relationships";
export * from "./requests";
export * from "./tokens";
103 changes: 102 additions & 1 deletion src/modules/coreHttpApi/controllers/AttributesController.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { ApplicationError } from "@js-soft/ts-utils";
import { ConsumptionServices, RuntimeErrors, TransportServices } from "@nmshd/runtime";
import { Inject } from "typescript-ioc";
import { Accept, Context, GET, POST, Path, PathParam, Return, ServiceContext } from "typescript-rest";
import { Accept, Context, GET, POST, Path, PathParam, QueryParam, Return, ServiceContext } from "typescript-rest";
import { Envelope } from "../../../infrastructure";
import { BaseController } from "../common/BaseController";

Expand Down Expand Up @@ -74,6 +74,90 @@ export class AttributesController extends BaseController {
return this.ok(result);
}

@GET
@Path("/Own/Repository")
@Accept("application/json")
public async getOwnRepositoryAttributes(@QueryParam("onlyLatestVersions") onlyLatestVersions?: string): Promise<Envelope> {
const result = await this.consumptionServices.attributes.getRepositoryAttributes({
onlyLatestVersions: this.stringToBoolean(onlyLatestVersions)
});
return this.ok(result);
}

@GET
@Path("/Own/Shared/Identity")
@Accept("application/json")
public async getOwnSharedIdentityAttributes(
@Context context: ServiceContext,
@QueryParam("peer") peer: string,
@QueryParam("hideTechnical") hideTechnical?: string,
@QueryParam("onlyLatestVersions") onlyLatestVersions?: string,
@QueryParam("onlyValid") onlyValid?: string
): Promise<Envelope> {
const query: Record<string, any> = this.extractQuery(context.request.query, ["peer", "hideTechnical", "onlyLatestVersions", "onlyValid"]);

const result = await this.consumptionServices.attributes.getOwnSharedAttributes({
peer,
hideTechnical: this.stringToBoolean(hideTechnical),
query,
onlyLatestVersions: this.stringToBoolean(onlyLatestVersions),
onlyValid: this.stringToBoolean(onlyValid)
});
return this.ok(result);
}

@GET
@Path("/Peer/Shared/Identity")
@Accept("application/json")
public async getPeerSharedIdentityAttributes(
@Context context: ServiceContext,
@QueryParam("peer") peer: string,
@QueryParam("hideTechnical") hideTechnical?: string,
@QueryParam("onlyLatestVersions") onlyLatestVersions?: string,
@QueryParam("onlyValid") onlyValid?: string
): Promise<Envelope> {
const query: Record<string, any> = this.extractQuery(context.request.query, ["peer", "hideTechnical", "onlyLatestVersions", "onlyValid"]);

const result = await this.consumptionServices.attributes.getPeerSharedAttributes({
peer,
hideTechnical: this.stringToBoolean(hideTechnical),
query,
onlyLatestVersions: this.stringToBoolean(onlyLatestVersions),
onlyValid: this.stringToBoolean(onlyValid)
});
return this.ok(result);
}

@GET
@Path("/:id/Versions")
@Accept("application/json")
public async getVersionsOfAttribute(@PathParam("id") attributeId: string): Promise<Envelope> {
const result = await this.consumptionServices.attributes.getVersionsOfAttribute({
attributeId
});
return this.ok(result);
}

@GET
@Path("/:id/Versions/Shared")
@Accept("application/json")
public async getSharedVersionsOfRepositoryAttribute(
@PathParam("id") attributeId: string,
@QueryParam("peers") peers?: string | string[],
@QueryParam("onlyLatestVersions") onlyLatestVersions?: string
): Promise<Envelope> {
if (typeof peers === "string") {
peers = [peers];
}

const result = await this.consumptionServices.attributes.getSharedVersionsOfRepositoryAttribute({
attributeId,
onlyLatestVersions: this.stringToBoolean(onlyLatestVersions),
peers
});
return this.ok(result);
}

@GET
@Path("/Valid")
@Accept("application/json")
Expand Down Expand Up @@ -129,4 +213,21 @@ export class AttributesController extends BaseController {
const result = await this.consumptionServices.attributes.getAttribute({ id });
return this.ok(result);
}

private stringToBoolean(value: string | undefined): boolean | undefined {
if (value === undefined) {
return undefined;
}

return value.toLowerCase() === "true";
}

private extractQuery(query: ServiceContext["request"]["query"], nonQueryParams: string[]): Record<string, any> {
return Object.entries(query)
.filter(([key, _]) => !nonQueryParams.includes(key))
.reduce<Record<string, any>>((previous, [key, value]) => {
previous[key] = value as string | string[];
return previous;
}, {});
}
}
Loading

0 comments on commit d8a15c9

Please sign in to comment.