Browse Source

组和角色优化,增加角色动态任务,删除resumeTime和suspendTime

MaxKey 7 months ago
parent
commit
194b8bbe7c

+ 0 - 24
maxkey-core/src/main/java/org/dromara/maxkey/entity/idm/Groups.java

@@ -65,10 +65,6 @@ public class Groups extends JpaEntity implements Serializable {
     
     @Column
     String orgIdsList;
-    @Column
-    String resumeTime; 
-    @Column
-    String suspendTime;
     
     @Column
     int isdefault;
@@ -228,22 +224,6 @@ public class Groups extends JpaEntity implements Serializable {
         this.orgIdsList = orgIdsList;
     }
 
-    public String getResumeTime() {
-        return resumeTime;
-    }
-
-    public void setResumeTime(String resumeTime) {
-        this.resumeTime = resumeTime;
-    }
-
-    public String getSuspendTime() {
-        return suspendTime;
-    }
-
-    public void setSuspendTime(String suspendTime) {
-        this.suspendTime = suspendTime;
-    }
-
     public String getInstId() {
 		return instId;
 	}
@@ -275,10 +255,6 @@ public class Groups extends JpaEntity implements Serializable {
 		builder.append(filters);
 		builder.append(", orgIdsList=");
 		builder.append(orgIdsList);
-		builder.append(", resumeTime=");
-		builder.append(resumeTime);
-		builder.append(", suspendTime=");
-		builder.append(suspendTime);
 		builder.append(", isdefault=");
 		builder.append(isdefault);
 		builder.append(", description=");

+ 0 - 24
maxkey-core/src/main/java/org/dromara/maxkey/entity/permissions/Roles.java

@@ -64,10 +64,6 @@ public class Roles extends JpaEntity implements Serializable {
     
     @Column
     String orgIdsList;
-    @Column
-    String resumeTime; 
-    @Column
-    String suspendTime;
     
     @Column
     int isdefault;
@@ -230,22 +226,6 @@ public class Roles extends JpaEntity implements Serializable {
         this.orgIdsList = orgIdsList;
     }
 
-    public String getResumeTime() {
-        return resumeTime;
-    }
-
-    public void setResumeTime(String resumeTime) {
-        this.resumeTime = resumeTime;
-    }
-
-    public String getSuspendTime() {
-        return suspendTime;
-    }
-
-    public void setSuspendTime(String suspendTime) {
-        this.suspendTime = suspendTime;
-    }
-
     public String getAppId() {
 		return appId;
 	}
@@ -285,10 +265,6 @@ public class Roles extends JpaEntity implements Serializable {
 		builder.append(filters);
 		builder.append(", orgIdsList=");
 		builder.append(orgIdsList);
-		builder.append(", resumeTime=");
-		builder.append(resumeTime);
-		builder.append(", suspendTime=");
-		builder.append(suspendTime);
 		builder.append(", isdefault=");
 		builder.append(isdefault);
 		builder.append(", description=");

+ 7 - 40
maxkey-persistence/src/main/java/org/dromara/maxkey/persistence/service/GroupsService.java

@@ -18,8 +18,6 @@
 package org.dromara.maxkey.persistence.service;
 
 import java.sql.Types;
-import java.time.LocalDateTime;
-import java.time.LocalTime;
 import java.util.List;
 
 import org.apache.commons.lang3.StringUtils;
@@ -35,13 +33,10 @@ import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Repository;
 
-import com.fasterxml.jackson.annotation.JsonIgnore;
-
 @Repository
 public class GroupsService  extends JpaService<Groups>{
-    
     static final  Logger _logger = LoggerFactory.getLogger(GroupsService.class);
-    @JsonIgnore
+
     @Autowired
     GroupMemberService groupMemberService;
     
@@ -77,26 +72,6 @@ public class GroupsService  extends JpaService<Groups>{
 	
 	public void refreshDynamicGroups(Groups dynamicGroup){
 	    if(dynamicGroup.getCategory().equals(Roles.Category.DYNAMIC)) {
-	        boolean isDynamicTimeSupport = false;
-	        boolean isBetweenEffectiveTime = false;
-	        if(StringUtils.isNotBlank(dynamicGroup.getResumeTime())
-	                &&StringUtils.isNotBlank(dynamicGroup.getSuspendTime())
-	                &&!dynamicGroup.getSuspendTime().equals("00:00")) {
-	            LocalTime currentTime = LocalDateTime.now().toLocalTime();
-	            LocalTime resumeTime = LocalTime.parse(dynamicGroup.getResumeTime());
-	            LocalTime suspendTime = LocalTime.parse(dynamicGroup.getSuspendTime());
-	            
-	            _logger.info("currentTime: {} , resumeTime : {} , suspendTime: {}" 
-	            		, currentTime 
-                        , resumeTime 
-                        , suspendTime);
-	            isDynamicTimeSupport = true;
-	            
-	            if(resumeTime.isBefore(currentTime) && currentTime.isBefore(suspendTime)) {
-	                isBetweenEffectiveTime = true;
-	            }
-	            
-	        }
 	        
 	        if(StringUtils.isNotBlank(dynamicGroup.getOrgIdsList())) {
     	    	String []orgIds = dynamicGroup.getOrgIdsList().split(",");
@@ -120,23 +95,15 @@ public class GroupsService  extends JpaService<Groups>{
 	    			_logger.info("filters include SQL Injection Attack Risk.");
 	    			return;
 	    		}
-	    		filters = filters.replace("&", " AND ");
-	    	    filters = filters.replace("|", " OR ");
+	    		//replace & with AND, | with OR
+	    		filters = filters.replace("&", " AND ").replace("|", " OR ");
 	    	    
 	    	    dynamicGroup.setFilters(filters);
     	    }
-    	    
-    	    if(isDynamicTimeSupport) {
-    	        if(isBetweenEffectiveTime) {
-    	        	groupMemberService.deleteDynamicMember(dynamicGroup);
-    	        	groupMemberService.addDynamicMember(dynamicGroup);
-    	        }else {
-    	        	groupMemberService.deleteDynamicMember(dynamicGroup);
-    	        }
-    	    }else{
-    	    	groupMemberService.deleteDynamicMember(dynamicGroup);
-    	    	groupMemberService.addDynamicMember(dynamicGroup);
-            }
+	    
+	    	groupMemberService.deleteDynamicMember(dynamicGroup);
+	    	groupMemberService.addDynamicMember(dynamicGroup);
+            
 	    }
     }
 	

+ 6 - 37
maxkey-persistence/src/main/java/org/dromara/maxkey/persistence/service/RolesService.java

@@ -20,8 +20,6 @@
 package org.dromara.maxkey.persistence.service;
 
 import java.sql.Types;
-import java.time.LocalDateTime;
-import java.time.LocalTime;
 import java.util.List;
 
 import org.apache.commons.lang3.StringUtils;
@@ -36,13 +34,10 @@ import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Repository;
 
-import com.fasterxml.jackson.annotation.JsonIgnore;
-
 @Repository
 public class RolesService  extends JpaService<Roles> {
     static final  Logger _logger = LoggerFactory.getLogger(RolesService.class);
     
-    @JsonIgnore
     @Autowired
     RoleMemberService roleMemberService;
     
@@ -75,24 +70,6 @@ public class RolesService  extends JpaService<Roles> {
 	
 	public void refreshDynamicRoles(Roles dynamicRole){
 	    if(dynamicRole.getCategory().equals(Roles.Category.DYNAMIC)) {
-	        boolean isDynamicTimeSupport = false;
-	        boolean isBetweenEffectiveTime = false;
-	        if(StringUtils.isNotBlank(dynamicRole.getResumeTime())
-	                &&StringUtils.isNotBlank(dynamicRole.getSuspendTime())
-	                &&!dynamicRole.getSuspendTime().equals("00:00")) {
-	            LocalTime currentTime = LocalDateTime.now().toLocalTime();
-	            LocalTime resumeTime = LocalTime.parse(dynamicRole.getResumeTime());
-	            LocalTime suspendTime = LocalTime.parse(dynamicRole.getSuspendTime());
-	            
-	            _logger.info("currentTime: {}  , resumeTime : {} , suspendTime: {}" , 
-	            		currentTime  , resumeTime , suspendTime);
-	            isDynamicTimeSupport = true;
-	            
-	            if(resumeTime.isBefore(currentTime) && currentTime.isBefore(suspendTime)) {
-	                isBetweenEffectiveTime = true;
-	            }
-	            
-	        }
 	        
 	        if(StringUtils.isNotBlank(dynamicRole.getOrgIdsList())) {
     	    	String []orgIds = dynamicRole.getOrgIdsList().split(",");
@@ -117,24 +94,16 @@ public class RolesService  extends JpaService<Roles> {
 	    			_logger.info("filters include SQL Injection Attack Risk.");
 	    			return;
 	    		}
-	    		filters = filters.replace("&", " AND ");
-	    		filters = filters.replaceAll("\\|", " OR ");
+	    		//replace & with AND, | with OR
+	    		filters = filters.replace("&", " AND ").replace("\\|", " OR ");
 	    	    
 	    		_logger.debug("set filters {}" , filters);
 	    	    dynamicRole.setFilters(filters);
     	    }
-    	    
-    	    if(isDynamicTimeSupport) {
-    	        if(isBetweenEffectiveTime) {
-    	        	roleMemberService.deleteDynamicRoleMember(dynamicRole);
-    	        	roleMemberService.addDynamicRoleMember(dynamicRole);
-    	        }else {
-    	        	roleMemberService.deleteDynamicRoleMember(dynamicRole);
-    	        }
-    	    }else{
-    	    	roleMemberService.deleteDynamicRoleMember(dynamicRole);
-    	    	roleMemberService.addDynamicRoleMember(dynamicRole);
-            }
+	    
+	    	roleMemberService.deleteDynamicRoleMember(dynamicRole);
+	    	roleMemberService.addDynamicRoleMember(dynamicRole);
+        
 	    }
     }
 	

+ 0 - 19
maxkey-web-frontend/maxkey-web-mgt-app/src/app/entity/Groups.ts

@@ -24,13 +24,8 @@ export class Groups extends BaseEntity {
   category!: String;
   filters!: String;
   orgIdsList!: String;
-  resumeTime!: String;
-  suspendTime!: String;
   isdefault!: String;
 
-  picker_resumeTime: Date = new Date(format(new Date(), 'yyyy-MM-dd 00:00:00'));
-  picker_suspendTime: Date = new Date(format(new Date(), 'yyyy-MM-dd 00:00:00'));
-
   constructor() {
     super();
   }
@@ -40,13 +35,6 @@ export class Groups extends BaseEntity {
     if (this.status == 1) {
       this.switch_status = true;
     }
-
-    if (this.resumeTime != '') {
-      this.picker_resumeTime = new Date(format(new Date(), `yyyy-MM-dd ${this.resumeTime}:00`));
-    }
-    if (this.suspendTime != '') {
-      this.picker_suspendTime = new Date(format(new Date(), `yyyy-MM-dd ${this.suspendTime}:00`));
-    }
   }
   override trans(): void {
     if (this.switch_status) {
@@ -54,12 +42,5 @@ export class Groups extends BaseEntity {
     } else {
       this.status = 0;
     }
-
-    if (this.picker_resumeTime) {
-      this.resumeTime = format(this.picker_resumeTime, 'HH:mm');
-    }
-    if (this.picker_suspendTime) {
-      this.suspendTime = format(this.picker_suspendTime, 'HH:mm');
-    }
   }
 }

+ 3 - 21
maxkey-web-frontend/maxkey-web-mgt-app/src/app/entity/Roles.ts

@@ -1,19 +1,18 @@
 /*
  * Copyright [2024] [MaxKey of copyright http://www.maxkey.top]
- * 
+ *
  * 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.
  */
- 
 
 import format from 'date-fns/format';
 
@@ -27,11 +26,7 @@ export class Roles extends BaseEntity {
   category!: String;
   filters!: String;
   orgIdsList!: String;
-  resumeTime!: String;
-  suspendTime!: String;
   isdefault!: String;
-  picker_resumeTime: Date = new Date(format(new Date(), 'yyyy-MM-dd 00:00:00'));
-  picker_suspendTime: Date = new Date(format(new Date(), 'yyyy-MM-dd 00:00:00'));
 
   constructor() {
     super();
@@ -45,13 +40,6 @@ export class Roles extends BaseEntity {
     } else {
       this.switch_status = false;
     }
-
-    if (this.resumeTime != '') {
-      this.picker_resumeTime = new Date(format(new Date(), `yyyy-MM-dd ${this.resumeTime}:00`));
-    }
-    if (this.suspendTime != '') {
-      this.picker_suspendTime = new Date(format(new Date(), `yyyy-MM-dd ${this.suspendTime}:00`));
-    }
   }
 
   override trans(): void {
@@ -60,11 +48,5 @@ export class Roles extends BaseEntity {
     } else {
       this.status = 0;
     }
-    if (this.picker_resumeTime) {
-      this.resumeTime = format(this.picker_resumeTime, 'HH:mm');
-    }
-    if (this.picker_suspendTime) {
-      this.suspendTime = format(this.picker_suspendTime, 'HH:mm');
-    }
   }
 }

+ 0 - 24
maxkey-web-frontend/maxkey-web-mgt-app/src/app/routes/idm/groups/group-editer/group-editer.component.html

@@ -29,30 +29,6 @@
       </nz-form-control>
     </nz-form-item>
     <nz-form-item *ngIf="form.model.category == 'dynamic'">
-      <nz-form-label [nzSm]="6" [nzXs]="24" nzFor="resumeTime">{{ 'mxk.groups.resumeTime' | i18n }}</nz-form-label>
-      <nz-form-control [nzSm]="18" [nzXs]="24" nzErrorTip="The input is not valid port!">
-        <nz-time-picker
-          [(ngModel)]="form.model.picker_resumeTime"
-          [ngModelOptions]="{ standalone: true }"
-          nzFormat="HH:mm"
-          name="picker_resumeTime"
-          id="picker_resumeTime"
-        ></nz-time-picker>
-      </nz-form-control>
-    </nz-form-item>
-    <nz-form-item *ngIf="form.model.category == 'dynamic'">
-      <nz-form-label [nzSm]="6" [nzXs]="24" nzFor="suspendTime">{{ 'mxk.groups.suspendTime' | i18n }}</nz-form-label>
-      <nz-form-control [nzSm]="18" [nzXs]="24" nzErrorTip="The input is not valid suspendTime!">
-        <nz-time-picker
-          [(ngModel)]="form.model.picker_suspendTime"
-          [ngModelOptions]="{ standalone: true }"
-          nzFormat="HH:mm"
-          name="picker_suspendTime"
-          id="picker_suspendTime"
-        ></nz-time-picker>
-      </nz-form-control>
-    </nz-form-item>
-    <nz-form-item *ngIf="form.model.category == 'dynamic'">
       <nz-form-label [nzSm]="6" [nzXs]="24" nzFor="orgIdsList">{{ 'mxk.groups.orgIdsList' | i18n }}</nz-form-label>
       <nz-form-control [nzSm]="18" [nzXs]="24" nzErrorTip="The input is not valid upperCase!">
         <input

+ 48 - 32
maxkey-web-frontend/maxkey-web-mgt-app/src/app/routes/permissions/roles/role-editer/role-editer.component.html

@@ -4,8 +4,7 @@
     <nz-form-item class="d-none">
       <nz-form-label [nzMd]="6" nzRequired nzFor="id">{{ 'mxk.text.id' | i18n }}</nz-form-label>
       <nz-form-control [nzMd]="18" nzErrorTip="The input is not valid id!">
-        <input [(ngModel)]="form.model.id" disabled="{{ isEdit }}" [ngModelOptions]="{ standalone: true }" nz-input
-          name="id" id="id" />
+        <input [(ngModel)]="form.model.id" disabled="{{ isEdit }}" [ngModelOptions]="{ standalone: true }" nz-input name="id" id="id" />
       </nz-form-control>
     </nz-form-item>
     <nz-form-item>
@@ -19,22 +18,26 @@
     <nz-form-item>
       <nz-form-label [nzMd]="6" nzRequired nzFor="roleCode">{{ 'mxk.text.id' | i18n }}</nz-form-label>
       <nz-form-control [nzMd]="18" nzErrorTip="The input is not valid roleCode!">
-        <input [(ngModel)]="form.model.roleCode" disabled="{{ isEdit }}" [ngModelOptions]="{ standalone: true }"
-          nz-input name="roleCode" id="roleCode" />
+        <input
+          [(ngModel)]="form.model.roleCode"
+          disabled="{{ isEdit }}"
+          [ngModelOptions]="{ standalone: true }"
+          nz-input
+          name="roleCode"
+          id="roleCode"
+        />
       </nz-form-control>
     </nz-form-item>
     <nz-form-item>
       <nz-form-label [nzSm]="6" [nzXs]="24" nzRequired nzFor="name">{{ 'mxk.roles.name' | i18n }}</nz-form-label>
       <nz-form-control [nzSm]="18" [nzMd]="18" [nzXs]="36" [nzXl]="48" nzErrorTip="The input is not valid minLength!">
-        <input [(ngModel)]="form.model.roleName" [ngModelOptions]="{ standalone: true }" nz-input name="roleName"
-          id="roleName" />
+        <input [(ngModel)]="form.model.roleName" [ngModelOptions]="{ standalone: true }" nz-input name="roleName" id="roleName" />
       </nz-form-control>
     </nz-form-item>
     <nz-form-item style="display: none">
       <nz-form-label [nzSm]="6" [nzXs]="24" nzRequired nzFor="name">{{ 'mxk.roles.appId' | i18n }}</nz-form-label>
       <nz-form-control [nzSm]="18" [nzMd]="18" [nzXs]="36" [nzXl]="48" nzErrorTip="The input is not valid minLength!">
-        <input [(ngModel)]="form.model.appId" [ngModelOptions]="{ standalone: true }" nz-input name="roleName"
-          id="roleName" />
+        <input [(ngModel)]="form.model.appId" [ngModelOptions]="{ standalone: true }" nz-input name="roleName" id="roleName" />
       </nz-form-control>
     </nz-form-item>
 
@@ -49,42 +52,55 @@
       </nz-form-control>
     </nz-form-item>
     <nz-form-item *ngIf="form.model.category == 'dynamic'">
-      <nz-form-label [nzSm]="6" [nzXs]="24" nzFor="resumeTime">{{ 'mxk.roles.resumeTime' | i18n }}</nz-form-label>
-      <nz-form-control [nzSm]="18" [nzXs]="24" nzErrorTip="The input is not valid port!">
-        <nz-time-picker [(ngModel)]="form.model.picker_resumeTime" [ngModelOptions]="{ standalone: true }"
-          nzFormat="HH:mm" name="picker_resumeTime" id="picker_resumeTime"></nz-time-picker>
-      </nz-form-control>
-    </nz-form-item>
-    <nz-form-item *ngIf="form.model.category == 'dynamic'">
-      <nz-form-label [nzSm]="6" [nzXs]="24" nzFor="suspendTime">{{ 'mxk.roles.suspendTime' | i18n }}</nz-form-label>
-      <nz-form-control [nzSm]="18" [nzXs]="24" nzErrorTip="The input is not valid suspendTime!">
-        <nz-time-picker [(ngModel)]="form.model.picker_suspendTime" [ngModelOptions]="{ standalone: true }"
-          nzFormat="HH:mm" name="picker_suspendTime" id="picker_suspendTime"></nz-time-picker>
-      </nz-form-control>
-    </nz-form-item>
-    <nz-form-item *ngIf="form.model.category == 'dynamic'">
       <nz-form-label [nzSm]="6" [nzXs]="24" nzFor="orgIdsList">{{ 'mxk.roles.orgIdsList' | i18n }}</nz-form-label>
       <nz-form-control [nzSm]="18" [nzXs]="24" nzErrorTip="The input is not valid upperCase!">
-        <input type="hidden" [(ngModel)]="form.model.orgIdsList" [ngModelOptions]="{ standalone: true }" nz-input
-          name="orgIdsList" id="orgIdsList" />
-        <nz-tree-select nzVirtualHeight="300px" [nzMaxTagCount]="3" [(ngModel)]="selectValues"
-          [ngModelOptions]="{ standalone: true }" [nzNodes]="treeNodes.nodes" nzCheckable nzPlaceHolder="Please select"
-          [nzCheckStrictly]="true">
+        <input
+          type="hidden"
+          [(ngModel)]="form.model.orgIdsList"
+          [ngModelOptions]="{ standalone: true }"
+          nz-input
+          name="orgIdsList"
+          id="orgIdsList"
+        />
+        <nz-tree-select
+          nzVirtualHeight="300px"
+          [nzMaxTagCount]="3"
+          [(ngModel)]="selectValues"
+          [ngModelOptions]="{ standalone: true }"
+          [nzNodes]="treeNodes.nodes"
+          nzCheckable
+          nzPlaceHolder="Please select"
+          [nzCheckStrictly]="true"
+        >
         </nz-tree-select>
       </nz-form-control>
     </nz-form-item>
     <nz-form-item *ngIf="form.model.category == 'dynamic'">
       <nz-form-label [nzSm]="6" [nzXs]="24" nzFor="filters">{{ 'mxk.roles.filters' | i18n }}</nz-form-label>
       <nz-form-control [nzSm]="18" [nzXs]="24" nzErrorTip="The input is not valid filters!">
-        <textarea rows="4" nz-input [(ngModel)]="form.model.filters" [ngModelOptions]="{ standalone: true }" nz-input
-          name="filters" id="filters"></textarea>
+        <textarea
+          rows="4"
+          nz-input
+          [(ngModel)]="form.model.filters"
+          [ngModelOptions]="{ standalone: true }"
+          nz-input
+          name="filters"
+          id="filters"
+        ></textarea>
       </nz-form-control>
     </nz-form-item>
     <nz-form-item>
       <nz-form-label [nzSm]="6" [nzXs]="24" nzFor="description">{{ 'mxk.text.description' | i18n }}</nz-form-label>
       <nz-form-control [nzSm]="18" [nzXs]="24" nzErrorTip="The input is not valid encoding!">
-        <textarea rows="4" nz-input [(ngModel)]="form.model.description" [ngModelOptions]="{ standalone: true }"
-          nz-input name="description" id="description"></textarea>
+        <textarea
+          rows="4"
+          nz-input
+          [(ngModel)]="form.model.description"
+          [ngModelOptions]="{ standalone: true }"
+          nz-input
+          name="description"
+          id="description"
+        ></textarea>
       </nz-form-control>
     </nz-form-item>
   </form>
@@ -93,4 +109,4 @@
 <div *nzModalFooter>
   <button nz-button nzType="default" (click)="onClose($event)">{{ 'mxk.text.close' | i18n }}</button>
   <button nz-button nzType="primary" (click)="onSubmit($event)">{{ 'mxk.text.submit' | i18n }}</button>
-</div>
+</div>

+ 19 - 0
maxkey-webs/maxkey-web-mgt/src/main/java/org/dromara/maxkey/autoconfigure/MaxKeyMgtListenerConfig.java

@@ -20,11 +20,13 @@ package org.dromara.maxkey.autoconfigure;
 import org.dromara.maxkey.authn.session.SessionManager;
 import org.dromara.maxkey.configuration.ApplicationConfig;
 import org.dromara.maxkey.listener.DynamicGroupsListenerAdapter;
+import org.dromara.maxkey.listener.DynamicRolesListenerAdapter;
 import org.dromara.maxkey.listener.ReorgDeptListenerAdapter;
 import org.dromara.maxkey.listener.SessionListenerAdapter;
 import org.dromara.maxkey.persistence.service.ConnectorsService;
 import org.dromara.maxkey.persistence.service.GroupsService;
 import org.dromara.maxkey.persistence.service.OrganizationsService;
+import org.dromara.maxkey.persistence.service.RolesService;
 import org.dromara.maxkey.provision.thread.ProvisioningRunner;
 import org.dromara.maxkey.provision.thread.ProvisioningRunnerThread;
 import org.dromara.maxkey.schedule.ScheduleAdapterBuilder;
@@ -85,6 +87,23 @@ public class MaxKeyMgtListenerConfig  {
         logger.debug("DynamicGroups ListenerAdapter inited .");
         return "dynamicGroupsListenerAdapter";
     }
+    
+    @Bean
+    String dynamicRolesListenerAdapter(
+            Scheduler scheduler,
+            RolesService rolesService,
+            @Value("${maxkey.job.cron.schedule}") String cronSchedule
+    ) throws SchedulerException {
+    	new ScheduleAdapterBuilder()
+			.setScheduler(scheduler)
+			.setCron(cronSchedule)
+			.setJobClass(DynamicRolesListenerAdapter.class)
+			.setJobData("rolesService",rolesService)
+			.build();
+
+        logger.debug("Dynamic Roles ListenerAdapter inited .");
+        return "dynamicRolesListenerAdapter";
+    }
 
     @Bean
     String provisioningRunnerThread(

+ 68 - 0
maxkey-webs/maxkey-web-mgt/src/main/java/org/dromara/maxkey/listener/DynamicRolesListenerAdapter.java

@@ -0,0 +1,68 @@
+/*
+ * Copyright [2024] [MaxKey of copyright http://www.maxkey.top]
+ * 
+ * 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 org.dromara.maxkey.listener;
+
+import java.io.Serializable;
+
+import org.dromara.maxkey.persistence.service.RolesService;
+import org.dromara.maxkey.schedule.ScheduleAdapter;
+import org.quartz.Job;
+import org.quartz.JobExecutionContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class DynamicRolesListenerAdapter extends ScheduleAdapter  implements Job , Serializable {
+	/**
+	 * 
+	 */
+	private static final long serialVersionUID = 7000735366821127880L;
+
+	static final  Logger logger = LoggerFactory.getLogger(DynamicRolesListenerAdapter.class);
+    
+    transient RolesService rolesService;
+
+    @Override
+    public void execute(JobExecutionContext context){
+        if(jobStatus == JOBSTATUS.RUNNING) {return;}
+        
+        init(context);
+        
+        logger.debug("running ... " );
+        jobStatus = JOBSTATUS.RUNNING;
+        try {
+            if(rolesService != null) {
+            	rolesService.refreshAllDynamicRoles();
+            	Thread.sleep(10 * 1000);//10 minutes
+            }
+            logger.debug("finished  " );
+            jobStatus = JOBSTATUS.FINISHED;
+        }catch(Exception e) {
+            jobStatus = JOBSTATUS.ERROR;
+            logger.error("Exception " ,e);
+        }
+    }
+
+    @Override
+	protected void init(JobExecutionContext context){
+    	super.init(context);
+    	if(rolesService == null) {
+    		rolesService = getParameter("rolesService",RolesService.class);
+        }
+    }
+
+}