fixed privilege check on SEB Client Events list and update quiz filter

This commit is contained in:
anhefti 2020-03-03 09:36:43 +01:00
parent a37ab31ff1
commit e7af727854
7 changed files with 441 additions and 439 deletions

View file

@ -1,41 +1,41 @@
/*
* 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.gui;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;
import ch.ethz.seb.sebserver.SEBServerInit;
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
@Component
@GuiProfile
public class GuiInit implements ApplicationListener<ApplicationReadyEvent> {
private final SEBServerInit sebServerInit;
protected GuiInit(final SEBServerInit sebServerInit) {
this.sebServerInit = sebServerInit;
}
@Override
public void onApplicationEvent(final ApplicationReadyEvent event) {
this.sebServerInit.init();
SEBServerInit.INIT_LOGGER.info("---->");
SEBServerInit.INIT_LOGGER.info("----> **** GUI Service starting up... ****");
SEBServerInit.INIT_LOGGER.info("---->");
SEBServerInit.INIT_LOGGER.info("----> GUI Service sucessfully successfully started up!");
SEBServerInit.INIT_LOGGER.info("---->");
}
}
/*
* 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.gui;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;
import ch.ethz.seb.sebserver.SEBServerInit;
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
@Component
@GuiProfile
public class GuiInit implements ApplicationListener<ApplicationReadyEvent> {
private final SEBServerInit sebServerInit;
protected GuiInit(final SEBServerInit sebServerInit) {
this.sebServerInit = sebServerInit;
}
@Override
public void onApplicationEvent(final ApplicationReadyEvent event) {
this.sebServerInit.init();
SEBServerInit.INIT_LOGGER.info("---->");
SEBServerInit.INIT_LOGGER.info("----> **** GUI Service starting up... ****");
SEBServerInit.INIT_LOGGER.info("---->");
SEBServerInit.INIT_LOGGER.info("----> GUI Service successfully successfully started up!");
SEBServerInit.INIT_LOGGER.info("---->");
}
}

View file

@ -73,12 +73,12 @@ public final class InstitutionalAuthenticationEntryPoint implements Authenticati
this.webserviceURIService = webserviceURIService;
this.clientHttpRequestFactoryService = clientHttpRequestFactoryService;
String _defaultLogo = null;
String _defaultLogo;
if (!Constants.NO_NAME.equals(defaultLogoFileName)) {
try {
final String extension = ImageUploadSelection.SUPPORTED_IMAGE_FILES.stream()
.filter(ext -> defaultLogoFileName.endsWith(ext))
.filter(defaultLogoFileName::endsWith)
.findFirst()
.orElse(null);
@ -141,7 +141,7 @@ public final class InstitutionalAuthenticationEntryPoint implements Authenticati
: null);
if (log.isDebugEnabled()) {
log.debug("Known and active gui entrypoint requested:", institutions);
log.debug("Known and active gui entrypoint requested: {}", institutions);
}
final String logoImageBase64 = requestLogoImage(institutionalEndpoint);
@ -184,9 +184,7 @@ public final class InstitutionalAuthenticationEntryPoint implements Authenticati
}
try {
return requestURI.substring(
requestURI.lastIndexOf(Constants.SLASH) + 1,
requestURI.length());
return requestURI.substring(requestURI.lastIndexOf(Constants.SLASH) + 1);
} catch (final Exception e) {
log.error("Failed to extract institutional URL suffix: {}", e.getMessage());
return null;
@ -231,12 +229,12 @@ public final class InstitutionalAuthenticationEntryPoint implements Authenticati
if (exchange.getStatusCodeValue() == HttpStatus.OK.value()) {
return exchange.getBody();
} else {
log.warn("Failed to verify insitution from requested entrypoint url: {}, response: {}",
log.warn("Failed to verify institution from requested entrypoint url: {}, response: {}",
institutionalEndpoint,
exchange);
}
} catch (final Exception e) {
log.warn("Failed to verify insitution from requested entrypoint url: {}",
log.warn("Failed to verify institution from requested entrypoint url: {}",
institutionalEndpoint,
e);
}
@ -245,7 +243,7 @@ public final class InstitutionalAuthenticationEntryPoint implements Authenticati
}
/** TODO this seems not to work as expected. Different Theme is only possible in RAP on different
* entry-points and since entry-points are statically defined within the RAPConficuration
* entry-points and since entry-points are statically defined within the RAPConfiguration
* there is no possibility to apply them dynamically within an institution so far.
*
* @param institutionalEndpoint

View file

@ -1,164 +1,164 @@
/*
* Copyright (c) 2018 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.gui;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpSession;
import org.eclipse.rap.rwt.RWT;
import org.eclipse.rap.rwt.application.AbstractEntryPoint;
import org.eclipse.rap.rwt.application.Application;
import org.eclipse.rap.rwt.application.ApplicationConfiguration;
import org.eclipse.rap.rwt.application.EntryPoint;
import org.eclipse.rap.rwt.application.EntryPointFactory;
import org.eclipse.rap.rwt.client.WebClient;
import org.eclipse.rap.rwt.internal.theme.ThemeUtil;
import org.eclipse.rap.rwt.service.ServiceManager;
import org.eclipse.swt.widgets.Composite;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
import ch.ethz.seb.sebserver.gui.service.remote.download.DownloadService;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.AuthorizationContextHolder;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.SEBServerAuthorizationContext;
public class RAPConfiguration implements ApplicationConfiguration {
private static final String DEFAULT_THEME_NAME = "sebserver";
private static final Logger log = LoggerFactory.getLogger(RAPConfiguration.class);
@Override
public void configure(final Application application) {
try {
// TODO get file path from properties
//application.addStyleSheet(RWT.DEFAULT_THEME_ID, "static/css/sebserver.css");
application.addStyleSheet(DEFAULT_THEME_NAME, "resource/theme/default.css");
application.addStyleSheet(DEFAULT_THEME_NAME, "static/css/sebserver.css");
application.addStyleSheet("sms", "resource/theme/default.css");
application.addStyleSheet("sms", "static/css/sms.css");
final Map<String, String> properties = new HashMap<>();
properties.put(WebClient.PAGE_TITLE, "SEB Server");
properties.put(WebClient.BODY_HTML, "<big>Loading Application<big>");
properties.put(WebClient.THEME_ID, DEFAULT_THEME_NAME);
// properties.put(WebClient.FAVICON, "icons/favicon.png");
application.addEntryPoint("/gui", new RAPSpringEntryPointFactory(), properties);
} catch (final RuntimeException re) {
throw re;
} catch (final Exception e) {
log.error("Error during CSS parsing. Please check the custom CSS files for errors.", e);
}
}
public static interface EntryPointService {
void loadLoginPage(final Composite parent);
void loadMainPage(final Composite parent);
}
public static final class RAPSpringEntryPointFactory implements EntryPointFactory {
private boolean initialized = false;
@Override
public EntryPoint create() {
return new AbstractEntryPoint() {
private static final long serialVersionUID = -1299125117752916270L;
@Override
protected void createContents(final Composite parent) {
final HttpSession httpSession = RWT
.getUISession(parent.getDisplay())
.getHttpSession();
log.debug("Create new GUI entrypoint. HttpSession: " + httpSession);
if (httpSession == null) {
log.error("HttpSession not available from RWT.getUISession().getHttpSession()");
throw new IllegalStateException(
"HttpSession not available from RWT.getUISession().getHttpSession()");
}
final Object themeId = httpSession.getAttribute("themeId");
if (themeId != null) {
ThemeUtil.setCurrentThemeId(RWT.getUISession(parent.getDisplay()), String.valueOf(themeId));
parent.redraw();
parent.layout(true);
parent.redraw();
}
final WebApplicationContext webApplicationContext = getWebApplicationContext(httpSession);
initSpringBasedRAPServices(webApplicationContext);
final EntryPointService entryPointService = webApplicationContext
.getBean(EntryPointService.class);
if (isAuthenticated(httpSession, webApplicationContext)) {
entryPointService.loadMainPage(parent);
} else {
entryPointService.loadLoginPage(parent);
}
}
};
}
private void initSpringBasedRAPServices(final WebApplicationContext webApplicationContext) {
if (!this.initialized) {
try {
final ServiceManager manager = RWT.getServiceManager();
final DownloadService downloadService = webApplicationContext.getBean(DownloadService.class);
manager.registerServiceHandler(DownloadService.DOWNLOAD_SERVICE_NAME, downloadService);
this.initialized = true;
} catch (final IllegalArgumentException iae) {
log.warn("Failed to register DownloadService on ServiceManager. Already registered: ", iae);
}
}
}
private boolean isAuthenticated(
final HttpSession httpSession,
final WebApplicationContext webApplicationContext) {
final AuthorizationContextHolder authorizationContextHolder = webApplicationContext
.getBean(AuthorizationContextHolder.class);
final SEBServerAuthorizationContext authorizationContext = authorizationContextHolder
.getAuthorizationContext(httpSession);
return authorizationContext.isValid() && authorizationContext.isLoggedIn();
}
private WebApplicationContext getWebApplicationContext(final HttpSession httpSession) {
try {
final ServletContext servletContext = httpSession.getServletContext();
log.debug("Initialize Spring-Context on Servlet-Context: " + servletContext);
return WebApplicationContextUtils
.getRequiredWebApplicationContext(servletContext);
} catch (final RuntimeException e) {
log.error("Failed to initialize Spring-Context on HttpSession: " + httpSession);
throw e;
} catch (final Exception e) {
log.error("Failed to initialize Spring-Context on HttpSession: " + httpSession);
throw new RuntimeException("Failed to initialize Spring-Context on HttpSession: " + httpSession);
}
}
};
}
/*
* Copyright (c) 2018 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.gui;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpSession;
import org.eclipse.rap.rwt.RWT;
import org.eclipse.rap.rwt.application.AbstractEntryPoint;
import org.eclipse.rap.rwt.application.Application;
import org.eclipse.rap.rwt.application.ApplicationConfiguration;
import org.eclipse.rap.rwt.application.EntryPoint;
import org.eclipse.rap.rwt.application.EntryPointFactory;
import org.eclipse.rap.rwt.client.WebClient;
import org.eclipse.rap.rwt.internal.theme.ThemeUtil;
import org.eclipse.rap.rwt.service.ServiceManager;
import org.eclipse.swt.widgets.Composite;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
import ch.ethz.seb.sebserver.gui.service.remote.download.DownloadService;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.AuthorizationContextHolder;
import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.SEBServerAuthorizationContext;
public class RAPConfiguration implements ApplicationConfiguration {
private static final String DEFAULT_THEME_NAME = "sebserver";
private static final Logger log = LoggerFactory.getLogger(RAPConfiguration.class);
@Override
public void configure(final Application application) {
try {
// TODO get file path from properties
//application.addStyleSheet(RWT.DEFAULT_THEME_ID, "static/css/sebserver.css");
application.addStyleSheet(DEFAULT_THEME_NAME, "resource/theme/default.css");
application.addStyleSheet(DEFAULT_THEME_NAME, "static/css/sebserver.css");
application.addStyleSheet("sms", "resource/theme/default.css");
application.addStyleSheet("sms", "static/css/sms.css");
final Map<String, String> properties = new HashMap<>();
properties.put(WebClient.PAGE_TITLE, "SEB Server");
properties.put(WebClient.BODY_HTML, "<big>Loading Application<big>");
properties.put(WebClient.THEME_ID, DEFAULT_THEME_NAME);
// properties.put(WebClient.FAVICON, "icons/favicon.png");
application.addEntryPoint("/gui", new RAPSpringEntryPointFactory(), properties);
} catch (final RuntimeException re) {
throw re;
} catch (final Exception e) {
log.error("Error during CSS parsing. Please check the custom CSS files for errors.", e);
}
}
public interface EntryPointService {
void loadLoginPage(final Composite parent);
void loadMainPage(final Composite parent);
}
public static final class RAPSpringEntryPointFactory implements EntryPointFactory {
private boolean initialized = false;
@Override
public EntryPoint create() {
return new AbstractEntryPoint() {
private static final long serialVersionUID = -1299125117752916270L;
@Override
protected void createContents(final Composite parent) {
final HttpSession httpSession = RWT
.getUISession(parent.getDisplay())
.getHttpSession();
log.debug("Create new GUI entrypoint. HttpSession: " + httpSession);
if (httpSession == null) {
log.error("HttpSession not available from RWT.getUISession().getHttpSession()");
throw new IllegalStateException(
"HttpSession not available from RWT.getUISession().getHttpSession()");
}
final Object themeId = httpSession.getAttribute("themeId");
if (themeId != null) {
ThemeUtil.setCurrentThemeId(RWT.getUISession(parent.getDisplay()), String.valueOf(themeId));
parent.redraw();
parent.layout(true);
parent.redraw();
}
final WebApplicationContext webApplicationContext = getWebApplicationContext(httpSession);
initSpringBasedRAPServices(webApplicationContext);
final EntryPointService entryPointService = webApplicationContext
.getBean(EntryPointService.class);
if (isAuthenticated(httpSession, webApplicationContext)) {
entryPointService.loadMainPage(parent);
} else {
entryPointService.loadLoginPage(parent);
}
}
};
}
private void initSpringBasedRAPServices(final WebApplicationContext webApplicationContext) {
if (!this.initialized) {
try {
final ServiceManager manager = RWT.getServiceManager();
final DownloadService downloadService = webApplicationContext.getBean(DownloadService.class);
manager.registerServiceHandler(DownloadService.DOWNLOAD_SERVICE_NAME, downloadService);
this.initialized = true;
} catch (final IllegalArgumentException iae) {
log.warn("Failed to register DownloadService on ServiceManager. Already registered: ", iae);
}
}
}
private boolean isAuthenticated(
final HttpSession httpSession,
final WebApplicationContext webApplicationContext) {
final AuthorizationContextHolder authorizationContextHolder = webApplicationContext
.getBean(AuthorizationContextHolder.class);
final SEBServerAuthorizationContext authorizationContext = authorizationContextHolder
.getAuthorizationContext(httpSession);
return authorizationContext.isValid() && authorizationContext.isLoggedIn();
}
private WebApplicationContext getWebApplicationContext(final HttpSession httpSession) {
try {
final ServletContext servletContext = httpSession.getServletContext();
log.debug("Initialize Spring-Context on Servlet-Context: " + servletContext);
return WebApplicationContextUtils
.getRequiredWebApplicationContext(servletContext);
} catch (final RuntimeException e) {
log.error("Failed to initialize Spring-Context on HttpSession: " + httpSession);
throw e;
} catch (final Exception e) {
log.error("Failed to initialize Spring-Context on HttpSession: " + httpSession);
throw new RuntimeException("Failed to initialize Spring-Context on HttpSession: " + httpSession);
}
}
}
}

View file

@ -1,83 +1,81 @@
/*
* Copyright (c) 2018 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.gui;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextListener;
import javax.servlet.ServletException;
import org.eclipse.rap.rwt.engine.RWTServlet;
import org.eclipse.rap.rwt.engine.RWTServletContextListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.servlet.ServletContextInitializer;
import org.springframework.boot.web.servlet.ServletListenerRegistrationBean;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ReloadableResourceBundleMessageSource;
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
@Configuration
@GuiProfile
public class RAPSpringConfig {
private static final Logger log = LoggerFactory.getLogger(RAPSpringConfig.class);
@Value("${sebserver.gui.entrypoint}")
private String entrypoint;
@Value("${sebserver.gui.external.messages:messages}")
private String externalMessagesPath;
@Bean
public ServletContextInitializer initializer() {
return new RAPServletContextInitializer();
}
@Bean
public ServletListenerRegistrationBean<ServletContextListener> listenerRegistrationBean() {
final ServletListenerRegistrationBean<ServletContextListener> bean =
new ServletListenerRegistrationBean<>();
bean.setListener(new RWTServletContextListener());
return bean;
}
@Bean
public ServletRegistrationBean<RWTServlet> servletRegistrationBean() {
return new ServletRegistrationBean<>(new RWTServlet(), this.entrypoint + "/*");
}
@Bean
public MessageSource messageSource() {
final ReloadableResourceBundleMessageSource reloadableResourceBundleMessageSource =
new ReloadableResourceBundleMessageSource();
log.info(" +++ Register external messages resources from: {}", this.externalMessagesPath);
reloadableResourceBundleMessageSource.setBasenames(
this.externalMessagesPath,
"classpath:messages");
return reloadableResourceBundleMessageSource;
}
private static class RAPServletContextInitializer implements ServletContextInitializer {
@Override
public void onStartup(final ServletContext servletContext) throws ServletException {
servletContext.setInitParameter(
"org.eclipse.rap.applicationConfiguration",
RAPConfiguration.class.getName());
}
}
}
/*
* Copyright (c) 2018 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.gui;
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
import org.eclipse.rap.rwt.engine.RWTServlet;
import org.eclipse.rap.rwt.engine.RWTServletContextListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.servlet.ServletContextInitializer;
import org.springframework.boot.web.servlet.ServletListenerRegistrationBean;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ReloadableResourceBundleMessageSource;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextListener;
@Configuration
@GuiProfile
public class RAPSpringConfig {
private static final Logger log = LoggerFactory.getLogger(RAPSpringConfig.class);
@Value("${sebserver.gui.entrypoint}")
private String entrypoint;
@Value("${sebserver.gui.external.messages:messages}")
private String externalMessagesPath;
@Bean
public ServletContextInitializer initializer() {
return new RAPServletContextInitializer();
}
@Bean
public ServletListenerRegistrationBean<ServletContextListener> listenerRegistrationBean() {
final ServletListenerRegistrationBean<ServletContextListener> bean =
new ServletListenerRegistrationBean<>();
bean.setListener(new RWTServletContextListener());
return bean;
}
@Bean
public ServletRegistrationBean<RWTServlet> servletRegistrationBean() {
return new ServletRegistrationBean<>(new RWTServlet(), this.entrypoint + "/*");
}
@Bean
public MessageSource messageSource() {
final ReloadableResourceBundleMessageSource reloadableResourceBundleMessageSource =
new ReloadableResourceBundleMessageSource();
log.info(" +++ Register external messages resources from: {}", this.externalMessagesPath);
reloadableResourceBundleMessageSource.setBasenames(
this.externalMessagesPath,
"classpath:messages");
return reloadableResourceBundleMessageSource;
}
private static class RAPServletContextInitializer implements ServletContextInitializer {
@Override
public void onStartup(final ServletContext servletContext) {
servletContext.setInitParameter(
"org.eclipse.rap.applicationConfiguration",
RAPConfiguration.class.getName());
}
}
}

View file

@ -123,7 +123,7 @@ public class WidgetFactory {
private ImageData image = null;
private ImageData greyedImage = null;
private ImageIcon(final String fileName) {
ImageIcon(final String fileName) {
this.fileName = fileName;
}
@ -199,7 +199,7 @@ public class WidgetFactory {
public final String key;
private CustomVariant(final String key) {
CustomVariant(final String key) {
this.key = key;
}
}
@ -268,7 +268,7 @@ public class WidgetFactory {
* @param parent The parent Composite
* @return the scrolled Composite to add the form content */
public Composite createPopupScrollComposite(final Composite parent) {
final Composite grid = PageService.createManagedVScrolledComposite(
return PageService.createManagedVScrolledComposite(
parent,
scrolledComposite -> {
final Composite g = new Composite(scrolledComposite, SWT.NONE);
@ -277,7 +277,6 @@ public class WidgetFactory {
return g;
},
false);
return grid;
}
public Composite createWarningPanel(final Composite parent) {
@ -733,7 +732,7 @@ public class WidgetFactory {
new FileUploadSelection(parent, this.i18nSupport, readonly);
if (supportedFiles != null) {
supportedFiles.forEach(ext -> fileUploadSelection.withSupportFor(ext));
supportedFiles.forEach(fileUploadSelection::withSupportFor);
}
return fileUploadSelection;
}

View file

@ -23,6 +23,7 @@ import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetup;
import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetupTestResult;
import ch.ethz.seb.sebserver.gbl.util.Result;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.FilterMap;
import org.joda.time.DateTimeZone;
/** Defines the LMS API access service interface with all functionality needed to access
* a LMS API within a given LmsSetup configuration.
@ -101,12 +102,12 @@ public interface LmsAPIService {
static Predicate<QuizData> quizFilterPredicate(final FilterMap filterMap) {
final String name = filterMap.getQuizName();
final DateTime from = filterMap.getQuizFromTime();
//final DateTime now = DateTime.now(DateTimeZone.UTC);
return q -> {
final boolean nameFilter = StringUtils.isBlank(name) || (q.name != null && q.name.contains(name));
final boolean startTimeFilter =
(from == null) || (q.startTime != null && (q.startTime.isEqual(from) || q.startTime.isAfter(from)));
return nameFilter && startTimeFilter /* && endTimeFilter */;
final boolean currentlyRunning = DateTime.now(DateTimeZone.UTC).isBefore(q.endTime);
return nameFilter && (startTimeFilter || currentlyRunning) ;
};
}

View file

@ -1,135 +1,141 @@
/*
* 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 java.util.Collection;
import org.mybatis.dynamic.sql.SqlTable;
import org.springframework.http.MediaType;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import ch.ethz.seb.sebserver.gbl.api.API;
import ch.ethz.seb.sebserver.gbl.api.API.BulkActionType;
import ch.ethz.seb.sebserver.gbl.api.EntityType;
import ch.ethz.seb.sebserver.gbl.api.authorization.PrivilegeType;
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
import ch.ethz.seb.sebserver.gbl.model.GrantEntity;
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.ExtendedClientEvent;
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.ClientEventRecordDynamicSqlSupport;
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.PermissionDeniedException;
import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.UserService;
import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.impl.SEBServerUser;
import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.BulkActionService;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ClientEventDAO;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ExamDAO;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.FilterMap;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.UserActivityLogDAO;
import ch.ethz.seb.sebserver.webservice.servicelayer.validation.BeanValidationService;
@WebServiceProfile
@RestController
@RequestMapping("${sebserver.webservice.api.admin.endpoint}" + API.SEB_CLIENT_EVENT_ENDPOINT)
public class ClientEventController extends ReadonlyEntityController<ClientEvent, ClientEvent> {
private final ExamDAO examDAO;
private final ClientEventDAO clientEventDAO;
protected ClientEventController(
final AuthorizationService authorization,
final BulkActionService bulkActionService,
final ClientEventDAO entityDAO,
final UserActivityLogDAO userActivityLogDAO,
final PaginationService paginationService,
final BeanValidationService beanValidationService,
final ExamDAO examDAO) {
super(authorization,
bulkActionService,
entityDAO,
userActivityLogDAO,
paginationService,
beanValidationService);
this.examDAO = examDAO;
this.clientEventDAO = entityDAO;
}
@RequestMapping(
path = API.SEB_CLIENT_EVENT_SEARCH_PATH_SEGMENT,
method = RequestMethod.GET,
consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE,
produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
public Page<ExtendedClientEvent> getExtendedPage(
@RequestParam(
name = API.PARAM_INSTITUTION_ID,
required = true,
defaultValue = UserService.USERS_INSTITUTION_AS_DEFAULT) final Long institutionId,
@RequestParam(name = Page.ATTR_PAGE_NUMBER, required = false) final Integer pageNumber,
@RequestParam(name = Page.ATTR_PAGE_SIZE, required = false) final Integer pageSize,
@RequestParam(name = Page.ATTR_SORT, required = false) final String sort,
@RequestParam final MultiValueMap<String, String> allRequestParams) {
// 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);
// if current user has no read access for specified entity type within other institution
// then the current users institutionId is put as a SQL filter criteria attribute to extends query performance
if (!this.authorization.hasGrant(PrivilegeType.READ, getGrantEntityType())) {
filterMap.putIfAbsent(API.PARAM_INSTITUTION_ID, String.valueOf(institutionId));
}
return this.paginationService.getPage(
pageNumber,
pageSize,
sort,
getSQLTableOfEntity().name(),
() -> this.clientEventDAO.allMatchingExtended(filterMap, this::hasReadAccess))
.getOrThrow();
}
@Override
public Collection<EntityKey> getDependencies(final String modelId, final BulkActionType bulkActionType) {
throw new UnsupportedOperationException();
}
@Override
protected SqlTable getSQLTableOfEntity() {
return ClientEventRecordDynamicSqlSupport.clientEventRecord;
}
@Override
protected GrantEntity toGrantEntity(final ClientEvent entity) {
return this.examDAO
.byClientConnection(entity.connectionId)
.getOrThrow();
}
@Override
protected void checkReadPrivilege(final Long institutionId) {
final SEBServerUser currentUser = this.authorization.getUserService().getCurrentUser();
if (currentUser.institutionId().longValue() != institutionId.longValue()) {
throw new PermissionDeniedException(
EntityType.CLIENT_EVENT,
PrivilegeType.READ,
currentUser.getUserInfo());
}
}
}
/*
* 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 java.util.Collection;
import org.mybatis.dynamic.sql.SqlTable;
import org.springframework.http.MediaType;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import ch.ethz.seb.sebserver.gbl.api.API;
import ch.ethz.seb.sebserver.gbl.api.API.BulkActionType;
import ch.ethz.seb.sebserver.gbl.api.EntityType;
import ch.ethz.seb.sebserver.gbl.api.authorization.PrivilegeType;
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
import ch.ethz.seb.sebserver.gbl.model.GrantEntity;
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.ExtendedClientEvent;
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.ClientEventRecordDynamicSqlSupport;
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.PermissionDeniedException;
import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.UserService;
import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.impl.SEBServerUser;
import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.BulkActionService;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ClientEventDAO;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ExamDAO;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.FilterMap;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.UserActivityLogDAO;
import ch.ethz.seb.sebserver.webservice.servicelayer.validation.BeanValidationService;
@WebServiceProfile
@RestController
@RequestMapping("${sebserver.webservice.api.admin.endpoint}" + API.SEB_CLIENT_EVENT_ENDPOINT)
public class ClientEventController extends ReadonlyEntityController<ClientEvent, ClientEvent> {
private final ExamDAO examDAO;
private final ClientEventDAO clientEventDAO;
protected ClientEventController(
final AuthorizationService authorization,
final BulkActionService bulkActionService,
final ClientEventDAO entityDAO,
final UserActivityLogDAO userActivityLogDAO,
final PaginationService paginationService,
final BeanValidationService beanValidationService,
final ExamDAO examDAO) {
super(authorization,
bulkActionService,
entityDAO,
userActivityLogDAO,
paginationService,
beanValidationService);
this.examDAO = examDAO;
this.clientEventDAO = entityDAO;
}
@RequestMapping(
path = API.SEB_CLIENT_EVENT_SEARCH_PATH_SEGMENT,
method = RequestMethod.GET,
consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE,
produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
public Page<ExtendedClientEvent> getExtendedPage(
@RequestParam(
name = API.PARAM_INSTITUTION_ID,
required = true,
defaultValue = UserService.USERS_INSTITUTION_AS_DEFAULT) final Long institutionId,
@RequestParam(name = Page.ATTR_PAGE_NUMBER, required = false) final Integer pageNumber,
@RequestParam(name = Page.ATTR_PAGE_SIZE, required = false) final Integer pageSize,
@RequestParam(name = Page.ATTR_SORT, required = false) final String sort,
@RequestParam final MultiValueMap<String, String> allRequestParams) {
// 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);
// if current user has no read access for specified entity type within other institution
// then the current users institutionId is put as a SQL filter criteria attribute to extends query performance
if (!this.authorization.hasGrant(PrivilegeType.READ, getGrantEntityType())) {
filterMap.putIfAbsent(API.PARAM_INSTITUTION_ID, String.valueOf(institutionId));
}
try {
return this.paginationService.getPage(
pageNumber,
pageSize,
sort,
getSQLTableOfEntity().name(),
() -> this.clientEventDAO.allMatchingExtended(filterMap, this::hasReadAccess))
.getOrThrow();
} catch (Exception e) {
e.printStackTrace();
throw e;
}
}
@Override
public Collection<EntityKey> getDependencies(final String modelId, final BulkActionType bulkActionType) {
throw new UnsupportedOperationException();
}
@Override
protected SqlTable getSQLTableOfEntity() {
return ClientEventRecordDynamicSqlSupport.clientEventRecord;
}
@Override
protected GrantEntity toGrantEntity(final ClientEvent entity) {
return this.examDAO
.byClientConnection(entity.connectionId)
.get();
}
@Override
protected void checkReadPrivilege(final Long institutionId) {
final SEBServerUser currentUser = this.authorization.getUserService().getCurrentUser();
if (currentUser.institutionId().longValue() != institutionId.longValue()) {
throw new PermissionDeniedException(
EntityType.CLIENT_EVENT,
PrivilegeType.READ,
currentUser.getUserInfo());
}
}
}