added login and logout activity logs

This commit is contained in:
anhefti 2020-07-06 16:29:31 +02:00
parent 6ab849d40d
commit 36364ed607
8 changed files with 109 additions and 17 deletions

View file

@ -41,8 +41,11 @@ public final class API {
public static final String OAUTH_TOKEN_ENDPOINT = OAUTH_ENDPOINT + "/token"; public static final String OAUTH_TOKEN_ENDPOINT = OAUTH_ENDPOINT + "/token";
public static final String OAUTH_REVOKE_TOKEN_ENDPOINT = OAUTH_ENDPOINT + "/revoke-token"; public static final String OAUTH_REVOKE_TOKEN_ENDPOINT = OAUTH_ENDPOINT + "/revoke-token";
public static final String CURRENT_USER_ENDPOINT = API.USER_ACCOUNT_ENDPOINT + "/me"; public static final String CURRENT_USER_PATH_SEGMENT = "/me";
public static final String CURRENT_USER_ENDPOINT = API.USER_ACCOUNT_ENDPOINT + CURRENT_USER_PATH_SEGMENT;
public static final String SELF_PATH_SEGMENT = "/self"; public static final String SELF_PATH_SEGMENT = "/self";
public static final String LOGIN_PATH_SEGMENT = "/loglogin";
public static final String LOGOUT_PATH_SEGMENT = "/loglogout";
public static final String INFO_ENDPOINT = "/info"; public static final String INFO_ENDPOINT = "/info";
public static final String INFO_PARAM_INST_SUFFIX = "urlSuffix"; public static final String INFO_PARAM_INST_SUFFIX = "urlSuffix";

View file

@ -18,5 +18,7 @@ public enum UserLogActivityType {
PASSWORD_CHANGE, PASSWORD_CHANGE,
DEACTIVATE, DEACTIVATE,
ACTIVATE, ACTIVATE,
DELETE DELETE,
LOGIN,
LOGOUT
} }

View file

@ -8,12 +8,15 @@
package ch.ethz.seb.sebserver.gui.service.remote.webservice.auth; package ch.ethz.seb.sebserver.gui.service.remote.webservice.auth;
import ch.ethz.seb.sebserver.ClientHttpRequestFactoryService; import java.io.IOException;
import ch.ethz.seb.sebserver.gbl.model.user.UserInfo; import java.net.URI;
import ch.ethz.seb.sebserver.gbl.model.user.UserRole; import java.nio.charset.StandardCharsets;
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile; import java.util.Arrays;
import ch.ethz.seb.sebserver.gbl.util.Result; import java.util.Collections;
import ch.ethz.seb.sebserver.gbl.util.Utils; import java.util.List;
import javax.servlet.http.HttpSession;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -41,13 +44,12 @@ import org.springframework.web.client.ResponseExtractor;
import org.springframework.web.client.RestClientException; import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate; import org.springframework.web.client.RestTemplate;
import javax.servlet.http.HttpSession; import ch.ethz.seb.sebserver.ClientHttpRequestFactoryService;
import java.io.IOException; import ch.ethz.seb.sebserver.gbl.model.user.UserInfo;
import java.net.URI; import ch.ethz.seb.sebserver.gbl.model.user.UserRole;
import java.nio.charset.StandardCharsets; import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
import java.util.Arrays; import ch.ethz.seb.sebserver.gbl.util.Result;
import java.util.Collections; import ch.ethz.seb.sebserver.gbl.util.Utils;
import java.util.List;
@Lazy @Lazy
@Component @Component
@ -148,6 +150,8 @@ public class OAuth2AuthorizationContextHolder implements AuthorizationContextHol
private final DisposableOAuth2RestTemplate restTemplate; private final DisposableOAuth2RestTemplate restTemplate;
private final String revokeTokenURI; private final String revokeTokenURI;
private final String currentUserURI; private final String currentUserURI;
private final String loginLogURI;
private final String logoutLogURI;
private Result<UserInfo> loggedInUser = null; private Result<UserInfo> loggedInUser = null;
@ -173,6 +177,8 @@ public class OAuth2AuthorizationContextHolder implements AuthorizationContextHol
this.revokeTokenURI = webserviceURIService.getOAuthRevokeTokenURI(); this.revokeTokenURI = webserviceURIService.getOAuthRevokeTokenURI();
this.currentUserURI = webserviceURIService.getCurrentUserRequestURI(); this.currentUserURI = webserviceURIService.getCurrentUserRequestURI();
this.loginLogURI = webserviceURIService.getLoginLogPostURI();
this.logoutLogURI = webserviceURIService.getLogoutLogPostURI();
} }
@Override @Override
@ -216,6 +222,19 @@ public class OAuth2AuthorizationContextHolder implements AuthorizationContextHol
this.restTemplate.getAccessToken(); this.restTemplate.getAccessToken();
log.debug("Got token for user: {}", username); log.debug("Got token for user: {}", username);
this.loggedInUser = getLoggedInUser(); this.loggedInUser = getLoggedInUser();
// call log login on webservice API
try {
final ResponseEntity<Void> response = this.restTemplate.postForEntity(
this.loginLogURI,
null,
Void.class);
if (response.getStatusCode() != HttpStatus.OK) {
log.error("Failed to log login: {}", response.getStatusCode());
}
} catch (final Exception e) {
log.error("Failed to log login: {}", e.getMessage());
}
return true; return true;
} catch (final OAuth2AccessDeniedException | AccessDeniedException e) { } catch (final OAuth2AccessDeniedException | AccessDeniedException e) {
log.info("Access Denied for user: {}", username); log.info("Access Denied for user: {}", username);
@ -225,6 +244,19 @@ public class OAuth2AuthorizationContextHolder implements AuthorizationContextHol
@Override @Override
public boolean logout() { public boolean logout() {
// call log logout on webservice API
try {
final ResponseEntity<Void> response = this.restTemplate.postForEntity(
this.logoutLogURI,
null,
Void.class);
if (response.getStatusCode() != HttpStatus.OK) {
log.error("Failed to log logout: {}", response.getStatusCode());
}
} catch (final Exception e) {
log.error("Failed to log logout: {}", e.getMessage());
}
// set this context invalid to force creation of a new context on next request // set this context invalid to force creation of a new context on next request
this.valid = false; this.valid = false;
this.loggedInUser = null; this.loggedInUser = null;

View file

@ -31,7 +31,8 @@ public class WebserviceURIService {
@Value("${sebserver.gui.webservice.apipath}") final String webserviceAPIPath) { @Value("${sebserver.gui.webservice.apipath}") final String webserviceAPIPath) {
this.servletContextPath = servletContextPath; this.servletContextPath = servletContextPath;
this.webserviceServerAddress = webserviceProtocol + "://" + webserviceServerAddress + ":" + webserviceServerPort; this.webserviceServerAddress =
webserviceProtocol + "://" + webserviceServerAddress + ":" + webserviceServerPort;
this.webserviceURIBuilder = UriComponentsBuilder this.webserviceURIBuilder = UriComponentsBuilder
.fromHttpUrl(webserviceProtocol + "://" + webserviceServerAddress) .fromHttpUrl(webserviceProtocol + "://" + webserviceServerAddress)
.port(webserviceServerPort) .port(webserviceServerPort)
@ -66,4 +67,16 @@ public class WebserviceURIService {
.path(API.CURRENT_USER_ENDPOINT) .path(API.CURRENT_USER_ENDPOINT)
.toUriString(); .toUriString();
} }
public String getLoginLogPostURI() {
return getURIBuilder()
.path(API.USER_ACCOUNT_ENDPOINT + API.LOGIN_PATH_SEGMENT)
.toUriString();
}
public String getLogoutLogPostURI() {
return getURIBuilder()
.path(API.USER_ACCOUNT_ENDPOINT + API.LOGOUT_PATH_SEGMENT)
.toUriString();
}
} }

View file

@ -15,6 +15,7 @@ import ch.ethz.seb.sebserver.gbl.api.EntityType;
import ch.ethz.seb.sebserver.gbl.model.Entity; import ch.ethz.seb.sebserver.gbl.model.Entity;
import ch.ethz.seb.sebserver.gbl.model.user.UserAccount; import ch.ethz.seb.sebserver.gbl.model.user.UserAccount;
import ch.ethz.seb.sebserver.gbl.model.user.UserActivityLog; import ch.ethz.seb.sebserver.gbl.model.user.UserActivityLog;
import ch.ethz.seb.sebserver.gbl.model.user.UserInfo;
import ch.ethz.seb.sebserver.gbl.model.user.UserLogActivityType; import ch.ethz.seb.sebserver.gbl.model.user.UserLogActivityType;
import ch.ethz.seb.sebserver.gbl.util.Result; import ch.ethz.seb.sebserver.gbl.util.Result;
import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.impl.SEBServerUser; import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.impl.SEBServerUser;
@ -24,6 +25,18 @@ public interface UserActivityLogDAO extends
EntityDAO<UserActivityLog, UserActivityLog>, EntityDAO<UserActivityLog, UserActivityLog>,
UserRelatedEntityDAO<UserActivityLog> { UserRelatedEntityDAO<UserActivityLog> {
/** Create a user activity log entry for the current users login action
*
* @param user the UserInfo
* @return Result of the Entity or referring to an Error if happened */
Result<UserInfo> logLogin(UserInfo user);
/** Create a user activity log entry for the current user logut action
*
* @param user the UserInfo
* @return Result of the Entity or referring to an Error if happened */
Result<UserInfo> logLogout(UserInfo user);
/** Create a user activity log entry for the current user of activity type CREATE /** Create a user activity log entry for the current user of activity type CREATE
* *
* @param entity the Entity * @param entity the Entity

View file

@ -38,6 +38,7 @@ import ch.ethz.seb.sebserver.gbl.model.Entity;
import ch.ethz.seb.sebserver.gbl.model.EntityKey; import ch.ethz.seb.sebserver.gbl.model.EntityKey;
import ch.ethz.seb.sebserver.gbl.model.user.UserAccount; import ch.ethz.seb.sebserver.gbl.model.user.UserAccount;
import ch.ethz.seb.sebserver.gbl.model.user.UserActivityLog; import ch.ethz.seb.sebserver.gbl.model.user.UserActivityLog;
import ch.ethz.seb.sebserver.gbl.model.user.UserInfo;
import ch.ethz.seb.sebserver.gbl.model.user.UserLogActivityType; import ch.ethz.seb.sebserver.gbl.model.user.UserLogActivityType;
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile; import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
import ch.ethz.seb.sebserver.gbl.util.Result; import ch.ethz.seb.sebserver.gbl.util.Result;
@ -82,6 +83,16 @@ public class UserActivityLogDAOImpl implements UserActivityLogDAO {
return EntityType.USER_ACTIVITY_LOG; return EntityType.USER_ACTIVITY_LOG;
} }
@Override
public Result<UserInfo> logLogin(final UserInfo user) {
return log(UserLogActivityType.LOGIN, user);
}
@Override
public Result<UserInfo> logLogout(final UserInfo user) {
return log(UserLogActivityType.LOGOUT, user);
}
@Override @Override
@Transactional @Transactional
public <E extends Entity> Result<E> logCreate(final E entity) { public <E extends Entity> Result<E> logCreate(final E entity) {

View file

@ -83,7 +83,7 @@ public class UserAccountController extends ActivatableEntityController<UserInfo,
this.userPasswordEncoder = userPasswordEncoder; this.userPasswordEncoder = userPasswordEncoder;
} }
@RequestMapping(path = "/me", method = RequestMethod.GET) @RequestMapping(path = API.CURRENT_USER_PATH_SEGMENT, method = RequestMethod.GET)
public UserInfo loggedInUser() { public UserInfo loggedInUser() {
return this.authorization return this.authorization
.getUserService() .getUserService()
@ -91,6 +91,22 @@ public class UserAccountController extends ActivatableEntityController<UserInfo,
.getUserInfo(); .getUserInfo();
} }
@RequestMapping(path = API.LOGIN_PATH_SEGMENT, method = RequestMethod.POST)
public void logLogin() {
this.userActivityLogDAO.logLogin(this.authorization
.getUserService()
.getCurrentUser()
.getUserInfo());
}
@RequestMapping(path = API.LOGOUT_PATH_SEGMENT, method = RequestMethod.POST)
public void logLogout() {
this.userActivityLogDAO.logLogout(this.authorization
.getUserService()
.getCurrentUser()
.getUserInfo());
}
@Override @Override
protected SqlTable getSQLTableOfEntity() { protected SqlTable getSQLTableOfEntity() {
return UserRecordDynamicSqlSupport.userRecord; return UserRecordDynamicSqlSupport.userRecord;

View file

@ -46,6 +46,8 @@ sebserver.overall.types.activityType.PASSWORD_CHANGE=Password Change
sebserver.overall.types.activityType.DEACTIVATE=Deactivate sebserver.overall.types.activityType.DEACTIVATE=Deactivate
sebserver.overall.types.activityType.ACTIVATE=Activate sebserver.overall.types.activityType.ACTIVATE=Activate
sebserver.overall.types.activityType.DELETE=Delete sebserver.overall.types.activityType.DELETE=Delete
sebserver.overall.types.activityType.LOGIN=Login
sebserver.overall.types.activityType.LOGOUT=Logout
sebserver.overall.types.entityType.CONFIGURATION_ATTRIBUTE=Configuration Attribute sebserver.overall.types.entityType.CONFIGURATION_ATTRIBUTE=Configuration Attribute
sebserver.overall.types.entityType.CONFIGURATION_VALUE=Configuration Value sebserver.overall.types.entityType.CONFIGURATION_VALUE=Configuration Value