From 0092008ce02853790dbde89e24d5102927d2ed82 Mon Sep 17 00:00:00 2001 From: sandradeng20 Date: Tue, 5 Mar 2024 11:37:28 +0800 Subject: [PATCH 01/16] 1771-dev-user-agent: init user agent --- Agents/UserAgent/.dockerignore | 2 + Agents/UserAgent/.gitignore | 1 + Agents/UserAgent/.m2/settings-security.xml | 3 + Agents/UserAgent/.m2/settings.xml | 47 +++ Agents/UserAgent/Dockerfile | 34 ++ Agents/UserAgent/README.md | 49 +++ Agents/UserAgent/UserAgent/WEB-INF/web.xml | 17 + Agents/UserAgent/UserAgent/pom.xml | 324 ++++++++++++++++++ .../jps/agent/useragent/EndpointConfig.java | 51 +++ .../jps/agent/useragent/KGQueryClient.java | 30 ++ .../cares/jps/agent/useragent/UserAgent.java | 71 ++++ Agents/UserAgent/credentials/.gitignore | 2 + Agents/UserAgent/docker-compose-build.yml | 4 + Agents/UserAgent/docker-compose-debug.yml | 9 + Agents/UserAgent/docker-compose-stack.yml | 43 +++ Agents/UserAgent/docker-compose.yml | 6 + Agents/UserAgent/docker/entrypoint.sh | 7 + .../inputs/config/data/user.obda | 16 + .../config/services/user-agent-debug.json | 49 +++ .../inputs/config/services/user-agent.json | 46 +++ Agents/UserAgent/stack.sh | 9 + 21 files changed, 820 insertions(+) create mode 100644 Agents/UserAgent/.dockerignore create mode 100644 Agents/UserAgent/.gitignore create mode 100644 Agents/UserAgent/.m2/settings-security.xml create mode 100644 Agents/UserAgent/.m2/settings.xml create mode 100644 Agents/UserAgent/Dockerfile create mode 100644 Agents/UserAgent/README.md create mode 100644 Agents/UserAgent/UserAgent/WEB-INF/web.xml create mode 100644 Agents/UserAgent/UserAgent/pom.xml create mode 100644 Agents/UserAgent/UserAgent/src/main/java/uk/ac/cam/cares/jps/agent/useragent/EndpointConfig.java create mode 100644 Agents/UserAgent/UserAgent/src/main/java/uk/ac/cam/cares/jps/agent/useragent/KGQueryClient.java create mode 100644 Agents/UserAgent/UserAgent/src/main/java/uk/ac/cam/cares/jps/agent/useragent/UserAgent.java create mode 100644 Agents/UserAgent/credentials/.gitignore create mode 100644 Agents/UserAgent/docker-compose-build.yml create mode 100644 Agents/UserAgent/docker-compose-debug.yml create mode 100644 Agents/UserAgent/docker-compose-stack.yml create mode 100644 Agents/UserAgent/docker-compose.yml create mode 100644 Agents/UserAgent/docker/entrypoint.sh create mode 100644 Agents/UserAgent/stack-manager-config/inputs/config/data/user.obda create mode 100644 Agents/UserAgent/stack-manager-config/inputs/config/services/user-agent-debug.json create mode 100644 Agents/UserAgent/stack-manager-config/inputs/config/services/user-agent.json create mode 100644 Agents/UserAgent/stack.sh diff --git a/Agents/UserAgent/.dockerignore b/Agents/UserAgent/.dockerignore new file mode 100644 index 00000000000..58d58a3bf5b --- /dev/null +++ b/Agents/UserAgent/.dockerignore @@ -0,0 +1,2 @@ +Dockerfile +docker-compose.yml \ No newline at end of file diff --git a/Agents/UserAgent/.gitignore b/Agents/UserAgent/.gitignore new file mode 100644 index 00000000000..499adf970ce --- /dev/null +++ b/Agents/UserAgent/.gitignore @@ -0,0 +1 @@ +*log4j2.xml \ No newline at end of file diff --git a/Agents/UserAgent/.m2/settings-security.xml b/Agents/UserAgent/.m2/settings-security.xml new file mode 100644 index 00000000000..88c4e581833 --- /dev/null +++ b/Agents/UserAgent/.m2/settings-security.xml @@ -0,0 +1,3 @@ + + MASTER_PASSWORD + diff --git a/Agents/UserAgent/.m2/settings.xml b/Agents/UserAgent/.m2/settings.xml new file mode 100644 index 00000000000..4ba3c9e3fd4 --- /dev/null +++ b/Agents/UserAgent/.m2/settings.xml @@ -0,0 +1,47 @@ + + + ${user.home}/.m2/repository + + + false + + + false + + + false + + + + + repo + REPO_USERNAME + REPO_PASSWORD + + + + + + Default Profile + + + + repo + https://maven.pkg.github.com/cambridge-cares/TheWorldAvatar/ + default + + true + + + true + + + + + + + + + Default Profile + + \ No newline at end of file diff --git a/Agents/UserAgent/Dockerfile b/Agents/UserAgent/Dockerfile new file mode 100644 index 00000000000..d1bdb68be25 --- /dev/null +++ b/Agents/UserAgent/Dockerfile @@ -0,0 +1,34 @@ +# First stage: build war file +#================================================================================================== +FROM maven:3.6-openjdk-11-slim as builder + +# Copy all files into root's home, including the source, pom file, ./m2 directory and credentials +ADD . /root + +# Populate settings templates with credentials, repo name +WORKDIR /root/.m2 +# (Note that | rather than / is used as the sed delimiter, since encrypted passwords can contain the latter, but not the former +RUN sed -i "s|MASTER_PASSWORD|$(mvn --encrypt-master-password master_password)|" settings-security.xml +RUN sed -i "s|REPO_USERNAME|$(cat ../credentials/repo_username.txt)|;s|REPO_PASSWORD|$(cat ../credentials/repo_password.txt|xargs mvn --encrypt-password)|" settings.xml + + +# Build +WORKDIR /root/trajectoryqueryagent +RUN --mount=type=cache,target=/root/.m2/repository mvn package +#================================================================================================== + +# Second stage: copy the downloaded dependency into a new image and build into an app +#================================================================================================== +FROM tomcat:9.0 as agent + +WORKDIR /root/trajectoryqueryagent + +# #================================================================================================== +# Copy the compiled jar from the builder +COPY --from=builder /root/trajectoryqueryagent/output/user-agent##1.0.0.war $CATALINA_HOME/webapps/ +COPY ./docker/entrypoint.sh entrypoint.sh + +# Port for Java debugging +EXPOSE 5005 + +ENTRYPOINT ["./entrypoint.sh"] \ No newline at end of file diff --git a/Agents/UserAgent/README.md b/Agents/UserAgent/README.md new file mode 100644 index 00000000000..467637b48f6 --- /dev/null +++ b/Agents/UserAgent/README.md @@ -0,0 +1,49 @@ +# UserAgent +## 1. Description + +## 2. Pre-requisites + + + +## 3. Agent Configuration + + +## 4. Deploy +### 4.1 Retrieving TrajectoryQueryAgent's image +The TrajectoryQueryAgent should be pulled automatically with the stack-manager, if not you can pull the latest version from [cambridge_cares package](https://github.com/orgs/cambridge-cares/packages/container/package/trajectoryqueryagent) using `docker pull ghcr.io/cambridge-cares/trajectoryqueryagent:` + +### 4.2 Starting with the stack-manager +The agent has been implemented to work in the stack, which requires the TrajectoryQueryAgent Docker container to be deployed in the stack. To do so, place [trajectoryqueryagent.json](stack-manager-config/inputs/config/services/user-agent.json) in the [stack-manager config directory]. + +Then, run `./stack.sh start ` in the [stack-manager] main folder. This will spin up the agent in the stack. + +### 4.3 Configuring AccessAgent endpoints +On this same directory run, replace `STACK-NAME` with your stack-manager name. +``` +./copy.sh start +``` + +### 4.4 Start recording +Once all the configurations and server has been set, press the Start Recording button inside the SensorLogger mobile app to begin session. + +## 5. Build and debug +## 5.1 Credentials +The docker image uses TheWorldAvatar maven repository (`https://maven.pkg.github.com/cambridge-cares/TheWorldAvatar/`). +You will need to provide your credentials (GitHub username/personal access token) in single-word text files as follows: +``` +./credentials/ + repo_username.txt + repo_password.txt +``` + +### 5.2 Building Docker Image +In the same directory as this README, run `./stack.sh build`. This will build the TrajectoryQueryAgent local Docker Image. + +### 5.2 Spinning up with stack-manager +To debug the agent, replace [`trajectoryqueryagent-debug.json`](stack-manager-config/inputs/config/services/user-agent-debug.json) instead of [`trajectoryqueryagent.json`](stack-manager-config/inputs/config/services/user-agent.json) in the [stack-manager config directory]. + +Spin up with `./stack.sh start ` in the [stack-manager]'s main folder. +The debugger port will be available at 5005. + +[stack-manager]: https://github.com/cambridge-cares/TheWorldAvatar/tree/main/Deploy/stacks/dynamic/stack-manager +[stack-manager config directory]: https://github.com/cambridge-cares/TheWorldAvatar/tree/main/Deploy/stacks/dynamic/stack-manager/inputs/config/services \ No newline at end of file diff --git a/Agents/UserAgent/UserAgent/WEB-INF/web.xml b/Agents/UserAgent/UserAgent/WEB-INF/web.xml new file mode 100644 index 00000000000..796e944df52 --- /dev/null +++ b/Agents/UserAgent/UserAgent/WEB-INF/web.xml @@ -0,0 +1,17 @@ + + + UserAgent + A java agent for manage user related data. + + + UserAgent + uk.ac.cam.cares.jps.agent + + + + UserAgent + / + + + + \ No newline at end of file diff --git a/Agents/UserAgent/UserAgent/pom.xml b/Agents/UserAgent/UserAgent/pom.xml new file mode 100644 index 00000000000..ce1fc6e517d --- /dev/null +++ b/Agents/UserAgent/UserAgent/pom.xml @@ -0,0 +1,324 @@ + + + 4.0.0 + uk.ac.cam.cares.jps + user-agent + 1.0.0 + war + + + 11 + 11 + UTF-8 + + + 1.39.1 + + + + + + uk.ac.cam.cares.jps + jps-parent-pom + 2.2.0 + + + + + + + dev-profile + + true + + + + java-logging-dev + + + + + + prod-profile + + + java-logging-prod + + + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.7.0 + + ${maven.compiler.source} + ${maven.compiler.target} + + + + + + org.codehaus.mojo + exec-maven-plugin + 1.6.0 + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.22.0 + + + + + org.apache.maven.plugins + maven-war-plugin + 3.3.1 + + + + + org.apache.maven.plugins + maven-dependency-plugin + 3.2.0 + + + + + + + + + + + + + uk.ac.cam.cares.jps + jps-base-lib + ${jps.base.version} + + + + + org.springframework + spring-core + 6.0.5 + + + + org.apache.jena + jena-core + + + + + org.apache.jena + jena-jdbc-core + + + + + org.apache.jena + jena-jdbc-driver-remote + + + + + + + org.apache.jena + jena-jdbc-driver-bundle + 4.6.1 + + + + org.apache.jena + jena + 4.6.1 + pom + + + + uk.ac.cam.cares.downsampling + downsampling + 1.0.0 + + + + + + + + + javax.servlet + javax.servlet-api + + + + + org.json + json + 20180813 + jar + + + + + + org.apache.logging.log4j + log4j-api + 2.14.1 + + + org.apache.logging.log4j + log4j-core + 2.14.1 + + + org.apache.logging.log4j + log4j-web + 2.14.1 + + + + + org.junit.jupiter + junit-jupiter-api + + + org.junit.jupiter + junit-jupiter-engine + + + + org.apache.jena + jena-geosparql + 4.1.0 + + + + + + + + + org.postgresql + postgresql + 42.5.4 + + + + + + + + com.cmclinnovations + stack-clients + 1.14.1 + + + + + org.projectlombok + lombok + 1.18.22 + provided + + + + uk.ac.cam.cares.ogm + ogm + 1.1.1 + + + + org.testng + testng + 7.6.1 + test + + + + + + + + + + org.apache.jena + jena-arq + 4.6.1 + + + + org.apache.jena + jena-core + 4.6.1 + + + org.apache.tomcat + tomcat-catalina + 9.0.56 + + + + org.apache.jena + jena-jdbc-driver-remote + 4.5.0 + + + + + org.apache.jena + jena-jdbc-core + 4.5.0 + + + + org.apache.jena + jena-jdbc-driver-mem + 4.6.1 + + + + + com.fasterxml.jackson.module + jackson-module-jaxb-annotations + 2.10.3 + + + + org.apache.jena + jena-shaded-guava + 3.1.1 + + + + + + + \ No newline at end of file diff --git a/Agents/UserAgent/UserAgent/src/main/java/uk/ac/cam/cares/jps/agent/useragent/EndpointConfig.java b/Agents/UserAgent/UserAgent/src/main/java/uk/ac/cam/cares/jps/agent/useragent/EndpointConfig.java new file mode 100644 index 00000000000..4122882255f --- /dev/null +++ b/Agents/UserAgent/UserAgent/src/main/java/uk/ac/cam/cares/jps/agent/useragent/EndpointConfig.java @@ -0,0 +1,51 @@ +package uk.ac.cam.cares.jps.agent.useragent; + +import com.cmclinnovations.stack.clients.blazegraph.BlazegraphEndpointConfig; +import com.cmclinnovations.stack.clients.docker.ContainerClient; +import com.cmclinnovations.stack.clients.ontop.OntopEndpointConfig; +import com.cmclinnovations.stack.clients.postgis.PostGISEndpointConfig; + +public class EndpointConfig { + private String kgurl; + private String kguser; + private String kgpassword; + + private String ontopurl; + + private String dbuser; + private String dbpassword; + private PostGISEndpointConfig postGISEndpointConfig; + + public EndpointConfig() { + ContainerClient containerClient = new ContainerClient(); + BlazegraphEndpointConfig blazegraphEndpointConfig = containerClient.readEndpointConfig("blazegraph", + BlazegraphEndpointConfig.class); + this.kgurl = blazegraphEndpointConfig.getUrl("kb"); + this.kguser = blazegraphEndpointConfig.getUsername(); + this.kgpassword = blazegraphEndpointConfig.getPassword(); + + OntopEndpointConfig ontopEndpointConfig = containerClient.readEndpointConfig("ontop", OntopEndpointConfig.class); + this.ontopurl = ontopEndpointConfig.getUrl(); + + postGISEndpointConfig = containerClient.readEndpointConfig("postgis", + PostGISEndpointConfig.class); + this.dbuser = postGISEndpointConfig.getUsername(); + this.dbpassword = postGISEndpointConfig.getPassword(); + } + public String getKgurl() { + return this.kgurl; + } + public String getOntopurl() { return this.ontopurl; } + public String getDburl() { + return postGISEndpointConfig.getJdbcURL("postgres"); + } + public String getDburl(String database) { + return postGISEndpointConfig.getJdbcURL(database); + } + public String getDbuser() { + return this.dbuser; + } + public String getDbpassword() { + return this.dbpassword; + } +} diff --git a/Agents/UserAgent/UserAgent/src/main/java/uk/ac/cam/cares/jps/agent/useragent/KGQueryClient.java b/Agents/UserAgent/UserAgent/src/main/java/uk/ac/cam/cares/jps/agent/useragent/KGQueryClient.java new file mode 100644 index 00000000000..391b8449450 --- /dev/null +++ b/Agents/UserAgent/UserAgent/src/main/java/uk/ac/cam/cares/jps/agent/useragent/KGQueryClient.java @@ -0,0 +1,30 @@ +package uk.ac.cam.cares.jps.agent.useragent; + +import org.apache.jena.sparql.core.Var; + +import uk.ac.cam.cares.jps.base.query.RemoteStoreClient; + +public class KGQueryClient { + + private RemoteStoreClient storeClient; + private String ontopEndpoint; + // Prefixes + static final String ONTOSLMA = "https://www.theworldavatar.com/kg/ontosensorloggermobileapp/"; + static final String SLA = "https://www.theworldavatar.com/kg/sensorloggerapp/"; + static final String OM = "http://www.ontology-of-units-of-measure.org/resource/om-2/"; + static final String SF ="http://www.opengis.net/ont/sf#"; + static final String ONTODEVICE = "https://www.theworldavatar.com/kg/ontodevice/"; + static final String MON = "https://w3id.org/MON/person.owl"; + static final String SAREF="https://saref.etsi.org/core/"; + static final String RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#"; + final static String str_s = "s"; + final static Var VAR_S = Var.alloc(str_s); + final static String str_o = "o"; + final static Var VAR_O = Var.alloc(str_o); + + public KGQueryClient(RemoteStoreClient storeClient, String ontopEndpoint) { + this.storeClient = storeClient; + this.ontopEndpoint = ontopEndpoint; + } + +} diff --git a/Agents/UserAgent/UserAgent/src/main/java/uk/ac/cam/cares/jps/agent/useragent/UserAgent.java b/Agents/UserAgent/UserAgent/src/main/java/uk/ac/cam/cares/jps/agent/useragent/UserAgent.java new file mode 100644 index 00000000000..e788c54c4d5 --- /dev/null +++ b/Agents/UserAgent/UserAgent/src/main/java/uk/ac/cam/cares/jps/agent/useragent/UserAgent.java @@ -0,0 +1,71 @@ +package uk.ac.cam.cares.jps.agent.useragent; + +import com.cmclinnovations.stack.clients.ontop.OntopClient; +import org.apache.log4j.LogManager; +import org.apache.log4j.Logger; +import org.json.JSONArray; +import org.json.JSONObject; +import uk.ac.cam.cares.jps.base.agent.JPSAgent; +import uk.ac.cam.cares.jps.base.query.RemoteRDBStoreClient; +import uk.ac.cam.cares.jps.base.query.RemoteStoreClient; + +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServletRequest; + +import java.nio.file.Path; + + +@WebServlet(urlPatterns = "/registerPhone") + +public class UserAgent extends JPSAgent { + private KGQueryClient kgQueryClient; + private RemoteStoreClient storeClient; + private RemoteRDBStoreClient timelineRdbClient; + private final Logger LOGGER = LogManager.getLogger(UserAgent.class); + + private static final Path obdaFile = Path.of("/inputs/user.obda"); + + public void init() { + EndpointConfig endpointConfig = new EndpointConfig(); + storeClient = new RemoteStoreClient(endpointConfig.getKgurl(), endpointConfig.getKgurl()); + kgQueryClient = new KGQueryClient(storeClient, endpointConfig.getOntopurl()); + + initTimelineDatabase(endpointConfig); + timelineRdbClient = new RemoteRDBStoreClient(endpointConfig.getDburl("timeline"), endpointConfig.getDbuser(), endpointConfig.getDbpassword()); + initPhoneTable(); + + try { + OntopClient ontopClient = OntopClient.getInstance(); + ontopClient.updateOBDA(obdaFile); + } catch (Exception e) { + System.out.println("Could not retrieve user.obda file."); + } + } + + private void initTimelineDatabase(EndpointConfig endpointConfig) { + RemoteRDBStoreClient postgresRdbClient = new RemoteRDBStoreClient(endpointConfig.getDburl(), endpointConfig.getDbuser(), endpointConfig.getDbpassword()); + JSONArray result = postgresRdbClient.executeQuery("SELECT datname FROM pg_database WHERE datname = 'timeline';"); + if (!result.isEmpty()) { + return; + } + + postgresRdbClient.executeUpdate("CREATE DATABASE timeline;"); + } + + private void initPhoneTable() { + timelineRdbClient.executeUpdate("CREATE TABLE IF NOT EXISTS 'timeline'.'smartPhone' (" + + "phone_id CHAR(36) PRIMARY KEY," + + "user_id CHAR(36)"); + } + + @Override + public JSONObject processRequestParameters(JSONObject requestParams, HttpServletRequest request) { + return processRequestParameters(requestParams); + } + + @Override + public JSONObject processRequestParameters(JSONObject requestParams) { + return new JSONObject(); + } + +} \ No newline at end of file diff --git a/Agents/UserAgent/credentials/.gitignore b/Agents/UserAgent/credentials/.gitignore new file mode 100644 index 00000000000..76b47e66d59 --- /dev/null +++ b/Agents/UserAgent/credentials/.gitignore @@ -0,0 +1,2 @@ +repo_password +repo_username \ No newline at end of file diff --git a/Agents/UserAgent/docker-compose-build.yml b/Agents/UserAgent/docker-compose-build.yml new file mode 100644 index 00000000000..99f4f0de6a8 --- /dev/null +++ b/Agents/UserAgent/docker-compose-build.yml @@ -0,0 +1,4 @@ +version: '3.8' +services: + user-agent: + build: . diff --git a/Agents/UserAgent/docker-compose-debug.yml b/Agents/UserAgent/docker-compose-debug.yml new file mode 100644 index 00000000000..66ed671d199 --- /dev/null +++ b/Agents/UserAgent/docker-compose-debug.yml @@ -0,0 +1,9 @@ +version: '3.8' +services: + user-agent: + environment: + - JPDA_ADDRESS=0.0.0.0:5005 + - JPDA_TRANSPORT=dt_socket + - DEBUG=ON + ports: + - "${DEBUG_PORT}:5005" diff --git a/Agents/UserAgent/docker-compose-stack.yml b/Agents/UserAgent/docker-compose-stack.yml new file mode 100644 index 00000000000..a2b16727380 --- /dev/null +++ b/Agents/UserAgent/docker-compose-stack.yml @@ -0,0 +1,43 @@ +version: '3.8' +services: + user-agent: + deploy: + mode: replicated + replicas: 1 + restart_policy: + condition: none + security_opt: + - label=disable + volumes: + - scratch:/stack_scratch + - /var/run/docker.sock:/var/run/docker.sock + networks: + - stack + +volumes: + scratch: + name: ${STACK_NAME}_scratch + labels: + - com.docker.stack.namespace:${STACK_NAME} + +configs: + postgis: + name: ${STACK_NAME}_postgis + external: true + blazegraph: + name: ${STACK_NAME}_blazegraph + external: true + ontop: + name: ${STACK_NAME}_ontop + external: true + +networks: + stack: + name: ${STACK_NAME} + driver: overlay + external: true + +secrets: + postgis_password: + name: ${STACK_NAME}_postgis_password + external: true diff --git a/Agents/UserAgent/docker-compose.yml b/Agents/UserAgent/docker-compose.yml new file mode 100644 index 00000000000..0f3576a4ac2 --- /dev/null +++ b/Agents/UserAgent/docker-compose.yml @@ -0,0 +1,6 @@ +version: "3.8" + +services: + trajectoryqueryagent: + image: ghcr.io/cambridge-cares/user-agent:1.1.0 + build: . \ No newline at end of file diff --git a/Agents/UserAgent/docker/entrypoint.sh b/Agents/UserAgent/docker/entrypoint.sh new file mode 100644 index 00000000000..8481864c2eb --- /dev/null +++ b/Agents/UserAgent/docker/entrypoint.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +if [[ ${DEBUG} == ON ]]; then + catalina.sh jpda run +else + catalina.sh run +fi diff --git a/Agents/UserAgent/stack-manager-config/inputs/config/data/user.obda b/Agents/UserAgent/stack-manager-config/inputs/config/data/user.obda new file mode 100644 index 00000000000..db94f3ab8e7 --- /dev/null +++ b/Agents/UserAgent/stack-manager-config/inputs/config/data/user.obda @@ -0,0 +1,16 @@ +[PrefixDeclaration] +xsd: http://www.w3.org/2001/XMLSchema# +bot: https://w3id.org/bot# +mon: https://w3id.org/MON/person.owl# +sla: https://www.theworldavatar.com/kg/sensorloggerapp/ + +[MappingDeclaration] @collection [[ +mappingId User +target mon:Person_{id} a mon:Person; + mon:personalMailbox {email}^^xsd:string; + mon:firstName {first_name}^^xsd:string; + mon:lastName {last_name}^^xsd:string; + sla:userName {username}^^xsd:string. +source SELECT id, email, first_name, last_name, username + FROM "keycloak"."user_entity" +]] \ No newline at end of file diff --git a/Agents/UserAgent/stack-manager-config/inputs/config/services/user-agent-debug.json b/Agents/UserAgent/stack-manager-config/inputs/config/services/user-agent-debug.json new file mode 100644 index 00000000000..d5750e3ea8b --- /dev/null +++ b/Agents/UserAgent/stack-manager-config/inputs/config/services/user-agent-debug.json @@ -0,0 +1,49 @@ +{ + "ServiceSpec": { + "Name": "user-agent", + "TaskTemplate": { + "ContainerSpec": { + "Image": "user-agent:1.0.0", + "Mounts": [ + { + "Type": "bind", + "Source": "user.obda", + "Target": "/inputs/user.obda" + } + ], + "Env": [ + "JAVA_TOOL_OPTIONS=-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=*:5005" + ], + "Configs": [ + { + "ConfigName": "blazegraph" + }, + { + "ConfigName": "postgis" + } + ], + "Secrets": [ + { + "SecretName": "postgis_password" + } + ] + } + }, + "EndpointSpec": { + "Ports": [ + { + "Name": "web", + "Protocol": "tcp", + "TargetPort": "5005", + "PublishedPort": "5005" + } + ] + } + }, + "endpoints": { + "isochroneagent": { + "url": "http://localhost:8080/user-agent/", + "externalPath": "/user-agent/" + } + } + } \ No newline at end of file diff --git a/Agents/UserAgent/stack-manager-config/inputs/config/services/user-agent.json b/Agents/UserAgent/stack-manager-config/inputs/config/services/user-agent.json new file mode 100644 index 00000000000..1338ed55ac2 --- /dev/null +++ b/Agents/UserAgent/stack-manager-config/inputs/config/services/user-agent.json @@ -0,0 +1,46 @@ +{ + "ServiceSpec": { + "Name": "user-agent", + "TaskTemplate": { + "ContainerSpec": { + "Image": "ghcr.io/cambridge-cares/user-agent:1.0.0", + "Mounts": [ + { + "Type": "bind", + "Source": "user.obda", + "Target": "/inputs/user.obda" + } + ], + "Configs": [ + { + "ConfigName": "blazegraph" + }, + { + "ConfigName": "postgis" + } + ], + "Secrets": [ + { + "SecretName": "postgis_password" + } + ] + } + }, + "EndpointSpec": { + "Ports": [ + { + "Name": "web", + "Protocol": "tcp", + "TargetPort": "5005", + "PublishedPort": "5005" + } + ] + } + }, + "endpoints": { + "isochroneagent": { + "url": "http://localhost:8080/user-agent/", + "externalPath": "/user-agent/" + } + } +} \ No newline at end of file diff --git a/Agents/UserAgent/stack.sh b/Agents/UserAgent/stack.sh new file mode 100644 index 00000000000..ea6cfb73c42 --- /dev/null +++ b/Agents/UserAgent/stack.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +COMMAND=$1 +shift + +SCRIPTS_DIR="$(git rev-parse --show-toplevel)/Deploy/stacks/dynamic/common-scripts" +export SCRIPTS_DIR + +"${SCRIPTS_DIR}/${COMMAND}.sh" "$@" \ No newline at end of file From b7a9ca7f4d00a9c69cfc21180ccc82c9d1e4f183 Mon Sep 17 00:00:00 2001 From: sandradeng20 Date: Fri, 22 Mar 2024 15:46:30 +0800 Subject: [PATCH 02/16] 1771-dev-user-agent: register phone to user --- Agents/UserAgent/Dockerfile | 8 +-- .../jps/agent/useragent/EndpointConfig.java | 8 +-- .../useragent/TimelineRDBStoreHelper.java | 53 +++++++++++++++++ .../cares/jps/agent/useragent/UserAgent.java | 59 ++++++++++--------- .../inputs/config/data/user.obda | 7 ++- .../config/services/user-agent-debug.json | 5 +- .../inputs/config/services/user-agent.json | 13 +--- 7 files changed, 105 insertions(+), 48 deletions(-) create mode 100644 Agents/UserAgent/UserAgent/src/main/java/uk/ac/cam/cares/jps/agent/useragent/TimelineRDBStoreHelper.java diff --git a/Agents/UserAgent/Dockerfile b/Agents/UserAgent/Dockerfile index d1bdb68be25..545af620ed3 100644 --- a/Agents/UserAgent/Dockerfile +++ b/Agents/UserAgent/Dockerfile @@ -13,19 +13,19 @@ RUN sed -i "s|REPO_USERNAME|$(cat ../credentials/repo_username.txt)|;s|REPO_PASS # Build -WORKDIR /root/trajectoryqueryagent -RUN --mount=type=cache,target=/root/.m2/repository mvn package +WORKDIR /root/UserAgent +RUN --mount=type=cache,target=/root/.m2/repository mvn clean package #================================================================================================== # Second stage: copy the downloaded dependency into a new image and build into an app #================================================================================================== FROM tomcat:9.0 as agent -WORKDIR /root/trajectoryqueryagent +WORKDIR /root/UserAgent # #================================================================================================== # Copy the compiled jar from the builder -COPY --from=builder /root/trajectoryqueryagent/output/user-agent##1.0.0.war $CATALINA_HOME/webapps/ +COPY --from=builder /root/UserAgent/output/user-agent##1.0.0.war $CATALINA_HOME/webapps/ COPY ./docker/entrypoint.sh entrypoint.sh # Port for Java debugging diff --git a/Agents/UserAgent/UserAgent/src/main/java/uk/ac/cam/cares/jps/agent/useragent/EndpointConfig.java b/Agents/UserAgent/UserAgent/src/main/java/uk/ac/cam/cares/jps/agent/useragent/EndpointConfig.java index 4122882255f..7ab7845a712 100644 --- a/Agents/UserAgent/UserAgent/src/main/java/uk/ac/cam/cares/jps/agent/useragent/EndpointConfig.java +++ b/Agents/UserAgent/UserAgent/src/main/java/uk/ac/cam/cares/jps/agent/useragent/EndpointConfig.java @@ -1,6 +1,7 @@ package uk.ac.cam.cares.jps.agent.useragent; import com.cmclinnovations.stack.clients.blazegraph.BlazegraphEndpointConfig; +import com.cmclinnovations.stack.clients.core.EndpointNames; import com.cmclinnovations.stack.clients.docker.ContainerClient; import com.cmclinnovations.stack.clients.ontop.OntopEndpointConfig; import com.cmclinnovations.stack.clients.postgis.PostGISEndpointConfig; @@ -18,16 +19,16 @@ public class EndpointConfig { public EndpointConfig() { ContainerClient containerClient = new ContainerClient(); - BlazegraphEndpointConfig blazegraphEndpointConfig = containerClient.readEndpointConfig("blazegraph", + BlazegraphEndpointConfig blazegraphEndpointConfig = containerClient.readEndpointConfig(EndpointNames.BLAZEGRAPH, BlazegraphEndpointConfig.class); this.kgurl = blazegraphEndpointConfig.getUrl("kb"); this.kguser = blazegraphEndpointConfig.getUsername(); this.kgpassword = blazegraphEndpointConfig.getPassword(); - OntopEndpointConfig ontopEndpointConfig = containerClient.readEndpointConfig("ontop", OntopEndpointConfig.class); + OntopEndpointConfig ontopEndpointConfig = containerClient.readEndpointConfig(EndpointNames.ONTOP, OntopEndpointConfig.class); this.ontopurl = ontopEndpointConfig.getUrl(); - postGISEndpointConfig = containerClient.readEndpointConfig("postgis", + postGISEndpointConfig = containerClient.readEndpointConfig(EndpointNames.POSTGIS, PostGISEndpointConfig.class); this.dbuser = postGISEndpointConfig.getUsername(); this.dbpassword = postGISEndpointConfig.getPassword(); @@ -35,7 +36,6 @@ public EndpointConfig() { public String getKgurl() { return this.kgurl; } - public String getOntopurl() { return this.ontopurl; } public String getDburl() { return postGISEndpointConfig.getJdbcURL("postgres"); } diff --git a/Agents/UserAgent/UserAgent/src/main/java/uk/ac/cam/cares/jps/agent/useragent/TimelineRDBStoreHelper.java b/Agents/UserAgent/UserAgent/src/main/java/uk/ac/cam/cares/jps/agent/useragent/TimelineRDBStoreHelper.java new file mode 100644 index 00000000000..eaa45d35d22 --- /dev/null +++ b/Agents/UserAgent/UserAgent/src/main/java/uk/ac/cam/cares/jps/agent/useragent/TimelineRDBStoreHelper.java @@ -0,0 +1,53 @@ +package uk.ac.cam.cares.jps.agent.useragent; + +import org.apache.log4j.Logger; +import org.json.JSONArray; +import uk.ac.cam.cares.jps.base.query.RemoteRDBStoreClient; + +public class TimelineRDBStoreHelper { + private RemoteRDBStoreClient postgresRdbClient; + private Logger LOGGER = Logger.getLogger(TimelineRDBStoreHelper.class); + + public TimelineRDBStoreHelper(RemoteRDBStoreClient postgresRdbClient) { + this.postgresRdbClient = postgresRdbClient; + initRDBStore(); + } + + private void initRDBStore() { + initTimelineSchema(); + initPhoneTable(); + } + + private void initTimelineSchema() { + JSONArray result = postgresRdbClient.executeQuery("SELECT schema_name \n" + + "FROM information_schema.schemata\n" + + "WHERE schema_name = 'timeline';"); + LOGGER.debug(result); + if (!result.isEmpty()) { + return; + } + + LOGGER.debug("creating schema"); + postgresRdbClient.executeUpdate("CREATE SCHEMA timeline;"); + } + + private void initPhoneTable() { + JSONArray result = postgresRdbClient.executeQuery("SELECT table_name\n" + + "FROM information_schema.tables\n" + + "WHERE table_schema = 'timeline'\n" + + "AND table_name = 'smartPhone';"); + + if (!result.isEmpty()) { + return; + } + + postgresRdbClient.executeUpdate("CREATE TABLE IF NOT EXISTS \"postgres\".\"timeline\".\"smartPhone\" (" + + "phone_id CHAR(36) PRIMARY KEY," + + "user_id CHAR(36));"); + } + + public void registerPhone(String phoneId, String userId) { + postgresRdbClient.executeUpdate("INSERT INTO \"timeline\".\"smartPhone\" (\"phone_id\", \"user_id\")\n" + + String.format("VALUES ('%s', '%s');", phoneId, userId)); + } +} diff --git a/Agents/UserAgent/UserAgent/src/main/java/uk/ac/cam/cares/jps/agent/useragent/UserAgent.java b/Agents/UserAgent/UserAgent/src/main/java/uk/ac/cam/cares/jps/agent/useragent/UserAgent.java index e788c54c4d5..07ef1eed4cb 100644 --- a/Agents/UserAgent/UserAgent/src/main/java/uk/ac/cam/cares/jps/agent/useragent/UserAgent.java +++ b/Agents/UserAgent/UserAgent/src/main/java/uk/ac/cam/cares/jps/agent/useragent/UserAgent.java @@ -3,14 +3,16 @@ import com.cmclinnovations.stack.clients.ontop.OntopClient; import org.apache.log4j.LogManager; import org.apache.log4j.Logger; -import org.json.JSONArray; +import org.codehaus.jettison.json.JSONArray; import org.json.JSONObject; import uk.ac.cam.cares.jps.base.agent.JPSAgent; import uk.ac.cam.cares.jps.base.query.RemoteRDBStoreClient; import uk.ac.cam.cares.jps.base.query.RemoteStoreClient; +import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.BadRequestException; import java.nio.file.Path; @@ -18,54 +20,55 @@ @WebServlet(urlPatterns = "/registerPhone") public class UserAgent extends JPSAgent { - private KGQueryClient kgQueryClient; - private RemoteStoreClient storeClient; - private RemoteRDBStoreClient timelineRdbClient; + private TimelineRDBStoreHelper timelineRdbStoreHelper; private final Logger LOGGER = LogManager.getLogger(UserAgent.class); private static final Path obdaFile = Path.of("/inputs/user.obda"); public void init() { + LOGGER.debug("This is a debug message."); + LOGGER.info("This is an info message."); + LOGGER.warn("This is a warn message."); + LOGGER.error("This is an error message."); + LOGGER.fatal("This is a fatal message."); + EndpointConfig endpointConfig = new EndpointConfig(); - storeClient = new RemoteStoreClient(endpointConfig.getKgurl(), endpointConfig.getKgurl()); - kgQueryClient = new KGQueryClient(storeClient, endpointConfig.getOntopurl()); - initTimelineDatabase(endpointConfig); - timelineRdbClient = new RemoteRDBStoreClient(endpointConfig.getDburl("timeline"), endpointConfig.getDbuser(), endpointConfig.getDbpassword()); - initPhoneTable(); + LOGGER.info("initializing rdb"); + RemoteRDBStoreClient postgresRdbClient = new RemoteRDBStoreClient(endpointConfig.getDburl(), endpointConfig.getDbuser(), endpointConfig.getDbpassword()); + timelineRdbStoreHelper = new TimelineRDBStoreHelper(postgresRdbClient); try { OntopClient ontopClient = OntopClient.getInstance(); + LOGGER.info("updating obda"); ontopClient.updateOBDA(obdaFile); } catch (Exception e) { + System.out.println(e.getMessage()); System.out.println("Could not retrieve user.obda file."); } } - private void initTimelineDatabase(EndpointConfig endpointConfig) { - RemoteRDBStoreClient postgresRdbClient = new RemoteRDBStoreClient(endpointConfig.getDburl(), endpointConfig.getDbuser(), endpointConfig.getDbpassword()); - JSONArray result = postgresRdbClient.executeQuery("SELECT datname FROM pg_database WHERE datname = 'timeline';"); - if (!result.isEmpty()) { - return; - } - - postgresRdbClient.executeUpdate("CREATE DATABASE timeline;"); - } - - private void initPhoneTable() { - timelineRdbClient.executeUpdate("CREATE TABLE IF NOT EXISTS 'timeline'.'smartPhone' (" + - "phone_id CHAR(36) PRIMARY KEY," + - "user_id CHAR(36)"); - } @Override public JSONObject processRequestParameters(JSONObject requestParams, HttpServletRequest request) { + if (request.getRequestURI().contains("registerPhone")) { + validateInputRegisterPhone(requestParams); + timelineRdbStoreHelper.registerPhone(requestParams.getString("phoneId"), requestParams.getString("userId")); + + JSONObject result = new JSONObject(); + result.put("Comment", "Phone is registered successfully."); + return result; + } return processRequestParameters(requestParams); } - @Override - public JSONObject processRequestParameters(JSONObject requestParams) { - return new JSONObject(); + private void validateInputRegisterPhone(JSONObject requestParams) throws BadRequestException { + LOGGER.debug("Request received: " + requestParams.toString()); + if (!requestParams.has("userId")) { + throw new BadRequestException("No user id provided"); + } + if (!requestParams.has("phoneId")) { + throw new BadRequestException("No phone id provided"); + } } - } \ No newline at end of file diff --git a/Agents/UserAgent/stack-manager-config/inputs/config/data/user.obda b/Agents/UserAgent/stack-manager-config/inputs/config/data/user.obda index db94f3ab8e7..ac97c36e50d 100644 --- a/Agents/UserAgent/stack-manager-config/inputs/config/data/user.obda +++ b/Agents/UserAgent/stack-manager-config/inputs/config/data/user.obda @@ -6,11 +6,16 @@ sla: https://www.theworldavatar.com/kg/sensorloggerapp/ [MappingDeclaration] @collection [[ mappingId User -target mon:Person_{id} a mon:Person; +target mon:person_{id} a mon:Person; mon:personalMailbox {email}^^xsd:string; mon:firstName {first_name}^^xsd:string; mon:lastName {last_name}^^xsd:string; sla:userName {username}^^xsd:string. source SELECT id, email, first_name, last_name, username FROM "keycloak"."user_entity" + +mappingId Phone +target mon:person_{user_id} sla::hasA sla:smartphone_{phone_id}. +source SELECT user_id, phone_id + FROM "timeline"."smartPhone" ]] \ No newline at end of file diff --git a/Agents/UserAgent/stack-manager-config/inputs/config/services/user-agent-debug.json b/Agents/UserAgent/stack-manager-config/inputs/config/services/user-agent-debug.json index d5750e3ea8b..e6614ef8da3 100644 --- a/Agents/UserAgent/stack-manager-config/inputs/config/services/user-agent-debug.json +++ b/Agents/UserAgent/stack-manager-config/inputs/config/services/user-agent-debug.json @@ -20,6 +20,9 @@ }, { "ConfigName": "postgis" + }, + { + "ConfigName": "ontop" } ], "Secrets": [ @@ -46,4 +49,4 @@ "externalPath": "/user-agent/" } } - } \ No newline at end of file +} \ No newline at end of file diff --git a/Agents/UserAgent/stack-manager-config/inputs/config/services/user-agent.json b/Agents/UserAgent/stack-manager-config/inputs/config/services/user-agent.json index 1338ed55ac2..559f2aa3806 100644 --- a/Agents/UserAgent/stack-manager-config/inputs/config/services/user-agent.json +++ b/Agents/UserAgent/stack-manager-config/inputs/config/services/user-agent.json @@ -17,6 +17,9 @@ }, { "ConfigName": "postgis" + }, + { + "ConfigName": "ontop" } ], "Secrets": [ @@ -25,16 +28,6 @@ } ] } - }, - "EndpointSpec": { - "Ports": [ - { - "Name": "web", - "Protocol": "tcp", - "TargetPort": "5005", - "PublishedPort": "5005" - } - ] } }, "endpoints": { From abda40e3f6210904dcfb07aecaf4c368cda00204 Mon Sep 17 00:00:00 2001 From: sandradeng20 Date: Fri, 22 Mar 2024 18:17:00 +0800 Subject: [PATCH 03/16] 1771-dev-user-agent: get phone ids with user id --- Agents/UserAgent/UserAgent/pom.xml | 6 ++-- .../jps/agent/useragent/EndpointConfig.java | 3 ++ .../jps/agent/useragent/KGQueryClient.java | 32 +++++++++++++------ .../cares/jps/agent/useragent/UserAgent.java | 23 +++++++++++-- .../inputs/config/data/user.obda | 2 +- 5 files changed, 49 insertions(+), 17 deletions(-) diff --git a/Agents/UserAgent/UserAgent/pom.xml b/Agents/UserAgent/UserAgent/pom.xml index ce1fc6e517d..035819d74d7 100644 --- a/Agents/UserAgent/UserAgent/pom.xml +++ b/Agents/UserAgent/UserAgent/pom.xml @@ -178,17 +178,17 @@ org.apache.logging.log4j log4j-api - 2.14.1 + 2.11.0 org.apache.logging.log4j log4j-core - 2.14.1 + 2.11.0 org.apache.logging.log4j log4j-web - 2.14.1 + 2.11.0 diff --git a/Agents/UserAgent/UserAgent/src/main/java/uk/ac/cam/cares/jps/agent/useragent/EndpointConfig.java b/Agents/UserAgent/UserAgent/src/main/java/uk/ac/cam/cares/jps/agent/useragent/EndpointConfig.java index 7ab7845a712..53fa0069fbf 100644 --- a/Agents/UserAgent/UserAgent/src/main/java/uk/ac/cam/cares/jps/agent/useragent/EndpointConfig.java +++ b/Agents/UserAgent/UserAgent/src/main/java/uk/ac/cam/cares/jps/agent/useragent/EndpointConfig.java @@ -48,4 +48,7 @@ public String getDbuser() { public String getDbpassword() { return this.dbpassword; } + public String getOntopurl() { + return ontopurl; + } } diff --git a/Agents/UserAgent/UserAgent/src/main/java/uk/ac/cam/cares/jps/agent/useragent/KGQueryClient.java b/Agents/UserAgent/UserAgent/src/main/java/uk/ac/cam/cares/jps/agent/useragent/KGQueryClient.java index 391b8449450..2fd1156ba75 100644 --- a/Agents/UserAgent/UserAgent/src/main/java/uk/ac/cam/cares/jps/agent/useragent/KGQueryClient.java +++ b/Agents/UserAgent/UserAgent/src/main/java/uk/ac/cam/cares/jps/agent/useragent/KGQueryClient.java @@ -1,30 +1,42 @@ package uk.ac.cam.cares.jps.agent.useragent; +import org.apache.jena.arq.querybuilder.SelectBuilder; +import org.apache.jena.arq.querybuilder.WhereBuilder; +import org.apache.jena.graph.Node; +import org.apache.jena.graph.NodeFactory; +import org.apache.jena.graph.Node_URI; import org.apache.jena.sparql.core.Var; - +import org.json.JSONArray; import uk.ac.cam.cares.jps.base.query.RemoteStoreClient; public class KGQueryClient { private RemoteStoreClient storeClient; - private String ontopEndpoint; // Prefixes - static final String ONTOSLMA = "https://www.theworldavatar.com/kg/ontosensorloggermobileapp/"; static final String SLA = "https://www.theworldavatar.com/kg/sensorloggerapp/"; - static final String OM = "http://www.ontology-of-units-of-measure.org/resource/om-2/"; - static final String SF ="http://www.opengis.net/ont/sf#"; - static final String ONTODEVICE = "https://www.theworldavatar.com/kg/ontodevice/"; static final String MON = "https://w3id.org/MON/person.owl"; - static final String SAREF="https://saref.etsi.org/core/"; - static final String RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#"; final static String str_s = "s"; final static Var VAR_S = Var.alloc(str_s); final static String str_o = "o"; final static Var VAR_O = Var.alloc(str_o); - public KGQueryClient(RemoteStoreClient storeClient, String ontopEndpoint) { + public KGQueryClient(RemoteStoreClient storeClient) { this.storeClient = storeClient; - this.ontopEndpoint = ontopEndpoint; + } + + public JSONArray getPhoneIds(String userId) { + String userIri = MON + "#person_" + userId; + Node userIriNode = NodeFactory.createURI(userIri); + + WhereBuilder wb = new WhereBuilder() + .addPrefix("slm", SLA) + .addWhere(userIriNode, "slm:hasA", VAR_O); + + SelectBuilder sb = new SelectBuilder() + .setDistinct(true) + .addVar(VAR_O).addWhere(wb); + + return storeClient.executeQuery(sb.buildString()); } } diff --git a/Agents/UserAgent/UserAgent/src/main/java/uk/ac/cam/cares/jps/agent/useragent/UserAgent.java b/Agents/UserAgent/UserAgent/src/main/java/uk/ac/cam/cares/jps/agent/useragent/UserAgent.java index 07ef1eed4cb..804597be9ad 100644 --- a/Agents/UserAgent/UserAgent/src/main/java/uk/ac/cam/cares/jps/agent/useragent/UserAgent.java +++ b/Agents/UserAgent/UserAgent/src/main/java/uk/ac/cam/cares/jps/agent/useragent/UserAgent.java @@ -3,13 +3,12 @@ import com.cmclinnovations.stack.clients.ontop.OntopClient; import org.apache.log4j.LogManager; import org.apache.log4j.Logger; -import org.codehaus.jettison.json.JSONArray; +import org.json.JSONArray; import org.json.JSONObject; import uk.ac.cam.cares.jps.base.agent.JPSAgent; import uk.ac.cam.cares.jps.base.query.RemoteRDBStoreClient; import uk.ac.cam.cares.jps.base.query.RemoteStoreClient; -import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServletRequest; import javax.ws.rs.BadRequestException; @@ -17,10 +16,11 @@ import java.nio.file.Path; -@WebServlet(urlPatterns = "/registerPhone") +@WebServlet(urlPatterns = {"/registerPhone", "/getPhoneIds"}) public class UserAgent extends JPSAgent { private TimelineRDBStoreHelper timelineRdbStoreHelper; + private KGQueryClient kgQueryClient; private final Logger LOGGER = LogManager.getLogger(UserAgent.class); private static final Path obdaFile = Path.of("/inputs/user.obda"); @@ -34,6 +34,8 @@ public void init() { EndpointConfig endpointConfig = new EndpointConfig(); + kgQueryClient = new KGQueryClient(new RemoteStoreClient(endpointConfig.getOntopurl())); + LOGGER.info("initializing rdb"); RemoteRDBStoreClient postgresRdbClient = new RemoteRDBStoreClient(endpointConfig.getDburl(), endpointConfig.getDbuser(), endpointConfig.getDbpassword()); timelineRdbStoreHelper = new TimelineRDBStoreHelper(postgresRdbClient); @@ -58,7 +60,15 @@ public JSONObject processRequestParameters(JSONObject requestParams, HttpServlet JSONObject result = new JSONObject(); result.put("Comment", "Phone is registered successfully."); return result; + } else if (request.getRequestURI().contains("getPhoneIds")) { + validateInputGetPhoneIds(requestParams); + JSONArray phoneIds = kgQueryClient.getPhoneIds(requestParams.getString("userId")); + JSONObject result = new JSONObject(); + result.put("PhoneIds", phoneIds); + result.put("Comment", "Phone ids are retrieved."); + return result; } + return processRequestParameters(requestParams); } @@ -71,4 +81,11 @@ private void validateInputRegisterPhone(JSONObject requestParams) throws BadRequ throw new BadRequestException("No phone id provided"); } } + + private void validateInputGetPhoneIds(JSONObject requestParams) throws BadRequestException { + LOGGER.debug("Request received: " + requestParams.toString()); + if (!requestParams.has("userId")) { + throw new BadRequestException("No user id provided"); + } + } } \ No newline at end of file diff --git a/Agents/UserAgent/stack-manager-config/inputs/config/data/user.obda b/Agents/UserAgent/stack-manager-config/inputs/config/data/user.obda index ac97c36e50d..95c4e2da3b1 100644 --- a/Agents/UserAgent/stack-manager-config/inputs/config/data/user.obda +++ b/Agents/UserAgent/stack-manager-config/inputs/config/data/user.obda @@ -15,7 +15,7 @@ source SELECT id, email, first_name, last_name, username FROM "keycloak"."user_entity" mappingId Phone -target mon:person_{user_id} sla::hasA sla:smartphone_{phone_id}. +target mon:person_{user_id} sla:hasA sla:smartphone_{phone_id}. source SELECT user_id, phone_id FROM "timeline"."smartPhone" ]] \ No newline at end of file From 242ac5f03d6e34fdb6c8f07f4e5b586fb2b7cec2 Mon Sep 17 00:00:00 2001 From: sandradeng20 Date: Tue, 26 Mar 2024 10:57:34 +0800 Subject: [PATCH 04/16] 1771-dev-user-agent: wait for ontop to be restarted in init --- .../ac/cam/cares/jps/agent/useragent/KGQueryClient.java | 9 ++++++++- .../uk/ac/cam/cares/jps/agent/useragent/UserAgent.java | 3 +++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/Agents/UserAgent/UserAgent/src/main/java/uk/ac/cam/cares/jps/agent/useragent/KGQueryClient.java b/Agents/UserAgent/UserAgent/src/main/java/uk/ac/cam/cares/jps/agent/useragent/KGQueryClient.java index 2fd1156ba75..aba91246fa2 100644 --- a/Agents/UserAgent/UserAgent/src/main/java/uk/ac/cam/cares/jps/agent/useragent/KGQueryClient.java +++ b/Agents/UserAgent/UserAgent/src/main/java/uk/ac/cam/cares/jps/agent/useragent/KGQueryClient.java @@ -7,6 +7,7 @@ import org.apache.jena.graph.Node_URI; import org.apache.jena.sparql.core.Var; import org.json.JSONArray; +import org.json.JSONObject; import uk.ac.cam.cares.jps.base.query.RemoteStoreClient; public class KGQueryClient { @@ -36,7 +37,13 @@ public JSONArray getPhoneIds(String userId) { .setDistinct(true) .addVar(VAR_O).addWhere(wb); - return storeClient.executeQuery(sb.buildString()); + JSONArray jsonArray = storeClient.executeQuery(sb.buildString()); + JSONArray result = new JSONArray(); + for (int i = 0; i < jsonArray.length(); i++) { + JSONObject jsonObject = jsonArray.getJSONObject(i); + result.put(jsonObject.get("o")); + } + return result; } } diff --git a/Agents/UserAgent/UserAgent/src/main/java/uk/ac/cam/cares/jps/agent/useragent/UserAgent.java b/Agents/UserAgent/UserAgent/src/main/java/uk/ac/cam/cares/jps/agent/useragent/UserAgent.java index 804597be9ad..553b8440e48 100644 --- a/Agents/UserAgent/UserAgent/src/main/java/uk/ac/cam/cares/jps/agent/useragent/UserAgent.java +++ b/Agents/UserAgent/UserAgent/src/main/java/uk/ac/cam/cares/jps/agent/useragent/UserAgent.java @@ -44,6 +44,9 @@ public void init() { OntopClient ontopClient = OntopClient.getInstance(); LOGGER.info("updating obda"); ontopClient.updateOBDA(obdaFile); + + // wait for ontop to be restarted + Thread.sleep(1500); } catch (Exception e) { System.out.println(e.getMessage()); System.out.println("Could not retrieve user.obda file."); From 21f2b2cd8ce0c41ad578a4e6849c1d4dd5aaff00 Mon Sep 17 00:00:00 2001 From: sandradeng20 Date: Tue, 2 Apr 2024 17:02:23 +0800 Subject: [PATCH 05/16] 1771-dev-user-agent: update stack config file --- .../config/services/user-agent-debug.json | 89 ++++++++++--------- .../inputs/config/services/user-agent.json | 3 +- 2 files changed, 47 insertions(+), 45 deletions(-) diff --git a/Agents/UserAgent/stack-manager-config/inputs/config/services/user-agent-debug.json b/Agents/UserAgent/stack-manager-config/inputs/config/services/user-agent-debug.json index e6614ef8da3..18602e5abf9 100644 --- a/Agents/UserAgent/stack-manager-config/inputs/config/services/user-agent-debug.json +++ b/Agents/UserAgent/stack-manager-config/inputs/config/services/user-agent-debug.json @@ -1,52 +1,53 @@ { - "ServiceSpec": { - "Name": "user-agent", - "TaskTemplate": { - "ContainerSpec": { - "Image": "user-agent:1.0.0", - "Mounts": [ - { - "Type": "bind", - "Source": "user.obda", - "Target": "/inputs/user.obda" - } - ], - "Env": [ - "JAVA_TOOL_OPTIONS=-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=*:5005" - ], - "Configs": [ - { - "ConfigName": "blazegraph" - }, - { - "ConfigName": "postgis" - }, - { - "ConfigName": "ontop" - } - ], - "Secrets": [ - { - "SecretName": "postgis_password" - } - ] - } - }, - "EndpointSpec": { - "Ports": [ + "type": "basic-agent", + "ServiceSpec": { + "Name": "user-agent", + "TaskTemplate": { + "ContainerSpec": { + "Image": "user-agent:1.0.0", + "Mounts": [ + { + "Type": "bind", + "Source": "user.obda", + "Target": "/inputs/user.obda" + } + ], + "Env": [ + "JAVA_TOOL_OPTIONS=-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=*:5005" + ], + "Configs": [ + { + "ConfigName": "blazegraph" + }, + { + "ConfigName": "postgis" + }, { - "Name": "web", - "Protocol": "tcp", - "TargetPort": "5005", - "PublishedPort": "5005" + "ConfigName": "ontop" + } + ], + "Secrets": [ + { + "SecretName": "postgis_password" } ] } }, - "endpoints": { - "isochroneagent": { - "url": "http://localhost:8080/user-agent/", - "externalPath": "/user-agent/" - } + "EndpointSpec": { + "Ports": [ + { + "Name": "web", + "Protocol": "tcp", + "TargetPort": "5005", + "PublishedPort": "5005" + } + ] + } + }, + "endpoints": { + "useragent": { + "url": "http://localhost:8080/user-agent/", + "externalPath": "/user-agent/" } + } } \ No newline at end of file diff --git a/Agents/UserAgent/stack-manager-config/inputs/config/services/user-agent.json b/Agents/UserAgent/stack-manager-config/inputs/config/services/user-agent.json index 559f2aa3806..8bbeda9e506 100644 --- a/Agents/UserAgent/stack-manager-config/inputs/config/services/user-agent.json +++ b/Agents/UserAgent/stack-manager-config/inputs/config/services/user-agent.json @@ -1,4 +1,5 @@ { + "type": "basic-agent", "ServiceSpec": { "Name": "user-agent", "TaskTemplate": { @@ -31,7 +32,7 @@ } }, "endpoints": { - "isochroneagent": { + "useragent": { "url": "http://localhost:8080/user-agent/", "externalPath": "/user-agent/" } From eb991790fbac88555807451c42419c2584edff18 Mon Sep 17 00:00:00 2001 From: sandradeng20 Date: Tue, 2 Apr 2024 17:04:19 +0800 Subject: [PATCH 06/16] 1771-dev-user-agent: update stack config file --- .../{user-agent-debug.json => useragent-debug.json} | 6 +++--- .../config/services/{user-agent.json => useragent.json} | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) rename Agents/UserAgent/stack-manager-config/inputs/config/services/{user-agent-debug.json => useragent-debug.json} (89%) rename Agents/UserAgent/stack-manager-config/inputs/config/services/{user-agent.json => useragent.json} (96%) diff --git a/Agents/UserAgent/stack-manager-config/inputs/config/services/user-agent-debug.json b/Agents/UserAgent/stack-manager-config/inputs/config/services/useragent-debug.json similarity index 89% rename from Agents/UserAgent/stack-manager-config/inputs/config/services/user-agent-debug.json rename to Agents/UserAgent/stack-manager-config/inputs/config/services/useragent-debug.json index 18602e5abf9..09094e64604 100644 --- a/Agents/UserAgent/stack-manager-config/inputs/config/services/user-agent-debug.json +++ b/Agents/UserAgent/stack-manager-config/inputs/config/services/useragent-debug.json @@ -1,7 +1,7 @@ { "type": "basic-agent", "ServiceSpec": { - "Name": "user-agent", + "Name": "useragent", "TaskTemplate": { "ContainerSpec": { "Image": "user-agent:1.0.0", @@ -46,8 +46,8 @@ }, "endpoints": { "useragent": { - "url": "http://localhost:8080/user-agent/", - "externalPath": "/user-agent/" + "url": "http://localhost:8080/useragent/", + "externalPath": "/useragent/" } } } \ No newline at end of file diff --git a/Agents/UserAgent/stack-manager-config/inputs/config/services/user-agent.json b/Agents/UserAgent/stack-manager-config/inputs/config/services/useragent.json similarity index 96% rename from Agents/UserAgent/stack-manager-config/inputs/config/services/user-agent.json rename to Agents/UserAgent/stack-manager-config/inputs/config/services/useragent.json index 8bbeda9e506..e3d11524859 100644 --- a/Agents/UserAgent/stack-manager-config/inputs/config/services/user-agent.json +++ b/Agents/UserAgent/stack-manager-config/inputs/config/services/useragent.json @@ -1,7 +1,7 @@ { "type": "basic-agent", "ServiceSpec": { - "Name": "user-agent", + "Name": "useragent", "TaskTemplate": { "ContainerSpec": { "Image": "ghcr.io/cambridge-cares/user-agent:1.0.0", From 431dd745ff1e50d44d157effcb7c69e869875cb6 Mon Sep 17 00:00:00 2001 From: sandradeng20 Date: Tue, 23 Apr 2024 10:49:53 +0800 Subject: [PATCH 07/16] 1771-dev-user-agent: check whether phone id is registered with another user --- Agents/UserAgent/UserAgent/pom.xml | 42 +++---------------- .../useragent/TimelineRDBStoreHelper.java | 15 +++++++ .../cares/jps/agent/useragent/UserAgent.java | 31 ++++++++++++-- 3 files changed, 47 insertions(+), 41 deletions(-) diff --git a/Agents/UserAgent/UserAgent/pom.xml b/Agents/UserAgent/UserAgent/pom.xml index 035819d74d7..a34ae4a2dd3 100644 --- a/Agents/UserAgent/UserAgent/pom.xml +++ b/Agents/UserAgent/UserAgent/pom.xml @@ -173,24 +173,6 @@ jar - - - - org.apache.logging.log4j - log4j-api - 2.11.0 - - - org.apache.logging.log4j - log4j-core - 2.11.0 - - - org.apache.logging.log4j - log4j-web - 2.11.0 - - org.junit.jupiter @@ -207,31 +189,17 @@ 4.1.0 - - - - - org.postgresql postgresql 42.5.4 - + + org.jooq + jooq + 3.16.23 + diff --git a/Agents/UserAgent/UserAgent/src/main/java/uk/ac/cam/cares/jps/agent/useragent/TimelineRDBStoreHelper.java b/Agents/UserAgent/UserAgent/src/main/java/uk/ac/cam/cares/jps/agent/useragent/TimelineRDBStoreHelper.java index eaa45d35d22..e310ffdfcfb 100644 --- a/Agents/UserAgent/UserAgent/src/main/java/uk/ac/cam/cares/jps/agent/useragent/TimelineRDBStoreHelper.java +++ b/Agents/UserAgent/UserAgent/src/main/java/uk/ac/cam/cares/jps/agent/useragent/TimelineRDBStoreHelper.java @@ -1,15 +1,24 @@ package uk.ac.cam.cares.jps.agent.useragent; import org.apache.log4j.Logger; + +import org.jooq.DSLContext; +import org.jooq.Query; +import org.jooq.SQLDialect; +import org.jooq.conf.ParamType; import org.json.JSONArray; import uk.ac.cam.cares.jps.base.query.RemoteRDBStoreClient; +import static org.jooq.impl.DSL.*; + public class TimelineRDBStoreHelper { private RemoteRDBStoreClient postgresRdbClient; private Logger LOGGER = Logger.getLogger(TimelineRDBStoreHelper.class); + private DSLContext context; public TimelineRDBStoreHelper(RemoteRDBStoreClient postgresRdbClient) { this.postgresRdbClient = postgresRdbClient; + context = using(SQLDialect.POSTGRES); initRDBStore(); } @@ -50,4 +59,10 @@ public void registerPhone(String phoneId, String userId) { postgresRdbClient.executeUpdate("INSERT INTO \"timeline\".\"smartPhone\" (\"phone_id\", \"user_id\")\n" + String.format("VALUES ('%s', '%s');", phoneId, userId)); } + + public JSONArray getExistingPhoneIdRecord(String phoneId) { + Query query = context.select(field("user_id")) + .from(table("\"postgres\".\"timeline\".\"smartPhone\"")).where(field("phone_id").eq(phoneId)); + return postgresRdbClient.executeQuery(query.getSQL(ParamType.INLINED)); + } } diff --git a/Agents/UserAgent/UserAgent/src/main/java/uk/ac/cam/cares/jps/agent/useragent/UserAgent.java b/Agents/UserAgent/UserAgent/src/main/java/uk/ac/cam/cares/jps/agent/useragent/UserAgent.java index 553b8440e48..c51c08d0893 100644 --- a/Agents/UserAgent/UserAgent/src/main/java/uk/ac/cam/cares/jps/agent/useragent/UserAgent.java +++ b/Agents/UserAgent/UserAgent/src/main/java/uk/ac/cam/cares/jps/agent/useragent/UserAgent.java @@ -6,6 +6,7 @@ import org.json.JSONArray; import org.json.JSONObject; import uk.ac.cam.cares.jps.base.agent.JPSAgent; +import uk.ac.cam.cares.jps.base.exception.JPSRuntimeException; import uk.ac.cam.cares.jps.base.query.RemoteRDBStoreClient; import uk.ac.cam.cares.jps.base.query.RemoteStoreClient; @@ -16,8 +17,7 @@ import java.nio.file.Path; -@WebServlet(urlPatterns = {"/registerPhone", "/getPhoneIds"}) - +@WebServlet(urlPatterns = {"/registerPhone", "/getPhoneIds", "/status"}) public class UserAgent extends JPSAgent { private TimelineRDBStoreHelper timelineRdbStoreHelper; private KGQueryClient kgQueryClient; @@ -56,13 +56,36 @@ public void init() { @Override public JSONObject processRequestParameters(JSONObject requestParams, HttpServletRequest request) { - if (request.getRequestURI().contains("registerPhone")) { + if (request.getRequestURI().contains("status")) { + JSONObject jo = new JSONObject(); + jo.put("Message", "User agent is up and running"); + return jo; + } + else if (request.getRequestURI().contains("registerPhone")) { validateInputRegisterPhone(requestParams); - timelineRdbStoreHelper.registerPhone(requestParams.getString("phoneId"), requestParams.getString("userId")); + String userId = requestParams.getString("userId"); + String phoneId = requestParams.getString("phoneId"); + + JSONArray jsonArray = timelineRdbStoreHelper.getExistingPhoneIdRecord(phoneId); + if (!jsonArray.isEmpty()) { + if (jsonArray.getJSONObject(0).getString("user_id").equals(userId)) { + LOGGER.info("Phone has already been registered"); + JSONObject result = new JSONObject(); + result.put("Comment", "Phone has already been registered"); + return result; + } else { + LOGGER.error("Phone is already registered with another userId: " + jsonArray.getJSONObject(0).getString("user_id")); + throw new JPSRuntimeException("Phone is already registered with another userId"); + } + } + + timelineRdbStoreHelper.registerPhone(requestParams.getString("phoneId"), requestParams.getString("userId")); JSONObject result = new JSONObject(); result.put("Comment", "Phone is registered successfully."); + LOGGER.info(phoneId + " is registered to " + userId); return result; + } else if (request.getRequestURI().contains("getPhoneIds")) { validateInputGetPhoneIds(requestParams); JSONArray phoneIds = kgQueryClient.getPhoneIds(requestParams.getString("userId")); From 60ea573f9dddb303ecc4546d53e34d58b2fda6ae Mon Sep 17 00:00:00 2001 From: sandradeng20 Date: Tue, 23 Apr 2024 11:50:44 +0800 Subject: [PATCH 08/16] 1771-dev-user-agent: use jooq to prevent SQL injection --- .../useragent/TimelineRDBStoreHelper.java | 37 +++++++++---------- .../config/services/useragent-debug.json | 8 ++-- .../inputs/config/services/useragent.json | 4 +- 3 files changed, 24 insertions(+), 25 deletions(-) diff --git a/Agents/UserAgent/UserAgent/src/main/java/uk/ac/cam/cares/jps/agent/useragent/TimelineRDBStoreHelper.java b/Agents/UserAgent/UserAgent/src/main/java/uk/ac/cam/cares/jps/agent/useragent/TimelineRDBStoreHelper.java index e310ffdfcfb..e6c75dd6af9 100644 --- a/Agents/UserAgent/UserAgent/src/main/java/uk/ac/cam/cares/jps/agent/useragent/TimelineRDBStoreHelper.java +++ b/Agents/UserAgent/UserAgent/src/main/java/uk/ac/cam/cares/jps/agent/useragent/TimelineRDBStoreHelper.java @@ -3,6 +3,7 @@ import org.apache.log4j.Logger; import org.jooq.DSLContext; +import org.jooq.Name; import org.jooq.Query; import org.jooq.SQLDialect; import org.jooq.conf.ParamType; @@ -28,9 +29,11 @@ private void initRDBStore() { } private void initTimelineSchema() { - JSONArray result = postgresRdbClient.executeQuery("SELECT schema_name \n" + - "FROM information_schema.schemata\n" + - "WHERE schema_name = 'timeline';"); + Query query = context.select(field("schema_name")) + .from(table(name("information_schema", "schemata"))) + .where(field("schema_name").eq(val("timeline"))); + JSONArray result = postgresRdbClient.executeQuery(query.getSQL(ParamType.INLINED)); + LOGGER.debug(result); if (!result.isEmpty()) { return; @@ -41,28 +44,24 @@ private void initTimelineSchema() { } private void initPhoneTable() { - JSONArray result = postgresRdbClient.executeQuery("SELECT table_name\n" + - "FROM information_schema.tables\n" + - "WHERE table_schema = 'timeline'\n" + - "AND table_name = 'smartPhone';"); - - if (!result.isEmpty()) { - return; - } - - postgresRdbClient.executeUpdate("CREATE TABLE IF NOT EXISTS \"postgres\".\"timeline\".\"smartPhone\" (" + - "phone_id CHAR(36) PRIMARY KEY," + - "user_id CHAR(36));"); + Query queryCreateTable = context.createTableIfNotExists(name("postgres", "timeline", "smartPhone")) + .column(column(name("phone_id"), SQLDataType.CHAR.length(36))) + .column(column(name("user_id"), SQLDataType.CHAR.length(36))) + .constraints(constraint("pk_phone_id").primaryKey(name(phoneIdColumnName))); + postgresRdbClient.executeUpdate(queryCreateTable.getSQL()); } public void registerPhone(String phoneId, String userId) { - postgresRdbClient.executeUpdate("INSERT INTO \"timeline\".\"smartPhone\" (\"phone_id\", \"user_id\")\n" + - String.format("VALUES ('%s', '%s');", phoneId, userId)); + Query query = context.insertInto(table(name("timeline", "smartPhone"))) + .columns(field(name("phone_id")), field(name("user_id"))) + .values(val(phoneId), val(userId)); + postgresRdbClient.executeUpdate(query.getSQL()); } public JSONArray getExistingPhoneIdRecord(String phoneId) { Query query = context.select(field("user_id")) - .from(table("\"postgres\".\"timeline\".\"smartPhone\"")).where(field("phone_id").eq(phoneId)); - return postgresRdbClient.executeQuery(query.getSQL(ParamType.INLINED)); + .from(table(name("postgres", "timeline", "smartPhone"))) + .where(field("phone_id").eq(val(phoneId))); + return postgresRdbClient.executeQuery(query.getSQL()); } } diff --git a/Agents/UserAgent/stack-manager-config/inputs/config/services/useragent-debug.json b/Agents/UserAgent/stack-manager-config/inputs/config/services/useragent-debug.json index 09094e64604..0192bd0f090 100644 --- a/Agents/UserAgent/stack-manager-config/inputs/config/services/useragent-debug.json +++ b/Agents/UserAgent/stack-manager-config/inputs/config/services/useragent-debug.json @@ -1,7 +1,7 @@ { "type": "basic-agent", "ServiceSpec": { - "Name": "useragent", + "Name": "user-agent", "TaskTemplate": { "ContainerSpec": { "Image": "user-agent:1.0.0", @@ -45,9 +45,9 @@ } }, "endpoints": { - "useragent": { - "url": "http://localhost:8080/useragent/", - "externalPath": "/useragent/" + "rest": { + "url": "http://localhost:8080/user-agent/", + "externalPath": "/user-agent/" } } } \ No newline at end of file diff --git a/Agents/UserAgent/stack-manager-config/inputs/config/services/useragent.json b/Agents/UserAgent/stack-manager-config/inputs/config/services/useragent.json index e3d11524859..3762edc1785 100644 --- a/Agents/UserAgent/stack-manager-config/inputs/config/services/useragent.json +++ b/Agents/UserAgent/stack-manager-config/inputs/config/services/useragent.json @@ -1,7 +1,7 @@ { "type": "basic-agent", "ServiceSpec": { - "Name": "useragent", + "Name": "user-agent", "TaskTemplate": { "ContainerSpec": { "Image": "ghcr.io/cambridge-cares/user-agent:1.0.0", @@ -32,7 +32,7 @@ } }, "endpoints": { - "useragent": { + "rest": { "url": "http://localhost:8080/user-agent/", "externalPath": "/user-agent/" } From 22fac0db8e1d9722f00d34492656facf604737bc Mon Sep 17 00:00:00 2001 From: sandradeng20 Date: Tue, 23 Apr 2024 14:48:17 +0800 Subject: [PATCH 09/16] 1771-dev-user-agent: fix bugs --- .../cares/jps/agent/useragent/TimelineRDBStoreHelper.java | 7 ++++--- Agents/UserAgent/docker-compose.yml | 4 ++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/Agents/UserAgent/UserAgent/src/main/java/uk/ac/cam/cares/jps/agent/useragent/TimelineRDBStoreHelper.java b/Agents/UserAgent/UserAgent/src/main/java/uk/ac/cam/cares/jps/agent/useragent/TimelineRDBStoreHelper.java index e6c75dd6af9..b5e562d0fe9 100644 --- a/Agents/UserAgent/UserAgent/src/main/java/uk/ac/cam/cares/jps/agent/useragent/TimelineRDBStoreHelper.java +++ b/Agents/UserAgent/UserAgent/src/main/java/uk/ac/cam/cares/jps/agent/useragent/TimelineRDBStoreHelper.java @@ -7,6 +7,7 @@ import org.jooq.Query; import org.jooq.SQLDialect; import org.jooq.conf.ParamType; +import org.jooq.impl.SQLDataType; import org.json.JSONArray; import uk.ac.cam.cares.jps.base.query.RemoteRDBStoreClient; @@ -45,9 +46,9 @@ private void initTimelineSchema() { private void initPhoneTable() { Query queryCreateTable = context.createTableIfNotExists(name("postgres", "timeline", "smartPhone")) - .column(column(name("phone_id"), SQLDataType.CHAR.length(36))) - .column(column(name("user_id"), SQLDataType.CHAR.length(36))) - .constraints(constraint("pk_phone_id").primaryKey(name(phoneIdColumnName))); + .column(name("phone_id"), SQLDataType.CHAR.length(36)) + .column(name("user_id"), SQLDataType.CHAR.length(36)) + .constraints(constraint("pk_phone_id").primaryKey(name("phone_id"))); postgresRdbClient.executeUpdate(queryCreateTable.getSQL()); } diff --git a/Agents/UserAgent/docker-compose.yml b/Agents/UserAgent/docker-compose.yml index 0f3576a4ac2..0ab06db46cf 100644 --- a/Agents/UserAgent/docker-compose.yml +++ b/Agents/UserAgent/docker-compose.yml @@ -1,6 +1,6 @@ version: "3.8" services: - trajectoryqueryagent: - image: ghcr.io/cambridge-cares/user-agent:1.1.0 + user-agent: + image: ghcr.io/cambridge-cares/user-agent:1.0.0 build: . \ No newline at end of file From 29cdc534e428d05584f1f27b072e8f130e066d4e Mon Sep 17 00:00:00 2001 From: sandradeng20 Date: Tue, 23 Apr 2024 14:59:18 +0800 Subject: [PATCH 10/16] 1771-dev-user-agent: rename file --- .../services/{useragent-debug.json => user-agent-debug.json} | 0 .../inputs/config/services/{useragent.json => user-agent.json} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename Agents/UserAgent/stack-manager-config/inputs/config/services/{useragent-debug.json => user-agent-debug.json} (100%) rename Agents/UserAgent/stack-manager-config/inputs/config/services/{useragent.json => user-agent.json} (100%) diff --git a/Agents/UserAgent/stack-manager-config/inputs/config/services/useragent-debug.json b/Agents/UserAgent/stack-manager-config/inputs/config/services/user-agent-debug.json similarity index 100% rename from Agents/UserAgent/stack-manager-config/inputs/config/services/useragent-debug.json rename to Agents/UserAgent/stack-manager-config/inputs/config/services/user-agent-debug.json diff --git a/Agents/UserAgent/stack-manager-config/inputs/config/services/useragent.json b/Agents/UserAgent/stack-manager-config/inputs/config/services/user-agent.json similarity index 100% rename from Agents/UserAgent/stack-manager-config/inputs/config/services/useragent.json rename to Agents/UserAgent/stack-manager-config/inputs/config/services/user-agent.json From 1bc76e6e983d23b1d4a5e8834c6f91da6234ade2 Mon Sep 17 00:00:00 2001 From: sandradeng20 Date: Wed, 24 Apr 2024 14:24:47 +0800 Subject: [PATCH 11/16] 1771-dev-user-agent: change obda folder --- .../stack-manager-config/inputs/{config => }/data/user.obda | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename Agents/UserAgent/stack-manager-config/inputs/{config => }/data/user.obda (100%) diff --git a/Agents/UserAgent/stack-manager-config/inputs/config/data/user.obda b/Agents/UserAgent/stack-manager-config/inputs/data/user.obda similarity index 100% rename from Agents/UserAgent/stack-manager-config/inputs/config/data/user.obda rename to Agents/UserAgent/stack-manager-config/inputs/data/user.obda From 3090cd6c156f98baf01bc59f8d563bf549f67e7a Mon Sep 17 00:00:00 2001 From: sandradeng20 Date: Wed, 24 Apr 2024 14:25:12 +0800 Subject: [PATCH 12/16] 1771-dev-user-agent: fix bug in building sql query --- .../cam/cares/jps/agent/useragent/TimelineRDBStoreHelper.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Agents/UserAgent/UserAgent/src/main/java/uk/ac/cam/cares/jps/agent/useragent/TimelineRDBStoreHelper.java b/Agents/UserAgent/UserAgent/src/main/java/uk/ac/cam/cares/jps/agent/useragent/TimelineRDBStoreHelper.java index b5e562d0fe9..4bbc47984f5 100644 --- a/Agents/UserAgent/UserAgent/src/main/java/uk/ac/cam/cares/jps/agent/useragent/TimelineRDBStoreHelper.java +++ b/Agents/UserAgent/UserAgent/src/main/java/uk/ac/cam/cares/jps/agent/useragent/TimelineRDBStoreHelper.java @@ -56,13 +56,13 @@ public void registerPhone(String phoneId, String userId) { Query query = context.insertInto(table(name("timeline", "smartPhone"))) .columns(field(name("phone_id")), field(name("user_id"))) .values(val(phoneId), val(userId)); - postgresRdbClient.executeUpdate(query.getSQL()); + postgresRdbClient.executeUpdate(query.getSQL(ParamType.INLINED)); } public JSONArray getExistingPhoneIdRecord(String phoneId) { Query query = context.select(field("user_id")) .from(table(name("postgres", "timeline", "smartPhone"))) .where(field("phone_id").eq(val(phoneId))); - return postgresRdbClient.executeQuery(query.getSQL()); + return postgresRdbClient.executeQuery(query.getSQL(ParamType.INLINED)); } } From cce8f029dc3ae645a0b013e31ebaa82104011066 Mon Sep 17 00:00:00 2001 From: sandradeng20 Date: Tue, 3 Dec 2024 09:41:04 +0800 Subject: [PATCH 13/16] 1771-dev-user-agent: update dockerfile --- Agents/UserAgent/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Agents/UserAgent/Dockerfile b/Agents/UserAgent/Dockerfile index 545af620ed3..f0eba7b3db1 100644 --- a/Agents/UserAgent/Dockerfile +++ b/Agents/UserAgent/Dockerfile @@ -25,7 +25,7 @@ WORKDIR /root/UserAgent # #================================================================================================== # Copy the compiled jar from the builder -COPY --from=builder /root/UserAgent/output/user-agent##1.0.0.war $CATALINA_HOME/webapps/ +COPY --from=builder /root/UserAgent/output/user-agent##*.war $CATALINA_HOME/webapps/ COPY ./docker/entrypoint.sh entrypoint.sh # Port for Java debugging From 340e8716f49d1cd85a6e29691ffc1b713cc45201 Mon Sep 17 00:00:00 2001 From: sandradeng20 Date: Wed, 15 Jan 2025 14:48:48 +0800 Subject: [PATCH 14/16] 1771-dev-user-agent: update readme --- Agents/UserAgent/README.md | 44 ++++++++++++++++---------------------- 1 file changed, 18 insertions(+), 26 deletions(-) diff --git a/Agents/UserAgent/README.md b/Agents/UserAgent/README.md index 467637b48f6..d0898324585 100644 --- a/Agents/UserAgent/README.md +++ b/Agents/UserAgent/README.md @@ -1,33 +1,25 @@ # UserAgent ## 1. Description +UserAgent is an agent that manages TWA user with other services account or devices (e.g. smartphones). It currently supports the following functions through the endpoints: +- `/registerPhone`: register a new phone with the user +- `/getPhoneIds`: get the phone ids of the user +- `/status`: get the status of the agent. Used for testing. -## 2. Pre-requisites +## 2. Requirements +Launch stack with the default containers and the following additional containers: +- keycloak +## 3. Deploy +### 3.1 Retrieving UserAgent's image +The UserAgent should be pulled automatically with the stack-manager, if not you can pull the latest version from [cambridge_cares package](https://github.com/orgs/cambridge-cares/packages/container/package/user-agent) using `docker pull ghcr.io/cambridge-cares/user-agent:` +### 3.2 Starting with the stack-manager +The agent has been implemented to work in the stack, which requires the UserAgent Docker container to be deployed in the stack. To do so, place [user-agent.json](stack-manager-config/inputs/config/services/user-agent.json) in the [stack-manager config directory]. -## 3. Agent Configuration +Then, run `./stack.sh start ` in the [stack-manager](https://github.com/cambridge-cares/TheWorldAvatar/tree/main/Deploy/stacks/dynamic/stack-manager) main folder. This will spin up the agent in the stack. - -## 4. Deploy -### 4.1 Retrieving TrajectoryQueryAgent's image -The TrajectoryQueryAgent should be pulled automatically with the stack-manager, if not you can pull the latest version from [cambridge_cares package](https://github.com/orgs/cambridge-cares/packages/container/package/trajectoryqueryagent) using `docker pull ghcr.io/cambridge-cares/trajectoryqueryagent:` - -### 4.2 Starting with the stack-manager -The agent has been implemented to work in the stack, which requires the TrajectoryQueryAgent Docker container to be deployed in the stack. To do so, place [trajectoryqueryagent.json](stack-manager-config/inputs/config/services/user-agent.json) in the [stack-manager config directory]. - -Then, run `./stack.sh start ` in the [stack-manager] main folder. This will spin up the agent in the stack. - -### 4.3 Configuring AccessAgent endpoints -On this same directory run, replace `STACK-NAME` with your stack-manager name. -``` -./copy.sh start -``` - -### 4.4 Start recording -Once all the configurations and server has been set, press the Start Recording button inside the SensorLogger mobile app to begin session. - -## 5. Build and debug -## 5.1 Credentials +## 4. Build and debug +## 4.1 Credentials The docker image uses TheWorldAvatar maven repository (`https://maven.pkg.github.com/cambridge-cares/TheWorldAvatar/`). You will need to provide your credentials (GitHub username/personal access token) in single-word text files as follows: ``` @@ -36,11 +28,11 @@ You will need to provide your credentials (GitHub username/personal access token repo_password.txt ``` -### 5.2 Building Docker Image +### 4.2 Building Docker Image In the same directory as this README, run `./stack.sh build`. This will build the TrajectoryQueryAgent local Docker Image. -### 5.2 Spinning up with stack-manager -To debug the agent, replace [`trajectoryqueryagent-debug.json`](stack-manager-config/inputs/config/services/user-agent-debug.json) instead of [`trajectoryqueryagent.json`](stack-manager-config/inputs/config/services/user-agent.json) in the [stack-manager config directory]. +### 4.2 Spinning up with stack-manager +To debug the agent, replace [`user-agent-debug.json`](stack-manager-config/inputs/config/services/user-agent-debug.json) instead of [`user-agent.json`](stack-manager-config/inputs/config/services/user-agent.json) in the [stack-manager config directory]. Spin up with `./stack.sh start ` in the [stack-manager]'s main folder. The debugger port will be available at 5005. From 574689913d99d666cb9a829786ca75e070bbd10c Mon Sep 17 00:00:00 2001 From: sandradeng20 Date: Wed, 15 Jan 2025 14:49:16 +0800 Subject: [PATCH 15/16] 1771-dev-user-agent: update pkg version --- Agents/UserAgent/UserAgent/pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Agents/UserAgent/UserAgent/pom.xml b/Agents/UserAgent/UserAgent/pom.xml index a34ae4a2dd3..4a1edbd096f 100644 --- a/Agents/UserAgent/UserAgent/pom.xml +++ b/Agents/UserAgent/UserAgent/pom.xml @@ -14,7 +14,7 @@ UTF-8 - 1.39.1 + 1.45.0 @@ -206,7 +206,7 @@ com.cmclinnovations stack-clients - 1.14.1 + 1.39.1 From d4ecba5c5ca9b2bcda9dcbf2fa9826677c400c64 Mon Sep 17 00:00:00 2001 From: sandradeng20 Date: Wed, 15 Jan 2025 14:50:24 +0800 Subject: [PATCH 16/16] 1771-dev-user-agent: remove redundant string --- .../UserAgent/stack-manager-config/inputs/data/user.obda | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Agents/UserAgent/stack-manager-config/inputs/data/user.obda b/Agents/UserAgent/stack-manager-config/inputs/data/user.obda index 95c4e2da3b1..0970922b612 100644 --- a/Agents/UserAgent/stack-manager-config/inputs/data/user.obda +++ b/Agents/UserAgent/stack-manager-config/inputs/data/user.obda @@ -7,10 +7,10 @@ sla: https://www.theworldavatar.com/kg/sensorloggerapp/ [MappingDeclaration] @collection [[ mappingId User target mon:person_{id} a mon:Person; - mon:personalMailbox {email}^^xsd:string; - mon:firstName {first_name}^^xsd:string; - mon:lastName {last_name}^^xsd:string; - sla:userName {username}^^xsd:string. + mon:personalMailbox {email}; + mon:firstName {first_name}; + mon:lastName {last_name}; + sla:userName {username}. source SELECT id, email, first_name, last_name, username FROM "keycloak"."user_entity"