SEBSERV-191 finished back-end implementation
This commit is contained in:
parent
2f2a3670b7
commit
c414586fec
6 changed files with 152 additions and 27 deletions
|
@ -197,6 +197,8 @@ public final class API {
|
||||||
|
|
||||||
public static final String SEB_CLIENT_EVENT_ENDPOINT = "/seb-client-event";
|
public static final String SEB_CLIENT_EVENT_ENDPOINT = "/seb-client-event";
|
||||||
public static final String SEB_CLIENT_EVENT_SEARCH_PATH_SEGMENT = "/search";
|
public static final String SEB_CLIENT_EVENT_SEARCH_PATH_SEGMENT = "/search";
|
||||||
|
public static final String SEB_CLIENT_EVENT_EXPORT_PATH_SEGMENT = "/export";
|
||||||
|
public static final String SEB_CLIENT_EVENT_EXPORT_TYPE = "exportType";
|
||||||
public static final String SEB_CLIENT_EVENT_EXTENDED_PAGE_ENDPOINT = SEB_CLIENT_EVENT_ENDPOINT
|
public static final String SEB_CLIENT_EVENT_EXTENDED_PAGE_ENDPOINT = SEB_CLIENT_EVENT_ENDPOINT
|
||||||
+ SEB_CLIENT_EVENT_SEARCH_PATH_SEGMENT;
|
+ SEB_CLIENT_EVENT_SEARCH_PATH_SEGMENT;
|
||||||
|
|
||||||
|
|
|
@ -666,4 +666,11 @@ public final class Utils {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String toCSVString(final String text) {
|
||||||
|
if (StringUtils.isBlank(text)) {
|
||||||
|
return StringUtils.EMPTY;
|
||||||
|
}
|
||||||
|
return Constants.DOUBLE_QUOTE + text.replace("\"", "\"\"") + Constants.DOUBLE_QUOTE;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,13 +10,11 @@ package ch.ethz.seb.sebserver.webservice.servicelayer.exam;
|
||||||
|
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.function.Predicate;
|
|
||||||
|
|
||||||
import org.springframework.scheduling.annotation.Async;
|
import org.springframework.scheduling.annotation.Async;
|
||||||
|
|
||||||
import ch.ethz.seb.sebserver.gbl.async.AsyncServiceSpringConfig;
|
import ch.ethz.seb.sebserver.gbl.async.AsyncServiceSpringConfig;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.EntityProcessingReport;
|
import ch.ethz.seb.sebserver.gbl.model.EntityProcessingReport;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.session.ClientEvent;
|
|
||||||
import ch.ethz.seb.sebserver.gbl.model.session.ClientEvent.ExportType;
|
import ch.ethz.seb.sebserver.gbl.model.session.ClientEvent.ExportType;
|
||||||
import ch.ethz.seb.sebserver.gbl.util.Result;
|
import ch.ethz.seb.sebserver.gbl.util.Result;
|
||||||
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.FilterMap;
|
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.FilterMap;
|
||||||
|
@ -30,7 +28,6 @@ public interface SEBClientEventAdminService {
|
||||||
OutputStream output,
|
OutputStream output,
|
||||||
FilterMap filterMap,
|
FilterMap filterMap,
|
||||||
String sort,
|
String sort,
|
||||||
final Predicate<ClientEvent> predicate,
|
|
||||||
ExportType exportType,
|
ExportType exportType,
|
||||||
boolean includeConnectionDetails,
|
boolean includeConnectionDetails,
|
||||||
boolean includeExamDetails);
|
boolean includeExamDetails);
|
||||||
|
|
|
@ -13,11 +13,11 @@ import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.EnumMap;
|
import java.util.EnumMap;
|
||||||
|
import java.util.EnumSet;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.function.Predicate;
|
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
@ -31,14 +31,17 @@ import ch.ethz.seb.sebserver.gbl.model.EntityKey;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.EntityProcessingReport;
|
import ch.ethz.seb.sebserver.gbl.model.EntityProcessingReport;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.EntityProcessingReport.ErrorEntry;
|
import ch.ethz.seb.sebserver.gbl.model.EntityProcessingReport.ErrorEntry;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.exam.Exam;
|
import ch.ethz.seb.sebserver.gbl.model.exam.Exam;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.session.ClientEvent;
|
|
||||||
import ch.ethz.seb.sebserver.gbl.model.session.ClientEvent.ExportType;
|
import ch.ethz.seb.sebserver.gbl.model.session.ClientEvent.ExportType;
|
||||||
|
import ch.ethz.seb.sebserver.gbl.model.user.UserRole;
|
||||||
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;
|
||||||
|
import ch.ethz.seb.sebserver.gbl.util.Utils;
|
||||||
import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.ClientEventRecordDynamicSqlSupport;
|
import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.ClientEventRecordDynamicSqlSupport;
|
||||||
import ch.ethz.seb.sebserver.webservice.datalayer.batis.model.ClientConnectionRecord;
|
import ch.ethz.seb.sebserver.webservice.datalayer.batis.model.ClientConnectionRecord;
|
||||||
import ch.ethz.seb.sebserver.webservice.datalayer.batis.model.ClientEventRecord;
|
import ch.ethz.seb.sebserver.webservice.datalayer.batis.model.ClientEventRecord;
|
||||||
import ch.ethz.seb.sebserver.webservice.servicelayer.PaginationService;
|
import ch.ethz.seb.sebserver.webservice.servicelayer.PaginationService;
|
||||||
|
import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.AuthorizationService;
|
||||||
|
import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.impl.SEBServerUser;
|
||||||
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ClientEventDAO;
|
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ClientEventDAO;
|
||||||
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.FilterMap;
|
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.FilterMap;
|
||||||
import ch.ethz.seb.sebserver.webservice.servicelayer.exam.SEBClientEventAdminService;
|
import ch.ethz.seb.sebserver.webservice.servicelayer.exam.SEBClientEventAdminService;
|
||||||
|
@ -55,16 +58,19 @@ public class SEBClientEventAdminServiceImpl implements SEBClientEventAdminServic
|
||||||
private final ClientEventDAO clientEventDAO;
|
private final ClientEventDAO clientEventDAO;
|
||||||
private final SEBClientEventExportTransactionHandler sebClientEventExportTransactionHandler;
|
private final SEBClientEventExportTransactionHandler sebClientEventExportTransactionHandler;
|
||||||
private final EnumMap<ExportType, SEBClientEventExporter> exporter;
|
private final EnumMap<ExportType, SEBClientEventExporter> exporter;
|
||||||
|
private final AuthorizationService authorizationService;
|
||||||
|
|
||||||
public SEBClientEventAdminServiceImpl(
|
public SEBClientEventAdminServiceImpl(
|
||||||
final PaginationService paginationService,
|
final PaginationService paginationService,
|
||||||
final ClientEventDAO clientEventDAO,
|
final ClientEventDAO clientEventDAO,
|
||||||
final SEBClientEventExportTransactionHandler sebClientEventExportTransactionHandler,
|
final SEBClientEventExportTransactionHandler sebClientEventExportTransactionHandler,
|
||||||
final Collection<SEBClientEventExporter> exporter) {
|
final Collection<SEBClientEventExporter> exporter,
|
||||||
|
final AuthorizationService authorizationService) {
|
||||||
|
|
||||||
this.paginationService = paginationService;
|
this.paginationService = paginationService;
|
||||||
this.clientEventDAO = clientEventDAO;
|
this.clientEventDAO = clientEventDAO;
|
||||||
this.sebClientEventExportTransactionHandler = sebClientEventExportTransactionHandler;
|
this.sebClientEventExportTransactionHandler = sebClientEventExportTransactionHandler;
|
||||||
|
this.authorizationService = authorizationService;
|
||||||
|
|
||||||
this.exporter = new EnumMap<>(ExportType.class);
|
this.exporter = new EnumMap<>(ExportType.class);
|
||||||
exporter.forEach(exp -> this.exporter.putIfAbsent(exp.exportType(), exp));
|
exporter.forEach(exp -> this.exporter.putIfAbsent(exp.exportType(), exp));
|
||||||
|
@ -102,7 +108,6 @@ public class SEBClientEventAdminServiceImpl implements SEBClientEventAdminServic
|
||||||
final OutputStream output,
|
final OutputStream output,
|
||||||
final FilterMap filterMap,
|
final FilterMap filterMap,
|
||||||
final String sort,
|
final String sort,
|
||||||
final Predicate<ClientEvent> predicate,
|
|
||||||
final ExportType exportType,
|
final ExportType exportType,
|
||||||
final boolean includeConnectionDetails,
|
final boolean includeConnectionDetails,
|
||||||
final boolean includeExamDetails) {
|
final boolean includeExamDetails) {
|
||||||
|
@ -111,7 +116,7 @@ public class SEBClientEventAdminServiceImpl implements SEBClientEventAdminServic
|
||||||
this.exporter.get(exportType),
|
this.exporter.get(exportType),
|
||||||
includeConnectionDetails,
|
includeConnectionDetails,
|
||||||
includeExamDetails,
|
includeExamDetails,
|
||||||
new Pager(filterMap, sort, predicate),
|
new Pager(filterMap, sort),
|
||||||
output)
|
output)
|
||||||
.run();
|
.run();
|
||||||
|
|
||||||
|
@ -147,17 +152,28 @@ public class SEBClientEventAdminServiceImpl implements SEBClientEventAdminServic
|
||||||
|
|
||||||
public void run() {
|
public void run() {
|
||||||
|
|
||||||
|
final SEBServerUser currentUser = SEBClientEventAdminServiceImpl.this.authorizationService
|
||||||
|
.getUserService()
|
||||||
|
.getCurrentUser();
|
||||||
|
final EnumSet<UserRole> userRoles = currentUser.getUserRoles();
|
||||||
|
final boolean isSupporterOnly = userRoles.size() == 1 && userRoles.contains(UserRole.EXAM_SUPPORTER);
|
||||||
|
|
||||||
// first stream header line
|
// first stream header line
|
||||||
this.exporter.streamHeader(this.output, this.includeConnectionDetails, this.includeExamDetails);
|
this.exporter.streamHeader(this.output, this.includeConnectionDetails, this.includeExamDetails);
|
||||||
|
|
||||||
// then batch with the pager and stream line per line
|
// then batch with the pager and stream line per line
|
||||||
while (this.pager.hasNext()) {
|
while (this.pager.hasNext()) {
|
||||||
this.pager.next().forEach(rec -> {
|
this.pager.next().forEach(rec -> {
|
||||||
this.exporter.streamData(
|
|
||||||
this.output,
|
final Exam exam = getExam(rec.getClientConnectionId());
|
||||||
rec,
|
|
||||||
this.includeConnectionDetails ? getConnection(rec.getClientConnectionId()) : null,
|
if (!isSupporterOnly || exam.isOwner(currentUser.uuid())) {
|
||||||
this.includeExamDetails ? getExam(rec.getClientConnectionId()) : null);
|
this.exporter.streamData(
|
||||||
|
this.output,
|
||||||
|
rec,
|
||||||
|
this.includeConnectionDetails ? getConnection(rec.getClientConnectionId()) : null,
|
||||||
|
this.includeExamDetails ? getExam(rec.getClientConnectionId()) : null);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -195,7 +211,6 @@ public class SEBClientEventAdminServiceImpl implements SEBClientEventAdminServic
|
||||||
|
|
||||||
private final FilterMap filterMap;
|
private final FilterMap filterMap;
|
||||||
private final String sort;
|
private final String sort;
|
||||||
private final Predicate<ClientEvent> predicate;
|
|
||||||
|
|
||||||
private int pageNumber = 0;
|
private int pageNumber = 0;
|
||||||
private final int pageSize = 100;
|
private final int pageSize = 100;
|
||||||
|
@ -204,12 +219,10 @@ public class SEBClientEventAdminServiceImpl implements SEBClientEventAdminServic
|
||||||
|
|
||||||
public Pager(
|
public Pager(
|
||||||
final FilterMap filterMap,
|
final FilterMap filterMap,
|
||||||
final String sort,
|
final String sort) {
|
||||||
final Predicate<ClientEvent> predicate) {
|
|
||||||
|
|
||||||
this.filterMap = filterMap;
|
this.filterMap = filterMap;
|
||||||
this.sort = sort;
|
this.sort = sort;
|
||||||
this.predicate = predicate;
|
|
||||||
|
|
||||||
fetchNext();
|
fetchNext();
|
||||||
}
|
}
|
||||||
|
@ -235,7 +248,7 @@ public class SEBClientEventAdminServiceImpl implements SEBClientEventAdminServic
|
||||||
this.sort,
|
this.sort,
|
||||||
ClientEventRecordDynamicSqlSupport.clientEventRecord.name(),
|
ClientEventRecordDynamicSqlSupport.clientEventRecord.name(),
|
||||||
() -> SEBClientEventAdminServiceImpl.this.sebClientEventExportTransactionHandler
|
() -> SEBClientEventAdminServiceImpl.this.sebClientEventExportTransactionHandler
|
||||||
.allMatching(this.filterMap, this.predicate))
|
.allMatching(this.filterMap, Utils.truePredicate()))
|
||||||
.getOrThrow();
|
.getOrThrow();
|
||||||
|
|
||||||
this.pageNumber++;
|
this.pageNumber++;
|
||||||
|
|
|
@ -8,16 +8,25 @@
|
||||||
|
|
||||||
package ch.ethz.seb.sebserver.webservice.servicelayer.exam.impl;
|
package ch.ethz.seb.sebserver.webservice.servicelayer.exam.impl;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import ch.ethz.seb.sebserver.gbl.Constants;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.exam.Exam;
|
import ch.ethz.seb.sebserver.gbl.model.exam.Exam;
|
||||||
|
import ch.ethz.seb.sebserver.gbl.model.session.ClientEvent.EventType;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.session.ClientEvent.ExportType;
|
import ch.ethz.seb.sebserver.gbl.model.session.ClientEvent.ExportType;
|
||||||
|
import ch.ethz.seb.sebserver.gbl.util.Utils;
|
||||||
import ch.ethz.seb.sebserver.webservice.datalayer.batis.model.ClientConnectionRecord;
|
import ch.ethz.seb.sebserver.webservice.datalayer.batis.model.ClientConnectionRecord;
|
||||||
import ch.ethz.seb.sebserver.webservice.datalayer.batis.model.ClientEventRecord;
|
import ch.ethz.seb.sebserver.webservice.datalayer.batis.model.ClientEventRecord;
|
||||||
import ch.ethz.seb.sebserver.webservice.servicelayer.exam.SEBClientEventExporter;
|
import ch.ethz.seb.sebserver.webservice.servicelayer.exam.SEBClientEventExporter;
|
||||||
|
|
||||||
public class SEBClientEventCSVExporter implements SEBClientEventExporter {
|
public class SEBClientEventCSVExporter implements SEBClientEventExporter {
|
||||||
|
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(SEBClientEventCSVExporter.class);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ExportType exportType() {
|
public ExportType exportType() {
|
||||||
return ExportType.CSV;
|
return ExportType.CSV;
|
||||||
|
@ -29,7 +38,24 @@ public class SEBClientEventCSVExporter implements SEBClientEventExporter {
|
||||||
final boolean includeConnectionDetails,
|
final boolean includeConnectionDetails,
|
||||||
final boolean includeExamDetails) {
|
final boolean includeExamDetails) {
|
||||||
|
|
||||||
// TODO
|
final StringBuilder builder = new StringBuilder();
|
||||||
|
builder.append("Event Type,Message,Value,Client Time (UTC),Server Time (UTC)");
|
||||||
|
|
||||||
|
if (includeConnectionDetails) {
|
||||||
|
builder.append(",User Session-ID,Client Machine,Connection Status,Connection Token");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (includeExamDetails) {
|
||||||
|
builder.append("Exam Name,Exam Description,Exam Type,Start Time (LMS),End Time (LMS)");
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.append(Constants.CARRIAGE_RETURN);
|
||||||
|
|
||||||
|
try {
|
||||||
|
output.write(Utils.toByteArray(builder));
|
||||||
|
} catch (final IOException e) {
|
||||||
|
log.error("Failed to stream header: ", e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -39,11 +65,37 @@ public class SEBClientEventCSVExporter implements SEBClientEventExporter {
|
||||||
final ClientConnectionRecord connectionData,
|
final ClientConnectionRecord connectionData,
|
||||||
final Exam examData) {
|
final Exam examData) {
|
||||||
|
|
||||||
// TODO
|
final StringBuilder builder = new StringBuilder();
|
||||||
}
|
final EventType type = EventType.byId(eventData.getType());
|
||||||
|
|
||||||
private String toCSVString(final String text) {
|
builder.append(type.name());
|
||||||
|
builder.append(Utils.toCSVString(eventData.getText()));
|
||||||
|
builder.append(eventData.getNumericValue());
|
||||||
|
builder.append(Utils.toDateTimeUTC(eventData.getClientTime()));
|
||||||
|
builder.append(Utils.toDateTimeUTC(eventData.getServerTime()));
|
||||||
|
|
||||||
|
if (connectionData != null) {
|
||||||
|
builder.append(Utils.toCSVString(connectionData.getExamUserSessionId()));
|
||||||
|
builder.append(Utils.toCSVString(connectionData.getClientAddress()));
|
||||||
|
builder.append(connectionData.getStatus());
|
||||||
|
builder.append(connectionData.getConnectionToken());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (examData != null) {
|
||||||
|
builder.append(Utils.toCSVString(examData.getName()));
|
||||||
|
builder.append(Utils.toCSVString(examData.getDescription()));
|
||||||
|
builder.append(examData.getType().name());
|
||||||
|
builder.append(examData.getStartTime());
|
||||||
|
builder.append(examData.getEndTime());
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.append(Constants.CARRIAGE_RETURN);
|
||||||
|
|
||||||
|
try {
|
||||||
|
output.write(Utils.toByteArray(builder));
|
||||||
|
} catch (final IOException e) {
|
||||||
|
log.error("Failed to stream header: ", e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,13 +8,19 @@
|
||||||
|
|
||||||
package ch.ethz.seb.sebserver.webservice.weblayer.api;
|
package ch.ethz.seb.sebserver.webservice.weblayer.api;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.EnumSet;
|
import java.util.EnumSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.servlet.ServletOutputStream;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
import org.mybatis.dynamic.sql.SqlTable;
|
import org.mybatis.dynamic.sql.SqlTable;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
import org.springframework.util.MultiValueMap;
|
import org.springframework.util.MultiValueMap;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
@ -31,6 +37,7 @@ import ch.ethz.seb.sebserver.gbl.model.EntityProcessingReport;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.GrantEntity;
|
import ch.ethz.seb.sebserver.gbl.model.GrantEntity;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.Page;
|
import ch.ethz.seb.sebserver.gbl.model.Page;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.session.ClientEvent;
|
import ch.ethz.seb.sebserver.gbl.model.session.ClientEvent;
|
||||||
|
import ch.ethz.seb.sebserver.gbl.model.session.ClientEvent.ExportType;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.session.ExtendedClientEvent;
|
import ch.ethz.seb.sebserver.gbl.model.session.ExtendedClientEvent;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.user.UserRole;
|
import ch.ethz.seb.sebserver.gbl.model.user.UserRole;
|
||||||
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
|
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
|
||||||
|
@ -54,6 +61,8 @@ import ch.ethz.seb.sebserver.webservice.servicelayer.validation.BeanValidationSe
|
||||||
@RequestMapping("${sebserver.webservice.api.admin.endpoint}" + API.SEB_CLIENT_EVENT_ENDPOINT)
|
@RequestMapping("${sebserver.webservice.api.admin.endpoint}" + API.SEB_CLIENT_EVENT_ENDPOINT)
|
||||||
public class ClientEventController extends ReadonlyEntityController<ClientEvent, ClientEvent> {
|
public class ClientEventController extends ReadonlyEntityController<ClientEvent, ClientEvent> {
|
||||||
|
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(ClientEventController.class);
|
||||||
|
|
||||||
private final ExamDAO examDao;
|
private final ExamDAO examDao;
|
||||||
private final ClientEventDAO clientEventDAO;
|
private final ClientEventDAO clientEventDAO;
|
||||||
private final SEBClientEventAdminService sebClientEventAdminService;
|
private final SEBClientEventAdminService sebClientEventAdminService;
|
||||||
|
@ -138,6 +147,49 @@ public class ClientEventController extends ReadonlyEntityController<ClientEvent,
|
||||||
.getOrThrow();
|
.getOrThrow();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@RequestMapping(
|
||||||
|
path = API.SEB_CLIENT_EVENT_EXPORT_PATH_SEGMENT,
|
||||||
|
method = RequestMethod.GET,
|
||||||
|
produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
|
||||||
|
public void exportEvents(
|
||||||
|
@RequestParam(
|
||||||
|
name = API.PARAM_INSTITUTION_ID,
|
||||||
|
required = true,
|
||||||
|
defaultValue = UserService.USERS_INSTITUTION_AS_DEFAULT) final Long institutionId,
|
||||||
|
@RequestParam(name = API.SEB_CLIENT_EVENT_EXPORT_TYPE, required = true) final ExportType type,
|
||||||
|
@RequestParam(name = Page.ATTR_SORT, required = false) final String sort,
|
||||||
|
@RequestParam final MultiValueMap<String, String> allRequestParams,
|
||||||
|
final HttpServletRequest request,
|
||||||
|
final HttpServletResponse response) throws IOException {
|
||||||
|
|
||||||
|
// at least current user must have base read access for specified entity type within its own institution
|
||||||
|
checkReadPrivilege(institutionId);
|
||||||
|
|
||||||
|
final FilterMap filterMap = new FilterMap(allRequestParams, request.getQueryString());
|
||||||
|
populateFilterMap(filterMap, institutionId, sort);
|
||||||
|
|
||||||
|
final ServletOutputStream outputStream = response.getOutputStream();
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
this.sebClientEventAdminService.exportSEBClientLogs(
|
||||||
|
outputStream,
|
||||||
|
filterMap,
|
||||||
|
sort,
|
||||||
|
type,
|
||||||
|
false,
|
||||||
|
false);
|
||||||
|
|
||||||
|
response.setStatus(HttpStatus.OK.value());
|
||||||
|
} catch (final Exception e) {
|
||||||
|
log.error("Unexpected error while trying to export SEB client logs: ", e);
|
||||||
|
response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
|
||||||
|
} finally {
|
||||||
|
outputStream.flush();
|
||||||
|
outputStream.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<EntityDependency> getDependencies(
|
public Collection<EntityDependency> getDependencies(
|
||||||
final String modelId,
|
final String modelId,
|
||||||
|
@ -154,12 +206,14 @@ public class ClientEventController extends ReadonlyEntityController<ClientEvent,
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Result<ClientEvent> checkReadAccess(final ClientEvent entity) {
|
protected Result<ClientEvent> checkReadAccess(final ClientEvent entity) {
|
||||||
|
final EnumSet<UserRole> userRoles = this.authorization
|
||||||
|
.getUserService()
|
||||||
|
.getCurrentUser()
|
||||||
|
.getUserRoles();
|
||||||
|
final boolean isSupporterOnly = userRoles.size() == 1 && userRoles.contains(UserRole.EXAM_SUPPORTER);
|
||||||
|
|
||||||
return Result.tryCatch(() -> {
|
return Result.tryCatch(() -> {
|
||||||
final EnumSet<UserRole> userRoles = this.authorization
|
|
||||||
.getUserService()
|
|
||||||
.getCurrentUser()
|
|
||||||
.getUserRoles();
|
|
||||||
final boolean isSupporterOnly = userRoles.size() == 1 && userRoles.contains(UserRole.EXAM_SUPPORTER);
|
|
||||||
if (isSupporterOnly) {
|
if (isSupporterOnly) {
|
||||||
// check owner grant be getting exam
|
// check owner grant be getting exam
|
||||||
return super.checkReadAccess(entity)
|
return super.checkReadAccess(entity)
|
||||||
|
|
Loading…
Reference in a new issue