ThymeleafAdminController.java
package sk.iway.iwcm.admin;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
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.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.util.MultiValueMap;
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.RequestParam;
import org.springframework.web.server.ResponseStatusException;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import sk.iway.iwcm.*;
import sk.iway.iwcm.admin.layout.LayoutService;
import sk.iway.iwcm.admin.layout.MenuService;
import sk.iway.iwcm.common.LogonTools;
import sk.iway.iwcm.i18n.Prop;
import sk.iway.iwcm.system.spring.WebjetAuthentificationProvider;
import sk.iway.iwcm.system.spring.events.WebjetEvent;
import sk.iway.iwcm.system.spring.events.WebjetEventType;
import sk.iway.iwcm.system.spring.services.WebjetSecurityService;
import sk.iway.iwcm.users.UsersDB;
import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.List;
/**
* ThymeleafAdminController.java
*
* Zakladna trieda pre zobrazenie stranok administracie cez Thymeleaf sablony
*
* Title webjet9 Company Interway a.s. (www.interway.sk) Copyright Interway a.s.
* (c) 2001-2020
*
* @author $Author: jeeff $
*/
@Controller
@PreAuthorize("@WebjetSecurityService.isAdmin()")
public class ThymeleafAdminController {
/**
*
* @param page String
* @param subpage - String - nesmie obsahovat znak ., cize nemoze to byt subor
* @param allParams MultiValueMap<String, String>
* @param model ModelMap
* @param request HttpServletRequest
* @return String
*/
@GetMapping({ "/admin/v9/", "/admin/v9/{page}/", "/admin/v9/{page}/{subpage:[^.]*}" })
public ModelAndView defaultHandler(@PathVariable(required = false) String page,
@PathVariable(required = false) String subpage,
@RequestParam(required = false) final MultiValueMap<String, String> allParams,
final ModelMap model,
final RedirectAttributes redirectAttributes,
final HttpServletRequest request) {
// /admin/v9/ == zobraz dashboard
if (Tools.isEmpty(page)) {
page = "dashboard";
subpage = "overview";
}
if (Tools.isEmpty(subpage))
subpage = "index";
// @TODO: nepotrebujeme sem nejaku kontrolu URL parametrov?
String forward = "admin/v9/dist/views/" + page + "/" + subpage;
Logger.debug(ThymeleafAdminController.class, "Thymeleaf forward=" + forward);
removePermissionFromCurrentUser(request);
fireEvent(page, subpage, model, redirectAttributes, request);
setLayout(model, request);
if (model.containsKey("redirect")) {
return new ModelAndView("redirect:" + model.get("redirect"));
}
forward = checkPerms(forward, forward, request);
return new ModelAndView(forward);
}
@PostMapping(path = { "/admin/v9/{page}/", "/admin/v9/{page}/{subpage:[^.]*}" }, consumes = { MediaType.MULTIPART_FORM_DATA_VALUE })
public ModelAndView defaultHandlerPost(@PathVariable(required = false) String page,
@PathVariable(required = false) String subpage,
@RequestParam(required = false) final MultiValueMap<String, String> allParams,
final ModelMap model,
final RedirectAttributes redirectAttributes,
final HttpServletRequest request) {
Logger.debug(ThymeleafAdminController.class, "post loaded admin: {}", page);
return defaultHandler(page, subpage, allParams, model, redirectAttributes, request);
}
/**
* Vykona forward pre admin cast aplikacii, tie sa nachadzaju v /app/MENO_APP/admin/ adresari
* Technicky vykona forward na app/default.pug kde sa do vnutra stranky dynamicky includne
* HTML subor z app adresara (cize v nom nie je potrebne riesit okoli stranky ako hlavicka a menu)
* @param app String
* @param subpage String
* @param model ModelMap
* @param request HttpServletRequest
* @return String
*/
@GetMapping({ "/apps/{app}/admin/", "/apps/{app}/admin/index.html", "/apps/{app}/admin/{subpage:[^.]+}" })
@PreAuthorize(value = "@WebjetSecurityService.isAdmin()")
public ModelAndView appHandler(
@PathVariable String app,
@PathVariable(required = false) String subpage,
final ModelMap model,
final RedirectAttributes redirectAttributes,
final HttpServletRequest request)
{
String originalPath = "/apps/"+app+"/admin/";
if (Tools.isNotEmpty(subpage) && "index.html".equals(subpage)==false) originalPath += subpage+"/";
//spring zrazu prazdne subpage vracia ako index.html
if (Tools.isEmpty(subpage) || "index.html".equals(subpage))
subpage = "index";
String forward = "admin/v9/dist/views/apps/default";
final String appIncludePath = "apps/"+app+"/admin/"+subpage+".html";
//kontrola, ci zadana cesta existuje
if (FileTools.isFile("/"+appIncludePath) == false) {
throw new ResponseStatusException(HttpStatus.NOT_FOUND);
}
model.addAttribute("appIncludePath", appIncludePath);
Logger.debug(ThymeleafAdminController.class, "Thymeleaf APP forward=" + forward + " appIncludePath=" + appIncludePath);
//check if there is index.js file to include as script element
String jsFilePath = "/apps/"+app+"/admin/"+app+".js";
if (FileTools.isFile(jsFilePath)) {
model.addAttribute("appIncludePathJs", jsFilePath);
}
removePermissionFromCurrentUser(request);
fireEvent(app, subpage, model, redirectAttributes, request);
setLayout(model, request);
if (model.containsKey("redirect")) {
return new ModelAndView("redirect:" + model.get("redirect"));
}
forward = checkPerms(forward, originalPath, request);
return new ModelAndView(forward);
}
@PostMapping(path = { "/apps/{app}/admin/", "/apps/{app}/admin/index.html", "/apps/{app}/admin/{subpage:[^.]+}" }, consumes = { MediaType.MULTIPART_FORM_DATA_VALUE })
@PreAuthorize(value = "@WebjetSecurityService.isAdmin()")
public ModelAndView appHandlerPost(
@PathVariable String app,
@PathVariable(required = false) String subpage,
final ModelMap model,
final RedirectAttributes redirectAttributes,
final HttpServletRequest request) {
Logger.debug(ThymeleafAdminController.class, "post loaded: {}", app);
return appHandler(app, subpage, model, redirectAttributes, request);
}
/**
* Vyvola event, na ktory sa da pocuvat a doplnit do modelu dalsie data
* @param page String
* @param subpage String
* @param model ModelMap
* @param request HttpServletRequest
*/
private void fireEvent(String page, String subpage, ModelMap model, RedirectAttributes redirectAttributes, HttpServletRequest request) {
//event vyvolame pred layoutService, keby event nieco v layoute menil (napr. domenu)
if ("apps".equals(page)) {
//pre napr. /admin/v9/apps/gallery nastavime podobne ako pre /apps/admin/gallery/
page = subpage;
subpage = "index";
}
ThymeleafEvent event = new ThymeleafEvent(page, subpage, model, redirectAttributes, request);
(new WebjetEvent<>(event, WebjetEventType.ON_START)).publishEvent();
}
/**
* Nastavi LayoutService pre generovanie hlavicky/menu
* @param model ModelMap
* @param request HttpServletRequest
*/
private void setLayout(ModelMap model, HttpServletRequest request) {
final LayoutService ls = new LayoutService(request);
model.addAttribute("layout", ls.getLayoutBean());
model.addAttribute("layoutService", ls);
if ("true".equals(request.getParameter("userlngr"))) {
String lng = Prop.getLng(request, false);
Prop.getInstance(Constants.getServletContext(), lng, true);
}
}
private void removePermissionFromCurrentUser(HttpServletRequest request) {
String permission = request.getParameter("removePerm");
if (Tools.isNotEmpty(permission)) removePermissionFromCurrentUser(permission, request);
}
private void removePermissionFromCurrentUser(String permissionString, HttpServletRequest request) {
Identity user = UsersDB.getCurrentUser(request);
if (user != null && user.getLogin().startsWith("tester")) {
String[] permsArr = Tools.getTokens(permissionString, ",");
for(String permission : permsArr) {
user.addDisabledItem(permission);
}
LogonTools.setUserToSession(request.getSession(), user);
//setUserToSession nepomohlo, musime hacknut
try
{
//prihlasenie pre SPRING / REST
//RequestBean requestBean = SetCharacterEncodingFilter.getCurrentRequestBean();
if (Constants.getServletContext().getAttribute("springContext")!=null)
{
Authentication authentication = WebjetAuthentificationProvider.authenticate(user);
List<GrantedAuthority> grantedAuths = new ArrayList<>();
for (GrantedAuthority ga : authentication.getAuthorities()) {
if (ga instanceof SimpleGrantedAuthority) {
SimpleGrantedAuthority sig = (SimpleGrantedAuthority)ga;
boolean remove = false;
for(String permission : permsArr) {
String itemKey = WebjetSecurityService.normalizeUserGroupName(permission);
String name = "ROLE_Permission_" + itemKey;
if (sig.getAuthority().equals(name)) {
Logger.debug(ThymeleafAdminController.class, "Removing SPRING perm "+name);
remove = true;
}
}
if (remove == false) {
grantedAuths.add(ga);
}
}
}
Authentication auth = new UsernamePasswordAuthenticationToken(
user.getLogin(),
"password",
grantedAuths);
SecurityContextHolder.getContext().setAuthentication(auth);
}
}
catch (Exception ex)
{
Logger.error(ThymeleafAdminController.class, ex);
}
//este raz, lebo to zle nastavovalo
user = UsersDB.getCurrentUser(request);
for(String permission : permsArr) {
user.addDisabledItem(permission);
}
}
}
/**
* Overi pravo na zobrazenie originalUrl, ak je povolene, vrati forward, inak /admin/403.jsp
* @param forward - adresa stranky pre zobrazenie (thymeleaf sablona)
* @param originalUrl - povodna URL adresa v prehliadaci
* @param request
* @return
*/
private String checkPerms(String forward, String originalUrl, HttpServletRequest request) {
String perms = MenuService.getPerms(originalUrl);
Identity user = UsersDB.getCurrentUser(request);
if (Tools.isNotEmpty(perms) && user.isDisabledItem(perms)) {
Logger.debug(ThymeleafAdminController.class, "====> PERMS DENIED: perms="+perms+" originalUrl="+originalUrl+" forward="+forward);
return "redirect:/admin/403.jsp";
}
return forward;
}
}