From 2ecf709d8d09dfd8adcd5e1c441cdd8f0f762ef4 Mon Sep 17 00:00:00 2001 From: anhefti Date: Mon, 14 Jan 2019 12:59:08 +0100 Subject: [PATCH] SEBSERV-15 #added automatic user activity logging to bulk action service --- .../servicelayer/bulkaction/BulkAction.java | 13 ++++++-- .../bulkaction/BulkActionService.java | 30 +++++++++++++++-- .../weblayer/api/InstitutionController.java | 4 ++- .../weblayer/api/LmsSetupController.java | 21 ++++++++++++ .../webservice/weblayer/api/RestAPI.java | 1 + .../weblayer/api/UserAccountController.java | 4 ++- .../integration/api/UserAPITest.java | 33 +++++++++++++++++++ 7 files changed, 99 insertions(+), 7 deletions(-) create mode 100644 src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/LmsSetupController.java diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/bulkaction/BulkAction.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/bulkaction/BulkAction.java index c0296019..5ae9c073 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/bulkaction/BulkAction.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/bulkaction/BulkAction.java @@ -19,13 +19,20 @@ import java.util.stream.Collectors; import ch.ethz.seb.sebserver.gbl.model.EntityKey; import ch.ethz.seb.sebserver.gbl.model.EntityType; import ch.ethz.seb.sebserver.gbl.util.Result; +import ch.ethz.seb.sebserver.webservice.servicelayer.dao.UserActivityLogDAO.ActivityType; public final class BulkAction { public enum Type { - HARD_DELETE, - DEACTIVATE, - ACTIVATE + HARD_DELETE(ActivityType.DELETE), + DEACTIVATE(ActivityType.DEACTIVATE), + ACTIVATE(ActivityType.ACTIVATE); + + public final ActivityType activityType; + + private Type(final ActivityType activityType) { + this.activityType = activityType; + } } public final Type type; diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/bulkaction/BulkActionService.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/bulkaction/BulkActionService.java index f06f54c2..053c62a4 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/bulkaction/BulkActionService.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/bulkaction/BulkActionService.java @@ -13,17 +13,24 @@ import java.util.List; import org.springframework.stereotype.Service; +import ch.ethz.seb.sebserver.gbl.model.EntityKey; import ch.ethz.seb.sebserver.gbl.model.EntityProcessingReport; import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile; +import ch.ethz.seb.sebserver.webservice.servicelayer.dao.UserActivityLogDAO; @Service @WebServiceProfile public class BulkActionService { private final Collection supporter; + private final UserActivityLogDAO userActivityLogDAO; + + public BulkActionService( + final Collection supporter, + final UserActivityLogDAO userActivityLogDAO) { - public BulkActionService(final Collection supporter) { this.supporter = supporter; + this.userActivityLogDAO = userActivityLogDAO; } public void collectDependencies(final BulkAction action) { @@ -55,8 +62,9 @@ public class BulkActionService { } } - // process bulk action action.result.addAll(supportForSource.processBulkAction(action)); + + processUserActivityLog(action); action.alreadyProcessed = true; } @@ -72,6 +80,24 @@ public class BulkActionService { return report; } + private void processUserActivityLog(final BulkAction action) { + for (final EntityKey key : action.dependencies) { + this.userActivityLogDAO.log( + action.type.activityType, + key.entityType, + key.entityId, + "bulk action dependency"); + } + + for (final EntityKey key : action.sources) { + this.userActivityLogDAO.log( + action.type.activityType, + key.entityType, + key.entityId, + "bulk action source"); + } + } + private BulkActionSupport getSupporterForSource(final BulkAction action) { for (final BulkActionSupport support : this.supporter) { if (support.entityType() == action.sourceType) { diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/InstitutionController.java b/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/InstitutionController.java index bd6e97aa..80a9c183 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/InstitutionController.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/InstitutionController.java @@ -192,7 +192,9 @@ public class InstitutionController { EntityType.INSTITUTION, new EntityKey(id, EntityType.INSTITUTION))); - return this.institutionDAO.byId(id).getOrThrow(); + return this.institutionDAO + .byId(id) + .getOrThrow(); } private Result _saveInstitution(final Institution institution, final PrivilegeType privilegeType) { diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/LmsSetupController.java b/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/LmsSetupController.java new file mode 100644 index 00000000..451fee2c --- /dev/null +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/LmsSetupController.java @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2019 ETH Zürich, Educational Development and Technology (LET) + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +package ch.ethz.seb.sebserver.webservice.weblayer.api; + +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile; + +@WebServiceProfile +@RestController +@RequestMapping("/${sebserver.webservice.api.admin.endpoint}" + RestAPI.ENDPOINT_LMS_SETUP) +public class LmsSetupController { + +} diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/RestAPI.java b/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/RestAPI.java index a2c32c95..682bdb01 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/RestAPI.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/RestAPI.java @@ -11,6 +11,7 @@ package ch.ethz.seb.sebserver.webservice.weblayer.api; public class RestAPI { public static final String ENDPOINT_INSTITUTION = "/institution"; + public static final String ENDPOINT_LMS_SETUP = "/lms_setup"; public static final String ENDPOINT_USER_ACCOUNT = "/useraccount"; diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/UserAccountController.java b/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/UserAccountController.java index 888c6f6b..74077429 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/UserAccountController.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/weblayer/api/UserAccountController.java @@ -200,7 +200,9 @@ public class UserAccountController { EntityType.USER, new EntityKey(uuid, EntityType.USER, false))); - return this.userDao.byUuid(uuid).getOrThrow(); + return this.userDao + .byUuid(uuid) + .getOrThrow(); } private Result _saveUser(final UserMod userData, final PrivilegeType privilegeType) { diff --git a/src/test/java/ch/ethz/seb/sebserver/webservice/integration/api/UserAPITest.java b/src/test/java/ch/ethz/seb/sebserver/webservice/integration/api/UserAPITest.java index 5dd687fe..f086b3e9 100644 --- a/src/test/java/ch/ethz/seb/sebserver/webservice/integration/api/UserAPITest.java +++ b/src/test/java/ch/ethz/seb/sebserver/webservice/integration/api/UserAPITest.java @@ -34,6 +34,7 @@ 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.UserMod; import ch.ethz.seb.sebserver.gbl.model.user.UserRole; +import ch.ethz.seb.sebserver.webservice.servicelayer.dao.UserActivityLogDAO.ActivityType; import ch.ethz.seb.sebserver.webservice.weblayer.api.RestAPI; @Sql(scripts = { "classpath:schema-test.sql", "classpath:data-test.sql" }) @@ -699,6 +700,7 @@ public class UserAPITest extends AdministrationAPIIntegrationTest { @Test public void deactivateUserAccount() throws Exception { + final long timeNow = System.currentTimeMillis(); // only a SEB Administrator or an Institutional administrator should be able to deactivate a user-account final String examAdminToken = getExamAdmin1(); this.mockMvc.perform(post(this.endpoint + RestAPI.ENDPOINT_USER_ACCOUNT + "/user4/deactivate") @@ -717,10 +719,26 @@ public class UserAPITest extends AdministrationAPIIntegrationTest { assertNotNull(deactivatedUser); assertFalse(deactivatedUser.isActive()); + + // check also user activity log + final Collection userLogs = this.jsonMapper.readValue( + this.mockMvc.perform(get(this.endpoint + RestAPI.ENDPOINT_USER_ACTIVITY_LOG + "/user1?from=" + timeNow) + .header("Authorization", "Bearer " + sebAdminToken)) + .andExpect(status().isOk()) + .andReturn().getResponse().getContentAsString(), + new TypeReference>() { + }); + + assertNotNull(userLogs); + assertTrue(userLogs.size() == 1); + final UserActivityLog userLog = userLogs.iterator().next(); + assertEquals(ActivityType.DEACTIVATE, userLog.activityType); + assertEquals("user4", userLog.entityId); } @Test public void activateUserAccount() throws Exception { + final long timeNow = System.currentTimeMillis(); // only a SEB Administrator or an Institutional administrator should be able to deactivate a user-account final String examAdminToken = getExamAdmin1(); this.mockMvc.perform(post(this.endpoint + RestAPI.ENDPOINT_USER_ACCOUNT + "/user6/activate") @@ -739,6 +757,21 @@ public class UserAPITest extends AdministrationAPIIntegrationTest { assertNotNull(activatedUser); assertTrue(activatedUser.isActive()); + + // check also user activity log + final Collection userLogs = this.jsonMapper.readValue( + this.mockMvc.perform(get(this.endpoint + RestAPI.ENDPOINT_USER_ACTIVITY_LOG + "/user1?from=" + timeNow) + .header("Authorization", "Bearer " + sebAdminToken)) + .andExpect(status().isOk()) + .andReturn().getResponse().getContentAsString(), + new TypeReference>() { + }); + + assertNotNull(userLogs); + assertTrue(userLogs.size() == 1); + final UserActivityLog userLog = userLogs.iterator().next(); + assertEquals(ActivityType.ACTIVATE, userLog.activityType); + assertEquals("user6", userLog.entityId); } private UserInfo getUserInfo(final String name, final Collection infos) {