This is an automated email from the ASF dual-hosted git repository.

arshad pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/seatunnel-web.git


The following commit(s) were added to refs/heads/main by this push:
     new b343fdf7 [Feature] Add Support for Authorization (#285)
b343fdf7 is described below

commit b343fdf742df2954b06ffd53ed3dc93b7a470c7e
Author: Mohammad Arshad <ars...@apache.org>
AuthorDate: Fri Apr 11 15:11:25 2025 +0530

    [Feature] Add Support for Authorization (#285)
---
 pom.xml                                            |   1 +
 seatunnel-server/seatunnel-app/pom.xml             |   5 +
 .../src/main/bin/seatunnel-backend-daemon.sh       |   9 +-
 .../seatunnel/app/adapter/SeatunnelWebAdapter.java |   3 +
 .../app/controller/JobConfigController.java        |   4 +-
 .../seatunnel/app/dal/mapper/JobLineMapper.java    |   2 -
 .../seatunnel/app/dal/mapper/UserMapper.java       |   2 +
 .../app/interceptor/AuthenticationInterceptor.java |   8 +-
 .../app/permission/ISeatunnelPermissonService.java |  60 --
 .../SeatunnelAccessControllerConfig.java           |  45 ++
 .../SeatunnelAccessControllerDefaultImpl.java      |  45 ++
 .../permission/SeatunnelPermissionServiceImpl.java |  61 --
 .../apache/seatunnel/app/security/UserContext.java |   3 +-
 .../seatunnel/app/security/UserContextHolder.java  |   6 +
 .../seatunnel/app/service/IJobConfigService.java   |   6 +-
 .../app/service/ISeatunnelBaseService.java         |  19 +-
 .../seatunnel/app/service/WorkspaceService.java    |   2 -
 .../app/service/impl/DatasourceServiceImpl.java    | 109 ++-
 .../app/service/impl/JobConfigServiceImpl.java     |  26 +-
 .../app/service/impl/JobDefinitionServiceImpl.java |  53 +-
 .../app/service/impl/JobInstanceServiceImpl.java   |  11 +-
 .../seatunnel/app/service/impl/JobServiceImpl.java |  20 +-
 .../app/service/impl/SeatunnelBaseServiceImpl.java |  38 +-
 .../app/service/impl/TaskInstanceServiceImpl.java  |  26 +-
 .../app/service/impl/UserServiceImpl.java          |  41 +-
 .../app/service/impl/VirtualTableServiceImpl.java  |  52 +-
 .../app/service/impl/WorkspaceServiceImpl.java     |  48 +-
 .../app/utils/GlobalExceptionHandler.java          |   6 +
 .../src/main/resources/application.yml             |   1 +
 .../server/common/SeatunnelErrorEnum.java          |   3 +-
 seatunnel-web-common/pom.xml                       |  25 +
 .../common/access/AccessDeniedException.java       |  27 +-
 .../apache/seatunnel/common/access/AccessInfo.java |  18 +-
 .../apache/seatunnel/common/access/AccessType.java |  22 +-
 .../seatunnel/common/access/ResourceType.java      |  23 +-
 .../common/access/SeatunnelAccessController.java   |  30 +-
 .../app/common/AccessControllerTestingImp.java     | 105 +++
 .../app/common/ResourcePermissionData.java         |  14 +-
 .../controller/JobDefinitionControllerWrapper.java |  11 +
 .../SeatunnelDatasourceControllerWrapper.java      |  23 +
 .../app/test/SeatunnelAccessControllerTest.java    | 790 +++++++++++++++++++++
 .../src/test/resources/application.yml             |   1 +
 42 files changed, 1420 insertions(+), 384 deletions(-)

diff --git a/pom.xml b/pom.xml
index 852f2f30..7be25220 100644
--- a/pom.xml
+++ b/pom.xml
@@ -33,6 +33,7 @@
     <description>Production ready big data processing product based on Apache 
Spark and Apache Flink.</description>
 
     <modules>
+        <module>seatunnel-web-common</module>
         <module>seatunnel-server</module>
         <module>seatunnel-datasource</module>
         <module>seatunnel-web-dist</module>
diff --git a/seatunnel-server/seatunnel-app/pom.xml 
b/seatunnel-server/seatunnel-app/pom.xml
index 98d93670..f6ab19e4 100644
--- a/seatunnel-server/seatunnel-app/pom.xml
+++ b/seatunnel-server/seatunnel-app/pom.xml
@@ -45,6 +45,11 @@
             <groupId>org.apache.seatunnel</groupId>
             <artifactId>seatunnel-common</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.apache.seatunnel</groupId>
+            <artifactId>seatunnel-web-common</artifactId>
+            <version>${project.version}</version>
+        </dependency>
         <dependency>
             <groupId>org.apache.seatunnel</groupId>
             <artifactId>seatunnel-api</artifactId>
diff --git 
a/seatunnel-server/seatunnel-app/src/main/bin/seatunnel-backend-daemon.sh 
b/seatunnel-server/seatunnel-app/src/main/bin/seatunnel-backend-daemon.sh
index 98506c8d..582fcb46 100755
--- a/seatunnel-server/seatunnel-app/src/main/bin/seatunnel-backend-daemon.sh
+++ b/seatunnel-server/seatunnel-app/src/main/bin/seatunnel-backend-daemon.sh
@@ -54,9 +54,14 @@ start() {
   fi
 
   echo "$WORKDIR"
+  CLASSPATH="$WORKDIR/../conf:$WORKDIR/../libs/*:$WORKDIR/../datasource/*"
+  if [ -d "$WORKDIR/../ranger-seatunnel-plugin" ]; then
+  CLASSPATH="$CLASSPATH:$WORKDIR/../ranger-seatunnel-plugin/lib/*.jar"
+  
CLASSPATH="$CLASSPATH:$WORKDIR/../ranger-seatunnel-plugin/lib/ranger-seatunnel-plugin-impl/*"
+  fi
+
   nohup $JAVA_HOME/bin/java $JAVA_OPTS \
-  -cp "$WORKDIR/../conf":"$WORKDIR/../libs/*":"$WORKDIR/../datasource/*" \
-  $SPRING_OPTS \
+  -cp "$CLASSPATH" $SPRING_OPTS \
   org.apache.seatunnel.app.SeatunnelApplication >> "${LOGDIR}/seatunnel.out" 
2>&1 &
   echo "seatunnel-web started"
 }
diff --git 
a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/adapter/SeatunnelWebAdapter.java
 
b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/adapter/SeatunnelWebAdapter.java
index a20f5a8f..0974e456 100644
--- 
a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/adapter/SeatunnelWebAdapter.java
+++ 
b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/adapter/SeatunnelWebAdapter.java
@@ -42,6 +42,8 @@ public class SeatunnelWebAdapter implements WebMvcConfigurer {
     public static final String LOGIN_INTERCEPTOR_PATH_PATTERN = "/**/*";
     public static final String LOGIN_PATH_PATTERN = 
"/seatunnel/api/v1/user/login**";
     public static final String REGISTER_PATH_PATTERN = "/users/register";
+    private static final String RESOURCE_NAME_PATH_PATTERN =
+            "/seatunnel/api/v1/resources/workspace";
 
     @Bean
     public AuthenticationInterceptor authenticationInterceptor() {
@@ -74,6 +76,7 @@ public class SeatunnelWebAdapter implements WebMvcConfigurer {
                 .excludePathPatterns(
                         LOGIN_PATH_PATTERN,
                         REGISTER_PATH_PATTERN,
+                        RESOURCE_NAME_PATH_PATTERN,
                         "/swagger-resources/**",
                         "/webjars/**",
                         "/v2/**",
diff --git 
a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/controller/JobConfigController.java
 
b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/controller/JobConfigController.java
index 2ec31541..cdce8f6e 100644
--- 
a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/controller/JobConfigController.java
+++ 
b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/controller/JobConfigController.java
@@ -46,7 +46,7 @@ public class JobConfigController {
             @ApiParam(value = "jobVersionId", required = true) @PathVariable 
long jobVersionId,
             @ApiParam(value = "jobConfig", required = true) @RequestBody 
JobConfig jobConfig)
             throws JsonProcessingException {
-        jobConfigService.updateJobConfig(jobVersionId, jobConfig);
+        jobConfigService.updateJobConfig(jobVersionId, jobConfig, false);
         return Result.success();
     }
 
@@ -55,6 +55,6 @@ public class JobConfigController {
     Result<JobConfigRes> getJobConfig(
             @ApiParam(value = "jobVersionId", required = true) @PathVariable 
long jobVersionId)
             throws JsonProcessingException {
-        return Result.success(jobConfigService.getJobConfig(jobVersionId));
+        return Result.success(jobConfigService.getJobConfig(jobVersionId, 
false));
     }
 }
diff --git 
a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/mapper/JobLineMapper.java
 
b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/mapper/JobLineMapper.java
index 9317520a..479f2749 100644
--- 
a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/mapper/JobLineMapper.java
+++ 
b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/mapper/JobLineMapper.java
@@ -27,7 +27,5 @@ import java.util.List;
 
 public interface JobLineMapper extends BaseMapper<JobLine> {
 
-    void deleteLinesByVersionId(@Param("versionId") long jobVersionId);
-
     void insertBatchLines(@Param("lines") List<JobLine> lines);
 }
diff --git 
a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/mapper/UserMapper.java
 
b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/mapper/UserMapper.java
index 9648ecd9..ff8131bd 100644
--- 
a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/mapper/UserMapper.java
+++ 
b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/mapper/UserMapper.java
@@ -49,4 +49,6 @@ public interface UserMapper {
             @Param("authProvider") String authProvider);
 
     List<User> queryEnabledUsers();
+
+    List<String> queryUserNames(@Param("searchName") String searchName);
 }
diff --git 
a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/interceptor/AuthenticationInterceptor.java
 
b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/interceptor/AuthenticationInterceptor.java
index 07ccf566..78ee6a85 100644
--- 
a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/interceptor/AuthenticationInterceptor.java
+++ 
b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/interceptor/AuthenticationInterceptor.java
@@ -23,6 +23,7 @@ import org.apache.seatunnel.app.dal.entity.User;
 import org.apache.seatunnel.app.dal.entity.UserLoginLog;
 import org.apache.seatunnel.app.security.JwtUtils;
 import org.apache.seatunnel.app.security.UserContext;
+import org.apache.seatunnel.common.access.AccessInfo;
 
 import org.apache.commons.lang3.StringUtils;
 
@@ -106,7 +107,12 @@ public class AuthenticationInterceptor implements 
HandlerInterceptor {
         UserContext userContext = new UserContext();
         userContext.setUser(user);
         userContext.setWorkspaceId(workspaceIdFromToken);
-        userContext.setWorkspaceName((String) map.get("workspaceName"));
+
+        AccessInfo accessInfo = new AccessInfo();
+        accessInfo.setUsername(user.getUsername());
+        accessInfo.setWorkspaceName((String) map.get("workspaceName"));
+        userContext.setAccessInfo(accessInfo);
+
         request.setAttribute(Constants.SESSION_USER_CONTEXT, userContext);
 
         request.setAttribute("userId", userId);
diff --git 
a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/permission/ISeatunnelPermissonService.java
 
b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/permission/ISeatunnelPermissonService.java
deleted file mode 100644
index 11d1eae0..00000000
--- 
a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/permission/ISeatunnelPermissonService.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.apache.seatunnel.app.permission;
-
-import java.util.List;
-
-public interface ISeatunnelPermissonService {
-
-    /**
-     * func permission check
-     *
-     * @param permissionKey permissionKey
-     * @param userId userId
-     */
-    void funcPermissionCheck(String permissionKey, int userId);
-
-    /**
-     * func permission and resource permission check
-     *
-     * @param permissionKey permissionKey
-     * @param resourceType resourceType
-     * @param resourceCodes resourceCodes
-     * @param userId userId
-     */
-    void funcAndResourcePermissionCheck(
-            String permissionKey, String resourceType, List<Object> 
resourceCodes, int userId);
-
-    /**
-     * resource post handle
-     *
-     * @param resourceType resourceType
-     * @param resourceCodes resourceCodes
-     * @param userId userId
-     */
-    void resourcePostHandle(String resourceType, List<Object> resourceCodes, 
int userId);
-
-    /**
-     * available resource range
-     *
-     * @param resourceType resourceType
-     * @param userId userId
-     * @return list
-     */
-    List<Object> availableResourceRange(String resourceType, int userId);
-}
diff --git 
a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/permission/SeatunnelAccessControllerConfig.java
 
b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/permission/SeatunnelAccessControllerConfig.java
new file mode 100644
index 00000000..61576a82
--- /dev/null
+++ 
b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/permission/SeatunnelAccessControllerConfig.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.seatunnel.app.permission;
+
+import org.apache.seatunnel.common.access.SeatunnelAccessController;
+
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class SeatunnelAccessControllerConfig {
+
+    @Value(
+            
"${seatunnel-web.access-controller-class:org.apache.seatunnel.app.permission.SeatunnelAccessControllerDefaultImpl
 org.apache.seatunnel.app.permission.DefaultSeatunnelAccessController}")
+    private String accessControllerClassName;
+
+    @Bean
+    public SeatunnelAccessController seatunnelAccessController() {
+        try {
+            Class<?> clazz = Class.forName(accessControllerClassName);
+            return (SeatunnelAccessController) 
clazz.getDeclaredConstructor().newInstance();
+        } catch (Exception e) {
+            throw new IllegalStateException(
+                    "Failed to create SeatunnelAccessController instance for 
class: "
+                            + accessControllerClassName,
+                    e);
+        }
+    }
+}
diff --git 
a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/permission/SeatunnelAccessControllerDefaultImpl.java
 
b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/permission/SeatunnelAccessControllerDefaultImpl.java
new file mode 100644
index 00000000..262be786
--- /dev/null
+++ 
b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/permission/SeatunnelAccessControllerDefaultImpl.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.seatunnel.app.permission;
+
+import org.apache.seatunnel.common.access.AccessInfo;
+import org.apache.seatunnel.common.access.AccessType;
+import org.apache.seatunnel.common.access.ResourceType;
+import org.apache.seatunnel.common.access.SeatunnelAccessController;
+
+public class SeatunnelAccessControllerDefaultImpl implements 
SeatunnelAccessController {
+
+    @Override
+    public void authorizeAccess(
+            String resourceName,
+            ResourceType resourceType,
+            AccessType accessType,
+            AccessInfo accessInfo) {
+        // Default implementation: Allow all access
+        // You can add your custom logic here
+    }
+
+    @Override
+    public boolean hasPermission(
+            String resourceName,
+            ResourceType resourceType,
+            AccessType accessType,
+            AccessInfo accessInfo) {
+        return true;
+    }
+}
diff --git 
a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/permission/SeatunnelPermissionServiceImpl.java
 
b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/permission/SeatunnelPermissionServiceImpl.java
deleted file mode 100644
index d97d2019..00000000
--- 
a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/permission/SeatunnelPermissionServiceImpl.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.apache.seatunnel.app.permission;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Component;
-
-import java.util.List;
-
-@Component
-public class SeatunnelPermissionServiceImpl implements 
ISeatunnelPermissonService {
-
-    private static final Logger LOGGER =
-            LoggerFactory.getLogger(SeatunnelPermissionServiceImpl.class);
-
-    @Autowired private AvailableResourceRangeService 
availableResourceRangeService;
-
-    @Override
-    public void funcPermissionCheck(String permissionKey, int userId) {
-        // user id will be replaced by shiro in ws when user id == 0
-        LOGGER.warn("func permission check in seatunnel");
-    }
-
-    @Override
-    public void funcAndResourcePermissionCheck(
-            String permissionKey, String sourceType, List<Object> sourceCodes, 
int userId) {
-        // user id will be replaced by shiro in ws when user id == 0
-        LOGGER.warn("func and resource permission check in seatunnel");
-    }
-
-    @Override
-    public void resourcePostHandle(String sourceType, List<Object> 
sourceCodes, int userId) {
-        // user id will be replaced by shiro in ws when user id == 0
-        LOGGER.warn("resource post handle in seatunnel");
-    }
-
-    @Override
-    public List<Object> availableResourceRange(String sourceType, int userId) {
-        // user id will be replaced by shiro in ws when user id == 0
-        LOGGER.warn("query available resource range in seatunnel");
-        return 
availableResourceRangeService.queryAvailableResourceRangeBySourceType(
-                sourceType, userId);
-    }
-}
diff --git 
a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/security/UserContext.java
 
b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/security/UserContext.java
index 8897779a..7857b1fc 100644
--- 
a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/security/UserContext.java
+++ 
b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/security/UserContext.java
@@ -17,6 +17,7 @@
 package org.apache.seatunnel.app.security;
 
 import org.apache.seatunnel.app.dal.entity.User;
+import org.apache.seatunnel.common.access.AccessInfo;
 
 import lombok.AllArgsConstructor;
 import lombok.Data;
@@ -28,5 +29,5 @@ import lombok.NoArgsConstructor;
 public class UserContext {
     User user;
     Long workspaceId;
-    String workspaceName;
+    AccessInfo accessInfo;
 }
diff --git 
a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/security/UserContextHolder.java
 
b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/security/UserContextHolder.java
index bd6eb5c9..e23bc2ee 100644
--- 
a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/security/UserContextHolder.java
+++ 
b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/security/UserContextHolder.java
@@ -17,6 +17,7 @@
 package org.apache.seatunnel.app.security;
 
 import org.apache.seatunnel.app.dal.entity.User;
+import org.apache.seatunnel.common.access.AccessInfo;
 
 public class UserContextHolder {
     private static final ThreadLocal<UserContext> userContextHolder = new 
ThreadLocal<>();
@@ -30,6 +31,11 @@ public class UserContextHolder {
         return userContext.getUser();
     }
 
+    public static AccessInfo getAccessInfo() {
+        UserContext userContext = getUserContext();
+        return userContext.getAccessInfo();
+    }
+
     public static UserContext getUserContext() {
         UserContext userContext = userContextHolder.get();
         if (userContext == null) {
diff --git 
a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/service/IJobConfigService.java
 
b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/service/IJobConfigService.java
index 23891174..ee238f8c 100644
--- 
a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/service/IJobConfigService.java
+++ 
b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/service/IJobConfigService.java
@@ -22,7 +22,9 @@ import 
org.apache.seatunnel.app.domain.response.job.JobConfigRes;
 import com.fasterxml.jackson.core.JsonProcessingException;
 
 public interface IJobConfigService {
-    JobConfigRes getJobConfig(long jobVersionIdId) throws 
JsonProcessingException;
+    JobConfigRes getJobConfig(long jobVersionIdId, boolean isPermissionChecked)
+            throws JsonProcessingException;
 
-    void updateJobConfig(long jobVersionId, JobConfig jobConfig) throws 
JsonProcessingException;
+    void updateJobConfig(long jobVersionId, JobConfig jobConfig, boolean 
isPermissionChecked)
+            throws JsonProcessingException;
 }
diff --git 
a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/service/ISeatunnelBaseService.java
 
b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/service/ISeatunnelBaseService.java
index aa7f38fa..0668f900 100644
--- 
a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/service/ISeatunnelBaseService.java
+++ 
b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/service/ISeatunnelBaseService.java
@@ -17,16 +17,23 @@
 
 package org.apache.seatunnel.app.service;
 
-import java.util.List;
+import org.apache.seatunnel.common.access.AccessInfo;
+import org.apache.seatunnel.common.access.AccessType;
+import org.apache.seatunnel.common.access.ResourceType;
 
 public interface ISeatunnelBaseService {
 
     void funcPermissionCheck(String permissionKey, int userId);
 
-    void funcAndResourcePermissionCheck(
-            String permissionKey, String resourceType, List resourceCodes, int 
userId);
+    void permissionCheck(
+            String resourceName,
+            ResourceType resourceType,
+            AccessType accessType,
+            AccessInfo accessInfo);
 
-    void resourcePostHandle(String sourceType, List resourceCodes, int userId);
-
-    List availableResourceRange(String resourceType, int userId);
+    boolean hasPermission(
+            String resourceName,
+            ResourceType resourceType,
+            AccessType accessType,
+            AccessInfo accessInfo);
 }
diff --git 
a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/service/WorkspaceService.java
 
b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/service/WorkspaceService.java
index 7b413f1a..b8f5b385 100644
--- 
a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/service/WorkspaceService.java
+++ 
b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/service/WorkspaceService.java
@@ -37,7 +37,5 @@ public interface WorkspaceService {
 
     Workspace getDefaultWorkspace();
 
-    Long getWorkspaceIdOrDefault(Long workspaceId);
-
     Long getWorkspaceIdOrCurrent(String workspaceName);
 }
diff --git 
a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/service/impl/DatasourceServiceImpl.java
 
b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/service/impl/DatasourceServiceImpl.java
index 2a0d790c..a55bcded 100644
--- 
a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/service/impl/DatasourceServiceImpl.java
+++ 
b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/service/impl/DatasourceServiceImpl.java
@@ -31,7 +31,7 @@ import 
org.apache.seatunnel.app.domain.response.datasource.DatasourceRes;
 import 
org.apache.seatunnel.app.domain.response.datasource.VirtualTableFieldRes;
 import org.apache.seatunnel.app.dynamicforms.FormStructure;
 import 
org.apache.seatunnel.app.permission.constants.SeatunnelFuncPermissionKeyConstant;
-import 
org.apache.seatunnel.app.permission.enums.SeatunnelResourcePermissionModuleEnum;
+import org.apache.seatunnel.app.security.UserContextHolder;
 import org.apache.seatunnel.app.service.IDatasourceService;
 import org.apache.seatunnel.app.service.IJobDefinitionService;
 import org.apache.seatunnel.app.service.ITableSchemaService;
@@ -39,6 +39,8 @@ import 
org.apache.seatunnel.app.thirdparty.datasource.DataSourceClientFactory;
 import 
org.apache.seatunnel.app.thirdparty.framework.SeaTunnelOptionRuleWrapper;
 import org.apache.seatunnel.app.utils.ConfigShadeUtil;
 import org.apache.seatunnel.app.utils.ServletUtils;
+import org.apache.seatunnel.common.access.AccessType;
+import org.apache.seatunnel.common.access.ResourceType;
 import org.apache.seatunnel.common.utils.JsonUtils;
 import org.apache.seatunnel.datasource.plugin.api.DataSourcePluginInfo;
 import org.apache.seatunnel.datasource.plugin.api.DatasourcePluginTypeEnum;
@@ -106,7 +108,7 @@ public class DatasourceServiceImpl extends 
SeatunnelBaseServiceImpl
             Map<String, String> datasourceConfig)
             throws CodeGenerateUtils.CodeGenerateException {
         Integer userId = ServletUtils.getCurrentUserId();
-        
funcPermissionCheck(SeatunnelFuncPermissionKeyConstant.DATASOURCE_CREATE, 
userId);
+        permCheck(datasourceName, AccessType.CREATE);
         long uuid = CodeGenerateUtils.getInstance().genCode();
         boolean unique = 
datasourceDao.checkDatasourceNameUnique(datasourceName, 0L);
         if (!unique) {
@@ -135,10 +137,6 @@ public class DatasourceServiceImpl extends 
SeatunnelBaseServiceImpl
                         .build();
         boolean success = datasourceDao.insertDatasource(datasource);
         if (success) {
-            resourcePostHandle(
-                    SeatunnelResourcePermissionModuleEnum.DATASOURCE.name(),
-                    Collections.singletonList(datasource.getId()),
-                    userId);
             return String.valueOf(uuid);
         }
         throw new 
SeatunnelException(SeatunnelErrorEnum.DATASOURCE_CREATE_FAILED);
@@ -150,11 +148,6 @@ public class DatasourceServiceImpl extends 
SeatunnelBaseServiceImpl
             String datasourceName,
             String description,
             Map<String, String> datasourceConfig) {
-        funcAndResourcePermissionCheck(
-                SeatunnelFuncPermissionKeyConstant.DATASOURCE_UPDATE,
-                SeatunnelResourcePermissionModuleEnum.DATASOURCE.name(),
-                Collections.singletonList(datasourceId),
-                ServletUtils.getCurrentUserId());
         if (datasourceId == null) {
             throw new SeatunnelException(
                     SeatunnelErrorEnum.DATASOURCE_PRAM_NOT_ALLOWED_NULL, 
"datasourceId");
@@ -172,6 +165,7 @@ public class DatasourceServiceImpl extends 
SeatunnelBaseServiceImpl
                         SeatunnelErrorEnum.DATASOURCE_NAME_ALREADY_EXISTS, 
datasourceName);
             }
         }
+        permCheck(datasource.getDatasourceName(), AccessType.UPDATE);
         datasource.setUpdateUserId(ServletUtils.getCurrentUserId());
         datasource.setUpdateTime(new Date());
         datasource.setDescription(description);
@@ -185,12 +179,6 @@ public class DatasourceServiceImpl extends 
SeatunnelBaseServiceImpl
 
     @Override
     public boolean deleteDatasource(Long datasourceId) {
-        // check role permission
-        funcAndResourcePermissionCheck(
-                SeatunnelFuncPermissionKeyConstant.DATASOURCE_DELETE,
-                SeatunnelResourcePermissionModuleEnum.DATASOURCE.name(),
-                Collections.singletonList(datasourceId),
-                ServletUtils.getCurrentUserId());
         // check has job task has used this datasource
         List<JobTask> jobTaskList = 
jobTaskDao.getJobTaskByDataSourceId(datasourceId);
         if (!CollectionUtils.isEmpty(jobTaskList)) {
@@ -204,6 +192,11 @@ public class DatasourceServiceImpl extends 
SeatunnelBaseServiceImpl
         if 
(!jobDefinitionService.getJobVersionByDataSourceId(datasourceId).isEmpty()) {
             throw new 
SeatunnelException(SeatunnelErrorEnum.DATASOURCE_CAN_NOT_DELETE);
         }
+        Datasource datasource = 
datasourceDao.selectDatasourceById(datasourceId);
+        if (datasource == null) {
+            return true;
+        }
+        permCheck(datasource.getDatasourceName(), AccessType.DELETE);
         return datasourceDao.deleteDatasourceById(datasourceId);
     }
 
@@ -219,16 +212,12 @@ public class DatasourceServiceImpl extends 
SeatunnelBaseServiceImpl
 
     @Override
     public boolean testDatasourceConnectionAble(Long datasourceId) {
-        funcAndResourcePermissionCheck(
-                SeatunnelFuncPermissionKeyConstant.DATASOURCE_TEST_CONNECT,
-                SeatunnelResourcePermissionModuleEnum.DATASOURCE.name(),
-                Collections.singletonList(datasourceId),
-                ServletUtils.getCurrentUserId());
         Datasource datasource = 
datasourceDao.selectDatasourceById(datasourceId);
         if (datasource == null) {
             throw new SeatunnelException(
                     SeatunnelErrorEnum.DATASOURCE_NOT_FOUND, 
datasourceId.toString());
         }
+        permCheck(datasource.getDatasourceName(), AccessType.EXECUTE);
         String configJson = datasource.getDatasourceConfig();
         Map<String, String> datasourceConfig =
                 JsonUtils.toMap(configJson, String.class, String.class);
@@ -301,7 +290,6 @@ public class DatasourceServiceImpl extends 
SeatunnelBaseServiceImpl
     @Override
     public List<String> queryTableNames(
             String datasourceName, String databaseName, String filterName, 
Integer size) {
-        
funcPermissionCheck(SeatunnelFuncPermissionKeyConstant.DATASOURCE_TABLE, 0);
         Datasource datasource = 
datasourceDao.queryDatasourceByName(datasourceName);
         if (null == datasource) {
             throw new 
SeatunnelException(SeatunnelErrorEnum.DATASOURCE_NOT_FOUND, datasourceName);
@@ -323,7 +311,6 @@ public class DatasourceServiceImpl extends 
SeatunnelBaseServiceImpl
 
     @Override
     public List<String> queryTableNames(String datasourceName, String 
databaseName) {
-        
funcPermissionCheck(SeatunnelFuncPermissionKeyConstant.DATASOURCE_TABLE, 0);
         Datasource datasource = 
datasourceDao.queryDatasourceByName(datasourceName);
         if (null == datasource) {
             throw new 
SeatunnelException(SeatunnelErrorEnum.DATASOURCE_NOT_FOUND, datasourceName);
@@ -344,7 +331,6 @@ public class DatasourceServiceImpl extends 
SeatunnelBaseServiceImpl
     @Override
     public List<TableField> queryTableSchema(
             String datasourceName, String databaseName, String tableName) {
-        
funcPermissionCheck(SeatunnelFuncPermissionKeyConstant.DATASOURCE_TABLE_SCHEMA, 
0);
         Datasource datasource = 
datasourceDao.queryDatasourceByName(datasourceName);
         if (null == datasource) {
             throw new 
SeatunnelException(SeatunnelErrorEnum.DATASOURCE_NOT_FOUND, datasourceName);
@@ -399,18 +385,22 @@ public class DatasourceServiceImpl extends 
SeatunnelBaseServiceImpl
     @Override
     public PageInfo<DatasourceRes> queryDatasourceList(
             String searchVal, String pluginName, Integer pageNo, Integer 
pageSize) {
-        Integer userId = ServletUtils.getCurrentUserId();
-        
funcPermissionCheck(SeatunnelFuncPermissionKeyConstant.DATASOURCE_LIST, userId);
         Page<Datasource> page = new Page<>(pageNo, pageSize);
         PageInfo<DatasourceRes> pageInfo = new PageInfo<>();
-        List<Long> ids =
-                availableResourceRange(
-                        
SeatunnelResourcePermissionModuleEnum.DATASOURCE.name(), userId);
-        if (org.springframework.util.CollectionUtils.isEmpty(ids)) {
+        IPage<Datasource> datasourceWithoutAuthorization =
+                datasourceDao.selectDatasourceByParam(page, null, searchVal, 
pluginName);
+
+        List<Long> filteredIds =
+                datasourceWithoutAuthorization.getRecords().stream()
+                        .filter(datasource -> 
hasReadPerm(datasource.getDatasourceName()))
+                        .map(Datasource::getId)
+                        .collect(Collectors.toList());
+
+        if (org.springframework.util.CollectionUtils.isEmpty(filteredIds)) {
             return pageInfo;
         }
         IPage<Datasource> datasourcePage =
-                datasourceDao.selectDatasourceByParam(page, ids, searchVal, 
pluginName);
+                datasourceDao.selectDatasourceByParam(page, filteredIds, 
searchVal, pluginName);
         pageInfo = new PageInfo<>();
         pageInfo.setPageNo((int) datasourcePage.getPages());
         pageInfo.setPageSize((int) datasourcePage.getSize());
@@ -419,15 +409,6 @@ public class DatasourceServiceImpl extends 
SeatunnelBaseServiceImpl
             pageInfo.setData(new ArrayList<>());
             return pageInfo;
         }
-        List<Integer> userIds = new ArrayList<>();
-        datasourcePage
-                .getRecords()
-                .forEach(
-                        datasource -> {
-                            userIds.add(datasource.getCreateUserId());
-                            userIds.add(datasource.getUpdateUserId());
-                        });
-
         List<DatasourceRes> datasourceResList =
                 datasourcePage.getRecords().stream()
                         .map(
@@ -554,11 +535,6 @@ public class DatasourceServiceImpl extends 
SeatunnelBaseServiceImpl
         if (CollectionUtils.isEmpty(datasourceIds)) {
             return new ArrayList<>();
         }
-        funcAndResourcePermissionCheck(
-                SeatunnelFuncPermissionKeyConstant.DATASOURCE_DETAIL_LIST,
-                SeatunnelResourcePermissionModuleEnum.DATASOURCE.name(),
-                datasourceIds,
-                0);
         List<Long> datasourceIdsLong =
                 
datasourceIds.stream().map(Long::parseLong).collect(Collectors.toList());
         List<Datasource> datasourceList = 
datasourceDao.selectDatasourceByIds(datasourceIdsLong);
@@ -570,22 +546,13 @@ public class DatasourceServiceImpl extends 
SeatunnelBaseServiceImpl
         if (CollectionUtils.isEmpty(datasourceList)) {
             return new ArrayList<>();
         }
-        List<Integer> userIds = new ArrayList<>();
-        datasourceList.forEach(
-                datasource -> {
-                    if (null != datasource.getCreateUserId()) {
-                        userIds.add(datasource.getCreateUserId());
-                    }
-                    if (null != datasource.getUpdateUserId()) {
-                        userIds.add(datasource.getUpdateUserId());
-                    }
-                });
         List<DatasourceDetailRes> datasourceDetailResList = new ArrayList<>();
-
-        datasourceList.forEach(
-                datasource -> {
-                    
datasourceDetailResList.add(getDatasourceDetailRes(datasource));
-                });
+        datasourceList.stream()
+                .filter(datasource -> 
hasReadPerm(datasource.getDatasourceName()))
+                .forEach(
+                        datasource -> {
+                            
datasourceDetailResList.add(getDatasourceDetailRes(datasource));
+                        });
         return datasourceDetailResList;
     }
 
@@ -597,7 +564,7 @@ public class DatasourceServiceImpl extends 
SeatunnelBaseServiceImpl
 
     @Override
     public DatasourceDetailRes queryDatasourceDetailByDatasourceName(String 
datasourceName) {
-        
funcPermissionCheck(SeatunnelFuncPermissionKeyConstant.DATASOURCE_DETAIL, 0);
+        permCheck(datasourceName, AccessType.READ);
         Datasource datasource = 
datasourceDao.queryDatasourceByName(datasourceName);
         // @cc liuli
         if (null == datasource) {
@@ -627,11 +594,11 @@ public class DatasourceServiceImpl extends 
SeatunnelBaseServiceImpl
     @Override
     public DatasourceDetailRes queryDatasourceDetailById(String datasourceId) {
         long datasourceIdLong = Long.parseLong(datasourceId);
-        
funcPermissionCheck(SeatunnelFuncPermissionKeyConstant.DATASOURCE_DETAIL, 0);
         Datasource datasource = 
datasourceDao.selectDatasourceById(datasourceIdLong);
         if (null == datasource) {
             throw new 
SeatunnelException(SeatunnelErrorEnum.DATASOURCE_NOT_FOUND, datasourceId);
         }
+        permCheck(datasource.getDatasourceName(), AccessType.READ);
         return getDatasourceDetailRes(datasource);
     }
 
@@ -639,4 +606,20 @@ public class DatasourceServiceImpl extends 
SeatunnelBaseServiceImpl
     public void setApplicationContext(ApplicationContext applicationContext) 
throws BeansException {
         this.applicationContext = applicationContext;
     }
+
+    private void permCheck(String resourceName, AccessType accessType) {
+        permissionCheck(
+                resourceName,
+                ResourceType.DATASOURCE,
+                accessType,
+                UserContextHolder.getAccessInfo());
+    }
+
+    private boolean hasReadPerm(String resourceName) {
+        return hasPermission(
+                resourceName,
+                ResourceType.DATASOURCE,
+                AccessType.READ,
+                UserContextHolder.getAccessInfo());
+    }
 }
diff --git 
a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/service/impl/JobConfigServiceImpl.java
 
b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/service/impl/JobConfigServiceImpl.java
index 97bf1884..add8e3b0 100644
--- 
a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/service/impl/JobConfigServiceImpl.java
+++ 
b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/service/impl/JobConfigServiceImpl.java
@@ -22,9 +22,11 @@ import org.apache.seatunnel.app.dal.entity.JobDefinition;
 import org.apache.seatunnel.app.dal.entity.JobVersion;
 import org.apache.seatunnel.app.domain.request.job.JobConfig;
 import org.apache.seatunnel.app.domain.response.job.JobConfigRes;
-import 
org.apache.seatunnel.app.permission.constants.SeatunnelFuncPermissionKeyConstant;
+import org.apache.seatunnel.app.security.UserContextHolder;
 import org.apache.seatunnel.app.service.IJobConfigService;
 import org.apache.seatunnel.app.utils.ServletUtils;
+import org.apache.seatunnel.common.access.AccessType;
+import org.apache.seatunnel.common.access.ResourceType;
 import org.apache.seatunnel.common.constants.JobMode;
 import org.apache.seatunnel.common.utils.JsonUtils;
 import org.apache.seatunnel.server.common.SeatunnelErrorEnum;
@@ -48,14 +50,21 @@ public class JobConfigServiceImpl extends 
SeatunnelBaseServiceImpl implements IJ
     @Resource private IJobDefinitionDao jobDefinitionDao;
 
     @Override
-    public JobConfigRes getJobConfig(long jobVersionId) throws 
JsonProcessingException {
-        
funcPermissionCheck(SeatunnelFuncPermissionKeyConstant.JOB_CONFIG_DETAIL, 0);
+    public JobConfigRes getJobConfig(long jobVersionId, boolean 
isPermissionChecked)
+            throws JsonProcessingException {
         JobVersion jobVersion = jobVersionDao.getVersionById(jobVersionId);
         if (jobVersion == null) {
             throw new SeatunnelException(
                     SeatunnelErrorEnum.RESOURCE_NOT_FOUND, "job version not 
found.");
         }
         JobDefinition jobDefinition = 
jobDefinitionDao.getJob(jobVersion.getJobId());
+        if (!isPermissionChecked) {
+            permissionCheck(
+                    jobDefinition.getName(),
+                    ResourceType.JOB,
+                    AccessType.READ,
+                    UserContextHolder.getAccessInfo());
+        }
         JobConfigRes jobConfigRes = new JobConfigRes();
         jobConfigRes.setName(jobDefinition.getName());
         jobConfigRes.setId(jobVersion.getId());
@@ -70,15 +79,22 @@ public class JobConfigServiceImpl extends 
SeatunnelBaseServiceImpl implements IJ
 
     @Override
     @Transactional
-    public void updateJobConfig(long jobVersionId, JobConfig jobConfig)
+    public void updateJobConfig(long jobVersionId, JobConfig jobConfig, 
boolean isPermissionChecked)
             throws JsonProcessingException {
         Integer userId = ServletUtils.getCurrentUserId();
-        
funcPermissionCheck(SeatunnelFuncPermissionKeyConstant.JOB_CONFIG_UPDATE, 0);
         JobVersion version = jobVersionDao.getVersionById(jobVersionId);
         if (version == null) {
             throw new SeatunnelException(
                     SeatunnelErrorEnum.RESOURCE_NOT_FOUND, "job version not 
found.");
         }
+        JobDefinition existingJobDefinition = 
jobDefinitionDao.getJob(version.getJobId());
+        if (!isPermissionChecked && existingJobDefinition != null) {
+            permissionCheck(
+                    existingJobDefinition.getName(),
+                    ResourceType.JOB,
+                    AccessType.UPDATE,
+                    UserContextHolder.getAccessInfo());
+        }
         JobDefinition jobDefinition = new JobDefinition();
         jobDefinition.setId(version.getJobId());
         jobDefinition.setUpdateUserId(userId);
diff --git 
a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/service/impl/JobDefinitionServiceImpl.java
 
b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/service/impl/JobDefinitionServiceImpl.java
index 07c07125..915193a0 100644
--- 
a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/service/impl/JobDefinitionServiceImpl.java
+++ 
b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/service/impl/JobDefinitionServiceImpl.java
@@ -29,9 +29,11 @@ import 
org.apache.seatunnel.app.domain.request.job.DataSourceOption;
 import org.apache.seatunnel.app.domain.request.job.JobReq;
 import org.apache.seatunnel.app.domain.response.PageInfo;
 import org.apache.seatunnel.app.domain.response.job.JobDefinitionRes;
-import 
org.apache.seatunnel.app.permission.constants.SeatunnelFuncPermissionKeyConstant;
+import org.apache.seatunnel.app.security.UserContextHolder;
 import org.apache.seatunnel.app.service.IJobDefinitionService;
 import org.apache.seatunnel.app.utils.ServletUtils;
+import org.apache.seatunnel.common.access.AccessType;
+import org.apache.seatunnel.common.access.ResourceType;
 import org.apache.seatunnel.common.constants.JobMode;
 import org.apache.seatunnel.common.utils.JsonUtils;
 import org.apache.seatunnel.server.common.CodeGenerateUtils;
@@ -74,7 +76,7 @@ public class JobDefinitionServiceImpl extends 
SeatunnelBaseServiceImpl
     @Transactional
     public long createJob(JobReq jobReq) throws 
CodeGenerateUtils.CodeGenerateException {
         Integer userId = ServletUtils.getCurrentUserId();
-        
funcPermissionCheck(SeatunnelFuncPermissionKeyConstant.JOB_DEFINITION_CREATE, 
userId);
+        permCheck(jobReq.getName(), AccessType.CREATE);
         long uuid = CodeGenerateUtils.getInstance().genCode();
         jobDefinitionDao.add(
                 JobDefinition.builder()
@@ -111,7 +113,6 @@ public class JobDefinitionServiceImpl extends 
SeatunnelBaseServiceImpl
     @Override
     public PageInfo<JobDefinitionRes> getJob(
             String searchName, Integer pageNo, Integer pageSize, String 
jobMode) {
-        
funcPermissionCheck(SeatunnelFuncPermissionKeyConstant.JOB_DEFINITION_VIEW, 0);
         if (StringUtils.isNotEmpty(jobMode)) {
             try {
                 JobMode.valueOf(jobMode);
@@ -120,13 +121,27 @@ public class JobDefinitionServiceImpl extends 
SeatunnelBaseServiceImpl
                         SeatunnelErrorEnum.ILLEGAL_STATE, "Unsupported 
JobMode");
             }
         }
-        return jobDefinitionDao.getJob(searchName, pageNo, pageSize, jobMode);
+        PageInfo<JobDefinitionRes> job =
+                jobDefinitionDao.getJob(searchName, pageNo, pageSize, jobMode);
+        if (CollectionUtils.isEmpty(job.getData())) {
+            return job;
+        }
+
+        List<JobDefinitionRes> filteredJobs =
+                job.getData().stream()
+                        .filter(jobDefinitionRes -> 
hasReadPerm(jobDefinitionRes.getName()))
+                        .collect(Collectors.toList());
+
+        PageInfo<JobDefinitionRes> jobs = new PageInfo<>();
+        jobs.setData(filteredJobs);
+        jobs.setPageSize(pageSize);
+        jobs.setPageNo(pageNo);
+        jobs.setTotalCount(filteredJobs.size());
+        return jobs;
     }
 
     @Override
     public Map<Long, String> getJob(@NonNull String name) {
-
-        
funcPermissionCheck(SeatunnelFuncPermissionKeyConstant.JOB_DEFINITION_VIEW, 0);
         List<JobDefinition> job = jobDefinitionDao.getJobList(name);
         if (CollectionUtils.isEmpty(job)) {
             return new HashMap<>();
@@ -135,7 +150,9 @@ public class JobDefinitionServiceImpl extends 
SeatunnelBaseServiceImpl
         Map<Long, String> jobDefineMap = new HashMap<>();
         job.forEach(
                 jobDefine -> {
-                    jobDefineMap.put(jobDefine.getId(), jobDefine.getName());
+                    if (hasReadPerm(jobDefine.getName())) {
+                        jobDefineMap.put(jobDefine.getId(), 
jobDefine.getName());
+                    }
                 });
 
         return jobDefineMap;
@@ -143,8 +160,11 @@ public class JobDefinitionServiceImpl extends 
SeatunnelBaseServiceImpl
 
     @Override
     public JobDefinition getJobDefinitionByJobId(long jobId) {
-        
funcPermissionCheck(SeatunnelFuncPermissionKeyConstant.JOB_DEFINITION_DETAIL, 
0);
-        return jobDefinitionDao.getJob(jobId);
+        JobDefinition job = jobDefinitionDao.getJob(jobId);
+        if (null != job) {
+            permCheck(job.getName(), AccessType.READ);
+        }
+        return job;
     }
 
     @Override
@@ -179,7 +199,20 @@ public class JobDefinitionServiceImpl extends 
SeatunnelBaseServiceImpl
 
     @Override
     public void deleteJob(long id) {
-        
funcPermissionCheck(SeatunnelFuncPermissionKeyConstant.JOB_DEFINITION_DELETE, 
0);
+        JobDefinition job = jobDefinitionDao.getJob(id);
+        if (job != null) {
+            permCheck(job.getName(), AccessType.DELETE);
+        }
         jobDefinitionDao.delete(id);
     }
+
+    private void permCheck(String resourceName, AccessType accessType) {
+        permissionCheck(
+                resourceName, ResourceType.JOB, accessType, 
UserContextHolder.getAccessInfo());
+    }
+
+    private boolean hasReadPerm(String resourceName) {
+        return hasPermission(
+                resourceName, ResourceType.JOB, AccessType.READ, 
UserContextHolder.getAccessInfo());
+    }
 }
diff --git 
a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/service/impl/JobInstanceServiceImpl.java
 
b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/service/impl/JobInstanceServiceImpl.java
index cd453048..d0db526f 100644
--- 
a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/service/impl/JobInstanceServiceImpl.java
+++ 
b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/service/impl/JobInstanceServiceImpl.java
@@ -55,6 +55,7 @@ import 
org.apache.seatunnel.app.domain.response.datasource.DatasourceDetailRes;
 import 
org.apache.seatunnel.app.domain.response.datasource.VirtualTableDetailRes;
 import org.apache.seatunnel.app.domain.response.executor.JobExecutorRes;
 import 
org.apache.seatunnel.app.permission.constants.SeatunnelFuncPermissionKeyConstant;
+import org.apache.seatunnel.app.security.UserContextHolder;
 import org.apache.seatunnel.app.service.IDatasourceService;
 import org.apache.seatunnel.app.service.IJobInstanceService;
 import org.apache.seatunnel.app.service.IJobMetricsService;
@@ -65,6 +66,8 @@ import org.apache.seatunnel.app.utils.ConfigShadeUtil;
 import org.apache.seatunnel.app.utils.JobUtils;
 import org.apache.seatunnel.app.utils.SeaTunnelConfigUtil;
 import org.apache.seatunnel.app.utils.ServletUtils;
+import org.apache.seatunnel.common.access.AccessType;
+import org.apache.seatunnel.common.access.ResourceType;
 import org.apache.seatunnel.common.constants.PluginType;
 import org.apache.seatunnel.common.utils.ExceptionUtils;
 import org.apache.seatunnel.common.utils.JsonUtils;
@@ -137,12 +140,17 @@ public class JobInstanceServiceImpl extends 
SeatunnelBaseServiceImpl
     public JobExecutorRes createExecuteResource(
             @NonNull Long jobDefineId, JobExecParam executeParam) {
         int userId = ServletUtils.getCurrentUserId();
-        
funcPermissionCheck(SeatunnelFuncPermissionKeyConstant.JOB_EXECUTOR_RESOURCE, 
userId);
         log.info(
                 "receive createExecuteResource request, userId:{}, 
jobDefineId:{}",
                 userId,
                 jobDefineId);
         JobDefinition job = jobDefinitionDao.getJob(jobDefineId);
+        permissionCheck(
+                job.getName(),
+                ResourceType.JOB,
+                AccessType.EXECUTE,
+                UserContextHolder.getAccessInfo());
+
         JobVersion latestVersion = jobVersionDao.getLatestVersion(job.getId());
         JobInstance jobInstance = new JobInstance();
         String jobConfig = createJobConfig(latestVersion, executeParam);
@@ -370,7 +378,6 @@ public class JobInstanceServiceImpl extends 
SeatunnelBaseServiceImpl
     public void complete(
             @NonNull Long jobInstanceId, @NonNull String jobEngineId, 
JobResult jobResult) {
         int userId = ServletUtils.getCurrentUserId();
-        
funcPermissionCheck(SeatunnelFuncPermissionKeyConstant.JOB_EXECUTOR_COMPLETE, 
userId);
         JobInstance jobInstance = 
jobInstanceDao.getJobInstanceMapper().selectById(jobInstanceId);
         jobMetricsService.syncJobDataToDb(jobInstance, jobEngineId);
         jobInstance.setJobStatus(jobResult.getStatus());
diff --git 
a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/service/impl/JobServiceImpl.java
 
b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/service/impl/JobServiceImpl.java
index 8a2620f5..8838d1e2 100644
--- 
a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/service/impl/JobServiceImpl.java
+++ 
b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/service/impl/JobServiceImpl.java
@@ -26,10 +26,13 @@ import 
org.apache.seatunnel.app.domain.request.job.JobTaskInfo;
 import org.apache.seatunnel.app.domain.request.job.PluginConfig;
 import org.apache.seatunnel.app.domain.response.job.JobConfigRes;
 import org.apache.seatunnel.app.domain.response.job.JobRes;
+import org.apache.seatunnel.app.security.UserContextHolder;
 import org.apache.seatunnel.app.service.IJobConfigService;
 import org.apache.seatunnel.app.service.IJobDefinitionService;
 import org.apache.seatunnel.app.service.IJobService;
 import org.apache.seatunnel.app.service.IJobTaskService;
+import org.apache.seatunnel.common.access.AccessType;
+import org.apache.seatunnel.common.access.ResourceType;
 import org.apache.seatunnel.common.constants.JobMode;
 import org.apache.seatunnel.server.common.CodeGenerateUtils;
 import org.apache.seatunnel.server.common.ParamValidationException;
@@ -61,6 +64,11 @@ public class JobServiceImpl extends SeatunnelBaseServiceImpl 
implements IJobServ
     @Override
     @Transactional
     public long createJob(JobCreateReq jobCreateRequest) throws 
JsonProcessingException {
+        permissionCheck(
+                jobCreateRequest.getJobConfig().getName(),
+                ResourceType.JOB,
+                AccessType.CREATE,
+                UserContextHolder.getAccessInfo());
         JobReq jobDefinition = 
getJobDefinition(jobCreateRequest.getJobConfig());
         long jobId = jobService.createJob(jobDefinition);
         createTasks(jobCreateRequest, jobId);
@@ -90,7 +98,7 @@ public class JobServiceImpl extends SeatunnelBaseServiceImpl 
implements IJobServ
                 pluginNameVsPluginId.put(pluginIdKey, newPluginId);
             }
         }
-        jobConfigService.updateJobConfig(jobId, 
jobCreateRequest.getJobConfig());
+        jobConfigService.updateJobConfig(jobId, 
jobCreateRequest.getJobConfig(), true);
         JobDAG jobDAG = jobCreateRequest.getJobDAG();
         // Replace the plugin name with plugin id
         List<Edge> edges = jobDAG.getEdges();
@@ -136,13 +144,21 @@ public class JobServiceImpl extends 
SeatunnelBaseServiceImpl implements IJobServ
     @Override
     public void updateJob(long jobVersionId, JobCreateReq jobCreateReq)
             throws JsonProcessingException {
+        JobConfigRes jobConfig = jobConfigService.getJobConfig(jobVersionId, 
true);
+        if (jobConfig != null) {
+            permissionCheck(
+                    jobConfig.getName(),
+                    ResourceType.JOB,
+                    AccessType.UPDATE,
+                    UserContextHolder.getAccessInfo());
+        }
         jobTaskService.deleteTaskByVersionId(jobVersionId);
         createTasks(jobCreateReq, jobVersionId);
     }
 
     @Override
     public JobRes getJob(long jobVersionId) throws JsonProcessingException {
-        JobConfigRes jobConfig = jobConfigService.getJobConfig(jobVersionId);
+        JobConfigRes jobConfig = jobConfigService.getJobConfig(jobVersionId, 
false);
         JobTaskInfo taskConfig = jobTaskService.getTaskConfig(jobVersionId);
         return new JobRes(jobConfig, taskConfig.getPlugins(), new 
JobDAG(taskConfig.getEdges()));
     }
diff --git 
a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/service/impl/SeatunnelBaseServiceImpl.java
 
b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/service/impl/SeatunnelBaseServiceImpl.java
index d6341968..878458c3 100644
--- 
a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/service/impl/SeatunnelBaseServiceImpl.java
+++ 
b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/service/impl/SeatunnelBaseServiceImpl.java
@@ -16,38 +16,42 @@
  */
 package org.apache.seatunnel.app.service.impl;
 
-import org.apache.seatunnel.app.permission.ISeatunnelPermissonService;
 import org.apache.seatunnel.app.service.ISeatunnelBaseService;
+import org.apache.seatunnel.common.access.AccessInfo;
+import org.apache.seatunnel.common.access.AccessType;
+import org.apache.seatunnel.common.access.ResourceType;
+import org.apache.seatunnel.common.access.SeatunnelAccessController;
 
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
-import java.util.List;
+import javax.annotation.Resource;
 
 @Service
 public class SeatunnelBaseServiceImpl implements ISeatunnelBaseService {
-
-    @Autowired private ISeatunnelPermissonService iSeatunnelPermissonService;
+    @Resource private SeatunnelAccessController seatunnelAccessController;
 
     @Override
     public void funcPermissionCheck(String permissionKey, int userId) {
-        iSeatunnelPermissonService.funcPermissionCheck(permissionKey, userId);
-    }
-
-    @Override
-    public void funcAndResourcePermissionCheck(
-            String permissionKey, String resourceType, List resourceCodes, int 
userId) {
-        iSeatunnelPermissonService.funcAndResourcePermissionCheck(
-                permissionKey, resourceType, resourceCodes, userId);
+        // Placeholder method: To be removed after thorough analysis of all 
references and usages.
     }
 
     @Override
-    public void resourcePostHandle(String sourceType, List resourceCodes, int 
userId) {
-        iSeatunnelPermissonService.resourcePostHandle(sourceType, 
resourceCodes, userId);
+    public void permissionCheck(
+            String resourceName,
+            ResourceType resourceType,
+            AccessType accessType,
+            AccessInfo accessInfo) {
+        seatunnelAccessController.authorizeAccess(
+                resourceName, resourceType, accessType, accessInfo);
     }
 
     @Override
-    public List availableResourceRange(String resourceType, int userId) {
-        return iSeatunnelPermissonService.availableResourceRange(resourceType, 
userId);
+    public boolean hasPermission(
+            String resourceName,
+            ResourceType resourceType,
+            AccessType accessType,
+            AccessInfo accessInfo) {
+        return seatunnelAccessController.hasPermission(
+                resourceName, resourceType, accessType, accessInfo);
     }
 }
diff --git 
a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/service/impl/TaskInstanceServiceImpl.java
 
b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/service/impl/TaskInstanceServiceImpl.java
index f30ea239..778ee8ff 100644
--- 
a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/service/impl/TaskInstanceServiceImpl.java
+++ 
b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/service/impl/TaskInstanceServiceImpl.java
@@ -25,11 +25,14 @@ import org.apache.seatunnel.app.dal.entity.JobInstance;
 import org.apache.seatunnel.app.domain.dto.job.SeaTunnelJobInstanceDto;
 import org.apache.seatunnel.app.domain.response.executor.JobExecutionStatus;
 import org.apache.seatunnel.app.domain.response.metrics.JobSummaryMetricsRes;
+import org.apache.seatunnel.app.security.UserContextHolder;
 import org.apache.seatunnel.app.service.BaseService;
 import org.apache.seatunnel.app.service.IJobDefinitionService;
 import org.apache.seatunnel.app.service.IJobMetricsService;
 import org.apache.seatunnel.app.service.ITaskInstanceService;
 import org.apache.seatunnel.app.utils.PageInfo;
+import org.apache.seatunnel.common.access.AccessType;
+import org.apache.seatunnel.common.access.ResourceType;
 import org.apache.seatunnel.common.constants.JobMode;
 import org.apache.seatunnel.server.common.SeatunnelErrorEnum;
 import org.apache.seatunnel.server.common.SeatunnelException;
@@ -50,10 +53,12 @@ import java.util.Date;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.stream.Collectors;
 
 @Service
 @Slf4j
-public class TaskInstanceServiceImpl implements 
ITaskInstanceService<SeaTunnelJobInstanceDto> {
+public class TaskInstanceServiceImpl extends SeatunnelBaseServiceImpl
+        implements ITaskInstanceService<SeaTunnelJobInstanceDto> {
 
     @Autowired IJobInstanceDao jobInstanceDao;
 
@@ -88,13 +93,19 @@ public class TaskInstanceServiceImpl implements 
ITaskInstanceService<SeaTunnelJo
                         new Page<>(pageNo, pageSize), startDate, endDate, 
jobDefineName, jobMode);
 
         List<SeaTunnelJobInstanceDto> records = jobInstanceIPage.getRecords();
-        if (CollectionUtils.isEmpty(records)) {
+        List<SeaTunnelJobInstanceDto> filteredRecords =
+                records.stream()
+                        .filter(
+                                jobDefinitionRes ->
+                                        
hasReadPerm(jobDefinitionRes.getJobDefineName()))
+                        .collect(Collectors.toList());
+        if (CollectionUtils.isEmpty(filteredRecords)) {
             return result;
         }
-        addRunningTimeToResult(records);
-        jobPipelineSummaryMetrics(records, jobMode);
+        addRunningTimeToResult(filteredRecords);
+        jobPipelineSummaryMetrics(filteredRecords, jobMode);
         pageInfo.setTotal((int) jobInstanceIPage.getTotal());
-        pageInfo.setTotalList(records);
+        pageInfo.setTotalList(filteredRecords);
         result.setData(pageInfo);
         return result;
     }
@@ -215,4 +226,9 @@ public class TaskInstanceServiceImpl implements 
ITaskInstanceService<SeaTunnelJo
         jobInstanceDao.deleteById(jobInstanceId);
         return Result.success();
     }
+
+    private boolean hasReadPerm(String resourceName) {
+        return hasPermission(
+                resourceName, ResourceType.JOB, AccessType.READ, 
UserContextHolder.getAccessInfo());
+    }
 }
diff --git 
a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/service/impl/UserServiceImpl.java
 
b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/service/impl/UserServiceImpl.java
index 138ab4b5..2a47e299 100644
--- 
a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/service/impl/UserServiceImpl.java
+++ 
b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/service/impl/UserServiceImpl.java
@@ -34,6 +34,7 @@ import org.apache.seatunnel.app.domain.response.PageInfo;
 import org.apache.seatunnel.app.domain.response.user.AddUserRes;
 import org.apache.seatunnel.app.domain.response.user.UserSimpleInfoRes;
 import org.apache.seatunnel.app.security.JwtUtils;
+import org.apache.seatunnel.app.security.UserContextHolder;
 import 
org.apache.seatunnel.app.security.authentication.strategy.IAuthenticationStrategy;
 import 
org.apache.seatunnel.app.security.authentication.strategy.impl.DBAuthenticationStrategy;
 import 
org.apache.seatunnel.app.security.authentication.strategy.impl.LDAPAuthenticationStrategy;
@@ -42,6 +43,8 @@ import org.apache.seatunnel.app.service.IUserService;
 import org.apache.seatunnel.app.service.WorkspaceService;
 import org.apache.seatunnel.app.utils.PasswordUtils;
 import org.apache.seatunnel.app.utils.ServletUtils;
+import org.apache.seatunnel.common.access.AccessType;
+import org.apache.seatunnel.common.access.ResourceType;
 import org.apache.seatunnel.server.common.PageData;
 import org.apache.seatunnel.server.common.SeatunnelErrorEnum;
 import org.apache.seatunnel.server.common.SeatunnelException;
@@ -97,9 +100,9 @@ public class UserServiceImpl extends 
SeatunnelBaseServiceImpl implements IUserSe
     @Override
     @Transactional(rollbackFor = Exception.class)
     public AddUserRes add(AddUserReq addReq) {
+        permCheck(addReq.getUsername(), AccessType.CREATE);
         // 1. check duplicate user first
         userDaoImpl.checkUserExists(addReq.getUsername());
-
         // 2. add a new user.
         final UpdateUserDto dto =
                 UpdateUserDto.builder()
@@ -123,6 +126,7 @@ public class UserServiceImpl extends 
SeatunnelBaseServiceImpl implements IUserSe
 
     @Override
     public void update(UpdateUserReq updateReq) {
+        permCheck(updateReq.getUsername(), AccessType.UPDATE);
         final UpdateUserDto dto =
                 UpdateUserDto.builder()
                         .id(updateReq.getUserId())
@@ -145,6 +149,11 @@ public class UserServiceImpl extends 
SeatunnelBaseServiceImpl implements IUserSe
             throw new SeatunnelException(
                     SeatunnelErrorEnum.INVALID_OPERATION, "Can't delete 
yourself");
         }
+        User user = userDaoImpl.getById(id);
+        if (user == null) {
+            return;
+        }
+        permCheck(user.getUsername(), AccessType.DELETE);
         userDaoImpl.delete(id);
         roleServiceImpl.deleteByUserId(id);
     }
@@ -158,7 +167,10 @@ public class UserServiceImpl extends 
SeatunnelBaseServiceImpl implements IUserSe
                 userDaoImpl.list(dto, userListReq.getRealPageNo(), 
userListReq.getPageSize());
 
         final List<UserSimpleInfoRes> data =
-                
userPageData.getData().stream().map(this::translate).collect(Collectors.toList());
+                userPageData.getData().stream()
+                        .filter(user -> hasReadPerm(user.getUsername()))
+                        .map(this::translate)
+                        .collect(Collectors.toList());
         final PageInfo<UserSimpleInfoRes> pageInfo = new PageInfo<>();
         pageInfo.setPageNo(userListReq.getPageNo());
         pageInfo.setPageSize(userListReq.getPageSize());
@@ -170,12 +182,20 @@ public class UserServiceImpl extends 
SeatunnelBaseServiceImpl implements IUserSe
 
     @Override
     public void enable(int id) {
-        userDaoImpl.enable(id);
+        User user = userDaoImpl.getById(id);
+        if (user != null) {
+            permCheck(user.getUsername(), AccessType.UPDATE);
+            userDaoImpl.enable(id);
+        }
     }
 
     @Override
     public void disable(int id) {
-        userDaoImpl.disable(id);
+        User user = userDaoImpl.getById(id);
+        if (user != null) {
+            permCheck(user.getUsername(), AccessType.UPDATE);
+            userDaoImpl.disable(id);
+        }
     }
 
     @Override
@@ -224,4 +244,17 @@ public class UserServiceImpl extends 
SeatunnelBaseServiceImpl implements IUserSe
         info.setName(user.getUsername());
         return info;
     }
+
+    private void permCheck(String resourceName, AccessType accessType) {
+        permissionCheck(
+                resourceName, ResourceType.USER, accessType, 
UserContextHolder.getAccessInfo());
+    }
+
+    private boolean hasReadPerm(String resourceName) {
+        return hasPermission(
+                resourceName,
+                ResourceType.USER,
+                AccessType.READ,
+                UserContextHolder.getAccessInfo());
+    }
 }
diff --git 
a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/service/impl/VirtualTableServiceImpl.java
 
b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/service/impl/VirtualTableServiceImpl.java
index b3efb204..12e4ee41 100644
--- 
a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/service/impl/VirtualTableServiceImpl.java
+++ 
b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/service/impl/VirtualTableServiceImpl.java
@@ -33,6 +33,7 @@ import org.apache.seatunnel.app.dynamicforms.FormStructure;
 import 
org.apache.seatunnel.app.permission.constants.SeatunnelFuncPermissionKeyConstant;
 import org.apache.seatunnel.app.service.IJobDefinitionService;
 import org.apache.seatunnel.app.service.IVirtualTableService;
+import org.apache.seatunnel.app.service.WorkspaceService;
 import org.apache.seatunnel.app.thirdparty.datasource.DataSourceClientFactory;
 import 
org.apache.seatunnel.app.thirdparty.framework.SeaTunnelOptionRuleWrapper;
 import org.apache.seatunnel.app.utils.ServletUtils;
@@ -71,6 +72,8 @@ public class VirtualTableServiceImpl extends 
SeatunnelBaseServiceImpl
     @Resource(name = "datasourceDaoImpl")
     IDatasourceDao datasourceDao;
 
+    @Autowired private WorkspaceService workspaceService;
+
     @Autowired private ConnectorDataSourceMapperConfig dataSourceMapperConfig;
 
     @Override
@@ -328,53 +331,4 @@ public class VirtualTableServiceImpl extends 
SeatunnelBaseServiceImpl
         Long datasourceIdLong = Long.valueOf(datasourceId);
         return virtualTableDao.getVirtualDatabaseNames(datasourceIdLong);
     }
-
-    private VirtualTableFieldRes 
convertVirtualTableFieldReq(VirtualTableFieldReq req) {
-
-        return VirtualTableFieldRes.builder()
-                .fieldName(req.getFieldName())
-                .fieldType(req.getFieldType())
-                .nullable(req.getNullable())
-                .defaultValue(req.getDefaultValue())
-                .fieldComment(req.getFieldComment())
-                .primaryKey(req.getPrimaryKey())
-                .build();
-    }
-
-    /* private VirtualTableDetailRes 
convertVirtualTableDetailResponse(VirtualTableDetailResponse response) {
-        VirtualTableDetailRes res = new VirtualTableDetailRes();
-        res.setTableId(response.getId().toString());
-        res.setTableName(response.getTableName());
-        res.setDatabaseName(response.getDatabaseName());
-        res.setDescription(response.getDescription());
-        res.setCreateTime(response.getCreateTime());
-        res.setUpdateTime(response.getUpdateTime());
-
-        res.setFields(convertVirtualTableFieldResponse(response.getFields()));
-
-        List<Integer> userIds = new ArrayList<>();
-        userIds.add(Integer.parseInt(response.getCreateUserId()));
-        userIds.add(Integer.parseInt(response.getUpdateUserId()));
-        Map<Integer, String> userNames = queryUserNamesByIds(userIds);
-        
res.setCreateUserName(userNames.get(Integer.parseInt(response.getCreateUserId())));
-        
res.setUpdateUserName(userNames.get(Integer.parseInt(response.getUpdateUserId())));
-        return res;
-    }
-
-    private List<VirtualTableFieldRes> 
convertVirtualTableFieldResponse(List<VirtualTableFieldResponse> 
fieldResponses) {
-        List<VirtualTableFieldRes> fields = new ArrayList<>();
-        if (fieldResponses != null && !fieldResponses.isEmpty()) {
-            for (VirtualTableFieldResponse fieldResponse : fieldResponses) {
-                VirtualTableFieldRes field = new VirtualTableFieldRes();
-                field.setFieldName(fieldResponse.getName());
-                field.setFieldType(fieldResponse.getType());
-                field.setNullable(fieldResponse.getNullable());
-                field.setDefaultValue(fieldResponse.getDefaultValue());
-                field.setFieldComment(fieldResponse.getComment());
-                field.setPrimaryKey(fieldResponse.getPrimaryKey());
-                fields.add(field);
-            }
-        }
-        return fields;
-    }*/
 }
diff --git 
a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/service/impl/WorkspaceServiceImpl.java
 
b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/service/impl/WorkspaceServiceImpl.java
index 2700c7d3..9406aada 100644
--- 
a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/service/impl/WorkspaceServiceImpl.java
+++ 
b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/service/impl/WorkspaceServiceImpl.java
@@ -20,8 +20,11 @@ package org.apache.seatunnel.app.service.impl;
 import org.apache.seatunnel.app.dal.dao.IWorkspaceDao;
 import org.apache.seatunnel.app.dal.entity.Workspace;
 import org.apache.seatunnel.app.domain.request.workspace.WorkspaceReq;
+import org.apache.seatunnel.app.security.UserContextHolder;
 import org.apache.seatunnel.app.service.WorkspaceService;
 import org.apache.seatunnel.app.utils.ServletUtils;
+import org.apache.seatunnel.common.access.AccessType;
+import org.apache.seatunnel.common.access.ResourceType;
 import org.apache.seatunnel.server.common.CodeGenerateUtils;
 import org.apache.seatunnel.server.common.ParamValidationException;
 import org.apache.seatunnel.server.common.SeatunnelErrorEnum;
@@ -29,19 +32,22 @@ import 
org.apache.seatunnel.server.common.SeatunnelException;
 
 import org.apache.commons.lang3.StringUtils;
 
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
+import javax.annotation.Resource;
+
 import java.util.Date;
 import java.util.List;
+import java.util.stream.Collectors;
 
 @Service
 public class WorkspaceServiceImpl extends SeatunnelBaseServiceImpl implements 
WorkspaceService {
-    @Autowired private IWorkspaceDao workspaceDao;
+    @Resource private IWorkspaceDao workspaceDao;
 
     @Override
     public Long createWorkspace(WorkspaceReq workspaceReq) {
         validateWorkspaceParam(workspaceReq);
+        permCheck(workspaceReq.getWorkspaceName(), AccessType.CREATE);
         Workspace workspaceByName =
                 
workspaceDao.selectWorkspaceByName(workspaceReq.getWorkspaceName());
         if (workspaceByName != null) {
@@ -95,6 +101,7 @@ public class WorkspaceServiceImpl extends 
SeatunnelBaseServiceImpl implements Wo
                     SeatunnelErrorEnum.RESOURCE_NOT_FOUND,
                     "Workspace with id " + id + " not found.");
         }
+        permCheck(workspace.getWorkspaceName(), AccessType.UPDATE);
         validateWorkspaceParam(workspaceReq);
 
         // Check if the workspace name is being changed and if it already 
exists in the database
@@ -115,6 +122,7 @@ public class WorkspaceServiceImpl extends 
SeatunnelBaseServiceImpl implements Wo
     public boolean deleteWorkspace(Long id) {
         Workspace workspace = workspaceDao.selectWorkspaceById(id);
         if (null != workspace) {
+            permCheck(workspace.getWorkspaceName(), AccessType.DELETE);
             return workspaceDao.deleteWorkspaceById(id);
         }
         return false;
@@ -122,7 +130,9 @@ public class WorkspaceServiceImpl extends 
SeatunnelBaseServiceImpl implements Wo
 
     @Override
     public List<Workspace> getAllWorkspaces() {
-        return workspaceDao.selectAllWorkspaces();
+        return workspaceDao.selectAllWorkspaces().stream()
+                .filter(workspace -> hasReadPerm(workspace.getWorkspaceName()))
+                .collect(Collectors.toList());
     }
 
     @Override
@@ -130,22 +140,6 @@ public class WorkspaceServiceImpl extends 
SeatunnelBaseServiceImpl implements Wo
         return getWorkspace("default");
     }
 
-    @Override
-    public Long getWorkspaceIdOrDefault(Long workspaceId) {
-        if (workspaceId == null || workspaceId == 0 || workspaceId == 1) {
-            return getDefaultWorkspace().getId();
-        } else {
-            // Check if the workspace exists
-            Workspace workspaceById = getWorkspace(workspaceId);
-            if (workspaceById == null) {
-                throw new SeatunnelException(
-                        SeatunnelErrorEnum.RESOURCE_NOT_FOUND,
-                        "Workspace with id " + workspaceId + " not found.");
-            }
-            return workspaceById.getId();
-        }
-    }
-
     public Long getWorkspaceIdOrCurrent(String workspaceName) {
         if (StringUtils.isEmpty(workspaceName)) {
             // get names from current workspace
@@ -154,4 +148,20 @@ public class WorkspaceServiceImpl extends 
SeatunnelBaseServiceImpl implements Wo
             return getWorkspace(workspaceName).getId();
         }
     }
+
+    private void permCheck(String resourceName, AccessType accessType) {
+        permissionCheck(
+                resourceName,
+                ResourceType.WORKSPACE,
+                accessType,
+                UserContextHolder.getAccessInfo());
+    }
+
+    private boolean hasReadPerm(String resourceName) {
+        return hasPermission(
+                resourceName,
+                ResourceType.WORKSPACE,
+                AccessType.READ,
+                UserContextHolder.getAccessInfo());
+    }
 }
diff --git 
a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/utils/GlobalExceptionHandler.java
 
b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/utils/GlobalExceptionHandler.java
index f7d22b7d..f18ebe7f 100644
--- 
a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/utils/GlobalExceptionHandler.java
+++ 
b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/utils/GlobalExceptionHandler.java
@@ -18,6 +18,7 @@
 package org.apache.seatunnel.app.utils;
 
 import org.apache.seatunnel.app.common.Result;
+import org.apache.seatunnel.common.access.AccessDeniedException;
 import org.apache.seatunnel.datasource.plugin.api.DataSourcePluginException;
 import org.apache.seatunnel.server.common.ParamValidationException;
 import org.apache.seatunnel.server.common.SeatunnelErrorEnum;
@@ -88,4 +89,9 @@ public class GlobalExceptionHandler {
     private Result<String> paramValidationHandler(SeatunnelException e) {
         return Result.failure(e);
     }
+
+    @ExceptionHandler(value = AccessDeniedException.class)
+    private Result<String> paramValidationHandler(AccessDeniedException e) {
+        return Result.failure(SeatunnelErrorEnum.ACCESS_DENIED, 
e.getMessage());
+    }
 }
diff --git a/seatunnel-server/seatunnel-app/src/main/resources/application.yml 
b/seatunnel-server/seatunnel-app/src/main/resources/application.yml
index a90a6366..57117794 100644
--- a/seatunnel-server/seatunnel-app/src/main/resources/application.yml
+++ b/seatunnel-server/seatunnel-app/src/main/resources/application.yml
@@ -59,6 +59,7 @@ seatunnel-web:
       keys-to-encrypt:
         - password
         - auth
+  access-controller-class: 
org.apache.seatunnel.app.permission.SeatunnelAccessControllerDefaultImpl
 ---
 spring:
   config:
diff --git 
a/seatunnel-server/seatunnel-server-common/src/main/java/org/apache/seatunnel/server/common/SeatunnelErrorEnum.java
 
b/seatunnel-server/seatunnel-server-common/src/main/java/org/apache/seatunnel/server/common/SeatunnelErrorEnum.java
index 5318b550..77afcff9 100644
--- 
a/seatunnel-server/seatunnel-server-common/src/main/java/org/apache/seatunnel/server/common/SeatunnelErrorEnum.java
+++ 
b/seatunnel-server/seatunnel-server-common/src/main/java/org/apache/seatunnel/server/common/SeatunnelErrorEnum.java
@@ -140,7 +140,8 @@ public enum SeatunnelErrorEnum {
     INVALID_PARAM(60019, "", "param [%s] is invalid. %s"),
     TASK_NAME_ALREADY_EXISTS(60020, "task name already exists", "task [%s] 
already exists"),
     RESOURCE_NOT_FOUND(404, "", "%s"),
-    RESOURCE_ALREADY_EXISTS(60021, "resource already exists", "resource [%s] 
already exists");
+    RESOURCE_ALREADY_EXISTS(60021, "resource already exists", "resource [%s] 
already exists"),
+    ACCESS_DENIED(403, "Access denied", "%s");
 
     private final int code;
     private final String msg;
diff --git a/seatunnel-web-common/pom.xml b/seatunnel-web-common/pom.xml
new file mode 100644
index 00000000..e74ae266
--- /dev/null
+++ b/seatunnel-web-common/pom.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You 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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd";>
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.apache.seatunnel</groupId>
+        <artifactId>seatunnel-web</artifactId>
+        <version>${revision}</version>
+    </parent>
+    <artifactId>seatunnel-web-common</artifactId>
+</project>
diff --git 
a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/security/UserContext.java
 
b/seatunnel-web-common/src/main/java/org/apache/seatunnel/common/access/AccessDeniedException.java
similarity index 56%
copy from 
seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/security/UserContext.java
copy to 
seatunnel-web-common/src/main/java/org/apache/seatunnel/common/access/AccessDeniedException.java
index 8897779a..c18a3c02 100644
--- 
a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/security/UserContext.java
+++ 
b/seatunnel-web-common/src/main/java/org/apache/seatunnel/common/access/AccessDeniedException.java
@@ -14,19 +14,22 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.seatunnel.app.security;
 
-import org.apache.seatunnel.app.dal.entity.User;
+package org.apache.seatunnel.common.access;
 
-import lombok.AllArgsConstructor;
-import lombok.Data;
-import lombok.NoArgsConstructor;
+public class AccessDeniedException extends RuntimeException {
+    public AccessDeniedException(String message) {
+        super(message);
+    }
 
-@Data
-@AllArgsConstructor
-@NoArgsConstructor
-public class UserContext {
-    User user;
-    Long workspaceId;
-    String workspaceName;
+    public static void accessDenied(
+            String userName,
+            String resourceName,
+            ResourceType resourceType,
+            AccessType accessType) {
+        throw new AccessDeniedException(
+                String.format(
+                        "Access denied: user=%s, resource=%s, 
resource-type=%s, operation=%s",
+                        userName, resourceName, resourceType.getName(), 
accessType.getName()));
+    }
 }
diff --git 
a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/security/UserContext.java
 
b/seatunnel-web-common/src/main/java/org/apache/seatunnel/common/access/AccessInfo.java
similarity index 74%
copy from 
seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/security/UserContext.java
copy to 
seatunnel-web-common/src/main/java/org/apache/seatunnel/common/access/AccessInfo.java
index 8897779a..7ed8f39c 100644
--- 
a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/security/UserContext.java
+++ 
b/seatunnel-web-common/src/main/java/org/apache/seatunnel/common/access/AccessInfo.java
@@ -14,19 +14,17 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.seatunnel.app.security;
 
-import org.apache.seatunnel.app.dal.entity.User;
+package org.apache.seatunnel.common.access;
 
-import lombok.AllArgsConstructor;
 import lombok.Data;
-import lombok.NoArgsConstructor;
+
+import java.util.Set;
 
 @Data
-@AllArgsConstructor
-@NoArgsConstructor
-public class UserContext {
-    User user;
-    Long workspaceId;
-    String workspaceName;
+public class AccessInfo {
+    private String username;
+    private String workspaceName;
+    private Set<String> userGroups;
+    private Set<String> userRoles;
 }
diff --git 
a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/security/UserContext.java
 
b/seatunnel-web-common/src/main/java/org/apache/seatunnel/common/access/AccessType.java
similarity index 71%
copy from 
seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/security/UserContext.java
copy to 
seatunnel-web-common/src/main/java/org/apache/seatunnel/common/access/AccessType.java
index 8897779a..b8f12a99 100644
--- 
a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/security/UserContext.java
+++ 
b/seatunnel-web-common/src/main/java/org/apache/seatunnel/common/access/AccessType.java
@@ -14,19 +14,17 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.seatunnel.app.security;
 
-import org.apache.seatunnel.app.dal.entity.User;
+package org.apache.seatunnel.common.access;
 
-import lombok.AllArgsConstructor;
-import lombok.Data;
-import lombok.NoArgsConstructor;
+public enum AccessType {
+    CREATE,
+    READ,
+    UPDATE,
+    DELETE,
+    EXECUTE;
 
-@Data
-@AllArgsConstructor
-@NoArgsConstructor
-public class UserContext {
-    User user;
-    Long workspaceId;
-    String workspaceName;
+    public String getName() {
+        return this.name().toLowerCase();
+    }
 }
diff --git 
a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/security/UserContext.java
 
b/seatunnel-web-common/src/main/java/org/apache/seatunnel/common/access/ResourceType.java
similarity index 71%
copy from 
seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/security/UserContext.java
copy to 
seatunnel-web-common/src/main/java/org/apache/seatunnel/common/access/ResourceType.java
index 8897779a..2a1bc67b 100644
--- 
a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/security/UserContext.java
+++ 
b/seatunnel-web-common/src/main/java/org/apache/seatunnel/common/access/ResourceType.java
@@ -14,19 +14,16 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.seatunnel.app.security;
+package org.apache.seatunnel.common.access;
 
-import org.apache.seatunnel.app.dal.entity.User;
+public enum ResourceType {
+    WORKSPACE,
+    DATASOURCE,
+    JOB,
+    USER,
+    VIRTUAL_TABLE;
 
-import lombok.AllArgsConstructor;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-@Data
-@AllArgsConstructor
-@NoArgsConstructor
-public class UserContext {
-    User user;
-    Long workspaceId;
-    String workspaceName;
+    public String getName() {
+        return this.name().toLowerCase();
+    }
 }
diff --git 
a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/mapper/JobLineMapper.java
 
b/seatunnel-web-common/src/main/java/org/apache/seatunnel/common/access/SeatunnelAccessController.java
similarity index 65%
copy from 
seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/mapper/JobLineMapper.java
copy to 
seatunnel-web-common/src/main/java/org/apache/seatunnel/common/access/SeatunnelAccessController.java
index 9317520a..06a8ad4e 100644
--- 
a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/mapper/JobLineMapper.java
+++ 
b/seatunnel-web-common/src/main/java/org/apache/seatunnel/common/access/SeatunnelAccessController.java
@@ -14,20 +14,18 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
-package org.apache.seatunnel.app.dal.mapper;
-
-import org.apache.seatunnel.app.dal.entity.JobLine;
-
-import org.apache.ibatis.annotations.Param;
-
-import com.baomidou.mybatisplus.core.mapper.BaseMapper;
-
-import java.util.List;
-
-public interface JobLineMapper extends BaseMapper<JobLine> {
-
-    void deleteLinesByVersionId(@Param("versionId") long jobVersionId);
-
-    void insertBatchLines(@Param("lines") List<JobLine> lines);
+package org.apache.seatunnel.common.access;
+
+public interface SeatunnelAccessController {
+    void authorizeAccess(
+            String resourceName,
+            ResourceType resourceType,
+            AccessType accessType,
+            AccessInfo accessInfo);
+
+    boolean hasPermission(
+            String resourceName,
+            ResourceType resourceType,
+            AccessType accessType,
+            AccessInfo accessInfo);
 }
diff --git 
a/seatunnel-web-it/src/test/java/org/apache/seatunnel/app/common/AccessControllerTestingImp.java
 
b/seatunnel-web-it/src/test/java/org/apache/seatunnel/app/common/AccessControllerTestingImp.java
new file mode 100644
index 00000000..94e052cb
--- /dev/null
+++ 
b/seatunnel-web-it/src/test/java/org/apache/seatunnel/app/common/AccessControllerTestingImp.java
@@ -0,0 +1,105 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.seatunnel.app.common;
+
+import org.apache.seatunnel.common.access.AccessDeniedException;
+import org.apache.seatunnel.common.access.AccessInfo;
+import org.apache.seatunnel.common.access.AccessType;
+import org.apache.seatunnel.common.access.ResourceType;
+import org.apache.seatunnel.common.access.SeatunnelAccessController;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * This class is intended to provide basic access control functionality for 
testing purposes, rather
+ * than simulating a full-fledged Ranger access controller.
+ */
+public class AccessControllerTestingImp implements SeatunnelAccessController {
+    private static boolean isAccessControllerEnabled = false;
+    private static final Map<String, List<ResourcePermissionData>> 
permissionList = new HashMap<>();
+
+    public static void resetResourcePermission(String username, 
ResourcePermissionData permission) {
+        clearPermission();
+        addResourcePermission(username, permission);
+    }
+
+    public static void addResourcePermission(String username, 
ResourcePermissionData permission) {
+        List<ResourcePermissionData> resourcePermissionDataList =
+                permissionList.computeIfAbsent(username, k -> new 
ArrayList<>());
+        resourcePermissionDataList.add(permission);
+    }
+
+    public static void enableAccessController() {
+        isAccessControllerEnabled = true;
+    }
+
+    public static void disableAccessController() {
+        isAccessControllerEnabled = false;
+    }
+
+    public static void clearPermission() {
+        permissionList.clear();
+    }
+
+    @Override
+    public void authorizeAccess(
+            String resourceName,
+            ResourceType resourceType,
+            AccessType accessType,
+            AccessInfo accessInfo) {
+        if (!hasPermission(resourceName, resourceType, accessType, 
accessInfo)) {
+            AccessDeniedException.accessDenied(
+                    accessInfo.getUsername(), resourceName, resourceType, 
accessType);
+        }
+    }
+
+    @Override
+    public boolean hasPermission(
+            String resourceName,
+            ResourceType resourceType,
+            AccessType accessType,
+            AccessInfo accessInfo) {
+        if (!isAccessControllerEnabled) {
+            return true;
+        }
+        List<ResourcePermissionData> permissions = 
permissionList.get(accessInfo.getUsername());
+        if (permissions != null) {
+            for (ResourcePermissionData permission : permissions) {
+                if (resourceType == ResourceType.USER || resourceType == 
ResourceType.WORKSPACE) {
+                    // Do not consider workspace name
+                    if (permission.getResourceName().equals(resourceName)
+                            && permission.getResourceType() == resourceType
+                            && 
permission.getAccessTypes().contains(accessType)) {
+                        return true;
+                    }
+                } else {
+                    if 
(permission.getWorkspaceName().equals(accessInfo.getWorkspaceName())
+                            && 
permission.getResourceName().equals(resourceName)
+                            && permission.getResourceType() == resourceType
+                            && 
permission.getAccessTypes().contains(accessType)) {
+                        return true;
+                    }
+                }
+            }
+        }
+        return false;
+    }
+}
diff --git 
a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/security/UserContext.java
 
b/seatunnel-web-it/src/test/java/org/apache/seatunnel/app/common/ResourcePermissionData.java
similarity index 76%
copy from 
seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/security/UserContext.java
copy to 
seatunnel-web-it/src/test/java/org/apache/seatunnel/app/common/ResourcePermissionData.java
index 8897779a..06e5050a 100644
--- 
a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/security/UserContext.java
+++ 
b/seatunnel-web-it/src/test/java/org/apache/seatunnel/app/common/ResourcePermissionData.java
@@ -14,19 +14,23 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.seatunnel.app.security;
+package org.apache.seatunnel.app.common;
 
-import org.apache.seatunnel.app.dal.entity.User;
+import org.apache.seatunnel.common.access.AccessType;
+import org.apache.seatunnel.common.access.ResourceType;
 
 import lombok.AllArgsConstructor;
 import lombok.Data;
 import lombok.NoArgsConstructor;
 
+import java.util.List;
+
 @Data
 @AllArgsConstructor
 @NoArgsConstructor
-public class UserContext {
-    User user;
-    Long workspaceId;
+public class ResourcePermissionData {
     String workspaceName;
+    String resourceName;
+    ResourceType resourceType;
+    List<AccessType> accessTypes;
 }
diff --git 
a/seatunnel-web-it/src/test/java/org/apache/seatunnel/app/controller/JobDefinitionControllerWrapper.java
 
b/seatunnel-web-it/src/test/java/org/apache/seatunnel/app/controller/JobDefinitionControllerWrapper.java
index ccff9c3c..3a76371d 100644
--- 
a/seatunnel-web-it/src/test/java/org/apache/seatunnel/app/controller/JobDefinitionControllerWrapper.java
+++ 
b/seatunnel-web-it/src/test/java/org/apache/seatunnel/app/controller/JobDefinitionControllerWrapper.java
@@ -25,9 +25,11 @@ import 
org.apache.seatunnel.app.domain.response.job.JobDefinitionRes;
 import org.apache.seatunnel.app.utils.JSONTestUtils;
 import org.apache.seatunnel.common.constants.JobMode;
 import org.apache.seatunnel.common.utils.JsonUtils;
+import org.apache.seatunnel.server.common.SeatunnelErrorEnum;
 
 import com.fasterxml.jackson.core.type.TypeReference;
 
+import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 
 public class JobDefinitionControllerWrapper extends SeatunnelWebTestingBase {
@@ -48,6 +50,15 @@ public class JobDefinitionControllerWrapper extends 
SeatunnelWebTestingBase {
         return result.getData();
     }
 
+    public void createJobExpectingFailure(String jobName) {
+        JobReq jobReq = new JobReq();
+        jobReq.setName(jobName);
+        jobReq.setDescription(jobName + " description");
+        jobReq.setJobType(BusinessMode.DATA_INTEGRATION);
+        Result<Long> result = createJobDefinition(jobReq);
+        assertEquals(SeatunnelErrorEnum.ACCESS_DENIED.getCode(), 
result.getCode());
+    }
+
     public Result<PageInfo<JobDefinitionRes>> getJobDefinition(
             String searchName, Integer pageNo, Integer pageSize, JobMode 
jobMode) {
         String response =
diff --git 
a/seatunnel-web-it/src/test/java/org/apache/seatunnel/app/controller/SeatunnelDatasourceControllerWrapper.java
 
b/seatunnel-web-it/src/test/java/org/apache/seatunnel/app/controller/SeatunnelDatasourceControllerWrapper.java
index 3f2af1f2..d8fd642c 100644
--- 
a/seatunnel-web-it/src/test/java/org/apache/seatunnel/app/controller/SeatunnelDatasourceControllerWrapper.java
+++ 
b/seatunnel-web-it/src/test/java/org/apache/seatunnel/app/controller/SeatunnelDatasourceControllerWrapper.java
@@ -25,9 +25,13 @@ import 
org.apache.seatunnel.app.domain.response.datasource.DatasourceDetailRes;
 import org.apache.seatunnel.app.domain.response.datasource.DatasourceRes;
 import org.apache.seatunnel.app.utils.JSONTestUtils;
 import org.apache.seatunnel.common.utils.JsonUtils;
+import org.apache.seatunnel.server.common.SeatunnelErrorEnum;
 
 import com.fasterxml.jackson.core.type.TypeReference;
 
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 
 public class SeatunnelDatasourceControllerWrapper extends 
SeatunnelWebTestingBase {
@@ -39,6 +43,12 @@ public class SeatunnelDatasourceControllerWrapper extends 
SeatunnelWebTestingBas
         return result.getData();
     }
 
+    public void createDatasourceExpectingFailure(String datasourceName) {
+        DatasourceReq req = getFakeSourceDatasourceReq(datasourceName);
+        Result<String> result = createDatasource(req);
+        assertEquals(SeatunnelErrorEnum.ACCESS_DENIED.getCode(), 
result.getCode());
+    }
+
     public String createConsoleDatasource(String datasourceName) {
         DatasourceReq req = getConsoleDatasourceReq(datasourceName);
         Result<String> result = createDatasource(req);
@@ -121,4 +131,17 @@ public class SeatunnelDatasourceControllerWrapper extends 
SeatunnelWebTestingBas
                 
"{\"url\":\"jdbc:mysql://localhost:3306/test?useSSL=false&useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true&allowPublicKeyRetrieval=true\",\"driver\":\"com.mysql.cj.jdbc.Driver\",\"user\":\"someUser\",\"password\":\"somePassword\"}");
         return req;
     }
+
+    public Result<List<String>> getDatasourceNames(String namePrefix) {
+        String response;
+        if (namePrefix == null) {
+            response = sendRequest(String.format("%s/datasource/names", 
baseUrl));
+        } else {
+            response =
+                    sendRequest(
+                            String.format(
+                                    "%s/datasource/names?namePrefix=%s", 
baseUrl, namePrefix));
+        }
+        return JSONTestUtils.parseObject(response, new 
TypeReference<Result<List<String>>>() {});
+    }
 }
diff --git 
a/seatunnel-web-it/src/test/java/org/apache/seatunnel/app/test/SeatunnelAccessControllerTest.java
 
b/seatunnel-web-it/src/test/java/org/apache/seatunnel/app/test/SeatunnelAccessControllerTest.java
new file mode 100644
index 00000000..6aa69b69
--- /dev/null
+++ 
b/seatunnel-web-it/src/test/java/org/apache/seatunnel/app/test/SeatunnelAccessControllerTest.java
@@ -0,0 +1,790 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.seatunnel.app.test;
+
+import org.apache.seatunnel.app.common.AccessControllerTestingImp;
+import org.apache.seatunnel.app.common.ResourcePermissionData;
+import org.apache.seatunnel.app.common.Result;
+import org.apache.seatunnel.app.common.SeaTunnelWebCluster;
+import org.apache.seatunnel.app.controller.JobConfigControllerWrapper;
+import org.apache.seatunnel.app.controller.JobControllerWrapper;
+import org.apache.seatunnel.app.controller.JobDefinitionControllerWrapper;
+import org.apache.seatunnel.app.controller.JobExecutorControllerWrapper;
+import 
org.apache.seatunnel.app.controller.SeatunnelDatasourceControllerWrapper;
+import org.apache.seatunnel.app.controller.UserControllerWrapper;
+import org.apache.seatunnel.app.controller.WorkspaceControllerWrapper;
+import org.apache.seatunnel.app.dal.entity.Workspace;
+import org.apache.seatunnel.app.domain.request.datasource.DatasourceReq;
+import org.apache.seatunnel.app.domain.request.job.JobConfig;
+import org.apache.seatunnel.app.domain.request.job.JobCreateReq;
+import org.apache.seatunnel.app.domain.request.user.AddUserReq;
+import org.apache.seatunnel.app.domain.request.user.UpdateUserReq;
+import org.apache.seatunnel.app.domain.request.user.UserLoginReq;
+import org.apache.seatunnel.app.domain.request.workspace.WorkspaceReq;
+import org.apache.seatunnel.app.domain.response.PageInfo;
+import org.apache.seatunnel.app.domain.response.datasource.DatasourceDetailRes;
+import org.apache.seatunnel.app.domain.response.datasource.DatasourceRes;
+import org.apache.seatunnel.app.domain.response.job.JobConfigRes;
+import org.apache.seatunnel.app.domain.response.job.JobDefinitionRes;
+import org.apache.seatunnel.app.domain.response.job.JobRes;
+import org.apache.seatunnel.app.domain.response.user.AddUserRes;
+import org.apache.seatunnel.app.domain.response.user.UserSimpleInfoRes;
+import org.apache.seatunnel.app.utils.JobTestingUtils;
+import org.apache.seatunnel.common.access.AccessType;
+import org.apache.seatunnel.common.access.ResourceType;
+import org.apache.seatunnel.common.constants.JobMode;
+import org.apache.seatunnel.server.common.SeatunnelErrorEnum;
+
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public class SeatunnelAccessControllerTest {
+    private static final SeaTunnelWebCluster seaTunnelWebCluster = new 
SeaTunnelWebCluster();
+    private static WorkspaceControllerWrapper workspaceControllerWrapper;
+    private static UserControllerWrapper userControllerWrapper;
+    private static SeatunnelDatasourceControllerWrapper 
datasourceControllerWrapper;
+    private static JobDefinitionControllerWrapper 
jobDefinitionControllerWrapper;
+    private static JobConfigControllerWrapper jobConfigControllerWrapper;
+    private static JobControllerWrapper jobControllerWrapper;
+    private static JobExecutorControllerWrapper jobExecutorControllerWrapper;
+    private static final String uniqueId = "_" + System.currentTimeMillis();
+
+    @BeforeAll
+    public static void setUp() {
+        seaTunnelWebCluster.start();
+        workspaceControllerWrapper = new WorkspaceControllerWrapper();
+        userControllerWrapper = new UserControllerWrapper();
+        datasourceControllerWrapper = new 
SeatunnelDatasourceControllerWrapper();
+        jobDefinitionControllerWrapper = new JobDefinitionControllerWrapper();
+        jobConfigControllerWrapper = new JobConfigControllerWrapper();
+        jobControllerWrapper = new JobControllerWrapper();
+        jobExecutorControllerWrapper = new JobExecutorControllerWrapper();
+        AccessControllerTestingImp.enableAccessController();
+    }
+
+    @Test
+    public void testWorkspaceAccessPermission() {
+        String user1 = "admin";
+        String workspaceName = "workspace_access_workspace" + uniqueId;
+
+        Result<Long> createWorkspaceResult =
+                workspaceControllerWrapper.createWorkspace(workspaceName);
+        assertEquals(SeatunnelErrorEnum.ACCESS_DENIED.getCode(), 
createWorkspaceResult.getCode());
+
+        AccessControllerTestingImp.resetResourcePermission(
+                user1,
+                new ResourcePermissionData(
+                        null,
+                        workspaceName,
+                        ResourceType.WORKSPACE,
+                        Collections.singletonList(AccessType.CREATE)));
+        createWorkspaceResult = 
workspaceControllerWrapper.createWorkspace(workspaceName);
+        assertTrue(createWorkspaceResult.isSuccess());
+
+        // Handle read operation
+        AccessControllerTestingImp.clearPermission();
+        Result<List<Workspace>> getWorkspaces = 
workspaceControllerWrapper.getAllWorkspaces();
+        assertTrue(getWorkspaces.isSuccess());
+        assertEquals(0, getWorkspaces.getData().size());
+
+        AccessControllerTestingImp.resetResourcePermission(
+                user1,
+                new ResourcePermissionData(
+                        null,
+                        workspaceName,
+                        ResourceType.WORKSPACE,
+                        Collections.singletonList(AccessType.READ)));
+
+        getWorkspaces = workspaceControllerWrapper.getAllWorkspaces();
+        assertTrue(getWorkspaces.isSuccess());
+        assertEquals(1, getWorkspaces.getData().size());
+
+        String anotherWorkspace = "another_workspace_access" + uniqueId;
+        AccessControllerTestingImp.clearPermission();
+        AccessControllerTestingImp.resetResourcePermission(
+                user1,
+                new ResourcePermissionData(
+                        null,
+                        anotherWorkspace,
+                        ResourceType.WORKSPACE,
+                        Collections.singletonList(AccessType.CREATE)));
+        Result<Long> anotherCreateWorkspaceResult =
+                workspaceControllerWrapper.createWorkspace(anotherWorkspace);
+        assertTrue(anotherCreateWorkspaceResult.isSuccess());
+
+        getWorkspaces = workspaceControllerWrapper.getAllWorkspaces();
+        assertTrue(anotherCreateWorkspaceResult.isSuccess());
+        assertEquals(0, getWorkspaces.getData().size());
+
+        AccessControllerTestingImp.clearPermission();
+        AccessControllerTestingImp.resetResourcePermission(
+                user1,
+                new ResourcePermissionData(
+                        null,
+                        workspaceName,
+                        ResourceType.WORKSPACE,
+                        Collections.singletonList(AccessType.READ)));
+        AccessControllerTestingImp.addResourcePermission(
+                user1,
+                new ResourcePermissionData(
+                        null,
+                        anotherWorkspace,
+                        ResourceType.WORKSPACE,
+                        Collections.singletonList(AccessType.READ)));
+        getWorkspaces = workspaceControllerWrapper.getAllWorkspaces();
+        assertTrue(anotherCreateWorkspaceResult.isSuccess());
+        assertEquals(2, getWorkspaces.getData().size());
+
+        // Handle update operation
+        AccessControllerTestingImp.clearPermission();
+        WorkspaceReq updateWorkspaceReq =
+                new WorkspaceReq(workspaceName + "_new", "new description");
+        Result<Boolean> updateResult =
+                workspaceControllerWrapper.updateWorkspace(
+                        createWorkspaceResult.getData(), updateWorkspaceReq);
+        assertEquals(SeatunnelErrorEnum.ACCESS_DENIED.getCode(), 
updateResult.getCode());
+
+        AccessControllerTestingImp.resetResourcePermission(
+                user1,
+                new ResourcePermissionData(
+                        null,
+                        workspaceName,
+                        ResourceType.WORKSPACE,
+                        Collections.singletonList(AccessType.UPDATE)));
+        updateResult =
+                workspaceControllerWrapper.updateWorkspace(
+                        createWorkspaceResult.getData(), updateWorkspaceReq);
+        assertTrue(updateResult.isSuccess(), updateResult.getMsg());
+
+        // Handle delete operation
+        AccessControllerTestingImp.clearPermission();
+        Result<Boolean> deleteResult =
+                
workspaceControllerWrapper.deleteWorkspace(createWorkspaceResult.getData());
+        assertEquals(SeatunnelErrorEnum.ACCESS_DENIED.getCode(), 
deleteResult.getCode());
+
+        AccessControllerTestingImp.resetResourcePermission(
+                user1,
+                new ResourcePermissionData(
+                        null,
+                        updateWorkspaceReq.getWorkspaceName(),
+                        ResourceType.WORKSPACE,
+                        Collections.singletonList(AccessType.DELETE)));
+        deleteResult = 
workspaceControllerWrapper.deleteWorkspace(createWorkspaceResult.getData());
+        assertTrue(deleteResult.isSuccess(), deleteResult.getMsg());
+    }
+
+    @Test
+    public void testUserAccessPermission() {
+        String user1 = "user_access_user_1" + uniqueId;
+        String pass = "somePassword";
+        String workspaceName = "workspace_access_user" + uniqueId;
+
+        List<AccessType> accessTypes = new ArrayList<>();
+        accessTypes.add(AccessType.CREATE);
+
+        createWorkspaceAndUser(workspaceName, user1, pass);
+        login(new UserLoginReq(user1, pass, workspaceName));
+
+        // Handle create operation
+        accessTypes.clear();
+        String newUser = "new_user_access" + uniqueId;
+        Result<AddUserRes> addUserResult =
+                userControllerWrapper.addUser(getAddUserReq(newUser, pass));
+        assertEquals(SeatunnelErrorEnum.ACCESS_DENIED.getCode(), 
addUserResult.getCode());
+        accessTypes.add(AccessType.CREATE);
+        AccessControllerTestingImp.resetResourcePermission(
+                user1,
+                new ResourcePermissionData(workspaceName, newUser, 
ResourceType.USER, accessTypes));
+        // should be successful as user1 has access to create user
+        addUserResult = userControllerWrapper.addUser(getAddUserReq(newUser, 
pass));
+        assertTrue(addUserResult.isSuccess());
+
+        // Handle read operation
+        Result<PageInfo<UserSimpleInfoRes>> getUsers = 
userControllerWrapper.listUsers(newUser);
+        assertTrue(getUsers.isSuccess());
+        assertEquals(0, getUsers.getData().getData().size());
+
+        accessTypes.clear();
+        accessTypes.add(AccessType.READ);
+        AccessControllerTestingImp.resetResourcePermission(
+                user1,
+                new ResourcePermissionData(workspaceName, newUser, 
ResourceType.USER, accessTypes));
+        getUsers = userControllerWrapper.listUsers(newUser);
+        assertTrue(getUsers.isSuccess());
+        assertEquals(1, getUsers.getData().getData().size());
+
+        String anotherUser = "another_user_access" + uniqueId;
+        accessTypes.clear();
+        accessTypes.add(AccessType.CREATE);
+        AccessControllerTestingImp.resetResourcePermission(
+                user1,
+                new ResourcePermissionData(
+                        workspaceName, anotherUser, ResourceType.USER, 
accessTypes));
+        Result<AddUserRes> anotherAddUserResult =
+                userControllerWrapper.addUser(getAddUserReq(anotherUser, 
pass));
+        assertTrue(anotherAddUserResult.isSuccess());
+
+        Result<PageInfo<UserSimpleInfoRes>> listUsers = 
userControllerWrapper.listUsers();
+        assertTrue(anotherAddUserResult.isSuccess());
+        assertEquals(0, listUsers.getData().getData().size());
+
+        accessTypes.clear();
+        accessTypes.add(AccessType.READ);
+        AccessControllerTestingImp.resetResourcePermission(
+                user1,
+                new ResourcePermissionData(workspaceName, newUser, 
ResourceType.USER, accessTypes));
+        AccessControllerTestingImp.addResourcePermission(
+                user1,
+                new ResourcePermissionData(
+                        workspaceName, anotherUser, ResourceType.USER, 
accessTypes));
+        listUsers = userControllerWrapper.listUsers();
+        assertTrue(listUsers.isSuccess());
+        assertEquals(2, listUsers.getData().getData().size());
+
+        // Handle update operation
+        UpdateUserReq updateUserReq = new UpdateUserReq();
+        updateUserReq.setUsername(newUser);
+        updateUserReq.setUserId(addUserResult.getData().getId());
+        updateUserReq.setPassword("newPassword");
+        updateUserReq.setStatus((byte) 0);
+        updateUserReq.setType((byte) 0);
+        Result<Void> updateResult =
+                userControllerWrapper.updateUser(
+                        String.valueOf(updateUserReq.getUserId()), 
updateUserReq);
+        assertEquals(SeatunnelErrorEnum.ACCESS_DENIED.getCode(), 
updateResult.getCode());
+
+        accessTypes.clear();
+        accessTypes.add(AccessType.UPDATE);
+        AccessControllerTestingImp.resetResourcePermission(
+                user1,
+                new ResourcePermissionData(workspaceName, newUser, 
ResourceType.USER, accessTypes));
+        updateResult =
+                userControllerWrapper.updateUser(
+                        String.valueOf(updateUserReq.getUserId()), 
updateUserReq);
+        assertTrue(updateResult.isSuccess(), updateResult.getMsg());
+
+        // Handle disable operation
+        AccessControllerTestingImp.clearPermission();
+        Result<Void> disableResult =
+                
userControllerWrapper.disableUser(String.valueOf(updateUserReq.getUserId()));
+        assertEquals(
+                SeatunnelErrorEnum.ACCESS_DENIED.getCode(),
+                disableResult.getCode(),
+                disableResult.getMsg());
+
+        accessTypes.clear();
+        accessTypes.add(AccessType.UPDATE);
+        AccessControllerTestingImp.resetResourcePermission(
+                user1,
+                new ResourcePermissionData(workspaceName, newUser, 
ResourceType.USER, accessTypes));
+        disableResult =
+                
userControllerWrapper.disableUser(String.valueOf(updateUserReq.getUserId()));
+        assertTrue(disableResult.isSuccess());
+
+        // Handle enable operation
+        AccessControllerTestingImp.clearPermission();
+        Result<Void> enableResult =
+                
userControllerWrapper.enableUser(String.valueOf(updateUserReq.getUserId()));
+        assertEquals(SeatunnelErrorEnum.ACCESS_DENIED.getCode(), 
enableResult.getCode());
+
+        accessTypes.clear();
+        accessTypes.add(AccessType.UPDATE);
+        AccessControllerTestingImp.resetResourcePermission(
+                user1,
+                new ResourcePermissionData(workspaceName, newUser, 
ResourceType.USER, accessTypes));
+        enableResult = 
userControllerWrapper.enableUser(String.valueOf(updateUserReq.getUserId()));
+        assertTrue(enableResult.isSuccess());
+
+        // Handle delete operation
+        AccessControllerTestingImp.clearPermission();
+        Result<Void> deleteResult =
+                
userControllerWrapper.deleteUser(String.valueOf(addUserResult.getData().getId()));
+        assertEquals(SeatunnelErrorEnum.ACCESS_DENIED.getCode(), 
deleteResult.getCode());
+
+        accessTypes.clear();
+        accessTypes.add(AccessType.DELETE);
+        AccessControllerTestingImp.resetResourcePermission(
+                user1,
+                new ResourcePermissionData(workspaceName, newUser, 
ResourceType.USER, accessTypes));
+        deleteResult =
+                
userControllerWrapper.deleteUser(String.valueOf(addUserResult.getData().getId()));
+        assertTrue(deleteResult.isSuccess());
+    }
+
+    @Test
+    public void testDatasourceAccessPermission() {
+        String user1 = "user_access_datasource_1" + uniqueId;
+        String user2 = "user_access_datasource_2" + uniqueId;
+        String pass = "somePassword";
+        String workspaceName = "workspace_access_datasource" + uniqueId;
+
+        // create workspaces and users using admin credentials
+        createWorkspaceAndUser(workspaceName, user1, pass);
+        createUserAndVerify(user2, pass);
+
+        login(new UserLoginReq(user1, pass, workspaceName));
+
+        // Handle create operation
+        String datasourceName1 = "1_datasource_access" + uniqueId;
+        
datasourceControllerWrapper.createDatasourceExpectingFailure(datasourceName1);
+        List<AccessType> accessTypes = new ArrayList<>();
+        accessTypes.add(AccessType.CREATE);
+        AccessControllerTestingImp.resetResourcePermission(
+                user1,
+                new ResourcePermissionData(
+                        workspaceName, datasourceName1, 
ResourceType.DATASOURCE, accessTypes));
+        // should be successful as user1 has access to create datasource
+        String datasourceId1 =
+                
datasourceControllerWrapper.createFakeSourceDatasource(datasourceName1);
+
+        Result<DatasourceDetailRes> getDataSource =
+                datasourceControllerWrapper.getDatasource(datasourceId1);
+        assertEquals(SeatunnelErrorEnum.ACCESS_DENIED.getCode(), 
getDataSource.getCode());
+
+        // Handle read operation
+        accessTypes.clear();
+        accessTypes.add(AccessType.READ);
+        AccessControllerTestingImp.resetResourcePermission(
+                user1,
+                new ResourcePermissionData(
+                        workspaceName, datasourceName1, 
ResourceType.DATASOURCE, accessTypes));
+        getDataSource = 
datasourceControllerWrapper.getDatasource(datasourceId1);
+        assertTrue(getDataSource.isSuccess());
+
+        // Handle update operation
+        DatasourceReq req = new DatasourceReq();
+        req.setDescription(getDataSource.getData().getDescription() + " new 
description");
+        Result<Boolean> updateResult =
+                datasourceControllerWrapper.updateDatasource(datasourceId1, 
req);
+        assertEquals(SeatunnelErrorEnum.ACCESS_DENIED.getCode(), 
updateResult.getCode());
+
+        accessTypes.clear();
+        accessTypes.add(AccessType.UPDATE);
+        AccessControllerTestingImp.resetResourcePermission(
+                user1,
+                new ResourcePermissionData(
+                        workspaceName, datasourceName1, 
ResourceType.DATASOURCE, accessTypes));
+        updateResult = 
datasourceControllerWrapper.updateDatasource(datasourceId1, req);
+        assertTrue(updateResult.isSuccess());
+
+        // Handle delete operation
+        Result<Boolean> deleteResult = 
datasourceControllerWrapper.deleteDatasource(datasourceId1);
+        assertEquals(SeatunnelErrorEnum.ACCESS_DENIED.getCode(), 
deleteResult.getCode());
+
+        accessTypes.clear();
+        accessTypes.add(AccessType.DELETE);
+        AccessControllerTestingImp.resetResourcePermission(
+                user1,
+                new ResourcePermissionData(
+                        workspaceName, datasourceName1, 
ResourceType.DATASOURCE, accessTypes));
+        deleteResult = 
datasourceControllerWrapper.deleteDatasource(datasourceId1);
+        assertTrue(deleteResult.isSuccess());
+
+        // create again to use in list datasource
+        accessTypes.clear();
+        accessTypes.add(AccessType.CREATE);
+        AccessControllerTestingImp.resetResourcePermission(
+                user1,
+                new ResourcePermissionData(
+                        workspaceName, datasourceName1, 
ResourceType.DATASOURCE, accessTypes));
+        
datasourceControllerWrapper.createFakeSourceDatasource(datasourceName1);
+
+        // logout and login with another user
+        userControllerWrapper.logout();
+        login(new UserLoginReq(user2, pass, workspaceName));
+        // Handle list operation
+        String datasourceName2 = "2_datasource_access" + uniqueId;
+        accessTypes.clear();
+        accessTypes.add(AccessType.CREATE);
+        AccessControllerTestingImp.resetResourcePermission(
+                user2,
+                new ResourcePermissionData(
+                        workspaceName, datasourceName2, 
ResourceType.DATASOURCE, accessTypes));
+        String datasourceId2 =
+                
datasourceControllerWrapper.createFakeSourceDatasource(datasourceName2);
+        Result<PageInfo<DatasourceRes>> datasourceList =
+                datasourceControllerWrapper.getDatasourceList(
+                        "datasource_access" + uniqueId, "FakeSource", 1, 10);
+        assertTrue(datasourceList.isSuccess());
+        assertEquals(0, datasourceList.getData().getData().size());
+
+        accessTypes.clear();
+        accessTypes.add(AccessType.READ);
+        AccessControllerTestingImp.resetResourcePermission(
+                user2,
+                new ResourcePermissionData(
+                        workspaceName, datasourceName2, 
ResourceType.DATASOURCE, accessTypes));
+        datasourceList =
+                datasourceControllerWrapper.getDatasourceList(
+                        "datasource_access" + uniqueId, "FakeSource", 1, 10);
+        assertTrue(datasourceList.isSuccess());
+        assertEquals(1, datasourceList.getData().getData().size());
+        assertEquals(datasourceId2, 
datasourceList.getData().getData().get(0).getId());
+
+        // Give permission to user2 on datasource created by user1
+        AccessControllerTestingImp.addResourcePermission(
+                user2,
+                new ResourcePermissionData(
+                        workspaceName, datasourceName1, 
ResourceType.DATASOURCE, accessTypes));
+        datasourceList =
+                datasourceControllerWrapper.getDatasourceList(
+                        "datasource_access" + uniqueId, "FakeSource", 1, 10);
+        assertTrue(datasourceList.isSuccess());
+        assertEquals(2, datasourceList.getData().getData().size());
+    }
+
+    @Test
+    public void testJobAccessPermission() {
+        String user1 = "user_access_job_1" + uniqueId;
+        String user2 = "user_access_job_2" + uniqueId;
+        String pass = "somePassword";
+        String workspaceName = "workspace_access_job" + uniqueId;
+
+        // create workspaces and users using admin credentials
+        createWorkspaceAndUser(workspaceName, user1, pass);
+        createUserAndVerify(user2, pass);
+
+        login(new UserLoginReq(user1, pass, workspaceName));
+
+        // Handle create operation
+        String jobName1 = "1_job_access" + uniqueId;
+        jobDefinitionControllerWrapper.createJobExpectingFailure(jobName1);
+        List<AccessType> accessTypes = new ArrayList<>();
+        accessTypes.add(AccessType.CREATE);
+        AccessControllerTestingImp.resetResourcePermission(
+                user1,
+                new ResourcePermissionData(workspaceName, jobName1, 
ResourceType.JOB, accessTypes));
+        // should be successful as user1 has access to create job
+        Long jobId = 
jobDefinitionControllerWrapper.createJobDefinition(jobName1);
+
+        // Handle read operation
+        Result<JobDefinitionRes> getJob =
+                jobDefinitionControllerWrapper.getJobDefinitionById(jobId);
+        assertEquals(SeatunnelErrorEnum.ACCESS_DENIED.getCode(), 
getJob.getCode());
+
+        Result<JobConfigRes> getJobConfig = 
jobConfigControllerWrapper.getJobConfig(jobId);
+        assertEquals(SeatunnelErrorEnum.ACCESS_DENIED.getCode(), 
getJobConfig.getCode());
+
+        accessTypes.clear();
+        accessTypes.add(AccessType.READ);
+        AccessControllerTestingImp.resetResourcePermission(
+                user1,
+                new ResourcePermissionData(workspaceName, jobName1, 
ResourceType.JOB, accessTypes));
+        getJob = jobDefinitionControllerWrapper.getJobDefinitionById(jobId);
+        assertTrue(getJob.isSuccess());
+
+        getJobConfig = jobConfigControllerWrapper.getJobConfig(jobId);
+        assertTrue(getJobConfig.isSuccess());
+
+        // Handle update operation
+        AccessControllerTestingImp.clearPermission();
+        JobConfig jobConfig = 
jobConfigControllerWrapper.populateJobConfigObject(jobName1);
+        Result<Void> updateResult = 
jobConfigControllerWrapper.updateJobConfig(jobId, jobConfig);
+        assertEquals(SeatunnelErrorEnum.ACCESS_DENIED.getCode(), 
updateResult.getCode());
+
+        accessTypes.clear();
+        accessTypes.add(AccessType.UPDATE);
+        AccessControllerTestingImp.resetResourcePermission(
+                user1,
+                new ResourcePermissionData(workspaceName, jobName1, 
ResourceType.JOB, accessTypes));
+        updateResult = jobConfigControllerWrapper.updateJobConfig(jobId, 
jobConfig);
+        assertTrue(updateResult.isSuccess());
+
+        // Handle delete operation
+        Result<Void> deleteResult = 
jobDefinitionControllerWrapper.deleteJobDefinition(jobId);
+        assertEquals(SeatunnelErrorEnum.ACCESS_DENIED.getCode(), 
deleteResult.getCode());
+
+        accessTypes.clear();
+        accessTypes.add(AccessType.DELETE);
+        AccessControllerTestingImp.resetResourcePermission(
+                user1,
+                new ResourcePermissionData(workspaceName, jobName1, 
ResourceType.JOB, accessTypes));
+        deleteResult = 
jobDefinitionControllerWrapper.deleteJobDefinition(jobId);
+        assertTrue(deleteResult.isSuccess());
+
+        // create again to use in list job
+        accessTypes.clear();
+        accessTypes.add(AccessType.CREATE);
+        AccessControllerTestingImp.resetResourcePermission(
+                user1,
+                new ResourcePermissionData(workspaceName, jobName1, 
ResourceType.JOB, accessTypes));
+        jobDefinitionControllerWrapper.createJobDefinition(jobName1);
+
+        // logout and login with another user
+        userControllerWrapper.logout();
+        login(new UserLoginReq(user2, pass, workspaceName));
+        // Handle list operation
+        String jobName2 = "2_job_access" + uniqueId;
+        accessTypes.clear();
+        accessTypes.add(AccessType.CREATE);
+        AccessControllerTestingImp.resetResourcePermission(
+                user2,
+                new ResourcePermissionData(workspaceName, jobName2, 
ResourceType.JOB, accessTypes));
+        Long jobId2 = 
jobDefinitionControllerWrapper.createJobDefinition(jobName2);
+        Result<PageInfo<JobDefinitionRes>> jobList =
+                jobDefinitionControllerWrapper.getJobDefinition(
+                        "job_access" + uniqueId, 1, 10, JobMode.BATCH);
+        assertTrue(jobList.isSuccess());
+        assertEquals(0, jobList.getData().getData().size());
+
+        accessTypes.clear();
+        accessTypes.add(AccessType.READ);
+        AccessControllerTestingImp.resetResourcePermission(
+                user2,
+                new ResourcePermissionData(workspaceName, jobName2, 
ResourceType.JOB, accessTypes));
+        jobList =
+                jobDefinitionControllerWrapper.getJobDefinition(
+                        "job_access" + uniqueId, 1, 10, JobMode.BATCH);
+        assertTrue(jobList.isSuccess());
+        assertEquals(1, jobList.getData().getData().size());
+        assertEquals(jobId2, jobList.getData().getData().get(0).getId());
+
+        // Give permission to user2 on job created by user1
+        AccessControllerTestingImp.addResourcePermission(
+                user2,
+                new ResourcePermissionData(workspaceName, jobName1, 
ResourceType.JOB, accessTypes));
+        jobList =
+                jobDefinitionControllerWrapper.getJobDefinition(
+                        "job_access" + uniqueId, 1, 10, JobMode.BATCH);
+        assertTrue(jobList.isSuccess());
+        assertEquals(2, jobList.getData().getData().size());
+    }
+
+    @Test
+    public void testJobExecutionAccessPermission() {
+        String userName = "jobExec_user_access" + uniqueId;
+        String pass = "somePassword";
+        String workspaceName = "jobExec_workspace_access" + uniqueId;
+
+        // create workspaces and users using admin credentials
+        createWorkspaceAndUser(workspaceName, userName, pass);
+
+        login(new UserLoginReq(userName, pass, workspaceName));
+
+        String jobName = "execJob_access" + uniqueId;
+        List<AccessType> accessTypes = new ArrayList<>();
+        accessTypes.add(AccessType.CREATE);
+        // job update api is called during job creation,
+        accessTypes.add(AccessType.UPDATE);
+        AccessControllerTestingImp.resetResourcePermission(
+                userName,
+                new ResourcePermissionData(workspaceName, jobName, 
ResourceType.JOB, accessTypes));
+        AccessControllerTestingImp.addResourcePermission(
+                userName,
+                new ResourcePermissionData(
+                        workspaceName,
+                        "source_" + jobName,
+                        ResourceType.DATASOURCE,
+                        Arrays.asList(AccessType.CREATE, AccessType.READ)));
+
+        AccessControllerTestingImp.addResourcePermission(
+                userName,
+                new ResourcePermissionData(
+                        workspaceName,
+                        "console_" + jobName,
+                        ResourceType.DATASOURCE,
+                        Arrays.asList(AccessType.CREATE, AccessType.READ)));
+
+        long jobVersionId = JobTestingUtils.createJob(jobName);
+
+        Result<Long> executionResult = 
jobExecutorControllerWrapper.jobExecutor(jobVersionId);
+        assertEquals(SeatunnelErrorEnum.ACCESS_DENIED.getCode(), 
executionResult.getCode());
+
+        accessTypes.add(AccessType.EXECUTE);
+        AccessControllerTestingImp.resetResourcePermission(
+                userName,
+                new ResourcePermissionData(workspaceName, jobName, 
ResourceType.JOB, accessTypes));
+        AccessControllerTestingImp.addResourcePermission(
+                userName,
+                new ResourcePermissionData(
+                        workspaceName,
+                        "source_" + jobName,
+                        ResourceType.DATASOURCE,
+                        Collections.singletonList(AccessType.READ)));
+
+        AccessControllerTestingImp.addResourcePermission(
+                userName,
+                new ResourcePermissionData(
+                        workspaceName,
+                        "console_" + jobName,
+                        ResourceType.DATASOURCE,
+                        Collections.singletonList(AccessType.READ)));
+        executionResult = 
jobExecutorControllerWrapper.jobExecutor(jobVersionId);
+        assertTrue(executionResult.isSuccess(), executionResult.getMsg());
+    }
+
+    @Test
+    public void testJobAccessPermissionForSingleJobCreateAPI() {
+        String user1 = "user_access_single_job_1" + uniqueId;
+        String user2 = "user_access_single_job_2" + uniqueId;
+        String pass = "somePassword";
+        String workspaceName = "workspace_access_single_job" + uniqueId;
+
+        // create workspaces and users using admin credentials
+        createWorkspaceAndUser(workspaceName, user1, pass);
+        createUserAndVerify(user2, pass);
+
+        login(new UserLoginReq(user1, pass, workspaceName));
+
+        // Handle create operation
+        String jobName = "access_single_api" + uniqueId;
+        String fsdSourceName = "fake_source_create" + uniqueId;
+        String csSourceName = "console_create" + uniqueId;
+        List<AccessType> accessTypes = new ArrayList<>();
+        accessTypes.add(AccessType.CREATE);
+        AccessControllerTestingImp.resetResourcePermission(
+                user1,
+                new ResourcePermissionData(
+                        workspaceName, fsdSourceName, ResourceType.DATASOURCE, 
accessTypes));
+
+        AccessControllerTestingImp.addResourcePermission(
+                user1,
+                new ResourcePermissionData(
+                        workspaceName, csSourceName, ResourceType.DATASOURCE, 
accessTypes));
+        JobCreateReq jobCreateReq =
+                JobTestingUtils.populateJobCreateReqFromFile(jobName, 
fsdSourceName, csSourceName);
+        Result<Long> jobCreation = 
jobControllerWrapper.createJob(jobCreateReq);
+        assertEquals(SeatunnelErrorEnum.ACCESS_DENIED.getCode(), 
jobCreation.getCode());
+
+        accessTypes.clear();
+        accessTypes.add(AccessType.CREATE);
+        AccessControllerTestingImp.resetResourcePermission(
+                user1,
+                new ResourcePermissionData(workspaceName, jobName, 
ResourceType.JOB, accessTypes));
+
+        AccessControllerTestingImp.addResourcePermission(
+                user1,
+                new ResourcePermissionData(
+                        workspaceName,
+                        fsdSourceName,
+                        ResourceType.DATASOURCE,
+                        Collections.singletonList(AccessType.READ)));
+
+        AccessControllerTestingImp.addResourcePermission(
+                user1,
+                new ResourcePermissionData(
+                        workspaceName,
+                        csSourceName,
+                        ResourceType.DATASOURCE,
+                        Collections.singletonList(AccessType.READ)));
+        jobCreation = jobControllerWrapper.createJob(jobCreateReq);
+        assertTrue(jobCreation.isSuccess());
+
+        // Handle read operation
+        Result<JobRes> getJobResponse = 
jobControllerWrapper.getJob(jobCreation.getData());
+        assertEquals(SeatunnelErrorEnum.ACCESS_DENIED.getCode(), 
getJobResponse.getCode());
+
+        accessTypes.clear();
+        accessTypes.add(AccessType.READ);
+        AccessControllerTestingImp.resetResourcePermission(
+                user1,
+                new ResourcePermissionData(workspaceName, jobName, 
ResourceType.JOB, accessTypes));
+        getJobResponse = jobControllerWrapper.getJob(jobCreation.getData());
+        assertTrue(getJobResponse.isSuccess(), getJobResponse.getMsg());
+
+        // Handle update operation
+        JobCreateReq jobUpdateReq =
+                
jobControllerWrapper.convertJobResToJobCreateReq(getJobResponse.getData());
+        Result<Void> updateResult =
+                jobControllerWrapper.updateJob(jobCreation.getData(), 
jobUpdateReq);
+        assertEquals(SeatunnelErrorEnum.ACCESS_DENIED.getCode(), 
updateResult.getCode());
+
+        accessTypes.clear();
+        accessTypes.add(AccessType.UPDATE);
+        AccessControllerTestingImp.resetResourcePermission(
+                user1,
+                new ResourcePermissionData(workspaceName, jobName, 
ResourceType.JOB, accessTypes));
+        AccessControllerTestingImp.addResourcePermission(
+                user1,
+                new ResourcePermissionData(
+                        workspaceName,
+                        fsdSourceName,
+                        ResourceType.DATASOURCE,
+                        Collections.singletonList(AccessType.READ)));
+
+        AccessControllerTestingImp.addResourcePermission(
+                user1,
+                new ResourcePermissionData(
+                        workspaceName,
+                        csSourceName,
+                        ResourceType.DATASOURCE,
+                        Collections.singletonList(AccessType.READ)));
+        updateResult = jobControllerWrapper.updateJob(jobCreation.getData(), 
jobUpdateReq);
+        assertTrue(updateResult.isSuccess(), updateResult.getMsg());
+    }
+
+    private void createWorkspaceAndUser(String workspaceName, String username, 
String password) {
+        AccessControllerTestingImp.resetResourcePermission(
+                "admin",
+                new ResourcePermissionData(
+                        null,
+                        workspaceName,
+                        ResourceType.WORKSPACE,
+                        Arrays.asList(AccessType.CREATE, AccessType.UPDATE)));
+        workspaceControllerWrapper.createWorkspaceAndVerify(workspaceName);
+        createUserAndVerify(username, password);
+    }
+
+    private void createUserAndVerify(String username, String password) {
+        AccessControllerTestingImp.addResourcePermission(
+                "admin",
+                new ResourcePermissionData(
+                        null,
+                        username,
+                        ResourceType.USER,
+                        Collections.singletonList(AccessType.CREATE)));
+        Result<AddUserRes> result =
+                userControllerWrapper.addUser(getAddUserReq(username, 
password));
+        assertTrue(result.isSuccess());
+    }
+
+    private static void login(UserLoginReq userLoginReq) {
+        Result<UserSimpleInfoRes> login = 
userControllerWrapper.login(userLoginReq, null, true);
+        assertTrue(login.isSuccess());
+    }
+
+    private AddUserReq getAddUserReq(String user, String pass) {
+        AddUserReq addUserReq = new AddUserReq();
+        addUserReq.setUsername(user);
+        addUserReq.setPassword(pass);
+        addUserReq.setStatus((byte) 0);
+        addUserReq.setType((byte) 0);
+        return addUserReq;
+    }
+
+    @AfterEach
+    public void cleanup() {
+        userControllerWrapper.logout();
+        AccessControllerTestingImp.clearPermission();
+    }
+
+    @AfterAll
+    public static void tearDown() {
+        AccessControllerTestingImp.disableAccessController();
+        seaTunnelWebCluster.stop();
+    }
+}
diff --git a/seatunnel-web-it/src/test/resources/application.yml 
b/seatunnel-web-it/src/test/resources/application.yml
index 752fbc7b..d691a712 100644
--- a/seatunnel-web-it/src/test/resources/application.yml
+++ b/seatunnel-web-it/src/test/resources/application.yml
@@ -55,6 +55,7 @@ seatunnel-web:
       keys-to-encrypt:
         - password
         - auth
+  access-controller-class: 
org.apache.seatunnel.app.common.AccessControllerTestingImp
 
 ---
 spring:


Reply via email to