Added a service to list active refresh tokens of a user.

Change-Id: I4f9508d9e12162bdf18fb2d61d3347000f29af0a


Change-Id: I4f9508d9e12162bdf18fb2d61d3347000f29af0a
diff --git a/full/src/main/java/de/ids_mannheim/korap/authentication/KustvaktAuthenticationManager.java b/full/src/main/java/de/ids_mannheim/korap/authentication/KustvaktAuthenticationManager.java
index 650a118..3fd5722 100644
--- a/full/src/main/java/de/ids_mannheim/korap/authentication/KustvaktAuthenticationManager.java
+++ b/full/src/main/java/de/ids_mannheim/korap/authentication/KustvaktAuthenticationManager.java
@@ -100,7 +100,7 @@
 	 */
 	@Override
 	public TokenContext getTokenContext(TokenType type, String token, 
-	        String host, String useragent) throws KustvaktException {
+	        String host, String userAgent) throws KustvaktException {
 
 		AuthenticationIface provider = getProvider(type , null);
 
@@ -111,6 +111,8 @@
 		}
 		
 		TokenContext context = provider.getTokenContext(token);
+		context.setHostAddress(host);
+		context.setUserAgent(userAgent);
 		// if (!matchStatus(host, useragent, context))
 		// provider.removeUserSession(token);
 		return context;
diff --git a/full/src/main/java/de/ids_mannheim/korap/oauth2/dao/RefreshTokenDao.java b/full/src/main/java/de/ids_mannheim/korap/oauth2/dao/RefreshTokenDao.java
index 87c7a6d..339f3cd 100644
--- a/full/src/main/java/de/ids_mannheim/korap/oauth2/dao/RefreshTokenDao.java
+++ b/full/src/main/java/de/ids_mannheim/korap/oauth2/dao/RefreshTokenDao.java
@@ -12,6 +12,7 @@
 import javax.persistence.criteria.CriteriaBuilder;
 import javax.persistence.criteria.CriteriaQuery;
 import javax.persistence.criteria.Join;
+import javax.persistence.criteria.Predicate;
 import javax.persistence.criteria.Root;
 
 import org.springframework.beans.factory.annotation.Autowired;
@@ -108,27 +109,26 @@
         return token;
     }
 
-    // public List<RefreshToken> retrieveRefreshTokenByUser (String
-    // username)
-    // throws KustvaktException {
-    // ParameterChecker.checkStringValue(username, "username");
-    //
-    // CriteriaBuilder builder = entityManager.getCriteriaBuilder();
-    // CriteriaQuery<RefreshToken> query =
-    // builder.createQuery(RefreshToken.class);
-    //
-    // Root<RefreshToken> root = query.from(RefreshToken.class);
-    // Predicate condition = builder.and(
-    // builder.equal(root.get(RefreshToken_.userId), username),
-    // builder.equal(root.get(RefreshToken_.isRevoked), false),
-    // builder.greaterThan(
-    // root.<ZonedDateTime> get(RefreshToken_.expiryDate),
-    // ZonedDateTime
-    // .now(ZoneId.of(Attributes.DEFAULT_TIME_ZONE)))
-    // );
-    // query.select(root);
-    // query.where(condition);
-    // TypedQuery<RefreshToken> q = entityManager.createQuery(query);
-    // return q.getResultList();
-    // }
+    public List<RefreshToken> retrieveRefreshTokenByUser (String username)
+            throws KustvaktException {
+        ParameterChecker.checkStringValue(username, "username");
+
+        CriteriaBuilder builder = entityManager.getCriteriaBuilder();
+        CriteriaQuery<RefreshToken> query =
+                builder.createQuery(RefreshToken.class);
+
+        Root<RefreshToken> root = query.from(RefreshToken.class);
+        root.fetch(RefreshToken_.client);
+        Predicate condition = builder.and(
+                builder.equal(root.get(RefreshToken_.userId), username),
+                builder.equal(root.get(RefreshToken_.isRevoked), false),
+                builder.greaterThan(
+                        root.<ZonedDateTime> get(RefreshToken_.expiryDate),
+                        ZonedDateTime
+                                .now(ZoneId.of(Attributes.DEFAULT_TIME_ZONE))));
+        query.select(root);
+        query.where(condition);
+        TypedQuery<RefreshToken> q = entityManager.createQuery(query);
+        return q.getResultList();
+    }
 }
diff --git a/full/src/main/java/de/ids_mannheim/korap/oauth2/dto/OAuth2RefreshTokenDto.java b/full/src/main/java/de/ids_mannheim/korap/oauth2/dto/OAuth2RefreshTokenDto.java
new file mode 100644
index 0000000..8fac3ca
--- /dev/null
+++ b/full/src/main/java/de/ids_mannheim/korap/oauth2/dto/OAuth2RefreshTokenDto.java
@@ -0,0 +1,97 @@
+package de.ids_mannheim.korap.oauth2.dto;
+
+import java.util.Set;
+
+/**
+ * Describes OAuth2 refresh tokens
+ * 
+ * @author margaretha
+ *
+ */
+public class OAuth2RefreshTokenDto {
+
+    private String token;
+    private String createdDate;
+    private String expiryDate;
+    private String userAuthenticationTime;
+    private Set<String> scopes;
+
+    private String clientId;
+    private String clientName;
+    private String clientDescription;
+    private String clientUrl;
+
+    public String getToken () {
+        return token;
+    }
+
+    public void setToken (String token) {
+        this.token = token;
+    }
+
+    public String getClientId () {
+        return clientId;
+    }
+
+    public void setClientId (String clientId) {
+        this.clientId = clientId;
+    }
+
+    public String getClientName () {
+        return clientName;
+    }
+
+    public void setClientName (String clientName) {
+        this.clientName = clientName;
+    }
+
+    public String getClientDescription () {
+        return clientDescription;
+    }
+
+    public void setClientDescription (String clientDescription) {
+        this.clientDescription = clientDescription;
+    }
+
+    public String getClientUrl () {
+        return clientUrl;
+    }
+
+    public void setClientUrl (String clientUrl) {
+        this.clientUrl = clientUrl;
+    }
+
+    public String getCreatedDate () {
+        return createdDate;
+    }
+
+    public void setCreatedDate (String createdDate) {
+        this.createdDate = createdDate;
+    }
+
+    public String getExpiryDate () {
+        return expiryDate;
+    }
+
+    public void setExpiryDate (String expiryDate) {
+        this.expiryDate = expiryDate;
+    }
+
+    public String getUserAuthenticationTime () {
+        return userAuthenticationTime;
+    }
+
+    public void setUserAuthenticationTime (
+            String userAuthenticationTime) {
+        this.userAuthenticationTime = userAuthenticationTime;
+    }
+
+    public Set<String> getScopes () {
+        return scopes;
+    }
+
+    public void setScopes (Set<String> scopes) {
+        this.scopes = scopes;
+    }
+
+}
diff --git a/full/src/main/java/de/ids_mannheim/korap/oauth2/oltu/service/OltuTokenService.java b/full/src/main/java/de/ids_mannheim/korap/oauth2/oltu/service/OltuTokenService.java
index c18ba88..feafc87 100644
--- a/full/src/main/java/de/ids_mannheim/korap/oauth2/oltu/service/OltuTokenService.java
+++ b/full/src/main/java/de/ids_mannheim/korap/oauth2/oltu/service/OltuTokenService.java
@@ -2,6 +2,8 @@
 
 import java.time.ZoneId;
 import java.time.ZonedDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
@@ -25,6 +27,7 @@
 import de.ids_mannheim.korap.oauth2.constant.OAuth2Error;
 import de.ids_mannheim.korap.oauth2.dao.AccessTokenDao;
 import de.ids_mannheim.korap.oauth2.dao.RefreshTokenDao;
+import de.ids_mannheim.korap.oauth2.dto.OAuth2RefreshTokenDto;
 import de.ids_mannheim.korap.oauth2.entity.AccessScope;
 import de.ids_mannheim.korap.oauth2.entity.AccessToken;
 import de.ids_mannheim.korap.oauth2.entity.Authorization;
@@ -32,6 +35,7 @@
 import de.ids_mannheim.korap.oauth2.entity.RefreshToken;
 import de.ids_mannheim.korap.oauth2.oltu.OAuth2RevokeTokenRequest;
 import de.ids_mannheim.korap.oauth2.oltu.OAuth2RevokeTokenSuperRequest;
+import de.ids_mannheim.korap.oauth2.service.OAuth2ClientService;
 import de.ids_mannheim.korap.oauth2.service.OAuth2TokenService;
 
 /** Implementation of token service using Apache Oltu.
@@ -49,6 +53,9 @@
     private AccessTokenDao tokenDao;
     @Autowired
     private RefreshTokenDao refreshDao;
+    
+    @Autowired
+    private OAuth2ClientService clientService;
 
     public OAuthResponse requestAccessToken (
             AbstractOAuthTokenRequest oAuthRequest)
@@ -438,4 +445,45 @@
             revokeRefreshToken(r);
         }
     }
+    
+    public List<OAuth2RefreshTokenDto> listUserRefreshToken (String username, String clientId,
+            String clientSecret) throws KustvaktException {
+        
+        OAuth2Client client = clientService.authenticateClient(clientId, clientSecret);
+        if (!client.isSuper()) {
+            throw new KustvaktException(StatusCodes.CLIENT_AUTHORIZATION_FAILED,
+                    "Only super client is allowed.",
+                    OAuth2Error.UNAUTHORIZED_CLIENT);
+        }
+
+        List<RefreshToken> tokens = refreshDao.retrieveRefreshTokenByUser(username);
+        List<OAuth2RefreshTokenDto> dtoList = new ArrayList<>(tokens.size());
+        for (RefreshToken t : tokens){
+            OAuth2Client tokenClient = t.getClient();
+            if (tokenClient.getId().equals(client.getId())){
+                continue;
+            }
+            OAuth2RefreshTokenDto dto = new OAuth2RefreshTokenDto();
+            dto.setClientId(tokenClient.getId());
+            dto.setClientName(tokenClient.getName());
+            dto.setClientUrl(tokenClient.getUrl());
+            dto.setClientDescription(tokenClient.getDescription());
+            
+            DateTimeFormatter f = DateTimeFormatter.ISO_DATE_TIME;
+            dto.setCreatedDate(t.getCreatedDate().format(f));
+            dto.setExpiryDate(t.getExpiryDate().format(f));
+            dto.setUserAuthenticationTime(
+                    t.getUserAuthenticationTime().format(f));
+            dto.setToken(t.getToken());
+            
+            Set<AccessScope> accessScopes = t.getScopes();
+            Set<String> scopes = new HashSet<>(accessScopes.size());
+            for (AccessScope s : accessScopes){
+                scopes.add(s.getId().toString());
+            }
+            dto.setScopes(scopes);
+            dtoList.add(dto);
+        }
+        return dtoList;
+    }
 }
diff --git a/full/src/main/java/de/ids_mannheim/korap/web/controller/OAuth2Controller.java b/full/src/main/java/de/ids_mannheim/korap/web/controller/OAuth2Controller.java
index 0cd6171..bbe1122 100644
--- a/full/src/main/java/de/ids_mannheim/korap/web/controller/OAuth2Controller.java
+++ b/full/src/main/java/de/ids_mannheim/korap/web/controller/OAuth2Controller.java
@@ -1,6 +1,7 @@
 package de.ids_mannheim.korap.web.controller;
 
 import java.time.ZonedDateTime;
+import java.util.List;
 
 import javax.servlet.http.HttpServletRequest;
 import javax.ws.rs.Consumes;
@@ -28,6 +29,7 @@
 
 import de.ids_mannheim.korap.constant.OAuth2Scope;
 import de.ids_mannheim.korap.exceptions.KustvaktException;
+import de.ids_mannheim.korap.oauth2.dto.OAuth2RefreshTokenDto;
 import de.ids_mannheim.korap.oauth2.oltu.OAuth2AuthorizationRequest;
 import de.ids_mannheim.korap.oauth2.oltu.OAuth2RevokeTokenRequest;
 import de.ids_mannheim.korap.oauth2.oltu.OAuth2RevokeTokenSuperRequest;
@@ -291,4 +293,28 @@
             throw responseHandler.throwit(e);
         }
     }
+    
+    @POST
+    @Path("token/list")
+    @ResourceFilters({ AuthenticationFilter.class, BlockingFilter.class })
+    @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
+    @Produces(MediaType.APPLICATION_JSON + ";charset=utf-8")
+    public List<OAuth2RefreshTokenDto> listUserRefreshToken (
+            @Context SecurityContext context,
+            @FormParam("client_id") String clientId,
+            @FormParam("client_secret") String clientSecret) {
+        
+        TokenContext tokenContext = (TokenContext) context.getUserPrincipal();
+        String username = tokenContext.getUsername();
+        
+        try {
+            return tokenService.listUserRefreshToken(username, clientId,
+                    clientSecret);            
+        }
+        catch (KustvaktException e) {
+            throw responseHandler.throwit(e);
+        }
+        
+        
+    }
 }