Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • arsnova/arsnova-backend
  • pcvl72/arsnova-backend
  • tksl38/arsnova-backend
3 results
Show changes
Showing
with 1096 additions and 1273 deletions
/*
* This file is part of ARSnova Backend.
* Copyright (C) 2012-2019 The ARSnova Team and Contributors
*
* ARSnova Backend is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* ARSnova Backend is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.thm.arsnova.controller;
import java.io.IOException;
import java.util.Arrays;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.pac4j.core.context.J2EContext;
import org.pac4j.oidc.client.OidcClient;
import org.pac4j.saml.client.SAML2Client;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.cas.web.CasAuthenticationEntryPoint;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.View;
import org.springframework.web.servlet.view.RedirectView;
import de.thm.arsnova.config.SecurityConfig;
import de.thm.arsnova.model.ClientAuthentication;
import de.thm.arsnova.model.LoginCredentials;
import de.thm.arsnova.model.UserProfile;
import de.thm.arsnova.security.LoginAuthenticationSucessHandler;
import de.thm.arsnova.service.UserService;
import de.thm.arsnova.web.exceptions.NotImplementedException;
@RestController
@RequestMapping("/auth")
public class AuthenticationController {
private UserService userService;
private OidcClient oidcClient;
private SAML2Client saml2Client;
private CasAuthenticationEntryPoint casEntryPoint;
public AuthenticationController(final UserService userService) {
this.userService = userService;
}
@Autowired(required = false)
public void setOidcClient(final OidcClient oidcClient) {
this.oidcClient = oidcClient;
}
@Autowired(required = false)
public void setSaml2Client(final SAML2Client saml2Client) {
this.saml2Client = saml2Client;
}
@Autowired(required = false)
public void setCasEntryPoint(final CasAuthenticationEntryPoint casEntryPoint) {
this.casEntryPoint = casEntryPoint;
}
@PostMapping("/login")
public ClientAuthentication login(@RequestParam(defaultValue = "false") final boolean refresh,
final HttpServletRequest request, final HttpServletResponse response) {
if (request.getCookies() != null && Arrays.stream(request.getCookies())
.anyMatch(c -> c.getName().equalsIgnoreCase(LoginAuthenticationSucessHandler.AUTH_COOKIE_NAME))) {
/* Delete cookie */
final Cookie cookie = new Cookie(LoginAuthenticationSucessHandler.AUTH_COOKIE_NAME, null);
cookie.setPath(request.getContextPath());
cookie.setMaxAge(0);
response.addCookie(cookie);
}
return userService.getCurrentClientAuthentication(refresh);
}
@PostMapping("/login/guest")
public ClientAuthentication loginGuest(final HttpServletRequest request) {
final ClientAuthentication currentAuthentication = userService.getCurrentClientAuthentication(false);
if (currentAuthentication != null
&& currentAuthentication.getAuthProvider() == UserProfile.AuthProvider.ARSNOVA_GUEST) {
return currentAuthentication;
}
userService.authenticate(new UsernamePasswordAuthenticationToken(null, null),
UserProfile.AuthProvider.ARSNOVA_GUEST, request.getRemoteAddr());
return userService.getCurrentClientAuthentication(false);
}
@PostMapping("/login/{providerId}")
public ClientAuthentication loginViaProvider(
@PathVariable final String providerId,
@RequestBody final LoginCredentials loginCredentials,
final HttpServletRequest request) {
switch (providerId) {
case "registered":
final String loginId = loginCredentials.getLoginId().toLowerCase();
userService.authenticate(new UsernamePasswordAuthenticationToken(
loginId, loginCredentials.getPassword()),
UserProfile.AuthProvider.ARSNOVA, request.getRemoteAddr());
return userService.getCurrentClientAuthentication(false);
case SecurityConfig.LDAP_PROVIDER_ID:
userService.authenticate(new UsernamePasswordAuthenticationToken(
loginCredentials.getLoginId(), loginCredentials.getPassword()),
UserProfile.AuthProvider.LDAP, request.getRemoteAddr());
return userService.getCurrentClientAuthentication(false);
default:
throw new IllegalArgumentException("Invalid provider ID.");
}
}
@GetMapping("/sso/{providerId}")
public View redirectToSso(@PathVariable final String providerId,
final HttpServletRequest request, final HttpServletResponse response) throws IOException, ServletException {
switch (providerId) {
case SecurityConfig.OIDC_PROVIDER_ID:
if (oidcClient == null) {
throw new IllegalArgumentException("Invalid provider ID.");
}
return new RedirectView(
oidcClient.getRedirectAction(new J2EContext(request, response)).getLocation());
case SecurityConfig.SAML_PROVIDER_ID:
if (saml2Client == null) {
throw new IllegalArgumentException("Invalid provider ID.");
}
return new RedirectView(
saml2Client.getRedirectAction(new J2EContext(request, response)).getLocation());
case SecurityConfig.CAS_PROVIDER_ID:
if (casEntryPoint == null) {
throw new IllegalArgumentException("Invalid provider ID.");
}
casEntryPoint.commence(request, response, null);
return null;
default:
throw new IllegalArgumentException("Invalid provider ID.");
}
}
@GetMapping(value = "/config/saml/sp-metadata.xml", produces = MediaType.APPLICATION_XML_VALUE)
public String samlSpMetadata() throws IOException {
if (saml2Client == null) {
throw new NotImplementedException("SAML authentication is disabled.");
}
return saml2Client.getServiceProviderMetadataResolver().getMetadata();
}
}
/*
* This file is part of ARSnova Backend.
* Copyright (C) 2012-2019 The ARSnova Team and Contributors
*
* ARSnova Backend is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* ARSnova Backend is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.thm.arsnova.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import de.thm.arsnova.model.Comment;
import de.thm.arsnova.service.CommentService;
@RestController
@RequestMapping(CommentController.REQUEST_MAPPING)
public class CommentController extends AbstractEntityController<Comment> {
protected static final String REQUEST_MAPPING = "/comment";
private CommentService commentService;
public CommentController(final CommentService commentService) {
super(commentService);
this.commentService = commentService;
}
@Override
protected String getMapping() {
return REQUEST_MAPPING;
}
}
/*
* This file is part of ARSnova Backend.
* Copyright (C) 2012-2019 The ARSnova Team and Contributors
*
* ARSnova Backend is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* ARSnova Backend is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.thm.arsnova.controller;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import de.thm.arsnova.config.SecurityConfig;
import de.thm.arsnova.config.properties.AuthenticationProviderProperties;
import de.thm.arsnova.config.properties.FeatureProperties;
import de.thm.arsnova.config.properties.UiProperties;
import de.thm.arsnova.model.AuthenticationProvider;
import de.thm.arsnova.model.Configuration;
@RestController
@RequestMapping(ConfigurationController.REQUEST_MAPPING)
@EnableConfigurationProperties(UiProperties.class)
public class ConfigurationController {
protected static final String REQUEST_MAPPING = "/configuration";
private AuthenticationProviderProperties providerProperties;
private UiProperties uiProperties;
private FeatureProperties featureProperties;
private List<AuthenticationProvider> authenticationProviders;
private Map<String, Object> featureConfig;
public ConfigurationController(
final AuthenticationProviderProperties authenticationProviderProperties,
final UiProperties uiProperties,
final FeatureProperties featureProperties) {
this.providerProperties = authenticationProviderProperties;
this.uiProperties = uiProperties;
this.featureProperties = featureProperties;
buildAuthenticationProviderConfig();
buildFeatureConfig();
}
@GetMapping
public Configuration get() {
final Configuration configuration = new Configuration();
configuration.setAuthenticationProviders(authenticationProviders);
configuration.setUi(uiProperties.getUi());
configuration.setFeatures(featureConfig);
return configuration;
}
private void buildAuthenticationProviderConfig() {
this.authenticationProviders = new ArrayList<>();
if (providerProperties.getGuest().isEnabled()) {
authenticationProviders.add(new AuthenticationProvider("guest", providerProperties.getGuest()));
}
if (providerProperties.getRegistered().isEnabled()) {
authenticationProviders.add(new AuthenticationProvider(
SecurityConfig.INTERNAL_PROVIDER_ID, providerProperties.getRegistered()));
}
if (!providerProperties.getLdap().isEmpty() && providerProperties.getLdap().get(0).isEnabled()) {
authenticationProviders.add(new AuthenticationProvider(
SecurityConfig.LDAP_PROVIDER_ID, providerProperties.getLdap().get(0)));
}
if (!providerProperties.getOidc().isEmpty() && providerProperties.getOidc().get(0).isEnabled()) {
authenticationProviders.add(new AuthenticationProvider(
SecurityConfig.OIDC_PROVIDER_ID, providerProperties.getOidc().get(0)));
}
if (providerProperties.getSaml().isEnabled()) {
authenticationProviders.add(new AuthenticationProvider(
SecurityConfig.SAML_PROVIDER_ID, providerProperties.getSaml()));
}
if (providerProperties.getCas().isEnabled()) {
authenticationProviders.add(new AuthenticationProvider(
SecurityConfig.CAS_PROVIDER_ID, providerProperties.getCas()));
}
}
private void buildFeatureConfig() {
this.featureConfig = new HashMap<>();
featureConfig.put("contents", featureProperties.getContents());
featureConfig.put("comments", featureProperties.getComments());
featureConfig.put("liveFeedback", featureProperties.getLiveFeedback());
featureConfig.put("contentPool", featureProperties.getContentPool());
}
}
/*
* This file is part of ARSnova Backend.
* Copyright (C) 2012-2019 The ARSnova Team and Contributors
*
* ARSnova Backend is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* ARSnova Backend is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.thm.arsnova.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import de.thm.arsnova.model.AnswerStatistics;
import de.thm.arsnova.model.Content;
import de.thm.arsnova.service.AnswerService;
import de.thm.arsnova.service.ContentService;
@RestController
@RequestMapping(ContentController.REQUEST_MAPPING)
public class ContentController extends AbstractEntityController<Content> {
protected static final String REQUEST_MAPPING = "/content";
private static final String GET_ANSWER_STATISTICS_MAPPING = DEFAULT_ID_MAPPING + "/stats";
private ContentService contentService;
private AnswerService answerService;
public ContentController(final ContentService contentService, final AnswerService answerService) {
super(contentService);
this.contentService = contentService;
this.answerService = answerService;
}
@Override
protected String getMapping() {
return REQUEST_MAPPING;
}
@GetMapping(GET_ANSWER_STATISTICS_MAPPING)
public AnswerStatistics getAnswerStatistics(@PathVariable final String id) {
return answerService.getAllStatistics(id);
}
}
/*
* This file is part of ARSnova Backend.
* Copyright (C) 2012-2019 The ARSnova Team and Contributors
*
* ARSnova Backend is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* ARSnova Backend is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.thm.arsnova.controller;
import java.util.Map;
import javax.naming.OperationNotSupportedException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.ektorp.DocumentNotFoundException;
import org.slf4j.event.Level;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.authentication.AnonymousAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;
import de.thm.arsnova.model.EntityValidationException;
import de.thm.arsnova.web.exceptions.BadRequestException;
import de.thm.arsnova.web.exceptions.ForbiddenException;
import de.thm.arsnova.web.exceptions.NoContentException;
import de.thm.arsnova.web.exceptions.NotFoundException;
import de.thm.arsnova.web.exceptions.NotImplementedException;
import de.thm.arsnova.web.exceptions.PayloadTooLargeException;
import de.thm.arsnova.web.exceptions.PreconditionFailedException;
import de.thm.arsnova.web.exceptions.UnauthorizedException;
/**
* Translates exceptions into HTTP status codes.
*/
@ControllerAdvice
public class ControllerExceptionHandler extends ResponseEntityExceptionHandler {
private ControllerExceptionHelper helper;
public ControllerExceptionHandler(final ControllerExceptionHelper helper) {
this.helper = helper;
}
@ExceptionHandler(NoContentException.class)
@ResponseBody
@ResponseStatus(HttpStatus.NO_CONTENT)
public Map<String, Object> handleNoContentException(final Exception e, final HttpServletRequest request) {
return helper.handleException(e, Level.TRACE);
}
@ExceptionHandler(NotFoundException.class)
@ResponseBody
@ResponseStatus(HttpStatus.NOT_FOUND)
public Map<String, Object> handleNotFoundException(final Exception e, final HttpServletRequest request) {
return helper.handleException(e, Level.TRACE);
}
@ExceptionHandler(UnauthorizedException.class)
@ResponseBody
@ResponseStatus(HttpStatus.UNAUTHORIZED)
public Map<String, Object> handleUnauthorizedException(final Exception e, final HttpServletRequest request) {
return helper.handleException(e, Level.TRACE);
}
@ExceptionHandler(AuthenticationException.class)
@ResponseStatus(HttpStatus.UNAUTHORIZED)
@ResponseBody
public Map<String, Object> handleAuthenticationExceptionException(
final Exception e, final HttpServletRequest request) {
return helper.handleException(e, Level.DEBUG);
}
@ExceptionHandler(AccessDeniedException.class)
@ResponseBody
public Map<String, Object> handleAccessDeniedException(
final Exception e,
final HttpServletRequest request,
final HttpServletResponse response) {
final Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication == null
|| authentication.getPrincipal() == null
|| authentication instanceof AnonymousAuthenticationToken) {
response.setStatus(HttpStatus.UNAUTHORIZED.value());
} else {
response.setStatus(HttpStatus.FORBIDDEN.value());
}
return helper.handleException(e, Level.DEBUG);
}
@ExceptionHandler(ForbiddenException.class)
@ResponseBody
@ResponseStatus(HttpStatus.FORBIDDEN)
public Map<String, Object> handleForbiddenException(final Exception e, final HttpServletRequest request) {
return helper.handleException(e, Level.DEBUG);
}
@ExceptionHandler(BadRequestException.class)
@ResponseBody
@ResponseStatus(HttpStatus.BAD_REQUEST)
public Map<String, Object> handleBadRequestException(final Exception e, final HttpServletRequest request) {
return helper.handleException(e, Level.DEBUG);
}
@ExceptionHandler(EntityValidationException.class)
@ResponseBody
@ResponseStatus(HttpStatus.BAD_REQUEST)
public Map<String, Object> handleEntityValidationException(
final EntityValidationException e, final HttpServletRequest request) {
return helper.handleException(e, Level.DEBUG);
}
@ExceptionHandler(PreconditionFailedException.class)
@ResponseBody
@ResponseStatus(HttpStatus.PRECONDITION_FAILED)
public Map<String, Object> handlePreconditionFailedException(final Exception e, final HttpServletRequest request) {
return helper.handleException(e, Level.DEBUG);
}
@ExceptionHandler({NotImplementedException.class, OperationNotSupportedException.class})
@ResponseBody
@ResponseStatus(HttpStatus.NOT_IMPLEMENTED)
public Map<String, Object> handleNotImplementedException(final Exception e, final HttpServletRequest request) {
return helper.handleException(e, Level.DEBUG);
}
@ExceptionHandler(PayloadTooLargeException.class)
@ResponseBody
@ResponseStatus(HttpStatus.PAYLOAD_TOO_LARGE)
public Map<String, Object> handlePayloadTooLargeException(final Exception e, final HttpServletRequest request) {
return helper.handleException(e, Level.DEBUG);
}
/* FIXME: Wrap persistance Exceptions - do not handle persistance Exceptions at the controller layer */
@ExceptionHandler(DocumentNotFoundException.class)
@ResponseBody
@ResponseStatus(HttpStatus.NOT_FOUND)
public Map<String, Object> handleDocumentNotFoundException(final Exception e, final HttpServletRequest request) {
return helper.handleException(e, Level.TRACE);
}
@Override
protected ResponseEntity<Object> handleExceptionInternal(final Exception ex, final Object body,
final HttpHeaders headers, final HttpStatus status, final WebRequest request) {
return new ResponseEntity<>(helper.handleException(ex, Level.TRACE), headers, status);
}
}
/*
* This file is part of ARSnova Backend.
* Copyright (C) 2012-2019 The ARSnova Team and Contributors
*
* ARSnova Backend is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* ARSnova Backend is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.thm.arsnova.controller;
import java.util.HashMap;
import java.util.Map;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.event.Level;
import org.springframework.stereotype.Component;
import de.thm.arsnova.config.properties.SystemProperties;
@Component
public class ControllerExceptionHelper {
private static final Logger logger = LoggerFactory.getLogger(ControllerExceptionHelper.class);
/* Since exception messages might contain sensitive data, they are not exposed by default. */
private boolean exposeMessages;
public ControllerExceptionHelper(final SystemProperties systemProperties) {
this.exposeMessages = systemProperties.getApi().isExposeErrorMessages();
}
public Map<String, Object> handleException(@NonNull final Throwable e, @NonNull final Level level) {
final String message = e.getMessage() != null ? e.getMessage() : "";
log(level, message, e);
final Map<String, Object> result = new HashMap<>();
result.put("errorType", e.getClass().getSimpleName());
if (exposeMessages) {
result.put("errorMessage", e.getMessage());
}
return result;
}
private void log(final Level level, final String message, final Throwable e) {
switch (level) {
case ERROR:
logger.error(message, e);
break;
case WARN:
logger.warn(message, e);
break;
case INFO:
logger.info(message, e);
break;
case DEBUG:
logger.debug(message, e);
break;
case TRACE:
logger.trace(message, e);
break;
default:
break;
}
}
}
/*
* This file is part of ARSnova Backend.
* Copyright (C) 2012-2019 The ARSnova Team and Contributors
*
* ARSnova Backend is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* ARSnova Backend is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.thm.arsnova.controller;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.slf4j.event.Level;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
@ControllerAdvice
public class DefaultControllerExceptionHandler {
private ControllerExceptionHelper helper;
public DefaultControllerExceptionHandler(final ControllerExceptionHelper helper) {
this.helper = helper;
}
@ExceptionHandler
@ResponseBody
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public Map<String, Object> defaultExceptionHandler(
final Exception e,
final HttpServletRequest req
) throws Exception {
/* If the exception is annotated with @ResponseStatus rethrow it and let
* the framework handle it.
* See https://spring.io/blog/2013/11/01/exception-handling-in-spring-mvc. */
if (AnnotationUtils.findAnnotation(e.getClass(), ResponseStatus.class) != null) {
throw e;
}
return helper.handleException(e, Level.ERROR);
}
}
/*
* Copyright (C) 2012 THM webMedia
*
* This file is part of ARSnova.
*
* ARSnova is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* ARSnova is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.thm.arsnova.controller;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import de.thm.arsnova.entities.Feedback;
import de.thm.arsnova.entities.User;
import de.thm.arsnova.exceptions.NotFoundException;
import de.thm.arsnova.services.IFeedbackService;
import de.thm.arsnova.services.IUserService;
@Controller
public class FeedbackController extends AbstractController {
public static final Logger LOGGER = LoggerFactory.getLogger(FeedbackController.class);
@Autowired
private IFeedbackService feedbackService;
@Autowired
private IUserService userService;
@RequestMapping(value = "/session/{sessionkey}/feedback", method = RequestMethod.GET)
@ResponseBody
public final Feedback getFeedback(@PathVariable final String sessionkey, final HttpServletResponse response) {
response.addHeader("X-Deprecated-API", "1");
return feedbackService.getFeedback(sessionkey);
}
@RequestMapping(value = "/session/{sessionkey}/myfeedback", method = RequestMethod.GET)
@ResponseBody
public final Integer getMyFeedback(@PathVariable final String sessionkey, final HttpServletResponse response) {
Integer value = feedbackService.getMyFeedback(sessionkey, userService.getCurrentUser());
response.addHeader("X-Deprecated-API", "1");
if (value != null && value >= Feedback.MIN_FEEDBACK_TYPE && value <= Feedback.MAX_FEEDBACK_TYPE) {
return value;
}
throw new NotFoundException();
}
@RequestMapping(value = "/session/{sessionkey}/feedbackcount", method = RequestMethod.GET)
@ResponseBody
public final int getFeedbackCount(@PathVariable final String sessionkey, final HttpServletResponse response) {
response.addHeader("X-Deprecated-API", "1");
return feedbackService.getFeedbackCount(sessionkey);
}
@RequestMapping(value = "/session/{sessionkey}/roundedaveragefeedback", method = RequestMethod.GET)
@ResponseBody
public final long getAverageFeedbackRounded(
@PathVariable final String sessionkey,
final HttpServletResponse response
) {
response.addHeader("X-Deprecated-API", "1");
return feedbackService.getAverageFeedbackRounded(sessionkey);
}
@RequestMapping(value = "/session/{sessionkey}/averagefeedback", method = RequestMethod.GET)
@ResponseBody
public final double getAverageFeedback(@PathVariable final String sessionkey, final HttpServletResponse response) {
response.addHeader("X-Deprecated-API", "1");
return feedbackService.getAverageFeedback(sessionkey);
}
@RequestMapping(value = "/session/{sessionkey}/feedback", method = RequestMethod.POST)
@ResponseBody
@ResponseStatus(HttpStatus.CREATED)
public final Feedback postFeedback(
@PathVariable final String sessionkey,
@RequestBody final int value,
final HttpServletResponse response
) {
response.addHeader("X-Deprecated-API", "1");
User user = userService.getCurrentUser();
if (feedbackService.saveFeedback(sessionkey, value, user)) {
Feedback feedback = feedbackService.getFeedback(sessionkey);
if (feedback != null) {
return feedback;
}
throw new RuntimeException();
}
throw new NotFoundException();
}
}
/*
* Copyright (C) 2012 THM webMedia
*
* This file is part of ARSnova.
*
* ARSnova is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* ARSnova is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.thm.arsnova.controller;
import java.util.List;
import javax.servlet.http.HttpServletResponse;
import net.sf.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import de.thm.arsnova.entities.FoodVote;
import de.thm.arsnova.services.IFoodService;
@Controller
@RequestMapping("/canteen/menu/vote")
public class FoodVoteController extends AbstractController {
public static final Logger LOGGER = LoggerFactory
.getLogger(FoodVoteController.class);
@Autowired
private IFoodService foodService;
@RequestMapping(value = "/", method = RequestMethod.POST)
public final void setFoodVote(
@RequestBody final Object menu,
final HttpServletResponse response
) {
String menustring = JSONObject.fromObject(menu).getString("menu");
foodService.vote(menustring);
}
@RequestMapping(value = "/", method = RequestMethod.GET)
@ResponseBody
public final List<FoodVote> getFoodVote() {
return foodService.getFoodVote();
}
@RequestMapping(value = "/count", method = RequestMethod.GET, produces = "text/plain")
@ResponseBody
public final String getFoodVoteCount() {
return Integer.toString(foodService.getFoodVoteCount());
}
}
/*
* This file is part of ARSnova Backend.
* Copyright (C) 2012-2019 The ARSnova Team and Contributors
*
* ARSnova Backend is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* ARSnova Backend is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.thm.arsnova.controller;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.json.MappingJacksonValue;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.AbstractMappingJacksonResponseBodyAdvice;
import org.springframework.web.util.UriComponentsBuilder;
import de.thm.arsnova.model.serialization.View;
/**
* This {@link ControllerAdvice} applies a {@link View} based on the
* <code>view</code> query parameter which is used by
* {@link com.fasterxml.jackson.annotation.JsonView} for serialization and makes
* sure that the user is authorized.
*
* @author Daniel Gerhardt
*/
@ControllerAdvice
public class JsonViewControllerAdvice extends AbstractMappingJacksonResponseBodyAdvice {
private static final String VIEW_PARAMETER = "view";
private static final Logger logger = LoggerFactory.getLogger(JsonViewControllerAdvice.class);
@Override
protected void beforeBodyWriteInternal(final MappingJacksonValue bodyContainer,
final MediaType contentType, final MethodParameter returnType,
final ServerHttpRequest request, final ServerHttpResponse response) {
/* TODO: Why does @ControllerAdvice(assignableTypes = AbstractEntityController.class) not work? */
if (!AbstractEntityController.class.isAssignableFrom(returnType.getContainingClass())) {
return;
}
final List<String> viewList = UriComponentsBuilder.fromUri(request.getURI()).build()
.getQueryParams().getOrDefault(VIEW_PARAMETER, Collections.emptyList());
if (viewList.isEmpty()) {
return;
}
final String view = viewList.get(0);
logger.debug("'{}' parameter found in request URI: {}", VIEW_PARAMETER, view);
if (bodyContainer.getValue() instanceof Collection) {
logger.warn("'{}' parameter is currently not supported for listing endpoints.", VIEW_PARAMETER);
}
tryAccess(bodyContainer.getValue(), view);
switch (view) {
case "owner":
bodyContainer.setSerializationView(View.Owner.class);
break;
case "admin":
bodyContainer.setSerializationView(View.Admin.class);
break;
default:
return;
}
}
@PreAuthorize("hasPermission(#targetDomainObject, #permission)")
protected void tryAccess(final Object targetDomainObject, final Object permission) {
/* Access check is done by aspect. No additional implementation needed. */
}
}
/*
* Copyright (C) 2012 THM webMedia
*
* This file is part of ARSnova.
*
* ARSnova is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* ARSnova is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.thm.arsnova.controller;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
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.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import de.thm.arsnova.entities.Answer;
import de.thm.arsnova.entities.Question;
import de.thm.arsnova.exceptions.BadRequestException;
import de.thm.arsnova.exceptions.NoContentException;
import de.thm.arsnova.exceptions.NotFoundException;
import de.thm.arsnova.services.IQuestionService;
@Controller
@RequestMapping("/lecturerquestion")
public class LecturerQuestionController extends AbstractController {
public static final Logger LOGGER = LoggerFactory.getLogger(LecturerQuestionController.class);
@Autowired
private IQuestionService questionService;
@RequestMapping(value = "/{questionId}", method = RequestMethod.GET)
@ResponseBody
public final Question getQuestion(
@PathVariable final String questionId,
final HttpServletResponse response
) {
Question question = questionService.getQuestion(questionId);
if (question != null) {
return question;
}
throw new NotFoundException();
}
@RequestMapping(value = "/", method = RequestMethod.POST)
@ResponseBody
@ResponseStatus(HttpStatus.CREATED)
public final Question postQuestion(@RequestBody final Question question, final HttpServletResponse response) {
if (questionService.saveQuestion(question) != null) {
return question;
}
throw new BadRequestException();
}
@RequestMapping(value = "/{questionId}", method = RequestMethod.PUT)
@ResponseBody
public final void updateQuestion(
@PathVariable final String questionId,
@RequestBody final Question question,
final HttpServletResponse response
) {
this.questionService.update(question);
}
@RequestMapping(value = "/{questionId}/publish", method = RequestMethod.POST)
@ResponseBody
public final void publishQuestion(
@PathVariable final String questionId,
@RequestParam(required = false) final Boolean publish,
@RequestBody final Question question,
final HttpServletResponse response
) {
if (publish != null) {
question.setActive(publish);
}
this.questionService.update(question);
}
@RequestMapping(value = "/{questionId}/publishstatistics", method = RequestMethod.POST)
@ResponseBody
public final void publishStatistics(
@PathVariable final String questionId,
@RequestParam(required = false) final Boolean showStatistics,
@RequestBody final Question question,
final HttpServletResponse response
) {
if (showStatistics != null) {
question.setShowStatistic(showStatistics);
}
this.questionService.update(question);
}
@RequestMapping(value = "/{questionId}/publishcorrectanswer", method = RequestMethod.POST)
@ResponseBody
public final void publishCorrectAnswer(
@PathVariable final String questionId,
@RequestParam(required = false) final Boolean showCorrectAnswer,
@RequestBody final Question question,
final HttpServletResponse response
) {
if (showCorrectAnswer != null) {
question.setShowAnswer(showCorrectAnswer);
}
this.questionService.update(question);
}
@RequestMapping(
value = { "/" },
method = RequestMethod.GET
)
@ResponseBody
public final List<Question> getSkillQuestions(
@RequestParam final String sessionkey,
final HttpServletResponse response
) {
List<Question> questions = questionService.getSkillQuestions(sessionkey);
if (questions == null || questions.isEmpty()) {
response.setStatus(HttpStatus.NO_CONTENT.value());
return null;
}
return questions;
}
@RequestMapping(value = "/count", method = RequestMethod.GET)
@ResponseBody
public final int getSkillQuestionCount(@RequestParam final String sessionkey, final HttpServletResponse response) {
response.addHeader("X-Deprecated-API", "1");
return questionService.getSkillQuestionCount(sessionkey);
}
/*
* TODO is this used anywhere?
@RequestMapping(value = "/ids", method = RequestMethod.GET)
@ResponseBody
public final List<String> getQuestionIds(
@RequestParam final String sessionkey,
final HttpServletResponse response
) {
List<String> questions = questionService.getQuestionIds(sessionkey);
if (questions == null || questions.isEmpty()) {
throw new NotFoundException();
}
return questions;
}
*/
@RequestMapping(value = "/{questionId}", method = RequestMethod.DELETE)
@ResponseBody
public final void deleteAnswersAndQuestion(
@PathVariable final String questionId,
final HttpServletResponse response
) {
questionService.deleteQuestion(questionId);
}
@RequestMapping(value = "/unanswered", method = RequestMethod.GET)
@ResponseBody
public final List<String> getUnAnsweredSkillQuestions(
@RequestParam final String sessionkey,
final HttpServletResponse response
) {
List<String> answers = questionService.getUnAnsweredQuestions(sessionkey);
if (answers == null || answers.isEmpty()) {
throw new NoContentException();
}
response.addHeader("X-Deprecated-API", "1");
return answers;
}
/**
* returns a JSON document which represents the given answer of a question.
*
* @param sessionKey
* Session Keyword to which the question belongs to
* @param questionId
* CouchDB Question ID for which the given answer should be
* retrieved
* @return JSON Document of {@link Answer} or {@link NotFoundException}
* @throws NotFoundException
* if wrong session, wrong question or no answer was given by
* the current user
* @throws ForbiddenException
* if not logged in
*/
@RequestMapping(value = "/{questionId}/myanswer", method = RequestMethod.GET)
@ResponseBody
public final Answer getMyAnswer(
@PathVariable final String questionId,
final HttpServletResponse response
) {
Answer answer = questionService.getMyAnswer(questionId);
if (answer == null) {
response.setStatus(HttpStatus.NO_CONTENT.value());
return null;
}
response.addHeader("X-Deprecated-API", "1");
return answer;
}
/**
* returns a list of {@link Answer}s encoded as a JSON document for a given
* question id. In this case only {@link Answer} <tt>questionId</tt>,
* <tt>answerText</tt>, <tt>answerSubject</tt> and <tt>answerCount</tt>
* properties are set
*
* @param sessionKey
* Session Keyword to which the question belongs to
* @param questionId
* CouchDB Question ID for which the given answers should be
* retrieved
* @return List<{@link Answer}> or {@link NotFoundException}
* @throws NotFoundException
* if wrong session, wrong question or no answers was given
* @throws ForbiddenException
* if not logged in
*/
@RequestMapping(value = "/{questionId}/answer/", method = RequestMethod.GET)
@ResponseBody
public final List<Answer> getAnswers(
@PathVariable final String questionId,
final HttpServletResponse response
) {
List<Answer> answers = questionService.getAnswers(questionId);
if (answers == null) {
return new ArrayList<Answer>();
}
return answers;
}
@RequestMapping(value = "/{questionId}/answer/", method = RequestMethod.POST)
@ResponseBody
public final Answer saveAnswer(
@PathVariable final String questionId,
@RequestBody final Answer answer,
final HttpServletResponse response
) {
return questionService.saveAnswer(answer);
}
@RequestMapping(value = "/{questionId}/answer/{answerId}", method = RequestMethod.PUT)
@ResponseBody
public final Answer updateAnswer(
@PathVariable final String questionId,
@PathVariable final String answerId,
@RequestBody final Answer answer,
final HttpServletResponse response
) {
return questionService.updateAnswer(answer);
}
@RequestMapping(value = "/{questionId}/answer/{answerId}", method = RequestMethod.DELETE)
@ResponseBody
public final void deleteAnswer(
@PathVariable final String questionId,
@PathVariable final String answerId,
final HttpServletResponse response
) {
questionService.deleteAnswer(questionId, answerId);
}
@RequestMapping(value = "/{questionId}/answer/", method = RequestMethod.DELETE)
@ResponseBody
public final void deleteAnswers(
@PathVariable final String questionId,
final HttpServletResponse response
) {
questionService.deleteAnswers(questionId);
}
/**
*
* @param sessionKey
* Session Keyword to which the question belongs to
* @param questionId
* CouchDB Question ID for which the given answers should be
* retrieved
* @return count of answers for given question id
* @throws NotFoundException
* if wrong session or wrong question
* @throws ForbiddenException
* if not logged in
*/
@RequestMapping(value = "/{questionId}/answercount", method = RequestMethod.GET)
@ResponseBody
public final int getAnswerCount(
@PathVariable final String questionId,
final HttpServletResponse response
) {
response.addHeader("X-Deprecated-API", "1");
return questionService.getAnswerCount(questionId);
}
@RequestMapping(value = "/{questionId}/freetextanswer/", method = RequestMethod.GET)
@ResponseBody
public final List<Answer> getFreetextAnswers(
@PathVariable final String questionId,
final HttpServletResponse response
) {
return questionService.getFreetextAnswers(questionId);
}
@RequestMapping(value = "/myanswers", method = RequestMethod.GET)
@ResponseBody
public final List<Answer> getMyAnswers(
@RequestParam final String sessionkey,
final HttpServletResponse response
) {
response.addHeader("X-Deprecated-API", "1");
return questionService.getMytAnswers(sessionkey);
}
@RequestMapping(value = "/answercount", method = RequestMethod.GET)
@ResponseBody
public final int getTotalAnswerCount(
@RequestParam final String sessionkey,
final HttpServletResponse response
) {
response.addHeader("X-Deprecated-API", "1");
return questionService.getTotalAnswerCount(sessionkey);
}
}
/*
* Copyright (C) 2012 THM webMedia
*
* This file is part of ARSnova.
*
* ARSnova is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* ARSnova is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.thm.arsnova.controller;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@Controller
public class LegacyController extends AbstractController {
public static final Logger LOGGER = LoggerFactory.getLogger(LegacyController.class);
/* specific routes */
@RequestMapping(value = "/session/mysessions", method = RequestMethod.GET)
public final String redirectSessionMy(
final HttpServletResponse response
) {
response.addHeader("X-Deprecated-API", "1");
return "forward:/session/?ownedonly=true";
}
@RequestMapping(value = "/session/visitedsessions", method = RequestMethod.GET)
public final String redirectSessionVisited(
final HttpServletResponse response
) {
response.addHeader("X-Deprecated-API", "1");
return "forward:/session/?visitedonly=true";
}
@RequestMapping(value = "/session/{sessionKey}/question")
public final String redirectQuestionByLecturer(
@PathVariable final String sessionKey,
final HttpServletResponse response
) {
response.addHeader("X-Deprecated-API", "1");
return String.format("forward:/lecturerquestion/?sessionkey=%s", sessionKey);
}
@RequestMapping(value = "/session/{sessionKey}/skillquestions", method = RequestMethod.GET)
public final String redirectQuestionByLecturerList(
@PathVariable final String sessionKey,
final HttpServletResponse response
) {
response.addHeader("X-Deprecated-API", "1");
return String.format("forward:/lecturerquestion/?sessionkey=%s", sessionKey);
}
@RequestMapping(value = "/session/{sessionKey}/skillquestioncount", method = RequestMethod.GET)
public final String redirectQuestionByLecturerCount(
@PathVariable final String sessionKey,
final HttpServletResponse response
) {
response.addHeader("X-Deprecated-API", "1");
return String.format("forward:/lecturerquestion/count?sessionkey=%s", sessionKey);
}
@RequestMapping(value = "/session/{sessionKey}/answercount", method = RequestMethod.GET)
public final String redirectQuestionByLecturerAnswerCount(
@PathVariable final String sessionKey,
final HttpServletResponse response
) {
response.addHeader("X-Deprecated-API", "1");
return String.format("forward:/lecturerquestion/answercount?sessionkey=%s", sessionKey);
}
@RequestMapping(value = "/session/{sessionKey}/unanswered", method = RequestMethod.GET)
public final String redirectQuestionByLecturerUnnsweredCount(
@PathVariable final String sessionKey,
final HttpServletResponse response
) {
response.addHeader("X-Deprecated-API", "1");
return String.format("forward:/lecturerquestion/answercount?sessionkey=%s", sessionKey);
}
@RequestMapping(value = "/session/{sessionKey}/myanswers", method = RequestMethod.GET)
public final String redirectQuestionByLecturerMyAnswers(
@PathVariable final String sessionKey,
final HttpServletResponse response
) {
response.addHeader("X-Deprecated-API", "1");
return String.format("forward:/lecturerquestion/myanswers?sessionkey=%s", sessionKey);
}
@RequestMapping(value = "/session/{sessionKey}/interposed")
public final String redirectQuestionByAudience(
@PathVariable final String sessionKey,
final HttpServletResponse response
) {
response.addHeader("X-Deprecated-API", "1");
return String.format("forward:/audiencequestion/?sessionkey=%s", sessionKey);
}
@RequestMapping(value = "/session/{sessionKey}/interposedcount", method = RequestMethod.GET)
public final String redirectQuestionByAudienceCount(
@PathVariable final String sessionKey,
final HttpServletResponse response
) {
response.addHeader("X-Deprecated-API", "1");
return String.format("forward:/audiencequestion/count?sessionkey=%s", sessionKey);
}
@RequestMapping(value = "/session/{sessionKey}/interposedreadingcount", method = RequestMethod.GET)
public final String redirectQuestionByAudienceReadCount(
@PathVariable final String sessionKey,
final HttpServletResponse response
) {
response.addHeader("X-Deprecated-API", "1");
return String.format("forward:/audiencequestion/readcount?sessionkey=%s", sessionKey);
}
/* generalized routes */
@RequestMapping(value = { "/session/{sessionKey}/question/{arg1}", "/session/{sessionKey}/questions/{arg1}" })
public final String redirectQuestionByLecturerWithOneArgument(
@PathVariable final String sessionKey,
@PathVariable final String arg1,
final HttpServletResponse response
) {
response.addHeader("X-Deprecated-API", "1");
return String.format("forward:/lecturerquestion/%s/?sessionkey=%s", arg1, sessionKey);
}
@RequestMapping(
value = { "/session/{sessionKey}/question/{arg1}/{arg2}", "/session/{sessionKey}/questions/{arg1}/{arg2}" }
)
public final String redirectQuestionByLecturerWithTwoArguments(
@PathVariable final String sessionKey,
@PathVariable final String arg1,
@PathVariable final String arg2,
final HttpServletResponse response
) {
response.addHeader("X-Deprecated-API", "1");
return String.format("forward:/lecturerquestion/%s/%s/?sessionkey=%s", arg1, arg2, sessionKey);
}
@RequestMapping(value = "/session/{sessionKey}/interposed/{arg1}")
public final String redirectQuestionByAudienceWithOneArgument(
@PathVariable final String sessionKey,
@PathVariable final String arg1,
final HttpServletResponse response
) {
response.addHeader("X-Deprecated-API", "1");
return String.format("forward:/audiencequestion/%s/?sessionkey=%s", arg1, sessionKey);
}
@RequestMapping(value = "/session/{sessionKey}/interposed/{arg1}/{arg2}")
public final String redirectQuestionByAudienceWithTwoArguments(
@PathVariable final String sessionKey,
@PathVariable final String arg1,
@PathVariable final String arg2,
final HttpServletResponse response
) {
response.addHeader("X-Deprecated-API", "1");
return String.format("forward:/audiencequestion/%s/%s/?sessionkey=%s", arg1, arg2, sessionKey);
}
}
/*
* Copyright (C) 2012 THM webMedia
*
* This file is part of ARSnova.
*
* ARSnova is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* ARSnova is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.thm.arsnova.controller;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.scribe.up.provider.impl.FacebookProvider;
import org.scribe.up.provider.impl.Google2Provider;
import org.scribe.up.provider.impl.TwitterProvider;
import org.scribe.up.session.HttpUserSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.cas.authentication.CasAuthenticationToken;
import org.springframework.security.cas.web.CasAuthenticationEntryPoint;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.token.Sha512DigestUtils;
import org.springframework.security.web.context.HttpSessionSecurityContextRepository;
import org.springframework.security.web.util.UrlUtils;
import org.springframework.stereotype.Controller;
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.ResponseBody;
import org.springframework.web.servlet.View;
import org.springframework.web.servlet.view.RedirectView;
import de.thm.arsnova.entities.User;
import de.thm.arsnova.services.IUserService;
@Controller
public class LoginController extends AbstractController {
private static final int MAX_USERNAME_LENGTH = 15;
@Autowired
private TwitterProvider twitterProvider;
@Autowired
private Google2Provider googleProvider;
@Autowired
private FacebookProvider facebookProvider;
@Autowired
private CasAuthenticationEntryPoint casEntryPoint;
@Autowired
private IUserService userService;
public static final Logger LOGGER = LoggerFactory.getLogger(LoginController.class);
@RequestMapping(value = { "/auth/login", "/doLogin" }, method = RequestMethod.GET)
public final View doLogin(
@RequestParam("type") final String type,
@RequestParam(value = "user", required = false) final String guestName,
@RequestParam(value = "referer", required = false) final String forcedReferer,
@RequestParam(value = "successurl", required = false) final String successUrl,
@RequestParam(value = "failureurl", required = false) final String failureUrl,
final HttpServletRequest request,
final HttpServletResponse response
) throws IOException, ServletException {
String referer = request.getHeader("referer");
if (null != forcedReferer && !UrlUtils.isAbsoluteUrl(referer)) {
/* Use a url from a request parameter as referer as long as the url is not absolute (to prevent
* abuse of the redirection). */
referer = forcedReferer;
}
if (null == referer) {
referer = "/";
}
request.getSession().setAttribute("ars-login-success-url",
null == successUrl ? referer + "#auth/checkLogin" : successUrl
);
request.getSession().setAttribute("ars-login-failure-url",
null == failureUrl ? referer : failureUrl
);
if ("cas".equals(type)) {
casEntryPoint.commence(request, response, null);
} else if ("twitter".equals(type)) {
String authUrl = twitterProvider.getAuthorizationUrl(new HttpUserSession(request));
return new RedirectView(authUrl);
} else if ("facebook".equals(type)) {
String authUrl = facebookProvider.getAuthorizationUrl(new HttpUserSession(request));
return new RedirectView(authUrl);
} else if ("google".equals(type)) {
String authUrl = googleProvider.getAuthorizationUrl(new HttpUserSession(request));
return new RedirectView(authUrl);
} else if ("guest".equals(type)) {
List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
authorities.add(new SimpleGrantedAuthority("ROLE_GUEST"));
String username = "";
if (guestName != null && guestName.startsWith("Guest") && guestName.length() == MAX_USERNAME_LENGTH) {
username = guestName;
} else {
username = "Guest" + Sha512DigestUtils.shaHex(request.getSession().getId()).substring(0, 10);
}
org.springframework.security.core.userdetails.User user =
new org.springframework.security.core.userdetails.User(
username, "", true, true, true, true, authorities
);
Authentication token = new UsernamePasswordAuthenticationToken(user, null, authorities);
SecurityContextHolder.getContext().setAuthentication(token);
request.getSession(true).setAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY,
SecurityContextHolder.getContext());
return new RedirectView(null == successUrl ? referer + "#auth/checkLogin" : successUrl);
}
return null;
}
@RequestMapping(value = { "/auth/", "/whoami" }, method = RequestMethod.GET)
@ResponseBody
public final User whoami() {
return userService.getCurrentUser();
}
@RequestMapping(value = { "/auth/logout", "/logout" }, method = RequestMethod.GET)
public final View doLogout(final HttpServletRequest request) {
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
request.getSession().invalidate();
SecurityContextHolder.clearContext();
if (auth instanceof CasAuthenticationToken) {
return new RedirectView("/j_spring_cas_security_logout");
}
return new RedirectView(request.getHeader("referer") != null ? request.getHeader("referer") : "/");
}
}
/*
* This file is part of ARSnova Backend.
* Copyright (C) 2012-2019 The ARSnova Team and Contributors
*
* ARSnova Backend is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* ARSnova Backend is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.thm.arsnova.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import de.thm.arsnova.model.Motd;
import de.thm.arsnova.service.MotdService;
@RestController
@RequestMapping(MotdController.REQUEST_MAPPING)
public class MotdController extends AbstractEntityController<Motd> {
protected static final String REQUEST_MAPPING = "/motd";
private MotdService motdService;
public MotdController(final MotdService motdService) {
super(motdService);
this.motdService = motdService;
}
@Override
protected String getMapping() {
return REQUEST_MAPPING;
}
}
/*
* This file is part of ARSnova Backend.
* Copyright (C) 2012-2019 The ARSnova Team and Contributors
*
* ARSnova Backend is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* ARSnova Backend is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.thm.arsnova.controller;
/**
* Adds pagination properties to controllers.
*/
public abstract class PaginationController extends AbstractController {
protected int offset = -1;
protected int limit = -1;
public void setRange(final int start, final int end) {
this.offset = start;
this.limit = end != -1 && start <= end ? end - start + 1 : -1;
}
}
/*
* This file is part of ARSnova Backend.
* Copyright (C) 2012-2019 The ARSnova Team and Contributors
*
* ARSnova Backend is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* ARSnova Backend is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.thm.arsnova.controller;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import de.thm.arsnova.model.ContentGroup;
import de.thm.arsnova.model.Room;
import de.thm.arsnova.model.RoomStatistics;
import de.thm.arsnova.service.ContentGroupService;
import de.thm.arsnova.service.RoomService;
@RestController
@RequestMapping(RoomController.REQUEST_MAPPING)
public class RoomController extends AbstractEntityController<Room> {
protected static final String REQUEST_MAPPING = "/room";
private static final String GET_MODERATORS_MAPPING = DEFAULT_ID_MAPPING + "/moderator";
private static final String MODERATOR_MAPPING = DEFAULT_ID_MAPPING + "/moderator/{userId}";
private static final String CONTENTGROUP_MAPPING = DEFAULT_ID_MAPPING + "/contentgroup/{groupName}";
private static final String CONTENTGROUP_ADD_MAPPING = CONTENTGROUP_MAPPING + "/{contentId}";
private static final String STATS_MAPPING = DEFAULT_ID_MAPPING + "/stats";
private RoomService roomService;
private ContentGroupService contentGroupService;
public RoomController(final RoomService roomService, final ContentGroupService contentGroupService) {
super(roomService);
this.roomService = roomService;
this.contentGroupService = contentGroupService;
}
@Override
protected String getMapping() {
return REQUEST_MAPPING;
}
@Override
protected String resolveAlias(final String shortId) {
return roomService.getIdByShortId(shortId);
}
@GetMapping(GET_MODERATORS_MAPPING)
public Set<Room.Moderator> getModerators(@PathVariable final String id) {
return roomService.get(id).getModerators();
}
@PutMapping(MODERATOR_MAPPING)
public void putModerator(@PathVariable final String id, @PathVariable final String userId,
@RequestBody final Room.Moderator moderator, final HttpServletResponse httpServletResponse) {
final Room room = roomService.get(id);
moderator.setUserId(userId);
if (moderator.getRoles().isEmpty()) {
moderator.getRoles().add(Room.Moderator.Role.EXECUTIVE_MODERATOR);
}
room.getModerators().removeIf(m -> m.getUserId().equals(userId));
room.getModerators().add(moderator);
roomService.update(room);
httpServletResponse.setHeader(ENTITY_ID_HEADER, room.getId());
httpServletResponse.setHeader(ENTITY_REVISION_HEADER, room.getRevision());
}
@DeleteMapping(MODERATOR_MAPPING)
public void deleteModerator(@PathVariable final String id, @PathVariable final String userId,
final HttpServletResponse httpServletResponse) {
final Room room = roomService.get(id);
room.getModerators().removeIf(m -> m.getUserId().equals(userId));
roomService.update(room);
httpServletResponse.setHeader(ENTITY_ID_HEADER, room.getId());
httpServletResponse.setHeader(ENTITY_REVISION_HEADER, room.getRevision());
}
@GetMapping(CONTENTGROUP_MAPPING)
public ContentGroup getContentGroup(@PathVariable final String id, @PathVariable final String groupName) {
return contentGroupService.getByRoomIdAndName(id, groupName);
}
@PostMapping(CONTENTGROUP_ADD_MAPPING)
public void addContentToGroup(@PathVariable final String id, @PathVariable final String groupName,
@RequestBody final String contentId) {
contentGroupService.addContentToGroup(id, groupName, contentId);
}
@PutMapping(CONTENTGROUP_MAPPING)
public void updateGroup(@PathVariable final String id, @PathVariable final String groupName,
@RequestBody final ContentGroup contentGroup) {
contentGroupService.updateContentGroup(contentGroup);
}
@GetMapping(STATS_MAPPING)
public RoomStatistics getStats(@PathVariable final String id) {
final RoomStatistics roomStatistics = new RoomStatistics();
final List<ContentGroup> contentGroups = contentGroupService.getByRoomId(id);
roomStatistics.setGroupStats(contentGroups.stream()
.map(cg -> new RoomStatistics.ContentGroupStatistics(cg)).collect(Collectors.toList()));
roomStatistics.setContentCount(contentGroups.stream()
.mapToInt(cg -> cg.getContentIds().size()).reduce((a, b) -> a + b).orElse(0));
return roomStatistics;
}
}
/*
* Copyright (C) 2012 THM webMedia
*
* This file is part of ARSnova.
*
* ARSnova is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* ARSnova is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.thm.arsnova.controller;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
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.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import de.thm.arsnova.connector.model.Course;
import de.thm.arsnova.entities.LoggedIn;
import de.thm.arsnova.entities.Question;
import de.thm.arsnova.entities.Session;
import de.thm.arsnova.entities.User;
import de.thm.arsnova.services.ISessionService;
import de.thm.arsnova.services.IUserService;
import de.thm.arsnova.services.SessionService.SessionNameComperator;
import de.thm.arsnova.services.SessionService.SessionShortNameComperator;
@Controller
@RequestMapping("/session")
public class SessionController extends AbstractController {
public static final Logger LOGGER = LoggerFactory.getLogger(SessionController.class);
@Autowired
private ISessionService sessionService;
@Autowired
private IUserService userService;
@RequestMapping(value = "/{sessionkey}", method = RequestMethod.GET)
@ResponseBody
public final Session joinSession(@PathVariable final String sessionkey) {
return sessionService.joinSession(sessionkey);
}
@RequestMapping(value = "/{sessionkey}/online", method = RequestMethod.POST)
@ResponseBody
@ResponseStatus(HttpStatus.CREATED)
public final LoggedIn registerAsOnlineUser(
@PathVariable final String sessionkey,
final HttpServletResponse response
) {
response.addHeader("X-Deprecated-API", "1");
User user = userService.getCurrentUser();
LoggedIn loggedIn = sessionService.registerAsOnlineUser(user, sessionkey);
if (loggedIn != null) {
return loggedIn;
}
throw new RuntimeException();
}
@RequestMapping(value = "/{sessionkey}/activeusercount", method = RequestMethod.GET)
@ResponseBody
public final int countActiveUsers(
@PathVariable final String sessionkey,
final HttpServletResponse response
) {
response.addHeader("X-Deprecated-API", "1");
return sessionService.countActiveUsers(sessionkey);
}
@RequestMapping(value = "/", method = RequestMethod.POST)
@ResponseBody
@ResponseStatus(HttpStatus.CREATED)
public final Session postNewSession(@RequestBody final Session session, final HttpServletResponse response) {
if (session != null && session.isCourseSession()) {
List<Course> courses = new ArrayList<Course>();
Course course = new Course();
course.setId(session.getCourseId());
courses.add(course);
int sessionCount = sessionService.countSessions(courses);
if (sessionCount > 0) {
String appendix = " (" + String.valueOf(sessionCount + 1) + ")";
session.setName(session.getName() + appendix);
session.setShortName(session.getShortName() + appendix);
}
}
Session newSession = sessionService.saveSession(session);
if (newSession == null) {
response.setStatus(HttpStatus.SERVICE_UNAVAILABLE.value());
return null;
}
return newSession;
}
@RequestMapping(value = "/", method = RequestMethod.GET)
@ResponseBody
public final List<Session> getSessions(
@RequestParam(value = "ownedonly", defaultValue = "false") final boolean ownedOnly,
@RequestParam(value = "visitedonly", defaultValue = "false") final boolean visitedOnly,
@RequestParam(value = "sortby", defaultValue = "name") final String sortby,
final HttpServletResponse response
) {
User user = userService.getCurrentUser();
List<Session> sessions = null;
/* TODO Could @Authorized annotation be used instead of this check? */
if (null == user) {
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
return null;
}
/* TODO implement all parameter combinations, implement use of user parameter */
if (ownedOnly && !visitedOnly) {
sessions = sessionService.getMySessions(user);
} else if (visitedOnly && !ownedOnly) {
sessions = sessionService.getMyVisitedSessions(userService.getCurrentUser());
} else {
response.setStatus(HttpStatus.NOT_IMPLEMENTED.value());
return null;
}
if (sessions == null || sessions.isEmpty()) {
response.setStatus(HttpServletResponse.SC_NO_CONTENT);
return null;
}
if (sortby != null && sortby.equals("shortname")) {
Collections.sort(sessions, new SessionShortNameComperator());
} else {
Collections.sort(sessions, new SessionNameComperator());
}
return sessions;
}
@RequestMapping(value = "/{sessionkey}/lock", method = RequestMethod.POST)
@ResponseBody
public final Session lockSession(
@PathVariable final String sessionkey,
@RequestParam(required = false) final Boolean lock,
final HttpServletResponse response
) {
if (lock != null) {
return this.sessionService.setActive(sessionkey, lock);
}
response.setStatus(HttpStatus.NOT_FOUND.value());
return null;
}
/* internal redirections */
@RequestMapping(value = "/{sessionKey}/lecturerquestion")
public final String redirectLecturerQuestion(
@PathVariable final String sessionKey,
final HttpServletResponse response
) {
response.addHeader("X-Forwarded", "1");
return String.format("forward:/lecturerquestion/?sessionkey=%s", sessionKey);
}
@RequestMapping(value = "/{sessionKey}/lecturerquestion/{arg1}")
public final String redirectLecturerQuestionWithOneArgument(
@PathVariable final String sessionKey,
@PathVariable final String arg1,
final HttpServletResponse response
) {
response.addHeader("X-Forwarded", "1");
return String.format("forward:/lecturerquestion/%s/?sessionkey=%s", arg1, sessionKey);
}
@RequestMapping(value = "/{sessionKey}/lecturerquestion/{arg1}/{arg2}")
public final String redirectLecturerQuestionWithTwoArguments(
@PathVariable final String sessionKey,
@PathVariable final String arg1,
@PathVariable final String arg2,
final HttpServletResponse response
) {
response.addHeader("X-Forwarded", "1");
return String.format("forward:/lecturerquestion/%s/%s/?sessionkey=%s", arg1, arg2, sessionKey);
}
@RequestMapping(value = "/{sessionKey}/lecturerquestion/{arg1}/{arg2}/{arg3}")
public final String redirectLecturerQuestionWithThreeArguments(
@PathVariable final String sessionKey,
@PathVariable final String arg1,
@PathVariable final String arg2,
@PathVariable final String arg3,
final HttpServletResponse response
) {
response.addHeader("X-Forwarded", "1");
return String.format("forward:/lecturerquestion/%s/%s/%s/?sessionkey=%s", arg1, arg2, arg3, sessionKey);
}
@RequestMapping(value = "/{sessionKey}/audiencequestion")
public final String redirectAudienceQuestion(
@PathVariable final String sessionKey,
final HttpServletResponse response
) {
response.addHeader("X-Forwarded", "1");
return String.format("forward:/audiencequestion/?sessionkey=%s", sessionKey);
}
@RequestMapping(value = "/{sessionKey}/audiencequestion/{arg1}")
public final String redirectAudienceQuestionWithOneArgument(
@PathVariable final String sessionKey,
@PathVariable final String arg1,
final HttpServletResponse response
) {
response.addHeader("X-Forwarded", "1");
return String.format("forward:/audiencequestion/%s/?sessionkey=%s", arg1, sessionKey);
}
@RequestMapping(value = "/{sessionKey}/audiencequestion/{arg1}/{arg2}")
public final String redirectAudienceQuestionWithTwoArguments(
@PathVariable final String sessionKey,
@PathVariable final String arg1,
@PathVariable final String arg2,
final HttpServletResponse response
) {
response.addHeader("X-Forwarded", "1");
return String.format("forward:/audiencequestion/%s/%s/?sessionkey=%s", arg1, arg2, sessionKey);
}
@RequestMapping(value = "/{sessionKey}/audiencequestion/{arg1}/{arg2}/{arg3}")
public final String redirectAudienceQuestionWithThreeArguments(
@PathVariable final String sessionKey,
@PathVariable final String arg1,
@PathVariable final String arg2,
@PathVariable final String arg3,
final HttpServletResponse response
) {
response.addHeader("X-Forwarded", "1");
return String.format("forward:/audiencequestion/%s/%s/%s/?sessionkey=%s", arg1, arg2, arg3, sessionKey);
}
}
/*
* Copyright (C) 2012 THM webMedia
*
* This file is part of ARSnova.
*
* ARSnova is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* ARSnova is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.thm.arsnova.controller;
import java.util.UUID;
import javax.servlet.http.HttpServletResponse;
import net.sf.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import de.thm.arsnova.entities.User;
import de.thm.arsnova.services.IUserService;
import de.thm.arsnova.socket.ARSnovaSocketIOServer;
@Controller
@RequestMapping("/socket")
public class SocketController extends AbstractController {
public static final Logger LOGGER = LoggerFactory.getLogger(SessionController.class);
@Autowired
private IUserService userService;
@Autowired
private ARSnovaSocketIOServer server;
@RequestMapping(method = RequestMethod.POST, value = "/assign")
public final void authorize(@RequestBody final Object sessionObject, final HttpServletResponse response) {
String socketid = (String) JSONObject.fromObject(sessionObject).get("session");
if (socketid == null) {
return;
}
User u = userService.getCurrentUser();
LOGGER.info("authorize session: " + socketid + ", user is: " + u);
response.setStatus(u != null ? HttpStatus.NO_CONTENT.value() : HttpStatus.UNAUTHORIZED.value());
if (u != null) {
userService.putUser2SocketId(UUID.fromString(socketid), u);
}
}
@RequestMapping(value = "/url", method = RequestMethod.GET)
@ResponseBody
public final String getSocketUrl() {
StringBuilder url = new StringBuilder();
url.append(server.isUseSSL() ? "https://" : "http://");
url.append(server.getHostIp() + ":" + server.getPortNumber());
return url.toString();
}
}
package de.thm.arsnova.controller;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import de.thm.arsnova.entities.Statistics;
import de.thm.arsnova.services.IStatisticsService;
@Controller
public class StatisticsController {
@Autowired
private IStatisticsService statisticsService;
@RequestMapping(method = RequestMethod.GET, value = "/statistics")
@ResponseBody
public final Statistics getStatistics() {
return statisticsService.getStatistics();
}
@RequestMapping(method = RequestMethod.GET, value = "/statistics/activeusercount", produces = "text/plain")
@ResponseBody
public final String countActiveUsers(HttpServletResponse response) {
response.addHeader("X-Deprecated-API", "1");
return Integer.toString(statisticsService.countActiveUsers());
}
@RequestMapping(method = RequestMethod.GET, value = "/statistics/sessioncount", produces = "text/plain")
@ResponseBody
public final String countSessions(HttpServletResponse response) {
response.addHeader("X-Deprecated-API", "1");
return Integer.toString(statisticsService.getStatistics().getOpenSessions()
+ statisticsService.getStatistics().getClosedSessions());
}
}
/*
* This file is part of ARSnova Backend.
* Copyright (C) 2012-2019 The ARSnova Team and Contributors
*
* ARSnova Backend is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* ARSnova Backend is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.thm.arsnova.controller;
import com.fasterxml.jackson.annotation.JsonView;
import javax.servlet.http.HttpServletRequest;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import de.thm.arsnova.model.LoginCredentials;
import de.thm.arsnova.model.UserProfile;
import de.thm.arsnova.model.serialization.View;
import de.thm.arsnova.service.RoomService;
import de.thm.arsnova.service.UserService;
import de.thm.arsnova.web.exceptions.BadRequestException;
import de.thm.arsnova.web.exceptions.ForbiddenException;
@RestController
@RequestMapping(UserController.REQUEST_MAPPING)
public class UserController extends AbstractEntityController<UserProfile> {
protected static final String REQUEST_MAPPING = "/user";
private static final String REGISTER_MAPPING = "/register";
private static final String ACTIVATE_MAPPING = DEFAULT_ID_MAPPING + "/activate";
private static final String RESET_PASSWORD_MAPPING = DEFAULT_ID_MAPPING + "/resetpassword";
private static final String ROOM_HISTORY_MAPPING = DEFAULT_ID_MAPPING + "/roomHistory";
private UserService userService;
private RoomService roomService;
public UserController(final UserService userService, final RoomService roomService) {
super(userService);
this.userService = userService;
this.roomService = roomService;
}
class Activation {
private String key;
public String getKey() {
return key;
}
@JsonView(View.Public.class)
public void setKey(final String key) {
this.key = key;
}
}
class PasswordReset {
private String key;
private String password;
public String getKey() {
return key;
}
@JsonView(View.Public.class)
public void setKey(final String key) {
this.key = key;
}
public String getPassword() {
return password;
}
@JsonView(View.Public.class)
public void setPassword(final String password) {
this.password = password;
}
}
@Override
protected String getMapping() {
return REQUEST_MAPPING;
}
@PostMapping(REGISTER_MAPPING)
public void register(@RequestBody final LoginCredentials loginCredentials) {
if (userService.create(loginCredentials.getLoginId(), loginCredentials.getPassword()) == null) {
throw new ForbiddenException();
}
}
@PostMapping(ACTIVATE_MAPPING)
public void activate(
@PathVariable final String id,
@RequestParam final String key,
final HttpServletRequest request) {
if (!userService.activateAccount(id, key, request.getRemoteAddr())) {
throw new BadRequestException();
}
}
@PostMapping(RESET_PASSWORD_MAPPING)
public void resetPassword(
@PathVariable final String id,
@RequestBody final PasswordReset passwordReset) {
final UserProfile userProfile = userService.get(id, true);
if (userProfile == null) {
throw new BadRequestException();
}
if (passwordReset.getKey() != null) {
if (!userService.resetPassword(userProfile, passwordReset.getKey(), passwordReset.getPassword())) {
throw new ForbiddenException();
}
} else {
userService.initiatePasswordReset(id);
}
}
@PostMapping(ROOM_HISTORY_MAPPING)
public void postRoomHistoryEntry(@PathVariable final String id,
@RequestBody final UserProfile.RoomHistoryEntry roomHistoryEntry) {
userService.addRoomToHistory(userService.get(id), roomService.get(roomHistoryEntry.getRoomId()));
}
@Override
protected String resolveAlias(final String alias) {
return userService.getByUsername(alias).getId();
}
}