From 5cf35144a3749d096eb9138d80a029e8b2476951 Mon Sep 17 00:00:00 2001 From: Linus Gasser Date: Thu, 30 Jul 2020 12:01:32 +0200 Subject: [PATCH] Adding documentation to DPPTConfigController Adds the same configuration as for the dpppt-backend-sdk-ws: - doc-annotations - README.md --- Makefile | 41 ++++ README.md | 44 ++++ documentation/yaml/sdk.yaml | 198 ++++++++++++++++++ dpppt-config-backend/.gitignore | 2 + dpppt-config-backend/pom.xml | 54 +++++ .../ws/controller/GaenConfigController.java | 77 ++++++- .../sdk/config/ws/model/ConfigResponse.java | 8 + .../sdk/config/ws/model/GAENSDKConfig.java | 17 ++ .../backend/sdk/config/ws/model/InfoBox.java | 6 + .../config/ws/model/InfoBoxCollection.java | 1 + 10 files changed, 444 insertions(+), 4 deletions(-) create mode 100644 Makefile create mode 100644 documentation/yaml/sdk.yaml create mode 100644 dpppt-config-backend/.gitignore diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..5632869 --- /dev/null +++ b/Makefile @@ -0,0 +1,41 @@ +###################### +# Makefile # +###################### + +FILE_NAME = documentation.tex + +LATEX = xelatex +BIBER = biber +RUSTY_SWAGGER = rusty-swagger + +all: clean all1 +all1: clean updateproject updatedoc swagger la la2 la3 +no: clean updateproject updatedoc swagger la la2 +docker-build: updateproject docker +doc: updatedoc swagger la la2 la3 + +updateproject: + mvn -f dpppt-config-backend/pom.xml install + +updatedoc: + mvn -f dpppt-config-backend/pom.xml install -Dmaven.test.skip=true + mvn springboot-swagger-3:springboot-swagger-3 -f dpppt-config-backend/pom.xml + mkdir -p documentation/yaml + cp dpppt-config-backend/generated/swagger/swagger.yaml documentation/yaml/sdk.yaml + +swagger: + cd documentation; $(RUSTY_SWAGGER) --file ../dpppt-config-backend/dpppt-config-backend/generated/swagger/swagger.yaml + +la: + cd documentation;$(LATEX) $(FILE_NAME) +bib: + cd documentation;$(BIBER) $(FILE_NAME) +la2: + cd documentation;$(LATEX) $(FILE_NAME) +la3: + cd documentation;$(LATEX) $(FILE_NAME) +show: + cd documentation; open $(FILE_NAME).pdf & + +clean: + @rm -f documentation/*.log documentation/*.aux documentation/*.dvi documentation/*.ps documentation/*.blg documentation/*.bbl documentation/*.out documentation/*.bcf documentation/*.run.xml documentation/*.fdb_latexmk documentation/*.fls documentation/*.toc diff --git a/README.md b/README.md index 0d8c596..1502f42 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,46 @@ # dp3t-config-backend-ch +This backend is used by the apps to get their config every 6h. It is used by the Swiss Government to update the +epidemiological parameters if needed. + +The following endpoints are available: + +- `/v1` - returns `Hello from DP3T Config WS` +- `/v1/config` - returns a `ConfigResponse` with the following structure and default values: + - `InfoBoxCollection` - empty by default + - `deInfoBox` `InfoBox` + - `title` `String` + - `msg` `String` + - `url` `String` + - `urlTitle` `String` + - `isDismissible = false` + - `frInfoBox` `InfoBox` + - `itInfoBox` `InfoBox` + - `enInfoBox` `InfoBox` + - `ptInfoBox` `InfoBox` + - `esInfoBox` `InfoBox` + - `sqInfoBox` `InfoBox` + - `bsInfoBox` `InfoBox` + - `hrInfoBox` `InfoBox` + - `srInfoBox` `InfoBox` + - `rmInfoBox` `InfoBox` + - `SDKConfig` - will soon be removed (30/7/2020) + - `numberOfWindowsForExposure = 3` + - @Deprecated `eventThreshold = 0.8f` + - @Deprecated `badAttenuationThreshold = 73.0f` + - `contactAttenuationThreshold = 73.0f` + - iOSGaenSdkConfig `GAENSDKConfig` + - `lowerThreshold = 53` + - `higherThreshold = 60` + - `factorLow = 1.0d` + - `factorHigh = 0.5d` + - `triggerThreshold = 15` + - androidGaenSdkConfig `GAENSDKConfig` +- `/v1/testinfobox/config` - returns a `ConfigResponse` with only the `SDKConfig` set to a static message + +## /config special actions + +The call to `/v1/config` does the following special actions: +1. `If iOS == 13.6`: warn that the German 'no risk' message is misleading +1. `If App == Testflight`: warn that the app should be updated to the official app-store app +1. `If App == Initial iOS test app`: set `factorHigh` = `0` to avoid errors diff --git a/documentation/yaml/sdk.yaml b/documentation/yaml/sdk.yaml new file mode 100644 index 0000000..951f325 --- /dev/null +++ b/documentation/yaml/sdk.yaml @@ -0,0 +1,198 @@ +openapi: 3.0.0 +servers: +- url: https://demo.dpppt.org + description: '' +info: + version: 1.0-gapple + description: DP3T API + title: DP3T API +paths: + /v1/: + get: + summary: hello + description: Echo endpoint + responses: + '200': + description: Hello from DP3T Config WS + content: + application/json: + schema: + type: string + /v1/config: + get: + summary: getConfig + description: Read latest configuration and messages, depending on the version + of the phone and the app. + responses: + '200': + description: ConfigResponse structure with eventual notifications and epidemic + parameters + content: + application/json: + schema: + $ref: '#/components/schemas/org.dpppt.switzerland.backend.sdk.config.ws.model.ConfigResponse' + parameters: + - name: osversion + in: query + description: Version of the OS + example: ios13.6 + required: true + schema: + type: string + - name: buildnr + in: query + description: Build number of the app + example: ios-200619.2333.175 + required: true + schema: + type: string + /v1/testinfobox/config: + get: + summary: getGhettoboxConfig + description: getGhettoboxConfig + responses: + '200': + description: '' + content: + application/json: + schema: + $ref: '#/components/schemas/org.dpppt.switzerland.backend.sdk.config.ws.model.ConfigResponse' + parameters: + - name: appversion + in: query + description: '' + required: true + schema: + type: string + - name: osversion + in: query + description: '' + required: true + schema: + type: string + - name: buildnr + in: query + description: '' + required: true + schema: + type: string +components: + schemas: + org.dpppt.switzerland.backend.sdk.config.ws.model.ConfigResponse: + type: object + properties: + forceUpdate: + type: boolean + forceTraceShutdown: + type: boolean + infoBox: + $ref: '#/components/schemas/org.dpppt.switzerland.backend.sdk.config.ws.model.InfoBoxCollection' + description: Holds a message translated in different languages + example: '' + sdkConfig: + $ref: '#/components/schemas/org.dpppt.switzerland.backend.sdk.config.ws.model.SDKConfig' + description: Configuration of the epidemiological parameters for the pre-GAEN + DPPPT process + example: '' + iOSGaenSdkConfig: + $ref: '#/components/schemas/org.dpppt.switzerland.backend.sdk.config.ws.model.GAENSDKConfig' + description: GAEN epidemiological parameters for iOS + example: '' + androidGaenSdkConfig: + $ref: '#/components/schemas/org.dpppt.switzerland.backend.sdk.config.ws.model.GAENSDKConfig' + description: GAEN epidemiological parameters for Android + example: '' + org.dpppt.switzerland.backend.sdk.config.ws.model.GAENSDKConfig: + type: object + properties: + lowerThreshold: + type: integer + description: Lower threshold that is sent to the GAEN to count encounters + with other devices. It is expressed in dB attenuation from the Bluetooth + chip. + example: '53' + higherThreshold: + type: integer + description: Higher threshold that is sent to the GAEN to count encounters + with other devices It is expressed in dB attenuation from the Bluetooth + chip. + example: '' + factorLow: + type: number + format: double + description: Multiplication factor used to weigh the return value of the + GAEN in attenuationDuration[0] + example: 1.0d + factorHigh: + type: number + format: double + description: Multiplication factor used to weigh the return value of the + GAEN in attenuationDuration[1] + example: 0.5d + triggerThreshold: + type: integer + description: Minimum duration of exposure in minutes, before an encounter + is added to the attenuationDuration + example: '15' + org.dpppt.switzerland.backend.sdk.config.ws.model.InfoBox: + type: object + properties: + title: + type: string + description: Title of the infobox + example: Alert + msg: + type: string + description: Message shown to the user + example: Please restart your phone + url: + type: string + description: If given, adds a url to the message + example: https://dp-3t.github.io/ + urlTitle: + type: string + description: Title to be shown for the URL + example: DP3T page + isDismissible: + type: boolean + description: If true, the user can cancel the message + example: 'true' + org.dpppt.switzerland.backend.sdk.config.ws.model.InfoBoxCollection: + type: object + properties: + deInfoBox: + $ref: '#/components/schemas/org.dpppt.switzerland.backend.sdk.config.ws.model.InfoBox' + frInfoBox: + $ref: '#/components/schemas/org.dpppt.switzerland.backend.sdk.config.ws.model.InfoBox' + itInfoBox: + $ref: '#/components/schemas/org.dpppt.switzerland.backend.sdk.config.ws.model.InfoBox' + enInfoBox: + $ref: '#/components/schemas/org.dpppt.switzerland.backend.sdk.config.ws.model.InfoBox' + ptInfoBox: + $ref: '#/components/schemas/org.dpppt.switzerland.backend.sdk.config.ws.model.InfoBox' + esInfoBox: + $ref: '#/components/schemas/org.dpppt.switzerland.backend.sdk.config.ws.model.InfoBox' + sqInfoBox: + $ref: '#/components/schemas/org.dpppt.switzerland.backend.sdk.config.ws.model.InfoBox' + bsInfoBox: + $ref: '#/components/schemas/org.dpppt.switzerland.backend.sdk.config.ws.model.InfoBox' + hrInfoBox: + $ref: '#/components/schemas/org.dpppt.switzerland.backend.sdk.config.ws.model.InfoBox' + srInfoBox: + $ref: '#/components/schemas/org.dpppt.switzerland.backend.sdk.config.ws.model.InfoBox' + rmInfoBox: + $ref: '#/components/schemas/org.dpppt.switzerland.backend.sdk.config.ws.model.InfoBox' + org.dpppt.switzerland.backend.sdk.config.ws.model.SDKConfig: + type: object + properties: + numberOfWindowsForExposure: + type: integer + eventThreshold: + type: number + format: float + badAttenuationThreshold: + type: number + format: float + contactAttenuationThreshold: + type: number + format: float diff --git a/dpppt-config-backend/.gitignore b/dpppt-config-backend/.gitignore new file mode 100644 index 0000000..95b5e53 --- /dev/null +++ b/dpppt-config-backend/.gitignore @@ -0,0 +1,2 @@ +generated +target diff --git a/dpppt-config-backend/pom.xml b/dpppt-config-backend/pom.xml index 0b69414..e8488c0 100644 --- a/dpppt-config-backend/pom.xml +++ b/dpppt-config-backend/pom.xml @@ -29,6 +29,12 @@ + + ch.ubique.openapi + doc-annotations + 1.0.1 + + org.springframework spring-context @@ -170,8 +176,27 @@ true + + + false + + ubique-oss-springboot-swagger3 + bintray + https://dl.bintray.com/ubique-oss/springboot-swagger3 + + + + + false + + ubique-oss-springboot-swagger3 + bintray + https://dl.bintray.com/ubique-oss/springboot-swagger3 + + + dpppt-config-backend @@ -198,6 +223,9 @@ ${java-version} ${java-version} + + -parameters + @@ -260,6 +288,32 @@ + + + ch.ubique.openapi + springboot-swagger-3 + 1.2.8 + + 1.0-gapple + + org.dpppt.switzerland.backend.sdk.config.ws.model + + + com.google.protobuf + + + byte + + + org.dpppt.switzerland.backend.sdk.config.ws.controller.DPPPTConfigController + + DP3T API + + https://demo.dpppt.org + + DP3T API + + diff --git a/dpppt-config-backend/src/main/java/org/dpppt/switzerland/backend/sdk/config/ws/controller/GaenConfigController.java b/dpppt-config-backend/src/main/java/org/dpppt/switzerland/backend/sdk/config/ws/controller/GaenConfigController.java index e65b8c9..d34d90c 100644 --- a/dpppt-config-backend/src/main/java/org/dpppt/switzerland/backend/sdk/config/ws/controller/GaenConfigController.java +++ b/dpppt-config-backend/src/main/java/org/dpppt/switzerland/backend/sdk/config/ws/controller/GaenConfigController.java @@ -29,6 +29,61 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; +import ch.ubique.openapi.docannotations.Documentation; + +/** + + @CrossOrigin(origins = { "https://editor.swagger.io" }) + @GetMapping(value = "") + public @ResponseBody String hello() { + return "Hello from DP3T Config WS"; + } + + @CrossOrigin(origins = { "https://editor.swagger.io" }) + @GetMapping(value = "/config") + public @ResponseBody ResponseEntity getConfig( + @RequestParam + String osversion, + @RequestParam + String appversion, + @RequestParam + String buildnr) { + ConfigResponse config = new ConfigResponse(); + // For iOS 13.6 users with language DE show information about weekly + // notification + if (osversion.equals(IOS_VERSION_DE_WEEKLY_NOTIFCATION_INFO)) { + setInfoTextForiOS136DE(config); + } + + // if we have testflight builds suggest to switch to store version + if (TESTFLIGHT_VERSIONS.contains(buildnr)) { + config = testFlightUpdate(); + } + + // Build nr of the initial iOS pilot test app. Contains bug, that factors are + // not used correctly in contact calculations. Set factorHigh to 0.0 for + // improving the calculation. + if (buildnr.equals("ios-200524.1316.87")) { + config.getiOSGaenSdkConfig().setFactorHigh(0.0d); + } + return ResponseEntity.ok().cacheControl(CacheControl.maxAge(Duration.ofMinutes(5))).body(config); + } + + @Documentation(description = "Infobox testing endpoint", responses = {"200 => Infobox in all languages"}) + @CrossOrigin(origins = { "https://editor.swagger.io" }) + @GetMapping(value = "/testinfobox/config") + public @ResponseBody ResponseEntity getGhettoboxConfig( + @RequestParam + String osversion, + @RequestParam + String appversion, + @RequestParam + String buildnr) { + ConfigResponse body = mockConfigResponseWithInfoBox(); + return ResponseEntity.ok(body); + } + + */ @Controller @RequestMapping("/v1") @@ -53,6 +108,8 @@ public GaenConfigController(Messages messages) { this.messages = messages; } + @Documentation(description = "Echo endpoint", + responses = {"200 => Hello from DP3T Config WS"}) @CrossOrigin(origins = {"https://editor.swagger.io"}) @GetMapping(value = "") public @ResponseBody @@ -60,11 +117,19 @@ String hello() { return "Hello from DP3T Config WS"; } + @Documentation(description="Read latest configuration and messages, depending on the version of the phone and the" + + " app.", + responses = {"200 => ConfigResponse structure with eventual notifications and epidemic parameters"}) @CrossOrigin(origins = {"https://editor.swagger.io"}) @GetMapping(value = "/config") public @ResponseBody - ResponseEntity getConfig(@RequestParam(required = true) String appversion, - @RequestParam(required = true) String osversion, @RequestParam(required = true) String buildnr) { + ResponseEntity getConfig( + @Documentation(description = "Version of the App installed", example = "ios-1.0.7") + @RequestParam String appversion, + @Documentation(description = "Version of the OS", example = "ios13.6") + @RequestParam String osversion, + @Documentation(description = "Build number of the app", example = "ios-200619.2333.175") + @RequestParam String buildnr) { ConfigResponse config = new ConfigResponse(); config.setWhatToDoPositiveTestTexts(whatToDoPositiveTestTexts(messages)); @@ -117,8 +182,12 @@ ResponseEntity getConfig(@RequestParam(required = true) String a @GetMapping(value = "/testinfobox/config") public @ResponseBody ResponseEntity getGhettoboxConfig( - @RequestParam(required = true) String appversion, @RequestParam(required = true) String osversion, - @RequestParam(required = true) String buildnr) { + @Documentation(description = "Version of the App installed", example = "ios-1.0.7") + @RequestParam String appversion, + @Documentation(description = "Version of the OS", example = "ios13.6") + @RequestParam String osversion, + @Documentation(description = "Build number of the app", example = "ios-200619.2333.175") + @RequestParam String buildnr) { ConfigResponse body = mockConfigResponseWithInfoBox(); return ResponseEntity.ok(body); } diff --git a/dpppt-config-backend/src/main/java/org/dpppt/switzerland/backend/sdk/config/ws/model/ConfigResponse.java b/dpppt-config-backend/src/main/java/org/dpppt/switzerland/backend/sdk/config/ws/model/ConfigResponse.java index a5879f0..2213175 100644 --- a/dpppt-config-backend/src/main/java/org/dpppt/switzerland/backend/sdk/config/ws/model/ConfigResponse.java +++ b/dpppt-config-backend/src/main/java/org/dpppt/switzerland/backend/sdk/config/ws/model/ConfigResponse.java @@ -11,16 +11,24 @@ package org.dpppt.switzerland.backend.sdk.config.ws.model; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import ch.ubique.openapi.docannotations.Documentation; @JsonIgnoreProperties(ignoreUnknown = true) + +@Documentation(description = "ConfigResponse description") public class ConfigResponse { + @Documentation(description = "Blocks the app and shows a link to the app-store. The user can only continue once " + + "she updated the app") private boolean forceUpdate = false; + @Documentation(description = "Holds a message translated in different languages") private InfoBoxCollection infoBox = null; private WhatToDoPositiveTestTextsCollection whatToDoPositiveTestTexts; + @Documentation(description = "GAEN epidemiological parameters for iOS") private GAENSDKConfig iOSGaenSdkConfig = new GAENSDKConfig(); + @Documentation(description = "GAEN epidemiological parameters for Android") private GAENSDKConfig androidGaenSdkConfig = new GAENSDKConfig(); public boolean isForceUpdate() { diff --git a/dpppt-config-backend/src/main/java/org/dpppt/switzerland/backend/sdk/config/ws/model/GAENSDKConfig.java b/dpppt-config-backend/src/main/java/org/dpppt/switzerland/backend/sdk/config/ws/model/GAENSDKConfig.java index 6af8c2d..711d607 100644 --- a/dpppt-config-backend/src/main/java/org/dpppt/switzerland/backend/sdk/config/ws/model/GAENSDKConfig.java +++ b/dpppt-config-backend/src/main/java/org/dpppt/switzerland/backend/sdk/config/ws/model/GAENSDKConfig.java @@ -10,12 +10,29 @@ package org.dpppt.switzerland.backend.sdk.config.ws.model; +import ch.ubique.openapi.docannotations.Documentation; + public class GAENSDKConfig { + @Documentation(description = "Lower threshold that is sent to the GAEN to count encounters with other devices. It" + + " is expressed in dB attenuation from the Bluetooth chip.", + example="53") private Integer lowerThreshold = 55; + @Documentation(description = "Higher threshold that is sent to the GAEN to count encounters with other devices " + + ".It is expressed in dB attenuation from the Bluetooth chip.", + example="60") private Integer higherThreshold = 63; + @Documentation(description = "Multiplication factor used to weigh the return value of the GAEN in " + + "attenuationDuration[0]", + example = "1.0d") private Double factorLow = 1.0d; + @Documentation(description = "Multiplication factor used to weigh the return value of the GAEN in " + + "attenuationDuration[1]", + example = "0.5d") private Double factorHigh = 0.5d; + @Documentation(description = "Minimum duration of exposure during one day reported by the GAEN before the user " + + "is alerted of an exposure risk", + example = "15") private Integer triggerThreshold = 15; public Integer getLowerThreshold() { diff --git a/dpppt-config-backend/src/main/java/org/dpppt/switzerland/backend/sdk/config/ws/model/InfoBox.java b/dpppt-config-backend/src/main/java/org/dpppt/switzerland/backend/sdk/config/ws/model/InfoBox.java index 9ddf65f..982150f 100644 --- a/dpppt-config-backend/src/main/java/org/dpppt/switzerland/backend/sdk/config/ws/model/InfoBox.java +++ b/dpppt-config-backend/src/main/java/org/dpppt/switzerland/backend/sdk/config/ws/model/InfoBox.java @@ -10,6 +10,7 @@ package org.dpppt.switzerland.backend.sdk.config.ws.model; +import ch.ubique.openapi.docannotations.Documentation; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; /** @@ -18,10 +19,15 @@ @JsonIgnoreProperties(ignoreUnknown = true) public class InfoBox { + @Documentation(description = "Title of the infobox", example = "Alert") private String title; + @Documentation(description = "Message shown to the user", example = "Please restart your phone") private String msg; + @Documentation(description = "If given, adds a url to the message", example = "https://dp-3t.github.io/") private String url; + @Documentation(description = "Title to be shown for the URL", example = "DP3T page") private String urlTitle; + @Documentation(description = "If true, the user can dismiss the message", example = "true") private boolean isDismissible = false; public String getInfoId() { diff --git a/dpppt-config-backend/src/main/java/org/dpppt/switzerland/backend/sdk/config/ws/model/InfoBoxCollection.java b/dpppt-config-backend/src/main/java/org/dpppt/switzerland/backend/sdk/config/ws/model/InfoBoxCollection.java index 13b4f15..753b1e6 100644 --- a/dpppt-config-backend/src/main/java/org/dpppt/switzerland/backend/sdk/config/ws/model/InfoBoxCollection.java +++ b/dpppt-config-backend/src/main/java/org/dpppt/switzerland/backend/sdk/config/ws/model/InfoBoxCollection.java @@ -10,6 +10,7 @@ package org.dpppt.switzerland.backend.sdk.config.ws.model; +import ch.ubique.openapi.docannotations.Documentation; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude.Include;