]> git.aero2k.de Git - tmp/jakarta-migration.git/blob
363719df3c0356e4a45414c53788b7877484651c
[tmp/jakarta-migration.git] /
1 package org.collectionspace.authentication;
2
3 import java.sql.Connection;
4 import java.sql.PreparedStatement;
5 import java.sql.ResultSet;
6 import java.sql.SQLException;
7
8 import javax.security.auth.login.AccountException;
9 import javax.security.auth.login.AccountNotFoundException;
10
11 import org.collectionspace.authentication.realm.db.CSpaceDbRealm;
12 import org.postgresql.util.PSQLState;
13 import org.springframework.context.ApplicationListener;
14 import org.springframework.security.authentication.event.AuthenticationSuccessEvent;
15 import org.springframework.security.core.Authentication;
16 import org.springframework.security.oauth2.server.authorization.authentication.OAuth2AuthorizationCodeRequestAuthenticationToken;
17 import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken;
18
19 public class CSpaceAuthenticationSuccessEvent implements ApplicationListener<AuthenticationSuccessEvent> {
20
21     private static final String UPDATE_USER_SQL =
22             "UPDATE users SET lastlogin = now() WHERE username = ?";
23
24     private static final String DELETE_EXPIRED_AUTHORIZATIONS_SQL =
25             "DELETE FROM oauth2_authorization WHERE access_token_expires_at < now()";
26
27     @Override
28     public void onApplicationEvent(AuthenticationSuccessEvent event) {
29         Object eventSource = event.getSource();
30
31         if (
32             eventSource instanceof Authentication
33             // Ignore authentication via JWT token, since this indicates a continuing session -- not what a user would consider a "log in"
34             && !(eventSource instanceof JwtAuthenticationToken)
35             // Ignore authorization code requests
36             && !(eventSource instanceof OAuth2AuthorizationCodeRequestAuthenticationToken)
37         ) {
38             Authentication authentication = (Authentication) eventSource;
39
40             if (authentication.getPrincipal() instanceof CSpaceUser) {
41                 CSpaceDbRealm cspaceDbRealm = new CSpaceDbRealm();
42                 CSpaceUser cspaceUser = (CSpaceUser) authentication.getPrincipal();
43                 String username = cspaceUser.getUsername();
44
45                 try {
46                     setLastLogin(cspaceDbRealm, username);
47                 } catch (Exception e) {
48                     e.printStackTrace();
49                 }
50
51                 try {
52                     deleteExpiredAuthorizations(cspaceDbRealm);
53                 } catch (Exception e) {
54                     e.printStackTrace();
55                 }
56             }
57         }
58     }
59
60         private void setLastLogin(CSpaceDbRealm cspaceDbRealm, String username) throws AccountException {
61         Connection conn = null;
62         PreparedStatement ps = null;
63         ResultSet rs = null;
64
65         try {
66             conn = cspaceDbRealm.getConnection();
67             ps = conn.prepareStatement(UPDATE_USER_SQL);
68             ps.setString(1, username);
69             int affected = ps.executeUpdate();
70             if (affected < 1) {
71                 String errMsg = String.format("No matching username '%s' found.", username);
72                 throw new AccountException(errMsg);
73             }
74         } catch (SQLException ex) {
75                 // Assuming PostgreSQL
76             if (PSQLState.UNDEFINED_COLUMN.getState().equals(ex.getSQLState())) {
77                 System.err.println("'users' table is missing 'lastlogin' column.");
78             } else {
79                 AccountException ae = new AccountException("Authentication query failed: " + ex.getLocalizedMessage());
80                 ae.initCause(ex);
81                 throw ae;
82             }
83         } catch (AccountNotFoundException ex) {
84             throw ex;
85         } catch (Exception ex) {
86             AccountException ae = new AccountException("Unknown Exception");
87             ae.initCause(ex);
88             throw ae;
89         } finally {
90             if (rs != null) {
91                 try {
92                     rs.close();
93                 } catch (SQLException e) {
94                 }
95             }
96             if (ps != null) {
97                 try {
98                     ps.close();
99                 } catch (SQLException e) {
100                 }
101             }
102             if (conn != null) {
103                 try {
104                     conn.close();
105                 } catch (SQLException ex) {
106                 }
107             }
108         }
109     }
110
111     private void deleteExpiredAuthorizations(CSpaceDbRealm cspaceDbRealm) throws AccountException {
112         Connection conn = null;
113         PreparedStatement ps = null;
114         ResultSet rs = null;
115
116         try {
117             conn = cspaceDbRealm.getConnection();
118             ps = conn.prepareStatement(DELETE_EXPIRED_AUTHORIZATIONS_SQL);
119             ps.executeUpdate();
120         } catch (Exception ex) {
121             AccountException ae = new AccountException("Unknown Exception");
122             ae.initCause(ex);
123             throw ae;
124         } finally {
125             if (rs != null) {
126                 try {
127                     rs.close();
128                 } catch (SQLException e) {
129                 }
130             }
131             if (ps != null) {
132                 try {
133                     ps.close();
134                 } catch (SQLException e) {
135                 }
136             }
137             if (conn != null) {
138                 try {
139                     conn.close();
140                 } catch (SQLException ex) {
141                 }
142             }
143         }
144     }
145 }