getErrorResponse(BindingResult result) {
+ return ResponseEntity.unprocessableEntity().body(
+ result.getFieldErrors().stream()
+ .map(fe -> String.format("[%s] %s", fe.getField(), fe.getDefaultMessage()))
+ .collect(Collectors.joining("
"))
+ );
+ }
}
\ No newline at end of file
diff --git a/src/main/java/ru/javawebinar/topjava/util/exception/ErrorInfo.java b/src/main/java/ru/javawebinar/topjava/util/exception/ErrorInfo.java
new file mode 100644
index 000000000000..d43323590d95
--- /dev/null
+++ b/src/main/java/ru/javawebinar/topjava/util/exception/ErrorInfo.java
@@ -0,0 +1,13 @@
+package ru.javawebinar.topjava.util.exception;
+
+public class ErrorInfo {
+ private final String url;
+ private final ErrorType type;
+ private final String detail;
+
+ public ErrorInfo(CharSequence url, ErrorType type, String detail) {
+ this.url = url.toString();
+ this.type = type;
+ this.detail = detail;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/ru/javawebinar/topjava/util/exception/ErrorType.java b/src/main/java/ru/javawebinar/topjava/util/exception/ErrorType.java
new file mode 100644
index 000000000000..c53a433bc668
--- /dev/null
+++ b/src/main/java/ru/javawebinar/topjava/util/exception/ErrorType.java
@@ -0,0 +1,8 @@
+package ru.javawebinar.topjava.util.exception;
+
+public enum ErrorType {
+ APP_ERROR,
+ DATA_NOT_FOUND,
+ DATA_ERROR,
+ VALIDATION_ERROR
+}
diff --git a/src/main/java/ru/javawebinar/topjava/util/exception/IllegalRequestDataException.java b/src/main/java/ru/javawebinar/topjava/util/exception/IllegalRequestDataException.java
new file mode 100644
index 000000000000..2b144f91c91c
--- /dev/null
+++ b/src/main/java/ru/javawebinar/topjava/util/exception/IllegalRequestDataException.java
@@ -0,0 +1,7 @@
+package ru.javawebinar.topjava.util.exception;
+
+public class IllegalRequestDataException extends RuntimeException {
+ public IllegalRequestDataException(String msg) {
+ super(msg);
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/ru/javawebinar/topjava/web/ExceptionInfoHandler.java b/src/main/java/ru/javawebinar/topjava/web/ExceptionInfoHandler.java
new file mode 100644
index 000000000000..5b7e9575810c
--- /dev/null
+++ b/src/main/java/ru/javawebinar/topjava/web/ExceptionInfoHandler.java
@@ -0,0 +1,65 @@
+package ru.javawebinar.topjava.web;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.core.Ordered;
+import org.springframework.core.annotation.Order;
+import org.springframework.dao.DataIntegrityViolationException;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.converter.HttpMessageNotReadableException;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.ResponseStatus;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.bind.annotation.RestControllerAdvice;
+import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
+import ru.javawebinar.topjava.util.ValidationUtil;
+import ru.javawebinar.topjava.util.exception.ErrorInfo;
+import ru.javawebinar.topjava.util.exception.ErrorType;
+import ru.javawebinar.topjava.util.exception.IllegalRequestDataException;
+import ru.javawebinar.topjava.util.exception.NotFoundException;
+
+import javax.servlet.http.HttpServletRequest;
+
+import static ru.javawebinar.topjava.util.exception.ErrorType.*;
+
+@RestControllerAdvice(annotations = RestController.class)
+@Order(Ordered.HIGHEST_PRECEDENCE + 5)
+public class ExceptionInfoHandler {
+ private static final Logger log = LoggerFactory.getLogger(ExceptionInfoHandler.class);
+
+ // http://stackoverflow.com/a/22358422/548473
+ @ResponseStatus(HttpStatus.UNPROCESSABLE_ENTITY)
+ @ExceptionHandler(NotFoundException.class)
+ public ErrorInfo notFoundError(HttpServletRequest req, NotFoundException e) {
+ return logAndGetErrorInfo(req, e, false, DATA_NOT_FOUND);
+ }
+
+ @ResponseStatus(HttpStatus.CONFLICT) // 409
+ @ExceptionHandler(DataIntegrityViolationException.class)
+ public ErrorInfo conflict(HttpServletRequest req, DataIntegrityViolationException e) {
+ return logAndGetErrorInfo(req, e, true, DATA_ERROR);
+ }
+
+ @ResponseStatus(HttpStatus.UNPROCESSABLE_ENTITY) // 422
+ @ExceptionHandler({IllegalRequestDataException.class, MethodArgumentTypeMismatchException.class, HttpMessageNotReadableException.class})
+ public ErrorInfo validationError(HttpServletRequest req, Exception e) {
+ return logAndGetErrorInfo(req, e, false, VALIDATION_ERROR);
+ }
+
+ @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
+ @ExceptionHandler(Exception.class)
+ public ErrorInfo internalError(HttpServletRequest req, Exception e) {
+ return logAndGetErrorInfo(req, e, true, APP_ERROR);
+ }
+
+ // https://stackoverflow.com/questions/538870/should-private-helper-methods-be-static-if-they-can-be-static
+ private static ErrorInfo logAndGetErrorInfo(HttpServletRequest req, Exception e, boolean logException, ErrorType errorType) {
+ Throwable rootCause = ValidationUtil.getRootCause(e);
+ if (logException) {
+ log.error(errorType + " at request " + req.getRequestURL(), rootCause);
+ } else {
+ log.warn("{} at request {}: {}", errorType, req.getRequestURL(), rootCause.toString());
+ }
+ return new ErrorInfo(req.getRequestURL(), errorType, rootCause.toString());
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/ru/javawebinar/topjava/web/GlobalExceptionHandler.java b/src/main/java/ru/javawebinar/topjava/web/GlobalExceptionHandler.java
new file mode 100644
index 000000000000..bd401d1c150e
--- /dev/null
+++ b/src/main/java/ru/javawebinar/topjava/web/GlobalExceptionHandler.java
@@ -0,0 +1,36 @@
+package ru.javawebinar.topjava.web;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.http.HttpStatus;
+import org.springframework.web.bind.annotation.ControllerAdvice;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.servlet.ModelAndView;
+import ru.javawebinar.topjava.AuthorizedUser;
+import ru.javawebinar.topjava.util.ValidationUtil;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.Map;
+
+@ControllerAdvice
+public class GlobalExceptionHandler {
+ private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class);
+
+ @ExceptionHandler(Exception.class)
+ public ModelAndView defaultErrorHandler(HttpServletRequest req, Exception e) throws Exception {
+ log.error("Exception at request " + req.getRequestURL(), e);
+ Throwable rootCause = ValidationUtil.getRootCause(e);
+
+ HttpStatus httpStatus = HttpStatus.INTERNAL_SERVER_ERROR;
+ ModelAndView mav = new ModelAndView("exception",
+ Map.of("exception", rootCause, "message", rootCause.toString(), "status", httpStatus));
+ mav.setStatus(httpStatus);
+
+ // Interceptor is not invoked, put userTo
+ AuthorizedUser authorizedUser = SecurityUtil.safeGet();
+ if (authorizedUser != null) {
+ mav.addObject("userTo", authorizedUser.getUserTo());
+ }
+ return mav;
+ }
+}
diff --git a/src/main/java/ru/javawebinar/topjava/web/RootController.java b/src/main/java/ru/javawebinar/topjava/web/RootController.java
index 3ca4591e02ca..d42b390d59fb 100644
--- a/src/main/java/ru/javawebinar/topjava/web/RootController.java
+++ b/src/main/java/ru/javawebinar/topjava/web/RootController.java
@@ -2,26 +2,22 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Controller;
-import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
-import ru.javawebinar.topjava.service.MealService;
-import ru.javawebinar.topjava.util.MealsUtil;
@Controller
public class RootController {
private static final Logger log = LoggerFactory.getLogger(RootController.class);
- @Autowired
- private MealService mealService;
-
@GetMapping("/")
public String root() {
log.info("root");
return "redirect:meals";
}
+ // @Secured("ROLE_ADMIN")
+ @PreAuthorize("hasRole('ADMIN')")
@GetMapping("/users")
public String getUsers() {
log.info("users");
@@ -35,10 +31,8 @@ public String login() {
}
@GetMapping("/meals")
- public String getMeals(Model model) {
+ public String getMeals() {
log.info("meals");
- model.addAttribute("meals",
- MealsUtil.getTos(mealService.getAll(SecurityUtil.authUserId()), SecurityUtil.authUserCaloriesPerDay()));
return "meals";
}
}
diff --git a/src/main/java/ru/javawebinar/topjava/web/interceptor/ModelInterceptor.java b/src/main/java/ru/javawebinar/topjava/web/interceptor/ModelInterceptor.java
new file mode 100644
index 000000000000..4ee6eaef1386
--- /dev/null
+++ b/src/main/java/ru/javawebinar/topjava/web/interceptor/ModelInterceptor.java
@@ -0,0 +1,25 @@
+package ru.javawebinar.topjava.web.interceptor;
+
+import org.springframework.web.servlet.HandlerInterceptor;
+import org.springframework.web.servlet.ModelAndView;
+import ru.javawebinar.topjava.AuthorizedUser;
+import ru.javawebinar.topjava.web.SecurityUtil;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * This interceptor adds userTo to the model of every requests
+ */
+public class ModelInterceptor implements HandlerInterceptor {
+
+ @Override
+ public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
+ if (modelAndView != null && !modelAndView.isEmpty()) {
+ AuthorizedUser authorizedUser = SecurityUtil.safeGet();
+ if (authorizedUser != null) {
+ modelAndView.getModelMap().addAttribute("userTo", authorizedUser.getUserTo());
+ }
+ }
+ }
+}
diff --git a/src/main/java/ru/javawebinar/topjava/web/json/JacksonObjectMapper.java b/src/main/java/ru/javawebinar/topjava/web/json/JacksonObjectMapper.java
index 8237df93bffe..58704d86db13 100644
--- a/src/main/java/ru/javawebinar/topjava/web/json/JacksonObjectMapper.java
+++ b/src/main/java/ru/javawebinar/topjava/web/json/JacksonObjectMapper.java
@@ -7,6 +7,7 @@
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.hibernate5.Hibernate5Module;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
+import ru.javawebinar.topjava.View;
/**
*
@@ -29,6 +30,9 @@ private JacksonObjectMapper() {
setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.NONE);
setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);
setSerializationInclusion(JsonInclude.Include.NON_NULL);
+
+// https://stackoverflow.com/questions/22875642/jackson-set-default-view
+ setConfig(getSerializationConfig().withView(View.JsonREST.class));
}
public static ObjectMapper getMapper() {
diff --git a/src/main/java/ru/javawebinar/topjava/web/json/JsonUtil.java b/src/main/java/ru/javawebinar/topjava/web/json/JsonUtil.java
index fda04590d618..4d753a8a4f8d 100644
--- a/src/main/java/ru/javawebinar/topjava/web/json/JsonUtil.java
+++ b/src/main/java/ru/javawebinar/topjava/web/json/JsonUtil.java
@@ -1,10 +1,13 @@
package ru.javawebinar.topjava.web.json;
import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectReader;
+import com.fasterxml.jackson.databind.ObjectWriter;
import java.io.IOException;
import java.util.List;
+import java.util.Map;
import static ru.javawebinar.topjava.web.json.JacksonObjectMapper.getMapper;
@@ -34,4 +37,22 @@ public static String writeValue(T obj) {
throw new IllegalStateException("Invalid write to JSON:\n'" + obj + "'", e);
}
}
+
+ public static String writeValue(T obj, ObjectWriter ow) {
+ try {
+ return ow.writeValueAsString(obj);
+ } catch (JsonProcessingException e) {
+ throw new IllegalStateException("Invalid write to JSON:\n'" + obj + "'", e);
+ }
+ }
+
+ public static String writeAdditionProps(T obj, String addName, Object addValue) {
+ return writeAdditionProps(obj, Map.of(addName, addValue));
+ }
+
+ public static String writeAdditionProps(T obj, Map addProps) {
+ Map map = getMapper().convertValue(obj, new TypeReference<>() {});
+ map.putAll(addProps);
+ return writeValue(map);
+ }
}
\ No newline at end of file
diff --git a/src/main/java/ru/javawebinar/topjava/web/meal/MealUIController.java b/src/main/java/ru/javawebinar/topjava/web/meal/MealUIController.java
index dafc7a70f284..26ccf85374b0 100644
--- a/src/main/java/ru/javawebinar/topjava/web/meal/MealUIController.java
+++ b/src/main/java/ru/javawebinar/topjava/web/meal/MealUIController.java
@@ -1,15 +1,20 @@
package ru.javawebinar.topjava.web.meal;
-import org.springframework.format.annotation.DateTimeFormat;
+import com.fasterxml.jackson.annotation.JsonView;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
import org.springframework.lang.Nullable;
+import org.springframework.validation.BindingResult;
+import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
+import ru.javawebinar.topjava.View;
+import ru.javawebinar.topjava.View.ValidatedUI;
import ru.javawebinar.topjava.model.Meal;
import ru.javawebinar.topjava.to.MealTo;
+import ru.javawebinar.topjava.util.ValidationUtil;
import java.time.LocalDate;
-import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.List;
@@ -19,10 +24,18 @@ public class MealUIController extends AbstractMealController {
@Override
@GetMapping
+ @JsonView(View.JsonUI.class)
public List getAll() {
return super.getAll();
}
+ @Override
+ @GetMapping( "/{id}")
+ @JsonView(View.JsonUI.class)
+ public Meal get(@PathVariable int id) {
+ return super.get(id);
+ }
+
@Override
@DeleteMapping("/{id}")
@ResponseStatus(HttpStatus.NO_CONTENT)
@@ -32,14 +45,22 @@ public void delete(@PathVariable int id) {
@PostMapping
@ResponseStatus(HttpStatus.NO_CONTENT)
- public void create(@RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime dateTime,
- @RequestParam String description,
- @RequestParam int calories) {
- super.create(new Meal(null, dateTime, description, calories));
+ public ResponseEntity createOrUpdate(@Validated(ValidatedUI.class) Meal meal, BindingResult result) {
+ if (result.hasErrors()) {
+ // TODO change to exception handler
+ return ValidationUtil.getErrorResponse(result);
+ }
+ if (meal.isNew()) {
+ super.create(meal);
+ } else {
+ super.update(meal, meal.getId());
+ }
+ return ResponseEntity.ok().build();
}
@Override
@GetMapping("/filter")
+ @JsonView(View.JsonUI.class)
public List getBetween(
@RequestParam @Nullable LocalDate startDate,
@RequestParam @Nullable LocalTime startTime,
diff --git a/src/main/java/ru/javawebinar/topjava/web/user/AbstractUserController.java b/src/main/java/ru/javawebinar/topjava/web/user/AbstractUserController.java
index 1b8a9432146f..18e3698e8f52 100644
--- a/src/main/java/ru/javawebinar/topjava/web/user/AbstractUserController.java
+++ b/src/main/java/ru/javawebinar/topjava/web/user/AbstractUserController.java
@@ -29,10 +29,10 @@ public User get(int id) {
return service.get(id);
}
- public void create(UserTo userTo) {
+ public User create(UserTo userTo) {
log.info("create {}", userTo);
checkNew(userTo);
- service.create(UsersUtil.createNewFromTo(userTo));
+ return service.create(UsersUtil.createNewFromTo(userTo));
}
public User create(User user) {
diff --git a/src/main/java/ru/javawebinar/topjava/web/user/AdminUIController.java b/src/main/java/ru/javawebinar/topjava/web/user/AdminUIController.java
index 199daa8f1916..0f52185605b8 100644
--- a/src/main/java/ru/javawebinar/topjava/web/user/AdminUIController.java
+++ b/src/main/java/ru/javawebinar/topjava/web/user/AdminUIController.java
@@ -7,10 +7,10 @@
import org.springframework.web.bind.annotation.*;
import ru.javawebinar.topjava.model.User;
import ru.javawebinar.topjava.to.UserTo;
+import ru.javawebinar.topjava.util.ValidationUtil;
import javax.validation.Valid;
import java.util.List;
-import java.util.stream.Collectors;
@RestController
@RequestMapping(value = "/admin/users", produces = MediaType.APPLICATION_JSON_VALUE)
@@ -39,10 +39,8 @@ public void delete(@PathVariable int id) {
@ResponseStatus(HttpStatus.NO_CONTENT)
public ResponseEntity createOrUpdate(@Valid UserTo userTo, BindingResult result) {
if (result.hasErrors()) {
- String errorFieldsMsg = result.getFieldErrors().stream()
- .map(fe -> String.format("[%s] %s", fe.getField(), fe.getDefaultMessage()))
- .collect(Collectors.joining("
"));
- return ResponseEntity.unprocessableEntity().body(errorFieldsMsg);
+ // TODO change to exception handler
+ return ValidationUtil.getErrorResponse(result);
}
if (userTo.isNew()) {
super.create(userTo);
diff --git a/src/main/java/ru/javawebinar/topjava/web/user/ProfileRestController.java b/src/main/java/ru/javawebinar/topjava/web/user/ProfileRestController.java
index ccc43013a471..c99f2ccaa689 100644
--- a/src/main/java/ru/javawebinar/topjava/web/user/ProfileRestController.java
+++ b/src/main/java/ru/javawebinar/topjava/web/user/ProfileRestController.java
@@ -2,10 +2,14 @@
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
+import org.springframework.web.servlet.support.ServletUriComponentsBuilder;
import ru.javawebinar.topjava.model.User;
import ru.javawebinar.topjava.to.UserTo;
+import java.net.URI;
+
import static ru.javawebinar.topjava.web.SecurityUtil.authUserId;
@RestController
@@ -24,6 +28,15 @@ public void delete() {
super.delete(authUserId());
}
+ @PostMapping(consumes = MediaType.APPLICATION_JSON_VALUE)
+ @ResponseStatus(HttpStatus.CREATED)
+ public ResponseEntity register(@RequestBody UserTo userTo) {
+ User created = super.create(userTo);
+ URI uriOfNewResource = ServletUriComponentsBuilder.fromCurrentContextPath()
+ .path(REST_URL).build().toUri();
+ return ResponseEntity.created(uriOfNewResource).body(created);
+ }
+
@PutMapping(consumes = MediaType.APPLICATION_JSON_VALUE)
@ResponseStatus(HttpStatus.NO_CONTENT)
public void update(@RequestBody UserTo userTo) {
diff --git a/src/main/java/ru/javawebinar/topjava/web/user/ProfileUIController.java b/src/main/java/ru/javawebinar/topjava/web/user/ProfileUIController.java
new file mode 100644
index 000000000000..657396a7dc18
--- /dev/null
+++ b/src/main/java/ru/javawebinar/topjava/web/user/ProfileUIController.java
@@ -0,0 +1,54 @@
+package ru.javawebinar.topjava.web.user;
+
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.ModelMap;
+import org.springframework.validation.BindingResult;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.support.SessionStatus;
+import ru.javawebinar.topjava.to.UserTo;
+import ru.javawebinar.topjava.web.SecurityUtil;
+
+import javax.validation.Valid;
+
+@Controller
+@RequestMapping("/profile")
+public class ProfileUIController extends AbstractUserController {
+
+ @GetMapping
+ public String profile() {
+ return "profile";
+ }
+
+ @PostMapping
+ public String updateProfile(@Valid UserTo userTo, BindingResult result, SessionStatus status) {
+ if (result.hasErrors()) {
+ return "profile";
+ } else {
+ super.update(userTo, SecurityUtil.authUserId());
+ SecurityUtil.get().setTo(userTo);
+ status.setComplete();
+ return "redirect:/meals";
+ }
+ }
+
+ @GetMapping("/register")
+ public String register(ModelMap model) {
+ model.addAttribute("userTo", new UserTo());
+ model.addAttribute("register", true);
+ return "profile";
+ }
+
+ @PostMapping("/register")
+ public String saveRegister(@Valid UserTo userTo, BindingResult result, SessionStatus status, ModelMap model) {
+ if (result.hasErrors()) {
+ model.addAttribute("register", true);
+ return "profile";
+ } else {
+ super.create(userTo);
+ status.setComplete();
+ return "redirect:/login?message=app.registered&username=" + userTo.getEmail();
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/db/populateDB.sql b/src/main/resources/db/populateDB.sql
index 9e9bd828babe..8d66cc0e5e12 100644
--- a/src/main/resources/db/populateDB.sql
+++ b/src/main/resources/db/populateDB.sql
@@ -3,10 +3,10 @@ DELETE FROM meal;
DELETE FROM users;
ALTER SEQUENCE global_seq RESTART WITH 100000;
-INSERT INTO users (name, email, password)
-VALUES ('User', 'user@yandex.ru', 'password'),
- ('Admin', 'admin@gmail.com', 'admin'),
- ('Guest', 'guest@gmail.com', 'guest');
+INSERT INTO users (name, email, password, calories_per_day)
+VALUES ('User', 'user@yandex.ru', '{noop}password', 2005),
+ ('Admin', 'admin@gmail.com', '{noop}admin', 1900),
+ ('Guest', 'guest@gmail.com', '{noop}guest', 2000);
INSERT INTO user_role (role, user_id)
VALUES ('USER', 100000),
diff --git a/src/main/resources/logback.xml b/src/main/resources/logback.xml
index e5ed3ccdebf1..e2b565616949 100644
--- a/src/main/resources/logback.xml
+++ b/src/main/resources/logback.xml
@@ -23,7 +23,8 @@
-
+
+
diff --git a/src/main/resources/spring/spring-db.xml b/src/main/resources/spring/spring-db.xml
index 48afdb11a749..9c090f3c544a 100644
--- a/src/main/resources/spring/spring-db.xml
+++ b/src/main/resources/spring/spring-db.xml
@@ -93,6 +93,9 @@
+
+
+
+
+
@@ -65,4 +69,8 @@
+
+
+
+
\ No newline at end of file
diff --git a/src/main/resources/spring/spring-security.xml b/src/main/resources/spring/spring-security.xml
index 97b944b4ed59..efcda19fe5ee 100644
--- a/src/main/resources/spring/spring-security.xml
+++ b/src/main/resources/spring/spring-security.xml
@@ -10,14 +10,16 @@
+
-
+
+
@@ -26,12 +28,11 @@
authentication-failure-url="/login?error=true"
login-processing-url="/spring_security_check"/>
-
-
+
+
+