SEBSERV-15 #added automatic user activity logging to bulk action service

This commit is contained in:
anhefti 2019-01-14 12:59:08 +01:00
parent df8aad3fec
commit 2ecf709d8d
7 changed files with 99 additions and 7 deletions

View file

@ -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;

View file

@ -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<BulkActionSupport> supporter;
private final UserActivityLogDAO userActivityLogDAO;
public BulkActionService(
final Collection<BulkActionSupport> supporter,
final UserActivityLogDAO userActivityLogDAO) {
public BulkActionService(final Collection<BulkActionSupport> 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) {

View file

@ -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<Institution> _saveInstitution(final Institution institution, final PrivilegeType privilegeType) {

View file

@ -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 {
}

View file

@ -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";

View file

@ -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<UserInfo> _saveUser(final UserMod userData, final PrivilegeType privilegeType) {

View file

@ -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<UserActivityLog> 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<Collection<UserActivityLog>>() {
});
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<UserActivityLog> 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<Collection<UserActivityLog>>() {
});
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<UserInfo> infos) {