diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1bc3496..da54c13 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -10,3 +10,5 @@ on: jobs: build: uses: axonivy-market/github-workflows/.github/workflows/ci.yml@v2 + with: + mvnArgs: -Dmaven.test.failure.ignore=true -Divy.engine.version=10.0.13 diff --git a/.gitignore b/.gitignore index c6cc0de..a0ceba0 100644 --- a/.gitignore +++ b/.gitignore @@ -16,3 +16,12 @@ lib/mvn-deps/ logs/ src_dataClasses/ src_wsproc/ + +# local config +**/resources/ +threema-connector/config/variables.yaml +threema-connector/config/variables.yaml_template +threema-connector/config/variables.yaml_complete + +# threema SKD +threema-connector/lib/threema-msgapi-tool.* diff --git a/.project b/.project new file mode 100644 index 0000000..cba7369 --- /dev/null +++ b/.project @@ -0,0 +1,17 @@ + + + threema-connector-modules + + + + + + org.eclipse.m2e.core.maven2Builder + + + + + + org.eclipse.m2e.core.maven2Nature + + diff --git a/.settings/org.eclipse.m2e.core.prefs b/.settings/org.eclipse.m2e.core.prefs new file mode 100644 index 0000000..f897a7f --- /dev/null +++ b/.settings/org.eclipse.m2e.core.prefs @@ -0,0 +1,4 @@ +activeProfiles= +eclipse.preferences.version=1 +resolveWorkspaceProjects=true +version=1 diff --git a/MY-PRODUCT-NAME-product/README.md b/MY-PRODUCT-NAME-product/README.md deleted file mode 100644 index ee9062a..0000000 --- a/MY-PRODUCT-NAME-product/README.md +++ /dev/null @@ -1,15 +0,0 @@ -# MY-PRODUCT-NAME - -YOUR DESCRIPTION GOES HERE - -## Demo - -YOUR DEMO DESCRIPTION GOES HERE - -## Setup - -YOUR SETUP DESCRIPTION GOES HERE - -``` -@variables.yaml@ -``` \ No newline at end of file diff --git a/README.md b/README.md index 0f94020..6d8f9d8 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ -# MY-PRODUCT-NAME +# Threema Connector -[![CI Build](https://github.com/axonivy-market/REPO-NAME/actions/workflows/ci.yml/badge.svg)](https://github.com/axonivy-market/REPO-NAME/actions/workflows/ci.yml) +[![CI Build](https://github.com/axonivy-market/threema-connector/actions/workflows/ci.yml/badge.svg)](https://github.com/axonivy-market/threema-connector/actions/workflows/ci.yml) -"YOUR SHORT DESCRIPTION GOES HERE" +Use the [Threema.Gateway API](https://threema.ch/en/gateway) to send messages to one or more recipients, enabling new notification options for your business processes. -Read our [documentation](MY-PRODUCT-NAME-product/README.md). +Read our [documentation](threema-connector-product/README.md). diff --git a/pom.xml b/pom.xml index 517336b..b19878c 100644 --- a/pom.xml +++ b/pom.xml @@ -1,9 +1,13 @@ - + 4.0.0 - com.axonivy.market - my-product - my-product-modules - 10.0.0-SNAPSHOT + com.axonivy.connector.threema + threema-connector + threema-connector-modules + 10.0.0-SNAPSHOT pom @@ -11,6 +15,7 @@ ${project.name}-demo ${project.name}-test ${project.name}-product + ${project.name}-webtest diff --git a/threema-connector-demo/.classpath b/threema-connector-demo/.classpath new file mode 100644 index 0000000..157b754 --- /dev/null +++ b/threema-connector-demo/.classpath @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/threema-connector-demo/.gitignore b/threema-connector-demo/.gitignore new file mode 100644 index 0000000..1b2547b --- /dev/null +++ b/threema-connector-demo/.gitignore @@ -0,0 +1,19 @@ +# general +Thumbs.db +.DS_Store +*~ +*.log + +# java +*.class +hs_err_pid* + +# maven +target/ +lib/mvn-deps/ + +# ivy +classes/ +src_dataClasses/ +src_wsproc/ +logs/ diff --git a/threema-connector-demo/.project b/threema-connector-demo/.project new file mode 100644 index 0000000..7289f72 --- /dev/null +++ b/threema-connector-demo/.project @@ -0,0 +1,49 @@ + + + threema-connector-demo + + + + + + ch.ivyteam.ivy.designer.dataClasses.ui.ivyDataClassBuilder + + + + + ch.ivyteam.ivy.designer.process.ui.ivyWebServiceProcessClassBuilder + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.wst.common.project.facet.core.builder + + + + + ch.ivyteam.ivy.designer.ide.ivyModelValidationBuilder + + + + + org.eclipse.m2e.core.maven2Builder + + + + + + ch.ivyteam.ivy.project.IvyProjectNature + org.eclipse.wst.common.modulecore.ModuleCoreNature + org.eclipse.jem.workbench.JavaEMFNature + org.eclipse.jdt.core.javanature + org.eclipse.m2e.core.maven2Nature + org.eclipse.jem.beaninfo.BeanInfoNature + org.eclipse.wst.common.project.facet.core.nature + org.eclipse.wst.jsdt.core.jsNature + + diff --git a/threema-connector-demo/.settings/.jsdtscope b/threema-connector-demo/.settings/.jsdtscope new file mode 100644 index 0000000..e4ab59a --- /dev/null +++ b/threema-connector-demo/.settings/.jsdtscope @@ -0,0 +1,17 @@ + + + + + + + + + + + + diff --git a/threema-connector-demo/.settings/ch.ivyteam.ivy.designer.prefs b/threema-connector-demo/.settings/ch.ivyteam.ivy.designer.prefs new file mode 100644 index 0000000..471c536 --- /dev/null +++ b/threema-connector-demo/.settings/ch.ivyteam.ivy.designer.prefs @@ -0,0 +1,5 @@ +ch.ivyteam.ivy.designer.preferences.DataClassPreferencePage\:DEFAULT_DATA_CLASS=threema.connector.demo.Data +ch.ivyteam.ivy.designer.preferences.DataClassPreferencePage\:DEFAULT_NAMESPACE=threema.connector.demo +ch.ivyteam.ivy.project.preferences\:PRIMEFACES_VERSION=11 +ch.ivyteam.ivy.project.preferences\:PROJECT_VERSION=100000 +eclipse.preferences.version=1 diff --git a/threema-connector-demo/.settings/org.eclipse.jdt.core.prefs b/threema-connector-demo/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..d4540a5 --- /dev/null +++ b/threema-connector-demo/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,10 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=17 +org.eclipse.jdt.core.compiler.compliance=17 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning +org.eclipse.jdt.core.compiler.release=enabled +org.eclipse.jdt.core.compiler.source=17 diff --git a/threema-connector-demo/.settings/org.eclipse.wst.common.component b/threema-connector-demo/.settings/org.eclipse.wst.common.component new file mode 100644 index 0000000..db6eed0 --- /dev/null +++ b/threema-connector-demo/.settings/org.eclipse.wst.common.component @@ -0,0 +1,18 @@ + + + + + + + + + + + diff --git a/threema-connector-demo/.settings/org.eclipse.wst.common.project.facet.core.prefs.xml b/threema-connector-demo/.settings/org.eclipse.wst.common.project.facet.core.prefs.xml new file mode 100644 index 0000000..e725c8d --- /dev/null +++ b/threema-connector-demo/.settings/org.eclipse.wst.common.project.facet.core.prefs.xml @@ -0,0 +1,8 @@ + + + + + + + diff --git a/threema-connector-demo/.settings/org.eclipse.wst.common.project.facet.core.xml b/threema-connector-demo/.settings/org.eclipse.wst.common.project.facet.core.xml new file mode 100644 index 0000000..3bb273d --- /dev/null +++ b/threema-connector-demo/.settings/org.eclipse.wst.common.project.facet.core.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/threema-connector-demo/.settings/org.eclipse.wst.css.core.prefs b/threema-connector-demo/.settings/org.eclipse.wst.css.core.prefs new file mode 100644 index 0000000..5ddc6bd --- /dev/null +++ b/threema-connector-demo/.settings/org.eclipse.wst.css.core.prefs @@ -0,0 +1,2 @@ +css-profile/=org.eclipse.wst.css.core.cssprofile.css3 +eclipse.preferences.version=1 diff --git a/threema-connector-demo/.settings/org.eclipse.wst.jsdt.ui.superType.container b/threema-connector-demo/.settings/org.eclipse.wst.jsdt.ui.superType.container new file mode 100644 index 0000000..3bd5d0a --- /dev/null +++ b/threema-connector-demo/.settings/org.eclipse.wst.jsdt.ui.superType.container @@ -0,0 +1 @@ +org.eclipse.wst.jsdt.launching.baseBrowserLibrary \ No newline at end of file diff --git a/threema-connector-demo/.settings/org.eclipse.wst.jsdt.ui.superType.name b/threema-connector-demo/.settings/org.eclipse.wst.jsdt.ui.superType.name new file mode 100644 index 0000000..05bd71b --- /dev/null +++ b/threema-connector-demo/.settings/org.eclipse.wst.jsdt.ui.superType.name @@ -0,0 +1 @@ +Window \ No newline at end of file diff --git a/threema-connector-demo/config/custom-fields.yaml b/threema-connector-demo/config/custom-fields.yaml new file mode 100644 index 0000000..bb20b70 --- /dev/null +++ b/threema-connector-demo/config/custom-fields.yaml @@ -0,0 +1,22 @@ +# yaml-language-server: $schema=https://json-schema.axonivy.com/app/0.0.1/custom-fields.json +# +# == Custom Fields Information == +# +# You can define here your project custom fields. +# Have a look at our documentation for more information. +# +CustomFields: +# Tasks: +# MyTaskCustomField: +# Label: My task custom field +# Description: This new task custom field can be used to ... +# Type: STRING +# Cases: +# MyCaseCustomField: +# Label: My case custom field +# Description: This new case custom field can be used to ... +# Type: STRING +# Starts: +# MyStartCustomField: +# Label: My start custom field +# Description: This new start custom field can be used to ... diff --git a/threema-connector-demo/config/databases.yaml b/threema-connector-demo/config/databases.yaml new file mode 100644 index 0000000..10319e2 --- /dev/null +++ b/threema-connector-demo/config/databases.yaml @@ -0,0 +1,2 @@ +# yaml-language-server: $schema=https://json-schema.axonivy.com/app/0.0.1/databases.json +Databases: diff --git a/threema-connector-demo/config/overrides.any b/threema-connector-demo/config/overrides.any new file mode 100644 index 0000000..f59ec20 --- /dev/null +++ b/threema-connector-demo/config/overrides.any @@ -0,0 +1 @@ +* \ No newline at end of file diff --git a/threema-connector-demo/config/persistence.xml b/threema-connector-demo/config/persistence.xml new file mode 100644 index 0000000..3de1768 --- /dev/null +++ b/threema-connector-demo/config/persistence.xml @@ -0,0 +1,4 @@ + + diff --git a/threema-connector-demo/config/rest-clients.yaml b/threema-connector-demo/config/rest-clients.yaml new file mode 100644 index 0000000..4bffaca --- /dev/null +++ b/threema-connector-demo/config/rest-clients.yaml @@ -0,0 +1,2 @@ +# yaml-language-server: $schema=https://json-schema.axonivy.com/app/0.0.1/rest-clients.json +RestClients: diff --git a/threema-connector-demo/config/roles.xml b/threema-connector-demo/config/roles.xml new file mode 100644 index 0000000..c7c6911 --- /dev/null +++ b/threema-connector-demo/config/roles.xml @@ -0,0 +1,4 @@ + + + Everybody + diff --git a/threema-connector-demo/config/users.xml b/threema-connector-demo/config/users.xml new file mode 100644 index 0000000..1e173fa --- /dev/null +++ b/threema-connector-demo/config/users.xml @@ -0,0 +1,2 @@ + + diff --git a/threema-connector-demo/config/variables.yaml b/threema-connector-demo/config/variables.yaml new file mode 100644 index 0000000..d0f17d7 --- /dev/null +++ b/threema-connector-demo/config/variables.yaml @@ -0,0 +1,4 @@ +Variables: + + + \ No newline at end of file diff --git a/threema-connector-demo/config/webservice-clients.yaml b/threema-connector-demo/config/webservice-clients.yaml new file mode 100644 index 0000000..688047a --- /dev/null +++ b/threema-connector-demo/config/webservice-clients.yaml @@ -0,0 +1,2 @@ +# yaml-language-server: $schema=https://json-schema.axonivy.com/app/0.0.1/webservice-clients.json +WebServiceClients: diff --git a/threema-connector-demo/dataclasses/threema/connector/demo/Data.ivyClass b/threema-connector-demo/dataclasses/threema/connector/demo/Data.ivyClass new file mode 100644 index 0000000..69ce4a5 --- /dev/null +++ b/threema-connector-demo/dataclasses/threema/connector/demo/Data.ivyClass @@ -0,0 +1,2 @@ +Data #class +threema.connector.demo #namespace diff --git a/threema-connector-demo/dataclasses/threema/connector/demo/Status.ivyClass b/threema-connector-demo/dataclasses/threema/connector/demo/Status.ivyClass new file mode 100644 index 0000000..ea4d952 --- /dev/null +++ b/threema-connector-demo/dataclasses/threema/connector/demo/Status.ivyClass @@ -0,0 +1,6 @@ +Status #class +threema.connector.demo #namespace +recipient String #field +recipient PERSISTENT #fieldModifier +status String #field +status PERSISTENT #fieldModifier diff --git a/threema-connector-demo/dataclasses/threema/connector/demo/sendDemoMessageData.ivyClass b/threema-connector-demo/dataclasses/threema/connector/demo/sendDemoMessageData.ivyClass new file mode 100644 index 0000000..54168df --- /dev/null +++ b/threema-connector-demo/dataclasses/threema/connector/demo/sendDemoMessageData.ivyClass @@ -0,0 +1,10 @@ +sendDemoMessageData #class +threema.connector.demo #namespace +receiver String #field +receiver PERSISTENT #fieldModifier +plainMessage String #field +plainMessage PERSISTENT #fieldModifier +type String #field +type PERSISTENT #fieldModifier +apiResponse List #field +apiResponse PERSISTENT #fieldModifier diff --git a/threema-connector-demo/pom.xml b/threema-connector-demo/pom.xml new file mode 100644 index 0000000..216711e --- /dev/null +++ b/threema-connector-demo/pom.xml @@ -0,0 +1,29 @@ + + + 4.0.0 + com.axonivy.connector.threema + threema-connector-demo + 10.0.0-SNAPSHOT + iar + + + com.axonivy.connector.threema + threema-connector + ${project.version} + iar + + + + + + com.axonivy.ivy.ci + project-build-plugin + 10.0.6 + true + + + + diff --git a/threema-connector-demo/processes/MessageMultipleRecipients.p.json b/threema-connector-demo/processes/MessageMultipleRecipients.p.json new file mode 100644 index 0000000..86b8832 --- /dev/null +++ b/threema-connector-demo/processes/MessageMultipleRecipients.p.json @@ -0,0 +1,106 @@ +{ + "format" : "10.0.0", + "id" : "18B1ED116183D822", + "config" : { + "data" : "threema.connector.demo.sendDemoMessageData" + }, + "elements" : [ { + "id" : "f0", + "type" : "RequestStart", + "name" : "start.ivp", + "config" : { + "callSignature" : "start", + "outLink" : "start.ivp", + "tags" : "demo" + }, + "visual" : { + "at" : { "x" : 112, "y" : 64 } + }, + "connect" : { "id" : "f3", "to" : "f2" } + }, { + "id" : "f1", + "type" : "TaskEnd", + "visual" : { + "at" : { "x" : 704, "y" : 64 } + } + }, { + "id" : "f2", + "type" : "DialogCall", + "name" : "multipleRecipients", + "config" : { + "dialogId" : "threema.connector.demo.multipleRecipients", + "startMethod" : "start(threema.connector.demo.sendDemoMessageData)", + "output" : { + "map" : { + "out" : [ + "in", + "result.sendDemoMessageData", + "result.sendDemoMessageData" + ] + } + }, + "call" : { + "params" : [ + { "name" : "sendDemoMessageData", "type" : "threema.connector.demo.sendDemoMessageData" } + ], + "map" : { + "param.sendDemoMessageData" : [ + "in", + "in" + ] + } + } + }, + "visual" : { + "at" : { "x" : 240, "y" : 64 } + }, + "connect" : { "id" : "f5", "to" : "f4" } + }, { + "id" : "f4", + "type" : "SubProcessCall", + "name" : "handleMessage", + "config" : { + "processCall" : "multipleRecipients:call(String,List)", + "output" : { + "map" : { + "out" : "in", + "out.apiResponse" : "result.apiResponse" + } + }, + "call" : { + "params" : [ + { "name" : "plainMsg", "type" : "String" }, + { "name" : "receivers", "type" : "List" } + ], + "map" : { + "param.plainMsg" : "in.plainMessage", + "param.receivers" : "in.receiver.split(\"\\n\")" + } + } + }, + "visual" : { + "at" : { "x" : 408, "y" : 64 } + }, + "connect" : { "id" : "f7", "to" : "f6" } + }, { + "id" : "f6", + "type" : "DialogCall", + "name" : "ResultPage", + "config" : { + "dialogId" : "threema.connector.demo.ResultPage", + "startMethod" : "start(threema.connector.demo.sendDemoMessageData)", + "call" : { + "params" : [ + { "name" : "sendDemoMessageData", "type" : "threema.connector.demo.sendDemoMessageData" } + ], + "map" : { + "param.sendDemoMessageData" : "in" + } + } + }, + "visual" : { + "at" : { "x" : 576, "y" : 64 } + }, + "connect" : { "id" : "f8", "to" : "f1" } + } ] +} \ No newline at end of file diff --git a/threema-connector-demo/processes/MessageSingleRecipient.p.json b/threema-connector-demo/processes/MessageSingleRecipient.p.json new file mode 100644 index 0000000..c0bbc6b --- /dev/null +++ b/threema-connector-demo/processes/MessageSingleRecipient.p.json @@ -0,0 +1,113 @@ +{ + "format" : "10.0.0", + "id" : "18B22F69680901D3", + "config" : { + "data" : "threema.connector.demo.sendDemoMessageData" + }, + "elements" : [ { + "id" : "f0", + "type" : "RequestStart", + "name" : "start.ivp", + "config" : { + "callSignature" : "start", + "outLink" : "start.ivp", + "tags" : "demo" + }, + "visual" : { + "at" : { "x" : 96, "y" : 64 } + }, + "connect" : { "id" : "f3", "to" : "f2" } + }, { + "id" : "f1", + "type" : "TaskEnd", + "visual" : { + "at" : { "x" : 768, "y" : 64 } + } + }, { + "id" : "f2", + "type" : "DialogCall", + "name" : "singleRecipient", + "config" : { + "dialogId" : "threema.connector.demo.singleRecipient", + "startMethod" : "start(threema.connector.demo.sendDemoMessageData)", + "output" : { + "map" : { + "out" : [ + "in", + "result.sendDemoMessageData" + ] + } + }, + "call" : { + "params" : [ + { "name" : "sendDemoMessageData", "type" : "threema.connector.demo.sendDemoMessageData" } + ], + "map" : { + "param.sendDemoMessageData" : "in" + } + } + }, + "visual" : { + "at" : { "x" : 272, "y" : 64 } + }, + "connect" : { "id" : "f5", "to" : "f4" } + }, { + "id" : "f4", + "type" : "SubProcessCall", + "name" : "singleMessage", + "config" : { + "processCall" : "singleRecipient:call(String,String,util.LookupType)", + "output" : { + "map" : { + "out" : "in", + "out.plainMessage" : "in.plainMessage" + }, + "code" : "out.apiResponse.add(result.apiResponse);" + }, + "call" : { + "params" : [ + { "name" : "plainMsg", "type" : "String" }, + { "name" : "receiverID", "type" : "String" }, + { "name" : "lookupType", "type" : "util.LookupType" } + ], + "map" : { + "param.plainMsg" : "in.plainMessage", + "param.receiverID" : "in.receiver", + "param.lookupType" : "util.LookupType.getByString(in.type)" + } + } + }, + "visual" : { + "at" : { "x" : 464, "y" : 64 } + }, + "connect" : { "id" : "f7", "to" : "f6" } + }, { + "id" : "f6", + "type" : "DialogCall", + "name" : "ResultPage", + "config" : { + "dialogId" : "threema.connector.demo.ResultPage", + "startMethod" : "start(threema.connector.demo.sendDemoMessageData)", + "output" : { + "map" : { + "out" : [ + "in", + "result.sendDemoMessageData" + ] + } + }, + "call" : { + "params" : [ + { "name" : "sendDemoMessageData", "type" : "threema.connector.demo.sendDemoMessageData" } + ], + "map" : { + "param.sendDemoMessageData" : "in" + } + } + }, + "visual" : { + "at" : { "x" : 640, "y" : 64 } + }, + "connect" : { "id" : "f8", "to" : "f1" } + } ] +} \ No newline at end of file diff --git a/threema-connector-demo/src_hd/threema/connector/demo/ResultPage/ResultPage.rddescriptor b/threema-connector-demo/src_hd/threema/connector/demo/ResultPage/ResultPage.rddescriptor new file mode 100644 index 0000000..ae605f0 --- /dev/null +++ b/threema-connector-demo/src_hd/threema/connector/demo/ResultPage/ResultPage.rddescriptor @@ -0,0 +1,7 @@ + + + + viewTechnology + JSF + + diff --git a/threema-connector-demo/src_hd/threema/connector/demo/ResultPage/ResultPage.xhtml b/threema-connector-demo/src_hd/threema/connector/demo/ResultPage/ResultPage.xhtml new file mode 100644 index 0000000..1b6ebe4 --- /dev/null +++ b/threema-connector-demo/src_hd/threema/connector/demo/ResultPage/ResultPage.xhtml @@ -0,0 +1,54 @@ + + + + ResultPage + + +

Message Status

+ + + + + + + + + + + + + + + + + + + + + +
+
+ + +
+
+ +
+
+
+ + \ No newline at end of file diff --git a/threema-connector-demo/src_hd/threema/connector/demo/ResultPage/ResultPageData.ivyClass b/threema-connector-demo/src_hd/threema/connector/demo/ResultPage/ResultPageData.ivyClass new file mode 100644 index 0000000..26676ce --- /dev/null +++ b/threema-connector-demo/src_hd/threema/connector/demo/ResultPage/ResultPageData.ivyClass @@ -0,0 +1,6 @@ +ResultPageData #class +threema.connector.demo.ResultPage #namespace +sendDemoMessageData threema.connector.demo.sendDemoMessageData #field +sendDemoMessageData PERSISTENT #fieldModifier +statusData List #field +statusData PERSISTENT #fieldModifier diff --git a/threema-connector-demo/src_hd/threema/connector/demo/ResultPage/ResultPageProcess.p.json b/threema-connector-demo/src_hd/threema/connector/demo/ResultPage/ResultPageProcess.p.json new file mode 100644 index 0000000..7f85581 --- /dev/null +++ b/threema-connector-demo/src_hd/threema/connector/demo/ResultPage/ResultPageProcess.p.json @@ -0,0 +1,84 @@ +{ + "format" : "10.0.0", + "id" : "18B23815CA49935E", + "kind" : "HTML_DIALOG", + "config" : { + "data" : "threema.connector.demo.ResultPage.ResultPageData" + }, + "elements" : [ { + "id" : "f0", + "type" : "HtmlDialogStart", + "name" : "start(sendDemoMessageData)", + "config" : { + "callSignature" : "start", + "result" : { + "params" : [ + { "name" : "sendDemoMessageData", "type" : "threema.connector.demo.sendDemoMessageData" } + ], + "map" : { + "result.sendDemoMessageData" : "in.sendDemoMessageData" + } + }, + "input" : { + "params" : [ + { "name" : "sendDemoMessageData", "type" : "threema.connector.demo.sendDemoMessageData" } + ], + "map" : { + "out.sendDemoMessageData" : "param.sendDemoMessageData" + } + }, + "guid" : "18B23815CA5CE936" + }, + "visual" : { + "at" : { "x" : 96, "y" : 64 } + }, + "connect" : { "id" : "f6", "to" : "f2" } + }, { + "id" : "f1", + "type" : "HtmlDialogEnd", + "visual" : { + "at" : { "x" : 312, "y" : 64 } + } + }, { + "id" : "f3", + "type" : "HtmlDialogEventStart", + "name" : "close", + "config" : { + "guid" : "18B23815CA6B079E" + }, + "visual" : { + "at" : { "x" : 96, "y" : 160 } + }, + "connect" : { "id" : "f5", "to" : "f4" } + }, { + "id" : "f4", + "type" : "HtmlDialogExit", + "visual" : { + "at" : { "x" : 312, "y" : 160 } + } + }, { + "id" : "f2", + "type" : "Script", + "name" : "loadData", + "config" : { + "output" : { + "code" : [ + "import threema.connector.demo.Status;", + "", + "List recipients = in.sendDemoMessageData.receiver.split(\"\\n\");", + "", + "for(int i = 0; i < recipients.size(); i++){", + " Status s = new Status();", + " s.recipient = recipients.get(i);", + " s.status = in.sendDemoMessageData.apiResponse.get(i);", + " out.statusData.add(s);", + "}" + ] + } + }, + "visual" : { + "at" : { "x" : 208, "y" : 64 } + }, + "connect" : { "id" : "f7", "to" : "f1" } + } ] +} \ No newline at end of file diff --git a/threema-connector-demo/src_hd/threema/connector/demo/multipleRecipients/multipleRecipients.rddescriptor b/threema-connector-demo/src_hd/threema/connector/demo/multipleRecipients/multipleRecipients.rddescriptor new file mode 100644 index 0000000..ae605f0 --- /dev/null +++ b/threema-connector-demo/src_hd/threema/connector/demo/multipleRecipients/multipleRecipients.rddescriptor @@ -0,0 +1,7 @@ + + + + viewTechnology + JSF + + diff --git a/threema-connector-demo/src_hd/threema/connector/demo/multipleRecipients/multipleRecipients.xhtml b/threema-connector-demo/src_hd/threema/connector/demo/multipleRecipients/multipleRecipients.xhtml new file mode 100644 index 0000000..e387c3d --- /dev/null +++ b/threema-connector-demo/src_hd/threema/connector/demo/multipleRecipients/multipleRecipients.xhtml @@ -0,0 +1,49 @@ + + + + multipleRecipients + + +

Send Message to multiple recipients via Threema

+ + + + + + + + + + + + + + +
+
+ + +
+
+ +
+
+
+ + \ No newline at end of file diff --git a/threema-connector-demo/src_hd/threema/connector/demo/multipleRecipients/multipleRecipientsData.ivyClass b/threema-connector-demo/src_hd/threema/connector/demo/multipleRecipients/multipleRecipientsData.ivyClass new file mode 100644 index 0000000..ab92c58 --- /dev/null +++ b/threema-connector-demo/src_hd/threema/connector/demo/multipleRecipients/multipleRecipientsData.ivyClass @@ -0,0 +1,4 @@ +multipleRecipientsData #class +threema.connector.demo.multipleRecipients #namespace +sendDemoMessageData threema.connector.demo.sendDemoMessageData #field +sendDemoMessageData PERSISTENT #fieldModifier diff --git a/threema-connector-demo/src_hd/threema/connector/demo/multipleRecipients/multipleRecipientsProcess.p.json b/threema-connector-demo/src_hd/threema/connector/demo/multipleRecipients/multipleRecipientsProcess.p.json new file mode 100644 index 0000000..246dd30 --- /dev/null +++ b/threema-connector-demo/src_hd/threema/connector/demo/multipleRecipients/multipleRecipientsProcess.p.json @@ -0,0 +1,60 @@ +{ + "format" : "10.0.0", + "id" : "18B23798EF7AA160", + "kind" : "HTML_DIALOG", + "config" : { + "data" : "threema.connector.demo.multipleRecipients.multipleRecipientsData" + }, + "elements" : [ { + "id" : "f0", + "type" : "HtmlDialogStart", + "name" : "start(sendDemoMessageData)", + "config" : { + "callSignature" : "start", + "result" : { + "params" : [ + { "name" : "sendDemoMessageData", "type" : "threema.connector.demo.sendDemoMessageData" } + ], + "map" : { + "result.sendDemoMessageData" : "in.sendDemoMessageData" + } + }, + "input" : { + "params" : [ + { "name" : "sendDemoMessageData", "type" : "threema.connector.demo.sendDemoMessageData" } + ], + "map" : { + "out.sendDemoMessageData" : "param.sendDemoMessageData" + } + }, + "guid" : "18B23798EF997276" + }, + "visual" : { + "at" : { "x" : 96, "y" : 64 } + }, + "connect" : { "id" : "f2", "to" : "f1" } + }, { + "id" : "f1", + "type" : "HtmlDialogEnd", + "visual" : { + "at" : { "x" : 224, "y" : 64 } + } + }, { + "id" : "f3", + "type" : "HtmlDialogEventStart", + "name" : "close", + "config" : { + "guid" : "18B23798EFB1720A" + }, + "visual" : { + "at" : { "x" : 96, "y" : 160 } + }, + "connect" : { "id" : "f5", "to" : "f4" } + }, { + "id" : "f4", + "type" : "HtmlDialogExit", + "visual" : { + "at" : { "x" : 224, "y" : 160 } + } + } ] +} \ No newline at end of file diff --git a/threema-connector-demo/src_hd/threema/connector/demo/singleRecipient/singleRecipient.rddescriptor b/threema-connector-demo/src_hd/threema/connector/demo/singleRecipient/singleRecipient.rddescriptor new file mode 100644 index 0000000..ae605f0 --- /dev/null +++ b/threema-connector-demo/src_hd/threema/connector/demo/singleRecipient/singleRecipient.rddescriptor @@ -0,0 +1,7 @@ + + + + viewTechnology + JSF + + diff --git a/threema-connector-demo/src_hd/threema/connector/demo/singleRecipient/singleRecipient.xhtml b/threema-connector-demo/src_hd/threema/connector/demo/singleRecipient/singleRecipient.xhtml new file mode 100644 index 0000000..83e4804 --- /dev/null +++ b/threema-connector-demo/src_hd/threema/connector/demo/singleRecipient/singleRecipient.xhtml @@ -0,0 +1,59 @@ + + + + singleRecipient + + +

Send Message via Threema

+ + + + + + + + + + + + + + + + + + + + +
+
+ + +
+
+ +
+
+
+ + \ No newline at end of file diff --git a/threema-connector-demo/src_hd/threema/connector/demo/singleRecipient/singleRecipientData.ivyClass b/threema-connector-demo/src_hd/threema/connector/demo/singleRecipient/singleRecipientData.ivyClass new file mode 100644 index 0000000..55cea03 --- /dev/null +++ b/threema-connector-demo/src_hd/threema/connector/demo/singleRecipient/singleRecipientData.ivyClass @@ -0,0 +1,4 @@ +singleRecipientData #class +threema.connector.demo.singleRecipient #namespace +sendDemoMessageData threema.connector.demo.sendDemoMessageData #field +sendDemoMessageData PERSISTENT #fieldModifier diff --git a/threema-connector-demo/src_hd/threema/connector/demo/singleRecipient/singleRecipientProcess.p.json b/threema-connector-demo/src_hd/threema/connector/demo/singleRecipient/singleRecipientProcess.p.json new file mode 100644 index 0000000..02b40b9 --- /dev/null +++ b/threema-connector-demo/src_hd/threema/connector/demo/singleRecipient/singleRecipientProcess.p.json @@ -0,0 +1,60 @@ +{ + "format" : "10.0.0", + "id" : "18B22F7818988EDB", + "kind" : "HTML_DIALOG", + "config" : { + "data" : "threema.connector.demo.singleRecipient.singleRecipientData" + }, + "elements" : [ { + "id" : "f0", + "type" : "HtmlDialogStart", + "name" : "start(sendDemoMessageData)", + "config" : { + "callSignature" : "start", + "result" : { + "params" : [ + { "name" : "sendDemoMessageData", "type" : "threema.connector.demo.sendDemoMessageData" } + ], + "map" : { + "result.sendDemoMessageData" : "in.sendDemoMessageData" + } + }, + "input" : { + "params" : [ + { "name" : "sendDemoMessageData", "type" : "threema.connector.demo.sendDemoMessageData" } + ], + "map" : { + "out.sendDemoMessageData" : "param.sendDemoMessageData" + } + }, + "guid" : "18B22F7818A93A33" + }, + "visual" : { + "at" : { "x" : 96, "y" : 64 } + }, + "connect" : { "id" : "f2", "to" : "f1" } + }, { + "id" : "f1", + "type" : "HtmlDialogEnd", + "visual" : { + "at" : { "x" : 224, "y" : 64 } + } + }, { + "id" : "f3", + "type" : "HtmlDialogEventStart", + "name" : "close", + "config" : { + "guid" : "18B22F7818C5C347" + }, + "visual" : { + "at" : { "x" : 96, "y" : 160 } + }, + "connect" : { "id" : "f5", "to" : "f4" } + }, { + "id" : "f4", + "type" : "HtmlDialogExit", + "visual" : { + "at" : { "x" : 224, "y" : 160 } + } + } ] +} \ No newline at end of file diff --git a/threema-connector-demo/webContent/layouts/frame-10.xhtml b/threema-connector-demo/webContent/layouts/frame-10.xhtml new file mode 100644 index 0000000..e0a3f36 --- /dev/null +++ b/threema-connector-demo/webContent/layouts/frame-10.xhtml @@ -0,0 +1,61 @@ + + + + + + + + + + <ui:insert name="title">Ivy Html Dialog</ui:insert> + + + + + + + + + +
+ + default content + +
+ + + + + + + +
+ \ No newline at end of file diff --git a/threema-connector-demo/webContent/layouts/includes/exception-details.xhtml b/threema-connector-demo/webContent/layouts/includes/exception-details.xhtml new file mode 100644 index 0000000..f04a69b --- /dev/null +++ b/threema-connector-demo/webContent/layouts/includes/exception-details.xhtml @@ -0,0 +1,130 @@ + + + + + + +

+ +

+ + +

Error + id

+

#{errorPage.exceptionId}

+

Error + Timestamp

+

#{errorPage.createdAt}

+
+ + + + +

Attributes

+
+ + + + + + + + + + + + + + + +
NameValue
+
+
+

Thrown by

+

+ Process: + +
Element: + +

+
+ + +

Process call stack

+ +
+      
+        #{caller.callerElement}
+      
+    
+
+
+ +

Technical cause

+ +
+        #{causedBy.class.simpleName}: #{causedBy.message.trim()}
+      
+
+
+
+ +

Request Uri

+

#{errorPage.getRequestUri()}

+
+

Servlet

+

#{errorPage.getServletName()}

+
+ +

Application

+

#{errorPage.applicationName}

+
+ + +

Thread local values

+
+ + + + + + + + + + + + + + + +
KeyValue
+
+
+
+ +

Stack-Trace

+
+    #{errorPage.getStackTrace()}
+  
+
+ diff --git a/threema-connector-demo/webContent/layouts/includes/exception.xhtml b/threema-connector-demo/webContent/layouts/includes/exception.xhtml new file mode 100644 index 0000000..1ed05ae --- /dev/null +++ b/threema-connector-demo/webContent/layouts/includes/exception.xhtml @@ -0,0 +1,47 @@ + + + + + + + + + +
+
+ + +
+ + + + + + + + + +
+ + \ No newline at end of file diff --git a/threema-connector-demo/webContent/layouts/includes/footer.xhtml b/threema-connector-demo/webContent/layouts/includes/footer.xhtml new file mode 100644 index 0000000..912a1cc --- /dev/null +++ b/threema-connector-demo/webContent/layouts/includes/footer.xhtml @@ -0,0 +1,19 @@ + + + +
+ + #{ivyAdvisor.applicationName} + + +
+
+ + \ No newline at end of file diff --git a/threema-connector-demo/webContent/layouts/includes/progress-loader.xhtml b/threema-connector-demo/webContent/layouts/includes/progress-loader.xhtml new file mode 100644 index 0000000..4b9d1ce --- /dev/null +++ b/threema-connector-demo/webContent/layouts/includes/progress-loader.xhtml @@ -0,0 +1,19 @@ + + + + +
+
+
Loading...
+
+
+ + + +
+
\ No newline at end of file diff --git a/threema-connector-product/README.md b/threema-connector-product/README.md new file mode 100644 index 0000000..23f3305 --- /dev/null +++ b/threema-connector-product/README.md @@ -0,0 +1,22 @@ +# Threema Connector +Axon Ivy's Threema Connector enables you to send end-to-end encrypted messages by integrating the [Threema.Gateway API](https://threema.ch/en/gateway) provided by Threema. With this connector you are able to send messages to one or more recipients using email, phone number or ThreemaID as identifier. + +Credentials and credits are required to send messages. The credentials can be created free of charge at [Threema.Gateway](https://gateway.threema.ch/en/signup). Credits can then be bought in accordance with usage. More info can be found at [Threema.Gateway API](https://threema.ch/en/gateway). + +## Demo +![Send to one recipient](./images/singleMessage.png) + +![Send to multiple recipients](./images/multiMessage.png) + +![Result screen](./images/resultScreen.png) + +## Setup +This Connector requires an "End-to-End Threema ID". [Request new ID](https://gateway.threema.ch/en/id-request) +
+For generating the keys and requesting a new Threema.Gateway ID refer to [Generate keys](https://gateway.threema.ch/en/developer/howto/create-keys/php). + +To use the Threema Connector, add the following variables to your Axon Ivy Project: + +``` +@variables.yaml@ +``` diff --git a/threema-connector-product/images/multiMessage.png b/threema-connector-product/images/multiMessage.png new file mode 100644 index 0000000..ad33fb8 Binary files /dev/null and b/threema-connector-product/images/multiMessage.png differ diff --git a/threema-connector-product/images/resultScreen.png b/threema-connector-product/images/resultScreen.png new file mode 100644 index 0000000..7436509 Binary files /dev/null and b/threema-connector-product/images/resultScreen.png differ diff --git a/threema-connector-product/images/singleMessage.png b/threema-connector-product/images/singleMessage.png new file mode 100644 index 0000000..57bed7a Binary files /dev/null and b/threema-connector-product/images/singleMessage.png differ diff --git a/MY-PRODUCT-NAME-product/pom.xml b/threema-connector-product/pom.xml similarity index 66% rename from MY-PRODUCT-NAME-product/pom.xml rename to threema-connector-product/pom.xml index dd59011..0f41ee5 100644 --- a/MY-PRODUCT-NAME-product/pom.xml +++ b/threema-connector-product/pom.xml @@ -1,12 +1,14 @@ - + 4.0.0 - com.axonivy.market - MY-PRODUCT-NAME-product + com.axonivy.connector.threema + threema-connector-product 10.0.0-SNAPSHOT pom - ../MY-PRODUCT-NAME/config/variables.yaml + ../threema-connector/config/variables.yaml @@ -42,9 +44,14 @@ - - - + + + diff --git a/MY-PRODUCT-NAME-product/product.json b/threema-connector-product/product.json similarity index 80% rename from MY-PRODUCT-NAME-product/product.json rename to threema-connector-product/product.json index a5a4b33..13070f6 100644 --- a/MY-PRODUCT-NAME-product/product.json +++ b/threema-connector-product/product.json @@ -6,8 +6,8 @@ "data": { "projects": [ { - "groupId": "MY-GROUP-ID", - "artifactId": "MY-PRODUCT-NAME-demo", + "groupId": "com.axonivy.connector.threema", + "artifactId": "threema-connector-demo", "version": "${version}", "type": "iar" } @@ -28,8 +28,8 @@ "data": { "dependencies": [ { - "groupId": "MY-GROUP-ID", - "artifactId": "MY-PRODUCT-NAME", + "groupId": "com.axonivy.connector.threema", + "artifactId": "threema-connector", "version": "${version}", "type": "iar" } @@ -50,8 +50,8 @@ "data": { "dependencies": [ { - "groupId": "MY-GROUP-ID", - "artifactId": "MY-PRODUCT-NAME", + "groupId": "com.axonivy.connector.threema", + "artifactId": "threema-connector", "version": "${version}" } ], diff --git a/MY-PRODUCT-NAME-product/zip.xml b/threema-connector-product/zip.xml similarity index 65% rename from MY-PRODUCT-NAME-product/zip.xml rename to threema-connector-product/zip.xml index 003f06c..ed24bd5 100644 --- a/MY-PRODUCT-NAME-product/zip.xml +++ b/threema-connector-product/zip.xml @@ -1,4 +1,7 @@ - + zip false diff --git a/threema-connector-test/.classpath b/threema-connector-test/.classpath new file mode 100644 index 0000000..8e30989 --- /dev/null +++ b/threema-connector-test/.classpath @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/threema-connector-test/.gitignore b/threema-connector-test/.gitignore new file mode 100644 index 0000000..1b2547b --- /dev/null +++ b/threema-connector-test/.gitignore @@ -0,0 +1,19 @@ +# general +Thumbs.db +.DS_Store +*~ +*.log + +# java +*.class +hs_err_pid* + +# maven +target/ +lib/mvn-deps/ + +# ivy +classes/ +src_dataClasses/ +src_wsproc/ +logs/ diff --git a/threema-connector-test/.project b/threema-connector-test/.project new file mode 100644 index 0000000..7068587 --- /dev/null +++ b/threema-connector-test/.project @@ -0,0 +1,49 @@ + + + threema-connector-test + + + + + + ch.ivyteam.ivy.designer.dataClasses.ui.ivyDataClassBuilder + + + + + ch.ivyteam.ivy.designer.process.ui.ivyWebServiceProcessClassBuilder + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.wst.common.project.facet.core.builder + + + + + ch.ivyteam.ivy.designer.ide.ivyModelValidationBuilder + + + + + org.eclipse.m2e.core.maven2Builder + + + + + + ch.ivyteam.ivy.project.IvyProjectNature + org.eclipse.wst.common.modulecore.ModuleCoreNature + org.eclipse.jem.workbench.JavaEMFNature + org.eclipse.jdt.core.javanature + org.eclipse.m2e.core.maven2Nature + org.eclipse.jem.beaninfo.BeanInfoNature + org.eclipse.wst.common.project.facet.core.nature + org.eclipse.wst.jsdt.core.jsNature + + diff --git a/threema-connector-test/.settings/.jsdtscope b/threema-connector-test/.settings/.jsdtscope new file mode 100644 index 0000000..e4ab59a --- /dev/null +++ b/threema-connector-test/.settings/.jsdtscope @@ -0,0 +1,17 @@ + + + + + + + + + + + + diff --git a/threema-connector-test/.settings/ch.ivyteam.ivy.designer.prefs b/threema-connector-test/.settings/ch.ivyteam.ivy.designer.prefs new file mode 100644 index 0000000..c370ccd --- /dev/null +++ b/threema-connector-test/.settings/ch.ivyteam.ivy.designer.prefs @@ -0,0 +1,5 @@ +ch.ivyteam.ivy.designer.preferences.DataClassPreferencePage\:DEFAULT_DATA_CLASS=threema.connector.test.Data +ch.ivyteam.ivy.designer.preferences.DataClassPreferencePage\:DEFAULT_NAMESPACE=threema.connector.test +ch.ivyteam.ivy.project.preferences\:PRIMEFACES_VERSION=11 +ch.ivyteam.ivy.project.preferences\:PROJECT_VERSION=100000 +eclipse.preferences.version=1 diff --git a/threema-connector-test/.settings/org.eclipse.jdt.core.prefs b/threema-connector-test/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..d4540a5 --- /dev/null +++ b/threema-connector-test/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,10 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=17 +org.eclipse.jdt.core.compiler.compliance=17 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning +org.eclipse.jdt.core.compiler.release=enabled +org.eclipse.jdt.core.compiler.source=17 diff --git a/threema-connector-test/.settings/org.eclipse.wst.common.component b/threema-connector-test/.settings/org.eclipse.wst.common.component new file mode 100644 index 0000000..dec10f3 --- /dev/null +++ b/threema-connector-test/.settings/org.eclipse.wst.common.component @@ -0,0 +1,18 @@ + + + + + + + + + + + diff --git a/threema-connector-test/.settings/org.eclipse.wst.common.project.facet.core.prefs.xml b/threema-connector-test/.settings/org.eclipse.wst.common.project.facet.core.prefs.xml new file mode 100644 index 0000000..e725c8d --- /dev/null +++ b/threema-connector-test/.settings/org.eclipse.wst.common.project.facet.core.prefs.xml @@ -0,0 +1,8 @@ + + + + + + + diff --git a/threema-connector-test/.settings/org.eclipse.wst.common.project.facet.core.xml b/threema-connector-test/.settings/org.eclipse.wst.common.project.facet.core.xml new file mode 100644 index 0000000..3bb273d --- /dev/null +++ b/threema-connector-test/.settings/org.eclipse.wst.common.project.facet.core.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/threema-connector-test/.settings/org.eclipse.wst.css.core.prefs b/threema-connector-test/.settings/org.eclipse.wst.css.core.prefs new file mode 100644 index 0000000..5ddc6bd --- /dev/null +++ b/threema-connector-test/.settings/org.eclipse.wst.css.core.prefs @@ -0,0 +1,2 @@ +css-profile/=org.eclipse.wst.css.core.cssprofile.css3 +eclipse.preferences.version=1 diff --git a/threema-connector-test/.settings/org.eclipse.wst.jsdt.ui.superType.container b/threema-connector-test/.settings/org.eclipse.wst.jsdt.ui.superType.container new file mode 100644 index 0000000..3bd5d0a --- /dev/null +++ b/threema-connector-test/.settings/org.eclipse.wst.jsdt.ui.superType.container @@ -0,0 +1 @@ +org.eclipse.wst.jsdt.launching.baseBrowserLibrary \ No newline at end of file diff --git a/threema-connector-test/.settings/org.eclipse.wst.jsdt.ui.superType.name b/threema-connector-test/.settings/org.eclipse.wst.jsdt.ui.superType.name new file mode 100644 index 0000000..05bd71b --- /dev/null +++ b/threema-connector-test/.settings/org.eclipse.wst.jsdt.ui.superType.name @@ -0,0 +1 @@ +Window \ No newline at end of file diff --git a/threema-connector-test/config/custom-fields.yaml b/threema-connector-test/config/custom-fields.yaml new file mode 100644 index 0000000..bb20b70 --- /dev/null +++ b/threema-connector-test/config/custom-fields.yaml @@ -0,0 +1,22 @@ +# yaml-language-server: $schema=https://json-schema.axonivy.com/app/0.0.1/custom-fields.json +# +# == Custom Fields Information == +# +# You can define here your project custom fields. +# Have a look at our documentation for more information. +# +CustomFields: +# Tasks: +# MyTaskCustomField: +# Label: My task custom field +# Description: This new task custom field can be used to ... +# Type: STRING +# Cases: +# MyCaseCustomField: +# Label: My case custom field +# Description: This new case custom field can be used to ... +# Type: STRING +# Starts: +# MyStartCustomField: +# Label: My start custom field +# Description: This new start custom field can be used to ... diff --git a/threema-connector-test/config/databases.yaml b/threema-connector-test/config/databases.yaml new file mode 100644 index 0000000..10319e2 --- /dev/null +++ b/threema-connector-test/config/databases.yaml @@ -0,0 +1,2 @@ +# yaml-language-server: $schema=https://json-schema.axonivy.com/app/0.0.1/databases.json +Databases: diff --git a/threema-connector-test/config/overrides.any b/threema-connector-test/config/overrides.any new file mode 100644 index 0000000..f59ec20 --- /dev/null +++ b/threema-connector-test/config/overrides.any @@ -0,0 +1 @@ +* \ No newline at end of file diff --git a/threema-connector-test/config/persistence.xml b/threema-connector-test/config/persistence.xml new file mode 100644 index 0000000..3de1768 --- /dev/null +++ b/threema-connector-test/config/persistence.xml @@ -0,0 +1,4 @@ + + diff --git a/threema-connector-test/config/rest-clients.yaml b/threema-connector-test/config/rest-clients.yaml new file mode 100644 index 0000000..4bffaca --- /dev/null +++ b/threema-connector-test/config/rest-clients.yaml @@ -0,0 +1,2 @@ +# yaml-language-server: $schema=https://json-schema.axonivy.com/app/0.0.1/rest-clients.json +RestClients: diff --git a/threema-connector-test/config/roles.xml b/threema-connector-test/config/roles.xml new file mode 100644 index 0000000..c7c6911 --- /dev/null +++ b/threema-connector-test/config/roles.xml @@ -0,0 +1,4 @@ + + + Everybody + diff --git a/threema-connector-test/config/users.xml b/threema-connector-test/config/users.xml new file mode 100644 index 0000000..1e173fa --- /dev/null +++ b/threema-connector-test/config/users.xml @@ -0,0 +1,2 @@ + + diff --git a/threema-connector-test/config/variables.yaml b/threema-connector-test/config/variables.yaml new file mode 100644 index 0000000..e24d46a --- /dev/null +++ b/threema-connector-test/config/variables.yaml @@ -0,0 +1,3 @@ +Variables: + + \ No newline at end of file diff --git a/threema-connector-test/config/webservice-clients.yaml b/threema-connector-test/config/webservice-clients.yaml new file mode 100644 index 0000000..688047a --- /dev/null +++ b/threema-connector-test/config/webservice-clients.yaml @@ -0,0 +1,2 @@ +# yaml-language-server: $schema=https://json-schema.axonivy.com/app/0.0.1/webservice-clients.json +WebServiceClients: diff --git a/threema-connector-test/dataclasses/threema/connector/test/Data.ivyClass b/threema-connector-test/dataclasses/threema/connector/test/Data.ivyClass new file mode 100644 index 0000000..de785c2 --- /dev/null +++ b/threema-connector-test/dataclasses/threema/connector/test/Data.ivyClass @@ -0,0 +1,2 @@ +Data #class +threema.connector.test #namespace diff --git a/threema-connector-test/pom.xml b/threema-connector-test/pom.xml new file mode 100644 index 0000000..975a634 --- /dev/null +++ b/threema-connector-test/pom.xml @@ -0,0 +1,47 @@ + + + 4.0.0 + com.axonivy.connector.threema + threema-connector-test + 10.0.0-SNAPSHOT + iar + + + com.axonivy.connector.threema + threema-connector + ${project.version} + iar + + + com.axonivy.ivy.test + unit-tester + 10.0.0 + test + + + + src_test + + + + maven-deploy-plugin + 3.0.0-M1 + + true + + + + + + + com.axonivy.ivy.ci + project-build-plugin + 10.0.6 + true + + + + diff --git a/threema-connector-test/src/ch/ivyteam/threema/mocks/ThreemaServiceMock.java b/threema-connector-test/src/ch/ivyteam/threema/mocks/ThreemaServiceMock.java new file mode 100644 index 0000000..860e3b8 --- /dev/null +++ b/threema-connector-test/src/ch/ivyteam/threema/mocks/ThreemaServiceMock.java @@ -0,0 +1,77 @@ +package ch.ivyteam.threema.mocks; + +import javax.annotation.security.PermitAll; +import javax.ws.rs.PathParam; +import javax.ws.rs.Consumes; +import javax.ws.rs.FormParam; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.ResponseBuilder; +import ch.ivyteam.ivy.environment.Ivy; +import ch.ivyteam.ivy.rest.client.config.IvyDefaultJaxRsTemplates; +import io.swagger.v3.oas.annotations.Hidden; + +@Path(ThreemaServiceMock.PATH_SUFFIX) +@PermitAll +@Hidden +@SuppressWarnings("all") +public class ThreemaServiceMock { + + static final String PATH_SUFFIX = "mock"; + private static final String THREEMA_ID = "validId"; + public static final String URI = "{" + IvyDefaultJaxRsTemplates.APP_URL + "}/api/" + PATH_SUFFIX; + // {ivy.app.baseurl}/api/mock + // https://msgapi.threema.ch + + @GET + @Path("/lookup/{type}/{id}") + @Produces(MediaType.TEXT_PLAIN) + public Response getThreemaIdByMail(@PathParam("type") String type, @PathParam("id") String id) { + Response resp; + if (id.equals("validId")) { + resp = Response.ok().entity(THREEMA_ID).build(); + } else { + resp = Response.status(404).build(); + } + return resp; + } + + @GET + @Path("/pubkeys/{id}") + @Produces(MediaType.TEXT_PLAIN) + public Response getPublicKey(@PathParam("id") String id) { + Response resp; + String pubKey = "ffbb40cfced42f75c4d83c7d35300c0698bf3ef1ab49ace323a1bbc38ee23f36"; + if (id.equals(THREEMA_ID)) { + resp = Response.ok().entity(pubKey).build(); + } else { + resp = Response.status(404).build(); + } + return resp; + } + + @POST + @Consumes(MediaType.APPLICATION_FORM_URLENCODED) + @Path("/send_e2e") + @Produces(MediaType.TEXT_PLAIN) + public Response sendMessage( + @FormParam("from") String from, + @FormParam("box") String box, + @FormParam("to") String to, + @FormParam("secret") String secret, + @FormParam("nonce") String nonce) { + String msgId = "b2885aa81e9b9c93"; + Response resp; + if (to.equals("validId")) { + resp = Response.ok().entity(msgId).build(); + } else { + resp = Response.status(404).build(); + } + return resp; + } +} diff --git a/threema-connector-test/src_test/threema/connector/test/process/GetReceiverInfoTest.java b/threema-connector-test/src_test/threema/connector/test/process/GetReceiverInfoTest.java new file mode 100644 index 0000000..173f74f --- /dev/null +++ b/threema-connector-test/src_test/threema/connector/test/process/GetReceiverInfoTest.java @@ -0,0 +1,110 @@ +package threema.connector.test.process; + +import static org.assertj.core.api.Assertions.assertThat; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import ch.ivyteam.ivy.bpm.engine.client.BpmClient; +import ch.ivyteam.ivy.bpm.engine.client.ExecutionResult; +import ch.ivyteam.ivy.bpm.engine.client.History; +import ch.ivyteam.ivy.bpm.engine.client.element.BpmElement; +import ch.ivyteam.ivy.bpm.engine.client.element.BpmProcess; +import ch.ivyteam.ivy.bpm.exec.client.IvyProcessTest; +import ch.ivyteam.ivy.environment.AppFixture; +import ch.ivyteam.threema.mocks.ThreemaServiceMock; +import threema.connector.ReceiverData; +import util.LookupType; + +@IvyProcessTest(enableWebServer = true) +public class GetReceiverInfoTest { + + private static final BpmProcess RECEIVER_INFO_PROCESS = BpmProcess.name("getReceiverInfo"); + private static final String VALID_ID = "validId"; + + @BeforeEach + void setup(AppFixture fixture) { + fixture.config("RestClients.ThreemaGateway.Url", ThreemaServiceMock.URI); + } + + @Test + void getIDByValidEmail(BpmClient bpmClient) { + BpmElement callable = RECEIVER_INFO_PROCESS.elementName("call(receiverData)"); + String email = VALID_ID; + ReceiverData recDatMail = new ReceiverData(); + recDatMail.setIdentifier(email); + recDatMail.setType(LookupType.EMAIL); + ExecutionResult resultMail = bpmClient.start().subProcess(callable).execute(recDatMail); + ReceiverData resultDataMail = resultMail.data().last(); + History historyMail = resultMail.history(); + assertThat(resultDataMail.getApiResponse()).contains("200"); + assertThat(historyMail.elementNames()) + .contains("call(receiverData)") + .contains("LookupId") + .contains("LookupPubKey"); + } + + @Test + void getIDByInvalidEmail(BpmClient bpmClient) { + BpmElement callable = RECEIVER_INFO_PROCESS.elementName("call(receiverData)"); + String email = "invalid@email.com"; + ReceiverData recDatMail = new ReceiverData(); + recDatMail.setIdentifier(email); + recDatMail.setType(LookupType.EMAIL); + ExecutionResult resultMail = bpmClient.start().subProcess(callable).execute(recDatMail); + ReceiverData resultDataMail = resultMail.data().last(); + History historyMail = resultMail.history(); + assertThat(resultDataMail.getApiResponse()).contains("404"); + assertThat(historyMail.elementNames()).contains("call(receiverData)") + .contains("LookupId") + .doesNotContain("LookupPubKey"); + } + + @Test + void getIDByValidPhone(BpmClient bpmClient) { + BpmElement callable = RECEIVER_INFO_PROCESS.elementName("call(receiverData)"); + String phone = VALID_ID; + ReceiverData recDatMail = new ReceiverData(); + recDatMail.setIdentifier(phone); + recDatMail.setType(LookupType.PHONE); + ExecutionResult resultMail = bpmClient.start().subProcess(callable).execute(recDatMail); + ReceiverData resultDataMail = resultMail.data().last(); + History historyMail = resultMail.history(); + assertThat(resultDataMail.getApiResponse()).contains("200"); + assertThat(historyMail.elementNames()).contains("call(receiverData)") + .contains("LookupId") + .contains("LookupPubKey"); + } + + @Test + void getPublicKeyByID(BpmClient bpmClient) { + BpmElement callable = RECEIVER_INFO_PROCESS.elementName("call(receiverData)"); + String threemaId = "validId"; + ReceiverData recDatId = new ReceiverData(); + recDatId.setIdentifier(threemaId); + recDatId.setType(LookupType.THREEMAID); + ExecutionResult resultId = bpmClient.start().subProcess(callable).execute(recDatId); + ReceiverData resultDataId = resultId.data().last(); + History historyId = resultId.history(); + assertThat(resultDataId.getApiResponse()).contains("200"); + assertThat(resultDataId.getPublicKey()) + .isEqualTo("ffbb40cfced42f75c4d83c7d35300c0698bf3ef1ab49ace323a1bbc38ee23f36"); + assertThat(historyId.elementNames()).contains("call(receiverData)") + .contains("LookupPubKey") + .doesNotContain("LookupId"); + } + + @Test + void getPublicKeyByInvalidID(BpmClient bpmClient) { + BpmElement callable = RECEIVER_INFO_PROCESS.elementName("call(receiverData)"); + String threemaId = "invalidID"; + ReceiverData recDatId = new ReceiverData(); + recDatId.setIdentifier(threemaId); + recDatId.setType(LookupType.THREEMAID); + ExecutionResult resultId = bpmClient.start().subProcess(callable).execute(recDatId); + ReceiverData resultDataId = resultId.data().last(); + History historyId = resultId.history(); + assertThat(resultDataId.getApiResponse()).contains("404"); + assertThat(historyId.elementNames()).contains("call(receiverData)") + .contains("LookupPubKey") + .doesNotContain("LookupId"); + } +} diff --git a/threema-connector-test/src_test/threema/connector/test/process/MessageEncryptionTest.java b/threema-connector-test/src_test/threema/connector/test/process/MessageEncryptionTest.java new file mode 100644 index 0000000..86c7844 --- /dev/null +++ b/threema-connector-test/src_test/threema/connector/test/process/MessageEncryptionTest.java @@ -0,0 +1,42 @@ +package threema.connector.test.process; + +import static javax.xml.bind.DatatypeConverter.parseHexBinary; +import static org.assertj.core.api.Assertions.assertThat; +import org.junit.jupiter.api.Test; +import ch.ivyteam.ivy.bpm.engine.client.BpmClient; +import ch.ivyteam.ivy.bpm.engine.client.ExecutionResult; +import ch.ivyteam.ivy.bpm.engine.client.element.BpmElement; +import ch.ivyteam.ivy.bpm.engine.client.element.BpmProcess; +import ch.ivyteam.ivy.bpm.exec.client.IvyProcessTest; +import ch.ivyteam.ivy.environment.Ivy; +import ch.threema.apitool.CryptTool; +import threema.connector.ReceiverData; + +@IvyProcessTest +public class MessageEncryptionTest { + + private final static BpmProcess ENCRYPTION_PROCESS = BpmProcess.name("messageEncryption"); + private final static String PUBLIC_KEY = "ffbb40cfced42f75c4d83c7d35300c0698bf3ef1ab49ace323a1bbc38ee23f36"; + private final static String PRIVATE_KEY = "ff364c727068fd6e3e6a711918393fa37649d902402a8eb31af108e79f625d82"; + + @Test + void encryptMessage(BpmClient bpmClient) { + BpmElement callable = ENCRYPTION_PROCESS.elementName("call(receiverData)"); + // set PrivateKey for this test + Ivy.var().set("threemaConnector.privateKey", PRIVATE_KEY); + String plainMsg = "Hello World"; + ReceiverData recData = new ReceiverData(); + recData.setPlainMessage(plainMsg); + recData.setPublicKey(PUBLIC_KEY); + ExecutionResult result = bpmClient.start().subProcess(callable).execute(recData); + ReceiverData resultData = result.data().last(); + assertThat(resultData.getEncryptedMessage()).isNotEmpty(); + byte[] decryptedByte = CryptTool.decrypt( + parseHexBinary(resultData.getEncryptedMessage()), + parseHexBinary(PRIVATE_KEY), + parseHexBinary(PUBLIC_KEY), + parseHexBinary(resultData.getNonce())); + String decryptedMsg = new String(decryptedByte); + assertThat(decryptedMsg).contains(plainMsg); + } +} diff --git a/threema-connector-test/src_test/threema/connector/test/process/MultipleRecipientsTest.java b/threema-connector-test/src_test/threema/connector/test/process/MultipleRecipientsTest.java new file mode 100644 index 0000000..8db51cd --- /dev/null +++ b/threema-connector-test/src_test/threema/connector/test/process/MultipleRecipientsTest.java @@ -0,0 +1,46 @@ +package threema.connector.test.process; + +import static org.assertj.core.api.Assertions.assertThat; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import ch.ivyteam.ivy.bpm.engine.client.BpmClient; +import ch.ivyteam.ivy.bpm.engine.client.ExecutionResult; +import ch.ivyteam.ivy.bpm.engine.client.element.BpmElement; +import ch.ivyteam.ivy.bpm.engine.client.element.BpmProcess; +import ch.ivyteam.ivy.bpm.exec.client.IvyProcessTest; +import ch.ivyteam.ivy.environment.AppFixture; +import ch.ivyteam.ivy.scripting.objects.List; +import ch.ivyteam.threema.mocks.ThreemaServiceMock; +import threema.connector.ReceiverData; +import threema.connector.SendThreemaMessageData; +import util.LookupType; + +@IvyProcessTest(enableWebServer = true) +public class MultipleRecipientsTest { + + private final static BpmProcess MULTIPLE_RECIPIENTS_PROCESS = BpmProcess.name("multipleRecipients"); + private final static String MESSAGE = "Hello World"; + + @BeforeEach + void setup(AppFixture fixture) { + fixture.config("RestClients.ThreemaGateway.Url", ThreemaServiceMock.URI); + } + + @Test + void prepareMultipleRecipients(BpmClient bpmClient) { + List recipients = new List(); + recipients.add("invalidThreemaID"); + recipients.add("41000000000"); + recipients.add("invalid@email.ch"); + BpmElement callable = MULTIPLE_RECIPIENTS_PROCESS.elementName("call(String,List)"); + ExecutionResult result = bpmClient.start().subProcess(callable).execute(MESSAGE, recipients); + SendThreemaMessageData msgData = result.data().last(); + List listReceiver = msgData.getReceiverData(); + assertThat(listReceiver.size()).isEqualTo(recipients.size()); + assertThat(listReceiver).extracting(ReceiverData::getType) + .containsExactly(LookupType.THREEMAID, LookupType.PHONE, LookupType.EMAIL); + for (String status : msgData.getApiResponses()) { + assertThat(status).contains("404"); + } + } +} diff --git a/threema-connector-test/src_test/threema/connector/test/process/SendMessageTest.java b/threema-connector-test/src_test/threema/connector/test/process/SendMessageTest.java new file mode 100644 index 0000000..77b5f6c --- /dev/null +++ b/threema-connector-test/src_test/threema/connector/test/process/SendMessageTest.java @@ -0,0 +1,74 @@ +package threema.connector.test.process; + +import static org.assertj.core.api.Assertions.assertThat; +import javax.xml.bind.DatatypeConverter; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import ch.ivyteam.ivy.bpm.engine.client.BpmClient; +import ch.ivyteam.ivy.bpm.engine.client.ExecutionResult; +import ch.ivyteam.ivy.bpm.engine.client.element.BpmElement; +import ch.ivyteam.ivy.bpm.engine.client.element.BpmProcess; +import ch.ivyteam.ivy.bpm.exec.client.IvyProcessTest; +import ch.ivyteam.ivy.environment.AppFixture; +import ch.ivyteam.threema.mocks.ThreemaServiceMock; +import ch.threema.apitool.CryptTool; +import ch.threema.apitool.results.EncryptResult; +import threema.connector.ReceiverData; + +@IvyProcessTest(enableWebServer = true) +public class SendMessageTest { + + private static final BpmProcess SEND_MESSAGE_PROCESS = BpmProcess.name("sendMessage"); + private static final String ECHO_PUBLIC_KEY = "4a6a1b34dcef15d43cb74de2fd36091be99fbbaf126d099d47d83d919712c72b"; + private static final String PRIVATE_KEY = "ff364c727068fd6e3e6a711918393fa37649d902402a8eb31af108e79f625d82"; + private static final String INVALID_PUBLIC_KEY = "0000004dcef15d43cb74de2fd36091be99fbbaf126d099d47d83d919712c72b"; + private static final String VALID_ID = "validId"; + private static final String INVALID_ID = "invalidId"; + private static final String message = "Hello World"; + private static String encryptedMessage; + private static String nonce; + + @BeforeAll + static void encryptMessage() { + EncryptResult encryptResult = CryptTool.encryptTextMessage( + message, + DatatypeConverter.parseHexBinary(PRIVATE_KEY), + DatatypeConverter.parseHexBinary(ECHO_PUBLIC_KEY)); + encryptedMessage = DatatypeConverter.printHexBinary(encryptResult.getResult()); + nonce = DatatypeConverter.printHexBinary(encryptResult.getNonce()); + } + + @BeforeEach + void setup(AppFixture fixture) { + fixture.config("RestClients.ThreemaGateway.Url", ThreemaServiceMock.URI); + } + + @Test + void sendValidMessage(BpmClient bpmClient) { + BpmElement callable = SEND_MESSAGE_PROCESS.elementName("call(receiverData)"); + ReceiverData recDat = new ReceiverData(); + recDat.setThreemaId(VALID_ID); + recDat.setPublicKey(ECHO_PUBLIC_KEY); + recDat.setEncryptedMessage(encryptedMessage); + recDat.setNonce(nonce); + recDat.setApiResponse(""); + ExecutionResult result = bpmClient.start().subProcess(callable).execute(recDat); + ReceiverData resultData = result.data().last(); + assertThat(resultData.getApiResponse()).contains("200"); + } + + @Test + void sendInvalidMessage(BpmClient bpmClient) { + BpmElement callable = SEND_MESSAGE_PROCESS.elementName("call(receiverData)"); + ReceiverData recDat = new ReceiverData(); + recDat.setThreemaId(INVALID_ID); + recDat.setPublicKey(INVALID_PUBLIC_KEY); + recDat.setEncryptedMessage(encryptedMessage); + recDat.setNonce(nonce); + recDat.setApiResponse(""); + ExecutionResult result = bpmClient.start().subProcess(callable).execute(recDat); + ReceiverData resultData = result.data().last(); + assertThat(resultData.getApiResponse()).contains("404"); + } +} diff --git a/threema-connector-test/src_test/threema/connector/test/process/SingleRecipientTest.java b/threema-connector-test/src_test/threema/connector/test/process/SingleRecipientTest.java new file mode 100644 index 0000000..60842db --- /dev/null +++ b/threema-connector-test/src_test/threema/connector/test/process/SingleRecipientTest.java @@ -0,0 +1,63 @@ +package threema.connector.test.process; + +import static org.assertj.core.api.Assertions.assertThat; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import ch.ivyteam.ivy.bpm.engine.client.BpmClient; +import ch.ivyteam.ivy.bpm.engine.client.ExecutionResult; +import ch.ivyteam.ivy.bpm.engine.client.element.BpmElement; +import ch.ivyteam.ivy.bpm.engine.client.element.BpmProcess; +import ch.ivyteam.ivy.bpm.exec.client.IvyProcessTest; +import ch.ivyteam.ivy.environment.AppFixture; +import ch.ivyteam.ivy.environment.Ivy; +import ch.ivyteam.threema.mocks.ThreemaServiceMock; +import threema.connector.ReceiverData; + +@IvyProcessTest(enableWebServer = true) +public class SingleRecipientTest { + + private static final BpmProcess SINGLE_RECEIVER_PROCESS = BpmProcess.name("singleRecipient"); + private static final String VALID_ID = "validId"; + private static final String INVALID_EMAIL = "invalid@mail.ch"; + private static final String INVALID_PHONE = "41000000000"; + private static final String MESSAGE = "Hello World"; + private static final String PRIVATE_KEY = "ff364c727068fd6e3e6a711918393fa37649d902402a8eb31af108e79f625d82"; + + @BeforeEach + void setup(AppFixture fixture) { + Ivy.var().set("threemaConnector.privateKey", PRIVATE_KEY); + Ivy.var().set("threemaConnector.secret", "secret"); + Ivy.var().set("threemaConnector.threemaId", "threemaId"); + fixture.config("RestClients.ThreemaGateway.Url", ThreemaServiceMock.URI); + } + + @Test + void sendMessageToValidSingleRecipientById(BpmClient bpmClient) { + BpmElement callable = SINGLE_RECEIVER_PROCESS.elementName("call(String,String,LookupType)"); + ExecutionResult result = bpmClient.start().subProcess(callable).execute(MESSAGE, VALID_ID, + util.LookupType.THREEMAID); + ReceiverData resultData = result.data().last(); + String apiStatus = resultData.getApiResponse(); + assertThat(apiStatus).contains("200"); + } + + @Test + void sendMessageToInvalidSingleRecipientByEmail(BpmClient bpmClient) { + BpmElement callable = SINGLE_RECEIVER_PROCESS.elementName("call(String,String,LookupType)"); + ExecutionResult result = bpmClient.start().subProcess(callable).execute(MESSAGE, INVALID_EMAIL, + util.LookupType.EMAIL); + ReceiverData resultData = result.data().last(); + String apiStatus = resultData.getApiResponse(); + assertThat(apiStatus).isEqualTo("ID-Lookup: 404"); + } + + @Test + void sendMessageToInvalidSingleRecipientByPhone(BpmClient bpmClient) { + BpmElement callable = SINGLE_RECEIVER_PROCESS.elementName("call(String,String,LookupType)"); + ExecutionResult result = bpmClient.start().subProcess(callable).execute(MESSAGE, INVALID_PHONE, + util.LookupType.PHONE); + ReceiverData resultData = result.data().last(); + String apiStatus = resultData.getApiResponse(); + assertThat(apiStatus).isEqualTo("ID-Lookup: 404"); + } +} diff --git a/threema-connector-test/src_test/threema/connector/test/util/LookupTypeTest.java b/threema-connector-test/src_test/threema/connector/test/util/LookupTypeTest.java new file mode 100644 index 0000000..7ce3758 --- /dev/null +++ b/threema-connector-test/src_test/threema/connector/test/util/LookupTypeTest.java @@ -0,0 +1,46 @@ +package threema.connector.test.util; + +import static org.assertj.core.api.Assertions.assertThat; +import org.junit.jupiter.api.Test; +import util.LookupType; + +public class LookupTypeTest { + + @Test + void getTypeByString() { + String email = "email"; + String phone = "phone"; + String threemaId = "threemaId"; + String invalid1 = "invalidType1"; + String invalid2 = "invalidType2"; + LookupType typeEmail = LookupType.getByString(email); + assertThat(typeEmail).isEqualTo(LookupType.EMAIL); + LookupType typePhone = LookupType.getByString(phone); + assertThat(typePhone).isEqualTo(LookupType.PHONE); + LookupType typeThreemaId = LookupType.getByString(threemaId); + assertThat(typeThreemaId).isEqualTo(LookupType.THREEMAID); + LookupType typeInvalid1 = LookupType.getByString(invalid1); + assertThat(typeInvalid1).isEqualTo(LookupType.INVALID); + LookupType typeInvalid2 = LookupType.getByString(invalid2); + assertThat(typeInvalid2).isEqualTo(LookupType.INVALID); + } + + @Test + void getTypebyPattern() { + String email = "xyz@xyz.yz"; + String phoneSimple = "00000000000"; + String phoneComplete = "+00000000000"; + String phoneCompleteSpace = "+00 00 000 00 00"; + String threemaId = "didegiasdfl"; + LookupType typeEmail = LookupType.getByPattern(email); + assertThat(typeEmail).isEqualTo(LookupType.EMAIL); + LookupType typePhone = LookupType.getByPattern(phoneSimple); + assertThat(typePhone).isEqualTo(LookupType.PHONE); + typePhone = LookupType.getByPattern(phoneComplete); + assertThat(typePhone).isEqualTo(LookupType.PHONE); + typePhone = LookupType.getByPattern(phoneCompleteSpace); + assertThat(typePhone).isEqualTo(LookupType.PHONE); + LookupType typeThreemaId = LookupType.getByPattern(threemaId); + assertThat(typeThreemaId).isEqualTo(LookupType.THREEMAID); + } +} diff --git a/threema-connector-webtest/.classpath b/threema-connector-webtest/.classpath new file mode 100644 index 0000000..26e6fb6 --- /dev/null +++ b/threema-connector-webtest/.classpath @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/threema-connector-webtest/.gitignore b/threema-connector-webtest/.gitignore new file mode 100644 index 0000000..1b2547b --- /dev/null +++ b/threema-connector-webtest/.gitignore @@ -0,0 +1,19 @@ +# general +Thumbs.db +.DS_Store +*~ +*.log + +# java +*.class +hs_err_pid* + +# maven +target/ +lib/mvn-deps/ + +# ivy +classes/ +src_dataClasses/ +src_wsproc/ +logs/ diff --git a/threema-connector-webtest/.project b/threema-connector-webtest/.project new file mode 100644 index 0000000..d8bca7c --- /dev/null +++ b/threema-connector-webtest/.project @@ -0,0 +1,49 @@ + + + threema-connector-webtest + + + + + + ch.ivyteam.ivy.designer.dataClasses.ui.ivyDataClassBuilder + + + + + ch.ivyteam.ivy.designer.process.ui.ivyWebServiceProcessClassBuilder + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.wst.common.project.facet.core.builder + + + + + ch.ivyteam.ivy.designer.ide.ivyModelValidationBuilder + + + + + org.eclipse.m2e.core.maven2Builder + + + + + + ch.ivyteam.ivy.project.IvyProjectNature + org.eclipse.wst.common.modulecore.ModuleCoreNature + org.eclipse.jem.workbench.JavaEMFNature + org.eclipse.jdt.core.javanature + org.eclipse.m2e.core.maven2Nature + org.eclipse.jem.beaninfo.BeanInfoNature + org.eclipse.wst.common.project.facet.core.nature + org.eclipse.wst.jsdt.core.jsNature + + diff --git a/threema-connector-webtest/.settings/.jsdtscope b/threema-connector-webtest/.settings/.jsdtscope new file mode 100644 index 0000000..e4ab59a --- /dev/null +++ b/threema-connector-webtest/.settings/.jsdtscope @@ -0,0 +1,17 @@ + + + + + + + + + + + + diff --git a/threema-connector-webtest/.settings/ch.ivyteam.ivy.designer.prefs b/threema-connector-webtest/.settings/ch.ivyteam.ivy.designer.prefs new file mode 100644 index 0000000..822cc6b --- /dev/null +++ b/threema-connector-webtest/.settings/ch.ivyteam.ivy.designer.prefs @@ -0,0 +1,5 @@ +ch.ivyteam.ivy.designer.preferences.DataClassPreferencePage\:DEFAULT_DATA_CLASS=threema.connector.webtest.Data +ch.ivyteam.ivy.designer.preferences.DataClassPreferencePage\:DEFAULT_NAMESPACE=threema.connector.webtest +ch.ivyteam.ivy.project.preferences\:PRIMEFACES_VERSION=11 +ch.ivyteam.ivy.project.preferences\:PROJECT_VERSION=100000 +eclipse.preferences.version=1 diff --git a/threema-connector-webtest/.settings/org.eclipse.jdt.core.prefs b/threema-connector-webtest/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..d4540a5 --- /dev/null +++ b/threema-connector-webtest/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,10 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=17 +org.eclipse.jdt.core.compiler.compliance=17 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning +org.eclipse.jdt.core.compiler.release=enabled +org.eclipse.jdt.core.compiler.source=17 diff --git a/threema-connector-webtest/.settings/org.eclipse.wst.common.component b/threema-connector-webtest/.settings/org.eclipse.wst.common.component new file mode 100644 index 0000000..294e9ee --- /dev/null +++ b/threema-connector-webtest/.settings/org.eclipse.wst.common.component @@ -0,0 +1,20 @@ + + + + + + + + + + + + diff --git a/threema-connector-webtest/.settings/org.eclipse.wst.common.project.facet.core.prefs.xml b/threema-connector-webtest/.settings/org.eclipse.wst.common.project.facet.core.prefs.xml new file mode 100644 index 0000000..e725c8d --- /dev/null +++ b/threema-connector-webtest/.settings/org.eclipse.wst.common.project.facet.core.prefs.xml @@ -0,0 +1,8 @@ + + + + + + + diff --git a/threema-connector-webtest/.settings/org.eclipse.wst.common.project.facet.core.xml b/threema-connector-webtest/.settings/org.eclipse.wst.common.project.facet.core.xml new file mode 100644 index 0000000..3bb273d --- /dev/null +++ b/threema-connector-webtest/.settings/org.eclipse.wst.common.project.facet.core.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/threema-connector-webtest/.settings/org.eclipse.wst.css.core.prefs b/threema-connector-webtest/.settings/org.eclipse.wst.css.core.prefs new file mode 100644 index 0000000..5ddc6bd --- /dev/null +++ b/threema-connector-webtest/.settings/org.eclipse.wst.css.core.prefs @@ -0,0 +1,2 @@ +css-profile/=org.eclipse.wst.css.core.cssprofile.css3 +eclipse.preferences.version=1 diff --git a/threema-connector-webtest/.settings/org.eclipse.wst.jsdt.ui.superType.container b/threema-connector-webtest/.settings/org.eclipse.wst.jsdt.ui.superType.container new file mode 100644 index 0000000..3bd5d0a --- /dev/null +++ b/threema-connector-webtest/.settings/org.eclipse.wst.jsdt.ui.superType.container @@ -0,0 +1 @@ +org.eclipse.wst.jsdt.launching.baseBrowserLibrary \ No newline at end of file diff --git a/threema-connector-webtest/.settings/org.eclipse.wst.jsdt.ui.superType.name b/threema-connector-webtest/.settings/org.eclipse.wst.jsdt.ui.superType.name new file mode 100644 index 0000000..05bd71b --- /dev/null +++ b/threema-connector-webtest/.settings/org.eclipse.wst.jsdt.ui.superType.name @@ -0,0 +1 @@ +Window \ No newline at end of file diff --git a/threema-connector-webtest/config/custom-fields.yaml b/threema-connector-webtest/config/custom-fields.yaml new file mode 100644 index 0000000..aa19ae0 --- /dev/null +++ b/threema-connector-webtest/config/custom-fields.yaml @@ -0,0 +1,20 @@ +# == Custom Fields Information == +# +# You can define here your project custom fields. +# Have a look at our documentation for more information. +# +CustomFields: +# Tasks: +# MyTaskCustomField: +# Label: My task custom field +# Description: This new task custom field can be used to ... +# Type: STRING +# Cases: +# MyCaseCustomField: +# Label: My case custom field +# Description: This new case custom field can be used to ... +# Type: STRING +# Starts: +# MyStartCustomField: +# Label: My start custom field +# Description: This new start custom field can be used to ... diff --git a/threema-connector-webtest/config/databases.yaml b/threema-connector-webtest/config/databases.yaml new file mode 100644 index 0000000..247b128 --- /dev/null +++ b/threema-connector-webtest/config/databases.yaml @@ -0,0 +1 @@ +Databases: diff --git a/threema-connector-webtest/config/overrides.any b/threema-connector-webtest/config/overrides.any new file mode 100644 index 0000000..f59ec20 --- /dev/null +++ b/threema-connector-webtest/config/overrides.any @@ -0,0 +1 @@ +* \ No newline at end of file diff --git a/threema-connector-webtest/config/persistence.xml b/threema-connector-webtest/config/persistence.xml new file mode 100644 index 0000000..3de1768 --- /dev/null +++ b/threema-connector-webtest/config/persistence.xml @@ -0,0 +1,4 @@ + + diff --git a/threema-connector-webtest/config/rest-clients.yaml b/threema-connector-webtest/config/rest-clients.yaml new file mode 100644 index 0000000..8e85296 --- /dev/null +++ b/threema-connector-webtest/config/rest-clients.yaml @@ -0,0 +1 @@ +RestClients: diff --git a/threema-connector-webtest/config/roles.xml b/threema-connector-webtest/config/roles.xml new file mode 100644 index 0000000..c7c6911 --- /dev/null +++ b/threema-connector-webtest/config/roles.xml @@ -0,0 +1,4 @@ + + + Everybody + diff --git a/threema-connector-webtest/config/users.xml b/threema-connector-webtest/config/users.xml new file mode 100644 index 0000000..1e173fa --- /dev/null +++ b/threema-connector-webtest/config/users.xml @@ -0,0 +1,2 @@ + + diff --git a/threema-connector-webtest/config/variables.yaml b/threema-connector-webtest/config/variables.yaml new file mode 100644 index 0000000..64c8fa0 --- /dev/null +++ b/threema-connector-webtest/config/variables.yaml @@ -0,0 +1,9 @@ +# == Variables == +# +# You can define here your project Variables. +# If you want to define/override a Variable for a specific Environment, +# add an additional ‘variables.yaml’ file in a subdirectory in the ‘Config’ folder: +# '/Config/_/variables.yaml +# +Variables: +# myVariable: value diff --git a/threema-connector-webtest/config/webservice-clients.yaml b/threema-connector-webtest/config/webservice-clients.yaml new file mode 100644 index 0000000..060b018 --- /dev/null +++ b/threema-connector-webtest/config/webservice-clients.yaml @@ -0,0 +1 @@ +WebServiceClients: diff --git a/threema-connector-webtest/dataclasses/threema/connector/webtest/Data.ivyClass b/threema-connector-webtest/dataclasses/threema/connector/webtest/Data.ivyClass new file mode 100644 index 0000000..34a701a --- /dev/null +++ b/threema-connector-webtest/dataclasses/threema/connector/webtest/Data.ivyClass @@ -0,0 +1,2 @@ +Data #class +threema.connector.webtest #namespace diff --git a/threema-connector-webtest/pom.xml b/threema-connector-webtest/pom.xml new file mode 100644 index 0000000..a59ddf9 --- /dev/null +++ b/threema-connector-webtest/pom.xml @@ -0,0 +1,36 @@ + + + 4.0.0 + com.axonivy.connector.threema + threema-connector-webtest + 10.0.0-SNAPSHOT + iar-integration-test + + + com.axonivy.connector.threema + threema-connector-demo + ${project.version} + iar + + + com.axonivy.ivy.webtest + web-tester + 10.0.0 + test + + + + src_test + + + com.axonivy.ivy.ci + project-build-plugin + 10.0.6 + true + + + + diff --git a/threema-connector-webtest/src_test/threema/connector/webtest/MessageMultipleRecipientsTest.java b/threema-connector-webtest/src_test/threema/connector/webtest/MessageMultipleRecipientsTest.java new file mode 100644 index 0000000..463e62f --- /dev/null +++ b/threema-connector-webtest/src_test/threema/connector/webtest/MessageMultipleRecipientsTest.java @@ -0,0 +1,40 @@ +package threema.connector.webtest; + +import static com.codeborne.selenide.Condition.empty; +import static com.codeborne.selenide.Condition.value; +import static com.codeborne.selenide.Selenide.$; +import static com.codeborne.selenide.Selenide.$$; +import static com.codeborne.selenide.Selenide.open; +import static org.assertj.core.api.Assertions.assertThat; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; +import org.openqa.selenium.By; +import com.axonivy.ivy.webtest.IvyWebTest; +import com.axonivy.ivy.webtest.engine.EngineUrl; +import com.codeborne.selenide.ElementsCollection; + +@IvyWebTest +public class MessageMultipleRecipientsTest { + + @Test + @Disabled + public void sendMessage() { + open(EngineUrl.createProcessUrl("threema-connector-demo/18B1ED116183D822/start.ivp")); + String message = "Hello World"; + String recipients = "validId\ninvalidId"; + // Assert empty form + $(By.id("form:sendDemoMessageDataPlainMessage")).shouldBe(empty); + $(By.id("form:sendDemoMessageDataReceiver")).shouldBe(empty); + // Proceed without required fields + $(By.id("form:proceed")).click(); + // Assert all fields required + ElementsCollection errorMessages = $$(By.cssSelector(".ui-state-error")); + assertThat(errorMessages).hasSize(4); + // Fill out form + $(By.id("form:sendDemoMessageDataPlainMessage")).sendKeys(message); + $(By.id("form:sendDemoMessageDataReceiver")).sendKeys(recipients); + // Assert filled out form + $(By.id("form:sendDemoMessageDataPlainMessage")).shouldBe(value(message)); + $(By.id("form:sendDemoMessageDataReceiver")).shouldBe(value(recipients)); + } +} diff --git a/threema-connector-webtest/src_test/threema/connector/webtest/MessageSingleRecipientTest.java b/threema-connector-webtest/src_test/threema/connector/webtest/MessageSingleRecipientTest.java new file mode 100644 index 0000000..fb96520 --- /dev/null +++ b/threema-connector-webtest/src_test/threema/connector/webtest/MessageSingleRecipientTest.java @@ -0,0 +1,45 @@ +package threema.connector.webtest; + +import static com.codeborne.selenide.Condition.empty; +import static com.codeborne.selenide.Condition.selected; +import static com.codeborne.selenide.Condition.value; +import static com.codeborne.selenide.Selenide.$; +import static com.codeborne.selenide.Selenide.$$; +import static com.codeborne.selenide.Selenide.open; +import static org.assertj.core.api.Assertions.assertThat; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; +import org.openqa.selenium.By; +import com.axonivy.ivy.webtest.IvyWebTest; +import com.axonivy.ivy.webtest.engine.EngineUrl; +import com.axonivy.ivy.webtest.primeui.PrimeUi; +import com.codeborne.selenide.ElementsCollection; + +@IvyWebTest +public class MessageSingleRecipientTest { + + @Test + @Disabled + public void sendMessage() { + open(EngineUrl.createProcessUrl("threema-connector-demo/18B22F69680901D3/start.ivp")); + String message = "Hello World"; + String validId = "validId"; + // Assert empty form + $(By.id("form:sendDemoMessageDataPlainMessage")).shouldBe(empty); + $(By.id("form:sendDemoMessageDataReceiver")).shouldBe(empty); + $(By.id("form:typeSelection:2")).shouldNotBe(selected); + // Proceed without required fields + $(By.id("form:proceed")).click(); + // Assert all fields required + ElementsCollection errorMessages = $$(By.cssSelector(".ui-state-error")); + assertThat(errorMessages).hasSize(8); + // Fill out form + $(By.id("form:sendDemoMessageDataPlainMessage")).sendKeys(message); + $(By.id("form:sendDemoMessageDataReceiver")).sendKeys(validId); + PrimeUi.selectOneRadio(By.id("form:typeSelection")).selectItemByValue("threemaid"); + // Assert filled out form + $(By.id("form:sendDemoMessageDataPlainMessage")).shouldBe(value(message)); + $(By.id("form:sendDemoMessageDataReceiver")).shouldBe(value(validId)); + $(By.id("form:typeSelection:2")).shouldBe(selected); + } +} diff --git a/threema-connector/.classpath b/threema-connector/.classpath new file mode 100644 index 0000000..37f38ba --- /dev/null +++ b/threema-connector/.classpath @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/threema-connector/.gitignore b/threema-connector/.gitignore new file mode 100644 index 0000000..1b2547b --- /dev/null +++ b/threema-connector/.gitignore @@ -0,0 +1,19 @@ +# general +Thumbs.db +.DS_Store +*~ +*.log + +# java +*.class +hs_err_pid* + +# maven +target/ +lib/mvn-deps/ + +# ivy +classes/ +src_dataClasses/ +src_wsproc/ +logs/ diff --git a/threema-connector/.project b/threema-connector/.project new file mode 100644 index 0000000..fd84dab --- /dev/null +++ b/threema-connector/.project @@ -0,0 +1,49 @@ + + + threema-connector + + + + + + ch.ivyteam.ivy.designer.dataClasses.ui.ivyDataClassBuilder + + + + + ch.ivyteam.ivy.designer.process.ui.ivyWebServiceProcessClassBuilder + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.wst.common.project.facet.core.builder + + + + + ch.ivyteam.ivy.designer.ide.ivyModelValidationBuilder + + + + + org.eclipse.m2e.core.maven2Builder + + + + + + ch.ivyteam.ivy.project.IvyProjectNature + org.eclipse.wst.common.modulecore.ModuleCoreNature + org.eclipse.jem.workbench.JavaEMFNature + org.eclipse.jdt.core.javanature + org.eclipse.m2e.core.maven2Nature + org.eclipse.jem.beaninfo.BeanInfoNature + org.eclipse.wst.common.project.facet.core.nature + org.eclipse.wst.jsdt.core.jsNature + + diff --git a/threema-connector/.settings/.jsdtscope b/threema-connector/.settings/.jsdtscope new file mode 100644 index 0000000..e4ab59a --- /dev/null +++ b/threema-connector/.settings/.jsdtscope @@ -0,0 +1,17 @@ + + + + + + + + + + + + diff --git a/threema-connector/.settings/ch.ivyteam.ivy.designer.prefs b/threema-connector/.settings/ch.ivyteam.ivy.designer.prefs new file mode 100644 index 0000000..99bffe8 --- /dev/null +++ b/threema-connector/.settings/ch.ivyteam.ivy.designer.prefs @@ -0,0 +1,5 @@ +ch.ivyteam.ivy.designer.preferences.DataClassPreferencePage\:DEFAULT_DATA_CLASS=threema.connector.Data +ch.ivyteam.ivy.designer.preferences.DataClassPreferencePage\:DEFAULT_NAMESPACE=threema.connector +ch.ivyteam.ivy.project.preferences\:PRIMEFACES_VERSION=11 +ch.ivyteam.ivy.project.preferences\:PROJECT_VERSION=100000 +eclipse.preferences.version=1 diff --git a/threema-connector/.settings/org.eclipse.jdt.core.prefs b/threema-connector/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..d4540a5 --- /dev/null +++ b/threema-connector/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,10 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=17 +org.eclipse.jdt.core.compiler.compliance=17 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning +org.eclipse.jdt.core.compiler.release=enabled +org.eclipse.jdt.core.compiler.source=17 diff --git a/threema-connector/.settings/org.eclipse.wst.common.component b/threema-connector/.settings/org.eclipse.wst.common.component new file mode 100644 index 0000000..e3fa242 --- /dev/null +++ b/threema-connector/.settings/org.eclipse.wst.common.component @@ -0,0 +1,17 @@ + + + + + + + + + + + diff --git a/threema-connector/.settings/org.eclipse.wst.common.project.facet.core.prefs.xml b/threema-connector/.settings/org.eclipse.wst.common.project.facet.core.prefs.xml new file mode 100644 index 0000000..e725c8d --- /dev/null +++ b/threema-connector/.settings/org.eclipse.wst.common.project.facet.core.prefs.xml @@ -0,0 +1,8 @@ + + + + + + + diff --git a/threema-connector/.settings/org.eclipse.wst.common.project.facet.core.xml b/threema-connector/.settings/org.eclipse.wst.common.project.facet.core.xml new file mode 100644 index 0000000..3bb273d --- /dev/null +++ b/threema-connector/.settings/org.eclipse.wst.common.project.facet.core.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/threema-connector/.settings/org.eclipse.wst.css.core.prefs b/threema-connector/.settings/org.eclipse.wst.css.core.prefs new file mode 100644 index 0000000..5ddc6bd --- /dev/null +++ b/threema-connector/.settings/org.eclipse.wst.css.core.prefs @@ -0,0 +1,2 @@ +css-profile/=org.eclipse.wst.css.core.cssprofile.css3 +eclipse.preferences.version=1 diff --git a/threema-connector/.settings/org.eclipse.wst.jsdt.ui.superType.container b/threema-connector/.settings/org.eclipse.wst.jsdt.ui.superType.container new file mode 100644 index 0000000..3bd5d0a --- /dev/null +++ b/threema-connector/.settings/org.eclipse.wst.jsdt.ui.superType.container @@ -0,0 +1 @@ +org.eclipse.wst.jsdt.launching.baseBrowserLibrary \ No newline at end of file diff --git a/threema-connector/.settings/org.eclipse.wst.jsdt.ui.superType.name b/threema-connector/.settings/org.eclipse.wst.jsdt.ui.superType.name new file mode 100644 index 0000000..05bd71b --- /dev/null +++ b/threema-connector/.settings/org.eclipse.wst.jsdt.ui.superType.name @@ -0,0 +1 @@ +Window \ No newline at end of file diff --git a/threema-connector/config/custom-fields.yaml b/threema-connector/config/custom-fields.yaml new file mode 100644 index 0000000..bb20b70 --- /dev/null +++ b/threema-connector/config/custom-fields.yaml @@ -0,0 +1,22 @@ +# yaml-language-server: $schema=https://json-schema.axonivy.com/app/0.0.1/custom-fields.json +# +# == Custom Fields Information == +# +# You can define here your project custom fields. +# Have a look at our documentation for more information. +# +CustomFields: +# Tasks: +# MyTaskCustomField: +# Label: My task custom field +# Description: This new task custom field can be used to ... +# Type: STRING +# Cases: +# MyCaseCustomField: +# Label: My case custom field +# Description: This new case custom field can be used to ... +# Type: STRING +# Starts: +# MyStartCustomField: +# Label: My start custom field +# Description: This new start custom field can be used to ... diff --git a/threema-connector/config/databases.yaml b/threema-connector/config/databases.yaml new file mode 100644 index 0000000..10319e2 --- /dev/null +++ b/threema-connector/config/databases.yaml @@ -0,0 +1,2 @@ +# yaml-language-server: $schema=https://json-schema.axonivy.com/app/0.0.1/databases.json +Databases: diff --git a/threema-connector/config/overrides.any b/threema-connector/config/overrides.any new file mode 100644 index 0000000..f59ec20 --- /dev/null +++ b/threema-connector/config/overrides.any @@ -0,0 +1 @@ +* \ No newline at end of file diff --git a/threema-connector/config/persistence.xml b/threema-connector/config/persistence.xml new file mode 100644 index 0000000..d6b96d7 --- /dev/null +++ b/threema-connector/config/persistence.xml @@ -0,0 +1,2 @@ + + diff --git a/threema-connector/config/rest-clients.yaml b/threema-connector/config/rest-clients.yaml new file mode 100644 index 0000000..52b6940 --- /dev/null +++ b/threema-connector/config/rest-clients.yaml @@ -0,0 +1,6 @@ +RestClients: + ThreemaGateway: + UUID: af315689-b538-4142-a823-0632d66754d7 + Url: https://msgapi.threema.ch + Features: + - ch.ivyteam.ivy.rest.client.mapper.JsonFeature diff --git a/threema-connector/config/roles.xml b/threema-connector/config/roles.xml new file mode 100644 index 0000000..c7c6911 --- /dev/null +++ b/threema-connector/config/roles.xml @@ -0,0 +1,4 @@ + + + Everybody + diff --git a/threema-connector/config/users.xml b/threema-connector/config/users.xml new file mode 100644 index 0000000..1e173fa --- /dev/null +++ b/threema-connector/config/users.xml @@ -0,0 +1,2 @@ + + diff --git a/threema-connector/config/webservice-clients.yaml b/threema-connector/config/webservice-clients.yaml new file mode 100644 index 0000000..688047a --- /dev/null +++ b/threema-connector/config/webservice-clients.yaml @@ -0,0 +1,2 @@ +# yaml-language-server: $schema=https://json-schema.axonivy.com/app/0.0.1/webservice-clients.json +WebServiceClients: diff --git a/threema-connector/dataclasses/threema/connector/Data.ivyClass b/threema-connector/dataclasses/threema/connector/Data.ivyClass new file mode 100644 index 0000000..d6fb40b --- /dev/null +++ b/threema-connector/dataclasses/threema/connector/Data.ivyClass @@ -0,0 +1,2 @@ +Data #class +threema.connector #namespace diff --git a/threema-connector/dataclasses/threema/connector/ReceiverData.ivyClass b/threema-connector/dataclasses/threema/connector/ReceiverData.ivyClass new file mode 100644 index 0000000..a03b5eb --- /dev/null +++ b/threema-connector/dataclasses/threema/connector/ReceiverData.ivyClass @@ -0,0 +1,20 @@ +ReceiverData #class +threema.connector #namespace +identifier String #field +identifier PERSISTENT #fieldModifier +threemaId String #field +threemaId PERSISTENT #fieldModifier +type util.LookupType #field +type PERSISTENT #fieldModifier +publicKey String #field +publicKey PERSISTENT #fieldModifier +nonce String #field +nonce PERSISTENT #fieldModifier +encryptedMessage String #field +encryptedMessage PERSISTENT #fieldModifier +plainMessage String #field +plainMessage PERSISTENT #fieldModifier +messageJson String #field +messageJson PERSISTENT #fieldModifier +apiResponse String #field +apiResponse PERSISTENT #fieldModifier diff --git a/threema-connector/dataclasses/threema/connector/SendThreemaMessageData.ivyClass b/threema-connector/dataclasses/threema/connector/SendThreemaMessageData.ivyClass new file mode 100644 index 0000000..7ffa4ff --- /dev/null +++ b/threema-connector/dataclasses/threema/connector/SendThreemaMessageData.ivyClass @@ -0,0 +1,12 @@ +SendThreemaMessageData #class +threema.connector #namespace +receiver List #field +receiver PERSISTENT #fieldModifier +plainMessage String #field +plainMessage PERSISTENT #fieldModifier +receiverData List #field +receiverData PERSISTENT #fieldModifier +sendCount Number #field +sendCount PERSISTENT #fieldModifier +apiResponses List #field +apiResponses PERSISTENT #fieldModifier diff --git a/threema-connector/pom.xml b/threema-connector/pom.xml new file mode 100644 index 0000000..0278c8f --- /dev/null +++ b/threema-connector/pom.xml @@ -0,0 +1,59 @@ + + + 4.0.0 + com.axonivy.connector.threema + threema-connector + 10.0.0-SNAPSHOT + iar + + + + + com.axonivy.ivy.ci + project-build-plugin + 10.0.6 + true + + + org.apache.maven.plugins + maven-antrun-plugin + 3.1.0 + + + download-threema-msgapi-tool + validate + + run + + + + + + + + + + extract-threema-msgapi-tool + validate + + run + + + + + + + + + + + + + + diff --git a/threema-connector/processes/multipleRecipients.p.json b/threema-connector/processes/multipleRecipients.p.json new file mode 100644 index 0000000..5714346 --- /dev/null +++ b/threema-connector/processes/multipleRecipients.p.json @@ -0,0 +1,127 @@ +{ + "format" : "10.0.0", + "id" : "18B22DA4C8AA09A2", + "kind" : "CALLABLE_SUB", + "config" : { + "data" : "threema.connector.SendThreemaMessageData" + }, + "elements" : [ { + "id" : "f0", + "type" : "CallSubStart", + "name" : "call(String,List)", + "config" : { + "callSignature" : "call", + "input" : { + "params" : [ + { "name" : "plainMsg", "type" : "String" }, + { "name" : "receivers", "type" : "List" } + ], + "map" : { + "out.plainMessage" : "param.plainMsg", + "out.receiver" : "param.receivers" + } + }, + "result" : { + "params" : [ + { "name" : "apiResponse", "type" : "List" } + ], + "map" : { + "result.apiResponse" : "in.apiResponses" + } + }, + "tags" : "connector" + }, + "visual" : { + "at" : { "x" : 96, "y" : 64 }, + "description" : [ + "Subprocess to handle sending messages to multiple recipients", + "Requires a list of recipients and the unencrypted message" + ], + "icon" : "res:/webContent/icons/threema-icon_black.png?small" + }, + "connect" : { "id" : "f3", "to" : "f2" } + }, { + "id" : "f1", + "type" : "CallSubEnd", + "visual" : { + "at" : { "x" : 600, "y" : 64 } + } + }, { + "id" : "f2", + "type" : "Script", + "name" : "createReceiverData", + "config" : { + "output" : { + "map" : { + "out" : "in", + "out.sendCount" : "0" + }, + "code" : [ + "import util.LookupType;", + "import threema.connector.ReceiverData;", + "", + "import ch.ivyteam.ivy.environment.Ivy;", + "", + "for(String rec : in.receiver){", + " ReceiverData recDat = new ReceiverData();", + " recDat.plainMessage = in.plainMessage;", + " recDat.identifier = rec;", + " recDat.type = LookupType.getByPattern(rec);", + " out.receiverData.add(recDat);", + "}", + "", + "for(ReceiverData rec : out.receiverData){", + " Ivy.log().debug(rec.identifier + \" \" + rec.type + \" \" + rec.plainMessage);", + "}" + ] + } + }, + "visual" : { + "at" : { "x" : 288, "y" : 64 }, + "icon" : "res:/webContent/icons/threema-icon_black.png" + }, + "connect" : { "id" : "f4", "to" : "f6" } + }, { + "id" : "f6", + "type" : "Alternative", + "visual" : { + "at" : { "x" : 432, "y" : 64 }, + "description" : "send messages to each recipient" + }, + "connect" : [ + { "id" : "f11", "to" : "f7", "via" : [ { "x" : 528, "y" : 208 } ], "condition" : "in.sendCount < in.receiverData.size()" }, + { "id" : "f10", "to" : "f1" } + ] + }, { + "id" : "f7", + "type" : "SubProcessCall", + "name" : "singleRecipient", + "config" : { + "processCall" : "singleRecipient:call(String,String,util.LookupType)", + "output" : { + "map" : { + "out" : "in", + "out.sendCount" : "in.sendCount + 1" + }, + "code" : "out.apiResponses.add(result.apiResponse);" + }, + "call" : { + "params" : [ + { "name" : "plainMsg", "type" : "String" }, + { "name" : "receiverID", "type" : "String" }, + { "name" : "lookupType", "type" : "util.LookupType" } + ], + "map" : { + "param.plainMsg" : "in.plainMessage", + "param.receiverID" : "in.receiverData.get(in.sendCount).identifier", + "param.lookupType" : "in.receiverData.get(in.sendCount).type" + } + } + }, + "visual" : { + "at" : { "x" : 432, "y" : 208 }, + "icon" : "res:/webContent/icons/threema-icon_black.png" + }, + "connect" : { "id" : "f5", "to" : "f6", "via" : [ { "x" : 344, "y" : 208 } ] } + } ] +} \ No newline at end of file diff --git a/threema-connector/processes/singleRecipient.p.json b/threema-connector/processes/singleRecipient.p.json new file mode 100644 index 0000000..544ffa6 --- /dev/null +++ b/threema-connector/processes/singleRecipient.p.json @@ -0,0 +1,151 @@ +{ + "format" : "10.0.0", + "id" : "18B22C8212D554A9", + "kind" : "CALLABLE_SUB", + "config" : { + "data" : "threema.connector.ReceiverData" + }, + "elements" : [ { + "id" : "f0", + "type" : "CallSubStart", + "name" : "call(String,String,LookupType)", + "config" : { + "callSignature" : "call", + "input" : { + "params" : [ + { "name" : "plainMsg", "type" : "String" }, + { "name" : "receiverID", "type" : "String" }, + { "name" : "lookupType", "type" : "util.LookupType" } + ], + "map" : { + "out.identifier" : "param.receiverID", + "out.plainMessage" : "param.plainMsg", + "out.type" : "param.lookupType" + }, + "code" : [ + "import util.LookupType;", + "", + "if(param.lookupType == LookupType.PHONE){", + " out.identifier = param.receiverID.replaceAll(\" \",\"\").replaceAll(\"\\\\+\", \"\");", + "}else{", + " out.identifier = param.receiverID;", + "}" + ] + }, + "result" : { + "params" : [ + { "name" : "apiResponse", "type" : "String" } + ], + "map" : { + "result.apiResponse" : "in.apiResponse" + } + }, + "tags" : "connector" + }, + "visual" : { + "at" : { "x" : 40, "y" : 64 }, + "description" : "Subprocess to handle sending an encrypted message", + "icon" : "res:/webContent/icons/threema-icon_black.png?small" + }, + "connect" : { "id" : "f2", "to" : "f3" } + }, { + "id" : "f1", + "type" : "CallSubEnd", + "visual" : { + "at" : { "x" : 720, "y" : 64 } + } + }, { + "id" : "f3", + "type" : "SubProcessCall", + "name" : "getReceiverInfo", + "config" : { + "processCall" : "util/getReceiverInfo:call(threema.connector.ReceiverData)", + "output" : { + "map" : { + "out" : "result.receiverData" + } + }, + "call" : { + "params" : [ + { "name" : "receiverData", "type" : "threema.connector.ReceiverData" } + ], + "map" : { + "param.receiverData" : "in" + } + } + }, + "visual" : { + "at" : { "x" : 184, "y" : 64 }, + "description" : "lookup receiver info (threemaId & public key)", + "icon" : "res:/webContent/icons/threema-icon_black.png" + }, + "connect" : { "id" : "f9", "to" : "f5" } + }, { + "id" : "f4", + "type" : "SubProcessCall", + "name" : "messageEncryption", + "config" : { + "processCall" : "util/messageEncryption:call(threema.connector.ReceiverData)", + "output" : { + "map" : { + "out" : "result.receiverData" + } + }, + "call" : { + "params" : [ + { "name" : "receiverData", "type" : "threema.connector.ReceiverData" } + ], + "map" : { + "param.receiverData" : "in" + } + } + }, + "visual" : { + "at" : { "x" : 384, "y" : 64 }, + "description" : "encrypt the message with receivers public key", + "icon" : "res:/webContent/icons/threema-icon_black.png" + }, + "connect" : { "id" : "f7", "to" : "f6" } + }, { + "id" : "f6", + "type" : "SubProcessCall", + "name" : "send", + "config" : { + "processCall" : "util/sendMessage:call(threema.connector.ReceiverData)", + "output" : { + "map" : { + "out" : "in", + "out.apiResponse" : "result.receiverData.apiResponse" + } + }, + "call" : { + "params" : [ + { "name" : "receiverData", "type" : "threema.connector.ReceiverData" } + ], + "map" : { + "param.receiverData" : "in" + } + } + }, + "visual" : { + "at" : { "x" : 576, "y" : 64 }, + "description" : "send the encrypted message", + "icon" : "res:/webContent/icons/threema-icon_black.png" + }, + "connect" : { "id" : "f8", "to" : "f1" } + }, { + "id" : "f5", + "type" : "Alternative", + "visual" : { + "at" : { "x" : 288, "y" : 64 } + }, + "connect" : [ + { "id" : "f12", "to" : "f1", "via" : [ { "x" : 288, "y" : 144 }, { "x" : 720, "y" : 144 } ], "label" : { + "name" : "Skip if lookup failed", + "segment" : 0.5, + "offset" : { "x" : 217, "y" : 30 } + }, "condition" : "!in.apiResponse.contains(\"200\")" }, + { "id" : "f11", "to" : "f4" } + ] + } ] +} \ No newline at end of file diff --git a/threema-connector/processes/util/getReceiverInfo.p.json b/threema-connector/processes/util/getReceiverInfo.p.json new file mode 100644 index 0000000..25a794d --- /dev/null +++ b/threema-connector/processes/util/getReceiverInfo.p.json @@ -0,0 +1,127 @@ +{ + "format" : "10.0.0", + "id" : "18B22C967B82A625", + "kind" : "CALLABLE_SUB", + "config" : { + "data" : "threema.connector.ReceiverData" + }, + "elements" : [ { + "id" : "f0", + "type" : "CallSubStart", + "name" : "call(receiverData)", + "config" : { + "callSignature" : "call", + "input" : { + "params" : [ + { "name" : "receiverData", "type" : "threema.connector.ReceiverData" } + ], + "map" : { + "out" : "param.receiverData", + "out.threemaId" : "param.receiverData.identifier" + } + }, + "result" : { + "params" : [ + { "name" : "receiverData", "type" : "threema.connector.ReceiverData" } + ], + "map" : { + "result.receiverData" : "in" + } + } + }, + "visual" : { + "at" : { "x" : 96, "y" : 64 }, + "icon" : "res:/webContent/icons/threema-icon_black.png?small" + }, + "connect" : { "id" : "f2", "to" : "f7" } + }, { + "id" : "f1", + "type" : "CallSubEnd", + "visual" : { + "at" : { "x" : 808, "y" : 64 } + } + }, { + "id" : "f3", + "type" : "RestClientCall", + "name" : "LookupId", + "config" : { + "path" : "/lookup/{type}/{id}", + "clientId" : "af315689-b538-4142-a823-0632d66754d7", + "clientErrorCode" : "ivy:error:rest:client", + "queryParams" : { + "secret" : "ivy.var.threemaConnector_secret", + "from" : "ivy.var.threemaConnector_threemaId" + }, + "statusErrorCode" : ">> Ignore status", + "responseMapping" : { + "out" : "in", + "out.apiResponse" : "\"ID-Lookup: \" + response.getStatus().toString()", + "out.threemaId" : "result" + }, + "templateParams" : { + "id" : "in.identifier", + "type" : "in.type.toString()" + }, + "resultType" : "java.lang.String" + }, + "visual" : { + "at" : { "x" : 336, "y" : 64 }, + "icon" : "res:/webContent/icons/threema-icon_black.png" + }, + "connect" : { "id" : "f8", "to" : "f4" } + }, { + "id" : "f6", + "type" : "RestClientCall", + "name" : "LookupPubKey", + "config" : { + "path" : "/pubkeys/{threemaId}", + "clientId" : "af315689-b538-4142-a823-0632d66754d7", + "clientErrorCode" : "ivy:error:rest:client", + "queryParams" : { + "from" : "ivy.var.threemaConnector_threemaId", + "secret" : "ivy.var.threemaConnector_secret" + }, + "statusErrorCode" : ">> Ignore status", + "responseMapping" : { + "out" : "in", + "out.apiResponse" : "\"PublicKey-Lookup: \" + response.getStatus().toString()", + "out.publicKey" : "result" + }, + "templateParams" : { + "threemaId" : "in.threemaId" + }, + "resultType" : "java.lang.String" + }, + "visual" : { + "at" : { "x" : 648, "y" : 64 }, + "icon" : "res:/webContent/icons/threema-icon_black.png" + }, + "connect" : { "id" : "f5", "to" : "f1" } + }, { + "id" : "f7", + "type" : "Alternative", + "visual" : { + "at" : { "x" : 176, "y" : 64 } + }, + "connect" : [ + { "id" : "f10", "to" : "f6", "via" : [ { "x" : 176, "y" : 136 }, { "x" : 648, "y" : 136 } ], "label" : { + "name" : "Skip if ThreemaID is known", + "segment" : 2.14, + "offset" : { "x" : -224, "y" : 7 } + }, "condition" : "in.type == util.LookupType.THREEMAID" }, + { "id" : "f9", "to" : "f3" } + ] + }, { + "id" : "f4", + "type" : "Alternative", + "visual" : { + "at" : { "x" : 512, "y" : 64 } + }, + "connect" : [ + { "id" : "f13", "to" : "f1", "via" : [ { "x" : 512, "y" : 0 }, { "x" : 808, "y" : 0 } ], "label" : { + "name" : "Skip if lookup failed" + }, "condition" : "!in.apiResponse.contains(\"200\")" }, + { "id" : "f12", "to" : "f6" } + ] + } ] +} \ No newline at end of file diff --git a/threema-connector/processes/util/messageEncryption.p.json b/threema-connector/processes/util/messageEncryption.p.json new file mode 100644 index 0000000..88e014f --- /dev/null +++ b/threema-connector/processes/util/messageEncryption.p.json @@ -0,0 +1,64 @@ +{ + "format" : "10.0.0", + "id" : "18B22CD369A6089F", + "kind" : "CALLABLE_SUB", + "config" : { + "data" : "threema.connector.ReceiverData" + }, + "elements" : [ { + "id" : "f0", + "type" : "CallSubStart", + "name" : "call(receiverData)", + "config" : { + "callSignature" : "call", + "input" : { + "params" : [ + { "name" : "receiverData", "type" : "threema.connector.ReceiverData" } + ], + "map" : { + "out" : "param.receiverData" + } + }, + "result" : { + "params" : [ + { "name" : "receiverData", "type" : "threema.connector.ReceiverData" } + ], + "map" : { + "result.receiverData" : "in" + } + } + }, + "visual" : { + "at" : { "x" : 96, "y" : 64 }, + "icon" : "res:/webContent/icons/threema-icon_black.png?small" + }, + "connect" : { "id" : "f4", "to" : "f2" } + }, { + "id" : "f1", + "type" : "CallSubEnd", + "visual" : { + "at" : { "x" : 480, "y" : 64 } + } + }, { + "id" : "f2", + "type" : "Script", + "name" : "Encrypt Message", + "config" : { + "output" : { + "code" : [ + "import util.MessageEncryptor;", + "import util.MessageEncryptor.EncryptionResult;", + "", + "EncryptionResult result = MessageEncryptor.encrypt(in.publicKey, in.plainMessage);", + "out.encryptedMessage = result.encryptedMessage();", + "out.nonce = result.nonce();" + ] + } + }, + "visual" : { + "at" : { "x" : 288, "y" : 64 }, + "icon" : "res:/webContent/icons/threema-icon_black.png" + }, + "connect" : { "id" : "f3", "to" : "f1" } + } ] +} \ No newline at end of file diff --git a/threema-connector/processes/util/sendMessage.p.json b/threema-connector/processes/util/sendMessage.p.json new file mode 100644 index 0000000..32439a5 --- /dev/null +++ b/threema-connector/processes/util/sendMessage.p.json @@ -0,0 +1,78 @@ +{ + "format" : "10.0.0", + "id" : "18B22CED0FA1555D", + "kind" : "CALLABLE_SUB", + "config" : { + "data" : "threema.connector.ReceiverData" + }, + "elements" : [ { + "id" : "f0", + "type" : "CallSubStart", + "name" : "call(receiverData)", + "config" : { + "callSignature" : "call", + "input" : { + "params" : [ + { "name" : "receiverData", "type" : "threema.connector.ReceiverData" } + ], + "map" : { + "out" : "param.receiverData" + } + }, + "result" : { + "params" : [ + { "name" : "receiverData", "type" : "threema.connector.ReceiverData" } + ], + "map" : { + "result.receiverData" : "in" + } + } + }, + "visual" : { + "at" : { "x" : 96, "y" : 64 }, + "icon" : "res:/webContent/icons/threema-icon_black.png?small" + }, + "connect" : { "id" : "f4", "to" : "f2" } + }, { + "id" : "f1", + "type" : "CallSubEnd", + "visual" : { + "at" : { "x" : 424, "y" : 64 } + } + }, { + "id" : "f2", + "type" : "RestClientCall", + "name" : "sendMessage", + "config" : { + "bodyForm" : { + "from" : "ivy.var.threemaConnector_threemaId", + "to" : "in.threemaId", + "nonce" : "in.nonce", + "box" : "in.encryptedMessage", + "secret" : "ivy.var.threemaConnector_secret", + "" : "" + }, + "path" : "send_e2e", + "headers" : { + "Accept" : "*/*", + "X-Requested-By" : "\"ivy\"" + }, + "clientId" : "af315689-b538-4142-a823-0632d66754d7", + "clientErrorCode" : "ivy:error:rest:client", + "method" : "POST", + "statusErrorCode" : ">> Ignore status", + "responseMapping" : { + "out" : "in", + "out.apiResponse" : "response.getStatus() == 200 ? \"Sent successfully (\" + response.getStatus() + \")\" : \"Error while sending (\" + response.getStatus() + \")\"" + }, + "resultType" : "java.lang.String", + "bodyInputType" : "FORM", + "bodyMediaType" : "application/x-www-form-urlencoded" + }, + "visual" : { + "at" : { "x" : 264, "y" : 64 }, + "icon" : "res:/webContent/icons/threema-icon_black.png" + }, + "connect" : { "id" : "f3", "to" : "f1" } + } ] +} \ No newline at end of file diff --git a/threema-connector/src/util/LookupType.java b/threema-connector/src/util/LookupType.java new file mode 100644 index 0000000..d7a85c8 --- /dev/null +++ b/threema-connector/src/util/LookupType.java @@ -0,0 +1,32 @@ +package util; +public enum LookupType { + + PHONE, EMAIL, THREEMAID, INVALID; + + @Override + public String toString() { + return this.name().toLowerCase(); + } + + public static LookupType getByString(String id) { + return switch (id.toLowerCase()) { + case "phone" -> LookupType.PHONE; + case "email" -> LookupType.EMAIL; + case "threemaid" -> LookupType.THREEMAID; + default -> LookupType.INVALID; + }; + } + + public static LookupType getByPattern(String id) { + LookupType type = LookupType.INVALID; + id = id.replaceAll(" ", ""); + if (id.lastIndexOf('@') < id.lastIndexOf('.')) { + type = LookupType.EMAIL; + } else if (id.matches("\\+?\\d{11}")) { + type = LookupType.PHONE; + } else { + type = LookupType.THREEMAID; + } + return type; + } +} diff --git a/threema-connector/src/util/MessageEncryptor.java b/threema-connector/src/util/MessageEncryptor.java new file mode 100644 index 0000000..cf90394 --- /dev/null +++ b/threema-connector/src/util/MessageEncryptor.java @@ -0,0 +1,24 @@ +package util; + +import javax.xml.bind.DatatypeConverter; +import ch.ivyteam.ivy.environment.Ivy; +import ch.threema.apitool.CryptTool; +import ch.threema.apitool.results.EncryptResult; + + + +public class MessageEncryptor { + public record EncryptionResult(String encryptedMessage, String nonce) {} + public static EncryptionResult encrypt(String publicKey, String msg) { + + byte[] encPrivKey = DatatypeConverter.parseHexBinary(Ivy.var().get("threemaConnector.privateKey")); + byte[] encPubKey = DatatypeConverter.parseHexBinary(publicKey); + + EncryptResult result = CryptTool.encryptTextMessage(msg, encPrivKey, encPubKey); + + String encryptedMessage = DatatypeConverter.printHexBinary(result.getResult()); + String nonce = DatatypeConverter.printHexBinary(result.getNonce()); + return new EncryptionResult(encryptedMessage, nonce); + } + +} diff --git a/threema-connector/webContent/icons/threema-icon_black.png b/threema-connector/webContent/icons/threema-icon_black.png new file mode 100644 index 0000000..ba0ef33 Binary files /dev/null and b/threema-connector/webContent/icons/threema-icon_black.png differ