From 3192717c0fb2b12e45d9c88b97be9fd4e098c2b0 Mon Sep 17 00:00:00 2001 From: click33 <2393584716@qq.com> Date: Wed, 8 Jan 2025 07:11:08 +0800 Subject: [PATCH] =?UTF-8?q?feat(plugin):=20=E6=96=B0=E5=A2=9E=20freemarker?= =?UTF-8?q?=20=E9=9B=86=E6=88=90=E6=8F=92=E4=BB=B6=E3=80=82=20fix:=20#651?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- mvn clean.bat | 1 + sa-token-bom/pom.xml | 5 + .../sa-token-demo-freemarker/pom.xml | 71 ++++++++++ .../pj/SaTokenFreemarkerDemoApplication.java | 16 +++ .../java/com/pj/satoken/SaTokenConfigure.java | 39 ++++++ .../java/com/pj/satoken/StpInterfaceImpl.java | 43 ++++++ .../java/com/pj/test/GlobalException.java | 23 ++++ .../main/java/com/pj/test/TestController.java | 39 ++++++ .../src/main/resources/application.yml | 16 +++ .../src/main/resources/templates/index.ftl | 39 ++++++ .../main/java/com/pj/test/TestController.java | 4 +- sa-token-dependencies/pom.xml | 12 +- sa-token-doc/_sidebar.md | 1 + sa-token-doc/plugin/freemarker-extend.md | 130 ++++++++++++++++++ sa-token-plugin/pom.xml | 1 + sa-token-plugin/sa-token-freemarker/pom.xml | 33 +++++ .../SaTokenTemplateDirectiveModel.java | 66 +++++++++ .../dialect/SaTokenTemplateModel.java | 98 +++++++++++++ 18 files changed, 633 insertions(+), 4 deletions(-) create mode 100644 sa-token-demo/sa-token-demo-freemarker/pom.xml create mode 100644 sa-token-demo/sa-token-demo-freemarker/src/main/java/com/pj/SaTokenFreemarkerDemoApplication.java create mode 100644 sa-token-demo/sa-token-demo-freemarker/src/main/java/com/pj/satoken/SaTokenConfigure.java create mode 100644 sa-token-demo/sa-token-demo-freemarker/src/main/java/com/pj/satoken/StpInterfaceImpl.java create mode 100644 sa-token-demo/sa-token-demo-freemarker/src/main/java/com/pj/test/GlobalException.java create mode 100644 sa-token-demo/sa-token-demo-freemarker/src/main/java/com/pj/test/TestController.java create mode 100644 sa-token-demo/sa-token-demo-freemarker/src/main/resources/application.yml create mode 100644 sa-token-demo/sa-token-demo-freemarker/src/main/resources/templates/index.ftl create mode 100644 sa-token-doc/plugin/freemarker-extend.md create mode 100644 sa-token-plugin/sa-token-freemarker/pom.xml create mode 100644 sa-token-plugin/sa-token-freemarker/src/main/java/cn/dev33/satoken/freemarker/dialect/SaTokenTemplateDirectiveModel.java create mode 100644 sa-token-plugin/sa-token-freemarker/src/main/java/cn/dev33/satoken/freemarker/dialect/SaTokenTemplateModel.java diff --git a/mvn clean.bat b/mvn clean.bat index 3f051542..57e7e58e 100644 --- a/mvn clean.bat +++ b/mvn clean.bat @@ -24,6 +24,7 @@ cd sa-token-demo-springboot-redisson & call mvn clean & cd .. cd sa-token-demo-ssm & call mvn clean & cd .. cd sa-token-demo-test & call mvn clean & cd .. cd sa-token-demo-thymeleaf & call mvn clean & cd .. +cd sa-token-demo-freemarker & call mvn clean & cd .. cd sa-token-demo-webflux & call mvn clean & cd .. cd sa-token-demo-webflux-springboot3 & call mvn clean & cd .. cd sa-token-demo-websocket & call mvn clean & cd .. diff --git a/sa-token-bom/pom.xml b/sa-token-bom/pom.xml index 74e4b510..cd45f03c 100644 --- a/sa-token-bom/pom.xml +++ b/sa-token-bom/pom.xml @@ -154,6 +154,11 @@ sa-token-dialect-thymeleaf ${revision} + + cn.dev33 + sa-token-freemarker + ${revision} + cn.dev33 sa-token-jwt diff --git a/sa-token-demo/sa-token-demo-freemarker/pom.xml b/sa-token-demo/sa-token-demo-freemarker/pom.xml new file mode 100644 index 00000000..65056b06 --- /dev/null +++ b/sa-token-demo/sa-token-demo-freemarker/pom.xml @@ -0,0 +1,71 @@ + + 4.0.0 + cn.dev33 + sa-token-demo-freemarker + 0.0.1-SNAPSHOT + + + + org.springframework.boot + spring-boot-starter-parent + 2.5.14 + + + + + + 1.39.0 + + + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-aop + + + + + org.springframework.boot + spring-boot-starter-freemarker + + + + + cn.dev33 + sa-token-spring-boot-starter + ${sa-token.version} + + + + + cn.dev33 + sa-token-freemarker + ${sa-token.version} + + + + + org.springframework.boot + spring-boot-devtools + provided + + + + + org.springframework.boot + spring-boot-configuration-processor + true + + + + + + diff --git a/sa-token-demo/sa-token-demo-freemarker/src/main/java/com/pj/SaTokenFreemarkerDemoApplication.java b/sa-token-demo/sa-token-demo-freemarker/src/main/java/com/pj/SaTokenFreemarkerDemoApplication.java new file mode 100644 index 00000000..4f171e97 --- /dev/null +++ b/sa-token-demo/sa-token-demo-freemarker/src/main/java/com/pj/SaTokenFreemarkerDemoApplication.java @@ -0,0 +1,16 @@ +package com.pj; + +import cn.dev33.satoken.SaManager; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class SaTokenFreemarkerDemoApplication { + + public static void main(String[] args) { + SpringApplication.run(SaTokenFreemarkerDemoApplication.class, args); + System.out.println("\n启动成功,Sa-Token 配置如下:" + SaManager.getConfig()); + System.out.println("\n测试访问:http://localhost:8081/"); + } + +} \ No newline at end of file diff --git a/sa-token-demo/sa-token-demo-freemarker/src/main/java/com/pj/satoken/SaTokenConfigure.java b/sa-token-demo/sa-token-demo-freemarker/src/main/java/com/pj/satoken/SaTokenConfigure.java new file mode 100644 index 00000000..a5b6b806 --- /dev/null +++ b/sa-token-demo/sa-token-demo-freemarker/src/main/java/com/pj/satoken/SaTokenConfigure.java @@ -0,0 +1,39 @@ +package com.pj.satoken; + +import cn.dev33.satoken.freemarker.dialect.SaTokenTemplateModel; +import cn.dev33.satoken.stp.StpUtil; +import freemarker.template.TemplateModelException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer; + +import javax.annotation.PostConstruct; + + +/** + * [Sa-Token 权限认证] 配置类 + * + * @author click33 + */ +@Configuration +public class SaTokenConfigure { + + @Autowired + FreeMarkerConfigurer configurer; + + /** + * 注入 Sa-Token Freemarker 标签模板模型 对象 + */ + @PostConstruct + public void setSaTokenTemplateModel() throws TemplateModelException { + + // 注入 Sa-Token Freemarker 标签模板模型,使之可以在 xxx.ftl 文件中使用 sa 标签, + // 例如:<#if sa.login()>... + configurer.getConfiguration().setSharedVariable("sa", new SaTokenTemplateModel()); + + // 注入 Sa-Token Freemarker 全局对象,使之可以在 xxx.ftl 文件中调用 StpLogic 相关方法, + // 例如:${stp.getSession().get('name')} + configurer.getConfiguration().setSharedVariable("stp", StpUtil.stpLogic); + } + +} diff --git a/sa-token-demo/sa-token-demo-freemarker/src/main/java/com/pj/satoken/StpInterfaceImpl.java b/sa-token-demo/sa-token-demo-freemarker/src/main/java/com/pj/satoken/StpInterfaceImpl.java new file mode 100644 index 00000000..6cfd8edb --- /dev/null +++ b/sa-token-demo/sa-token-demo-freemarker/src/main/java/com/pj/satoken/StpInterfaceImpl.java @@ -0,0 +1,43 @@ +package com.pj.satoken; + +import cn.dev33.satoken.stp.StpInterface; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.List; + +/** + * 自定义权限验证接口扩展 + */ +@Component // 打开此注解,保证此类被springboot扫描,即可完成sa-token的自定义权限验证扩展 +public class StpInterfaceImpl implements StpInterface { + + /** + * 返回一个账号所拥有的权限码集合 + */ + @Override + public List getPermissionList(Object loginId, String loginType) { + // 本list仅做模拟,实际项目中要根据具体业务逻辑来查询权限 + List list = new ArrayList(); + list.add("101"); + list.add("user-add"); + list.add("user-delete"); + list.add("user-update"); + list.add("user-get"); + list.add("article-get"); + return list; + } + + /** + * 返回一个账号所拥有的角色标识集合 + */ + @Override + public List getRoleList(Object loginId, String loginType) { + // 本list仅做模拟,实际项目中要根据具体业务逻辑来查询角色 + List list = new ArrayList(); + list.add("admin"); + list.add("super-admin"); + return list; + } + +} diff --git a/sa-token-demo/sa-token-demo-freemarker/src/main/java/com/pj/test/GlobalException.java b/sa-token-demo/sa-token-demo-freemarker/src/main/java/com/pj/test/GlobalException.java new file mode 100644 index 00000000..92d092cf --- /dev/null +++ b/sa-token-demo/sa-token-demo-freemarker/src/main/java/com/pj/test/GlobalException.java @@ -0,0 +1,23 @@ +package com.pj.test; + +import cn.dev33.satoken.util.SaResult; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestControllerAdvice; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * 全局异常处理 + */ +@RestControllerAdvice +public class GlobalException { + + // 全局异常拦截(拦截项目中的所有异常) + @ExceptionHandler + public SaResult handlerException(Exception e, HttpServletRequest request, HttpServletResponse response) throws Exception { + e.printStackTrace(); + return SaResult.error(e.getMessage()); + } + +} diff --git a/sa-token-demo/sa-token-demo-freemarker/src/main/java/com/pj/test/TestController.java b/sa-token-demo/sa-token-demo-freemarker/src/main/java/com/pj/test/TestController.java new file mode 100644 index 00000000..a6b7fc50 --- /dev/null +++ b/sa-token-demo/sa-token-demo-freemarker/src/main/java/com/pj/test/TestController.java @@ -0,0 +1,39 @@ +package com.pj.test; + +import cn.dev33.satoken.stp.StpUtil; +import cn.dev33.satoken.util.SaResult; +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.ModelAndView; + +/** + * 测试 Controller + * + * @author click33 + */ +@RestController +public class TestController { + + // 首页 + @RequestMapping("/") + public Object index() { + return new ModelAndView("index"); + } + + // 登录 + @RequestMapping("login") + public SaResult login(@RequestParam(defaultValue="10001") String id) { + StpUtil.login(id); + StpUtil.getSession().set("name", "zhangsan"); + return SaResult.ok(); + } + + // 注销 + @RequestMapping("logout") + public SaResult logout() { + StpUtil.logout(); + return SaResult.ok(); + } + +} diff --git a/sa-token-demo/sa-token-demo-freemarker/src/main/resources/application.yml b/sa-token-demo/sa-token-demo-freemarker/src/main/resources/application.yml new file mode 100644 index 00000000..8cb7f5fb --- /dev/null +++ b/sa-token-demo/sa-token-demo-freemarker/src/main/resources/application.yml @@ -0,0 +1,16 @@ +# 端口 +server: + port: 8081 + +spring: + # Freemarker 相关配置 + freemarker: + # 指定模板文件的目录 + template-loader-path: classpath:/templates + # 指定Freemarker模板文件的后缀名 + suffix: .ftl + # 关闭模板缓存,方便测试 + cache: false + # 检查模板更新延迟时间,设置为0表示立即检查,如果时间大于0会有缓存不方便进行模板测试 + settings: + template_update_delay: 0 \ No newline at end of file diff --git a/sa-token-demo/sa-token-demo-freemarker/src/main/resources/templates/index.ftl b/sa-token-demo/sa-token-demo-freemarker/src/main/resources/templates/index.ftl new file mode 100644 index 00000000..6989aee0 --- /dev/null +++ b/sa-token-demo/sa-token-demo-freemarker/src/main/resources/templates/index.ftl @@ -0,0 +1,39 @@ + + + + Sa-Token 集成 Freemarker 标签方言 + + + + +
+

Sa-Token 集成 Freemarker 标签方言 —— 测试页面

+

当前是否登录:<#if stp.isLogin()>是<#else>否

+

+ 登录 + 注销 +

+ +

登录之后才能显示:<@sa.login>value

+

不登录才能显示:<@sa.notLogin>value

+ +

具有角色 admin 才能显示:<@sa.hasRole value="admin">value

+

同时具备多个角色才能显示:<@sa.hasRoleAnd value="admin, ceo, cto">value

+

只要具有其中一个角色就能显示:<@sa.hasRoleOr value="admin, ceo, cto">value

+

不具有角色 admin 才能显示:<@sa.notRole value="admin">value

+ +

具有权限 user-add 才能显示:<@sa.hasPermission value="user-add">value

+

同时具备多个权限才能显示:<@sa.hasPermissionAnd value="user-add, user-delete, user-get">value

+

只要具有其中一个权限就能显示:<@sa.hasPermissionOr value="user-add, user-delete, user-get">value

+

不具有权限 user-add 才能显示:<@sa.notPermission value="user-add">value

+ +

+ 从SaSession中取值: + <#if stp.isLogin()> + ${stp.getSession().get('name')} + +

+ +
+ + diff --git a/sa-token-demo/sa-token-demo-thymeleaf/src/main/java/com/pj/test/TestController.java b/sa-token-demo/sa-token-demo-thymeleaf/src/main/java/com/pj/test/TestController.java index d9a85afd..c270a6e4 100644 --- a/sa-token-demo/sa-token-demo-thymeleaf/src/main/java/com/pj/test/TestController.java +++ b/sa-token-demo/sa-token-demo-thymeleaf/src/main/java/com/pj/test/TestController.java @@ -9,9 +9,9 @@ import cn.dev33.satoken.stp.StpUtil; import cn.dev33.satoken.util.SaResult; /** - * Sa-Token-SSO Server端 Controller - * @author click33 + * 测试 Controller * + * @author click33 */ @RestController public class TestController { diff --git a/sa-token-dependencies/pom.xml b/sa-token-dependencies/pom.xml index c711a34d..e8a4e93f 100644 --- a/sa-token-dependencies/pom.xml +++ b/sa-token-dependencies/pom.xml @@ -23,6 +23,7 @@ 3.1.0 6.0.0 3.0.9.RELEASE + 2.3.34 3.0.4 1.6.2 3.2.88 @@ -200,8 +201,15 @@ thymeleaf ${thymeleaf.version}
- - + + + + org.freemarker + freemarker + ${freemarker.version} + + + org.springframework.boot spring-boot-starter-thymeleaf diff --git a/sa-token-doc/_sidebar.md b/sa-token-doc/_sidebar.md index 7e0afe7d..0865c3ca 100644 --- a/sa-token-doc/_sidebar.md +++ b/sa-token-doc/_sidebar.md @@ -87,6 +87,7 @@ - [Alone独立Redis插件](/plugin/alone-redis) - [持久层扩展](/plugin/dao-extend) - [和 Thymeleaf 集成](/plugin/thymeleaf-extend) + - [和 Freemarker 集成](/plugin/freemarker-extend) - [和 jwt 集成](/plugin/jwt-extend) - [和 Dubbo 集成](/plugin/dubbo-extend) - [和 gRPC 集成](/plugin/grpc-extend) diff --git a/sa-token-doc/plugin/freemarker-extend.md b/sa-token-doc/plugin/freemarker-extend.md new file mode 100644 index 00000000..a4b3e476 --- /dev/null +++ b/sa-token-doc/plugin/freemarker-extend.md @@ -0,0 +1,130 @@ +# Freemarker 自定义标签 + +本插件的作用是让我们可以在 Freemarker 页面中使用 Sa-Token 自定义标签以及相关API。 + +--- + +### 1、引入依赖 +首先我们确保项目已经引入 Freemarker 依赖,然后在此基础上继续添加: + + + +``` xml + + + cn.dev33 + sa-token-freemarker + ${sa.top.version} + +``` + +``` gradle +// 在 Freemarker 页面中使用 Sa-Token 自定义标签 +implementation 'cn.dev33:sa-token-freemarker:${sa.top.version}' +``` + + + + +### 2、注入 Sa-Token Freemarker 标签模板模型 对象 +在 SaTokenConfigure 配置类中增加配置 +``` java +@Configuration +public class SaTokenConfigure { + + @Autowired + FreeMarkerConfigurer configurer; + + /** + * 注入 Sa-Token Freemarker 标签模板模型 对象 + */ + @PostConstruct + public void setSaTokenTemplateModel() throws TemplateModelException { + + // 注入 Sa-Token Freemarker 标签模板模型,使之可以在 xxx.ftl 文件中使用 sa 标签, + // 例如:<#if sa.login()>... + configurer.getConfiguration().setSharedVariable("sa", new SaTokenTemplateModel()); + + // 注入 Sa-Token Freemarker 全局对象,使之可以在 xxx.ftl 文件中调用 StpLogic 相关方法, + // 例如:${stp.getSession().get('name')} + configurer.getConfiguration().setSharedVariable("stp", StpUtil.stpLogic); + } + +} +``` + + +### 3、使用自定义标签 +然后我们就可以愉快的使用在 Freemarker 页面中使用 Sa-Token 自定义标签了 + +##### 3.1、登录判断 +``` html +

标签方言测试页面

+

+ 登录之后才能显示: + <@sa.login>value +

+

+ 不登录才能显示: + <@sa.notLogin>value +

+``` + +##### 3.2、角色判断 +``` html +

+ 具有角色 admin 才能显示: + <@sa.hasRole value="admin">value +

+

+ 同时具备多个角色才能显示: + <@sa.hasRoleAnd value="admin, ceo, cto">value +

+

+ 只要具有其中一个角色就能显示: + <@sa.hasRoleOr value="admin, ceo, cto">value +

+

+ 不具有角色 admin 才能显示: + <@sa.notRole value="admin">value +

+``` + +##### 3.3、权限判断 +``` html +

+ 具有权限 user-add 才能显示: + <@sa.hasPermission value="user-add">value +

+

+ 同时具备多个权限才能显示: + <@sa.hasPermissionAnd value="user-add, user-delete, user-get">value +

+

+ 只要具有其中一个权限就能显示: + <@sa.hasPermissionOr value="user-add, user-delete, user-get">value +

+

+ 不具有权限 user-add 才能显示: + <@sa.notPermission value="user-add">value +

+``` + + +### 4、调用 Sa-Token 相关API + +以上的自定义标签,可以满足我们大多数场景下的权限判断,然后有时候我们依然需要更加灵活的在页面中调用 Sa-Token 框架API : + + +``` html +

+ 从SaSession中取值: + <#if stp.isLogin()> + ${stp.getSession().get('name')} + +

+``` + + + + diff --git a/sa-token-plugin/pom.xml b/sa-token-plugin/pom.xml index f314bd16..027d6890 100644 --- a/sa-token-plugin/pom.xml +++ b/sa-token-plugin/pom.xml @@ -28,6 +28,7 @@ sa-token-alone-redis sa-token-hutool-timed-cache sa-token-dialect-thymeleaf + sa-token-freemarker sa-token-sso sa-token-oauth2 sa-token-quick-login diff --git a/sa-token-plugin/sa-token-freemarker/pom.xml b/sa-token-plugin/sa-token-freemarker/pom.xml new file mode 100644 index 00000000..542e008b --- /dev/null +++ b/sa-token-plugin/sa-token-freemarker/pom.xml @@ -0,0 +1,33 @@ + + + 4.0.0 + + + cn.dev33 + sa-token-plugin + ${revision} + ../pom.xml + + jar + + sa-token-freemarker + sa-token-freemarker + sa-token-freemarker + + + + + cn.dev33 + sa-token-core + + + + org.freemarker + freemarker + true + + + + diff --git a/sa-token-plugin/sa-token-freemarker/src/main/java/cn/dev33/satoken/freemarker/dialect/SaTokenTemplateDirectiveModel.java b/sa-token-plugin/sa-token-freemarker/src/main/java/cn/dev33/satoken/freemarker/dialect/SaTokenTemplateDirectiveModel.java new file mode 100644 index 00000000..ed4ee7ae --- /dev/null +++ b/sa-token-plugin/sa-token-freemarker/src/main/java/cn/dev33/satoken/freemarker/dialect/SaTokenTemplateDirectiveModel.java @@ -0,0 +1,66 @@ +/* + * Copyright 2020-2099 sa-token.cc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package cn.dev33.satoken.freemarker.dialect; + +import freemarker.core.Environment; +import freemarker.template.TemplateDirectiveBody; +import freemarker.template.TemplateDirectiveModel; +import freemarker.template.TemplateException; +import freemarker.template.TemplateModel; + +import java.io.IOException; +import java.util.Map; +import java.util.function.Function; + +/** + * Sa-Token Freemarker 标签模板指令模型 + * + * @author click33 + * @since 1.40.0 + */ +public class SaTokenTemplateDirectiveModel implements TemplateDirectiveModel { + + /** + * 使用标签指令模板时,指定值的属性名 + */ + String attrName; + + /** + * 断言函数,返回 true 时标签内容显示,返回 false 时标签内容不显示 + */ + Function fun; + + public SaTokenTemplateDirectiveModel(String attrName, Function fun) { + this.attrName = attrName; + this.fun = fun; + } + + @Override + public void execute(Environment environment, Map map, TemplateModel[] templateModels, TemplateDirectiveBody templateDirectiveBody) + throws TemplateException, IOException { + + // 获取 value + Object obj = map.get(attrName); + String value = obj == null ? null : obj.toString(); + + // 使用断言函数判断是否显示标签内容 + if(this.fun.apply(value)) { + templateDirectiveBody.render(environment.getOut()); + } + + } + +} \ No newline at end of file diff --git a/sa-token-plugin/sa-token-freemarker/src/main/java/cn/dev33/satoken/freemarker/dialect/SaTokenTemplateModel.java b/sa-token-plugin/sa-token-freemarker/src/main/java/cn/dev33/satoken/freemarker/dialect/SaTokenTemplateModel.java new file mode 100644 index 00000000..490adbd5 --- /dev/null +++ b/sa-token-plugin/sa-token-freemarker/src/main/java/cn/dev33/satoken/freemarker/dialect/SaTokenTemplateModel.java @@ -0,0 +1,98 @@ +/* + * Copyright 2020-2099 sa-token.cc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package cn.dev33.satoken.freemarker.dialect; + +import cn.dev33.satoken.stp.StpLogic; +import cn.dev33.satoken.stp.StpUtil; +import cn.dev33.satoken.util.SaFoxUtil; +import freemarker.template.SimpleHash; + +import java.util.List; + +/** + * Sa-Token Freemarker 标签模板模型 + * + * @author click33 + * @since 1.40.0 + */ +public class SaTokenTemplateModel extends SimpleHash { + + /** + * 默认值属性名 + */ + public static final String DEFAULT_ATTR_NAME = "value"; + + /** + * 底层使用的 StpLogic + */ + public StpLogic stpLogic; + + /** + * 使用默认参数注册标签模板模型 + */ + public SaTokenTemplateModel() { + this(DEFAULT_ATTR_NAME, StpUtil.stpLogic); + } + + /** + * 构造标签模板模型,使用自定义参数 + * + * @param stpLogic 使用的 StpLogic 对象 + */ + public SaTokenTemplateModel(StpLogic stpLogic) { + this(DEFAULT_ATTR_NAME, stpLogic); + } + + /** + * 构造标签模板模型,使用自定义参数 + * + * @param attrName 属性名 + * @param stpLogic 使用的 StpLogic 对象 + */ + public SaTokenTemplateModel(String attrName, StpLogic stpLogic) { + this.stpLogic = stpLogic; + + // 登录判断 + put("login", new SaTokenTemplateDirectiveModel(attrName, value -> stpLogic.isLogin())); + put("notLogin", new SaTokenTemplateDirectiveModel(attrName, value -> ! stpLogic.isLogin())); + + // 角色判断 + put("hasRole", new SaTokenTemplateDirectiveModel(attrName, value -> stpLogic.hasRole(value))); + put("hasRoleAnd", new SaTokenTemplateDirectiveModel(attrName, value -> stpLogic.hasRoleAnd(toArray(value)))); + put("hasRoleOr", new SaTokenTemplateDirectiveModel(attrName, value -> stpLogic.hasRoleOr(toArray(value)))); + put("notRole", new SaTokenTemplateDirectiveModel(attrName, value -> ! stpLogic.hasRole(value))); + put("lackRole", new SaTokenTemplateDirectiveModel(attrName, value -> ! stpLogic.hasRole(value))); + + // 权限判断 + put("hasPermission", new SaTokenTemplateDirectiveModel(attrName, value -> stpLogic.hasPermission(value))); + put("hasPermissionAnd", new SaTokenTemplateDirectiveModel(attrName, value -> stpLogic.hasPermissionAnd(toArray(value)))); + put("hasPermissionOr", new SaTokenTemplateDirectiveModel(attrName, value -> stpLogic.hasPermissionOr(toArray(value)))); + put("notPermission", new SaTokenTemplateDirectiveModel(attrName, value -> ! stpLogic.hasPermission(value))); + put("lackPermission", new SaTokenTemplateDirectiveModel(attrName, value -> ! stpLogic.hasPermission(value))); + + } + + /** + * String 转 Array + * @param str 字符串 + * @return 数组 + */ + public String[] toArray(String str) { + List list = SaFoxUtil.convertStringToList(str); + return list.toArray(new String[0]); + } + +} \ No newline at end of file