I have two user roles and a layout page for each, and a single .html
which has layout fragments with the main content, accessible by both users. I want to use the specific layout page depending on the user.
This is what I'm trying to do:
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
xmlns:sec="http://www.thymeleaf.org/extras/spring-security"
layout:decorate="~{(hasRole('ADMIN') ? adminLayout : customerLayout)}">
<head>...</head>
<body>
<th:block layout:fragment="someContent">
<h1>Same main content but replacing layout depending of the user!</h1>
....
</th:block>
</body>
</html>
But I keep getting errors of failed evaluation of the page or that the hasRole
method doesn't exist, depending of the syntax that I try:
org.springframework.expression.spel.SpelEvaluationException: EL1004E: Method call: Method hasRole(java.lang.String) cannot be found on type org.thymeleaf.spring5.expression.SPELContextMapWrapper
Is it possible to determine the layout decorator used based on the authenticated user role inside the .html
file (not in the Controller, etc)? Or rather, is it possible to access these security methods from a scope like this?
You must refer to the utility bean provided by spring security for thymeleaf to be able to call spring security methods.
Invoking spring security methods is done in the method expression
which is provided by the utility bean and it's return type is boolean. So your code will be like:
layout:decorate="~{#authorization.expression('hasRole(''ADMIN'')') ? 'adminLayout' : 'customerLayout'}"