// Path: src/main/java/com/pugnascotia/reactdemo/utils/State.java
// public final class State {
// 
// 	/** Populates standard parts of the shared client/server model into the Spring {@link Model}.
// 	 * Values prefixed with "__" will be made available to the JavaScript
// 	 * render function only. All other values will be passed in the client's state object.
// 	 */
// 	public static void populateModel(Model model, HttpServletRequest request) {
// 		model.addAttribute("__requestPath", getRequestPath(request));
// 		model.addAttribute("auth", getAuthState(request));
// 	}
// 
// 	/**
// 	 * Returns the request string, including the query fragment, so that it can be made available
// 	 * during server-side react-router rendering.
// 	 */
// 	private static String getRequestPath(HttpServletRequest request) {
// 		String queryString = request.getQueryString();
// 		return request.getRequestURI() + (queryString == null ? "" : "?" + queryString);
// 	}
// 
// 	/**
// 	 * Returns a representation of the user's authentication state, in the shape expected by the client.
// 	 */
// 	public static Map<String, Object> getAuthState(HttpServletRequest request) {
// 		Optional<List<String>> optionalRoles = getRoles(request);
// 
// 		return optionalRoles.map(roles -> {
// 			Map<String, Object> authState = new HashMap<>();
// 			authState.put("signedIn", !roles.contains("ROLE_ANONYMOUS"));
// 			authState.put("roles", roles);
// 
// 			return authState;
// 		})
// 		.orElseGet(() -> {
// 			Map<String, Object> authState = new HashMap<>();
// 			authState.put("signedIn", false);
// 			authState.put("roles", Collections.singletonList("ROLE_ANONYMOUS"));
// 
// 			return authState;
// 		});
// 	}
// 
// 	/**
// 	 * Return a list of the current user's roles. If they are not authenticated then they will
// 	 * have "ROLE_ANONYMOUS".
// 	 */
// 	private static Optional<List<String>> getRoles(HttpServletRequest request) {
// 		return getAuthentication(request)
// 			.map(a -> Functions.map(a.getAuthorities(), GrantedAuthority::getAuthority));
// 	}
// 
// 	/**
// 	 * Getting the current authentication object ought to be easy, by getting a context with
// 	 * {@link SecurityContextHolder#getContext()}, then calling {@link SecurityContext#getAuthentication()}.
// 	 * However there are circumstances where that doesn't work reliably, such as when handling
// 	 * exceptions. This method makes several attempts to get an {@link Authentication} instance.
// 	 */
// 	private static Optional<Authentication> getAuthentication(HttpServletRequest request) {
// 		Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
// 
// 		if (authentication == null) {
// 			RequestAttributes requestAttributes = new ServletRequestAttributes(request);
// 			SecurityContext securityContext = (SecurityContext) requestAttributes.getAttribute("SPRING_SECURITY_CONTEXT", RequestAttributes.SCOPE_SESSION);
// 			if (securityContext == null) {
// 				securityContext = (SecurityContext) requestAttributes.getAttribute("SPRING_SECURITY_CONTEXT", RequestAttributes.SCOPE_GLOBAL_SESSION);
// 			}
// 			if (securityContext != null) {
// 				authentication = securityContext.getAuthentication();
// 			}
// 		}
// 
// 		return Optional.ofNullable(authentication);
// 	}
// }


import java.util.Map;
import javax.inject.Inject;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.pugnascotia.reactdemo.utils.State;
import org.springframework.boot.autoconfigure.web.AbstractErrorController;
import org.springframework.boot.autoconfigure.web.ErrorAttributes;
import org.springframework.boot.autoconfigure.web.ErrorProperties;
import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
package com.pugnascotia.reactdemo.errors;



/**
 * Largely pinched from {@link org.springframework.boot.autoconfigure.web.BasicErrorController}
 * and customised to render our React template, along with an appropriate populated state.
 */

@Controller
@RequestMapping("/error")
public class ReactErrorController extends AbstractErrorController {

	private final ServerProperties serverProperties;

	@Inject
	public ReactErrorController(ErrorAttributes errorAttributes, ServerProperties serverProperties) {
		super(errorAttributes);
		this.serverProperties = serverProperties;
	}

	/**
	 * Render the standard template, but include all the error information we know about. In
	 * a production application, you may not want to pass all that information to the client.
	 */
	@RequestMapping(produces = "text/html")
	public String errorHtml(Model model, HttpServletRequest request, HttpServletResponse response) {
		response.setStatus(getStatus(request).value());
		model.addAttribute("errors", getErrorAttributes(request, isIncludeStackTrace(request)));

// Path: src/main/java/com/pugnascotia/reactdemo/utils/State.java
// public final class State {
// 
// 	/** Populates standard parts of the shared client/server model into the Spring {@link Model}.
// 	 * Values prefixed with "__" will be made available to the JavaScript
// 	 * render function only. All other values will be passed in the client's state object.
// 	 */
// 	public static void populateModel(Model model, HttpServletRequest request) {
// 		model.addAttribute("__requestPath", getRequestPath(request));
// 		model.addAttribute("auth", getAuthState(request));
// 	}
// 
// 	/**
// 	 * Returns the request string, including the query fragment, so that it can be made available
// 	 * during server-side react-router rendering.
// 	 */
// 	private static String getRequestPath(HttpServletRequest request) {
// 		String queryString = request.getQueryString();
// 		return request.getRequestURI() + (queryString == null ? "" : "?" + queryString);
// 	}
// 
// 	/**
// 	 * Returns a representation of the user's authentication state, in the shape expected by the client.
// 	 */
// 	public static Map<String, Object> getAuthState(HttpServletRequest request) {
// 		Optional<List<String>> optionalRoles = getRoles(request);
// 
// 		return optionalRoles.map(roles -> {
// 			Map<String, Object> authState = new HashMap<>();
// 			authState.put("signedIn", !roles.contains("ROLE_ANONYMOUS"));
// 			authState.put("roles", roles);
// 
// 			return authState;
// 		})
// 		.orElseGet(() -> {
// 			Map<String, Object> authState = new HashMap<>();
// 			authState.put("signedIn", false);
// 			authState.put("roles", Collections.singletonList("ROLE_ANONYMOUS"));
// 
// 			return authState;
// 		});
// 	}
// 
// 	/**
// 	 * Return a list of the current user's roles. If they are not authenticated then they will
// 	 * have "ROLE_ANONYMOUS".
// 	 */
// 	private static Optional<List<String>> getRoles(HttpServletRequest request) {
// 		return getAuthentication(request)
// 			.map(a -> Functions.map(a.getAuthorities(), GrantedAuthority::getAuthority));
// 	}
// 
// 	/**
// 	 * Getting the current authentication object ought to be easy, by getting a context with
// 	 * {@link SecurityContextHolder#getContext()}, then calling {@link SecurityContext#getAuthentication()}.
// 	 * However there are circumstances where that doesn't work reliably, such as when handling
// 	 * exceptions. This method makes several attempts to get an {@link Authentication} instance.
// 	 */
// 	private static Optional<Authentication> getAuthentication(HttpServletRequest request) {
// 		Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
// 
// 		if (authentication == null) {
// 			RequestAttributes requestAttributes = new ServletRequestAttributes(request);
// 			SecurityContext securityContext = (SecurityContext) requestAttributes.getAttribute("SPRING_SECURITY_CONTEXT", RequestAttributes.SCOPE_SESSION);
// 			if (securityContext == null) {
// 				securityContext = (SecurityContext) requestAttributes.getAttribute("SPRING_SECURITY_CONTEXT", RequestAttributes.SCOPE_GLOBAL_SESSION);
// 			}
// 			if (securityContext != null) {
// 				authentication = securityContext.getAuthentication();
// 			}
// 		}
// 
// 		return Optional.ofNullable(authentication);
// 	}
// }


// Path: src/main/java/com/pugnascotia/reactdemo/errors/ReactErrorController.java
import java.util.Map;
import javax.inject.Inject;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.pugnascotia.reactdemo.utils.State;
import org.springframework.boot.autoconfigure.web.AbstractErrorController;
import org.springframework.boot.autoconfigure.web.ErrorAttributes;
import org.springframework.boot.autoconfigure.web.ErrorProperties;
import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

package com.pugnascotia.reactdemo.errors;



/**
 * Largely pinched from {@link org.springframework.boot.autoconfigure.web.BasicErrorController}
 * and customised to render our React template, along with an appropriate populated state.
 */

@Controller
@RequestMapping("/error")
public class ReactErrorController extends AbstractErrorController {

	private final ServerProperties serverProperties;

	@Inject
	public ReactErrorController(ErrorAttributes errorAttributes, ServerProperties serverProperties) {
		super(errorAttributes);
		this.serverProperties = serverProperties;
	}

	/**
	 * Render the standard template, but include all the error information we know about. In
	 * a production application, you may not want to pass all that information to the client.
	 */
	@RequestMapping(produces = "text/html")
	public String errorHtml(Model model, HttpServletRequest request, HttpServletResponse response) {
		response.setStatus(getStatus(request).value());
		model.addAttribute("errors", getErrorAttributes(request, isIncludeStackTrace(request)));

		State.populateModel(model, request);