From 802fe032c3a1190e4876f512c4bd2ce9f43a4bf1 Mon Sep 17 00:00:00 2001
From: Sonia Zorba <sonia.zorba@inaf.it>
Date: Mon, 29 Mar 2021 12:47:15 +0200
Subject: [PATCH] Changes for using RAP tokens and GMS groups

---
 .gitlab-ci.yml                                |  2 +-
 Dockerfile                                    |  2 +-
 README.md                                     | 12 ++++----
 call-tap.sh                                   | 29 +++++++++++--------
 database/01-init.sql                          |  8 ++---
 private-rows-extension/Dockerfile-build-env   |  2 +-
 private-rows-extension/nb-configuration.xml   | 18 ------------
 private-rows-extension/pom.xml                | 23 +++++++++++++--
 ...Identifier.java => IA2UserIdentifier.java} | 19 +++++++-----
 .../src/main/resources/auth.properties        |  4 +++
 war/fill-war.sh                               |  2 +-
 war/tap.properties                            |  2 +-
 12 files changed, 67 insertions(+), 56 deletions(-)
 delete mode 100644 private-rows-extension/nb-configuration.xml
 rename private-rows-extension/src/main/java/it/inaf/ia2/vollt/{CustomUserIdentifier.java => IA2UserIdentifier.java} (62%)
 create mode 100644 private-rows-extension/src/main/resources/auth.properties

diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 0b192d1..0a98372 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -65,7 +65,7 @@ build_extension:
     - cd vollt
     - gradle jar
     - cd ../private-rows-extension
-    - mvn clean package
+    - JAVA_HOME=/usr/lib/jvm/java-14-openjdk-amd64 mvn clean package
   artifacts:
     paths:
       - private-rows-extension/target/private-rows-extension-*.jar
diff --git a/Dockerfile b/Dockerfile
index a67bc7b..70f0301 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,2 +1,2 @@
-FROM tomcat:9-jdk8
+FROM tomcat:9-jdk14
 ADD war/tap.war /usr/local/tomcat/webapps/
diff --git a/README.md b/README.md
index 77c3ead..65ca9a3 100644
--- a/README.md
+++ b/README.md
@@ -11,17 +11,15 @@ If you experience issues with the pull command use this setting in `/etc/docker/
 
 ## Demo
 
-    ./call-tap.sh badtoken
+Login to [RAP token issuer](https://sso.ia2.inaf.it/rap-ia2) to retrieve a valid JWT (select GMS service from dropdown menu).
 
-Only free records (2 rows)
+    ./call-tap.sh
 
-    ./call-tap.sh token1
+Returns only free records (2 rows)
 
-Free records + records associated with group1 and group2 (6 rows)
+    ./call-tap.sh <JWT>
 
-    ./call-tap.sh token2
-
-Free records + records associated with group2 (4 rows)
+Returns records associated with user groups retrieved from GMS
 
 ## Shutdown
 
diff --git a/call-tap.sh b/call-tap.sh
index f2583a0..280a3b9 100755
--- a/call-tap.sh
+++ b/call-tap.sh
@@ -1,15 +1,20 @@
 #!/bin/bash
 
-if [ "$#" -ne 1 ]; then
-    echo "Usage: $0 <token>"
-    exit 1
+if [ "$#" -eq 1 ]; then
+    curl -s -XPOST \
+            -H "Authorization: Bearer $1" \
+            -F 'REQUEST=doQuery' \
+            -F 'LANG=ADQL' \
+            -F 'FORMAT=text/csv' \
+            -F 'PHASE=RUN' \
+            -F "QUERY=SELECT * from demo.private_rows;" \
+            http://localhost:8080/tap/sync
+else
+    curl -s -XPOST \
+            -F 'REQUEST=doQuery' \
+            -F 'LANG=ADQL' \
+            -F 'FORMAT=text/csv' \
+            -F 'PHASE=RUN' \
+            -F "QUERY=SELECT * from demo.private_rows;" \
+            http://localhost:8080/tap/sync
 fi
-
-curl -s -XPOST \
-        -H "Authorization: Bearer $1" \
-        -F 'REQUEST=doQuery' \
-        -F 'LANG=ADQL' \
-        -F 'FORMAT=text/csv' \
-        -F 'PHASE=RUN' \
-        -F "QUERY=SELECT * from demo.private_rows;" \
-        http://localhost:8080/tap/sync
diff --git a/database/01-init.sql b/database/01-init.sql
index cbc3c02..c3533e1 100644
--- a/database/01-init.sql
+++ b/database/01-init.sql
@@ -8,10 +8,10 @@ CREATE TABLE demo.private_rows (
 
 INSERT INTO demo.private_rows (value, policy, "group") VALUES ('value1', 'FREE', '');
 INSERT INTO demo.private_rows (value, policy, "group") VALUES ('value2', 'FREE', '');
-INSERT INTO demo.private_rows (value, policy, "group") VALUES ('value3', 'PRIV', 'group1');
-INSERT INTO demo.private_rows (value, policy, "group") VALUES ('value4', 'PRIV', 'group1');
-INSERT INTO demo.private_rows (value, policy, "group") VALUES ('value5', 'PRIV', 'group2');
-INSERT INTO demo.private_rows (value, policy, "group") VALUES ('value6', 'PRIV', 'group2');
+INSERT INTO demo.private_rows (value, policy, "group") VALUES ('value3', 'PRIV', 'VLKB.group1');
+INSERT INTO demo.private_rows (value, policy, "group") VALUES ('value4', 'PRIV', 'VLKB.group1');
+INSERT INTO demo.private_rows (value, policy, "group") VALUES ('value5', 'PRIV', 'VLKB.group2');
+INSERT INTO demo.private_rows (value, policy, "group") VALUES ('value6', 'PRIV', 'VLKB.group2');
 
 -- WARNING: always create a new role because Row Level Security doesn't work for table owner
 CREATE ROLE tap WITH LOGIN PASSWORD 'demo';
diff --git a/private-rows-extension/Dockerfile-build-env b/private-rows-extension/Dockerfile-build-env
index 7ca2bf2..d13e628 100644
--- a/private-rows-extension/Dockerfile-build-env
+++ b/private-rows-extension/Dockerfile-build-env
@@ -1,2 +1,2 @@
 FROM gradle:jdk8
-RUN apt-get update && apt install -y maven
+RUN apt-get update && apt install -y openjdk-14-jdk maven
diff --git a/private-rows-extension/nb-configuration.xml b/private-rows-extension/nb-configuration.xml
deleted file mode 100644
index a65c451..0000000
--- a/private-rows-extension/nb-configuration.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project-shared-configuration>
-    <!--
-This file contains additional configuration written by modules in the NetBeans IDE.
-The configuration is intended to be shared among all the users of project and
-therefore it is assumed to be part of version control checkout.
-Without this configuration present, some functionality in the IDE may be limited or fail altogether.
--->
-    <properties xmlns="http://www.netbeans.org/ns/maven-properties-data/1">
-        <!--
-Properties that influence various parts of the IDE, especially code formatting and the like. 
-You can copy and paste the single properties, into the pom.xml file and the IDE will pick them up.
-That way multiple projects can share the same settings (useful for formatting rules for example).
-Any value defined here will override the pom.xml file value but is only applicable to the current project.
--->
-        <netbeans.hint.jdkPlatform>JDK_1.8</netbeans.hint.jdkPlatform>
-    </properties>
-</project-shared-configuration>
diff --git a/private-rows-extension/pom.xml b/private-rows-extension/pom.xml
index 2003e6b..12f0e4e 100644
--- a/private-rows-extension/pom.xml
+++ b/private-rows-extension/pom.xml
@@ -7,8 +7,8 @@
     <packaging>jar</packaging>
     <properties>
         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
-        <maven.compiler.source>8</maven.compiler.source>
-        <maven.compiler.target>8</maven.compiler.target>
+        <maven.compiler.source>14</maven.compiler.source>
+        <maven.compiler.target>14</maven.compiler.target>
     </properties>
     <dependencies>
         <dependency>
@@ -18,6 +18,11 @@
             <scope>system</scope>
             <systemPath>${basedir}/../vollt/build/libs/vollt.jar</systemPath>
         </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>auth-lib</artifactId>
+            <version>2.0.0-SNAPSHOT</version>
+        </dependency>
         <dependency>
             <groupId>javax</groupId>
             <artifactId>javaee-web-api</artifactId>
@@ -55,6 +60,20 @@
                 <artifactId>maven-surefire-plugin</artifactId>
                 <version>2.22.2</version>
             </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-shade-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>shade</goal>
+                        </goals>
+                        <configuration>
+                            <shadedArtifactAttached>true</shadedArtifactAttached>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
         </plugins>
     </build>
 </project>
\ No newline at end of file
diff --git a/private-rows-extension/src/main/java/it/inaf/ia2/vollt/CustomUserIdentifier.java b/private-rows-extension/src/main/java/it/inaf/ia2/vollt/IA2UserIdentifier.java
similarity index 62%
rename from private-rows-extension/src/main/java/it/inaf/ia2/vollt/CustomUserIdentifier.java
rename to private-rows-extension/src/main/java/it/inaf/ia2/vollt/IA2UserIdentifier.java
index 68aa8a9..5c19b7c 100644
--- a/private-rows-extension/src/main/java/it/inaf/ia2/vollt/CustomUserIdentifier.java
+++ b/private-rows-extension/src/main/java/it/inaf/ia2/vollt/IA2UserIdentifier.java
@@ -1,5 +1,8 @@
 package it.inaf.ia2.vollt;
 
+import it.inaf.ia2.aa.ServiceLocator;
+import it.inaf.ia2.aa.data.User;
+import it.inaf.ia2.aa.jwt.InvalidTokenException;
 import java.util.Arrays;
 import java.util.Map;
 import javax.servlet.http.HttpServletRequest;
@@ -8,7 +11,7 @@ import uws.job.user.JobOwner;
 import uws.service.UWSUrl;
 import uws.service.UserIdentifier;
 
-public class CustomUserIdentifier implements UserIdentifier {
+public class IA2UserIdentifier implements UserIdentifier {
 
     @Override
     public JobOwner extractUserId(UWSUrl urlInterpreter, HttpServletRequest request) throws UWSException {
@@ -22,7 +25,7 @@ public class CustomUserIdentifier implements UserIdentifier {
             }
         }
 
-        return getFakeUser(token);
+        return getUser(token);
     }
 
     @Override
@@ -30,14 +33,14 @@ public class CustomUserIdentifier implements UserIdentifier {
         throw new UnsupportedOperationException("Not supported yet.");
     }
 
-    private CustomJobOwner getFakeUser(String token) {
+    private CustomJobOwner getUser(String token) throws UWSException {
 
         if (token != null) {
-            switch (token) {
-                case "token1":
-                    return new CustomJobOwner("user1", Arrays.asList("group1", "group2"));
-                case "token2":
-                    return new CustomJobOwner("user2", Arrays.asList("group2"));
+            try {
+                User user = ServiceLocator.getInstance().getUserManager().getUserFromAccessToken(token);
+                return new CustomJobOwner(user.getName(), user.getGroups());
+            } catch (InvalidTokenException ex) {
+                throw new UWSException(401, "Invalid token");
             }
         }
 
diff --git a/private-rows-extension/src/main/resources/auth.properties b/private-rows-extension/src/main/resources/auth.properties
new file mode 100644
index 0000000..d549b76
--- /dev/null
+++ b/private-rows-extension/src/main/resources/auth.properties
@@ -0,0 +1,4 @@
+rap_uri=https://sso.ia2.inaf.it/rap-ia2
+gms_uri=https://sso.ia2.inaf.it/gms
+groups_autoload=true
+scope=openid read:gms read:rap
\ No newline at end of file
diff --git a/war/fill-war.sh b/war/fill-war.sh
index 059a06d..66267ee 100755
--- a/war/fill-war.sh
+++ b/war/fill-war.sh
@@ -6,7 +6,7 @@ rm tap.war
 unzip "$base_war" -d vollt
 cp tap.properties vollt/WEB-INF/classes/tap.properties
 cp web.xml vollt/WEB-INF/
-cp ../private-rows-extension/target/private-rows-extension-*.jar vollt/WEB-INF/lib/
+cp ../private-rows-extension/target/private-rows-extension-*-shaded.jar vollt/WEB-INF/lib/
 rm vollt/WEB-INF/lib/postgresql-9*.jar
 cp postgresql-*.jar vollt/WEB-INF/lib/
 cd vollt
diff --git a/war/tap.properties b/war/tap.properties
index 04ba433..1f66297 100644
--- a/war/tap.properties
+++ b/war/tap.properties
@@ -8,5 +8,5 @@ metadata = db
 file_manager = local
 file_root_path = /tmp
 TAP_SCHEMA = TAP_SCHEMA
-user_identifier={it.inaf.ia2.vollt.CustomUserIdentifier}
+user_identifier={it.inaf.ia2.vollt.IA2UserIdentifier}
 query_executor={it.inaf.ia2.vollt.PrivateRowsQueryExecutor}
-- 
GitLab