fixed privilege check on SEB Client Events list and update quiz filter
This commit is contained in:
parent
a37ab31ff1
commit
e7af727854
7 changed files with 441 additions and 439 deletions
|
@ -1,41 +1,41 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2019 ETH Zürich, Educational Development and Technology (LET)
|
* Copyright (c) 2019 ETH Zürich, Educational Development and Technology (LET)
|
||||||
*
|
*
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
* 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
|
* 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/.
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package ch.ethz.seb.sebserver.gui;
|
package ch.ethz.seb.sebserver.gui;
|
||||||
|
|
||||||
import org.springframework.boot.context.event.ApplicationReadyEvent;
|
import org.springframework.boot.context.event.ApplicationReadyEvent;
|
||||||
import org.springframework.context.ApplicationListener;
|
import org.springframework.context.ApplicationListener;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import ch.ethz.seb.sebserver.SEBServerInit;
|
import ch.ethz.seb.sebserver.SEBServerInit;
|
||||||
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
|
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
@GuiProfile
|
@GuiProfile
|
||||||
public class GuiInit implements ApplicationListener<ApplicationReadyEvent> {
|
public class GuiInit implements ApplicationListener<ApplicationReadyEvent> {
|
||||||
|
|
||||||
private final SEBServerInit sebServerInit;
|
private final SEBServerInit sebServerInit;
|
||||||
|
|
||||||
protected GuiInit(final SEBServerInit sebServerInit) {
|
protected GuiInit(final SEBServerInit sebServerInit) {
|
||||||
this.sebServerInit = sebServerInit;
|
this.sebServerInit = sebServerInit;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onApplicationEvent(final ApplicationReadyEvent event) {
|
public void onApplicationEvent(final ApplicationReadyEvent event) {
|
||||||
|
|
||||||
this.sebServerInit.init();
|
this.sebServerInit.init();
|
||||||
|
|
||||||
SEBServerInit.INIT_LOGGER.info("---->");
|
SEBServerInit.INIT_LOGGER.info("---->");
|
||||||
SEBServerInit.INIT_LOGGER.info("----> **** GUI Service starting up... ****");
|
SEBServerInit.INIT_LOGGER.info("----> **** GUI Service starting up... ****");
|
||||||
|
|
||||||
SEBServerInit.INIT_LOGGER.info("---->");
|
SEBServerInit.INIT_LOGGER.info("---->");
|
||||||
SEBServerInit.INIT_LOGGER.info("----> GUI Service sucessfully successfully started up!");
|
SEBServerInit.INIT_LOGGER.info("----> GUI Service successfully successfully started up!");
|
||||||
SEBServerInit.INIT_LOGGER.info("---->");
|
SEBServerInit.INIT_LOGGER.info("---->");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,12 +73,12 @@ public final class InstitutionalAuthenticationEntryPoint implements Authenticati
|
||||||
this.webserviceURIService = webserviceURIService;
|
this.webserviceURIService = webserviceURIService;
|
||||||
this.clientHttpRequestFactoryService = clientHttpRequestFactoryService;
|
this.clientHttpRequestFactoryService = clientHttpRequestFactoryService;
|
||||||
|
|
||||||
String _defaultLogo = null;
|
String _defaultLogo;
|
||||||
if (!Constants.NO_NAME.equals(defaultLogoFileName)) {
|
if (!Constants.NO_NAME.equals(defaultLogoFileName)) {
|
||||||
try {
|
try {
|
||||||
|
|
||||||
final String extension = ImageUploadSelection.SUPPORTED_IMAGE_FILES.stream()
|
final String extension = ImageUploadSelection.SUPPORTED_IMAGE_FILES.stream()
|
||||||
.filter(ext -> defaultLogoFileName.endsWith(ext))
|
.filter(defaultLogoFileName::endsWith)
|
||||||
.findFirst()
|
.findFirst()
|
||||||
.orElse(null);
|
.orElse(null);
|
||||||
|
|
||||||
|
@ -141,7 +141,7 @@ public final class InstitutionalAuthenticationEntryPoint implements Authenticati
|
||||||
: null);
|
: null);
|
||||||
|
|
||||||
if (log.isDebugEnabled()) {
|
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);
|
final String logoImageBase64 = requestLogoImage(institutionalEndpoint);
|
||||||
|
@ -184,9 +184,7 @@ public final class InstitutionalAuthenticationEntryPoint implements Authenticati
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return requestURI.substring(
|
return requestURI.substring(requestURI.lastIndexOf(Constants.SLASH) + 1);
|
||||||
requestURI.lastIndexOf(Constants.SLASH) + 1,
|
|
||||||
requestURI.length());
|
|
||||||
} catch (final Exception e) {
|
} catch (final Exception e) {
|
||||||
log.error("Failed to extract institutional URL suffix: {}", e.getMessage());
|
log.error("Failed to extract institutional URL suffix: {}", e.getMessage());
|
||||||
return null;
|
return null;
|
||||||
|
@ -231,12 +229,12 @@ public final class InstitutionalAuthenticationEntryPoint implements Authenticati
|
||||||
if (exchange.getStatusCodeValue() == HttpStatus.OK.value()) {
|
if (exchange.getStatusCodeValue() == HttpStatus.OK.value()) {
|
||||||
return exchange.getBody();
|
return exchange.getBody();
|
||||||
} else {
|
} else {
|
||||||
log.warn("Failed to verify insitution from requested entrypoint url: {}, response: {}",
|
log.warn("Failed to verify institution from requested entrypoint url: {}, response: {}",
|
||||||
institutionalEndpoint,
|
institutionalEndpoint,
|
||||||
exchange);
|
exchange);
|
||||||
}
|
}
|
||||||
} catch (final Exception e) {
|
} 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,
|
institutionalEndpoint,
|
||||||
e);
|
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
|
/** 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.
|
* there is no possibility to apply them dynamically within an institution so far.
|
||||||
*
|
*
|
||||||
* @param institutionalEndpoint
|
* @param institutionalEndpoint
|
||||||
|
|
|
@ -1,164 +1,164 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2018 ETH Zürich, Educational Development and Technology (LET)
|
* Copyright (c) 2018 ETH Zürich, Educational Development and Technology (LET)
|
||||||
*
|
*
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
* 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
|
* 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/.
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package ch.ethz.seb.sebserver.gui;
|
package ch.ethz.seb.sebserver.gui;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import javax.servlet.ServletContext;
|
import javax.servlet.ServletContext;
|
||||||
import javax.servlet.http.HttpSession;
|
import javax.servlet.http.HttpSession;
|
||||||
|
|
||||||
import org.eclipse.rap.rwt.RWT;
|
import org.eclipse.rap.rwt.RWT;
|
||||||
import org.eclipse.rap.rwt.application.AbstractEntryPoint;
|
import org.eclipse.rap.rwt.application.AbstractEntryPoint;
|
||||||
import org.eclipse.rap.rwt.application.Application;
|
import org.eclipse.rap.rwt.application.Application;
|
||||||
import org.eclipse.rap.rwt.application.ApplicationConfiguration;
|
import org.eclipse.rap.rwt.application.ApplicationConfiguration;
|
||||||
import org.eclipse.rap.rwt.application.EntryPoint;
|
import org.eclipse.rap.rwt.application.EntryPoint;
|
||||||
import org.eclipse.rap.rwt.application.EntryPointFactory;
|
import org.eclipse.rap.rwt.application.EntryPointFactory;
|
||||||
import org.eclipse.rap.rwt.client.WebClient;
|
import org.eclipse.rap.rwt.client.WebClient;
|
||||||
import org.eclipse.rap.rwt.internal.theme.ThemeUtil;
|
import org.eclipse.rap.rwt.internal.theme.ThemeUtil;
|
||||||
import org.eclipse.rap.rwt.service.ServiceManager;
|
import org.eclipse.rap.rwt.service.ServiceManager;
|
||||||
import org.eclipse.swt.widgets.Composite;
|
import org.eclipse.swt.widgets.Composite;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.web.context.WebApplicationContext;
|
import org.springframework.web.context.WebApplicationContext;
|
||||||
import org.springframework.web.context.support.WebApplicationContextUtils;
|
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.download.DownloadService;
|
||||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.AuthorizationContextHolder;
|
import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.AuthorizationContextHolder;
|
||||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.SEBServerAuthorizationContext;
|
import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.SEBServerAuthorizationContext;
|
||||||
|
|
||||||
public class RAPConfiguration implements ApplicationConfiguration {
|
public class RAPConfiguration implements ApplicationConfiguration {
|
||||||
|
|
||||||
private static final String DEFAULT_THEME_NAME = "sebserver";
|
private static final String DEFAULT_THEME_NAME = "sebserver";
|
||||||
private static final Logger log = LoggerFactory.getLogger(RAPConfiguration.class);
|
private static final Logger log = LoggerFactory.getLogger(RAPConfiguration.class);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void configure(final Application application) {
|
public void configure(final Application application) {
|
||||||
try {
|
try {
|
||||||
|
|
||||||
// TODO get file path from properties
|
// TODO get file path from properties
|
||||||
//application.addStyleSheet(RWT.DEFAULT_THEME_ID, "static/css/sebserver.css");
|
//application.addStyleSheet(RWT.DEFAULT_THEME_ID, "static/css/sebserver.css");
|
||||||
application.addStyleSheet(DEFAULT_THEME_NAME, "resource/theme/default.css");
|
application.addStyleSheet(DEFAULT_THEME_NAME, "resource/theme/default.css");
|
||||||
application.addStyleSheet(DEFAULT_THEME_NAME, "static/css/sebserver.css");
|
application.addStyleSheet(DEFAULT_THEME_NAME, "static/css/sebserver.css");
|
||||||
application.addStyleSheet("sms", "resource/theme/default.css");
|
application.addStyleSheet("sms", "resource/theme/default.css");
|
||||||
application.addStyleSheet("sms", "static/css/sms.css");
|
application.addStyleSheet("sms", "static/css/sms.css");
|
||||||
|
|
||||||
final Map<String, String> properties = new HashMap<>();
|
final Map<String, String> properties = new HashMap<>();
|
||||||
properties.put(WebClient.PAGE_TITLE, "SEB Server");
|
properties.put(WebClient.PAGE_TITLE, "SEB Server");
|
||||||
properties.put(WebClient.BODY_HTML, "<big>Loading Application<big>");
|
properties.put(WebClient.BODY_HTML, "<big>Loading Application<big>");
|
||||||
properties.put(WebClient.THEME_ID, DEFAULT_THEME_NAME);
|
properties.put(WebClient.THEME_ID, DEFAULT_THEME_NAME);
|
||||||
// properties.put(WebClient.FAVICON, "icons/favicon.png");
|
// properties.put(WebClient.FAVICON, "icons/favicon.png");
|
||||||
application.addEntryPoint("/gui", new RAPSpringEntryPointFactory(), properties);
|
application.addEntryPoint("/gui", new RAPSpringEntryPointFactory(), properties);
|
||||||
|
|
||||||
} catch (final RuntimeException re) {
|
} catch (final RuntimeException re) {
|
||||||
throw re;
|
throw re;
|
||||||
} catch (final Exception e) {
|
} catch (final Exception e) {
|
||||||
log.error("Error during CSS parsing. Please check the custom CSS files for errors.", e);
|
log.error("Error during CSS parsing. Please check the custom CSS files for errors.", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static interface EntryPointService {
|
public interface EntryPointService {
|
||||||
|
|
||||||
void loadLoginPage(final Composite parent);
|
void loadLoginPage(final Composite parent);
|
||||||
|
|
||||||
void loadMainPage(final Composite parent);
|
void loadMainPage(final Composite parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final class RAPSpringEntryPointFactory implements EntryPointFactory {
|
public static final class RAPSpringEntryPointFactory implements EntryPointFactory {
|
||||||
|
|
||||||
private boolean initialized = false;
|
private boolean initialized = false;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public EntryPoint create() {
|
public EntryPoint create() {
|
||||||
|
|
||||||
return new AbstractEntryPoint() {
|
return new AbstractEntryPoint() {
|
||||||
|
|
||||||
private static final long serialVersionUID = -1299125117752916270L;
|
private static final long serialVersionUID = -1299125117752916270L;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void createContents(final Composite parent) {
|
protected void createContents(final Composite parent) {
|
||||||
final HttpSession httpSession = RWT
|
final HttpSession httpSession = RWT
|
||||||
.getUISession(parent.getDisplay())
|
.getUISession(parent.getDisplay())
|
||||||
.getHttpSession();
|
.getHttpSession();
|
||||||
|
|
||||||
log.debug("Create new GUI entrypoint. HttpSession: " + httpSession);
|
log.debug("Create new GUI entrypoint. HttpSession: " + httpSession);
|
||||||
if (httpSession == null) {
|
if (httpSession == null) {
|
||||||
log.error("HttpSession not available from RWT.getUISession().getHttpSession()");
|
log.error("HttpSession not available from RWT.getUISession().getHttpSession()");
|
||||||
throw new IllegalStateException(
|
throw new IllegalStateException(
|
||||||
"HttpSession not available from RWT.getUISession().getHttpSession()");
|
"HttpSession not available from RWT.getUISession().getHttpSession()");
|
||||||
}
|
}
|
||||||
|
|
||||||
final Object themeId = httpSession.getAttribute("themeId");
|
final Object themeId = httpSession.getAttribute("themeId");
|
||||||
if (themeId != null) {
|
if (themeId != null) {
|
||||||
ThemeUtil.setCurrentThemeId(RWT.getUISession(parent.getDisplay()), String.valueOf(themeId));
|
ThemeUtil.setCurrentThemeId(RWT.getUISession(parent.getDisplay()), String.valueOf(themeId));
|
||||||
parent.redraw();
|
parent.redraw();
|
||||||
parent.layout(true);
|
parent.layout(true);
|
||||||
parent.redraw();
|
parent.redraw();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
final WebApplicationContext webApplicationContext = getWebApplicationContext(httpSession);
|
final WebApplicationContext webApplicationContext = getWebApplicationContext(httpSession);
|
||||||
initSpringBasedRAPServices(webApplicationContext);
|
initSpringBasedRAPServices(webApplicationContext);
|
||||||
|
|
||||||
final EntryPointService entryPointService = webApplicationContext
|
final EntryPointService entryPointService = webApplicationContext
|
||||||
.getBean(EntryPointService.class);
|
.getBean(EntryPointService.class);
|
||||||
|
|
||||||
if (isAuthenticated(httpSession, webApplicationContext)) {
|
if (isAuthenticated(httpSession, webApplicationContext)) {
|
||||||
entryPointService.loadMainPage(parent);
|
entryPointService.loadMainPage(parent);
|
||||||
} else {
|
} else {
|
||||||
entryPointService.loadLoginPage(parent);
|
entryPointService.loadLoginPage(parent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initSpringBasedRAPServices(final WebApplicationContext webApplicationContext) {
|
private void initSpringBasedRAPServices(final WebApplicationContext webApplicationContext) {
|
||||||
if (!this.initialized) {
|
if (!this.initialized) {
|
||||||
try {
|
try {
|
||||||
final ServiceManager manager = RWT.getServiceManager();
|
final ServiceManager manager = RWT.getServiceManager();
|
||||||
final DownloadService downloadService = webApplicationContext.getBean(DownloadService.class);
|
final DownloadService downloadService = webApplicationContext.getBean(DownloadService.class);
|
||||||
manager.registerServiceHandler(DownloadService.DOWNLOAD_SERVICE_NAME, downloadService);
|
manager.registerServiceHandler(DownloadService.DOWNLOAD_SERVICE_NAME, downloadService);
|
||||||
this.initialized = true;
|
this.initialized = true;
|
||||||
} catch (final IllegalArgumentException iae) {
|
} catch (final IllegalArgumentException iae) {
|
||||||
log.warn("Failed to register DownloadService on ServiceManager. Already registered: ", iae);
|
log.warn("Failed to register DownloadService on ServiceManager. Already registered: ", iae);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isAuthenticated(
|
private boolean isAuthenticated(
|
||||||
final HttpSession httpSession,
|
final HttpSession httpSession,
|
||||||
final WebApplicationContext webApplicationContext) {
|
final WebApplicationContext webApplicationContext) {
|
||||||
|
|
||||||
final AuthorizationContextHolder authorizationContextHolder = webApplicationContext
|
final AuthorizationContextHolder authorizationContextHolder = webApplicationContext
|
||||||
.getBean(AuthorizationContextHolder.class);
|
.getBean(AuthorizationContextHolder.class);
|
||||||
final SEBServerAuthorizationContext authorizationContext = authorizationContextHolder
|
final SEBServerAuthorizationContext authorizationContext = authorizationContextHolder
|
||||||
.getAuthorizationContext(httpSession);
|
.getAuthorizationContext(httpSession);
|
||||||
return authorizationContext.isValid() && authorizationContext.isLoggedIn();
|
return authorizationContext.isValid() && authorizationContext.isLoggedIn();
|
||||||
}
|
}
|
||||||
|
|
||||||
private WebApplicationContext getWebApplicationContext(final HttpSession httpSession) {
|
private WebApplicationContext getWebApplicationContext(final HttpSession httpSession) {
|
||||||
try {
|
try {
|
||||||
final ServletContext servletContext = httpSession.getServletContext();
|
final ServletContext servletContext = httpSession.getServletContext();
|
||||||
|
|
||||||
log.debug("Initialize Spring-Context on Servlet-Context: " + servletContext);
|
log.debug("Initialize Spring-Context on Servlet-Context: " + servletContext);
|
||||||
|
|
||||||
return WebApplicationContextUtils
|
return WebApplicationContextUtils
|
||||||
.getRequiredWebApplicationContext(servletContext);
|
.getRequiredWebApplicationContext(servletContext);
|
||||||
|
|
||||||
} catch (final RuntimeException e) {
|
} catch (final RuntimeException e) {
|
||||||
log.error("Failed to initialize Spring-Context on HttpSession: " + httpSession);
|
log.error("Failed to initialize Spring-Context on HttpSession: " + httpSession);
|
||||||
throw e;
|
throw e;
|
||||||
} catch (final Exception e) {
|
} catch (final Exception e) {
|
||||||
log.error("Failed to initialize Spring-Context on HttpSession: " + httpSession);
|
log.error("Failed to initialize Spring-Context on HttpSession: " + httpSession);
|
||||||
throw new RuntimeException("Failed to initialize Spring-Context on HttpSession: " + httpSession);
|
throw new RuntimeException("Failed to initialize Spring-Context on HttpSession: " + httpSession);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,83 +1,81 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2018 ETH Zürich, Educational Development and Technology (LET)
|
* Copyright (c) 2018 ETH Zürich, Educational Development and Technology (LET)
|
||||||
*
|
*
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
* 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
|
* 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/.
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package ch.ethz.seb.sebserver.gui;
|
package ch.ethz.seb.sebserver.gui;
|
||||||
|
|
||||||
import javax.servlet.ServletContext;
|
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
|
||||||
import javax.servlet.ServletContextListener;
|
import org.eclipse.rap.rwt.engine.RWTServlet;
|
||||||
import javax.servlet.ServletException;
|
import org.eclipse.rap.rwt.engine.RWTServletContextListener;
|
||||||
|
import org.slf4j.Logger;
|
||||||
import org.eclipse.rap.rwt.engine.RWTServlet;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.eclipse.rap.rwt.engine.RWTServletContextListener;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.slf4j.Logger;
|
import org.springframework.boot.web.servlet.ServletContextInitializer;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.springframework.boot.web.servlet.ServletListenerRegistrationBean;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.boot.web.servlet.ServletRegistrationBean;
|
||||||
import org.springframework.boot.web.servlet.ServletContextInitializer;
|
import org.springframework.context.MessageSource;
|
||||||
import org.springframework.boot.web.servlet.ServletListenerRegistrationBean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.boot.web.servlet.ServletRegistrationBean;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.context.MessageSource;
|
import org.springframework.context.support.ReloadableResourceBundleMessageSource;
|
||||||
import org.springframework.context.annotation.Bean;
|
|
||||||
import org.springframework.context.annotation.Configuration;
|
import javax.servlet.ServletContext;
|
||||||
import org.springframework.context.support.ReloadableResourceBundleMessageSource;
|
import javax.servlet.ServletContextListener;
|
||||||
|
|
||||||
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
|
@Configuration
|
||||||
|
@GuiProfile
|
||||||
@Configuration
|
public class RAPSpringConfig {
|
||||||
@GuiProfile
|
|
||||||
public class RAPSpringConfig {
|
private static final Logger log = LoggerFactory.getLogger(RAPSpringConfig.class);
|
||||||
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(RAPSpringConfig.class);
|
@Value("${sebserver.gui.entrypoint}")
|
||||||
|
private String entrypoint;
|
||||||
@Value("${sebserver.gui.entrypoint}")
|
|
||||||
private String entrypoint;
|
@Value("${sebserver.gui.external.messages:messages}")
|
||||||
|
private String externalMessagesPath;
|
||||||
@Value("${sebserver.gui.external.messages:messages}")
|
|
||||||
private String externalMessagesPath;
|
@Bean
|
||||||
|
public ServletContextInitializer initializer() {
|
||||||
@Bean
|
return new RAPServletContextInitializer();
|
||||||
public ServletContextInitializer initializer() {
|
}
|
||||||
return new RAPServletContextInitializer();
|
|
||||||
}
|
@Bean
|
||||||
|
public ServletListenerRegistrationBean<ServletContextListener> listenerRegistrationBean() {
|
||||||
@Bean
|
final ServletListenerRegistrationBean<ServletContextListener> bean =
|
||||||
public ServletListenerRegistrationBean<ServletContextListener> listenerRegistrationBean() {
|
new ServletListenerRegistrationBean<>();
|
||||||
final ServletListenerRegistrationBean<ServletContextListener> bean =
|
bean.setListener(new RWTServletContextListener());
|
||||||
new ServletListenerRegistrationBean<>();
|
return bean;
|
||||||
bean.setListener(new RWTServletContextListener());
|
}
|
||||||
return bean;
|
|
||||||
}
|
@Bean
|
||||||
|
public ServletRegistrationBean<RWTServlet> servletRegistrationBean() {
|
||||||
@Bean
|
return new ServletRegistrationBean<>(new RWTServlet(), this.entrypoint + "/*");
|
||||||
public ServletRegistrationBean<RWTServlet> servletRegistrationBean() {
|
}
|
||||||
return new ServletRegistrationBean<>(new RWTServlet(), this.entrypoint + "/*");
|
|
||||||
}
|
@Bean
|
||||||
|
public MessageSource messageSource() {
|
||||||
@Bean
|
final ReloadableResourceBundleMessageSource reloadableResourceBundleMessageSource =
|
||||||
public MessageSource messageSource() {
|
new ReloadableResourceBundleMessageSource();
|
||||||
final ReloadableResourceBundleMessageSource reloadableResourceBundleMessageSource =
|
|
||||||
new ReloadableResourceBundleMessageSource();
|
log.info(" +++ Register external messages resources from: {}", this.externalMessagesPath);
|
||||||
|
|
||||||
log.info(" +++ Register external messages resources from: {}", this.externalMessagesPath);
|
reloadableResourceBundleMessageSource.setBasenames(
|
||||||
|
this.externalMessagesPath,
|
||||||
reloadableResourceBundleMessageSource.setBasenames(
|
"classpath:messages");
|
||||||
this.externalMessagesPath,
|
|
||||||
"classpath:messages");
|
return reloadableResourceBundleMessageSource;
|
||||||
|
}
|
||||||
return reloadableResourceBundleMessageSource;
|
|
||||||
}
|
private static class RAPServletContextInitializer implements ServletContextInitializer {
|
||||||
|
@Override
|
||||||
private static class RAPServletContextInitializer implements ServletContextInitializer {
|
public void onStartup(final ServletContext servletContext) {
|
||||||
@Override
|
servletContext.setInitParameter(
|
||||||
public void onStartup(final ServletContext servletContext) throws ServletException {
|
"org.eclipse.rap.applicationConfiguration",
|
||||||
servletContext.setInitParameter(
|
RAPConfiguration.class.getName());
|
||||||
"org.eclipse.rap.applicationConfiguration",
|
}
|
||||||
RAPConfiguration.class.getName());
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
|
@ -123,7 +123,7 @@ public class WidgetFactory {
|
||||||
private ImageData image = null;
|
private ImageData image = null;
|
||||||
private ImageData greyedImage = null;
|
private ImageData greyedImage = null;
|
||||||
|
|
||||||
private ImageIcon(final String fileName) {
|
ImageIcon(final String fileName) {
|
||||||
this.fileName = fileName;
|
this.fileName = fileName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -199,7 +199,7 @@ public class WidgetFactory {
|
||||||
|
|
||||||
public final String key;
|
public final String key;
|
||||||
|
|
||||||
private CustomVariant(final String key) {
|
CustomVariant(final String key) {
|
||||||
this.key = key;
|
this.key = key;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -268,7 +268,7 @@ public class WidgetFactory {
|
||||||
* @param parent The parent Composite
|
* @param parent The parent Composite
|
||||||
* @return the scrolled Composite to add the form content */
|
* @return the scrolled Composite to add the form content */
|
||||||
public Composite createPopupScrollComposite(final Composite parent) {
|
public Composite createPopupScrollComposite(final Composite parent) {
|
||||||
final Composite grid = PageService.createManagedVScrolledComposite(
|
return PageService.createManagedVScrolledComposite(
|
||||||
parent,
|
parent,
|
||||||
scrolledComposite -> {
|
scrolledComposite -> {
|
||||||
final Composite g = new Composite(scrolledComposite, SWT.NONE);
|
final Composite g = new Composite(scrolledComposite, SWT.NONE);
|
||||||
|
@ -277,7 +277,6 @@ public class WidgetFactory {
|
||||||
return g;
|
return g;
|
||||||
},
|
},
|
||||||
false);
|
false);
|
||||||
return grid;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Composite createWarningPanel(final Composite parent) {
|
public Composite createWarningPanel(final Composite parent) {
|
||||||
|
@ -733,7 +732,7 @@ public class WidgetFactory {
|
||||||
new FileUploadSelection(parent, this.i18nSupport, readonly);
|
new FileUploadSelection(parent, this.i18nSupport, readonly);
|
||||||
|
|
||||||
if (supportedFiles != null) {
|
if (supportedFiles != null) {
|
||||||
supportedFiles.forEach(ext -> fileUploadSelection.withSupportFor(ext));
|
supportedFiles.forEach(fileUploadSelection::withSupportFor);
|
||||||
}
|
}
|
||||||
return fileUploadSelection;
|
return fileUploadSelection;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.model.institution.LmsSetupTestResult;
|
||||||
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;
|
||||||
|
import org.joda.time.DateTimeZone;
|
||||||
|
|
||||||
/** Defines the LMS API access service interface with all functionality needed to access
|
/** Defines the LMS API access service interface with all functionality needed to access
|
||||||
* a LMS API within a given LmsSetup configuration.
|
* a LMS API within a given LmsSetup configuration.
|
||||||
|
@ -101,12 +102,12 @@ public interface LmsAPIService {
|
||||||
static Predicate<QuizData> quizFilterPredicate(final FilterMap filterMap) {
|
static Predicate<QuizData> quizFilterPredicate(final FilterMap filterMap) {
|
||||||
final String name = filterMap.getQuizName();
|
final String name = filterMap.getQuizName();
|
||||||
final DateTime from = filterMap.getQuizFromTime();
|
final DateTime from = filterMap.getQuizFromTime();
|
||||||
//final DateTime now = DateTime.now(DateTimeZone.UTC);
|
|
||||||
return q -> {
|
return q -> {
|
||||||
final boolean nameFilter = StringUtils.isBlank(name) || (q.name != null && q.name.contains(name));
|
final boolean nameFilter = StringUtils.isBlank(name) || (q.name != null && q.name.contains(name));
|
||||||
final boolean startTimeFilter =
|
final boolean startTimeFilter =
|
||||||
(from == null) || (q.startTime != null && (q.startTime.isEqual(from) || q.startTime.isAfter(from)));
|
(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) ;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,135 +1,141 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2019 ETH Zürich, Educational Development and Technology (LET)
|
* Copyright (c) 2019 ETH Zürich, Educational Development and Technology (LET)
|
||||||
*
|
*
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
* 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
|
* 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/.
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package ch.ethz.seb.sebserver.webservice.weblayer.api;
|
package ch.ethz.seb.sebserver.webservice.weblayer.api;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
||||||
import org.mybatis.dynamic.sql.SqlTable;
|
import org.mybatis.dynamic.sql.SqlTable;
|
||||||
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;
|
||||||
import org.springframework.web.bind.annotation.RequestMethod;
|
import org.springframework.web.bind.annotation.RequestMethod;
|
||||||
import org.springframework.web.bind.annotation.RequestParam;
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
import ch.ethz.seb.sebserver.gbl.api.API;
|
import ch.ethz.seb.sebserver.gbl.api.API;
|
||||||
import ch.ethz.seb.sebserver.gbl.api.API.BulkActionType;
|
import ch.ethz.seb.sebserver.gbl.api.API.BulkActionType;
|
||||||
import ch.ethz.seb.sebserver.gbl.api.EntityType;
|
import ch.ethz.seb.sebserver.gbl.api.EntityType;
|
||||||
import ch.ethz.seb.sebserver.gbl.api.authorization.PrivilegeType;
|
import ch.ethz.seb.sebserver.gbl.api.authorization.PrivilegeType;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
|
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
|
||||||
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.ExtendedClientEvent;
|
import ch.ethz.seb.sebserver.gbl.model.session.ExtendedClientEvent;
|
||||||
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
|
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
|
||||||
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.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.AuthorizationService;
|
||||||
import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.PermissionDeniedException;
|
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.UserService;
|
||||||
import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.impl.SEBServerUser;
|
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.bulkaction.BulkActionService;
|
||||||
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.ExamDAO;
|
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.FilterMap;
|
||||||
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.UserActivityLogDAO;
|
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.UserActivityLogDAO;
|
||||||
import ch.ethz.seb.sebserver.webservice.servicelayer.validation.BeanValidationService;
|
import ch.ethz.seb.sebserver.webservice.servicelayer.validation.BeanValidationService;
|
||||||
|
|
||||||
@WebServiceProfile
|
@WebServiceProfile
|
||||||
@RestController
|
@RestController
|
||||||
@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 final ExamDAO examDAO;
|
private final ExamDAO examDAO;
|
||||||
private final ClientEventDAO clientEventDAO;
|
private final ClientEventDAO clientEventDAO;
|
||||||
|
|
||||||
protected ClientEventController(
|
protected ClientEventController(
|
||||||
final AuthorizationService authorization,
|
final AuthorizationService authorization,
|
||||||
final BulkActionService bulkActionService,
|
final BulkActionService bulkActionService,
|
||||||
final ClientEventDAO entityDAO,
|
final ClientEventDAO entityDAO,
|
||||||
final UserActivityLogDAO userActivityLogDAO,
|
final UserActivityLogDAO userActivityLogDAO,
|
||||||
final PaginationService paginationService,
|
final PaginationService paginationService,
|
||||||
final BeanValidationService beanValidationService,
|
final BeanValidationService beanValidationService,
|
||||||
final ExamDAO examDAO) {
|
final ExamDAO examDAO) {
|
||||||
|
|
||||||
super(authorization,
|
super(authorization,
|
||||||
bulkActionService,
|
bulkActionService,
|
||||||
entityDAO,
|
entityDAO,
|
||||||
userActivityLogDAO,
|
userActivityLogDAO,
|
||||||
paginationService,
|
paginationService,
|
||||||
beanValidationService);
|
beanValidationService);
|
||||||
|
|
||||||
this.examDAO = examDAO;
|
this.examDAO = examDAO;
|
||||||
this.clientEventDAO = entityDAO;
|
this.clientEventDAO = entityDAO;
|
||||||
}
|
}
|
||||||
|
|
||||||
@RequestMapping(
|
@RequestMapping(
|
||||||
path = API.SEB_CLIENT_EVENT_SEARCH_PATH_SEGMENT,
|
path = API.SEB_CLIENT_EVENT_SEARCH_PATH_SEGMENT,
|
||||||
method = RequestMethod.GET,
|
method = RequestMethod.GET,
|
||||||
consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE,
|
consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE,
|
||||||
produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
|
produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
|
||||||
public Page<ExtendedClientEvent> getExtendedPage(
|
public Page<ExtendedClientEvent> getExtendedPage(
|
||||||
@RequestParam(
|
@RequestParam(
|
||||||
name = API.PARAM_INSTITUTION_ID,
|
name = API.PARAM_INSTITUTION_ID,
|
||||||
required = true,
|
required = true,
|
||||||
defaultValue = UserService.USERS_INSTITUTION_AS_DEFAULT) final Long institutionId,
|
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_NUMBER, required = false) final Integer pageNumber,
|
||||||
@RequestParam(name = Page.ATTR_PAGE_SIZE, required = false) final Integer pageSize,
|
@RequestParam(name = Page.ATTR_PAGE_SIZE, required = false) final Integer pageSize,
|
||||||
@RequestParam(name = Page.ATTR_SORT, required = false) final String sort,
|
@RequestParam(name = Page.ATTR_SORT, required = false) final String sort,
|
||||||
@RequestParam final MultiValueMap<String, String> allRequestParams) {
|
@RequestParam final MultiValueMap<String, String> allRequestParams) {
|
||||||
|
|
||||||
// at least current user must have base read access for specified entity type within its own institution
|
// at least current user must have base read access for specified entity type within its own institution
|
||||||
checkReadPrivilege(institutionId);
|
checkReadPrivilege(institutionId);
|
||||||
|
|
||||||
final FilterMap filterMap = new FilterMap(allRequestParams);
|
final FilterMap filterMap = new FilterMap(allRequestParams);
|
||||||
|
|
||||||
// if current user has no read access for specified entity type within other institution
|
// 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
|
// then the current users institutionId is put as a SQL filter criteria attribute to extends query performance
|
||||||
if (!this.authorization.hasGrant(PrivilegeType.READ, getGrantEntityType())) {
|
if (!this.authorization.hasGrant(PrivilegeType.READ, getGrantEntityType())) {
|
||||||
filterMap.putIfAbsent(API.PARAM_INSTITUTION_ID, String.valueOf(institutionId));
|
filterMap.putIfAbsent(API.PARAM_INSTITUTION_ID, String.valueOf(institutionId));
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.paginationService.getPage(
|
try {
|
||||||
pageNumber,
|
|
||||||
pageSize,
|
return this.paginationService.getPage(
|
||||||
sort,
|
pageNumber,
|
||||||
getSQLTableOfEntity().name(),
|
pageSize,
|
||||||
() -> this.clientEventDAO.allMatchingExtended(filterMap, this::hasReadAccess))
|
sort,
|
||||||
.getOrThrow();
|
getSQLTableOfEntity().name(),
|
||||||
}
|
() -> this.clientEventDAO.allMatchingExtended(filterMap, this::hasReadAccess))
|
||||||
|
.getOrThrow();
|
||||||
@Override
|
} catch (Exception e) {
|
||||||
public Collection<EntityKey> getDependencies(final String modelId, final BulkActionType bulkActionType) {
|
e.printStackTrace();
|
||||||
throw new UnsupportedOperationException();
|
throw e;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
@Override
|
|
||||||
protected SqlTable getSQLTableOfEntity() {
|
@Override
|
||||||
return ClientEventRecordDynamicSqlSupport.clientEventRecord;
|
public Collection<EntityKey> getDependencies(final String modelId, final BulkActionType bulkActionType) {
|
||||||
}
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
@Override
|
|
||||||
protected GrantEntity toGrantEntity(final ClientEvent entity) {
|
@Override
|
||||||
return this.examDAO
|
protected SqlTable getSQLTableOfEntity() {
|
||||||
.byClientConnection(entity.connectionId)
|
return ClientEventRecordDynamicSqlSupport.clientEventRecord;
|
||||||
.getOrThrow();
|
}
|
||||||
}
|
|
||||||
|
@Override
|
||||||
@Override
|
protected GrantEntity toGrantEntity(final ClientEvent entity) {
|
||||||
protected void checkReadPrivilege(final Long institutionId) {
|
return this.examDAO
|
||||||
final SEBServerUser currentUser = this.authorization.getUserService().getCurrentUser();
|
.byClientConnection(entity.connectionId)
|
||||||
if (currentUser.institutionId().longValue() != institutionId.longValue()) {
|
.get();
|
||||||
throw new PermissionDeniedException(
|
}
|
||||||
EntityType.CLIENT_EVENT,
|
|
||||||
PrivilegeType.READ,
|
@Override
|
||||||
currentUser.getUserInfo());
|
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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue