diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/JDBCAuthenticationProviderService.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/JDBCAuthenticationProviderService.java index 646bf20d3..1bb2c68e7 100644 --- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/JDBCAuthenticationProviderService.java +++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/JDBCAuthenticationProviderService.java @@ -139,6 +139,7 @@ public class JDBCAuthenticationProviderService implements AuthenticationProvider // Initialize the UserContext with the user account and return it. context.init(user.getCurrentUser()); + context.recordUserLogin(); return context; } diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/ModeledUserContext.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/ModeledUserContext.java index e98a25a04..fe60a5faf 100644 --- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/ModeledUserContext.java +++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/ModeledUserContext.java @@ -48,6 +48,7 @@ import org.apache.guacamole.net.auth.ConnectionGroup; import org.apache.guacamole.net.auth.Directory; import org.apache.guacamole.net.auth.SharingProfile; import org.apache.guacamole.net.auth.User; +import org.apache.guacamole.net.auth.UserContext; import org.apache.guacamole.net.auth.UserGroup; /** @@ -117,6 +118,12 @@ public class ModeledUserContext extends RestrictedObject @Inject private Provider userRecordSetProvider; + /** + * Provider for retrieving UserContext instances. + */ + @Inject + private Provider userContextProvider; + /** * Mapper for user login records. */ @@ -124,7 +131,10 @@ public class ModeledUserContext extends RestrictedObject private UserRecordMapper userRecordMapper; /** - * The activity record associated with this user's Guacamole session. + * The activity record associated with this user's Guacamole session. If + * this user's session will not have an associated activity record, such as + * a temporary privileged session created via getPrivileged(), this will be + * null. */ private ActivityRecordModel userRecord; @@ -141,15 +151,40 @@ public class ModeledUserContext extends RestrictedObject sharingProfileDirectory.init(currentUser); activeConnectionDirectory.init(currentUser); + } + + /** + * Records that the user associated with this UserContext has logged in, + * creating a partial activity record. The resulting activity record will + * contain a start date only, with the end date being automatically + * populated when this UserContext is invalidated. If this function is + * invoked more than once for the same UserContext, only the first + * invocation has any effect. If this function is never invoked, no + * activity record will be recorded, including when this UserContext is + * invalidated. + */ + public void recordUserLogin() { + + // Do nothing if invoked multiple times + if (userRecord != null) + return; + // Create login record for user userRecord = new ActivityRecordModel(); - userRecord.setUsername(currentUser.getIdentifier()); + userRecord.setUsername(getCurrentUser().getIdentifier()); userRecord.setStartDate(new Date()); - userRecord.setRemoteHost(currentUser.getCredentials().getRemoteAddress()); + userRecord.setRemoteHost(getCurrentUser().getCredentials().getRemoteAddress()); // Insert record representing login userRecordMapper.insert(userRecord); + + } + @Override + public UserContext getPrivileged() { + ModeledUserContext context = userContextProvider.get(); + context.init(new PrivilegedModeledAuthenticatedUser(getCurrentUser())); + return context; } @Override @@ -253,9 +288,11 @@ public class ModeledUserContext extends RestrictedObject @Override public void invalidate() { - // Record logout time - userRecord.setEndDate(new Date()); - userRecordMapper.update(userRecord); + // Record logout time only if login time was recorded + if (userRecord != null) { + userRecord.setEndDate(new Date()); + userRecordMapper.update(userRecord); + } } diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/PrivilegedModeledAuthenticatedUser.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/PrivilegedModeledAuthenticatedUser.java new file mode 100644 index 000000000..82fcf0852 --- /dev/null +++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/PrivilegedModeledAuthenticatedUser.java @@ -0,0 +1,50 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.guacamole.auth.jdbc.user; + +import org.apache.guacamole.GuacamoleException; + +/** + * A ModeledAuthenticatedUser which is always privileged, returning true for + * every call to isPrivileged(). + */ +public class PrivilegedModeledAuthenticatedUser extends ModeledAuthenticatedUser { + + /** + * Creates a new PrivilegedModeledAuthenticatedUser which shares the same + * user identity as the given ModeledAuthenticatedUser. Regardless of the + * privileges explicitly granted to the given user, the resulting + * PrivilegedModeledAuthenticatedUser will always assert that it is + * privileged. + * + * @param authenticatedUser + * The ModeledAuthenticatedUser that declares the identity of the user + * in question. + */ + public PrivilegedModeledAuthenticatedUser(ModeledAuthenticatedUser authenticatedUser){ + super(authenticatedUser, authenticatedUser.getModelAuthenticationProvider(), authenticatedUser.getUser()); + } + + @Override + public boolean isPrivileged() throws GuacamoleException { + return true; + } + +}