You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@streampark.apache.org by be...@apache.org on 2024/06/01 03:17:19 UTC

(incubator-streampark) branch dev updated: [Improve] sync code from branch 2.1.4 (#3729)

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

benjobs pushed a commit to branch dev
in repository https://gitbox.apache.org/repos/asf/incubator-streampark.git


The following commit(s) were added to refs/heads/dev by this push:
     new 83824b4b2 [Improve] sync code from branch 2.1.4 (#3729)
83824b4b2 is described below

commit 83824b4b2015490bb1348937192e5b855c9848e4
Author: benjobs <be...@apache.org>
AuthorDate: Sat Jun 1 11:17:15 2024 +0800

    [Improve] sync code from branch 2.1.4 (#3729)
    
    * [Impove] sync from 2.1.4
    
    * [Improve] CommonService rename to ServiceHelper
    
    * [Improve] application entity drop appId column
    
    * [Improve] DingTalk alert bug fixed
    
    * [Improve] license header improvement
    
    * [Improve] token FE page improvement
    
    * [Improve] sql query "like" bug fixed.
    
    * [Improve] PermissionScope annotation user field default value bug fixed.
    
    * [Improve] freemarker bug fixed.
    
    * [Improve] token page minor improvement
    
    * [Improve] trivial improvements
    
    ---------
    
    Co-authored-by: benjobs <be...@gmail.com>
---
 .../apache/streampark/common/conf/ConfigKeys.scala |   2 +
 .../src/main/assembly/bin/jvm_opts.sh              |   3 +
 .../src/main/assembly/bin/streampark.sh            | 168 ++++++++----------
 .../console/base/config/MybatisConfig.java         |  20 ++-
 .../console/base/config/OpenapiConfig.java         |  14 +-
 .../console/base/domain/ApiDocConstant.java        |   2 +-
 .../console/base/domain/ResponseCode.java          |   2 +
 .../base/handler/GlobalExceptionHandler.java       |  46 ++---
 .../console/base/properties/ShiroProperties.java   |  33 ----
 .../console/base/util/BashJavaUtils.java           |  54 ++++++
 .../console/base/util/FreemarkerUtils.java         |  23 ++-
 .../apache/streampark/console/base/util/Tuple.java |  62 +++++++
 .../streampark/console/base/util/Tuple1.java       | 113 +++++++++++++
 .../streampark/console/base/util/Tuple2.java       | 163 ++++++++++++++++++
 .../streampark/console/base/util/Tuple3.java       | 171 +++++++++++++++++++
 .../streampark/console/base/util/Tuple4.java       | 187 +++++++++++++++++++++
 .../console/core/annotation/AppUpdated.java        |   4 +-
 .../annotation/{ApiAccess.java => OpenAPI.java}    |   2 +-
 ...{PermissionAction.java => PermissionScope.java} |  15 +-
 .../{ConsoleAspect.java => StreamParkAspect.java}  | 100 ++++++-----
 .../console/core/bean/AlertTemplate.java           |   4 +-
 .../console/core/controller/AlertController.java   |  14 --
 .../ApplicationBuildPipelineController.java        |  36 +---
 .../core/controller/ApplicationController.java     | 164 ++++++------------
 .../controller/ApplicationHistoryController.java   |  10 --
 .../console/core/controller/ConfigController.java  |   9 -
 .../core/controller/ExternalLinkController.java    |  14 --
 .../core/controller/FlinkClusterController.java    |  13 --
 .../core/controller/FlinkEnvController.java        |  12 --
 .../core/controller/FlinkGateWayController.java    |  10 --
 .../controller/FlinkPodTemplateController.java     |   8 -
 .../core/controller/FlinkSqlController.java        |  31 ++--
 .../console/core/controller/MessageController.java |   5 -
 .../console/core/controller/ProjectController.java |  64 +++----
 .../core/controller/ResourceController.java        |  10 --
 .../core/controller/SavePointController.java       |  50 +-----
 .../console/core/controller/SettingController.java |  13 --
 .../SparkApplicationBuildPipelineController.java   |  10 +-
 .../controller/SparkApplicationController.java     |  55 +-----
 .../core/controller/SparkEnvController.java        |  12 --
 .../core/controller/SqlWorkBenchController.java    |  36 ----
 .../core/controller/VariableController.java        |  11 --
 .../core/controller/YarnQueueController.java       |  16 --
 .../console/core/entity/Application.java           |  21 ++-
 ...issionTypeEnum.java => AuthenticationType.java} |  20 +--
 .../CommonServiceImpl.java => ServiceHelper.java}  |  79 ++++++---
 .../alert/impl/DingTalkAlertNotifyServiceImpl.java |  98 +++++------
 .../alert/impl/LarkAlertNotifyServiceImpl.java     |   1 +
 .../impl/ApplicationActionServiceImpl.java         |  77 ++++++---
 .../impl/ApplicationManageServiceImpl.java         |  87 +++++-----
 .../impl/SparkApplicationActionServiceImpl.java    |  13 +-
 .../impl/SparkApplicationManageServiceImpl.java    |   8 +-
 .../core/service/impl/AppBuildPipeServiceImpl.java |  10 +-
 .../core/service/impl/ExternalLinkServiceImpl.java |   2 +-
 .../core/service/impl/FlinkClusterServiceImpl.java |   6 +-
 .../core/service/impl/ResourceServiceImpl.java     |   6 +-
 .../core/service/impl/SavePointServiceImpl.java    |  15 +-
 .../service/impl/SparkAppBuildPipeServiceImpl.java |  10 +-
 .../core/service/impl/VariableServiceImpl.java     |   6 +-
 .../console/core/watcher/FlinkAppHttpWatcher.java  |   8 +-
 .../console/system/authentication/JWTFilter.java   |  40 ++---
 .../console/system/authentication/JWTToken.java    |   6 +-
 .../console/system/authentication/JWTUtil.java     | 106 +++++++-----
 .../console/system/authentication/ShiroConfig.java |  70 ++++----
 .../console/system/authentication/ShiroRealm.java  |  29 ++--
 .../system/controller/AccessTokenController.java   |  74 +-------
 .../system/controller/MemberController.java        |  19 +--
 .../console/system/controller/MenuController.java  |  11 +-
 .../system/controller/PassportController.java      |  63 +++++--
 .../console/system/controller/RoleController.java  |   9 -
 .../console/system/controller/TeamController.java  |   8 -
 .../console/system/controller/UserController.java  |  35 ++--
 .../console/system/service/AccessTokenService.java |   4 +-
 .../console/system/service/UserService.java        |   2 +
 .../service/impl/AccessTokenServiceImpl.java       |  35 ++--
 .../system/service/impl/TeamServiceImpl.java       |   6 +-
 .../system/service/impl/UserServiceImpl.java       |  74 ++++----
 .../resources/mapper/core/ApplicationMapper.xml    |  50 +++---
 .../main/resources/mapper/core/ProjectMapper.xml   |   7 +-
 .../main/resources/mapper/core/VariableMapper.xml  |  27 ++-
 .../main/resources/mapper/core/YarnQueueMapper.xml |   7 +-
 .../main/resources/mapper/system/MemberMapper.xml  |  11 +-
 .../main/resources/mapper/system/RoleMapper.xml    |   7 +-
 .../main/resources/mapper/system/TeamMapper.xml    |   7 +-
 .../main/resources/mapper/system/UserMapper.xml    |  72 ++++++--
 .../core/service/AccessTokenServiceTest.java       |   4 +-
 .../core/service/alert/AlertServiceTest.java       |   4 +-
 .../console/system/authentication/JWTTest.java     |   3 +
 .../src/api/flink/flinkSql.ts                      |   2 +-
 .../src/api/flink/savepoint.ts                     |   2 +-
 .../src/api/system/model/tokenModel.ts             |   2 -
 .../Application/src/AppDarkModeToggle.vue          |   4 +-
 .../src/components/ContextMenu/src/ContextMenu.vue |   4 +-
 .../src/components/Form/src/BasicForm.vue          |   2 +-
 .../components/Form/src/components/FormItem.vue    |   8 +-
 .../Modal/src/components/ModalWrapper.vue          |   4 +-
 .../src/components/Page/src/PageFooter.vue         |   4 +-
 .../components/Table/src/components/HeaderCell.vue |   2 +-
 .../src/hooks/setting/useMenuSetting.ts            |  10 +-
 .../src/hooks/web/useLockPage.ts                   |   9 +-
 .../src/locales/lang/en/flink/app.ts               |  21 ++-
 .../src/locales/lang/en/system/token.ts            |   1 -
 .../src/locales/lang/zh-CN/flink/app.ts            |   7 +
 .../src/locales/lang/zh-CN/system/token.ts         |   1 -
 .../streampark-console-webapp/src/utils/props.ts   |  53 +++---
 .../src/views/base/error-log/data.tsx              |  12 +-
 .../src/views/base/login/Login.vue                 |  27 ++-
 .../src/views/base/login/LoginForm.vue             |   4 +-
 .../src/views/flink/app/EditFlink.vue              |  17 +-
 .../src/views/flink/app/EditStreamPark.vue         |  31 ++--
 .../src/views/flink/app/View.vue                   |   5 -
 .../src/views/flink/app/components/AppConf.tsx     |   4 +-
 .../flink/app/components/AppDetail/DetailTab.vue   | 101 ++++++-----
 .../components/AppDetail/FlinkSqlCompareModal.vue  |   6 +-
 .../flink/app/components/AppView/AppDashboard.vue  |  14 +-
 .../components/AppView/StopApplicationModal.vue    |  50 ++----
 .../src/views/flink/app/components/Dependency.vue  |  23 +--
 .../src/views/flink/app/components/FlinkSql.vue    |  41 ++---
 .../src/views/flink/app/components/State.tsx       |   8 +-
 .../src/views/flink/app/data/detail.data.ts        |   2 +-
 .../src/views/flink/app/data/index.ts              |   1 +
 .../flink/app/hooks/useCreateAndEditSchema.ts      |  85 +++-------
 .../src/views/flink/app/hooks/useDetail.ts         |   2 +-
 .../src/views/flink/app/hooks/useEditStreamPark.ts |   7 +-
 .../src/views/flink/app/hooks/useFlinkRender.tsx   |  37 +++-
 .../src/views/flink/app/styles/Add.less            |   4 +-
 .../src/views/flink/app/styles/View.less           |   4 +-
 .../src/views/flink/app/utils/Pom.ts               |  77 +++------
 .../src/views/flink/app/utils/index.ts             |  24 ++-
 .../src/views/system/token/token.data.ts           |  14 --
 .../streampark/flink/client/FlinkClient.scala      |   6 +-
 ...tEndpoint.scala => FlinkClientEntrypoint.scala} |   2 +-
 132 files changed, 2122 insertions(+), 1670 deletions(-)

diff --git a/streampark-common/src/main/scala/org/apache/streampark/common/conf/ConfigKeys.scala b/streampark-common/src/main/scala/org/apache/streampark/common/conf/ConfigKeys.scala
index fb189db50..d28893a0e 100644
--- a/streampark-common/src/main/scala/org/apache/streampark/common/conf/ConfigKeys.scala
+++ b/streampark-common/src/main/scala/org/apache/streampark/common/conf/ConfigKeys.scala
@@ -40,6 +40,8 @@ object ConfigKeys {
   /** kerberos */
   val KEY_KERBEROS = "kerberos"
 
+  val KEY_KERBEROS_SERVICE_ACCOUNT = "kubernetes.service-account"
+
   val KEY_HADOOP_USER_NAME = "HADOOP_USER_NAME"
 
   /** hadoop.security.authentication */
diff --git a/streampark-console/streampark-console-service/src/main/assembly/bin/jvm_opts.sh b/streampark-console/streampark-console-service/src/main/assembly/bin/jvm_opts.sh
index 93fc9083e..2654c1751 100644
--- a/streampark-console/streampark-console-service/src/main/assembly/bin/jvm_opts.sh
+++ b/streampark-console/streampark-console-service/src/main/assembly/bin/jvm_opts.sh
@@ -17,6 +17,7 @@
 # specific language governing permissions and limitations
 # under the License.
 
+-server
 -Xms1g
 -Xmx1g
 -Xmn512m
@@ -33,3 +34,5 @@
 -XX:GCLogFileSize=50M
 -XX:NumberOfGCLogFiles=10
 
+# solved jdk1.8+ dynamic loading of resources to the classpath issue, if jdk > 1.8, you can enable this parameter
+#--add-opens java.base/jdk.internal.loader=ALL-UNNAMED --add-opens jdk.zipfs/jdk.nio.zipfs=ALL-UNNAMED
diff --git a/streampark-console/streampark-console-service/src/main/assembly/bin/streampark.sh b/streampark-console/streampark-console-service/src/main/assembly/bin/streampark.sh
index 5791ec333..f3f301be5 100755
--- a/streampark-console/streampark-console-service/src/main/assembly/bin/streampark.sh
+++ b/streampark-console/streampark-console-service/src/main/assembly/bin/streampark.sh
@@ -35,6 +35,13 @@
 #                   used
 # -----------------------------------------------------------------------------
 
+# Bugzilla 37848: When no TTY is available, don't output to console
+have_tty=0
+# shellcheck disable=SC2006
+if [[ "`tty`" != "not a tty" ]]; then
+    have_tty=1
+fi
+
 # Bugzilla 37848: When no TTY is available, don't output to console
 have_tty=0
 # shellcheck disable=SC2006
@@ -203,7 +210,7 @@ fi
 
 # Add on extra jar files to CLASSPATH
 # shellcheck disable=SC2236
-if [ ! -z "$CLASSPATH" ]; then
+if [[ ! -z "$CLASSPATH" ]]; then
   CLASSPATH="$CLASSPATH":
 fi
 CLASSPATH="$CLASSPATH"
@@ -222,7 +229,7 @@ if ${cygwin}; then
   CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
 fi
 
-if [ -z "$USE_NOHUP" ]; then
+if [[ -z "$USE_NOHUP" ]]; then
   if $hpux; then
     USE_NOHUP="true"
   else
@@ -230,18 +237,18 @@ if [ -z "$USE_NOHUP" ]; then
   fi
 fi
 unset NOHUP
-if [ "$USE_NOHUP" = "true" ]; then
+if [[ "$USE_NOHUP" = "true" ]]; then
   NOHUP="nohup"
 fi
 
-PARAM_CLI="org.apache.streampark.flink.core.conf.ParameterCli"
+BASH_UTIL="org.apache.streampark.console.base.util.BashJavaUtils"
 
 APP_MAIN="org.apache.streampark.console.StreamParkConsoleBootstrap"
 
 JVM_OPTS_FILE=${APP_HOME}/bin/jvm_opts.sh
 
-JVM_ARGS="-server"
-if [ -f $JVM_OPTS_FILE ]; then
+JVM_ARGS=""
+if [[ -f $JVM_OPTS_FILE ]]; then
   while read line
   do
       if [[ "$line" == -* ]]; then
@@ -265,39 +272,38 @@ print_logo() {
   printf '      %s  ___/ / /_/ /  /  __/ /_/ / / / / / / /_/ / /_/ / /  / ,<        %s\n'          $PRIMARY $RESET
   printf '      %s /____/\__/_/   \___/\__,_/_/ /_/ /_/ ____/\__,_/_/  /_/|_|       %s\n'          $PRIMARY $RESET
   printf '      %s                                   /_/                            %s\n\n'        $PRIMARY $RESET
-  printf '      %s   Version:  2.2.0 %s\n'                                                         $BLUE   $RESET
+  printf '      %s   Version:  2.1.4 %s\n'                                                         $BLUE   $RESET
   printf '      %s   WebSite:  https://streampark.apache.org%s\n'                                  $BLUE   $RESET
   printf '      %s   GitHub :  http://github.com/apache/streampark%s\n\n'                          $BLUE   $RESET
   printf '      %s   ──────── Apache StreamPark, Make stream processing easier ô~ô!%s\n\n'         $PRIMARY  $RESET
 }
 
-parse_yaml() {
-   local prefix=$2
-   local s='[[:space:]]*' w='[a-zA-Z0-9_]*' fs=$(echo @|tr @ '\034')
-   sed -ne "s|^\($s\):|\1|" \
-        -e "s|^\($s\)\($w\)$s:$s[\"']\(.*\)[\"']$s\$|\1$fs\2$fs\3|p" \
-        -e "s|^\($s\)\($w\)$s:$s\(.*\)$s\$|\1$fs\2$fs\3|p"  $1 |
-   awk -F$fs '{
-      indent = length($1)/2;
-      vname[indent] = $2;
-      for (i in vname) {if (i > indent) {delete vname[i]}}
-      if (length($3) > 0) {
-         vn=""; for (i=0; i<indent; i++) {vn=(vn)(vname[i])("_")}
-         printf("%s%s%s=\"%s\"\n", "'$prefix'",vn, $2, $3);
-      }
-   }'
+init_env() {
+  # shellcheck disable=SC2006
+  CONFIG="${APP_CONF}/application.yml"
+  if [[ -f "$CONFIG" ]] ; then
+    echo_y """[WARN] in the \"conf\" directory, found the \"application.yml\" file. The \"application.yml\" file is deprecated.
+       For compatibility, this application.yml will be used preferentially. The latest configuration file is \"config.yaml\". It is recommended to use \"config.yaml\".
+       Note: \"application.yml\" will be completely deprecated in version 2.2.0. """
+  else
+    CONFIG="${APP_CONF}/config.yaml"
+    if [[ ! -f "$CONFIG" ]] ; then
+      echo_r "can not found config.yaml in \"conf\" directory, please check."
+      exit 1;
+    fi
+  fi
 }
 
 # shellcheck disable=SC2120
 get_pid() {
-  if [ -f "$APP_PID" ]; then
-    if [ -s "$APP_PID" ]; then
+  if [[ -f "$APP_PID" ]]; then
+    if [[ -s "$APP_PID" ]]; then
       # shellcheck disable=SC2155
       # shellcheck disable=SC2006
       local PID=`cat "$APP_PID"`
       kill -0 $PID >/dev/null 2>&1
       # shellcheck disable=SC2181
-      if [ $? -eq 0 ]; then
+      if [[ $? -eq 0 ]]; then
         echo $PID
         exit 0
       fi
@@ -307,31 +313,25 @@ get_pid() {
   fi
 
   # shellcheck disable=SC2006
-  local PROPER="${APP_CONF}/application.yml"
-  if [[ ! -f "$PROPER" ]] ; then
-    echo_r "ERROR: config file application.yml invalid or not found! ";
+  local serverPort=`$_RUNJAVA -cp "$APP_LIB/*" $BASH_UTIL --get_yaml "server.port" "$CONFIG"`
+  if [[ x"${serverPort}" == x"" ]]; then
+    echo_r "server.port is required, please check $CONFIG"
     exit 1;
-  fi
-
-  # shellcheck disable=SC2046
-  eval $(parse_yaml "${PROPER}" "conf_")
-  # shellcheck disable=SC2154
-  # shellcheck disable=SC2155
-  # shellcheck disable=SC2116
-  local serverPort=$(echo "$conf_server_port")
-  # shellcheck disable=SC2006
-  # shellcheck disable=SC2155
-  local used=`lsof -i:"$serverPort" | wc -l`
-  if [ "$used" -gt 0 ]; then
-    # shellcheck disable=SC2006
-    local PID=`jps -l | grep "$APP_MAIN" | awk '{print $1}'`
-    if [ ! -z $PID ]; then
-      echo $PID
-    else
-      echo 0
-    fi
   else
-    echo 0
+     # shellcheck disable=SC2006
+      # shellcheck disable=SC2155
+      local used=`$_RUNJAVA -cp "$APP_LIB/*" $BASH_UTIL --check_port "$serverPort"`
+      if [[ x"${used}" == x"used" ]]; then
+        # shellcheck disable=SC2006
+        local PID=`jps -l | grep "$APP_MAIN" | awk '{print $1}'`
+        if [[ ! -z $PID ]]; then
+          echo $PID
+        else
+          echo 0
+        fi
+      else
+        echo 0
+      fi
   fi
 }
 
@@ -340,7 +340,7 @@ start() {
   # shellcheck disable=SC2006
   local PID=$(get_pid)
 
-  if [ $PID -gt 0 ]; then
+  if [[ $PID -gt 0 ]]; then
     # shellcheck disable=SC2006
     echo_r "StreamPark is already running pid: $PID , start aborted!"
     exit 1
@@ -358,31 +358,20 @@ start() {
     echo_w "Using APP_PID:   $APP_PID"
   fi
 
-  local PROPER="${APP_CONF}/application.yml"
-  if [[ ! -f "$PROPER" ]] ; then
-    echo_r "ERROR: config file application.yml invalid or not found! ";
-    exit 1;
-  else
-    echo_g "Usage: config file: $PROPER ";
-  fi
+   # shellcheck disable=SC2006
+   local workspace=`$_RUNJAVA -cp "$APP_LIB/*" $BASH_UTIL --get_yaml "streampark.workspace.local" "$CONFIG"`
+   if [[ ! -d $workspace ]]; then
+     echo_r "ERROR: streampark.workspace.local: \"$workspace\" is invalid path, Please reconfigure in $CONFIG"
+     echo_r "NOTE: \"streampark.workspace.local\" Do not set under APP_HOME($APP_HOME). Set it to a secure directory outside of APP_HOME.  "
+     exit 1;
+   fi
 
-  # shellcheck disable=SC2046
-  eval $(parse_yaml "${PROPER}" "conf_")
-  # shellcheck disable=SC2001
-  # shellcheck disable=SC2154
-  # shellcheck disable=SC2155
-  local workspace=$(echo "$conf_streampark_workspace_local" | sed 's/#.*$//g')
-  if [[ ! -d $workspace ]]; then
-    echo_r "ERROR: streampark.workspace.local: \"$workspace\" is invalid path, Please reconfigure in application.yml"
-    echo_r "NOTE: \"streampark.workspace.local\" Do not set under APP_HOME($APP_HOME). Set it to a secure directory outside of APP_HOME.  "
-    exit 1;
-  fi
   if [[ ! -w $workspace ]] || [[ ! -r $workspace ]]; then
       echo_r "ERROR: streampark.workspace.local: \"$workspace\" Permission denied! "
       exit 1;
   fi
 
-  if [ "${HADOOP_HOME}"x == ""x ]; then
+  if [[ "${HADOOP_HOME}"x == ""x ]]; then
     echo_y "WARN: HADOOP_HOME is undefined on your system env,please check it."
   else
     echo_w "Using HADOOP_HOME:   ${HADOOP_HOME}"
@@ -413,9 +402,7 @@ start() {
   # shellcheck disable=SC2034
   # shellcheck disable=SC2006
   # shellcheck disable=SC2155
-  local ADD_OPENS=`$_RUNJAVA -cp "$APP_CLASSPATH" $PARAM_CLI --vmopt`
-
-  local JAVA_OPTS="$ADD_OPENS $JVM_OPTS $DEBUG_OPTS"
+  local JAVA_OPTS="$JVM_OPTS $DEBUG_OPTS"
 
   echo_g "JAVA_OPTS:  ${JAVA_OPTS}"
 
@@ -423,7 +410,6 @@ start() {
     -classpath "$APP_CLASSPATH" \
     -Dapp.home="${APP_HOME}" \
     -Dlogging.config="${APP_CONF}/logback-spring.xml" \
-    -Dspring.config.location="${PROPER}" \
     -Djava.io.tmpdir="$APP_TMPDIR" \
     $APP_MAIN >> "$APP_OUT" 2>&1 "&"
 
@@ -455,15 +441,7 @@ start_docker() {
     echo_w "Using APP_PID:   $APP_PID"
   fi
 
-  local PROPER="${APP_CONF}/application.yml"
-  if [[ ! -f "$PROPER" ]] ; then
-    echo_r "ERROR: config file application.yml invalid or not found! ";
-    exit 1;
-  else
-    echo_g "Usage: config file: $PROPER ";
-  fi
-
-  if [ "${HADOOP_HOME}"x == ""x ]; then
+  if [[ "${HADOOP_HOME}"x == ""x ]]; then
     echo_y "WARN: HADOOP_HOME is undefined on your system env,please check it."
   else
     echo_w "Using HADOOP_HOME:   ${HADOOP_HOME}"
@@ -490,14 +468,9 @@ start_docker() {
     APP_CLASSPATH+=":${HADOOP_HOME}/etc/hadoop"
   fi
 
-  # shellcheck disable=SC2034
-  # shellcheck disable=SC2006
-  # shellcheck disable=SC2155
-  local ADD_OPENS=`$_RUNJAVA -cp "$APP_CLASSPATH" $PARAM_CLI --vmopt`
-
   JVM_OPTS="${JVM_OPTS} -XX:-UseContainerSupport"
 
-  local JAVA_OPTS="$ADD_OPENS $JVM_OPTS $DEBUG_OPTS"
+  local JAVA_OPTS="$JVM_OPTS $DEBUG_OPTS"
 
   echo_g "JAVA_OPTS:  ${JAVA_OPTS}"
 
@@ -505,14 +478,14 @@ start_docker() {
     -classpath "$APP_CLASSPATH" \
     -Dapp.home="${APP_HOME}" \
     -Dlogging.config="${APP_CONF}/logback-spring.xml" \
-    -Dspring.config.location="${PROPER}" \
     -Djava.io.tmpdir="$APP_TMPDIR" \
     $APP_MAIN
 
 }
 
 debug() {
-  if [ ! -n "$DEBUG_PORT" ]; then
+  # shellcheck disable=SC2236
+  if [[ ! -n "$DEBUG_PORT" ]]; then
     echo_r "If start with debug mode,Please fill in the debug port like: bash streampark.sh debug 10002 "
   else
     DEBUG_OPTS="""
@@ -540,17 +513,17 @@ stop() {
   # shellcheck disable=SC2006
   echo_g "StreamPark stopping with the PID: $PID"
 
-  kill -9 $PID
+  kill -9 "$PID"
 
   while [ $SLEEP -ge 0 ]; do
     # shellcheck disable=SC2046
     # shellcheck disable=SC2006
-    kill -0 $PID >/dev/null 2>&1
+    kill -0 "$PID" >/dev/null 2>&1
     # shellcheck disable=SC2181
-    if [ $? -gt 0 ]; then
+    if [[ $? -gt 0 ]]; then
       rm -f "$APP_PID" >/dev/null 2>&1
-      if [ $? != 0 ]; then
-        if [ -w "$APP_PID" ]; then
+      if [[ $? != 0 ]]; then
+        if [[ -w "$APP_PID" ]]; then
           cat /dev/null > "$APP_PID"
         else
           echo_r "The PID file could not be removed."
@@ -560,7 +533,7 @@ stop() {
       break
     fi
 
-    if [ $SLEEP -gt 0 ]; then
+    if [[ $SLEEP -gt 0 ]]; then
        sleep 1
     fi
     # shellcheck disable=SC2006
@@ -568,7 +541,7 @@ stop() {
     SLEEP=`expr $SLEEP - 1 `
   done
 
-  if [ "$SLEEP" -lt 0 ]; then
+  if [[ "$SLEEP" -lt 0 ]]; then
      echo_r "StreamPark has not been killed completely yet. The process might be waiting on some system call or might be UNINTERRUPTIBLE."
   fi
 }
@@ -577,7 +550,7 @@ status() {
   # shellcheck disable=SC2155
   # shellcheck disable=SC2006
   local PID=$(get_pid)
-  if [ $PID -eq 0 ]; then
+  if [[ $PID -eq 0 ]]; then
     echo_r "StreamPark is not running"
   else
     echo_g "StreamPark is running pid is: $PID"
@@ -593,6 +566,7 @@ restart() {
 
 main() {
   print_logo
+  init_env
   case "$1" in
     "debug")
         DEBUG_PORT=$2
diff --git a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/base/config/MybatisConfig.java b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/base/config/MybatisConfig.java
index df9b4f3e7..1999f4127 100644
--- a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/base/config/MybatisConfig.java
+++ b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/base/config/MybatisConfig.java
@@ -20,6 +20,8 @@ package org.apache.streampark.console.base.config;
 import org.apache.streampark.console.base.mybatis.interceptor.PostgreSQLPrepareInterceptor;
 import org.apache.streampark.console.base.mybatis.interceptor.PostgreSQLQueryInterceptor;
 
+import org.apache.ibatis.mapping.DatabaseIdProvider;
+import org.apache.ibatis.mapping.VendorDatabaseIdProvider;
 import org.apache.ibatis.type.JdbcType;
 
 import com.baomidou.mybatisplus.annotation.IdType;
@@ -34,6 +36,8 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
 
+import java.util.Properties;
+
 /** for MyBatis Configure management. */
 @Configuration
 @MapperScan(value = {"org.apache.streampark.console.*.mapper"})
@@ -52,7 +56,7 @@ public class MybatisConfig {
    * @return {@linkplain PostgreSQLQueryInterceptor}
    */
   @Bean
-  @ConditionalOnProperty(name = "spring.profiles.active", havingValue = "pgsql")
+  @ConditionalOnProperty(name = "datasource.dialect", havingValue = "pgsql")
   public PostgreSQLQueryInterceptor postgreSQLQueryInterceptor() {
     return new PostgreSQLQueryInterceptor();
   }
@@ -63,7 +67,7 @@ public class MybatisConfig {
    * @return {@linkplain PostgreSQLPrepareInterceptor}
    */
   @Bean
-  @ConditionalOnProperty(name = "spring.profiles.active", havingValue = "pgsql")
+  @ConditionalOnProperty(name = "datasource.dialect", havingValue = "pgsql")
   public PostgreSQLPrepareInterceptor postgreSQLPrepareInterceptor() {
     return new PostgreSQLPrepareInterceptor();
   }
@@ -90,4 +94,16 @@ public class MybatisConfig {
       properties.setGlobalConfig(globalConfig);
     };
   }
+
+  @Bean
+  public DatabaseIdProvider databaseIdProvider() {
+    VendorDatabaseIdProvider databaseIdProvider = new VendorDatabaseIdProvider();
+    Properties properties = new Properties();
+    properties.put("MySQL", "mysql");
+    // h2 is also used as the processing strategy for MySQL
+    properties.setProperty("H2", "mysql");
+    properties.setProperty("PostgreSQL", "pgsql");
+    databaseIdProvider.setProperties(properties);
+    return databaseIdProvider;
+  }
 }
diff --git a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/base/config/OpenapiConfig.java b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/base/config/OpenapiConfig.java
index 445495e2a..3cfd02e3c 100644
--- a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/base/config/OpenapiConfig.java
+++ b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/base/config/OpenapiConfig.java
@@ -42,11 +42,16 @@ import java.util.Collections;
 public class OpenapiConfig implements WebMvcConfigurer {
 
   private static final String OPEN_API_INFO_OVERVIEW = "Apache StreamPark Api Docs";
+  private static final String OPEN_API_INFO_DESCRIPTION =
+      "Apache StreamPark Open API for third-party system integration";
   private static final String OPEN_API_INFO_VERSION = "2.2.0-SNAPSHOT";
   private static final String OPEN_API_INFO_LICENSE_NAME = "Apache-2.0 license";
   private static final String OPEN_API_INFO_CONTACT_NAME = "Apache StreamPark";
   private static final String OPEN_API_INFO_CONTACT_URL = "https://streampark.apache.org";
   private static final String OPEN_API_INFO_CONTACT_EMAIL = "dev@streampark.apache.org";
+  private static final String OPEN_API_GROUP = "Open API";
+
+  private final String[] paths = new String[] {"/flink/app/start", "/flink/app/cancel"};
 
   @Bean
   public OpenAPI apiV1Info() {
@@ -54,7 +59,7 @@ public class OpenapiConfig implements WebMvcConfigurer {
         .info(
             new Info()
                 .title(OPEN_API_INFO_OVERVIEW)
-                .description(OPEN_API_INFO_OVERVIEW)
+                .description(OPEN_API_INFO_DESCRIPTION)
                 .contact(
                     new Contact()
                         .name(OPEN_API_INFO_CONTACT_NAME)
@@ -77,11 +82,6 @@ public class OpenapiConfig implements WebMvcConfigurer {
 
   @Bean
   public GroupedOpenApi publicApiV1() {
-    return GroupedOpenApi.builder().group("v1").pathsToExclude("/v2/**").build();
-  }
-
-  @Bean
-  public GroupedOpenApi publicApiV2() {
-    return GroupedOpenApi.builder().group("v2").pathsToMatch("/v2/**").build();
+    return GroupedOpenApi.builder().group(OPEN_API_GROUP).pathsToMatch(paths).build();
   }
 }
diff --git a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/base/domain/ApiDocConstant.java b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/base/domain/ApiDocConstant.java
index e3b9ab774..515bdec0e 100644
--- a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/base/domain/ApiDocConstant.java
+++ b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/base/domain/ApiDocConstant.java
@@ -20,5 +20,5 @@ package org.apache.streampark.console.base.domain;
 /** Interface document constants */
 public class ApiDocConstant {
 
-  public static final String FLINK_APP_OP_TAG = "FLINK_APPLICATION_OPERATION_TAG";
+  public static final String OPENAPI_TAG = "OpenAPI";
 }
diff --git a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/base/domain/ResponseCode.java b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/base/domain/ResponseCode.java
index 65ce33c9c..fe1c61c29 100644
--- a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/base/domain/ResponseCode.java
+++ b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/base/domain/ResponseCode.java
@@ -23,6 +23,8 @@ public interface ResponseCode {
 
   Long CODE_FAIL = 500L;
 
+  Long CODE_UNAUTHORIZED = 401L;
+
   Long CODE_FORBIDDEN = 403L;
 
   Long CODE_FAIL_ALERT = 501L;
diff --git a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/base/handler/GlobalExceptionHandler.java b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/base/handler/GlobalExceptionHandler.java
index 1f669eb96..6d27f4487 100644
--- a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/base/handler/GlobalExceptionHandler.java
+++ b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/base/handler/GlobalExceptionHandler.java
@@ -17,12 +17,14 @@
 
 package org.apache.streampark.console.base.handler;
 
+import org.apache.streampark.common.util.ExceptionUtils;
 import org.apache.streampark.console.base.domain.ResponseCode;
 import org.apache.streampark.console.base.domain.RestResponse;
 import org.apache.streampark.console.base.exception.AbstractApiException;
 
 import org.apache.commons.lang3.StringUtils;
-import org.apache.shiro.authz.UnauthorizedException;
+import org.apache.shiro.authc.AuthenticationException;
+import org.apache.shiro.authz.UnauthenticatedException;
 
 import com.baomidou.mybatisplus.core.toolkit.StringPool;
 import lombok.extern.slf4j.Slf4j;
@@ -31,7 +33,6 @@ import org.springframework.core.annotation.Order;
 import org.springframework.http.HttpStatus;
 import org.springframework.validation.BindException;
 import org.springframework.validation.FieldError;
-import org.springframework.web.HttpRequestMethodNotSupportedException;
 import org.springframework.web.bind.annotation.ExceptionHandler;
 import org.springframework.web.bind.annotation.ResponseStatus;
 import org.springframework.web.bind.annotation.RestControllerAdvice;
@@ -43,34 +44,41 @@ import javax.validation.Path;
 import java.util.List;
 import java.util.Set;
 
-/** A global exception handler that takes over all exceptions */
 @Slf4j
 @RestControllerAdvice
 @Order(value = Ordered.HIGHEST_PRECEDENCE)
 public class GlobalExceptionHandler {
 
-  @ExceptionHandler(value = Exception.class)
-  @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
-  public RestResponse handleException(Exception e) {
-    log.error("Internal server error:", e);
-    return RestResponse.fail(ResponseCode.CODE_FAIL, "internal server error: {}", e.getMessage());
+  @ExceptionHandler(value = UnauthenticatedException.class)
+  @ResponseStatus(HttpStatus.UNAUTHORIZED)
+  public RestResponse handelUnauthenticatedException(UnauthenticatedException e) {
+    log.error("Unauthenticated.", e);
+    return RestResponse.fail(ResponseCode.CODE_UNAUTHORIZED, "Unauthenticated.");
   }
 
-  @ExceptionHandler(value = HttpRequestMethodNotSupportedException.class)
-  @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
-  public RestResponse handleException(HttpRequestMethodNotSupportedException e) {
-    log.error("not supported request method,exception:{}", e);
-    return RestResponse.fail(
-        ResponseCode.CODE_FAIL, "not supported request method,exception:{}", e.getMessage());
+  @ExceptionHandler(value = AuthenticationException.class)
+  @ResponseStatus(HttpStatus.UNAUTHORIZED)
+  public RestResponse handelUnauthenticatedException(AuthenticationException e) {
+    log.error("Permission denied.", e);
+    return RestResponse.fail(ResponseCode.CODE_UNAUTHORIZED, "Permission denied.");
   }
 
   @ExceptionHandler(value = AbstractApiException.class)
   @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
   public RestResponse handleException(AbstractApiException e) {
-    log.error("api exception:{}", e);
+    log.error("api exception:", e);
     return RestResponse.fail(e.getResponseCode(), e.getMessage());
   }
 
+  @ExceptionHandler(value = Exception.class)
+  @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
+  @Order(value = Ordered.HIGHEST_PRECEDENCE)
+  public RestResponse handleException(Exception e) {
+    log.error("internal server error:", e);
+    return RestResponse.fail(
+        ResponseCode.CODE_FAIL, "internal server error: " + ExceptionUtils.stringifyException(e));
+  }
+
   /**
    * Unified processing of request parameter verification (entity object parameter transfer)
    *
@@ -80,6 +88,7 @@ public class GlobalExceptionHandler {
   @ExceptionHandler(BindException.class)
   @ResponseStatus(HttpStatus.BAD_REQUEST)
   public RestResponse validExceptionHandler(BindException e) {
+    log.error("bind exception:", e);
     StringBuilder message = new StringBuilder();
     List<FieldError> fieldErrors = e.getBindingResult().getFieldErrors();
     for (FieldError error : fieldErrors) {
@@ -98,6 +107,7 @@ public class GlobalExceptionHandler {
   @ExceptionHandler(value = ConstraintViolationException.class)
   @ResponseStatus(HttpStatus.BAD_REQUEST)
   public RestResponse handleConstraintViolationException(ConstraintViolationException e) {
+    log.error("constraint violation exception:", e);
     StringBuilder message = new StringBuilder();
     Set<ConstraintViolation<?>> violations = e.getConstraintViolations();
     for (ConstraintViolation<?> violation : violations) {
@@ -109,10 +119,4 @@ public class GlobalExceptionHandler {
     message = new StringBuilder(message.substring(0, message.length() - 1));
     return RestResponse.fail(ResponseCode.CODE_FAIL, message.toString());
   }
-
-  @ExceptionHandler(value = UnauthorizedException.class)
-  @ResponseStatus(HttpStatus.FORBIDDEN)
-  public void handleUnauthorizedException(Exception e) {
-    log.error("Permission denied,{}", e);
-  }
 }
diff --git a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/base/properties/ShiroProperties.java b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/base/properties/ShiroProperties.java
deleted file mode 100644
index 4a9d9f42c..000000000
--- a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/base/properties/ShiroProperties.java
+++ /dev/null
@@ -1,33 +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.streampark.console.base.properties;
-
-import lombok.Data;
-import org.springframework.boot.context.properties.ConfigurationProperties;
-import org.springframework.context.annotation.Configuration;
-
-@Data
-@Configuration
-@ConfigurationProperties(prefix = "streampark.shiro")
-public class ShiroProperties {
-
-  private String anonUrl;
-
-  /** token default effective time: 1d */
-  private Long jwtTimeOut = 86400L;
-}
diff --git a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/base/util/BashJavaUtils.java b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/base/util/BashJavaUtils.java
new file mode 100644
index 000000000..faf8b8ead
--- /dev/null
+++ b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/base/util/BashJavaUtils.java
@@ -0,0 +1,54 @@
+/*
+ * 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.streampark.console.base.util;
+
+import org.apache.streampark.common.util.PropertiesUtils;
+
+import java.io.IOException;
+import java.net.ServerSocket;
+import java.util.Arrays;
+import java.util.Map;
+
+public class BashJavaUtils {
+
+  public static void main(String[] args) throws IOException {
+    String action = args[0].toLowerCase();
+    String[] actionArgs = Arrays.copyOfRange(args, 1, args.length);
+
+    switch (action) {
+      case "--get_yaml":
+        String key = actionArgs[0];
+        String conf = actionArgs[1];
+        Map<String, String> confMap = PropertiesUtils.fromYamlFileAsJava(conf);
+        String value = confMap.get(key);
+        System.out.println(value);
+        break;
+      case "--check_port":
+        Integer port = Integer.parseInt(actionArgs[0]);
+        try {
+          new ServerSocket(port);
+          System.out.println("free");
+        } catch (Exception e) {
+          System.out.println("used");
+        }
+        break;
+      default:
+        break;
+    }
+  }
+}
diff --git a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/base/util/FreemarkerUtils.java b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/base/util/FreemarkerUtils.java
index 7f7dab1cc..064d3f8f2 100644
--- a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/base/util/FreemarkerUtils.java
+++ b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/base/util/FreemarkerUtils.java
@@ -18,6 +18,7 @@
 package org.apache.streampark.console.base.util;
 
 import freemarker.cache.StringTemplateLoader;
+import freemarker.core.TemplateClassResolver;
 import freemarker.template.Configuration;
 import freemarker.template.Template;
 import freemarker.template.TemplateException;
@@ -31,45 +32,41 @@ import java.io.StringWriter;
 @Slf4j
 public class FreemarkerUtils {
   private static final Configuration CONFIGURATION;
-  private static final String ALERT_TEMPLATE = "classpath:alert-template";
-  private static final String TEMPLATE = "template";
-  private static final String ENCODING = "UTF-8";
 
   static {
     SpringTemplateLoader templateLoader =
-        new SpringTemplateLoader(new DefaultResourceLoader(), ALERT_TEMPLATE);
+        new SpringTemplateLoader(new DefaultResourceLoader(), "classpath:alert-template");
     CONFIGURATION = new Configuration(Configuration.VERSION_2_3_28);
+    CONFIGURATION.setNewBuiltinClassResolver(TemplateClassResolver.SAFER_RESOLVER);
     CONFIGURATION.setTemplateLoader(templateLoader);
-    CONFIGURATION.setDefaultEncoding(ENCODING);
+    CONFIGURATION.setDefaultEncoding("UTF-8");
   }
 
-  private FreemarkerUtils() {}
-
   public static Template loadTemplateFile(String fileName) throws ExceptionInInitializerError {
     try {
       return CONFIGURATION.getTemplate(fileName);
     } catch (IOException e) {
       log.error("{} not found!", fileName);
-      throw new ExceptionInInitializerError(String.format("%s not found!", fileName));
+      throw new ExceptionInInitializerError(fileName + " not found!");
     }
   }
 
   public static Template loadTemplateString(String template) throws Exception {
     Configuration configuration = new Configuration(Configuration.VERSION_2_3_28);
+    configuration.setNewBuiltinClassResolver(TemplateClassResolver.SAFER_RESOLVER);
     StringTemplateLoader stringTemplateLoader = new StringTemplateLoader();
-    stringTemplateLoader.putTemplate(TEMPLATE, template);
+    stringTemplateLoader.putTemplate("template", template);
     configuration.setTemplateLoader(stringTemplateLoader);
-    return configuration.getTemplate(TEMPLATE);
+    return configuration.getTemplate("template");
   }
 
   public static String format(Template template, Object dataModel) throws TemplateException {
-    String result = null;
     try (StringWriter writer = new StringWriter()) {
       template.process(dataModel, writer);
-      result = writer.toString();
+      return writer.toString();
     } catch (IOException e) {
       log.error(e.getMessage());
     }
-    return result;
+    return null;
   }
 }
diff --git a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/base/util/Tuple.java b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/base/util/Tuple.java
new file mode 100644
index 000000000..f80d6bd38
--- /dev/null
+++ b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/base/util/Tuple.java
@@ -0,0 +1,62 @@
+/*
+ * 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.streampark.console.base.util;
+
+/**
+ * The base class of all tuples. Tuples have a fix length and contain a set of fields, which may all
+ * be of different types. Because Tuples are strongly typed, each distinct tuple length is
+ * represented by its own class. Tuples exists with up to 25 fields and are described in the classes
+ * {@link Tuple1} to {@link Tuple4}.
+ *
+ * <p>The fields in the tuples may be accessed directly a public fields, or via position (zero
+ * indexed) {@link #get(int)}.
+ *
+ * <p>Tuples are in principle serializable. However, they may contain non-serializable fields, in
+ * which case serialization will fail.
+ */
+public abstract class Tuple implements java.io.Serializable {
+
+  private static final long serialVersionUID = 1L;
+
+  /**
+   * Gets the field at the specified position.
+   *
+   * @param pos The position of the field, zero indexed.
+   * @return The field at the specified position.
+   * @throws IndexOutOfBoundsException Thrown, if the position is negative, or equal to, or larger
+   *     than the number of fields.
+   */
+  public abstract <T> T get(int pos);
+
+  /**
+   * Sets the field at the specified position.
+   *
+   * @param value The value to be assigned to the field at the specified position.
+   * @param pos The position of the field, zero indexed.
+   * @throws IndexOutOfBoundsException Thrown, if the position is negative, or equal to, or larger
+   *     than the number of fields.
+   */
+  public abstract <T> void set(T value, int pos);
+
+  /**
+   * Shallow tuple copy.
+   *
+   * @return A new Tuple with the same fields as this.
+   */
+  public abstract <T extends Tuple> T copy();
+}
diff --git a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/base/util/Tuple1.java b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/base/util/Tuple1.java
new file mode 100644
index 000000000..1a6f79d0b
--- /dev/null
+++ b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/base/util/Tuple1.java
@@ -0,0 +1,113 @@
+/*
+ * 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.streampark.console.base.util;
+
+import java.util.Objects;
+
+public class Tuple1<T0> extends Tuple {
+
+  private static final long serialVersionUID = 1L;
+
+  /** Field 0 of the tuple. */
+  public T0 t1;
+
+  /** Creates a new tuple where all fields are null. */
+  public Tuple1() {}
+
+  /**
+   * Creates a new tuple and assigns the given values to the tuple's fields.
+   *
+   * @param t0 The value for field 0
+   */
+  public Tuple1(T0 t0) {
+    this.t1 = t0;
+  }
+
+  @Override
+  @SuppressWarnings("unchecked")
+  public <T> T get(int pos) {
+    if (pos == 0) {
+      return (T) this.t1;
+    }
+    throw new IndexOutOfBoundsException(String.valueOf(pos));
+  }
+
+  @Override
+  @SuppressWarnings("unchecked")
+  public <T> void set(T value, int pos) {
+    if (pos == 0) {
+      this.t1 = (T0) value;
+    } else {
+      throw new IndexOutOfBoundsException(String.valueOf(pos));
+    }
+  }
+
+  /**
+   * Sets new values to all fields of the tuple.
+   *
+   * @param f0 The value for field 0
+   */
+  public void set(T0 f0) {
+    this.t1 = f0;
+  }
+
+  /**
+   * Deep equality for tuples by calling equals() on the tuple members.
+   *
+   * @param o the object checked for equality
+   * @return true if this is equal to o.
+   */
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+    if (!(o instanceof Tuple1)) {
+      return false;
+    }
+    @SuppressWarnings("rawtypes")
+    Tuple1 tuple = (Tuple1) o;
+    return Objects.equals(t1, tuple.t1);
+  }
+
+  @Override
+  public int hashCode() {
+    return t1 != null ? t1.hashCode() : 0;
+  }
+
+  /**
+   * Shallow tuple copy.
+   *
+   * @return A new Tuple with the same fields as this.
+   */
+  @Override
+  @SuppressWarnings("unchecked")
+  public Tuple1<T0> copy() {
+    return new Tuple1<>(this.t1);
+  }
+
+  /**
+   * Creates a new tuple and assigns the given values to the tuple's fields. This is more convenient
+   * than using the constructor, because the compiler can infer the generic type arguments
+   * implicitly. For example: {@code Tuple3.of(n, x, s)} instead of {@code new Tuple3<Integer,
+   * Double, String>(n, x, s)}
+   */
+  public static <T0> Tuple1<T0> of(T0 f0) {
+    return new Tuple1<>(f0);
+  }
+}
diff --git a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/base/util/Tuple2.java b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/base/util/Tuple2.java
new file mode 100644
index 000000000..886beb113
--- /dev/null
+++ b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/base/util/Tuple2.java
@@ -0,0 +1,163 @@
+/*
+ * 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.streampark.console.base.util;
+
+import java.util.Objects;
+
+/**
+ * A tuple with 2 fields. Tuples are strongly typed; each field may be of a separate type. The
+ * fields of the tuple can be accessed directly as public fields (f0, f1, ...) or via their position
+ * through the {@link #get(int)} method. The tuple field positions start at zero.
+ *
+ * <p>Tuples are mutable types, meaning that their fields can be re-assigned. This allows functions
+ * that work with Tuples to reuse objects in order to reduce pressure on the garbage collector.
+ *
+ * <p>Warning: If you subclass Tuple2, then be sure to either
+ *
+ * <ul>
+ *   <li>not add any new fields, or
+ *   <li>make it a POJO, and always declare the element type of your DataStreams/DataSets to your
+ *       descendant type. (That is, if you have a "class Foo extends Tuple2", then don't use
+ *       instances of Foo in a DataStream&lt;Tuple2&gt; / DataSet&lt;Tuple2&gt;, but declare it as
+ *       DataStream&lt;Foo&gt; / DataSet&lt;Foo&gt;.)
+ * </ul>
+ *
+ * @see Tuple
+ * @param <T0> The type of field 0
+ * @param <T1> The type of field 1
+ */
+public class Tuple2<T0, T1> extends Tuple {
+
+  private static final long serialVersionUID = 1L;
+
+  /** Field 0 of the tuple. */
+  public T0 t1;
+  /** Field 1 of the tuple. */
+  public T1 t2;
+
+  /** Creates a new tuple where all fields are null. */
+  public Tuple2() {}
+
+  /**
+   * Creates a new tuple and assigns the given values to the tuple's fields.
+   *
+   * @param t0 The value for field 0
+   * @param t1 The value for field 1
+   */
+  public Tuple2(T0 t0, T1 t1) {
+    this.t1 = t0;
+    this.t2 = t1;
+  }
+
+  @Override
+  @SuppressWarnings("unchecked")
+  public <T> T get(int pos) {
+    switch (pos) {
+      case 0:
+        return (T) this.t1;
+      case 1:
+        return (T) this.t2;
+      default:
+        throw new IndexOutOfBoundsException(String.valueOf(pos));
+    }
+  }
+
+  @SuppressWarnings("unchecked")
+  public <T> void set(T value, int pos) {
+    switch (pos) {
+      case 0:
+        this.t1 = (T0) value;
+        break;
+      case 1:
+        this.t2 = (T1) value;
+        break;
+      default:
+        throw new IndexOutOfBoundsException(String.valueOf(pos));
+    }
+  }
+
+  /**
+   * Sets new values to all fields of the tuple.
+   *
+   * @param f0 The value for field 0
+   * @param f1 The value for field 1
+   */
+  public void set(T0 f0, T1 f1) {
+    this.t1 = f0;
+    this.t2 = f1;
+  }
+
+  /**
+   * Returns a shallow copy of the tuple with swapped values.
+   *
+   * @return shallow copy of the tuple with swapped values
+   */
+  public Tuple2<T1, T0> swap() {
+    return new Tuple2<T1, T0>(t2, t1);
+  }
+
+  /**
+   * Deep equality for tuples by calling equals() on the tuple members.
+   *
+   * @param o the object checked for equality
+   * @return true if this is equal to o.
+   */
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+    if (!(o instanceof Tuple2)) {
+      return false;
+    }
+    @SuppressWarnings("rawtypes")
+    Tuple2 tuple = (Tuple2) o;
+    if (!Objects.equals(t1, tuple.t1)) {
+      return false;
+    }
+    return Objects.equals(t2, tuple.t2);
+  }
+
+  @Override
+  public int hashCode() {
+    int result = t1 != null ? t1.hashCode() : 0;
+    result = 31 * result + (t2 != null ? t2.hashCode() : 0);
+    return result;
+  }
+
+  /**
+   * Shallow tuple copy.
+   *
+   * @return A new Tuple with the same fields as this.
+   */
+  @Override
+  @SuppressWarnings("unchecked")
+  public Tuple2<T0, T1> copy() {
+    return new Tuple2<>(this.t1, this.t2);
+  }
+
+  /**
+   * Creates a new tuple and assigns the given values to the tuple's fields. This is more convenient
+   * than using the constructor, because the compiler can infer the generic type arguments
+   * implicitly. For example: {@code Tuple3.of(n, x, s)} instead of {@code new Tuple3<Integer,
+   * Double, String>(n, x, s)}
+   */
+  public static <T0, T1> Tuple2<T0, T1> of(T0 f0, T1 f1) {
+    return new Tuple2<>(f0, f1);
+  }
+}
diff --git a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/base/util/Tuple3.java b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/base/util/Tuple3.java
new file mode 100644
index 000000000..802262418
--- /dev/null
+++ b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/base/util/Tuple3.java
@@ -0,0 +1,171 @@
+/*
+ * 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.streampark.console.base.util;
+
+import java.util.Objects;
+
+/**
+ * A tuple with 3 fields. Tuples are strongly typed; each field may be of a separate type. The
+ * fields of the tuple can be accessed directly as public fields (f0, f1, ...) or via their position
+ * through the {@link #get(int)} method. The tuple field positions start at zero.
+ *
+ * <p>Tuples are mutable types, meaning that their fields can be re-assigned. This allows functions
+ * that work with Tuples to reuse objects in order to reduce pressure on the garbage collector.
+ *
+ * <p>Warning: If you subclass Tuple3, then be sure to either
+ *
+ * <ul>
+ *   <li>not add any new fields, or
+ *   <li>make it a POJO, and always declare the element type of your DataStreams/DataSets to your
+ *       descendant type. (That is, if you have a "class Foo extends Tuple3", then don't use
+ *       instances of Foo in a DataStream&lt;Tuple3&gt; / DataSet&lt;Tuple3&gt;, but declare it as
+ *       DataStream&lt;Foo&gt; / DataSet&lt;Foo&gt;.)
+ * </ul>
+ *
+ * @see Tuple
+ * @param <T0> The type of field 0
+ * @param <T1> The type of field 1
+ * @param <T2> The type of field 2
+ */
+public class Tuple3<T0, T1, T2> extends Tuple {
+
+  private static final long serialVersionUID = 1L;
+
+  /** Field 0 of the tuple. */
+  public T0 t1;
+  /** Field 1 of the tuple. */
+  public T1 t2;
+  /** Field 2 of the tuple. */
+  public T2 t3;
+
+  /** Creates a new tuple where all fields are null. */
+  public Tuple3() {}
+
+  /**
+   * Creates a new tuple and assigns the given values to the tuple's fields.
+   *
+   * @param t0 The value for field 0
+   * @param t1 The value for field 1
+   * @param t2 The value for field 2
+   */
+  public Tuple3(T0 t0, T1 t1, T2 t2) {
+    this.t1 = t0;
+    this.t2 = t1;
+    this.t3 = t2;
+  }
+
+  @Override
+  @SuppressWarnings("unchecked")
+  public <T> T get(int pos) {
+    switch (pos) {
+      case 0:
+        return (T) this.t1;
+      case 1:
+        return (T) this.t2;
+      case 2:
+        return (T) this.t3;
+      default:
+        throw new IndexOutOfBoundsException(String.valueOf(pos));
+    }
+  }
+
+  @Override
+  @SuppressWarnings("unchecked")
+  public <T> void set(T value, int pos) {
+    switch (pos) {
+      case 0:
+        this.t1 = (T0) value;
+        break;
+      case 1:
+        this.t2 = (T1) value;
+        break;
+      case 2:
+        this.t3 = (T2) value;
+        break;
+      default:
+        throw new IndexOutOfBoundsException(String.valueOf(pos));
+    }
+  }
+
+  /**
+   * Sets new values to all fields of the tuple.
+   *
+   * @param f0 The value for field 0
+   * @param f1 The value for field 1
+   * @param f2 The value for field 2
+   */
+  public void set(T0 f0, T1 f1, T2 f2) {
+    this.t1 = f0;
+    this.t2 = f1;
+    this.t3 = f2;
+  }
+
+  /**
+   * Deep equality for tuples by calling equals() on the tuple members.
+   *
+   * @param o the object checked for equality
+   * @return true if this is equal to o.
+   */
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+    if (!(o instanceof Tuple3)) {
+      return false;
+    }
+    @SuppressWarnings("rawtypes")
+    Tuple3 tuple = (Tuple3) o;
+    if (!Objects.equals(t1, tuple.t1)) {
+      return false;
+    }
+    if (!Objects.equals(t2, tuple.t2)) {
+      return false;
+    }
+    return Objects.equals(t3, tuple.t3);
+  }
+
+  @Override
+  public int hashCode() {
+    int result = t1 != null ? t1.hashCode() : 0;
+    result = 31 * result + (t2 != null ? t2.hashCode() : 0);
+    result = 31 * result + (t3 != null ? t3.hashCode() : 0);
+    return result;
+  }
+
+  /**
+   * Shallow tuple copy.
+   *
+   * @return A new Tuple with the same fields as this.
+   */
+  @Override
+  @SuppressWarnings("unchecked")
+  public Tuple3<T0, T1, T2> copy() {
+    return new Tuple3<>(this.t1, this.t2, this.t3);
+  }
+
+  /**
+   * Creates a new tuple and assigns the given values to the tuple's fields. This is more convenient
+   * than using the constructor, because the compiler can infer the generic type arguments
+   * implicitly. For example: {@code Tuple3.of(n, x, s)} instead of {@code new Tuple3<Integer,
+   * Double, String>(n, x, s)}
+   */
+  public static <T0, T1, T2> Tuple3<T0, T1, T2> of(T0 f0, T1 f1, T2 f2) {
+    return new Tuple3<>(f0, f1, f2);
+  }
+}
diff --git a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/base/util/Tuple4.java b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/base/util/Tuple4.java
new file mode 100644
index 000000000..0296d33e5
--- /dev/null
+++ b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/base/util/Tuple4.java
@@ -0,0 +1,187 @@
+/*
+ * 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.streampark.console.base.util;
+
+import java.util.Objects;
+
+/**
+ * A tuple with 4 fields. Tuples are strongly typed; each field may be of a separate type. The
+ * fields of the tuple can be accessed directly as public fields (f0, f1, ...) or via their position
+ * through the {@link #get(int)} method. The tuple field positions start at zero.
+ *
+ * <p>Tuples are mutable types, meaning that their fields can be re-assigned. This allows functions
+ * that work with Tuples to reuse objects in order to reduce pressure on the garbage collector.
+ *
+ * <p>Warning: If you subclass Tuple4, then be sure to either
+ *
+ * <ul>
+ *   <li>not add any new fields, or
+ *   <li>make it a POJO, and always declare the element type of your DataStreams/DataSets to your
+ *       descendant type. (That is, if you have a "class Foo extends Tuple4", then don't use
+ *       instances of Foo in a DataStream&lt;Tuple4&gt; / DataSet&lt;Tuple4&gt;, but declare it as
+ *       DataStream&lt;Foo&gt; / DataSet&lt;Foo&gt;.)
+ * </ul>
+ *
+ * @see Tuple
+ * @param <T0> The type of field 0
+ * @param <T1> The type of field 1
+ * @param <T2> The type of field 2
+ * @param <T3> The type of field 3
+ */
+public class Tuple4<T0, T1, T2, T3> extends Tuple {
+
+  private static final long serialVersionUID = 1L;
+
+  /** Field 0 of the tuple. */
+  public T0 t1;
+  /** Field 1 of the tuple. */
+  public T1 t2;
+  /** Field 2 of the tuple. */
+  public T2 t3;
+  /** Field 3 of the tuple. */
+  public T3 t4;
+
+  /** Creates a new tuple where all fields are null. */
+  public Tuple4() {}
+
+  /**
+   * Creates a new tuple and assigns the given values to the tuple's fields.
+   *
+   * @param t0 The value for field 0
+   * @param t1 The value for field 1
+   * @param t2 The value for field 2
+   * @param t4 The value for field 3
+   */
+  public Tuple4(T0 t0, T1 t1, T2 t2, T3 t4) {
+    this.t1 = t0;
+    this.t2 = t1;
+    this.t3 = t2;
+    this.t4 = t4;
+  }
+
+  @Override
+  @SuppressWarnings("unchecked")
+  public <T> T get(int pos) {
+    switch (pos) {
+      case 0:
+        return (T) this.t1;
+      case 1:
+        return (T) this.t2;
+      case 2:
+        return (T) this.t3;
+      case 3:
+        return (T) this.t4;
+      default:
+        throw new IndexOutOfBoundsException(String.valueOf(pos));
+    }
+  }
+
+  @Override
+  @SuppressWarnings("unchecked")
+  public <T> void set(T value, int pos) {
+    switch (pos) {
+      case 0:
+        this.t1 = (T0) value;
+        break;
+      case 1:
+        this.t2 = (T1) value;
+        break;
+      case 2:
+        this.t3 = (T2) value;
+        break;
+      case 3:
+        this.t4 = (T3) value;
+        break;
+      default:
+        throw new IndexOutOfBoundsException(String.valueOf(pos));
+    }
+  }
+
+  /**
+   * Sets new values to all fields of the tuple.
+   *
+   * @param f0 The value for field 0
+   * @param f1 The value for field 1
+   * @param f2 The value for field 2
+   * @param f3 The value for field 3
+   */
+  public void set(T0 f0, T1 f1, T2 f2, T3 f3) {
+    this.t1 = f0;
+    this.t2 = f1;
+    this.t3 = f2;
+    this.t4 = f3;
+  }
+
+  /**
+   * Deep equality for tuples by calling equals() on the tuple members.
+   *
+   * @param o the object checked for equality
+   * @return true if this is equal to o.
+   */
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+    if (!(o instanceof Tuple4)) {
+      return false;
+    }
+    @SuppressWarnings("rawtypes")
+    Tuple4 tuple = (Tuple4) o;
+    if (!Objects.equals(t1, tuple.t1)) {
+      return false;
+    }
+    if (!Objects.equals(t2, tuple.t2)) {
+      return false;
+    }
+    if (!Objects.equals(t3, tuple.t3)) {
+      return false;
+    }
+    return Objects.equals(t4, tuple.t4);
+  }
+
+  @Override
+  public int hashCode() {
+    int result = t1 != null ? t1.hashCode() : 0;
+    result = 31 * result + (t2 != null ? t2.hashCode() : 0);
+    result = 31 * result + (t3 != null ? t3.hashCode() : 0);
+    result = 31 * result + (t4 != null ? t4.hashCode() : 0);
+    return result;
+  }
+
+  /**
+   * Shallow tuple copy.
+   *
+   * @return A new Tuple with the same fields as this.
+   */
+  @Override
+  @SuppressWarnings("unchecked")
+  public Tuple4<T0, T1, T2, T3> copy() {
+    return new Tuple4<>(this.t1, this.t2, this.t3, this.t4);
+  }
+
+  /**
+   * Creates a new tuple and assigns the given values to the tuple's fields. This is more convenient
+   * than using the constructor, because the compiler can infer the generic type arguments
+   * implicitly. For example: {@code Tuple3.of(n, x, s)} instead of {@code new Tuple3<Integer,
+   * Double, String>(n, x, s)}
+   */
+  public static <T0, T1, T2, T3> Tuple4<T0, T1, T2, T3> of(T0 f0, T1 f1, T2 f2, T3 f3) {
+    return new Tuple4<>(f0, f1, f2, f3);
+  }
+}
diff --git a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/annotation/AppUpdated.java b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/annotation/AppUpdated.java
index e76ee5cfd..ce416c09d 100644
--- a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/annotation/AppUpdated.java
+++ b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/annotation/AppUpdated.java
@@ -17,7 +17,7 @@
 
 package org.apache.streampark.console.core.annotation;
 
-import org.apache.streampark.console.core.aspect.ConsoleAspect;
+import org.apache.streampark.console.core.aspect.StreamParkAspect;
 import org.apache.streampark.console.core.watcher.FlinkAppHttpWatcher;
 
 import org.aspectj.lang.ProceedingJoinPoint;
@@ -31,7 +31,7 @@ import java.lang.annotation.Target;
  * In the controller({@link org.apache.streampark.console.core.controller}), If some method causes
  * application state update, need to add this annotation, This annotation marks which methods will
  * cause the application to be updated, Will work together with {@link
- * ConsoleAspect#appUpdated(ProceedingJoinPoint)}, The final purpose will be refresh {@link
+ * StreamParkAspect#appUpdated(ProceedingJoinPoint)}, The final purpose will be refresh {@link
  * FlinkAppHttpWatcher#WATCHING_APPS}, Make the state of the job consistent with the database
  */
 @Target(ElementType.METHOD)
diff --git a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/annotation/ApiAccess.java b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/annotation/OpenAPI.java
similarity index 97%
rename from streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/annotation/ApiAccess.java
rename to streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/annotation/OpenAPI.java
index 5326c4dd8..e9f5bfdec 100644
--- a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/annotation/ApiAccess.java
+++ b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/annotation/OpenAPI.java
@@ -24,6 +24,6 @@ import java.lang.annotation.Target;
 
 @Target(ElementType.METHOD)
 @Retention(RetentionPolicy.RUNTIME)
-public @interface ApiAccess {
+public @interface OpenAPI {
   boolean value() default true;
 }
diff --git a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/annotation/PermissionAction.java b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/annotation/PermissionScope.java
similarity index 75%
rename from streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/annotation/PermissionAction.java
rename to streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/annotation/PermissionScope.java
index cca19d8a8..12339f0f4 100644
--- a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/annotation/PermissionAction.java
+++ b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/annotation/PermissionScope.java
@@ -17,21 +17,18 @@
 
 package org.apache.streampark.console.core.annotation;
 
-import org.apache.streampark.console.core.enums.PermissionTypeEnum;
-
 import java.lang.annotation.ElementType;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.lang.annotation.Target;
 
-/**
- * In the controller({@link org.apache.streampark.console.core.controller}), If the method contains
- * this annotation, it means that this method requires certain permissions to be called.
- */
 @Target(ElementType.METHOD)
 @Retention(RetentionPolicy.RUNTIME)
-public @interface PermissionAction {
-  String id();
+public @interface PermissionScope {
+
+  String user() default "";
+
+  String team() default "";
 
-  PermissionTypeEnum type();
+  String app() default "";
 }
diff --git a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/aspect/ConsoleAspect.java b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/aspect/StreamParkAspect.java
similarity index 65%
rename from streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/aspect/ConsoleAspect.java
rename to streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/aspect/StreamParkAspect.java
index 4170a9a83..c747590a7 100644
--- a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/aspect/ConsoleAspect.java
+++ b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/aspect/StreamParkAspect.java
@@ -19,15 +19,15 @@ package org.apache.streampark.console.core.aspect;
 
 import org.apache.streampark.console.base.domain.RestResponse;
 import org.apache.streampark.console.base.exception.ApiAlertException;
-import org.apache.streampark.console.core.annotation.ApiAccess;
-import org.apache.streampark.console.core.annotation.PermissionAction;
+import org.apache.streampark.console.core.annotation.OpenAPI;
+import org.apache.streampark.console.core.annotation.PermissionScope;
 import org.apache.streampark.console.core.entity.Application;
-import org.apache.streampark.console.core.enums.PermissionTypeEnum;
 import org.apache.streampark.console.core.enums.UserTypeEnum;
-import org.apache.streampark.console.core.service.CommonService;
+import org.apache.streampark.console.core.service.ServiceHelper;
 import org.apache.streampark.console.core.service.application.ApplicationManageService;
 import org.apache.streampark.console.core.watcher.FlinkAppHttpWatcher;
 import org.apache.streampark.console.system.entity.AccessToken;
+import org.apache.streampark.console.system.entity.Member;
 import org.apache.streampark.console.system.entity.User;
 import org.apache.streampark.console.system.service.MemberService;
 
@@ -48,15 +48,13 @@ import org.springframework.expression.spel.standard.SpelExpressionParser;
 import org.springframework.expression.spel.support.StandardEvaluationContext;
 import org.springframework.stereotype.Component;
 
-import java.util.Objects;
-
 @Slf4j
 @Component
 @Aspect
-public class ConsoleAspect {
+public class StreamParkAspect {
 
   @Autowired private FlinkAppHttpWatcher flinkAppHttpWatcher;
-  @Autowired private CommonService commonService;
+  @Autowired private ServiceHelper serviceHelper;
   @Autowired private MemberService memberService;
   @Autowired private ApplicationManageService applicationManageService;
 
@@ -64,21 +62,19 @@ public class ConsoleAspect {
       "execution(public"
           + " org.apache.streampark.console.base.domain.RestResponse"
           + " org.apache.streampark.console.*.controller.*.*(..))")
-  public void apiAccess() {}
+  public void openAPI() {}
 
   @SuppressWarnings("checkstyle:SimplifyBooleanExpression")
-  @Around(value = "apiAccess()")
-  public RestResponse apiAccess(ProceedingJoinPoint joinPoint) throws Throwable {
+  @Around(value = "openAPI()")
+  public RestResponse openAPI(ProceedingJoinPoint joinPoint) throws Throwable {
     MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
-    if (log.isDebugEnabled()) {
-      log.debug("restResponse aspect, method:{}", methodSignature.getName());
-    }
+    log.debug("restResponse aspect, method:{}", methodSignature.getName());
     Boolean isApi =
         (Boolean) SecurityUtils.getSubject().getSession().getAttribute(AccessToken.IS_API_TOKEN);
-    if (Objects.nonNull(isApi) && isApi) {
-      ApiAccess apiAccess = methodSignature.getMethod().getAnnotation(ApiAccess.class);
-      if (Objects.isNull(apiAccess) || !apiAccess.value()) {
-        throw new ApiAlertException("api accessToken authentication failed!");
+    if (isApi != null && isApi) {
+      OpenAPI openAPI = methodSignature.getMethod().getAnnotation(OpenAPI.class);
+      if (openAPI == null) {
+        throw new ApiAlertException("current api unsupported!");
       }
     }
     return (RestResponse) joinPoint.proceed();
@@ -90,63 +86,66 @@ public class ConsoleAspect {
   @Around("appUpdated()")
   public Object appUpdated(ProceedingJoinPoint joinPoint) throws Throwable {
     MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
-    if (log.isDebugEnabled()) {
-      log.debug("appUpdated aspect, method:{}", methodSignature.getName());
-    }
+    log.debug("appUpdated aspect, method:{}", methodSignature.getName());
     Object target = joinPoint.proceed();
     flinkAppHttpWatcher.init();
     return target;
   }
 
-  @Pointcut("@annotation(org.apache.streampark.console.core.annotation.PermissionAction)")
+  @Pointcut("@annotation(org.apache.streampark.console.core.annotation.PermissionScope)")
   public void permissionAction() {}
 
   @Around("permissionAction()")
   public RestResponse permissionAction(ProceedingJoinPoint joinPoint) throws Throwable {
     MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
-    PermissionAction permissionAction =
-        methodSignature.getMethod().getAnnotation(PermissionAction.class);
+    PermissionScope permissionScope =
+        methodSignature.getMethod().getAnnotation(PermissionScope.class);
 
-    User currentUser = commonService.getCurrentUser();
+    User currentUser = serviceHelper.getLoginUser();
     ApiAlertException.throwIfNull(currentUser, "Permission denied, please login first.");
 
     boolean isAdmin = currentUser.getUserType() == UserTypeEnum.ADMIN;
 
     if (!isAdmin) {
-      PermissionTypeEnum permissionTypeEnum = permissionAction.type();
-      Long paramId = getParamId(joinPoint, methodSignature, permissionAction.id());
+      // 1) check userId
+      Long userId = getId(joinPoint, methodSignature, permissionScope.user());
+      ApiAlertException.throwIfTrue(
+          userId != null && !currentUser.getUserId().equals(userId),
+          "Permission denied, operations can only be performed with the permissions of the currently logged-in user.");
+
+      // 2) check team
+      Long teamId = getId(joinPoint, methodSignature, permissionScope.team());
+      if (teamId != null) {
+        Member member = memberService.getByTeamIdUserName(teamId, currentUser.getUsername());
+        ApiAlertException.throwIfTrue(
+            member == null,
+            "Permission denied, only members of this team can access this permission");
+      }
 
-      switch (permissionTypeEnum) {
-        case USER:
-          ApiAlertException.throwIfTrue(
-              !currentUser.getUserId().equals(paramId),
-              "Permission denied, only user himself can access this permission");
-          break;
-        case TEAM:
+      // 3) check app
+      Long appId = getId(joinPoint, methodSignature, permissionScope.app());
+      if (appId != null) {
+        Application app = applicationManageService.getById(appId);
+        ApiAlertException.throwIfTrue(app == null, "Invalid operation, application is null");
+        if (!currentUser.getUserId().equals(app.getUserId())) {
+          Member member =
+              memberService.getByTeamIdUserName(app.getTeamId(), currentUser.getUsername());
           ApiAlertException.throwIfTrue(
-              memberService.getByTeamIdUserName(paramId, currentUser.getUsername()) == null,
-              "Permission denied, only user belongs to this team can access this permission");
-          break;
-        case APP:
-          Application app = applicationManageService.getById(paramId);
-          ApiAlertException.throwIfTrue(app == null, "Invalid operation, application is null");
-          ApiAlertException.throwIfTrue(
-              memberService.getByTeamIdUserName(app.getTeamId(), currentUser.getUsername()) == null,
-              "Permission denied, only user belongs to this team can access this permission");
-          break;
-        default:
-          throw new IllegalArgumentException(
-              String.format("Permission type %s is not supported.", permissionTypeEnum));
+              member == null,
+              "Permission denied, this job not created by the current user, And the job cannot be found in the current user's team.");
+        }
       }
     }
 
     return (RestResponse) joinPoint.proceed();
   }
 
-  private Long getParamId(
-      ProceedingJoinPoint joinPoint, MethodSignature methodSignature, String spELString) {
+  private Long getId(ProceedingJoinPoint joinPoint, MethodSignature methodSignature, String expr) {
+    if (StringUtils.isEmpty(expr)) {
+      return null;
+    }
     SpelExpressionParser parser = new SpelExpressionParser();
-    Expression expression = parser.parseExpression(spELString);
+    Expression expression = parser.parseExpression(expr);
     EvaluationContext context = new StandardEvaluationContext();
     Object[] args = joinPoint.getArgs();
     DefaultParameterNameDiscoverer discoverer = new DefaultParameterNameDiscoverer();
@@ -159,7 +158,6 @@ public class ConsoleAspect {
     if (value == null || StringUtils.isBlank(value.toString())) {
       return null;
     }
-
     try {
       return Long.parseLong(value.toString());
     } catch (NumberFormatException e) {
diff --git a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/bean/AlertTemplate.java b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/bean/AlertTemplate.java
index e96b31583..3491578de 100644
--- a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/bean/AlertTemplate.java
+++ b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/bean/AlertTemplate.java
@@ -67,7 +67,7 @@ public class AlertTemplate implements Serializable {
     return new AlertTemplateBuilder()
         .setDuration(application.getStartTime(), application.getEndTime())
         .setJobName(application.getJobName())
-        .setLink(application.getFlinkExecutionMode(), application.getAppId())
+        .setLink(application.getFlinkExecutionMode(), application.getClusterId())
         .setStartTime(application.getStartTime())
         .setEndTime(application.getEndTime())
         .setRestart(application.isNeedRestartOnFailed(), application.getRestartCount())
@@ -87,7 +87,7 @@ public class AlertTemplate implements Serializable {
     return new AlertTemplateBuilder()
         .setDuration(application.getStartTime(), application.getEndTime())
         .setJobName(application.getJobName())
-        .setLink(application.getFlinkExecutionMode(), application.getAppId())
+        .setLink(application.getFlinkExecutionMode(), application.getClusterId())
         .setStartTime(application.getStartTime())
         .setType(2)
         .setCpFailureRateInterval(
diff --git a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/controller/AlertController.java b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/controller/AlertController.java
index 234e5259f..5b115fb7b 100644
--- a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/controller/AlertController.java
+++ b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/controller/AlertController.java
@@ -28,10 +28,6 @@ import org.apache.streampark.console.core.service.alert.AlertConfigService;
 import org.apache.streampark.console.core.service.alert.AlertService;
 
 import com.baomidou.mybatisplus.core.metadata.IPage;
-import io.swagger.v3.oas.annotations.Operation;
-import io.swagger.v3.oas.annotations.Parameter;
-import io.swagger.v3.oas.annotations.Parameters;
-import io.swagger.v3.oas.annotations.tags.Tag;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.validation.annotation.Validated;
@@ -48,7 +44,6 @@ import java.util.Date;
 import java.util.List;
 import java.util.TimeZone;
 
-@Tag(name = "ALERT_TAG")
 @Slf4j
 @Validated
 @RequiredArgsConstructor
@@ -60,35 +55,30 @@ public class AlertController {
 
   private final AlertService alertService;
 
-  @Operation(summary = "Create alert config")
   @PostMapping(value = "/add")
   public RestResponse createAlertConfig(@RequestBody AlertConfigParams params) {
     boolean save = alertConfigService.save(AlertConfig.of(params));
     return RestResponse.success(save);
   }
 
-  @Operation(summary = "Check alert config exist")
   @PostMapping(value = "/exists")
   public RestResponse verifyAlertConfig(@RequestBody AlertConfigParams params) {
     boolean exist = alertConfigService.exist(AlertConfig.of(params));
     return RestResponse.success(exist);
   }
 
-  @Operation(summary = "Update alert config")
   @PostMapping(value = "/update")
   public RestResponse updateAlertConfig(@RequestBody AlertConfigParams params) {
     boolean update = alertConfigService.updateById(AlertConfig.of(params));
     return RestResponse.success(update);
   }
 
-  @Operation(summary = "Get alert config")
   @PostMapping("/get")
   public RestResponse getAlertConfig(@RequestBody AlertConfigParams params) {
     AlertConfig alertConfig = alertConfigService.getById(params.getId());
     return RestResponse.success(AlertConfigParams.of(alertConfig));
   }
 
-  @Operation(summary = "List alert configs (Pagination)")
   @PostMapping(value = "/list")
   public RestResponse alertConfigsPaginationList(
       @RequestBody AlertConfigParams params, RestRequest request) {
@@ -96,15 +86,12 @@ public class AlertController {
     return RestResponse.success(page);
   }
 
-  @Operation(summary = "List alert configs")
   @PostMapping(value = "/listWithOutPage")
   public RestResponse alertConfigsList() {
     List<AlertConfig> page = alertConfigService.list();
     return RestResponse.success(page);
   }
 
-  @Operation(summary = "Delete alert config")
-  @Parameters({@Parameter(name = "id", required = true, description = "config id")})
   @DeleteMapping("/delete")
   public RestResponse deleteAlertConfig(
       @RequestParam("id") @NotNull(message = "config id must be not null") Long id) {
@@ -112,7 +99,6 @@ public class AlertController {
     return RestResponse.success(result);
   }
 
-  @Operation(summary = "Send alert config")
   @PostMapping("/send")
   public RestResponse sendAlert(Long id) throws AlertException {
     AlertTemplate alertTemplate = new AlertTemplate();
diff --git a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/controller/ApplicationBuildPipelineController.java b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/controller/ApplicationBuildPipelineController.java
index a692e56fa..9fb8453c4 100644
--- a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/controller/ApplicationBuildPipelineController.java
+++ b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/controller/ApplicationBuildPipelineController.java
@@ -17,24 +17,16 @@
 
 package org.apache.streampark.console.core.controller;
 
-import org.apache.streampark.console.base.domain.ApiDocConstant;
 import org.apache.streampark.console.base.domain.RestResponse;
-import org.apache.streampark.console.core.annotation.ApiAccess;
-import org.apache.streampark.console.core.annotation.PermissionAction;
+import org.apache.streampark.console.core.annotation.PermissionScope;
 import org.apache.streampark.console.core.bean.AppBuildDockerResolvedDetail;
 import org.apache.streampark.console.core.entity.AppBuildPipeline;
-import org.apache.streampark.console.core.enums.PermissionTypeEnum;
 import org.apache.streampark.console.core.service.AppBuildPipeService;
 import org.apache.streampark.flink.packer.pipeline.DockerResolvedSnapshot;
 import org.apache.streampark.flink.packer.pipeline.PipelineTypeEnum;
 
 import org.apache.shiro.authz.annotation.RequiresPermissions;
 
-import io.swagger.v3.oas.annotations.Operation;
-import io.swagger.v3.oas.annotations.Parameter;
-import io.swagger.v3.oas.annotations.Parameters;
-import io.swagger.v3.oas.annotations.media.Schema;
-import io.swagger.v3.oas.annotations.tags.Tag;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.validation.annotation.Validated;
@@ -46,7 +38,6 @@ import java.util.HashMap;
 import java.util.Map;
 import java.util.Optional;
 
-@Tag(name = "FLINK_APPLICATION_BUILD_PIPELINE_TAG")
 @Slf4j
 @Validated
 @RestController
@@ -55,27 +46,7 @@ public class ApplicationBuildPipelineController {
 
   @Autowired private AppBuildPipeService appBuildPipeService;
 
-  /**
-   * Release application building pipeline.
-   *
-   * @param appId application id
-   * @param forceBuild forced start pipeline or not
-   * @return Whether the pipeline was successfully started
-   */
-  @Operation(
-      summary = "Release application",
-      tags = {ApiDocConstant.FLINK_APP_OP_TAG})
-  @Parameters({
-    @Parameter(name = "appId", description = "app id", required = true, example = "100000"),
-    @Parameter(
-        name = "forceBuild",
-        description = "force build",
-        required = true,
-        example = "false",
-        schema = @Schema(defaultValue = "false", implementation = boolean.class))
-  })
-  @ApiAccess
-  @PermissionAction(id = "#appId", type = PermissionTypeEnum.APP)
+  @PermissionScope(app = "#appId")
   @PostMapping(value = "build")
   @RequiresPermissions("app:create")
   public RestResponse buildApplication(Long appId, boolean forceBuild) {
@@ -93,9 +64,8 @@ public class ApplicationBuildPipelineController {
    * @param appId application id
    * @return "pipeline" -> pipeline details, "docker" -> docker resolved snapshot
    */
-  @Operation(summary = "Get application release pipeline")
-  @ApiAccess
   @PostMapping("/detail")
+  @PermissionScope(app = "#appId")
   @RequiresPermissions("app:view")
   public RestResponse getBuildProgressDetail(Long appId) {
     Map<String, Object> details = new HashMap<>(0);
diff --git a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/controller/ApplicationController.java b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/controller/ApplicationController.java
index 77736db00..9665404db 100644
--- a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/controller/ApplicationController.java
+++ b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/controller/ApplicationController.java
@@ -23,14 +23,13 @@ import org.apache.streampark.console.base.domain.ApiDocConstant;
 import org.apache.streampark.console.base.domain.RestRequest;
 import org.apache.streampark.console.base.domain.RestResponse;
 import org.apache.streampark.console.base.exception.InternalException;
-import org.apache.streampark.console.core.annotation.ApiAccess;
 import org.apache.streampark.console.core.annotation.AppUpdated;
-import org.apache.streampark.console.core.annotation.PermissionAction;
+import org.apache.streampark.console.core.annotation.OpenAPI;
+import org.apache.streampark.console.core.annotation.PermissionScope;
 import org.apache.streampark.console.core.entity.Application;
 import org.apache.streampark.console.core.entity.ApplicationBackUp;
 import org.apache.streampark.console.core.entity.ApplicationLog;
 import org.apache.streampark.console.core.enums.AppExistsStateEnum;
-import org.apache.streampark.console.core.enums.PermissionTypeEnum;
 import org.apache.streampark.console.core.service.ApplicationBackUpService;
 import org.apache.streampark.console.core.service.ApplicationLogService;
 import org.apache.streampark.console.core.service.ResourceService;
@@ -41,13 +40,11 @@ import org.apache.streampark.console.core.service.application.ApplicationManageS
 import org.apache.shiro.authz.annotation.RequiresPermissions;
 
 import com.baomidou.mybatisplus.core.metadata.IPage;
-import io.swagger.v3.oas.annotations.Hidden;
 import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.v3.oas.annotations.Parameter;
 import io.swagger.v3.oas.annotations.Parameters;
 import io.swagger.v3.oas.annotations.enums.ParameterIn;
 import io.swagger.v3.oas.annotations.media.Schema;
-import io.swagger.v3.oas.annotations.tags.Tag;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.validation.annotation.Validated;
@@ -62,7 +59,6 @@ import java.io.Serializable;
 import java.net.URI;
 import java.util.Map;
 
-@Tag(name = "FLINK_APPLICATION_TAG")
 @Slf4j
 @Validated
 @RestController
@@ -81,18 +77,15 @@ public class ApplicationController {
 
   @Autowired private ResourceService resourceService;
 
-  @Operation(summary = "Get application")
-  @ApiAccess
   @PostMapping("get")
+  @PermissionScope(app = "#app.id")
   @RequiresPermissions("app:detail")
   public RestResponse get(Application app) {
     Application application = applicationManageService.getApp(app.getId());
     return RestResponse.success(application);
   }
 
-  @Operation(summary = "Create application")
-  @ApiAccess
-  @PermissionAction(id = "#app.teamId", type = PermissionTypeEnum.TEAM)
+  @PermissionScope(team = "#app.teamId")
   @PostMapping("create")
   @RequiresPermissions("app:create")
   public RestResponse create(Application app) throws IOException {
@@ -100,25 +93,7 @@ public class ApplicationController {
     return RestResponse.success(saved);
   }
 
-  @Operation(
-      summary = "Copy application",
-      tags = {ApiDocConstant.FLINK_APP_OP_TAG})
-  @Parameters({
-    @Parameter(
-        name = "id",
-        description = "copied target app id",
-        in = ParameterIn.QUERY,
-        required = true,
-        example = "100000"),
-    @Parameter(
-        name = "jobName",
-        description = "new application name",
-        in = ParameterIn.QUERY,
-        example = "copy-app"),
-    @Parameter(name = "args", description = "new application args", in = ParameterIn.QUERY)
-  })
-  @ApiAccess
-  @PermissionAction(id = "#app.id", type = PermissionTypeEnum.APP)
+  @PermissionScope(app = "#app.id", team = "#app.teamId")
   @PostMapping(value = "copy")
   @RequiresPermissions("app:copy")
   public RestResponse copy(@Parameter(hidden = true) Application app) throws IOException {
@@ -126,9 +101,8 @@ public class ApplicationController {
     return RestResponse.success();
   }
 
-  @Operation(summary = "Update application")
   @AppUpdated
-  @PermissionAction(id = "#app.id", type = PermissionTypeEnum.APP)
+  @PermissionScope(app = "#app.id")
   @PostMapping("update")
   @RequiresPermissions("app:update")
   public RestResponse update(Application app) {
@@ -136,34 +110,32 @@ public class ApplicationController {
     return RestResponse.success(true);
   }
 
-  @Operation(summary = "Get applications dashboard data")
   @PostMapping("dashboard")
+  @PermissionScope(team = "#teamId")
   public RestResponse dashboard(Long teamId) {
     Map<String, Serializable> dashboardMap = applicationInfoService.getDashboardDataMap(teamId);
     return RestResponse.success(dashboardMap);
   }
 
-  @Operation(summary = "List applications")
-  @ApiAccess
   @PostMapping("list")
+  @PermissionScope(team = "#app.teamId")
   @RequiresPermissions("app:view")
   public RestResponse list(Application app, RestRequest request) {
     IPage<Application> applicationList = applicationManageService.page(app, request);
     return RestResponse.success(applicationList);
   }
 
-  @Operation(summary = "Mapping application")
   @AppUpdated
   @PostMapping("mapping")
+  @PermissionScope(app = "#app.id")
   @RequiresPermissions("app:mapping")
   public RestResponse mapping(Application app) {
     boolean flag = applicationManageService.mapping(app);
     return RestResponse.success(flag);
   }
 
-  @Operation(summary = "Revoke application")
   @AppUpdated
-  @PermissionAction(id = "#app.id", type = PermissionTypeEnum.APP)
+  @PermissionScope(app = "#app.id")
   @PostMapping("revoke")
   @RequiresPermissions("app:release")
   public RestResponse revoke(Application app) {
@@ -171,7 +143,7 @@ public class ApplicationController {
     return RestResponse.success();
   }
 
-  @PermissionAction(id = "#app.id", type = PermissionTypeEnum.APP)
+  @PermissionScope(app = "#app.id", team = "#app.teamId")
   @PostMapping(value = "check_start")
   @RequiresPermissions("app:start")
   public RestResponse checkStart(Application app) {
@@ -181,8 +153,14 @@ public class ApplicationController {
 
   @Operation(
       summary = "Start application",
-      tags = {ApiDocConstant.FLINK_APP_OP_TAG})
+      tags = {ApiDocConstant.OPENAPI_TAG})
   @Parameters({
+    @Parameter(
+        name = "Authorization",
+        description = "Access authorization token",
+        in = ParameterIn.HEADER,
+        required = true,
+        schema = @Schema(implementation = String.class)),
     @Parameter(
         name = "id",
         description = "start app id",
@@ -190,27 +168,33 @@ public class ApplicationController {
         required = true,
         example = "100000",
         schema = @Schema(implementation = Long.class)),
+    @Parameter(
+        name = "teamId",
+        description = "current user teamId",
+        in = ParameterIn.QUERY,
+        required = true,
+        example = "100000",
+        schema = @Schema(implementation = Long.class)),
     @Parameter(
         name = "savePointed",
         description = "restored app from the savepoint or latest checkpoint",
         in = ParameterIn.QUERY,
-        required = true,
         example = "false",
         schema = @Schema(implementation = boolean.class, defaultValue = "false")),
     @Parameter(
         name = "savePoint",
         description = "savepoint or checkpoint path",
         in = ParameterIn.QUERY,
+        required = false,
         schema = @Schema(implementation = String.class)),
     @Parameter(
         name = "allowNonRestored",
         description = "ignore savepoint if cannot be restored",
         in = ParameterIn.QUERY,
-        required = false,
         schema = @Schema(implementation = boolean.class, defaultValue = "false"))
   })
-  @ApiAccess
-  @PermissionAction(id = "#app.id", type = PermissionTypeEnum.APP)
+  @OpenAPI
+  @PermissionScope(app = "#app.id", team = "#app.teamId")
   @PostMapping(value = "start")
   @RequiresPermissions("app:start")
   public RestResponse start(@Parameter(hidden = true) Application app) {
@@ -224,9 +208,15 @@ public class ApplicationController {
 
   @Operation(
       summary = "Cancel application",
-      tags = {ApiDocConstant.FLINK_APP_OP_TAG})
-  @ApiAccess
+      tags = {ApiDocConstant.OPENAPI_TAG})
+  @OpenAPI
   @Parameters({
+    @Parameter(
+        name = "Authorization",
+        description = "Access authorization token",
+        in = ParameterIn.HEADER,
+        required = true,
+        schema = @Schema(implementation = String.class)),
     @Parameter(
         name = "id",
         description = "cancel app id",
@@ -234,11 +224,17 @@ public class ApplicationController {
         required = true,
         example = "100000",
         schema = @Schema(implementation = Long.class)),
+    @Parameter(
+        name = "teamId",
+        description = "current user teamId",
+        in = ParameterIn.QUERY,
+        required = true,
+        example = "100000",
+        schema = @Schema(implementation = Long.class)),
     @Parameter(
         name = "savePointed",
         description = "trigger savepoint before taking stopping",
         in = ParameterIn.QUERY,
-        required = true,
         schema = @Schema(implementation = boolean.class, defaultValue = "false")),
     @Parameter(
         name = "savePoint",
@@ -250,18 +246,10 @@ public class ApplicationController {
         name = "drain",
         description = "send max watermark before canceling",
         in = ParameterIn.QUERY,
-        required = true,
-        example = "false",
-        schema = @Schema(implementation = boolean.class, defaultValue = "false")),
-    @Parameter(
-        name = "nativeFormat",
-        description = "use savepoint native format",
-        in = ParameterIn.QUERY,
-        required = true,
         example = "false",
         schema = @Schema(implementation = boolean.class, defaultValue = "false"))
   })
-  @PermissionAction(id = "#app.id", type = PermissionTypeEnum.APP)
+  @PermissionScope(app = "#app.id", team = "#app.teamId")
   @PostMapping(value = "cancel")
   @RequiresPermissions("app:cancel")
   public RestResponse cancel(@Parameter(hidden = true) Application app) throws Exception {
@@ -269,20 +257,8 @@ public class ApplicationController {
     return RestResponse.success();
   }
 
-  @Operation(summary = "Clean application")
-  @AppUpdated
-  @ApiAccess
-  @PermissionAction(id = "#app.id", type = PermissionTypeEnum.APP)
-  @PostMapping("clean")
-  @RequiresPermissions("app:clean")
-  public RestResponse clean(Application app) {
-    applicationManageService.clean(app);
-    return RestResponse.success(true);
-  }
-
   /** force stop(stop normal start or in progress) */
-  @Operation(summary = "Force stop application")
-  @PermissionAction(id = "#app.id", type = PermissionTypeEnum.APP)
+  @PermissionScope(app = "#app.id")
   @PostMapping("forcedStop")
   @RequiresPermissions("app:cancel")
   public RestResponse forcedStop(Application app) {
@@ -290,56 +266,53 @@ public class ApplicationController {
     return RestResponse.success();
   }
 
-  @Operation(summary = "Get application on yarn proxy address")
   @PostMapping("yarn")
   public RestResponse yarn() {
     return RestResponse.success(YarnUtils.getRMWebAppProxyURL());
   }
 
-  @Operation(summary = "Get application on yarn name")
   @PostMapping("name")
+  @PermissionScope(app = "#app.id", team = "#app.teamId")
   public RestResponse yarnName(Application app) {
     String yarnName = applicationInfoService.getYarnName(app.getConfig());
     return RestResponse.success(yarnName);
   }
 
-  @Operation(summary = "Check the application exist status")
   @PostMapping("checkName")
+  @PermissionScope(app = "#app.id", team = "#app.teamId")
   public RestResponse checkName(Application app) {
     AppExistsStateEnum exists = applicationInfoService.checkExists(app);
     return RestResponse.success(exists.get());
   }
 
-  @Operation(summary = "Get application conf")
   @PostMapping("readConf")
   public RestResponse readConf(Application app) throws IOException {
     String config = applicationInfoService.readConf(app.getConfig());
     return RestResponse.success(config);
   }
 
-  @Operation(summary = "Get application main-class")
   @PostMapping("main")
+  @PermissionScope(app = "#app.id", team = "#app.teamId")
   public RestResponse getMain(Application application) {
     String mainClass = applicationInfoService.getMain(application);
     return RestResponse.success(mainClass);
   }
 
-  @Operation(summary = "List application backups")
   @PostMapping("backups")
+  @PermissionScope(app = "#backUp.appId", team = "#backUp.teamId")
   public RestResponse backups(ApplicationBackUp backUp, RestRequest request) {
     IPage<ApplicationBackUp> backups = backUpService.getPage(backUp, request);
     return RestResponse.success(backups);
   }
 
-  @Operation(summary = "List application operation logs")
   @PostMapping("optionlog")
-  public RestResponse optionlog(ApplicationLog applicationLog, RestRequest request) {
+  @PermissionScope(app = "#log.appId", team = "#log.teamId")
+  public RestResponse log(ApplicationLog applicationLog, RestRequest request) {
     IPage<ApplicationLog> applicationList = applicationLogService.getPage(applicationLog, request);
     return RestResponse.success(applicationList);
   }
 
-  @Operation(summary = "Delete application operation log")
-  @PermissionAction(id = "#applicationLog.appId", type = PermissionTypeEnum.APP)
+  @PermissionScope(app = "#log.appId", team = "#log.teamId")
   @PostMapping("deleteOperationLog")
   @RequiresPermissions("app:delete")
   public RestResponse deleteOperationLog(Long id) {
@@ -347,8 +320,7 @@ public class ApplicationController {
     return RestResponse.success(deleted);
   }
 
-  @Operation(summary = "Delete application")
-  @PermissionAction(id = "#app.id", type = PermissionTypeEnum.APP)
+  @PermissionScope(app = "#app.id", team = "#app.teamId")
   @PostMapping("delete")
   @RequiresPermissions("app:delete")
   public RestResponse delete(Application app) throws InternalException {
@@ -356,15 +328,13 @@ public class ApplicationController {
     return RestResponse.success(deleted);
   }
 
-  @Operation(summary = "Backup application when deleted")
-  @PermissionAction(id = "#backUp.appId", type = PermissionTypeEnum.APP)
+  @PermissionScope(app = "#backUp.appId")
   @PostMapping("deletebak")
   public RestResponse deleteBak(ApplicationBackUp backUp) throws InternalException {
     Boolean deleted = backUpService.removeById(backUp.getId());
     return RestResponse.success(deleted);
   }
 
-  @Operation(summary = "Check the application jar")
   @PostMapping("checkjar")
   public RestResponse checkjar(String jar) {
     File file = new File(jar);
@@ -376,7 +346,6 @@ public class ApplicationController {
     }
   }
 
-  @Operation(summary = "Upload the application jar")
   @PostMapping("upload")
   @RequiresPermissions("app:create")
   public RestResponse upload(MultipartFile file) throws Exception {
@@ -384,7 +353,6 @@ public class ApplicationController {
     return RestResponse.success(uploadPath);
   }
 
-  @Hidden
   @PostMapping("verifySchema")
   public RestResponse verifySchema(String path) {
     final URI uri = URI.create(path);
@@ -407,8 +375,8 @@ public class ApplicationController {
     return restResponse;
   }
 
-  @Operation(summary = "Check the application savepoint path")
   @PostMapping("checkSavepointPath")
+  @PermissionScope(app = "#app.id", team = "#app.teamId")
   public RestResponse checkSavepointPath(Application app) throws Exception {
     String error = applicationInfoService.checkSavepointPath(app);
     if (error == null) {
@@ -417,27 +385,7 @@ public class ApplicationController {
     return RestResponse.success(false).message(error);
   }
 
-  @Operation(summary = "Get application on k8s deploy logs")
-  @Parameters({
-    @Parameter(
-        name = "id",
-        description = "app id",
-        required = true,
-        example = "100000",
-        schema = @Schema(implementation = Long.class)),
-    @Parameter(
-        name = "offset",
-        description = "number of log lines offset",
-        required = true,
-        example = "0",
-        schema = @Schema(implementation = int.class)),
-    @Parameter(
-        name = "limit",
-        description = "number of log lines loaded at once",
-        required = true,
-        example = "100",
-        schema = @Schema(implementation = int.class)),
-  })
+  @PermissionScope(app = "#id")
   @PostMapping(value = "k8sStartLog")
   public RestResponse k8sStartLog(Long id, Integer offset, Integer limit) throws Exception {
     String resp = applicationInfoService.k8sStartLog(id, offset, limit);
diff --git a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/controller/ApplicationHistoryController.java b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/controller/ApplicationHistoryController.java
index 5b3c756e0..015244c6e 100644
--- a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/controller/ApplicationHistoryController.java
+++ b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/controller/ApplicationHistoryController.java
@@ -23,8 +23,6 @@ import org.apache.streampark.console.core.service.application.ApplicationInfoSer
 
 import org.apache.shiro.authz.annotation.RequiresPermissions;
 
-import io.swagger.v3.oas.annotations.Operation;
-import io.swagger.v3.oas.annotations.tags.Tag;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.validation.annotation.Validated;
@@ -35,7 +33,6 @@ import org.springframework.web.bind.annotation.RestController;
 import java.util.ArrayList;
 import java.util.List;
 
-@Tag(name = "FLINK_APPLICATION_HISTORY_TAG")
 @Slf4j
 @Validated
 @RestController
@@ -44,7 +41,6 @@ public class ApplicationHistoryController {
 
   @Autowired private ApplicationInfoService applicationInfoService;
 
-  @Operation(summary = "List the upload jar history records")
   @PostMapping("uploadJars")
   @RequiresPermissions("app:create")
   public RestResponse listUploadJars() {
@@ -52,7 +48,6 @@ public class ApplicationHistoryController {
     return RestResponse.success(jars);
   }
 
-  @Operation(summary = "List the k8s namespace history records")
   @PostMapping("k8sNamespaces")
   @RequiresPermissions("app:create")
   public RestResponse listK8sNamespace() {
@@ -60,7 +55,6 @@ public class ApplicationHistoryController {
     return RestResponse.success(namespaces);
   }
 
-  @Operation(summary = "List the session cluster history records")
   @PostMapping("sessionClusterIds")
   @RequiresPermissions("app:create")
   public RestResponse listSessionClusterId(int executionMode) {
@@ -78,7 +72,6 @@ public class ApplicationHistoryController {
     return RestResponse.success(clusterIds);
   }
 
-  @Operation(summary = "List the flink base image history records")
   @PostMapping("flinkBaseImages")
   @RequiresPermissions("app:create")
   public RestResponse listFlinkBaseImage() {
@@ -86,7 +79,6 @@ public class ApplicationHistoryController {
     return RestResponse.success(images);
   }
 
-  @Operation(summary = "List the flink pod template history records")
   @PostMapping("flinkPodTemplates")
   @RequiresPermissions("app:create")
   public RestResponse listPodTemplate() {
@@ -94,7 +86,6 @@ public class ApplicationHistoryController {
     return RestResponse.success(templates);
   }
 
-  @Operation(summary = "List the flink JM pod template history records")
   @PostMapping("flinkJmPodTemplates")
   @RequiresPermissions("app:create")
   public RestResponse listJmPodTemplate() {
@@ -102,7 +93,6 @@ public class ApplicationHistoryController {
     return RestResponse.success(templates);
   }
 
-  @Operation(summary = "List the flink TM pod template history records")
   @PostMapping("flinkTmPodTemplates")
   @RequiresPermissions("app:create")
   public RestResponse listTmPodTemplate() {
diff --git a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/controller/ConfigController.java b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/controller/ConfigController.java
index 06e1c167c..20fea6ff0 100644
--- a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/controller/ConfigController.java
+++ b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/controller/ConfigController.java
@@ -28,8 +28,6 @@ import org.apache.shiro.authz.annotation.RequiresPermissions;
 
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.google.common.collect.ImmutableMap;
-import io.swagger.v3.oas.annotations.Operation;
-import io.swagger.v3.oas.annotations.tags.Tag;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.validation.annotation.Validated;
@@ -40,7 +38,6 @@ import org.springframework.web.bind.annotation.RestController;
 import java.util.List;
 import java.util.Map;
 
-@Tag(name = "CONFIG_TAG")
 @Slf4j
 @Validated
 @RestController
@@ -49,35 +46,30 @@ public class ConfigController {
 
   @Autowired private ApplicationConfigService applicationConfigService;
 
-  @Operation(summary = "Get config")
   @PostMapping("get")
   public RestResponse get(Long id) {
     ApplicationConfig config = applicationConfigService.get(id);
     return RestResponse.success(config);
   }
 
-  @Operation(summary = "Get the flink application conf-template")
   @PostMapping("template")
   public RestResponse template() {
     String config = applicationConfigService.readTemplate();
     return RestResponse.success(config);
   }
 
-  @Operation(summary = "List the application configs")
   @PostMapping("list")
   public RestResponse list(ApplicationConfig config, RestRequest request) {
     IPage<ApplicationConfig> page = applicationConfigService.getPage(config, request);
     return RestResponse.success(page);
   }
 
-  @Operation(summary = "List application config histories")
   @PostMapping("history")
   public RestResponse history(Application application) {
     List<ApplicationConfig> history = applicationConfigService.list(application.getId());
     return RestResponse.success(history);
   }
 
-  @Operation(summary = "Delete config")
   @PostMapping("delete")
   @RequiresPermissions("conf:delete")
   public RestResponse delete(Long id) {
@@ -85,7 +77,6 @@ public class ConfigController {
     return RestResponse.success(deleted);
   }
 
-  @Operation(summary = "Get system hadoop configs")
   @PostMapping("sysHadoopConf")
   @RequiresPermissions("app:create")
   public RestResponse getSystemHadoopConfig() {
diff --git a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/controller/ExternalLinkController.java b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/controller/ExternalLinkController.java
index 22076c597..00d99de73 100644
--- a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/controller/ExternalLinkController.java
+++ b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/controller/ExternalLinkController.java
@@ -24,10 +24,6 @@ import org.apache.streampark.console.core.service.ExternalLinkService;
 
 import org.apache.shiro.authz.annotation.RequiresPermissions;
 
-import io.swagger.v3.oas.annotations.Operation;
-import io.swagger.v3.oas.annotations.Parameter;
-import io.swagger.v3.oas.annotations.Parameters;
-import io.swagger.v3.oas.annotations.tags.Tag;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.validation.annotation.Validated;
@@ -42,7 +38,6 @@ import javax.validation.constraints.NotNull;
 
 import java.util.List;
 
-@Tag(name = "FLINK_EXTERNAL_LINK_TAG")
 @Slf4j
 @Validated
 @RestController
@@ -51,7 +46,6 @@ public class ExternalLinkController {
 
   @Autowired private ExternalLinkService externalLinkService;
 
-  @Operation(summary = "List external link")
   @PostMapping("/list")
   @RequiresPermissions("externalLink:view")
   public RestResponse list() {
@@ -59,10 +53,6 @@ public class ExternalLinkController {
     return RestResponse.success(externalLink);
   }
 
-  @Operation(
-      summary = "Get the application external links",
-      description = "Render external link by app id")
-  @Parameters({@Parameter(name = "appId", required = true, example = "100000")})
   @PostMapping("/render")
   public RestResponse render(
       @NotNull(message = "The flink app id cannot be null") @RequestParam("appId") Long appId) {
@@ -70,7 +60,6 @@ public class ExternalLinkController {
     return RestResponse.success(renderedExternalLink);
   }
 
-  @Operation(summary = "Create external link")
   @PostMapping("/create")
   @RequiresPermissions("externalLink:create")
   public RestResponse create(@Valid ExternalLink externalLink) {
@@ -78,7 +67,6 @@ public class ExternalLinkController {
     return RestResponse.success();
   }
 
-  @Operation(summary = "Update external link")
   @PostMapping("/update")
   @RequiresPermissions("externalLink:update")
   public RestResponse update(@Valid ExternalLink externalLink) {
@@ -87,8 +75,6 @@ public class ExternalLinkController {
     return RestResponse.success();
   }
 
-  @Operation(summary = "Delete external link")
-  @Parameters({@Parameter(name = "appId", required = true, example = "100000")})
   @DeleteMapping("/delete")
   @RequiresPermissions("externalLink:delete")
   public RestResponse delete(
diff --git a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/controller/FlinkClusterController.java b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/controller/FlinkClusterController.java
index 27b0b80aa..71b297d67 100644
--- a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/controller/FlinkClusterController.java
+++ b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/controller/FlinkClusterController.java
@@ -26,8 +26,6 @@ import org.apache.streampark.console.core.service.FlinkClusterService;
 
 import org.apache.shiro.authz.annotation.RequiresPermissions;
 
-import io.swagger.v3.oas.annotations.Operation;
-import io.swagger.v3.oas.annotations.tags.Tag;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.validation.annotation.Validated;
@@ -37,7 +35,6 @@ import org.springframework.web.bind.annotation.RestController;
 
 import java.util.List;
 
-@Tag(name = "FLINK_CLUSTER_TAG")
 @Slf4j
 @Validated
 @RestController
@@ -46,35 +43,30 @@ public class FlinkClusterController {
 
   @Autowired private FlinkClusterService flinkClusterService;
 
-  @Operation(summary = "List flink clusters that are eligible")
   @PostMapping("availableList")
   public RestResponse listAvailableCluster() {
     List<FlinkCluster> flinkClusters = flinkClusterService.listAvailableCluster();
     return RestResponse.success(flinkClusters);
   }
 
-  @Operation(summary = "List flink clusters")
   @PostMapping("list")
   public RestResponse list() {
     List<FlinkCluster> flinkClusters = flinkClusterService.list();
     return RestResponse.success(flinkClusters);
   }
 
-  @Operation(summary = "Get flink cluster remote address")
   @PostMapping("remoteUrl")
   public RestResponse remoteUrl(Long id) {
     FlinkCluster cluster = flinkClusterService.getById(id);
     return RestResponse.success(cluster.getAddress());
   }
 
-  @Operation(summary = "Check the cluster status")
   @PostMapping("check")
   public RestResponse check(FlinkCluster cluster) {
     ResponseResult checkResult = flinkClusterService.check(cluster);
     return RestResponse.success(checkResult);
   }
 
-  @Operation(summary = "Create flink cluster")
   @PostMapping("create")
   @RequiresPermissions("cluster:create")
   public RestResponse create(FlinkCluster cluster) {
@@ -82,7 +74,6 @@ public class FlinkClusterController {
     return RestResponse.success(success);
   }
 
-  @Operation(summary = "Update flink cluster")
   @PostMapping("update")
   @RequiresPermissions("cluster:update")
   public RestResponse update(FlinkCluster cluster) {
@@ -90,14 +81,12 @@ public class FlinkClusterController {
     return RestResponse.success();
   }
 
-  @Operation(summary = "Get flink cluster")
   @PostMapping("get")
   public RestResponse get(Long id) throws InternalException {
     FlinkCluster cluster = flinkClusterService.getById(id);
     return RestResponse.success(cluster);
   }
 
-  @Operation(summary = "Start flink cluster")
   @PostMapping("start")
   public RestResponse start(FlinkCluster cluster) {
     flinkClusterService.updateClusterState(cluster.getId(), ClusterState.STARTING);
@@ -105,7 +94,6 @@ public class FlinkClusterController {
     return RestResponse.success();
   }
 
-  @Operation(summary = "Shutdown flink cluster")
   @PostMapping("shutdown")
   public RestResponse shutdown(FlinkCluster cluster) {
     if (flinkClusterService.allowShutdownCluster(cluster)) {
@@ -115,7 +103,6 @@ public class FlinkClusterController {
     return RestResponse.success();
   }
 
-  @Operation(summary = "Delete flink cluster")
   @PostMapping("delete")
   public RestResponse delete(FlinkCluster cluster) {
     flinkClusterService.remove(cluster.getId());
diff --git a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/controller/FlinkEnvController.java b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/controller/FlinkEnvController.java
index a4a663b81..e7c0e51b5 100644
--- a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/controller/FlinkEnvController.java
+++ b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/controller/FlinkEnvController.java
@@ -23,8 +23,6 @@ import org.apache.streampark.console.core.entity.FlinkEnv;
 import org.apache.streampark.console.core.enums.FlinkEnvCheckEnum;
 import org.apache.streampark.console.core.service.FlinkEnvService;
 
-import io.swagger.v3.oas.annotations.Operation;
-import io.swagger.v3.oas.annotations.tags.Tag;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.validation.annotation.Validated;
@@ -34,7 +32,6 @@ import org.springframework.web.bind.annotation.RestController;
 
 import java.util.List;
 
-@Tag(name = "FLINK_ENV_TAG")
 @Slf4j
 @Validated
 @RestController
@@ -43,21 +40,18 @@ public class FlinkEnvController {
 
   @Autowired private FlinkEnvService flinkEnvService;
 
-  @Operation(summary = "Get flink environment")
   @PostMapping("list")
   public RestResponse list() {
     List<FlinkEnv> flinkEnvList = flinkEnvService.list();
     return RestResponse.success(flinkEnvList);
   }
 
-  @Operation(summary = "Verify flink environment")
   @PostMapping("check")
   public RestResponse check(FlinkEnv version) {
     FlinkEnvCheckEnum checkResp = flinkEnvService.check(version);
     return RestResponse.success(checkResp.getCode());
   }
 
-  @Operation(summary = "Create flink environment")
   @PostMapping("create")
   public RestResponse create(FlinkEnv version) {
     try {
@@ -68,7 +62,6 @@ public class FlinkEnvController {
     return RestResponse.success(true);
   }
 
-  @Operation(summary = "Get flink environment")
   @PostMapping("get")
   public RestResponse get(Long id) throws Exception {
     FlinkEnv flinkEnv = flinkEnvService.getById(id);
@@ -76,14 +69,12 @@ public class FlinkEnvController {
     return RestResponse.success(flinkEnv);
   }
 
-  @Operation(summary = "Sync flink environment conf")
   @PostMapping("sync")
   public RestResponse sync(Long id) throws Exception {
     flinkEnvService.syncConf(id);
     return RestResponse.success();
   }
 
-  @Operation(summary = "Update flink environment")
   @PostMapping("update")
   public RestResponse update(FlinkEnv version) throws Exception {
     try {
@@ -94,21 +85,18 @@ public class FlinkEnvController {
     return RestResponse.success(true);
   }
 
-  @Operation(summary = "Delete flink environment")
   @PostMapping("delete")
   public RestResponse delete(Long id) {
     flinkEnvService.removeById(id);
     return RestResponse.success();
   }
 
-  @Operation(summary = "Check flink environment is valid, else throw exception")
   @PostMapping("validity")
   public RestResponse validity(FlinkEnv version) {
     flinkEnvService.validity(version.getId());
     return RestResponse.success(true);
   }
 
-  @Operation(summary = "Update flink environment as default")
   @PostMapping("default")
   public RestResponse setDefault(Long id) {
     flinkEnvService.setDefault(id);
diff --git a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/controller/FlinkGateWayController.java b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/controller/FlinkGateWayController.java
index 6f0e0ec4f..de8157de4 100644
--- a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/controller/FlinkGateWayController.java
+++ b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/controller/FlinkGateWayController.java
@@ -22,8 +22,6 @@ import org.apache.streampark.console.core.entity.FlinkGateWay;
 import org.apache.streampark.console.core.enums.GatewayTypeEnum;
 import org.apache.streampark.console.core.service.FlinkGateWayService;
 
-import io.swagger.v3.oas.annotations.Operation;
-import io.swagger.v3.oas.annotations.tags.Tag;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.validation.annotation.Validated;
@@ -39,7 +37,6 @@ import org.springframework.web.bind.annotation.RestController;
 
 import javax.validation.constraints.NotNull;
 
-@Tag(name = "FLINK_GATEWAY_TAG")
 @Slf4j
 @Validated
 @RestController
@@ -49,27 +46,23 @@ public class FlinkGateWayController {
 
   private final FlinkGateWayService flinkGatewayService;
 
-  @Operation(summary = "List flink gateways")
   @GetMapping("list")
   public RestResponse list() {
     return RestResponse.success(flinkGatewayService.list());
   }
 
-  @Operation(summary = "Create flink gateway")
   @PostMapping("create")
   public RestResponse create(@RequestBody FlinkGateWay flinkGateWay) {
     flinkGatewayService.create(flinkGateWay);
     return RestResponse.success();
   }
 
-  @Operation(summary = "Check flink gateway name")
   @GetMapping("check/name")
   public RestResponse checkName(
       @NotNull(message = "The Gateway name cannot be null") @RequestParam("name") String name) {
     return RestResponse.success(flinkGatewayService.existsByGatewayName(name));
   }
 
-  @Operation(summary = "Check flink gateway address")
   @GetMapping("check/address")
   public RestResponse checkAddress(
       @NotNull(message = "The Gateway address cannot be null") @RequestParam("address")
@@ -79,20 +72,17 @@ public class FlinkGateWayController {
     return RestResponse.success(gatewayVersion);
   }
 
-  @Operation(summary = "Update flink gateway")
   @PutMapping("update")
   public RestResponse update(@RequestBody FlinkGateWay flinkGateWay) {
     flinkGatewayService.update(flinkGateWay);
     return RestResponse.success();
   }
 
-  @Operation(summary = "Get flink gateway by id")
   @GetMapping("get/{id}")
   public RestResponse get(@PathVariable Long id) {
     return RestResponse.success(flinkGatewayService.getById(id));
   }
 
-  @Operation(summary = "Delete flink gateway by id")
   @DeleteMapping("delete")
   public RestResponse delete(
       @NotNull(message = "The Gateway id cannot be null") @RequestParam("id") Long id) {
diff --git a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/controller/FlinkPodTemplateController.java b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/controller/FlinkPodTemplateController.java
index 9b7805ac8..28c5d5e59 100644
--- a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/controller/FlinkPodTemplateController.java
+++ b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/controller/FlinkPodTemplateController.java
@@ -23,8 +23,6 @@ import org.apache.streampark.flink.kubernetes.PodTemplateParser;
 
 import org.apache.commons.lang3.StringUtils;
 
-import io.swagger.v3.oas.annotations.Operation;
-import io.swagger.v3.oas.annotations.tags.Tag;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.PostMapping;
@@ -37,14 +35,12 @@ import java.util.List;
 import java.util.Map;
 import java.util.stream.Collectors;
 
-@Tag(name = "FLINK_POD_TEMPLATE_TAG")
 @Slf4j
 @Validated
 @RestController
 @RequestMapping("flink/podtmpl")
 public class FlinkPodTemplateController {
 
-  @Operation(summary = "Get system hosts")
   @PostMapping("sysHosts")
   public RestResponse getHosts() {
     // hostname -> ipv4
@@ -56,14 +52,12 @@ public class FlinkPodTemplateController {
     return RestResponse.success(friendlyHosts);
   }
 
-  @Operation(summary = "Get initial pod template")
   @PostMapping("init")
   public RestResponse getInitContent() {
     return RestResponse.success(PodTemplateParser.getInitPodTemplateContent());
   }
 
   /** @param hosts hostname:ipv4,hostname:ipv4,hostname:ipv4... */
-  @Operation(summary = "Get pod template of complete host-alias")
   @PostMapping("compHostAlias")
   public RestResponse completeHostAlias(String hosts, String podTemplate) {
     Map<String, String> hostMap = covertHostsParamToMap(hosts);
@@ -85,7 +79,6 @@ public class FlinkPodTemplateController {
         .collect(Collectors.toMap(arr -> arr[0], arr -> arr[1]));
   }
 
-  @Operation(summary = "Extract host-alias from pod template")
   @PostMapping("extractHostAlias")
   public RestResponse extractHostAlias(String podTemplate) {
     Map<String, String> hosts = PodTemplateParser.extractHostAliasMap(podTemplate);
@@ -97,7 +90,6 @@ public class FlinkPodTemplateController {
   }
 
   /** @param hosts hostname:ipv4,hostname:ipv4,hostname:ipv4... */
-  @Operation(summary = "Preview pod template with host-alias")
   @PostMapping("previewHostAlias")
   public RestResponse previewHostAlias(String hosts) {
     Map<String, String> hostMap = covertHostsParamToMap(hosts);
diff --git a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/controller/FlinkSqlController.java b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/controller/FlinkSqlController.java
index e3dba3689..b78e5084b 100644
--- a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/controller/FlinkSqlController.java
+++ b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/controller/FlinkSqlController.java
@@ -19,7 +19,9 @@ package org.apache.streampark.console.core.controller;
 
 import org.apache.streampark.console.base.domain.RestRequest;
 import org.apache.streampark.console.base.domain.RestResponse;
+import org.apache.streampark.console.base.exception.ApiAlertException;
 import org.apache.streampark.console.base.exception.InternalException;
+import org.apache.streampark.console.core.annotation.PermissionScope;
 import org.apache.streampark.console.core.entity.Application;
 import org.apache.streampark.console.core.entity.FlinkSql;
 import org.apache.streampark.console.core.service.FlinkSqlService;
@@ -30,8 +32,6 @@ import org.apache.streampark.flink.core.FlinkSqlValidationResult;
 import org.apache.shiro.authz.annotation.RequiresPermissions;
 
 import com.baomidou.mybatisplus.core.metadata.IPage;
-import io.swagger.v3.oas.annotations.Operation;
-import io.swagger.v3.oas.annotations.tags.Tag;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.validation.annotation.Validated;
@@ -43,7 +43,6 @@ import javax.validation.constraints.NotNull;
 
 import java.util.List;
 
-@Tag(name = "FLINK_SQL_TAG")
 @Slf4j
 @Validated
 @RestController
@@ -60,7 +59,6 @@ public class FlinkSqlController {
 
   @Autowired private SqlCompleteService sqlComplete;
 
-  @Operation(summary = "Verify sql")
   @PostMapping("verify")
   public RestResponse verify(String sql, Long versionId, Long teamId) {
     sql = variableService.replaceVariable(teamId, sql);
@@ -86,24 +84,26 @@ public class FlinkSqlController {
     return RestResponse.success(true);
   }
 
-  @Operation(summary = "List the application sql")
   @PostMapping("list")
-  public RestResponse list(Long appId, RestRequest request) {
-    IPage<FlinkSql> page = flinkSqlService.getPage(appId, request);
+  @PermissionScope(app = "#flinkSql.appId", team = "#flinkSql.teamId")
+  public RestResponse list(FlinkSql flinkSql, RestRequest request) {
+    IPage<FlinkSql> page = flinkSqlService.getPage(flinkSql.getAppId(), request);
     return RestResponse.success(page);
   }
 
-  @Operation(summary = "Delete sql")
   @PostMapping("delete")
   @RequiresPermissions("sql:delete")
-  public RestResponse delete(Long id) {
-    Boolean deleted = flinkSqlService.removeById(id);
+  @PermissionScope(app = "#flinkSql.appId", team = "#flinkSql.teamId")
+  public RestResponse delete(FlinkSql flinkSql) {
+    Boolean deleted = flinkSqlService.removeById(flinkSql.getSql());
     return RestResponse.success(deleted);
   }
 
-  @Operation(summary = "List sql by ids")
   @PostMapping("get")
-  public RestResponse get(String id) throws InternalException {
+  @PermissionScope(app = "#appId", team = "#teamId")
+  public RestResponse get(Long appId, Long teamId, String id) throws InternalException {
+    ApiAlertException.throwIfTrue(
+        appId == null || teamId == null, "Permission denied, appId and teamId cannot be null");
     String[] array = id.split(",");
     FlinkSql flinkSql1 = flinkSqlService.getById(array[0]);
     flinkSql1.base64Encode();
@@ -115,14 +115,13 @@ public class FlinkSqlController {
     return RestResponse.success(new FlinkSql[] {flinkSql1, flinkSql2});
   }
 
-  @Operation(summary = "List the applications sql histories")
   @PostMapping("history")
-  public RestResponse sqlhistory(Application application) {
-    List<FlinkSql> sqlList = flinkSqlService.listFlinkSqlHistory(application.getId());
+  @PermissionScope(app = "#app.id", team = "#app.teamId")
+  public RestResponse sqlhistory(Application app) {
+    List<FlinkSql> sqlList = flinkSqlService.listFlinkSqlHistory(app.getId());
     return RestResponse.success(sqlList);
   }
 
-  @Operation(summary = "Get the complete sql")
   @PostMapping("sqlComplete")
   public RestResponse getSqlComplete(@NotNull(message = "{required}") String sql) {
     return RestResponse.success().put("word", sqlComplete.getComplete(sql));
diff --git a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/controller/MessageController.java b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/controller/MessageController.java
index e0bfaf28b..4f566dcb3 100644
--- a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/controller/MessageController.java
+++ b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/controller/MessageController.java
@@ -24,8 +24,6 @@ import org.apache.streampark.console.core.enums.NoticeTypeEnum;
 import org.apache.streampark.console.core.service.MessageService;
 
 import com.baomidou.mybatisplus.core.metadata.IPage;
-import io.swagger.v3.oas.annotations.Operation;
-import io.swagger.v3.oas.annotations.tags.Tag;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.validation.annotation.Validated;
@@ -33,7 +31,6 @@ import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
 
-@Tag(name = "MESSAGE_TAG")
 @Slf4j
 @Validated
 @RestController
@@ -42,7 +39,6 @@ public class MessageController {
 
   @Autowired private MessageService messageService;
 
-  @Operation(summary = "List notices")
   @PostMapping("notice")
   public RestResponse notice(Integer type, RestRequest request) {
     NoticeTypeEnum noticeTypeEnum = NoticeTypeEnum.of(type);
@@ -50,7 +46,6 @@ public class MessageController {
     return RestResponse.success(pages);
   }
 
-  @Operation(summary = "Delete notice")
   @PostMapping("delnotice")
   public RestResponse delNotice(Long id) {
     return RestResponse.success(messageService.removeById(id));
diff --git a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/controller/ProjectController.java b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/controller/ProjectController.java
index 191e8ae83..d63aeae36 100644
--- a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/controller/ProjectController.java
+++ b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/controller/ProjectController.java
@@ -21,6 +21,7 @@ import org.apache.streampark.console.base.domain.RestRequest;
 import org.apache.streampark.console.base.domain.RestResponse;
 import org.apache.streampark.console.base.exception.ApiAlertException;
 import org.apache.streampark.console.core.annotation.AppUpdated;
+import org.apache.streampark.console.core.annotation.PermissionScope;
 import org.apache.streampark.console.core.entity.Project;
 import org.apache.streampark.console.core.enums.GitAuthorizedErrorEnum;
 import org.apache.streampark.console.core.service.ProjectService;
@@ -28,8 +29,6 @@ import org.apache.streampark.console.core.service.ProjectService;
 import org.apache.shiro.authz.annotation.RequiresPermissions;
 
 import com.baomidou.mybatisplus.core.metadata.IPage;
-import io.swagger.v3.oas.annotations.Operation;
-import io.swagger.v3.oas.annotations.tags.Tag;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.validation.annotation.Validated;
@@ -42,7 +41,6 @@ import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 
-@Tag(name = "PROJECT_TAG")
 @Slf4j
 @Validated
 @RestController
@@ -51,8 +49,8 @@ public class ProjectController {
 
   @Autowired private ProjectService projectService;
 
-  @Operation(summary = "Create project")
   @PostMapping("create")
+  @PermissionScope(team = "#project.teamId")
   @RequiresPermissions("project:create")
   public RestResponse create(Project project) {
     ApiAlertException.throwIfNull(
@@ -60,40 +58,42 @@ public class ProjectController {
     return projectService.create(project);
   }
 
-  @Operation(summary = "Update project")
   @AppUpdated
   @PostMapping("update")
   @RequiresPermissions("project:update")
+  @PermissionScope(team = "#project.teamId")
   public RestResponse update(Project project) {
     boolean update = projectService.update(project);
     return RestResponse.success().data(update);
   }
 
-  @Operation(summary = "Get project")
   @PostMapping("get")
-  public RestResponse get(Long id) {
-    return RestResponse.success().data(projectService.getById(id));
+  @PermissionScope(team = "#project.teamId")
+  public RestResponse get(Project project) {
+    return RestResponse.success().data(projectService.getById(project.getId()));
   }
 
-  @Operation(summary = "Build project")
   @PostMapping("build")
   @RequiresPermissions("project:build")
-  public RestResponse build(Long id) throws Exception {
-    projectService.build(id);
+  @PermissionScope(team = "#project.teamId")
+  public RestResponse build(Project project) throws Exception {
+    projectService.build(project.getId());
     return RestResponse.success();
   }
 
-  @Operation(summary = "Get project build logs")
   @PostMapping("buildlog")
   @RequiresPermissions("project:build")
+  @PermissionScope(team = "#teamId")
   public RestResponse buildLog(
-      Long id, @RequestParam(value = "startOffset", required = false) Long startOffset) {
+      Long id,
+      @RequestParam(value = "startOffset", required = false) Long startOffset,
+      Long teamId) {
     return projectService.getBuildLog(id, startOffset);
   }
 
-  @Operation(summary = "List projects")
   @PostMapping("list")
   @RequiresPermissions("project:view")
+  @PermissionScope(team = "#project.teamId")
   public RestResponse list(Project project, RestRequest restRequest) {
     if (project.getTeamId() == null) {
       return RestResponse.success(Collections.emptyList());
@@ -102,60 +102,60 @@ public class ProjectController {
     return RestResponse.success().data(page);
   }
 
-  @Operation(summary = "List git project branches")
   @PostMapping("branches")
+  @PermissionScope(team = "#project.teamId")
   public RestResponse branches(Project project) {
-    List<String> branches = projectService.getAllBranches(project);
+    List<String> branches = project.getAllBranches();
     return RestResponse.success().data(branches);
   }
 
-  @Operation(summary = "Delete project")
   @PostMapping("delete")
   @RequiresPermissions("project:delete")
-  public RestResponse delete(Long id) {
-    Boolean deleted = projectService.removeById(id);
+  @PermissionScope(team = "#project.teamId")
+  public RestResponse delete(Project project) {
+    Boolean deleted = projectService.removeById(project.getId());
     return RestResponse.success().data(deleted);
   }
 
-  @Operation(summary = "Authenticate git project")
   @PostMapping("gitcheck")
+  @PermissionScope(team = "#project.teamId")
   public RestResponse gitCheck(Project project) {
-    GitAuthorizedErrorEnum error = projectService.gitCheck(project);
+    GitAuthorizedErrorEnum error = project.gitCheck();
     return RestResponse.success().data(error.getType());
   }
 
-  @Operation(summary = "Check the project")
   @PostMapping("exists")
+  @PermissionScope(team = "#project.teamId")
   public RestResponse exists(Project project) {
     boolean exists = projectService.exists(project);
     return RestResponse.success().data(exists);
   }
 
-  @Operation(summary = "List project modules")
   @PostMapping("modules")
-  public RestResponse modules(Long id) {
-    List<String> result = projectService.listModules(id);
+  @PermissionScope(team = "#project.teamId")
+  public RestResponse modules(Project project) {
+    List<String> result = projectService.listModules(project.getId());
     return RestResponse.success().data(result);
   }
 
-  @Operation(summary = "List project jars")
   @PostMapping("jars")
+  @PermissionScope(team = "#project.teamId")
   public RestResponse jars(Project project) {
     List<String> result = projectService.listJars(project);
     return RestResponse.success().data(result);
   }
 
-  @Operation(summary = "List project configurations")
   @PostMapping("listconf")
+  @PermissionScope(team = "#project.teamId")
   public RestResponse listConf(Project project) {
-    List<Map<String, Object>> confList = projectService.listConf(project);
-    return RestResponse.success().data(confList);
+    List<Map<String, Object>> list = projectService.listConf(project);
+    return RestResponse.success().data(list);
   }
 
-  @Operation(summary = "List the team projects")
   @PostMapping("select")
+  @PermissionScope(team = "#teamId")
   public RestResponse select(@RequestParam Long teamId) {
-    List<Project> projectList = projectService.listByTeamId(teamId);
-    return RestResponse.success().data(projectList);
+    List<Project> list = projectService.listByTeamId(teamId);
+    return RestResponse.success().data(list);
   }
 }
diff --git a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/controller/ResourceController.java b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/controller/ResourceController.java
index c2761e0bc..fab860df6 100644
--- a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/controller/ResourceController.java
+++ b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/controller/ResourceController.java
@@ -25,8 +25,6 @@ import org.apache.streampark.console.core.service.ResourceService;
 import org.apache.shiro.authz.annotation.RequiresPermissions;
 
 import com.baomidou.mybatisplus.core.metadata.IPage;
-import io.swagger.v3.oas.annotations.Operation;
-import io.swagger.v3.oas.annotations.tags.Tag;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.validation.annotation.Validated;
@@ -42,7 +40,6 @@ import javax.validation.Valid;
 
 import java.util.List;
 
-@Tag(name = "RESOURCE_TAG")
 @Slf4j
 @Validated
 @RestController
@@ -51,7 +48,6 @@ public class ResourceController {
 
   @Autowired private ResourceService resourceService;
 
-  @Operation(summary = "add resource")
   @PostMapping("add")
   @RequiresPermissions("resource:add")
   public RestResponse addResource(@Valid Resource resource) throws Exception {
@@ -59,20 +55,17 @@ public class ResourceController {
     return RestResponse.success();
   }
 
-  @Operation(summary = "check resource")
   @PostMapping("check")
   public RestResponse checkResource(@Valid Resource resource) throws Exception {
     return this.resourceService.checkResource(resource);
   }
 
-  @Operation(summary = "List resources")
   @PostMapping("page")
   public RestResponse page(RestRequest restRequest, Resource resource) {
     IPage<Resource> page = resourceService.getPage(resource, restRequest);
     return RestResponse.success(page);
   }
 
-  @Operation(summary = "Update resource")
   @PutMapping("update")
   @RequiresPermissions("resource:update")
   public RestResponse updateResource(@Valid Resource resource) {
@@ -80,7 +73,6 @@ public class ResourceController {
     return RestResponse.success();
   }
 
-  @Operation(summary = "Delete resource")
   @DeleteMapping("delete")
   @RequiresPermissions("resource:delete")
   public RestResponse deleteResource(@Valid Resource resource) {
@@ -88,14 +80,12 @@ public class ResourceController {
     return RestResponse.success();
   }
 
-  @Operation(summary = "List resource")
   @PostMapping("list")
   public RestResponse listResource(@RequestParam Long teamId) {
     List<Resource> resourceList = resourceService.listByTeamId(teamId);
     return RestResponse.success(resourceList);
   }
 
-  @Operation(summary = "Upload the resource jar")
   @PostMapping("upload")
   @RequiresPermissions("resource:add")
   public RestResponse upload(MultipartFile file) throws Exception {
diff --git a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/controller/SavePointController.java b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/controller/SavePointController.java
index e228b838e..18529a3dc 100644
--- a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/controller/SavePointController.java
+++ b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/controller/SavePointController.java
@@ -20,7 +20,7 @@ package org.apache.streampark.console.core.controller;
 import org.apache.streampark.console.base.domain.RestRequest;
 import org.apache.streampark.console.base.domain.RestResponse;
 import org.apache.streampark.console.base.exception.InternalException;
-import org.apache.streampark.console.core.annotation.ApiAccess;
+import org.apache.streampark.console.core.annotation.PermissionScope;
 import org.apache.streampark.console.core.entity.Application;
 import org.apache.streampark.console.core.entity.SavePoint;
 import org.apache.streampark.console.core.service.SavePointService;
@@ -29,11 +29,6 @@ import org.apache.streampark.console.core.service.application.ApplicationManageS
 import org.apache.shiro.authz.annotation.RequiresPermissions;
 
 import com.baomidou.mybatisplus.core.metadata.IPage;
-import io.swagger.v3.oas.annotations.Operation;
-import io.swagger.v3.oas.annotations.Parameter;
-import io.swagger.v3.oas.annotations.Parameters;
-import io.swagger.v3.oas.annotations.media.Schema;
-import io.swagger.v3.oas.annotations.tags.Tag;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.validation.annotation.Validated;
@@ -43,7 +38,6 @@ import org.springframework.web.bind.annotation.RestController;
 
 import javax.annotation.Nullable;
 
-@Tag(name = "SAVEPOINT_TAG")
 @Slf4j
 @Validated
 @RestController
@@ -54,51 +48,25 @@ public class SavePointController {
 
   @Autowired private SavePointService savePointService;
 
-  @Operation(summary = "Get application savepoint latest")
-  @PostMapping("latest")
-  public RestResponse latest(Long appId) {
-    SavePoint savePoint = savePointService.getLatest(appId);
-    return RestResponse.success(savePoint);
-  }
-
-  @Operation(summary = "List application savepoint histories")
   @PostMapping("history")
-  public RestResponse history(SavePoint savePoint, RestRequest request) {
-    IPage<SavePoint> page = savePointService.getPage(savePoint, request);
+  @PermissionScope(app = "#sp.appId", team = "#sp.teamId")
+  public RestResponse history(SavePoint sp, RestRequest request) {
+    IPage<SavePoint> page = savePointService.getPage(sp, request);
     return RestResponse.success(page);
   }
 
-  @Operation(summary = "Delete savepoint")
   @PostMapping("delete")
   @RequiresPermissions("savepoint:delete")
-  public RestResponse delete(Long id) throws InternalException {
-    SavePoint savePoint = savePointService.getById(id);
+  @PermissionScope(app = "#sp.appId", team = "#sp.teamId")
+  public RestResponse delete(SavePoint sp) throws InternalException {
+    SavePoint savePoint = savePointService.getById(sp.getId());
     Application application = applicationManageService.getById(savePoint.getAppId());
-    Boolean deleted = savePointService.remove(id, application);
+    Boolean deleted = savePointService.remove(sp.getId(), application);
     return RestResponse.success(deleted);
   }
 
-  @Operation(
-      summary = "Trigger savepoint",
-      description = "trigger savepoint for specified application")
-  @Parameters({
-    @Parameter(
-        name = "appId",
-        description = "app id",
-        required = true,
-        example = "100000",
-        schema = @Schema(implementation = Long.class)),
-    @Parameter(
-        name = "savepointPath",
-        description = "specified savepoint path",
-        schema = @Schema(implementation = String.class)),
-    @Parameter(
-        name = "nativeFormat",
-        description = "use native format",
-        schema = @Schema(implementation = Boolean.class))
-  })
-  @ApiAccess
   @PostMapping("trigger")
+  @PermissionScope(app = "#savePoint.appId", team = "#savePoint.teamId")
   @RequiresPermissions("savepoint:trigger")
   public RestResponse trigger(
       Long appId, @Nullable String savepointPath, @Nullable Boolean nativeFormat) {
diff --git a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/controller/SettingController.java b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/controller/SettingController.java
index 27b357549..2dfc876f7 100644
--- a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/controller/SettingController.java
+++ b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/controller/SettingController.java
@@ -28,8 +28,6 @@ import org.apache.streampark.console.core.service.SettingService;
 import org.apache.shiro.authz.annotation.RequiresPermissions;
 
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import io.swagger.v3.oas.annotations.Operation;
-import io.swagger.v3.oas.annotations.tags.Tag;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.validation.annotation.Validated;
@@ -39,7 +37,6 @@ import org.springframework.web.bind.annotation.RestController;
 
 import java.util.List;
 
-@Tag(name = "SETTING_TAG")
 @Slf4j
 @Validated
 @RestController
@@ -48,7 +45,6 @@ public class SettingController {
 
   @Autowired private SettingService settingService;
 
-  @Operation(summary = "List settings")
   @PostMapping("all")
   @RequiresPermissions("setting:view")
   public RestResponse all() {
@@ -58,14 +54,12 @@ public class SettingController {
     return RestResponse.success(setting);
   }
 
-  @Operation(summary = "Get setting")
   @PostMapping("get")
   public RestResponse get(String key) {
     Setting setting = settingService.get(key);
     return RestResponse.success(setting);
   }
 
-  @Operation(summary = "Update setting")
   @PostMapping("update")
   @RequiresPermissions("setting:update")
   public RestResponse update(Setting setting) {
@@ -73,7 +67,6 @@ public class SettingController {
     return RestResponse.success(updated);
   }
 
-  @Operation(summary = "get Docker config")
   @PostMapping("docker")
   @RequiresPermissions("setting:view")
   public RestResponse docker() {
@@ -81,7 +74,6 @@ public class SettingController {
     return RestResponse.success(dockerConfig);
   }
 
-  @Operation(summary = "check docker setting")
   @PostMapping("check/docker")
   @RequiresPermissions("setting:view")
   public RestResponse checkDocker(DockerConfig dockerConfig) {
@@ -89,7 +81,6 @@ public class SettingController {
     return RestResponse.success(result);
   }
 
-  @Operation(summary = "Update docker setting")
   @PostMapping("update/docker")
   @RequiresPermissions("setting:update")
   public RestResponse updateDocker(DockerConfig dockerConfig) {
@@ -97,7 +88,6 @@ public class SettingController {
     return RestResponse.success(updated);
   }
 
-  @Operation(summary = "get sender email")
   @PostMapping("email")
   @RequiresPermissions("setting:view")
   public RestResponse email() {
@@ -105,7 +95,6 @@ public class SettingController {
     return RestResponse.success(senderEmail);
   }
 
-  @Operation(summary = "check email")
   @PostMapping("check/email")
   @RequiresPermissions("setting:view")
   public RestResponse checkEmail(SenderEmail senderEmail) {
@@ -113,7 +102,6 @@ public class SettingController {
     return RestResponse.success(result);
   }
 
-  @Operation(summary = "Update sender email")
   @PostMapping("update/email")
   @RequiresPermissions("setting:update")
   public RestResponse updateEmail(SenderEmail senderEmail) {
@@ -121,7 +109,6 @@ public class SettingController {
     return RestResponse.success(updated);
   }
 
-  @Operation(summary = "Check hadoop status")
   @PostMapping("check/hadoop")
   public RestResponse checkHadoop() {
     try {
diff --git a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/controller/SparkApplicationBuildPipelineController.java b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/controller/SparkApplicationBuildPipelineController.java
index 459d30e78..1e179df56 100644
--- a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/controller/SparkApplicationBuildPipelineController.java
+++ b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/controller/SparkApplicationBuildPipelineController.java
@@ -18,14 +18,12 @@
 package org.apache.streampark.console.core.controller;
 
 import org.apache.streampark.console.base.domain.RestResponse;
-import org.apache.streampark.console.core.annotation.PermissionAction;
+import org.apache.streampark.console.core.annotation.PermissionScope;
 import org.apache.streampark.console.core.entity.AppBuildPipeline;
-import org.apache.streampark.console.core.enums.PermissionTypeEnum;
 import org.apache.streampark.console.core.service.SparkAppBuildPipeService;
 
 import org.apache.shiro.authz.annotation.RequiresPermissions;
 
-import io.swagger.v3.oas.annotations.tags.Tag;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.validation.annotation.Validated;
@@ -37,7 +35,6 @@ import java.util.HashMap;
 import java.util.Map;
 import java.util.Optional;
 
-@Tag(name = "SPARK_APPLICATION_BUILD_PIPELINE_TAG")
 @Slf4j
 @Validated
 @RestController
@@ -53,9 +50,9 @@ public class SparkApplicationBuildPipelineController {
    * @param forceBuild forced start pipeline or not
    * @return Whether the pipeline was successfully started
    */
-  @PermissionAction(id = "#appId", type = PermissionTypeEnum.APP)
   @PostMapping(value = "build")
   @RequiresPermissions("app:create")
+  @PermissionScope(app = "#appId")
   public RestResponse buildApplication(Long appId, boolean forceBuild) {
     try {
       boolean actionResult = appBuildPipeService.buildApplication(appId, forceBuild);
@@ -71,10 +68,9 @@ public class SparkApplicationBuildPipelineController {
    * @param appId application id
    * @return "pipeline" -> pipeline details, "docker" -> docker resolved snapshot
    */
-  //  @Operation(summary = "Get application release pipeline")
-  //  @ApiAccess
   @PostMapping("/detail")
   @RequiresPermissions("app:view")
+  @PermissionScope(app = "#appId")
   public RestResponse getBuildProgressDetail(Long appId) {
     Map<String, Object> details = new HashMap<>(0);
     Optional<AppBuildPipeline> pipeline = appBuildPipeService.getCurrentBuildPipeline(appId);
diff --git a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/controller/SparkApplicationController.java b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/controller/SparkApplicationController.java
index 0cc19ae8a..90ce3f22b 100644
--- a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/controller/SparkApplicationController.java
+++ b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/controller/SparkApplicationController.java
@@ -22,14 +22,11 @@ import org.apache.streampark.common.util.YarnUtils;
 import org.apache.streampark.console.base.domain.RestRequest;
 import org.apache.streampark.console.base.domain.RestResponse;
 import org.apache.streampark.console.base.exception.InternalException;
-import org.apache.streampark.console.core.annotation.ApiAccess;
 import org.apache.streampark.console.core.annotation.AppUpdated;
-import org.apache.streampark.console.core.annotation.PermissionAction;
 import org.apache.streampark.console.core.entity.ApplicationBackUp;
 import org.apache.streampark.console.core.entity.ApplicationLog;
 import org.apache.streampark.console.core.entity.SparkApplication;
 import org.apache.streampark.console.core.enums.AppExistsStateEnum;
-import org.apache.streampark.console.core.enums.PermissionTypeEnum;
 import org.apache.streampark.console.core.service.ApplicationBackUpService;
 import org.apache.streampark.console.core.service.ApplicationLogService;
 import org.apache.streampark.console.core.service.ResourceService;
@@ -40,10 +37,6 @@ import org.apache.streampark.console.core.service.application.SparkApplicationMa
 import org.apache.shiro.authz.annotation.RequiresPermissions;
 
 import com.baomidou.mybatisplus.core.metadata.IPage;
-import io.swagger.v3.oas.annotations.Hidden;
-import io.swagger.v3.oas.annotations.Operation;
-import io.swagger.v3.oas.annotations.Parameter;
-import io.swagger.v3.oas.annotations.tags.Tag;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.validation.annotation.Validated;
@@ -58,7 +51,6 @@ import java.io.Serializable;
 import java.net.URI;
 import java.util.Map;
 
-@Tag(name = "SPARK_APPLICATION_TAG")
 @Slf4j
 @Validated
 @RestController
@@ -77,8 +69,6 @@ public class SparkApplicationController {
 
   @Autowired private ResourceService resourceService;
 
-  @Operation(summary = "Get application")
-  @ApiAccess
   @PostMapping("get")
   @RequiresPermissions("app:detail")
   public RestResponse get(SparkApplication app) {
@@ -86,9 +76,6 @@ public class SparkApplicationController {
     return RestResponse.success(application);
   }
 
-  @Operation(summary = "Create application")
-  @ApiAccess
-  @PermissionAction(id = "#app.teamId", type = PermissionTypeEnum.TEAM)
   @PostMapping("create")
   @RequiresPermissions("app:create")
   public RestResponse create(SparkApplication app) throws IOException {
@@ -96,18 +83,14 @@ public class SparkApplicationController {
     return RestResponse.success(saved);
   }
 
-  @ApiAccess
-  @PermissionAction(id = "#app.id", type = PermissionTypeEnum.APP)
   @PostMapping(value = "copy")
   @RequiresPermissions("app:copy")
-  public RestResponse copy(@Parameter(hidden = true) SparkApplication app) throws IOException {
+  public RestResponse copy(SparkApplication app) throws IOException {
     applicationManageService.copy(app);
     return RestResponse.success();
   }
 
-  @Operation(summary = "Update application")
   @AppUpdated
-  @PermissionAction(id = "#app.id", type = PermissionTypeEnum.APP)
   @PostMapping("update")
   @RequiresPermissions("app:update")
   public RestResponse update(SparkApplication app) {
@@ -115,15 +98,12 @@ public class SparkApplicationController {
     return RestResponse.success(true);
   }
 
-  @Operation(summary = "Get applications dashboard data")
   @PostMapping("dashboard")
   public RestResponse dashboard(Long teamId) {
     Map<String, Serializable> dashboardMap = applicationInfoService.getDashboardDataMap(teamId);
     return RestResponse.success(dashboardMap);
   }
 
-  @Operation(summary = "List applications")
-  @ApiAccess
   @PostMapping("list")
   @RequiresPermissions("app:view")
   public RestResponse list(SparkApplication app, RestRequest request) {
@@ -131,7 +111,6 @@ public class SparkApplicationController {
     return RestResponse.success(applicationList);
   }
 
-  @Operation(summary = "Mapping application")
   @AppUpdated
   @PostMapping("mapping")
   @RequiresPermissions("app:mapping")
@@ -140,9 +119,7 @@ public class SparkApplicationController {
     return RestResponse.success(flag);
   }
 
-  @Operation(summary = "Revoke application")
   @AppUpdated
-  @PermissionAction(id = "#app.id", type = PermissionTypeEnum.APP)
   @PostMapping("revoke")
   @RequiresPermissions("app:release")
   public RestResponse revoke(SparkApplication app) {
@@ -150,7 +127,6 @@ public class SparkApplicationController {
     return RestResponse.success();
   }
 
-  @PermissionAction(id = "#app.id", type = PermissionTypeEnum.APP)
   @PostMapping(value = "check_start")
   @RequiresPermissions("app:start")
   public RestResponse checkStart(SparkApplication app) {
@@ -158,11 +134,9 @@ public class SparkApplicationController {
     return RestResponse.success(stateEnum.get());
   }
 
-  @ApiAccess
-  @PermissionAction(id = "#app.id", type = PermissionTypeEnum.APP)
   @PostMapping(value = "start")
   @RequiresPermissions("app:start")
-  public RestResponse start(@Parameter(hidden = true) SparkApplication app) {
+  public RestResponse start(SparkApplication app) {
     try {
       applicationActionService.start(app, false);
       return RestResponse.success(true);
@@ -171,18 +145,14 @@ public class SparkApplicationController {
     }
   }
 
-  @PermissionAction(id = "#app.id", type = PermissionTypeEnum.APP)
   @PostMapping(value = "cancel")
   @RequiresPermissions("app:cancel")
-  public RestResponse cancel(@Parameter(hidden = true) SparkApplication app) throws Exception {
+  public RestResponse cancel(SparkApplication app) throws Exception {
     applicationActionService.cancel(app);
     return RestResponse.success();
   }
 
-  @Operation(summary = "Clean application")
   @AppUpdated
-  @ApiAccess
-  @PermissionAction(id = "#app.id", type = PermissionTypeEnum.APP)
   @PostMapping("clean")
   @RequiresPermissions("app:clean")
   public RestResponse clean(SparkApplication app) {
@@ -190,9 +160,6 @@ public class SparkApplicationController {
     return RestResponse.success(true);
   }
 
-  /** force stop(stop normal start or in progress) */
-  @Operation(summary = "Force stop application")
-  @PermissionAction(id = "#app.id", type = PermissionTypeEnum.APP)
   @PostMapping("forcedStop")
   @RequiresPermissions("app:cancel")
   public RestResponse forcedStop(SparkApplication app) {
@@ -200,56 +167,47 @@ public class SparkApplicationController {
     return RestResponse.success();
   }
 
-  @Operation(summary = "Get application on yarn proxy address")
   @PostMapping("yarn")
   public RestResponse yarn() {
     return RestResponse.success(YarnUtils.getRMWebAppProxyURL());
   }
 
-  @Operation(summary = "Get application on yarn name")
   @PostMapping("name")
   public RestResponse yarnName(SparkApplication app) {
     String yarnName = applicationInfoService.getYarnName(app.getConfig());
     return RestResponse.success(yarnName);
   }
 
-  @Operation(summary = "Check the application exist status")
   @PostMapping("checkName")
   public RestResponse checkName(SparkApplication app) {
     AppExistsStateEnum exists = applicationInfoService.checkExists(app);
     return RestResponse.success(exists.get());
   }
 
-  @Operation(summary = "Get application conf")
   @PostMapping("readConf")
   public RestResponse readConf(SparkApplication app) throws IOException {
     String config = applicationInfoService.readConf(app.getConfig());
     return RestResponse.success(config);
   }
 
-  @Operation(summary = "Get application main-class")
   @PostMapping("main")
   public RestResponse getMain(SparkApplication application) {
     String mainClass = applicationInfoService.getMain(application);
     return RestResponse.success(mainClass);
   }
 
-  @Operation(summary = "List application backups")
   @PostMapping("backups")
   public RestResponse backups(ApplicationBackUp backUp, RestRequest request) {
     IPage<ApplicationBackUp> backups = backUpService.getPage(backUp, request);
     return RestResponse.success(backups);
   }
 
-  @Operation(summary = "List application operation logs")
   @PostMapping("optionlog")
   public RestResponse optionlog(ApplicationLog applicationLog, RestRequest request) {
     IPage<ApplicationLog> applicationList = applicationLogService.getPage(applicationLog, request);
     return RestResponse.success(applicationList);
   }
 
-  @Operation(summary = "Delete application operation log")
-  @PermissionAction(id = "#applicationLog.appId", type = PermissionTypeEnum.APP)
   @PostMapping("deleteOperationLog")
   @RequiresPermissions("app:delete")
   public RestResponse deleteOperationLog(Long id) {
@@ -257,8 +215,6 @@ public class SparkApplicationController {
     return RestResponse.success(deleted);
   }
 
-  @Operation(summary = "Delete application")
-  @PermissionAction(id = "#app.id", type = PermissionTypeEnum.APP)
   @PostMapping("delete")
   @RequiresPermissions("app:delete")
   public RestResponse delete(SparkApplication app) throws InternalException {
@@ -266,15 +222,12 @@ public class SparkApplicationController {
     return RestResponse.success(deleted);
   }
 
-  @Operation(summary = "Backup application when deleted")
-  @PermissionAction(id = "#backUp.appId", type = PermissionTypeEnum.APP)
   @PostMapping("deletebak")
   public RestResponse deleteBak(ApplicationBackUp backUp) throws InternalException {
     Boolean deleted = backUpService.removeById(backUp.getId());
     return RestResponse.success(deleted);
   }
 
-  @Operation(summary = "Check the application jar")
   @PostMapping("checkjar")
   public RestResponse checkjar(String jar) {
     File file = new File(jar);
@@ -286,7 +239,6 @@ public class SparkApplicationController {
     }
   }
 
-  @Operation(summary = "Upload the application jar")
   @PostMapping("upload")
   @RequiresPermissions("app:create")
   public RestResponse upload(MultipartFile file) throws Exception {
@@ -294,7 +246,6 @@ public class SparkApplicationController {
     return RestResponse.success(uploadPath);
   }
 
-  @Hidden
   @PostMapping("verifySchema")
   public RestResponse verifySchema(String path) {
     final URI uri = URI.create(path);
diff --git a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/controller/SparkEnvController.java b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/controller/SparkEnvController.java
index a5c714ec9..f418a08fa 100644
--- a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/controller/SparkEnvController.java
+++ b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/controller/SparkEnvController.java
@@ -23,8 +23,6 @@ import org.apache.streampark.console.core.entity.SparkEnv;
 import org.apache.streampark.console.core.enums.FlinkEnvCheckEnum;
 import org.apache.streampark.console.core.service.SparkEnvService;
 
-import io.swagger.v3.oas.annotations.Operation;
-import io.swagger.v3.oas.annotations.tags.Tag;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.validation.annotation.Validated;
@@ -34,7 +32,6 @@ import org.springframework.web.bind.annotation.RestController;
 
 import java.util.List;
 
-@Tag(name = "SPARK_ENV_TAG")
 @Slf4j
 @Validated
 @RestController
@@ -43,21 +40,18 @@ public class SparkEnvController {
 
   @Autowired private SparkEnvService sparkEnvService;
 
-  @Operation(summary = "Get spark environment")
   @PostMapping("list")
   public RestResponse list() {
     List<SparkEnv> sparkEnvList = sparkEnvService.list();
     return RestResponse.success(sparkEnvList);
   }
 
-  @Operation(summary = "Verify spark environment")
   @PostMapping("check")
   public RestResponse check(SparkEnv version) {
     FlinkEnvCheckEnum checkResp = sparkEnvService.check(version);
     return RestResponse.success(checkResp.getCode());
   }
 
-  @Operation(summary = "Create spark environment")
   @PostMapping("create")
   public RestResponse create(SparkEnv version) {
     try {
@@ -68,7 +62,6 @@ public class SparkEnvController {
     return RestResponse.success(true);
   }
 
-  @Operation(summary = "Get spark environment")
   @PostMapping("get")
   public RestResponse get(Long id) throws Exception {
     SparkEnv sparkEnv = sparkEnvService.getById(id);
@@ -76,14 +69,12 @@ public class SparkEnvController {
     return RestResponse.success(sparkEnv);
   }
 
-  @Operation(summary = "Sync spark environment conf")
   @PostMapping("sync")
   public RestResponse sync(Long id) throws Exception {
     sparkEnvService.syncConf(id);
     return RestResponse.success();
   }
 
-  @Operation(summary = "Update spark environment")
   @PostMapping("update")
   public RestResponse update(SparkEnv version) throws Exception {
     try {
@@ -94,21 +85,18 @@ public class SparkEnvController {
     return RestResponse.success(true);
   }
 
-  @Operation(summary = "Delete spark environment")
   @PostMapping("delete")
   public RestResponse delete(Long id) {
     sparkEnvService.removeById(id);
     return RestResponse.success();
   }
 
-  @Operation(summary = "Check spark environment is valid, else throw exception")
   @PostMapping("validity")
   public RestResponse validity(SparkEnv version) {
     sparkEnvService.validity(version.getId());
     return RestResponse.success(true);
   }
 
-  @Operation(summary = "Update spark environment as default")
   @PostMapping("default")
   public RestResponse setDefault(Long id) {
     sparkEnvService.setDefault(id);
diff --git a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/controller/SqlWorkBenchController.java b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/controller/SqlWorkBenchController.java
index c0d7aa77b..a17a7f5d9 100644
--- a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/controller/SqlWorkBenchController.java
+++ b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/controller/SqlWorkBenchController.java
@@ -18,13 +18,10 @@
 package org.apache.streampark.console.core.controller;
 
 import org.apache.streampark.console.base.domain.RestResponse;
-import org.apache.streampark.console.core.annotation.ApiAccess;
 import org.apache.streampark.console.core.service.SqlWorkBenchService;
 import org.apache.streampark.gateway.results.ResultQueryCondition;
 import org.apache.streampark.gateway.session.SessionHandle;
 
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.DeleteMapping;
@@ -36,7 +33,6 @@ import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.RestController;
 
-@Api(tags = {"FLINK_GATEWAY_TAG"})
 @Slf4j
 @Validated
 @RestController
@@ -51,9 +47,6 @@ public class SqlWorkBenchController {
   // -------------------------------------------------------------------------------------------
   // Validation API
   // -------------------------------------------------------------------------------------------
-  @ApiAccess
-  @ApiOperation(value = "Check Support", notes = "Check Support", tags = "FLINK_GATEWAY_TAG")
-  @GetMapping("{flinkClusterId}/check")
   public RestResponse check(@PathVariable Long flinkGatewayId, @PathVariable Long flinkClusterId) {
     return RestResponse.success(sqlWorkBenchService.check(flinkGatewayId, flinkClusterId));
   }
@@ -62,8 +55,6 @@ public class SqlWorkBenchController {
   // Info API
   // -------------------------------------------------------------------------------------------
 
-  @ApiAccess
-  @ApiOperation(value = "Get gateway info", notes = "Get gateway info", tags = "FLINK_GATEWAY_TAG")
   @GetMapping("getGatewayInfo")
   public RestResponse getGatewayInfo(@PathVariable Long flinkGatewayId) {
     return RestResponse.success(sqlWorkBenchService.getGatewayInfo(flinkGatewayId));
@@ -73,8 +64,6 @@ public class SqlWorkBenchController {
   // Session Management
   // -------------------------------------------------------------------------------------------
 
-  @ApiAccess
-  @ApiOperation(value = "Open sessions", notes = "Open sessions", tags = "FLINK_GATEWAY_TAG")
   @PostMapping("/{flinkClusterId}/sessions")
   public RestResponse openSession(
       @PathVariable Long flinkGatewayId, @PathVariable Long flinkClusterId) {
@@ -82,8 +71,6 @@ public class SqlWorkBenchController {
     return RestResponse.success(sessionHandle);
   }
 
-  @ApiAccess
-  @ApiOperation(value = "Heartbeat", notes = "Heartbeat", tags = "FLINK_GATEWAY_TAG")
   @PostMapping("sessions/{sessionHandle}/heartbeat")
   public RestResponse heartbeat(
       @PathVariable Long flinkGatewayId, @PathVariable String sessionHandle) {
@@ -91,8 +78,6 @@ public class SqlWorkBenchController {
     return RestResponse.success();
   }
 
-  @ApiAccess
-  @ApiOperation(value = "Close session", notes = "Close session", tags = "FLINK_GATEWAY_TAG")
   @DeleteMapping("sessions/{sessionHandle}")
   public RestResponse closeSession(
       @PathVariable Long flinkGatewayId, @PathVariable String sessionHandle) {
@@ -104,8 +89,6 @@ public class SqlWorkBenchController {
   // Operation Management
   // -------------------------------------------------------------------------------------------
 
-  @ApiAccess
-  @ApiOperation(value = "Cancel operation", notes = "Cancel operation", tags = "FLINK_GATEWAY_TAG")
   @PostMapping("sessions/{sessionHandle}/operations/{operationHandle}/cancel")
   public RestResponse cancelOperation(
       @PathVariable Long flinkGatewayId,
@@ -115,8 +98,6 @@ public class SqlWorkBenchController {
     return RestResponse.success();
   }
 
-  @ApiAccess
-  @ApiOperation(value = "Close operation", notes = "Close operation", tags = "FLINK_GATEWAY_TAG")
   @DeleteMapping("sessions/{sessionHandle}/operations/{operationHandle}/close")
   public RestResponse closeOperation(
       @PathVariable Long flinkGatewayId,
@@ -126,11 +107,6 @@ public class SqlWorkBenchController {
     return RestResponse.success();
   }
 
-  @ApiAccess
-  @ApiOperation(
-      value = "Get operation info",
-      notes = "Get operation info",
-      tags = "FLINK_GATEWAY_TAG")
   @PostMapping("sessions/{sessionHandle}/operations/{operationHandle}/info")
   public RestResponse getOperationInfo(
       @PathVariable Long flinkGatewayId,
@@ -140,11 +116,6 @@ public class SqlWorkBenchController {
         sqlWorkBenchService.getOperationInfo(flinkGatewayId, sessionHandle, operationHandle));
   }
 
-  @ApiAccess
-  @ApiOperation(
-      value = "Get operation result schema",
-      notes = "Get operation result schema",
-      tags = "FLINK_GATEWAY_TAG")
   @PostMapping("sessions/{sessionHandle}/operations/{operationHandle}/resultSchema")
   public RestResponse getOperationResultSchema(
       @PathVariable Long flinkGatewayId,
@@ -159,11 +130,6 @@ public class SqlWorkBenchController {
   // Statements API
   // -------------------------------------------------------------------------------------------
 
-  @ApiAccess
-  @ApiOperation(
-      value = "Execute statement",
-      notes = "Execute statement",
-      tags = "FLINK_GATEWAY_TAG")
   @PostMapping("sessions/{sessionHandle}/statements")
   public RestResponse executeStatement(
       @PathVariable Long flinkGatewayId,
@@ -173,8 +139,6 @@ public class SqlWorkBenchController {
         sqlWorkBenchService.executeStatement(flinkGatewayId, sessionHandle, statement));
   }
 
-  @ApiAccess
-  @ApiOperation(value = "Fetch results", notes = "Fetch results", tags = "FLINK_GATEWAY_TAG")
   @PostMapping("sessions/{sessionHandle}/statements/{operationHandle}/info")
   public RestResponse fetchResults(
       @PathVariable Long flinkGatewayId,
diff --git a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/controller/VariableController.java b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/controller/VariableController.java
index 68cc2d54c..569b46166 100644
--- a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/controller/VariableController.java
+++ b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/controller/VariableController.java
@@ -26,8 +26,6 @@ import org.apache.streampark.console.core.service.VariableService;
 import org.apache.shiro.authz.annotation.RequiresPermissions;
 
 import com.baomidou.mybatisplus.core.metadata.IPage;
-import io.swagger.v3.oas.annotations.Operation;
-import io.swagger.v3.oas.annotations.tags.Tag;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.validation.annotation.Validated;
@@ -43,7 +41,6 @@ import javax.validation.constraints.NotBlank;
 
 import java.util.List;
 
-@Tag(name = "VARIABLE_TAG")
 @Slf4j
 @Validated
 @RestController
@@ -59,7 +56,6 @@ public class VariableController {
    * @param variable
    * @return
    */
-  @Operation(summary = "List variables")
   @PostMapping("page")
   @RequiresPermissions("variable:view")
   public RestResponse page(RestRequest restRequest, Variable variable) {
@@ -77,7 +73,6 @@ public class VariableController {
    * @param keyword Fuzzy search keywords through variable code or description, Nullable.
    * @return
    */
-  @Operation(summary = "List variables")
   @PostMapping("list")
   public RestResponse variableList(@RequestParam Long teamId, String keyword) {
     List<Variable> variableList = variableService.listByTeamId(teamId, keyword);
@@ -87,7 +82,6 @@ public class VariableController {
     return RestResponse.success(variableList);
   }
 
-  @Operation(summary = "List the variable depend applications")
   @PostMapping("dependApps")
   @RequiresPermissions("variable:depend_apps")
   public RestResponse dependApps(RestRequest restRequest, Variable variable) {
@@ -95,7 +89,6 @@ public class VariableController {
     return RestResponse.success(dependApps);
   }
 
-  @Operation(summary = "Create variable")
   @PostMapping("post")
   @RequiresPermissions("variable:add")
   public RestResponse addVariable(@Valid Variable variable) {
@@ -103,7 +96,6 @@ public class VariableController {
     return RestResponse.success();
   }
 
-  @Operation(summary = "Update variable")
   @PutMapping("update")
   @RequiresPermissions("variable:update")
   public RestResponse updateVariable(@Valid Variable variable) {
@@ -111,7 +103,6 @@ public class VariableController {
     return RestResponse.success();
   }
 
-  @Operation(summary = "Get variable")
   @PostMapping("showOriginal")
   @RequiresPermissions("variable:show_original")
   public RestResponse showOriginal(@RequestParam Long id) {
@@ -119,7 +110,6 @@ public class VariableController {
     return RestResponse.success(v);
   }
 
-  @Operation(summary = "Delete variable")
   @DeleteMapping("delete")
   @RequiresPermissions("variable:delete")
   public RestResponse deleteVariable(@Valid Variable variable) {
@@ -127,7 +117,6 @@ public class VariableController {
     return RestResponse.success();
   }
 
-  @Operation(summary = "Check variable code")
   @PostMapping("check/code")
   public RestResponse checkVariableCode(
       @RequestParam Long teamId, @NotBlank(message = "{required}") String variableCode) {
diff --git a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/controller/YarnQueueController.java b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/controller/YarnQueueController.java
index 853b504fe..317c4ecd1 100644
--- a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/controller/YarnQueueController.java
+++ b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/controller/YarnQueueController.java
@@ -19,15 +19,12 @@ package org.apache.streampark.console.core.controller;
 
 import org.apache.streampark.console.base.domain.RestRequest;
 import org.apache.streampark.console.base.domain.RestResponse;
-import org.apache.streampark.console.core.annotation.ApiAccess;
 import org.apache.streampark.console.core.entity.YarnQueue;
 import org.apache.streampark.console.core.service.YarnQueueService;
 
 import org.apache.shiro.authz.annotation.RequiresPermissions;
 
 import com.baomidou.mybatisplus.core.metadata.IPage;
-import io.swagger.v3.oas.annotations.Operation;
-import io.swagger.v3.oas.annotations.tags.Tag;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.validation.annotation.Validated;
@@ -35,7 +32,6 @@ import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
 
-@Tag(name = "YARN_QUEUE_TAG")
 @Slf4j
 @Validated
 @RestController
@@ -51,31 +47,23 @@ public class YarnQueueController {
    * @param yarnQueue optional fields used to search.
    * @return RestResponse with IPage<{@link YarnQueue}> object.
    */
-  @Operation(summary = "List yarn queues")
-  @ApiAccess
   @PostMapping("list")
   public RestResponse list(RestRequest restRequest, YarnQueue yarnQueue) {
     IPage<YarnQueue> queuePage = yarnQueueService.getPage(yarnQueue, restRequest);
     return RestResponse.success(queuePage);
   }
 
-  @Operation(summary = "Check yarn queue valid")
-  @ApiAccess
   @PostMapping("check")
   public RestResponse check(YarnQueue yarnQueue) {
     return RestResponse.success(yarnQueueService.checkYarnQueue(yarnQueue));
   }
 
-  @Operation(summary = "Create yarn queue")
-  @ApiAccess
   @PostMapping("create")
   @RequiresPermissions("yarnQueue:create")
   public RestResponse create(YarnQueue yarnQueue) {
     return RestResponse.success(yarnQueueService.createYarnQueue(yarnQueue));
   }
 
-  @Operation(summary = "Update yarn queue")
-  @ApiAccess
   @PostMapping("update")
   @RequiresPermissions("yarnQueue:update")
   public RestResponse update(YarnQueue yarnQueue) {
@@ -83,10 +71,6 @@ public class YarnQueueController {
     return RestResponse.success();
   }
 
-  @Operation(
-      summary = "Delete yarn queue",
-      description = "delete by (team id & yarn queue) or yarn queue id")
-  @ApiAccess
   @PostMapping("delete")
   @RequiresPermissions("yarnQueue:delete")
   public RestResponse delete(YarnQueue yarnQueue) {
diff --git a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/entity/Application.java b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/entity/Application.java
index 255fa1afa..93dacc945 100644
--- a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/entity/Application.java
+++ b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/entity/Application.java
@@ -80,9 +80,6 @@ public class Application implements Serializable {
   /** The name of the frontend and program displayed in yarn */
   private String jobName;
 
-  @TableField(updateStrategy = FieldStrategy.IGNORED)
-  private String appId;
-
   @TableField(updateStrategy = FieldStrategy.IGNORED)
   private String jobId;
 
@@ -93,7 +90,7 @@ public class Application implements Serializable {
   /** flink version */
   private Long versionId;
 
-  /** k8s cluster id */
+  /** 1. yarn application id(on yarn) 2. k8s application id (on k8s application) */
   private String clusterId;
 
   /** flink docker base image */
@@ -256,6 +253,7 @@ public class Application implements Serializable {
   private transient String createTimeTo;
   private transient String backUpDescription;
   private transient String yarnQueue;
+  private transient String serviceAccount;
 
   /** Flink Web UI Url */
   private transient String flinkRestUrl;
@@ -549,10 +547,10 @@ public class Application implements Serializable {
   @SneakyThrows
   @SuppressWarnings("unchecked")
   public Map<String, Object> getHotParamsMap() {
-    if (StringUtils.isNotBlank(this.hotParams)) {
-      Map<String, Object> hotParamsMap = JacksonUtils.read(this.hotParams, Map.class);
-      hotParamsMap.entrySet().removeIf(entry -> entry.getValue() == null);
-      return hotParamsMap;
+    if (this.hotParams != null) {
+      Map<String, Object> map = JacksonUtils.read(this.hotParams, Map.class);
+      map.entrySet().removeIf(entry -> entry.getValue() == null);
+      return map;
     }
     return Collections.EMPTY_MAP;
   }
@@ -572,7 +570,12 @@ public class Application implements Serializable {
     if (needFillYarnQueueLabel(executionModeEnum)) {
       hotParams.putAll(YarnQueueLabelExpression.getQueueLabelMap(appParam.getYarnQueue()));
     }
-    if (MapUtils.isNotEmpty(hotParams)) {
+    if (executionModeEnum == FlinkExecutionMode.KUBERNETES_NATIVE_APPLICATION) {
+      if (StringUtils.isNotBlank(appParam.getServiceAccount())) {
+        hotParams.put(ConfigKeys.KEY_KERBEROS_SERVICE_ACCOUNT(), appParam.getServiceAccount());
+      }
+    }
+    if (!hotParams.isEmpty()) {
       this.setHotParams(JacksonUtils.write(hotParams));
     }
   }
diff --git a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/enums/PermissionTypeEnum.java b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/enums/AuthenticationType.java
similarity index 85%
rename from streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/enums/PermissionTypeEnum.java
rename to streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/enums/AuthenticationType.java
index 989fd5baa..d1a90c17a 100644
--- a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/enums/PermissionTypeEnum.java
+++ b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/enums/AuthenticationType.java
@@ -19,22 +19,22 @@ package org.apache.streampark.console.core.enums;
 
 import java.util.Arrays;
 
-public enum PermissionTypeEnum {
-  USER(1),
-  TEAM(2),
-  APP(3);
+public enum AuthenticationType {
+  SIGN(1),
 
-  private final int value;
+  OPENAPI(2);
 
-  public int get() {
-    return this.value;
-  }
+  private final Integer value;
 
-  PermissionTypeEnum(int value) {
+  AuthenticationType(int value) {
     this.value = value;
   }
 
-  public static PermissionTypeEnum of(Integer value) {
+  public int get() {
+    return this.value;
+  }
+
+  public static AuthenticationType of(Integer value) {
     return Arrays.stream(values()).filter((x) -> x.value == value).findFirst().orElse(null);
   }
 }
diff --git a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/service/impl/CommonServiceImpl.java b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/service/ServiceHelper.java
similarity index 63%
rename from streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/service/impl/CommonServiceImpl.java
rename to streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/service/ServiceHelper.java
index b4e6e50cf..f30ae1797 100644
--- a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/service/impl/CommonServiceImpl.java
+++ b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/service/ServiceHelper.java
@@ -15,62 +15,75 @@
  * limitations under the License.
  */
 
-package org.apache.streampark.console.core.service.impl;
+package org.apache.streampark.console.core.service;
 
 import org.apache.streampark.console.base.exception.ApiAlertException;
+import org.apache.streampark.console.base.exception.ApiDetailException;
 import org.apache.streampark.console.base.util.WebUtils;
 import org.apache.streampark.console.core.entity.FlinkEnv;
 import org.apache.streampark.console.core.entity.SparkEnv;
-import org.apache.streampark.console.core.service.CommonService;
 import org.apache.streampark.console.system.authentication.JWTUtil;
 import org.apache.streampark.console.system.entity.User;
 import org.apache.streampark.console.system.service.UserService;
+import org.apache.streampark.flink.kubernetes.ingress.IngressController;
 
 import org.apache.shiro.SecurityUtils;
+import org.apache.shiro.authc.AuthenticationException;
 
+import com.baomidou.mybatisplus.core.toolkit.StringUtils;
+import io.fabric8.kubernetes.client.KubernetesClientException;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
 import java.io.File;
+import java.nio.file.Files;
+import java.nio.file.Paths;
 import java.util.Arrays;
 import java.util.List;
 import java.util.Objects;
-import java.util.Optional;
 import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
 @Service
-public class CommonServiceImpl implements CommonService {
+public class ServiceHelper {
 
-  private String sqlClientJar = null;
-
-  private String sparkSqlClientJar = null;
+  @Autowired private SettingService settingService;
 
   @Autowired private UserService userService;
 
-  @Override
-  public User getCurrentUser() {
+  private String flinkSqlClientJar = null;
+
+  private String sparkSqlClientJar = null;
+
+  public User getLoginUser() {
     String token = (String) SecurityUtils.getSubject().getPrincipal();
     Long userId = JWTUtil.getUserId(token);
+    if (userId == null) {
+      throw new AuthenticationException("Unauthorized");
+    }
     return userService.getById(userId);
   }
 
-  @Override
   public Long getUserId() {
-    return Optional.ofNullable(getCurrentUser()).map(User::getUserId).orElse(null);
+    User user = getLoginUser();
+    if (user != null) {
+      return user.getUserId();
+    }
+    return null;
   }
 
-  @Override
-  public String getSqlClientJar(FlinkEnv flinkEnv) {
-    if (sqlClientJar == null) {
+  public String getFlinkSqlClientJar(FlinkEnv flinkEnv) {
+    if (flinkSqlClientJar == null) {
       File localClient = WebUtils.getAppClientDir();
       ApiAlertException.throwIfFalse(
           localClient.exists(), "[StreamPark] " + localClient + " no exists. please check.");
+
+      String regex =
+          String.format("streampark-flink-sqlclient_%s-.*\\.jar", flinkEnv.getScalaVersion());
+
       List<String> jars =
           Arrays.stream(Objects.requireNonNull(localClient.list()))
-              .filter(
-                  x ->
-                      x.matches(
-                          "streampark-flink-sqlclient_" + flinkEnv.getScalaVersion() + "-.*\\.jar"))
+              .filter(x -> x.matches(regex))
               .collect(Collectors.toList());
 
       ApiAlertException.throwIfTrue(
@@ -80,14 +93,12 @@ public class CommonServiceImpl implements CommonService {
       ApiAlertException.throwIfTrue(
           jars.size() > 1,
           "[StreamPark] found multiple streampark-flink-sqlclient jar in " + localClient);
-
-      sqlClientJar = jars.get(0);
+      flinkSqlClientJar = jars.get(0);
     }
-    return sqlClientJar;
+    return flinkSqlClientJar;
   }
 
-  @Override
-  public String getSqlClientJar(SparkEnv sparkEnv) {
+  public String getSparkSqlClientJar(SparkEnv sparkEnv) {
     if (sparkSqlClientJar == null) {
       File localClient = WebUtils.getAppClientDir();
       ApiAlertException.throwIfFalse(
@@ -112,4 +123,26 @@ public class CommonServiceImpl implements CommonService {
     }
     return sparkSqlClientJar;
   }
+
+  public String rollViewLog(String path, int offset, int limit) {
+    try {
+      File file = new File(path);
+      if (file.exists() && file.isFile()) {
+        try (Stream<String> stream = Files.lines(Paths.get(path))) {
+          return stream.skip(offset).limit(limit).collect(Collectors.joining("\r\n"));
+        }
+      }
+      return null;
+    } catch (Exception e) {
+      throw new ApiDetailException("roll view log error: " + e);
+    }
+  }
+
+  public void configureIngress(String clusterId, String namespace)
+      throws KubernetesClientException {
+    String domainName = settingService.getIngressModeDefault();
+    if (StringUtils.isNotBlank(domainName)) {
+      IngressController.configureIngress(domainName, clusterId, namespace);
+    }
+  }
 }
diff --git a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/service/alert/impl/DingTalkAlertNotifyServiceImpl.java b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/service/alert/impl/DingTalkAlertNotifyServiceImpl.java
index 38b24dded..a1282ac7c 100644
--- a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/service/alert/impl/DingTalkAlertNotifyServiceImpl.java
+++ b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/service/alert/impl/DingTalkAlertNotifyServiceImpl.java
@@ -26,6 +26,7 @@ import org.apache.streampark.console.core.bean.RobotResponse;
 import org.apache.streampark.console.core.service.alert.AlertNotifyService;
 
 import org.apache.commons.lang3.BooleanUtils;
+import org.apache.commons.net.util.Base64;
 
 import freemarker.template.Template;
 import lombok.extern.slf4j.Slf4j;
@@ -37,14 +38,13 @@ import org.springframework.stereotype.Service;
 import org.springframework.util.StringUtils;
 import org.springframework.web.client.RestTemplate;
 
-import javax.annotation.Nonnull;
+import javax.annotation.PostConstruct;
 import javax.crypto.Mac;
 import javax.crypto.spec.SecretKeySpec;
 
 import java.net.URLEncoder;
 import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
-import java.util.Base64;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
@@ -55,7 +55,7 @@ import java.util.StringJoiner;
 @Service
 @Lazy
 public class DingTalkAlertNotifyServiceImpl implements AlertNotifyService {
-  private final Template template = FreemarkerUtils.loadTemplateFile("alert-dingTalk.ftl");
+  private Template template;
 
   private final RestTemplate alertRestTemplate;
 
@@ -63,6 +63,12 @@ public class DingTalkAlertNotifyServiceImpl implements AlertNotifyService {
     this.alertRestTemplate = alertRestTemplate;
   }
 
+  @PostConstruct
+  public void loadTemplateFile() throws Exception {
+    String template = "alert-dingTalk.ftl";
+    this.template = FreemarkerUtils.loadTemplateFile(template);
+  }
+
   @Override
   public boolean doAlert(AlertConfigParams alertConfig, AlertTemplate alertTemplate)
       throws AlertException {
@@ -74,59 +80,37 @@ public class DingTalkAlertNotifyServiceImpl implements AlertNotifyService {
       if (StringUtils.hasLength(contacts)) {
         Collections.addAll(contactList, contacts.split(","));
       }
-      String title = renderTitle(alertTemplate, contactList);
-      Map<String, Object> contactMap = renderContact(contactList, dingTalkParams);
+      String title = alertTemplate.getTitle();
+      if (!contactList.isEmpty()) {
+        StringJoiner joiner = new StringJoiner(",@", title + " @", "");
+        contactList.forEach(joiner::add);
+        title = joiner.toString();
+      }
+      Map<String, Object> contactMap = new HashMap<>();
+      contactMap.put("atMobiles", contactList);
+      contactMap.put("isAtAll", BooleanUtils.toBoolean(dingTalkParams.getIsAtAll()));
+
       // format markdown
       String markdown = FreemarkerUtils.format(template, alertTemplate);
-      Map<String, String> contentMap = renderContent(title, markdown);
-      Map<String, Object> bodyMap = renderBody(contentMap, contactMap);
 
-      sendMessage(dingTalkParams, bodyMap);
+      Map<String, String> content = new HashMap<>();
+      content.put("title", title);
+      content.put("text", markdown);
+
+      Map<String, Object> body = new HashMap<>();
+      body.put("msgtype", "markdown");
+      body.put("markdown", content);
+      body.put("at", contactMap);
+
+      sendMessage(dingTalkParams, body);
       return true;
     } catch (AlertException alertException) {
       throw alertException;
     } catch (Exception e) {
-      throw new AlertException("Failed send DingTalk alert", e);
+      throw new AlertException("Failed send dingTalk alert", e);
     }
   }
 
-  @Nonnull
-  private Map<String, Object> renderBody(
-      Map<String, String> content, Map<String, Object> contactMap) {
-    Map<String, Object> body = new HashMap<>();
-    body.put("msgtype", "markdown");
-    body.put("markdown", content);
-    body.put("at", contactMap);
-    return body;
-  }
-
-  @Nonnull
-  private Map<String, String> renderContent(String title, String markdown) {
-    Map<String, String> content = new HashMap<>();
-    content.put("title", title);
-    content.put("text", markdown);
-    return content;
-  }
-
-  @Nonnull
-  private Map<String, Object> renderContact(
-      List<String> contactList, AlertDingTalkParams dingTalkParams) {
-    Map<String, Object> contactMap = new HashMap<>();
-    contactMap.put("atMobiles", contactList);
-    contactMap.put("isAtAll", BooleanUtils.toBoolean(dingTalkParams.getIsAtAll()));
-    return contactMap;
-  }
-
-  private String renderTitle(AlertTemplate alertTemplate, List<String> contactList) {
-    String title = alertTemplate.getTitle();
-    if (!contactList.isEmpty()) {
-      StringJoiner joiner = new StringJoiner(",@", title + " @", "");
-      contactList.forEach(joiner::add);
-      title = joiner.toString();
-    }
-    return title;
-  }
-
   private void sendMessage(AlertDingTalkParams params, Map<String, Object> body)
       throws AlertException {
     // get webhook url
@@ -141,16 +125,16 @@ public class DingTalkAlertNotifyServiceImpl implements AlertNotifyService {
     } catch (Exception e) {
       log.error("Failed to request DingTalk robot alarm,\nurl:{}", url, e);
       throw new AlertException(
-          String.format("Failed to request DingTalk robot alert,%nurl:%s", url), e);
+          String.format("Failed to request DingTalk robot alert,\nurl:%s", url), e);
     }
     if (robotResponse == null) {
       throw new AlertException(
-          String.format("Failed to request DingTalk robot alert,%nurl:%s", url));
+          String.format("Failed to request DingTalk robot alert,\nurl:%s", url));
     }
     if (robotResponse.getErrcode() != 0) {
       throw new AlertException(
           String.format(
-              "Failed to request DingTalk robot alert,%nurl:%s,%nerrorCode:%d,%nerrorMsg:%s",
+              "Failed to request DingTalk robot alert,\nurl:%s,\nerrorCode:%d,\nerrorMsg:%s",
               url, robotResponse.getErrcode(), robotResponse.getErrmsg()));
     }
   }
@@ -162,23 +146,19 @@ public class DingTalkAlertNotifyServiceImpl implements AlertNotifyService {
    * @return the webhook
    */
   private String getWebhook(AlertDingTalkParams params) {
-    String urlPef = "https://oapi.dingtalk.com/robot/send";
+    String urlPrefix = "https://oapi.dingtalk.com/robot/send";
     if (StringUtils.hasLength(params.getAlertDingURL())) {
-      urlPef = params.getAlertDingURL();
+      urlPrefix = params.getAlertDingURL().replaceFirst("\\?.*", "");
     }
-    if (!urlPef.endsWith("access_token=")) {
-      urlPef += "?access_token=";
-    }
-
     String url;
     if (params.getSecretEnable()) {
       Long timestamp = System.currentTimeMillis();
       url =
           String.format(
-              "%s%s&timestamp=%d&sign=%s",
-              urlPef, params.getToken(), timestamp, getSign(params.getSecretToken(), timestamp));
+              "%s?access_token=%s&timestamp=%d&sign=%s",
+              urlPrefix, params.getToken(), timestamp, getSign(params.getSecretToken(), timestamp));
     } else {
-      url = String.format("%s%s", urlPef, params.getToken());
+      url = String.format("%s?access_token=%s", urlPrefix, params.getToken());
     }
     if (log.isDebugEnabled()) {
       log.debug("The alarm robot url of DingTalk contains signature is {}", url);
@@ -203,7 +183,7 @@ public class DingTalkAlertNotifyServiceImpl implements AlertNotifyService {
       Mac mac = Mac.getInstance("HmacSHA256");
       mac.init(new SecretKeySpec(secret.getBytes(StandardCharsets.UTF_8), "HmacSHA256"));
       byte[] signData = mac.doFinal(stringToSign.getBytes(StandardCharsets.UTF_8));
-      String sign = URLEncoder.encode(new String(Base64.getEncoder().encode(signData)), "UTF-8");
+      String sign = URLEncoder.encode(new String(Base64.encodeBase64(signData)), "UTF-8");
       if (log.isDebugEnabled()) {
         log.debug("Calculate the signature success, sign:{}", sign);
       }
diff --git a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/service/alert/impl/LarkAlertNotifyServiceImpl.java b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/service/alert/impl/LarkAlertNotifyServiceImpl.java
index 86382c5f0..3dd899aae 100644
--- a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/service/alert/impl/LarkAlertNotifyServiceImpl.java
+++ b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/service/alert/impl/LarkAlertNotifyServiceImpl.java
@@ -134,6 +134,7 @@ public class LarkAlertNotifyServiceImpl implements AlertNotifyService {
    * @return the webhook
    */
   private String getWebhook(AlertLarkParams params) {
+    larkProxyUrl = larkProxyUrl.replaceFirst("/open-apis/bot/v2/hook/(.*)", "");
     String url = String.format(larkProxyUrl + "/open-apis/bot/v2/hook/%s", params.getToken());
     if (log.isDebugEnabled()) {
       log.debug("The alarm robot url of Lark is {}", url);
diff --git a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/service/application/impl/ApplicationActionServiceImpl.java b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/service/application/impl/ApplicationActionServiceImpl.java
index 60047f481..3fddda4c9 100644
--- a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/service/application/impl/ApplicationActionServiceImpl.java
+++ b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/service/application/impl/ApplicationActionServiceImpl.java
@@ -34,6 +34,7 @@ import org.apache.streampark.common.util.HadoopUtils;
 import org.apache.streampark.common.util.PropertiesUtils;
 import org.apache.streampark.console.base.exception.ApiAlertException;
 import org.apache.streampark.console.base.exception.ApplicationException;
+import org.apache.streampark.console.base.util.Tuple2;
 import org.apache.streampark.console.core.entity.AppBuildPipeline;
 import org.apache.streampark.console.core.entity.Application;
 import org.apache.streampark.console.core.entity.ApplicationConfig;
@@ -54,12 +55,12 @@ import org.apache.streampark.console.core.service.AppBuildPipeService;
 import org.apache.streampark.console.core.service.ApplicationBackUpService;
 import org.apache.streampark.console.core.service.ApplicationConfigService;
 import org.apache.streampark.console.core.service.ApplicationLogService;
-import org.apache.streampark.console.core.service.CommonService;
 import org.apache.streampark.console.core.service.FlinkClusterService;
 import org.apache.streampark.console.core.service.FlinkEnvService;
 import org.apache.streampark.console.core.service.FlinkSqlService;
 import org.apache.streampark.console.core.service.ResourceService;
 import org.apache.streampark.console.core.service.SavePointService;
+import org.apache.streampark.console.core.service.ServiceHelper;
 import org.apache.streampark.console.core.service.SettingService;
 import org.apache.streampark.console.core.service.VariableService;
 import org.apache.streampark.console.core.service.application.ApplicationActionService;
@@ -83,7 +84,6 @@ import org.apache.streampark.flink.packer.pipeline.ShadedBuildResponse;
 
 import org.apache.commons.lang3.StringUtils;
 import org.apache.flink.api.common.JobID;
-import org.apache.flink.api.java.tuple.Tuple2;
 import org.apache.flink.configuration.CoreOptions;
 import org.apache.flink.configuration.JobManagerOptions;
 import org.apache.flink.configuration.MemorySize;
@@ -151,7 +151,7 @@ public class ApplicationActionServiceImpl extends ServiceImpl<ApplicationMapper,
 
   @Autowired private SettingService settingService;
 
-  @Autowired private CommonService commonService;
+  @Autowired private ServiceHelper serviceHelper;
 
   @Autowired private FlinkK8sWatcher k8SFlinkTrackMonitor;
 
@@ -241,7 +241,7 @@ public class ApplicationActionServiceImpl extends ServiceImpl<ApplicationMapper,
     applicationLog.setJobManagerUrl(application.getJobManagerUrl());
     applicationLog.setOptionTime(new Date());
     applicationLog.setYarnAppId(application.getClusterId());
-    applicationLog.setUserId(commonService.getUserId());
+    applicationLog.setUserId(serviceHelper.getUserId());
 
     if (appParam.getSavePointed()) {
       FlinkAppHttpWatcher.addSavepoint(application.getId());
@@ -253,7 +253,7 @@ public class ApplicationActionServiceImpl extends ServiceImpl<ApplicationMapper,
     application.setOptionTime(new Date());
     this.baseMapper.updateById(application);
 
-    Long userId = commonService.getUserId();
+    Long userId = serviceHelper.getUserId();
     if (!application.getUserId().equals(userId)) {
       FlinkAppHttpWatcher.addCanceledApp(application.getId(), userId);
     }
@@ -269,23 +269,6 @@ public class ApplicationActionServiceImpl extends ServiceImpl<ApplicationMapper,
       }
     }
 
-    String clusterId = null;
-    if (FlinkExecutionMode.isKubernetesMode(application.getExecutionMode())) {
-      clusterId = application.getClusterId();
-    } else if (FlinkExecutionMode.isYarnMode(application.getExecutionMode())) {
-      if (FlinkExecutionMode.YARN_SESSION == application.getFlinkExecutionMode()) {
-        FlinkCluster cluster = flinkClusterService.getById(application.getFlinkClusterId());
-        ApiAlertException.throwIfNull(
-            cluster,
-            String.format(
-                "The yarn session clusterId=%s can't found, maybe the clusterId is wrong or the cluster has been deleted. Please contact the Admin.",
-                application.getFlinkClusterId()));
-        clusterId = cluster.getClusterId();
-      } else {
-        clusterId = application.getAppId();
-      }
-    }
-
     Map<String, Object> properties = new HashMap<>();
 
     if (FlinkExecutionMode.isRemoteMode(application.getFlinkExecutionMode())) {
@@ -301,6 +284,10 @@ public class ApplicationActionServiceImpl extends ServiceImpl<ApplicationMapper,
       properties.put(RestOptions.PORT.key(), activeAddress.getPort());
     }
 
+    Tuple2<String, String> clusterIdNamespace = getNamespaceClusterId(application);
+    String namespace = clusterIdNamespace.t1;
+    String clusterId = clusterIdNamespace.t2;
+
     CancelRequest cancelRequest =
         new CancelRequest(
             application.getId(),
@@ -313,7 +300,7 @@ public class ApplicationActionServiceImpl extends ServiceImpl<ApplicationMapper,
             appParam.getDrain(),
             customSavepoint,
             appParam.getNativeFormat(),
-            application.getK8sNamespace());
+            namespace);
 
     final Date triggerTime = new Date();
     CompletableFuture<CancelResponse> cancelFuture =
@@ -439,8 +426,8 @@ public class ApplicationActionServiceImpl extends ServiceImpl<ApplicationMapper,
             flinkK8sDataTypeConverter.genDefaultFlinkDeploymentIngressDef());
 
     Tuple2<String, String> userJarAndAppConf = getUserJarAndAppConf(flinkEnv, application);
-    String flinkUserJar = userJarAndAppConf.f0;
-    String appConf = userJarAndAppConf.f1;
+    String flinkUserJar = userJarAndAppConf.t1;
+    String appConf = userJarAndAppConf.t2;
 
     BuildResult buildResult = buildPipeline.getBuildResult();
     if (FlinkExecutionMode.YARN_APPLICATION == application.getFlinkExecutionMode()) {
@@ -498,7 +485,7 @@ public class ApplicationActionServiceImpl extends ServiceImpl<ApplicationMapper,
     applicationLog.setOptionName(OperationEnum.START.getValue());
     applicationLog.setAppId(application.getId());
     applicationLog.setOptionTime(new Date());
-    applicationLog.setUserId(commonService.getUserId());
+    applicationLog.setUserId(serviceHelper.getUserId());
     return applicationLog;
   }
 
@@ -518,11 +505,15 @@ public class ApplicationActionServiceImpl extends ServiceImpl<ApplicationMapper,
         application.setTmMemory(MemorySize.parse(tmMemory).getMebiBytes());
       }
     }
-    application.setAppId(response.clusterId());
     if (StringUtils.isNoneEmpty(response.jobId())) {
       application.setJobId(response.jobId());
     }
 
+    if (FlinkExecutionMode.isYarnMode(application.getExecutionMode())) {
+      application.setClusterId(response.clusterId());
+      applicationLog.setYarnAppId(response.clusterId());
+    }
+
     if (StringUtils.isNoneEmpty(response.jobManagerUrl())) {
       application.setJobManagerUrl(response.jobManagerUrl());
       applicationLog.setJobManagerUrl(response.jobManagerUrl());
@@ -637,7 +628,7 @@ public class ApplicationActionServiceImpl extends ServiceImpl<ApplicationMapper,
         FlinkSql flinkSql = flinkSqlService.getEffective(application.getId(), false);
         AssertUtils.notNull(flinkSql);
         // 1) dist_userJar
-        String sqlDistJar = commonService.getSqlClientJar(flinkEnv);
+        String sqlDistJar = serviceHelper.getFlinkSqlClientJar(flinkEnv);
         // 2) appConfig
         appConf =
             applicationConfig == null
@@ -848,4 +839,34 @@ public class ApplicationActionServiceImpl extends ServiceImpl<ApplicationMapper,
         flinkClusterWatcher.getClusterState(flinkCluster) == ClusterState.RUNNING,
         "[StreamPark] The flink cluster not running, please start it");
   }
+
+  private Tuple2<String, String> getNamespaceClusterId(Application application) {
+    String clusterId = null;
+    String k8sNamespace = null;
+    FlinkCluster cluster;
+    switch (application.getFlinkExecutionMode()) {
+      case YARN_APPLICATION:
+      case YARN_PER_JOB:
+      case YARN_SESSION:
+        clusterId = application.getClusterId();
+        break;
+      case KUBERNETES_NATIVE_APPLICATION:
+        clusterId = application.getJobName();
+        k8sNamespace = application.getK8sNamespace();
+        break;
+      case KUBERNETES_NATIVE_SESSION:
+        cluster = flinkClusterService.getById(application.getFlinkClusterId());
+        ApiAlertException.throwIfNull(
+            cluster,
+            String.format(
+                "The Kubernetes session clusterId=%s can't found, maybe the clusterId is wrong or the cluster has been deleted. Please contact the Admin.",
+                application.getFlinkClusterId()));
+        clusterId = cluster.getClusterId();
+        k8sNamespace = cluster.getK8sNamespace();
+        break;
+      default:
+        break;
+    }
+    return Tuple2.of(k8sNamespace, clusterId);
+  }
 }
diff --git a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/service/application/impl/ApplicationManageServiceImpl.java b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/service/application/impl/ApplicationManageServiceImpl.java
index 0fce782c3..2d7e4cf04 100644
--- a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/service/application/impl/ApplicationManageServiceImpl.java
+++ b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/service/application/impl/ApplicationManageServiceImpl.java
@@ -45,13 +45,13 @@ import org.apache.streampark.console.core.service.AppBuildPipeService;
 import org.apache.streampark.console.core.service.ApplicationBackUpService;
 import org.apache.streampark.console.core.service.ApplicationConfigService;
 import org.apache.streampark.console.core.service.ApplicationLogService;
-import org.apache.streampark.console.core.service.CommonService;
 import org.apache.streampark.console.core.service.EffectiveService;
 import org.apache.streampark.console.core.service.FlinkClusterService;
 import org.apache.streampark.console.core.service.FlinkSqlService;
 import org.apache.streampark.console.core.service.ProjectService;
 import org.apache.streampark.console.core.service.ResourceService;
 import org.apache.streampark.console.core.service.SavePointService;
+import org.apache.streampark.console.core.service.ServiceHelper;
 import org.apache.streampark.console.core.service.SettingService;
 import org.apache.streampark.console.core.service.YarnQueueService;
 import org.apache.streampark.console.core.service.application.ApplicationManageService;
@@ -121,7 +121,7 @@ public class ApplicationManageServiceImpl extends ServiceImpl<ApplicationMapper,
 
   @Autowired private SettingService settingService;
 
-  @Autowired private CommonService commonService;
+  @Autowired private ServiceHelper serviceHelper;
 
   @Autowired private FlinkK8sWatcher k8SFlinkTrackMonitor;
 
@@ -321,7 +321,7 @@ public class ApplicationManageServiceImpl extends ServiceImpl<ApplicationMapper,
   public boolean create(Application appParam) {
     ApiAlertException.throwIfNull(
         appParam.getTeamId(), "The teamId can't be null. Create application failed.");
-    appParam.setUserId(commonService.getUserId());
+    appParam.setUserId(serviceHelper.getUserId());
     appParam.setState(FlinkAppStateEnum.ADDED.getValue());
     appParam.setRelease(ReleaseStateEnum.NEED_RELEASE.get());
     appParam.setOptionState(OptionStateEnum.NONE.getValue());
@@ -395,63 +395,64 @@ public class ApplicationManageServiceImpl extends ServiceImpl<ApplicationMapper,
         !existsByJobName,
         "[StreamPark] Application names can't be repeated, copy application failed.");
 
-    Application oldApp = getById(appParam.getId());
+    Application persist = getById(appParam.getId());
     Application newApp = new Application();
     String jobName = appParam.getJobName();
 
     newApp.setJobName(jobName);
     newApp.setClusterId(
-        FlinkExecutionMode.isSessionMode(oldApp.getFlinkExecutionMode())
-            ? oldApp.getClusterId()
-            : jobName);
-    newApp.setArgs(appParam.getArgs() != null ? appParam.getArgs() : oldApp.getArgs());
-    newApp.setVersionId(oldApp.getVersionId());
-
-    newApp.setFlinkClusterId(oldApp.getFlinkClusterId());
-    newApp.setRestartSize(oldApp.getRestartSize());
-    newApp.setJobType(oldApp.getJobType());
-    newApp.setOptions(oldApp.getOptions());
-    newApp.setDynamicProperties(oldApp.getDynamicProperties());
-    newApp.setResolveOrder(oldApp.getResolveOrder());
-    newApp.setExecutionMode(oldApp.getExecutionMode());
-    newApp.setFlinkImage(oldApp.getFlinkImage());
-    newApp.setK8sNamespace(oldApp.getK8sNamespace());
-    newApp.setK8sRestExposedType(oldApp.getK8sRestExposedType());
-    newApp.setK8sPodTemplate(oldApp.getK8sPodTemplate());
-    newApp.setK8sJmPodTemplate(oldApp.getK8sJmPodTemplate());
-    newApp.setK8sTmPodTemplate(oldApp.getK8sTmPodTemplate());
-    newApp.setK8sHadoopIntegration(oldApp.getK8sHadoopIntegration());
-    newApp.setDescription(oldApp.getDescription());
-    newApp.setAlertId(oldApp.getAlertId());
-    newApp.setCpFailureAction(oldApp.getCpFailureAction());
-    newApp.setCpFailureRateInterval(oldApp.getCpFailureRateInterval());
-    newApp.setCpMaxFailureInterval(oldApp.getCpMaxFailureInterval());
-    newApp.setMainClass(oldApp.getMainClass());
-    newApp.setAppType(oldApp.getAppType());
-    newApp.setResourceFrom(oldApp.getResourceFrom());
-    newApp.setProjectId(oldApp.getProjectId());
-    newApp.setModule(oldApp.getModule());
-    newApp.setUserId(commonService.getUserId());
+        FlinkExecutionMode.isSessionMode(persist.getFlinkExecutionMode())
+            ? persist.getClusterId()
+            : null);
+    newApp.setArgs(appParam.getArgs() != null ? appParam.getArgs() : persist.getArgs());
+    newApp.setVersionId(persist.getVersionId());
+
+    newApp.setFlinkClusterId(persist.getFlinkClusterId());
+    newApp.setRestartSize(persist.getRestartSize());
+    newApp.setJobType(persist.getJobType());
+    newApp.setOptions(persist.getOptions());
+    newApp.setDynamicProperties(persist.getDynamicProperties());
+    newApp.setResolveOrder(persist.getResolveOrder());
+    newApp.setExecutionMode(persist.getExecutionMode());
+    newApp.setFlinkImage(persist.getFlinkImage());
+    newApp.setK8sNamespace(persist.getK8sNamespace());
+    newApp.setK8sRestExposedType(persist.getK8sRestExposedType());
+    newApp.setK8sPodTemplate(persist.getK8sPodTemplate());
+    newApp.setK8sJmPodTemplate(persist.getK8sJmPodTemplate());
+    newApp.setK8sTmPodTemplate(persist.getK8sTmPodTemplate());
+    newApp.setK8sHadoopIntegration(persist.getK8sHadoopIntegration());
+    newApp.setDescription(persist.getDescription());
+    newApp.setAlertId(persist.getAlertId());
+    newApp.setCpFailureAction(persist.getCpFailureAction());
+    newApp.setCpFailureRateInterval(persist.getCpFailureRateInterval());
+    newApp.setCpMaxFailureInterval(persist.getCpMaxFailureInterval());
+    newApp.setMainClass(persist.getMainClass());
+    newApp.setAppType(persist.getAppType());
+    newApp.setResourceFrom(persist.getResourceFrom());
+    newApp.setProjectId(persist.getProjectId());
+    newApp.setModule(persist.getModule());
+    newApp.setUserId(serviceHelper.getUserId());
     newApp.setState(FlinkAppStateEnum.ADDED.getValue());
     newApp.setRelease(ReleaseStateEnum.NEED_RELEASE.get());
     newApp.setOptionState(OptionStateEnum.NONE.getValue());
+    newApp.setHotParams(persist.getHotParams());
+
+    // createTime & modifyTime
     Date date = new Date();
     newApp.setCreateTime(date);
     newApp.setModifyTime(date);
-    newApp.setHotParams(oldApp.getHotParams());
 
-    newApp.setJar(oldApp.getJar());
-    newApp.setJarCheckSum(oldApp.getJarCheckSum());
-    newApp.setTags(oldApp.getTags());
-    newApp.setTeamId(oldApp.getTeamId());
-    newApp.setHadoopUser(oldApp.getHadoopUser());
+    newApp.setJar(persist.getJar());
+    newApp.setJarCheckSum(persist.getJarCheckSum());
+    newApp.setTags(persist.getTags());
+    newApp.setTeamId(persist.getTeamId());
+    newApp.setDependency(persist.getDependency());
 
     boolean saved = save(newApp);
     if (saved) {
       if (newApp.isFlinkSqlJob()) {
         FlinkSql copyFlinkSql = flinkSqlService.getLatestFlinkSql(appParam.getId(), true);
         newApp.setFlinkSql(copyFlinkSql.getSql());
-        newApp.setTeamResource(copyFlinkSql.getTeamResource());
         newApp.setDependency(copyFlinkSql.getDependency());
         FlinkSql flinkSql = new FlinkSql(newApp);
         flinkSqlService.create(flinkSql);
@@ -470,7 +471,7 @@ public class ApplicationManageServiceImpl extends ServiceImpl<ApplicationMapper,
       return newApp.getId();
     } else {
       throw new ApiAlertException(
-          "create application from copy failed, copy source app: " + oldApp.getJobName());
+          "create application from copy failed, copy source app: " + persist.getJobName());
     }
   }
 
diff --git a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/service/application/impl/SparkApplicationActionServiceImpl.java b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/service/application/impl/SparkApplicationActionServiceImpl.java
index b65375104..62f64c23e 100644
--- a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/service/application/impl/SparkApplicationActionServiceImpl.java
+++ b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/service/application/impl/SparkApplicationActionServiceImpl.java
@@ -52,10 +52,10 @@ import org.apache.streampark.console.core.mapper.SparkApplicationMapper;
 import org.apache.streampark.console.core.service.AppBuildPipeService;
 import org.apache.streampark.console.core.service.ApplicationConfigService;
 import org.apache.streampark.console.core.service.ApplicationLogService;
-import org.apache.streampark.console.core.service.CommonService;
 import org.apache.streampark.console.core.service.FlinkClusterService;
 import org.apache.streampark.console.core.service.FlinkSqlService;
 import org.apache.streampark.console.core.service.ResourceService;
+import org.apache.streampark.console.core.service.ServiceHelper;
 import org.apache.streampark.console.core.service.SparkEnvService;
 import org.apache.streampark.console.core.service.VariableService;
 import org.apache.streampark.console.core.service.application.SparkApplicationActionService;
@@ -124,7 +124,7 @@ public class SparkApplicationActionServiceImpl
 
   @Autowired private FlinkSqlService flinkSqlService;
 
-  @Autowired private CommonService commonService;
+  @Autowired private ServiceHelper serviceHelper;
 
   @Autowired private AppBuildPipeService appBuildPipeService;
 
@@ -202,7 +202,7 @@ public class SparkApplicationActionServiceImpl
     applicationLog.setJobManagerUrl(application.getJobManagerUrl());
     applicationLog.setOptionTime(new Date());
     applicationLog.setYarnAppId(application.getClusterId());
-    applicationLog.setUserId(commonService.getUserId());
+    applicationLog.setUserId(serviceHelper.getUserId());
 
     if (appParam.getSavePointed()) {
       FlinkAppHttpWatcher.addSavepoint(application.getId());
@@ -214,7 +214,7 @@ public class SparkApplicationActionServiceImpl
     application.setOptionTime(new Date());
     this.baseMapper.updateById(application);
 
-    Long userId = commonService.getUserId();
+    Long userId = serviceHelper.getUserId();
     if (!application.getUserId().equals(userId)) {
       FlinkAppHttpWatcher.addCanceledApp(application.getId(), userId);
     }
@@ -344,7 +344,7 @@ public class SparkApplicationActionServiceImpl
     applicationLog.setOptionName(OperationEnum.START.getValue());
     applicationLog.setAppId(application.getId());
     applicationLog.setOptionTime(new Date());
-    applicationLog.setUserId(commonService.getUserId());
+    applicationLog.setUserId(serviceHelper.getUserId());
 
     // set the latest to Effective, (it will only become the current effective at this time)
     //    applicationManageService.toEffective(application);
@@ -501,7 +501,8 @@ public class SparkApplicationActionServiceImpl
         FlinkSql flinkSql = flinkSqlService.getEffective(application.getId(), false);
         AssertUtils.notNull(flinkSql);
         // 1) dist_userJar
-        String sqlDistJar = commonService.getSqlClientJar(sparkEnv);
+        // todo
+        String sqlDistJar = serviceHelper.getFlinkSqlClientJar(null);
         // 2) appConfig
         appConf =
             applicationConfig == null
diff --git a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/service/application/impl/SparkApplicationManageServiceImpl.java b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/service/application/impl/SparkApplicationManageServiceImpl.java
index c7142aa87..985efb328 100644
--- a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/service/application/impl/SparkApplicationManageServiceImpl.java
+++ b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/service/application/impl/SparkApplicationManageServiceImpl.java
@@ -41,11 +41,11 @@ import org.apache.streampark.console.core.service.AppBuildPipeService;
 import org.apache.streampark.console.core.service.ApplicationBackUpService;
 import org.apache.streampark.console.core.service.ApplicationConfigService;
 import org.apache.streampark.console.core.service.ApplicationLogService;
-import org.apache.streampark.console.core.service.CommonService;
 import org.apache.streampark.console.core.service.EffectiveService;
 import org.apache.streampark.console.core.service.FlinkSqlService;
 import org.apache.streampark.console.core.service.ProjectService;
 import org.apache.streampark.console.core.service.ResourceService;
+import org.apache.streampark.console.core.service.ServiceHelper;
 import org.apache.streampark.console.core.service.SettingService;
 import org.apache.streampark.console.core.service.YarnQueueService;
 import org.apache.streampark.console.core.service.application.SparkApplicationManageService;
@@ -105,7 +105,7 @@ public class SparkApplicationManageServiceImpl
 
   @Autowired private SettingService settingService;
 
-  @Autowired private CommonService commonService;
+  @Autowired private ServiceHelper serviceHelper;
 
   @Autowired private AppBuildPipeService appBuildPipeService;
 
@@ -264,7 +264,7 @@ public class SparkApplicationManageServiceImpl
   public boolean create(SparkApplication appParam) {
     ApiAlertException.throwIfNull(
         appParam.getTeamId(), "The teamId can't be null. Create application failed.");
-    appParam.setUserId(commonService.getUserId());
+    appParam.setUserId(serviceHelper.getUserId());
     appParam.setState(FlinkAppStateEnum.ADDED.getValue());
     appParam.setRelease(ReleaseStateEnum.NEED_RELEASE.get());
     appParam.setOptionState(OptionStateEnum.NONE.getValue());
@@ -353,7 +353,7 @@ public class SparkApplicationManageServiceImpl
     newApp.setResourceFrom(oldApp.getResourceFrom());
     newApp.setProjectId(oldApp.getProjectId());
     newApp.setModule(oldApp.getModule());
-    newApp.setUserId(commonService.getUserId());
+    newApp.setUserId(serviceHelper.getUserId());
     newApp.setState(FlinkAppStateEnum.ADDED.getValue());
     newApp.setRelease(ReleaseStateEnum.NEED_RELEASE.get());
     newApp.setOptionState(OptionStateEnum.NONE.getValue());
diff --git a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/service/impl/AppBuildPipeServiceImpl.java b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/service/impl/AppBuildPipeServiceImpl.java
index 9d4bbe310..cf4d9adf0 100644
--- a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/service/impl/AppBuildPipeServiceImpl.java
+++ b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/service/impl/AppBuildPipeServiceImpl.java
@@ -50,11 +50,11 @@ import org.apache.streampark.console.core.service.AppBuildPipeService;
 import org.apache.streampark.console.core.service.ApplicationBackUpService;
 import org.apache.streampark.console.core.service.ApplicationConfigService;
 import org.apache.streampark.console.core.service.ApplicationLogService;
-import org.apache.streampark.console.core.service.CommonService;
 import org.apache.streampark.console.core.service.FlinkEnvService;
 import org.apache.streampark.console.core.service.FlinkSqlService;
 import org.apache.streampark.console.core.service.MessageService;
 import org.apache.streampark.console.core.service.ResourceService;
+import org.apache.streampark.console.core.service.ServiceHelper;
 import org.apache.streampark.console.core.service.SettingService;
 import org.apache.streampark.console.core.service.application.ApplicationActionService;
 import org.apache.streampark.console.core.service.application.ApplicationInfoService;
@@ -129,7 +129,7 @@ public class AppBuildPipeServiceImpl
 
   @Autowired private ApplicationBackUpService backUpService;
 
-  @Autowired private CommonService commonService;
+  @Autowired private ServiceHelper serviceHelper;
 
   @Autowired private SettingService settingService;
 
@@ -335,7 +335,7 @@ public class AppBuildPipeServiceImpl
             } else {
               Message message =
                   new Message(
-                      commonService.getUserId(),
+                      serviceHelper.getUserId(),
                       app.getId(),
                       app.getJobName().concat(" release failed"),
                       ExceptionUtils.stringifyException(snapshot.error().exception()),
@@ -399,7 +399,7 @@ public class AppBuildPipeServiceImpl
     applicationLog.setOptionName(RELEASE.getValue());
     applicationLog.setAppId(app.getId());
     applicationLog.setOptionTime(new Date());
-    applicationLog.setUserId(commonService.getUserId());
+    applicationLog.setUserId(serviceHelper.getUserId());
     return applicationLog;
   }
 
@@ -580,7 +580,7 @@ public class AppBuildPipeServiceImpl
       case PYFLINK:
         return String.format("%s/%s", app.getAppHome(), app.getJar());
       case FLINK_SQL:
-        String sqlDistJar = commonService.getSqlClientJar(flinkEnv);
+        String sqlDistJar = serviceHelper.getFlinkSqlClientJar(flinkEnv);
         if (app.getFlinkExecutionMode() == FlinkExecutionMode.YARN_APPLICATION) {
           String clientPath = Workspace.remote().APP_CLIENT();
           return String.format("%s/%s", clientPath, sqlDistJar);
diff --git a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/service/impl/ExternalLinkServiceImpl.java b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/service/impl/ExternalLinkServiceImpl.java
index ebf979c3f..800ba4ef8 100644
--- a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/service/impl/ExternalLinkServiceImpl.java
+++ b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/service/impl/ExternalLinkServiceImpl.java
@@ -90,7 +90,7 @@ public class ExternalLinkServiceImpl extends ServiceImpl<ExternalLinkMapper, Ext
     Map<String, String> placeholderValueMap = new HashMap<>();
     placeholderValueMap.put(PlaceholderTypeEnum.JOB_ID.get(), app.getJobId());
     placeholderValueMap.put(PlaceholderTypeEnum.JOB_NAME.get(), app.getJobName());
-    placeholderValueMap.put(PlaceholderTypeEnum.YARN_ID.get(), app.getAppId());
+    placeholderValueMap.put(PlaceholderTypeEnum.YARN_ID.get(), app.getClusterId());
     PropertyPlaceholderHelper propertyPlaceholderHelper = new PropertyPlaceholderHelper("{", "}");
     link.setRenderedLinkUrl(
         propertyPlaceholderHelper.replacePlaceholders(
diff --git a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/service/impl/FlinkClusterServiceImpl.java b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/service/impl/FlinkClusterServiceImpl.java
index 5f73ea2fd..73ee6370b 100644
--- a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/service/impl/FlinkClusterServiceImpl.java
+++ b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/service/impl/FlinkClusterServiceImpl.java
@@ -26,9 +26,9 @@ import org.apache.streampark.console.base.exception.ApiDetailException;
 import org.apache.streampark.console.core.bean.ResponseResult;
 import org.apache.streampark.console.core.entity.FlinkCluster;
 import org.apache.streampark.console.core.mapper.FlinkClusterMapper;
-import org.apache.streampark.console.core.service.CommonService;
 import org.apache.streampark.console.core.service.FlinkClusterService;
 import org.apache.streampark.console.core.service.FlinkEnvService;
+import org.apache.streampark.console.core.service.ServiceHelper;
 import org.apache.streampark.console.core.service.YarnQueueService;
 import org.apache.streampark.console.core.service.application.ApplicationInfoService;
 import org.apache.streampark.console.core.watcher.FlinkClusterWatcher;
@@ -82,7 +82,7 @@ public class FlinkClusterServiceImpl extends ServiceImpl<FlinkClusterMapper, Fli
 
   @Autowired private FlinkEnvService flinkEnvService;
 
-  @Autowired private CommonService commonService;
+  @Autowired private ServiceHelper serviceHelper;
 
   @Autowired private ApplicationInfoService applicationInfoService;
 
@@ -142,7 +142,7 @@ public class FlinkClusterServiceImpl extends ServiceImpl<FlinkClusterMapper, Fli
 
   @Override
   public Boolean create(FlinkCluster flinkCluster) {
-    flinkCluster.setUserId(commonService.getUserId());
+    flinkCluster.setUserId(serviceHelper.getUserId());
     return internalCreate(flinkCluster);
   }
 
diff --git a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/service/impl/ResourceServiceImpl.java b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/service/impl/ResourceServiceImpl.java
index f62bcf997..c8a23df7b 100644
--- a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/service/impl/ResourceServiceImpl.java
+++ b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/service/impl/ResourceServiceImpl.java
@@ -37,9 +37,9 @@ import org.apache.streampark.console.core.entity.FlinkSql;
 import org.apache.streampark.console.core.entity.Resource;
 import org.apache.streampark.console.core.enums.ResourceTypeEnum;
 import org.apache.streampark.console.core.mapper.ResourceMapper;
-import org.apache.streampark.console.core.service.CommonService;
 import org.apache.streampark.console.core.service.FlinkSqlService;
 import org.apache.streampark.console.core.service.ResourceService;
+import org.apache.streampark.console.core.service.ServiceHelper;
 import org.apache.streampark.console.core.service.application.ApplicationManageService;
 import org.apache.streampark.flink.packer.maven.Artifact;
 import org.apache.streampark.flink.packer.maven.MavenTool;
@@ -96,7 +96,7 @@ public class ResourceServiceImpl extends ServiceImpl<ResourceMapper, Resource>
 
   @Autowired private ApplicationManageService applicationManageService;
 
-  @Autowired private CommonService commonService;
+  @Autowired private ServiceHelper serviceHelper;
 
   @Autowired private FlinkSqlService flinkSqlService;
 
@@ -150,7 +150,7 @@ public class ResourceServiceImpl extends ServiceImpl<ResourceMapper, Resource>
       transferTeamResource(resource.getTeamId(), upFile);
     }
 
-    resource.setCreatorId(commonService.getUserId());
+    resource.setCreatorId(serviceHelper.getUserId());
     this.save(resource);
   }
 
diff --git a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/service/impl/SavePointServiceImpl.java b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/service/impl/SavePointServiceImpl.java
index b70dfbfa1..d2e1703e5 100644
--- a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/service/impl/SavePointServiceImpl.java
+++ b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/service/impl/SavePointServiceImpl.java
@@ -40,6 +40,7 @@ import org.apache.streampark.console.core.service.ApplicationLogService;
 import org.apache.streampark.console.core.service.FlinkClusterService;
 import org.apache.streampark.console.core.service.FlinkEnvService;
 import org.apache.streampark.console.core.service.SavePointService;
+import org.apache.streampark.console.core.service.ServiceHelper;
 import org.apache.streampark.console.core.service.application.ApplicationManageService;
 import org.apache.streampark.console.core.watcher.FlinkAppHttpWatcher;
 import org.apache.streampark.flink.client.FlinkClient;
@@ -101,7 +102,7 @@ public class SavePointServiceImpl extends ServiceImpl<SavePointMapper, SavePoint
 
   @Autowired private FlinkAppHttpWatcher flinkAppHttpWatcher;
 
-  @Autowired private CommonServiceImpl commonService;
+  @Autowired private ServiceHelper commonService;
 
   @Qualifier("triggerSavepointExecutor")
   @Autowired
@@ -302,18 +303,20 @@ public class SavePointServiceImpl extends ServiceImpl<SavePointMapper, SavePoint
 
   private String getClusterId(Application application, FlinkCluster cluster) {
     if (FlinkExecutionMode.isKubernetesMode(application.getExecutionMode())) {
-      return application.getClusterId();
-    }
-    if (FlinkExecutionMode.isYarnMode(application.getExecutionMode())) {
-      if (FlinkExecutionMode.YARN_SESSION == application.getFlinkExecutionMode()) {
+      return FlinkExecutionMode.isKubernetesSessionMode(application.getExecutionMode())
+          ? cluster.getClusterId()
+          : application.getClusterId();
+    } else if (FlinkExecutionMode.isYarnMode(application.getExecutionMode())) {
+      if (FlinkExecutionMode.YARN_SESSION.equals(application.getFlinkExecutionMode())) {
         AssertUtils.notNull(
             cluster,
             String.format(
                 "The yarn session clusterId=%s cannot be find, maybe the clusterId is wrong or the cluster has been deleted. Please contact the Admin.",
                 application.getFlinkClusterId()));
         return cluster.getClusterId();
+      } else {
+        return application.getClusterId();
       }
-      return application.getAppId();
     }
     return null;
   }
diff --git a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/service/impl/SparkAppBuildPipeServiceImpl.java b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/service/impl/SparkAppBuildPipeServiceImpl.java
index ff0a529a8..ebaaeadd0 100644
--- a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/service/impl/SparkAppBuildPipeServiceImpl.java
+++ b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/service/impl/SparkAppBuildPipeServiceImpl.java
@@ -47,10 +47,10 @@ import org.apache.streampark.console.core.mapper.ApplicationBuildPipelineMapper;
 import org.apache.streampark.console.core.service.ApplicationBackUpService;
 import org.apache.streampark.console.core.service.ApplicationConfigService;
 import org.apache.streampark.console.core.service.ApplicationLogService;
-import org.apache.streampark.console.core.service.CommonService;
 import org.apache.streampark.console.core.service.FlinkSqlService;
 import org.apache.streampark.console.core.service.MessageService;
 import org.apache.streampark.console.core.service.ResourceService;
+import org.apache.streampark.console.core.service.ServiceHelper;
 import org.apache.streampark.console.core.service.SettingService;
 import org.apache.streampark.console.core.service.SparkAppBuildPipeService;
 import org.apache.streampark.console.core.service.SparkEnvService;
@@ -109,7 +109,7 @@ public class SparkAppBuildPipeServiceImpl
 
   @Autowired private ApplicationBackUpService backUpService;
 
-  @Autowired private CommonService commonService;
+  @Autowired private ServiceHelper serviceHelper;
 
   @Autowired private SettingService settingService;
 
@@ -148,7 +148,7 @@ public class SparkAppBuildPipeServiceImpl
     applicationLog.setOptionName(RELEASE.getValue());
     applicationLog.setAppId(app.getId());
     applicationLog.setOptionTime(new Date());
-    applicationLog.setUserId(commonService.getUserId());
+    applicationLog.setUserId(serviceHelper.getUserId());
 
     // check if you need to go through the build process (if the jar and pom have changed,
     // you need to go through the build process, if other common parameters are modified,
@@ -298,7 +298,7 @@ public class SparkAppBuildPipeServiceImpl
             } else {
               Message message =
                   new Message(
-                      commonService.getUserId(),
+                      serviceHelper.getUserId(),
                       app.getId(),
                       app.getJobName().concat(" release failed"),
                       ExceptionUtils.stringifyException(snapshot.error().exception()),
@@ -410,7 +410,7 @@ public class SparkAppBuildPipeServiceImpl
       case PYFLINK:
         return String.format("%s/%s", app.getAppHome(), app.getJar());
       case FLINK_SQL:
-        String sqlDistJar = commonService.getSqlClientJar(sparkEnv);
+        String sqlDistJar = serviceHelper.getSparkSqlClientJar(sparkEnv);
         if (app.getSparkExecutionMode() == SparkExecutionMode.YARN_CLUSTER) {
           String clientPath = Workspace.remote().APP_CLIENT();
           return String.format("%s/%s", clientPath, sqlDistJar);
diff --git a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/service/impl/VariableServiceImpl.java b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/service/impl/VariableServiceImpl.java
index 928f79fa5..a5c3662b7 100644
--- a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/service/impl/VariableServiceImpl.java
+++ b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/service/impl/VariableServiceImpl.java
@@ -26,8 +26,8 @@ import org.apache.streampark.console.core.entity.FlinkSql;
 import org.apache.streampark.console.core.entity.Variable;
 import org.apache.streampark.console.core.enums.ReleaseStateEnum;
 import org.apache.streampark.console.core.mapper.VariableMapper;
-import org.apache.streampark.console.core.service.CommonService;
 import org.apache.streampark.console.core.service.FlinkSqlService;
+import org.apache.streampark.console.core.service.ServiceHelper;
 import org.apache.streampark.console.core.service.VariableService;
 import org.apache.streampark.console.core.service.application.ApplicationManageService;
 
@@ -69,7 +69,7 @@ public class VariableServiceImpl extends ServiceImpl<VariableMapper, Variable>
 
   @Autowired private FlinkSqlService flinkSqlService;
 
-  @Autowired private CommonService commonService;
+  @Autowired private ServiceHelper serviceHelper;
 
   @Override
   public void createVariable(Variable variable) {
@@ -78,7 +78,7 @@ public class VariableServiceImpl extends ServiceImpl<VariableMapper, Variable>
         this.findByVariableCode(variable.getTeamId(), variable.getVariableCode()) != null,
         "Sorry, the variable code already exists.");
 
-    variable.setCreatorId(commonService.getUserId());
+    variable.setCreatorId(serviceHelper.getUserId());
     this.save(variable);
   }
 
diff --git a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/watcher/FlinkAppHttpWatcher.java b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/watcher/FlinkAppHttpWatcher.java
index 2073d3b68..4cc490811 100644
--- a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/watcher/FlinkAppHttpWatcher.java
+++ b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/watcher/FlinkAppHttpWatcher.java
@@ -674,12 +674,12 @@ public class FlinkAppHttpWatcher {
   }
 
   private YarnAppInfo httpYarnAppInfo(Application application) throws Exception {
-    String reqURL = "ws/v1/cluster/apps/".concat(application.getAppId());
+    String reqURL = "ws/v1/cluster/apps/".concat(application.getClusterId());
     return yarnRestRequest(reqURL, YarnAppInfo.class);
   }
 
   private Overview httpOverview(Application application) throws IOException {
-    String appId = application.getAppId();
+    String appId = application.getClusterId();
     if (appId != null
         && (FlinkExecutionMode.YARN_APPLICATION == application.getFlinkExecutionMode()
             || FlinkExecutionMode.YARN_PER_JOB == application.getFlinkExecutionMode())) {
@@ -708,7 +708,7 @@ public class FlinkAppHttpWatcher {
         reqURL = String.format(format, jmURL);
       } else {
         String format = "proxy/%s/" + flinkUrl;
-        reqURL = String.format(format, application.getAppId());
+        reqURL = String.format(format, application.getClusterId());
       }
       return yarnRestRequest(reqURL, JobsOverview.class);
     }
@@ -743,7 +743,7 @@ public class FlinkAppHttpWatcher {
         reqURL = String.format(format, jmURL, application.getJobId());
       } else {
         String format = "proxy/%s/" + flinkUrl;
-        reqURL = String.format(format, application.getAppId(), application.getJobId());
+        reqURL = String.format(format, application.getClusterId(), application.getJobId());
       }
       return yarnRestRequest(reqURL, CheckPoints.class);
     }
diff --git a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTFilter.java b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTFilter.java
index 3eb1d2540..6e6fad929 100644
--- a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTFilter.java
+++ b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTFilter.java
@@ -17,18 +17,14 @@
 
 package org.apache.streampark.console.system.authentication;
 
-import org.apache.streampark.console.base.properties.ShiroProperties;
-import org.apache.streampark.console.base.util.SpringContextUtils;
 import org.apache.streampark.console.base.util.WebUtils;
+import org.apache.streampark.console.core.enums.AuthenticationType;
 
-import org.apache.commons.lang3.StringUtils;
 import org.apache.shiro.authz.UnauthorizedException;
 import org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter;
 
-import com.baomidou.mybatisplus.core.toolkit.StringPool;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.http.HttpStatus;
-import org.springframework.util.AntPathMatcher;
 import org.springframework.web.bind.annotation.RequestMethod;
 
 import javax.servlet.ServletRequest;
@@ -41,24 +37,10 @@ public class JWTFilter extends BasicHttpAuthenticationFilter {
 
   private static final String TOKEN = "Authorization";
 
-  private final AntPathMatcher pathMatcher = new AntPathMatcher();
-
   @Override
   protected boolean isAccessAllowed(
       ServletRequest request, ServletResponse response, Object mappedValue)
       throws UnauthorizedException {
-    HttpServletRequest httpServletRequest = (HttpServletRequest) request;
-    ShiroProperties properties = SpringContextUtils.getBean(ShiroProperties.class);
-    String[] anonUrl =
-        StringUtils.splitByWholeSeparatorPreserveAllTokens(
-            properties.getAnonUrl(), StringPool.COMMA);
-
-    for (String url : anonUrl) {
-      if (pathMatcher.match(url.trim(), httpServletRequest.getRequestURI())) {
-        return true;
-      }
-    }
-
     if (isLoginAttempt(request, response)) {
       return executeLogin(request, response);
     }
@@ -69,21 +51,27 @@ public class JWTFilter extends BasicHttpAuthenticationFilter {
   protected boolean isLoginAttempt(ServletRequest request, ServletResponse response) {
     HttpServletRequest req = (HttpServletRequest) request;
     String token = req.getHeader(TOKEN);
-    return StringUtils.isNotBlank(token);
+    return token != null;
   }
 
   @Override
   protected boolean executeLogin(ServletRequest request, ServletResponse response) {
     HttpServletRequest httpServletRequest = (HttpServletRequest) request;
     String token = httpServletRequest.getHeader(TOKEN);
-    JWTToken jwtToken = new JWTToken(WebUtils.decryptToken(token));
-    try {
-      getSubject(request, response).login(jwtToken);
-      return true;
-    } catch (Exception e) {
-      log.error("Error in executeLogin, token {}, jwtToken {}", token, jwtToken, e);
+    AuthenticationType type = JWTUtil.getAuthType(WebUtils.decryptToken(token));
+    if (type == null) {
       return false;
     }
+    if (type == AuthenticationType.OPENAPI) {
+      JWTToken jwtToken = new JWTToken(WebUtils.decryptToken(token));
+      try {
+        getSubject(request, response).login(jwtToken);
+        return true;
+      } catch (Exception e) {
+        return false;
+      }
+    }
+    return true;
   }
 
   /** cross-domain support */
diff --git a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTToken.java b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTToken.java
index f04adad00..4e00e70ce 100644
--- a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTToken.java
+++ b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTToken.java
@@ -19,10 +19,12 @@ package org.apache.streampark.console.system.authentication;
 
 import org.apache.shiro.authc.AuthenticationToken;
 
-import lombok.Data;
+import lombok.Getter;
+import lombok.Setter;
 
 /** JSON Web Token */
-@Data
+@Getter
+@Setter
 public class JWTToken implements AuthenticationToken {
 
   private static final long serialVersionUID = 1L;
diff --git a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTUtil.java b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTUtil.java
index 073bdeed0..8b033d512 100644
--- a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTUtil.java
+++ b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/JWTUtil.java
@@ -17,35 +17,21 @@
 
 package org.apache.streampark.console.system.authentication;
 
-import org.apache.streampark.console.base.properties.ShiroProperties;
-import org.apache.streampark.console.base.util.SpringContextUtils;
-
-import org.apache.commons.lang3.RandomStringUtils;
-import org.apache.shiro.authc.AuthenticationException;
+import org.apache.streampark.console.core.enums.AuthenticationType;
 
 import com.auth0.jwt.JWT;
 import com.auth0.jwt.JWTVerifier;
 import com.auth0.jwt.algorithms.Algorithm;
-import com.auth0.jwt.exceptions.JWTDecodeException;
-import com.auth0.jwt.exceptions.TokenExpiredException;
 import com.auth0.jwt.interfaces.DecodedJWT;
 import lombok.extern.slf4j.Slf4j;
 
 import java.util.Date;
+import java.util.regex.Pattern;
 
-/** Verification and parsing Token */
 @Slf4j
 public class JWTUtil {
 
-  private static final long JWT_TIME_OUT =
-      SpringContextUtils.getBean(ShiroProperties.class).getJwtTimeOut() * 1000;
-
-  private static final Algorithm algorithm =
-      Algorithm.HMAC256(RandomStringUtils.randomAlphanumeric(256));
-
-  private static final String USER_NAME = "userName";
-
-  private static final String USER_ID = "userId";
+  private static Long ttlOfSecond;
 
   /**
    * verify token
@@ -53,15 +39,13 @@ public class JWTUtil {
    * @param token token
    * @return is valid token
    */
-  public static boolean verify(String token, String username) {
+  public static boolean verify(String token, String username, String secret) {
     try {
-      JWTVerifier verifier = JWT.require(algorithm).withClaim(USER_NAME, username).build();
+      Algorithm algorithm = Algorithm.HMAC256(secret);
+      JWTVerifier verifier = JWT.require(algorithm).withClaim("userName", username).build();
       verifier.verify(token);
       return true;
-    } catch (TokenExpiredException e) {
-      throw new AuthenticationException(e.getMessage());
-    } catch (Exception e) {
-      log.error("token is invalid:{} , e:{}", e.getMessage(), e.getClass());
+    } catch (Exception ignored) {
       return false;
     }
   }
@@ -70,9 +54,8 @@ public class JWTUtil {
   public static String getUserName(String token) {
     try {
       DecodedJWT jwt = JWT.decode(token);
-      return jwt.getClaim(USER_NAME).asString();
-    } catch (JWTDecodeException e) {
-      log.error("error:{}", e.getMessage());
+      return jwt.getClaim("userName").asString();
+    } catch (Exception ignored) {
       return null;
     }
   }
@@ -80,9 +63,18 @@ public class JWTUtil {
   public static Long getUserId(String token) {
     try {
       DecodedJWT jwt = JWT.decode(token);
-      return jwt.getClaim(USER_ID).asLong();
-    } catch (JWTDecodeException e) {
-      log.error("error:{}", e.getMessage());
+      return jwt.getClaim("userId").asLong();
+    } catch (Exception ignored) {
+      return null;
+    }
+  }
+
+  public static AuthenticationType getAuthType(String token) {
+    try {
+      DecodedJWT jwt = JWT.decode(token);
+      int type = jwt.getClaim("type").asInt();
+      return AuthenticationType.of(type);
+    } catch (Exception ignored) {
       return null;
     }
   }
@@ -94,8 +86,11 @@ public class JWTUtil {
    * @param userName
    * @return
    */
-  public static String sign(Long userId, String userName) {
-    return sign(userId, userName, getExpireTime());
+  public static String sign(
+      Long userId, String userName, String secret, AuthenticationType authType) {
+    Long second = getTTLOfSecond() * 1000;
+    Long ttl = System.currentTimeMillis() + second;
+    return sign(userId, userName, secret, authType, ttl);
   }
 
   /**
@@ -106,22 +101,41 @@ public class JWTUtil {
    * @param expireTime
    * @return
    */
-  public static String sign(Long userId, String userName, Long expireTime) {
-    try {
-      Date date = new Date(expireTime);
-      return JWT.create()
-          .withClaim(USER_ID, userId)
-          .withClaim(USER_NAME, userName)
-          .withExpiresAt(date)
-          .sign(algorithm);
-    } catch (Exception e) {
-      log.error("error:{}", e.getMessage());
-      return null;
-    }
+  public static String sign(
+      Long userId, String userName, String secret, AuthenticationType authType, Long expireTime) {
+    Date date = new Date(expireTime);
+    Algorithm algorithm = Algorithm.HMAC256(secret);
+    return JWT.create()
+        .withClaim("userId", userId)
+        .withClaim("userName", userName)
+        .withClaim("type", authType.get())
+        .withExpiresAt(date)
+        .sign(algorithm);
   }
 
-  /** get token expire timestamp */
-  private static Long getExpireTime() {
-    return System.currentTimeMillis() + JWT_TIME_OUT;
+  public static Long getTTLOfSecond() {
+    if (ttlOfSecond == null) {
+      String ttl = System.getProperty("server.session.ttl", "24h").trim();
+      String regexp = "^\\d+(s|m|h|d)$";
+      Pattern pattern = Pattern.compile(regexp);
+      if (!pattern.matcher(ttl).matches()) {
+        throw new IllegalArgumentException(
+            "server.session.ttl is invalid, Time units must be [s|m|h|d], e.g: 24h, 2d... please check config.yaml ");
+      }
+      String unit = ttl.substring(ttl.length() - 1);
+      String time = ttl.substring(0, ttl.length() - 1);
+      Long second = Long.parseLong(time);
+      switch (unit) {
+        case "m":
+          return ttlOfSecond = second * 60;
+        case "h":
+          return ttlOfSecond = second * 60 * 60;
+        case "d":
+          return ttlOfSecond = second * 24 * 60 * 60;
+        default:
+          return ttlOfSecond = second;
+      }
+    }
+    return ttlOfSecond;
   }
 }
diff --git a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/ShiroConfig.java b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/ShiroConfig.java
index 0f490f748..3384723ae 100644
--- a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/ShiroConfig.java
+++ b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/ShiroConfig.java
@@ -32,52 +32,48 @@ import java.util.LinkedHashMap;
 @Configuration
 public class ShiroConfig {
 
-  private static final String ANON = "anon";
-
-  private static final String JWT = "jwt";
-
   @Bean
   public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
     ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
     shiroFilterFactoryBean.setSecurityManager(securityManager);
 
     LinkedHashMap<String, Filter> filters = new LinkedHashMap<>();
-    filters.put(JWT, new JWTFilter());
+    filters.put("jwt", new JWTFilter());
     shiroFilterFactoryBean.setFilters(filters);
 
     LinkedHashMap<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
-    filterChainDefinitionMap.put("/actuator/**", ANON);
-
-    filterChainDefinitionMap.put("/doc.html", ANON);
-    filterChainDefinitionMap.put("/swagger-ui.html", ANON);
-    filterChainDefinitionMap.put("/swagger-ui/**", ANON);
-    filterChainDefinitionMap.put("/swagger-resources/**", ANON);
-    filterChainDefinitionMap.put("/v3/api-docs/**", ANON);
-    filterChainDefinitionMap.put("/webjars/**", ANON);
-
-    filterChainDefinitionMap.put("/passport/**", ANON);
-    filterChainDefinitionMap.put("/systemName", ANON);
-    filterChainDefinitionMap.put("/member/teams", ANON);
-    filterChainDefinitionMap.put("/user/check/**", ANON);
-    filterChainDefinitionMap.put("/user/initTeam", ANON);
-    filterChainDefinitionMap.put("/websocket/**", ANON);
-    filterChainDefinitionMap.put("/metrics/**", ANON);
-
-    filterChainDefinitionMap.put("/index.html", ANON);
-    filterChainDefinitionMap.put("/assets/**", ANON);
-    filterChainDefinitionMap.put("/resource/**/**", ANON);
-    filterChainDefinitionMap.put("/css/**", ANON);
-    filterChainDefinitionMap.put("/fonts/**", ANON);
-    filterChainDefinitionMap.put("/img/**", ANON);
-    filterChainDefinitionMap.put("/js/**", ANON);
-    filterChainDefinitionMap.put("/loading/**", ANON);
-    filterChainDefinitionMap.put("/*.js", ANON);
-    filterChainDefinitionMap.put("/*.png", ANON);
-    filterChainDefinitionMap.put("/*.jpg", ANON);
-    filterChainDefinitionMap.put("/*.less", ANON);
-    filterChainDefinitionMap.put("/*.ico", ANON);
-    filterChainDefinitionMap.put("/", ANON);
-    filterChainDefinitionMap.put("/**", JWT);
+    filterChainDefinitionMap.put("/actuator/**", "anon");
+
+    filterChainDefinitionMap.put("/doc.html", "anon");
+    filterChainDefinitionMap.put("/swagger-ui.html", "anon");
+    filterChainDefinitionMap.put("/swagger-ui/**", "anon");
+    filterChainDefinitionMap.put("/swagger-resources/**", "anon");
+    filterChainDefinitionMap.put("/v3/api-docs/**", "anon");
+    filterChainDefinitionMap.put("/webjars/**", "anon");
+
+    filterChainDefinitionMap.put("/passport/**", "anon");
+    filterChainDefinitionMap.put("/systemName", "anon");
+    filterChainDefinitionMap.put("/member/teams", "anon");
+    filterChainDefinitionMap.put("/user/check/**", "anon");
+    filterChainDefinitionMap.put("/user/initTeam", "anon");
+    filterChainDefinitionMap.put("/websocket/**", "anon");
+    filterChainDefinitionMap.put("/metrics/**", "anon");
+
+    filterChainDefinitionMap.put("/index.html", "anon");
+    filterChainDefinitionMap.put("/assets/**", "anon");
+    filterChainDefinitionMap.put("/resource/**/**", "anon");
+    filterChainDefinitionMap.put("/css/**", "anon");
+    filterChainDefinitionMap.put("/fonts/**", "anon");
+    filterChainDefinitionMap.put("/img/**", "anon");
+    filterChainDefinitionMap.put("/js/**", "anon");
+    filterChainDefinitionMap.put("/loading/**", "anon");
+    filterChainDefinitionMap.put("/*.js", "anon");
+    filterChainDefinitionMap.put("/*.png", "anon");
+    filterChainDefinitionMap.put("/*.jpg", "anon");
+    filterChainDefinitionMap.put("/*.less", "anon");
+    filterChainDefinitionMap.put("/*.ico", "anon");
+    filterChainDefinitionMap.put("/", "anon");
+    filterChainDefinitionMap.put("/**", "jwt");
 
     shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
 
diff --git a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/ShiroRealm.java b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/ShiroRealm.java
index 41e7f0586..d17ac15a0 100644
--- a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/ShiroRealm.java
+++ b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/authentication/ShiroRealm.java
@@ -18,6 +18,7 @@
 package org.apache.streampark.console.system.authentication;
 
 import org.apache.streampark.console.base.util.WebUtils;
+import org.apache.streampark.console.core.enums.AuthenticationType;
 import org.apache.streampark.console.system.entity.AccessToken;
 import org.apache.streampark.console.system.entity.User;
 import org.apache.streampark.console.system.service.AccessTokenService;
@@ -79,28 +80,34 @@ public class ShiroRealm extends AuthorizingRealm {
   protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken)
       throws AuthenticationException {
     // The token here is passed from the executeLogin method of JWTFilter and has been decrypted
-    String token = (String) authenticationToken.getCredentials();
-    String username = JWTUtil.getUserName(token);
+    String credential = (String) authenticationToken.getCredentials();
+    String username = JWTUtil.getUserName(credential);
+
     if (StringUtils.isBlank(username)) {
-      throw new AuthenticationException("Token verification failed");
+      throw new AuthenticationException("the authorization token is invalid");
     }
     // Query user information by username
     User user = userService.getByUsername(username);
 
-    if (user == null) {
-      throw new AuthenticationException("ERROR Incorrect username or password!");
+    if (user == null || !JWTUtil.verify(credential, username, user.getSalt())) {
+      throw new AuthenticationException("the authorization token verification failed.");
     }
 
-    if (!JWTUtil.verify(token, username)) {
+    AuthenticationType authType = JWTUtil.getAuthType(credential);
+    if (authType == AuthenticationType.OPENAPI) {
       // Check whether the token belongs to the api and whether the permission is valid
-      String tokenDb = WebUtils.encryptToken(token);
-      boolean effective = accessTokenService.checkTokenEffective(user.getUserId(), tokenDb);
-      if (!effective) {
+      AccessToken accessToken = accessTokenService.getByUserId(user.getUserId());
+      if (accessToken == null
+          || !accessToken.getToken().equals(WebUtils.encryptToken(credential))) {
+        throw new AuthenticationException("the openapi authorization token is invalid");
+      }
+      if (AccessToken.STATUS_DISABLE.equals(accessToken.getFinalStatus())) {
         throw new AuthenticationException(
-            "Token checked failed: 1-[Browser Request] please check the username or password; 2-[Api Request] please check the user status or accessToken status");
+            "the openapi authorization token has been disabled, please contact the administrator");
       }
       SecurityUtils.getSubject().getSession().setAttribute(AccessToken.IS_API_TOKEN, true);
     }
-    return new SimpleAuthenticationInfo(token, token, "streampark_shiro_realm");
+
+    return new SimpleAuthenticationInfo(credential, credential, "streampark_shiro_realm");
   }
 }
diff --git a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/controller/AccessTokenController.java b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/controller/AccessTokenController.java
index ae723b141..ea60d0df7 100644
--- a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/controller/AccessTokenController.java
+++ b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/controller/AccessTokenController.java
@@ -22,19 +22,13 @@ import org.apache.streampark.console.base.domain.RestRequest;
 import org.apache.streampark.console.base.domain.RestResponse;
 import org.apache.streampark.console.base.exception.InternalException;
 import org.apache.streampark.console.core.enums.AccessTokenStateEnum;
-import org.apache.streampark.console.core.service.CommonService;
+import org.apache.streampark.console.core.service.ServiceHelper;
 import org.apache.streampark.console.system.entity.AccessToken;
 import org.apache.streampark.console.system.service.AccessTokenService;
 
 import org.apache.shiro.authz.annotation.RequiresPermissions;
 
 import com.baomidou.mybatisplus.core.metadata.IPage;
-import io.swagger.v3.oas.annotations.Operation;
-import io.swagger.v3.oas.annotations.Parameter;
-import io.swagger.v3.oas.annotations.Parameters;
-import io.swagger.v3.oas.annotations.enums.ParameterIn;
-import io.swagger.v3.oas.annotations.media.Schema;
-import io.swagger.v3.oas.annotations.tags.Tag;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.DeleteMapping;
 import org.springframework.web.bind.annotation.PostMapping;
@@ -45,49 +39,26 @@ import org.springframework.web.bind.annotation.RestController;
 import javax.validation.constraints.NotBlank;
 import javax.validation.constraints.NotNull;
 
-@Tag(name = "ACCESS_TOKEN_TAG")
 @RestController
 @RequestMapping("token")
 public class AccessTokenController {
 
   @Autowired private AccessTokenService accessTokenService;
 
-  @Autowired private CommonService commonService;
-
-  /** generate token string */
-  @Operation(summary = "Create token")
-  @Parameters({
-    @Parameter(
-        name = "userId",
-        description = "user id",
-        required = true,
-        example = "100000",
-        schema = @Schema(implementation = Long.class)),
-    @Parameter(
-        name = "expireTime",
-        description = "token expire time, yyyy-MM-dd HH:mm:ss",
-        required = true,
-        example = "9999-01-01 00:00:00",
-        schema = @Schema(implementation = String.class)),
-    @Parameter(
-        name = "description",
-        description = "token description",
-        schema = @Schema(implementation = String.class))
-  })
+  @Autowired private ServiceHelper serviceHelper;
+
   @PostMapping(value = "create")
   @RequiresPermissions("token:add")
   public RestResponse createToken(
       @NotBlank(message = "{required}") Long userId,
-      String expireTime,
       @RequestParam(required = false) String description)
       throws InternalException {
-    return accessTokenService.generateToken(userId, expireTime, description);
+    return accessTokenService.create(userId, description);
   }
 
-  @Operation(summary = "Verify current user token")
   @PostMapping(value = "check")
   public RestResponse verifyToken() {
-    Long userId = commonService.getUserId();
+    Long userId = serviceHelper.getUserId();
     RestResponse restResponse = RestResponse.success();
     if (userId != null) {
       AccessToken accessToken = accessTokenService.getByUserId(userId);
@@ -104,49 +75,19 @@ public class AccessTokenController {
     return restResponse;
   }
 
-  /** query token list */
-  @Operation(summary = "List tokens")
-  @Parameters({
-    @Parameter(
-        name = "userId",
-        in = ParameterIn.QUERY,
-        description = "user id",
-        schema = @Schema(implementation = Long.class))
-  })
   @PostMapping(value = "list")
   @RequiresPermissions("token:view")
-  public RestResponse tokensList(
-      RestRequest restRequest, @Parameter(hidden = true) AccessToken accessToken) {
+  public RestResponse tokensList(RestRequest restRequest, AccessToken accessToken) {
     IPage<AccessToken> accessTokens = accessTokenService.getPage(accessToken, restRequest);
     return RestResponse.success(accessTokens);
   }
 
-  /** update token status */
-  @Operation(summary = "Toggle token")
-  @Parameters({
-    @Parameter(
-        name = "tokenId",
-        description = "token id",
-        required = true,
-        example = "1",
-        schema = @Schema(implementation = Long.class))
-  })
   @PostMapping("toggle")
   @RequiresPermissions("token:add")
   public RestResponse toggleToken(@NotNull(message = "{required}") Long tokenId) {
     return accessTokenService.toggleToken(tokenId);
   }
 
-  /** delete token by id */
-  @Operation(summary = "Delete token")
-  @Parameters({
-    @Parameter(
-        name = "tokenId",
-        description = "token id",
-        required = true,
-        example = "1",
-        schema = @Schema(implementation = Long.class))
-  })
   @DeleteMapping(value = "delete")
   @RequiresPermissions("token:delete")
   public RestResponse deleteToken(@NotBlank(message = "{required}") Long tokenId) {
@@ -158,7 +99,6 @@ public class AccessTokenController {
    * copy cURL, hardcode now, there is no need for configuration here, because there are several
    * fixed interfaces
    */
-  @Operation(summary = "Generate api with token")
   @PostMapping(value = "curl")
   public RestResponse copyRestApiCurl(
       @NotBlank(message = "{required}") String appId,
@@ -170,7 +110,7 @@ public class AccessTokenController {
     curlBuilder
         .addHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8")
         .addHeader(
-            "Authorization", accessTokenService.getByUserId(commonService.getUserId()).getToken());
+            "Authorization", accessTokenService.getByUserId(serviceHelper.getUserId()).getToken());
 
     if ("/flink/app/start".equalsIgnoreCase(path)) {
       resultCURL =
diff --git a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/controller/MemberController.java b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/controller/MemberController.java
index 900245f4e..a1f1a694e 100644
--- a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/controller/MemberController.java
+++ b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/controller/MemberController.java
@@ -19,8 +19,7 @@ package org.apache.streampark.console.system.controller;
 
 import org.apache.streampark.console.base.domain.RestRequest;
 import org.apache.streampark.console.base.domain.RestResponse;
-import org.apache.streampark.console.core.annotation.PermissionAction;
-import org.apache.streampark.console.core.enums.PermissionTypeEnum;
+import org.apache.streampark.console.core.annotation.PermissionScope;
 import org.apache.streampark.console.system.entity.Member;
 import org.apache.streampark.console.system.entity.Team;
 import org.apache.streampark.console.system.entity.User;
@@ -29,8 +28,6 @@ import org.apache.streampark.console.system.service.MemberService;
 import org.apache.shiro.authz.annotation.RequiresPermissions;
 
 import com.baomidou.mybatisplus.core.metadata.IPage;
-import io.swagger.v3.oas.annotations.Operation;
-import io.swagger.v3.oas.annotations.tags.Tag;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.validation.annotation.Validated;
@@ -45,7 +42,6 @@ import javax.validation.constraints.NotBlank;
 
 import java.util.List;
 
-@Tag(name = "MEMBER_TAG")
 @Slf4j
 @Validated
 @RestController
@@ -54,55 +50,48 @@ public class MemberController {
 
   @Autowired private MemberService memberService;
 
-  @Operation(summary = "List members")
   @PostMapping("list")
   public RestResponse memberList(RestRequest restRequest, Member member) {
     IPage<Member> userList = memberService.getPage(member, restRequest);
     return RestResponse.success(userList);
   }
 
-  @Operation(summary = "List candidate users")
   @PostMapping("candidateUsers")
   public RestResponse candidateUsers(Long teamId) {
     List<User> userList = memberService.listUsersNotInTeam(teamId);
     return RestResponse.success(userList);
   }
 
-  @Operation(summary = "List teams")
   @PostMapping("teams")
   public RestResponse listTeams(Long userId) {
     List<Team> teamList = memberService.listTeamsByUserId(userId);
     return RestResponse.success(teamList);
   }
 
-  @Operation(summary = "Check the username")
   @PostMapping("check/user")
   public RestResponse check(@NotBlank(message = "{required}") Long teamId, String userName) {
     Member result = this.memberService.getByTeamIdUserName(teamId, userName);
     return RestResponse.success(result == null);
   }
 
-  @Operation(summary = "Create member")
-  @PermissionAction(id = "#member.teamId", type = PermissionTypeEnum.TEAM)
   @PostMapping("post")
+  @PermissionScope(team = "#member.teamId")
   @RequiresPermissions("member:add")
   public RestResponse create(@Valid Member member) {
     this.memberService.createMember(member);
     return RestResponse.success();
   }
 
-  @Operation(summary = "Delete member")
-  @PermissionAction(id = "#member.teamId", type = PermissionTypeEnum.TEAM)
   @DeleteMapping("delete")
+  @PermissionScope(team = "#member.teamId")
   @RequiresPermissions("member:delete")
   public RestResponse delete(Member member) {
     this.memberService.remove(member.getId());
     return RestResponse.success();
   }
 
-  @Operation(summary = "Update member")
-  @PermissionAction(id = "#member.teamId", type = PermissionTypeEnum.TEAM)
   @PutMapping("update")
+  @PermissionScope(team = "#member.teamId")
   @RequiresPermissions("member:update")
   public RestResponse update(Member member) {
     this.memberService.updateMember(member);
diff --git a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/controller/MenuController.java b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/controller/MenuController.java
index 328fa0688..52c0b60cb 100644
--- a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/controller/MenuController.java
+++ b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/controller/MenuController.java
@@ -19,14 +19,12 @@ package org.apache.streampark.console.system.controller;
 
 import org.apache.streampark.console.base.domain.RestResponse;
 import org.apache.streampark.console.base.domain.router.VueRouter;
-import org.apache.streampark.console.core.service.CommonService;
+import org.apache.streampark.console.core.service.ServiceHelper;
 import org.apache.streampark.console.system.entity.Menu;
 import org.apache.streampark.console.system.service.MenuService;
 
 import org.apache.shiro.authz.annotation.RequiresPermissions;
 
-import io.swagger.v3.oas.annotations.Operation;
-import io.swagger.v3.oas.annotations.tags.Tag;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.validation.annotation.Validated;
@@ -37,7 +35,6 @@ import org.springframework.web.bind.annotation.RestController;
 import java.util.List;
 import java.util.Map;
 
-@Tag(name = "MENU_TAG")
 @Slf4j
 @Validated
 @RestController
@@ -46,17 +43,15 @@ public class MenuController {
 
   @Autowired private MenuService menuService;
 
-  @Autowired private CommonService commonService;
+  @Autowired private ServiceHelper serviceHelper;
 
-  @Operation(summary = "List menu-routes")
   @PostMapping("router")
   public RestResponse getUserRouters(Long teamId) {
     // TODO The teamId is required, get routers should be called after choose teamId.
-    List<VueRouter<Menu>> routers = this.menuService.listRouters(commonService.getUserId(), teamId);
+    List<VueRouter<Menu>> routers = this.menuService.listRouters(serviceHelper.getUserId(), teamId);
     return RestResponse.success(routers);
   }
 
-  @Operation(summary = "List menus")
   @PostMapping("list")
   @RequiresPermissions("menu:view")
   public RestResponse menuList(Menu menu) {
diff --git a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/controller/PassportController.java b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/controller/PassportController.java
index 8cd1d2f2e..93a67976c 100644
--- a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/controller/PassportController.java
+++ b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/controller/PassportController.java
@@ -17,17 +17,22 @@
 
 package org.apache.streampark.console.system.controller;
 
+import org.apache.streampark.common.util.DateUtils;
+import org.apache.streampark.console.base.domain.ResponseCode;
 import org.apache.streampark.console.base.domain.RestResponse;
+import org.apache.streampark.console.base.util.WebUtils;
+import org.apache.streampark.console.core.enums.AuthenticationType;
 import org.apache.streampark.console.core.enums.LoginTypeEnum;
+import org.apache.streampark.console.system.authentication.JWTToken;
+import org.apache.streampark.console.system.authentication.JWTUtil;
 import org.apache.streampark.console.system.entity.User;
 import org.apache.streampark.console.system.security.Authenticator;
 import org.apache.streampark.console.system.service.UserService;
 
+import org.apache.commons.lang3.RandomStringUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.shiro.SecurityUtils;
 
-import io.swagger.v3.oas.annotations.Operation;
-import io.swagger.v3.oas.annotations.tags.Tag;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
@@ -36,12 +41,15 @@ import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
 
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
 import javax.validation.constraints.NotBlank;
 
+import java.time.LocalDateTime;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Map;
 
-@Tag(name = "PASSPORT_TAG")
 @Slf4j
 @Validated
 @RestController
@@ -58,7 +66,6 @@ public class PassportController {
   @Value("${ldap.enable:#{false}}")
   private Boolean ldapEnable;
 
-  @Operation(summary = "SigninType")
   @PostMapping("signtype")
   public RestResponse type() {
     List<String> types = new ArrayList<>();
@@ -72,25 +79,61 @@ public class PassportController {
     return RestResponse.success(types);
   }
 
-  @Operation(summary = "Signin")
   @PostMapping("signin")
   public RestResponse signin(
+      HttpServletRequest request,
+      HttpServletResponse response,
       @NotBlank(message = "{required}") String username,
       @NotBlank(message = "{required}") String password,
       @NotBlank(message = "{required}") String loginType)
       throws Exception {
 
-    if (StringUtils.isBlank(username)) {
-      return RestResponse.success().put(RestResponse.CODE_KEY, 0);
+    if (StringUtils.isEmpty(username)) {
+      return RestResponse.success().put("code", 0);
     }
+
     User user = authenticator.authenticate(username, password, loginType);
-    return userService.getLoginUserInfo(user);
+
+    if (user == null) {
+      return RestResponse.success().put("code", 0);
+    }
+
+    if (User.STATUS_LOCK.equals(user.getStatus())) {
+      return RestResponse.success().put("code", 1);
+    }
+
+    // set team
+    userService.fillInTeam(user);
+
+    // no team.
+    if (user.getLastTeamId() == null) {
+      return RestResponse.success().data(user.getUserId()).put("code", ResponseCode.CODE_FORBIDDEN);
+    }
+
+    this.userService.updateLoginTime(username);
+    String sign = JWTUtil.sign(user.getUserId(), username, user.getSalt(), AuthenticationType.SIGN);
+
+    LocalDateTime expireTime = LocalDateTime.now().plusSeconds(JWTUtil.getTTLOfSecond());
+    String ttl = DateUtils.formatFullTime(expireTime);
+
+    // shiro login
+    JWTToken loginToken = new JWTToken(sign, ttl);
+    SecurityUtils.getSubject().login(loginToken);
+
+    // generate UserInfo
+    String token = WebUtils.encryptToken(sign);
+    JWTToken jwtToken = new JWTToken(token, ttl);
+    String userId = RandomStringUtils.randomAlphanumeric(20);
+    user.setId(userId);
+    Map<String, Object> userInfo =
+        userService.generateFrontendUserInfo(user, user.getLastTeamId(), jwtToken);
+
+    return new RestResponse().data(userInfo);
   }
 
-  @Operation(summary = "Signout")
   @PostMapping("signout")
   public RestResponse signout() {
-    SecurityUtils.getSecurityManager().logout(SecurityUtils.getSubject());
+    SecurityUtils.getSubject().logout();
     return new RestResponse();
   }
 }
diff --git a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/controller/RoleController.java b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/controller/RoleController.java
index afa84ff0d..f94f650a4 100644
--- a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/controller/RoleController.java
+++ b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/controller/RoleController.java
@@ -27,8 +27,6 @@ import org.apache.streampark.console.system.service.RoleService;
 import org.apache.shiro.authz.annotation.RequiresPermissions;
 
 import com.baomidou.mybatisplus.core.metadata.IPage;
-import io.swagger.v3.oas.annotations.Operation;
-import io.swagger.v3.oas.annotations.tags.Tag;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.validation.annotation.Validated;
@@ -44,7 +42,6 @@ import javax.validation.constraints.NotBlank;
 import java.util.List;
 import java.util.stream.Collectors;
 
-@Tag(name = "ROLE_TAG")
 @Slf4j
 @Validated
 @RestController
@@ -54,7 +51,6 @@ public class RoleController {
   @Autowired private RoleService roleService;
   @Autowired private RoleMenuService roleMenuService;
 
-  @Operation(summary = "List roles")
   @PostMapping("list")
   @RequiresPermissions("role:view")
   public RestResponse roleList(RestRequest restRequest, Role role) {
@@ -62,14 +58,12 @@ public class RoleController {
     return RestResponse.success(roleList);
   }
 
-  @Operation(summary = "Check the role name")
   @PostMapping("check/name")
   public RestResponse checkRoleName(@NotBlank(message = "{required}") String roleName) {
     Role result = this.roleService.getByName(roleName);
     return RestResponse.success(result == null);
   }
 
-  @Operation(summary = "List role menus")
   @PostMapping("menu")
   public RestResponse getRoleMenus(@NotBlank(message = "{required}") String roleId) {
     List<RoleMenu> roleMenuList = this.roleMenuService.listByRoleId(roleId);
@@ -80,7 +74,6 @@ public class RoleController {
     return RestResponse.success(menuIdList);
   }
 
-  @Operation(summary = "Create role")
   @PostMapping("post")
   @RequiresPermissions("role:add")
   public RestResponse addRole(@Valid Role role) {
@@ -88,7 +81,6 @@ public class RoleController {
     return RestResponse.success();
   }
 
-  @Operation(summary = "Delete role")
   @DeleteMapping("delete")
   @RequiresPermissions("role:delete")
   public RestResponse deleteRole(Long roleId) {
@@ -96,7 +88,6 @@ public class RoleController {
     return RestResponse.success();
   }
 
-  @Operation(summary = "Update role")
   @PutMapping("update")
   @RequiresPermissions("role:update")
   public RestResponse updateRole(Role role) throws Exception {
diff --git a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/controller/TeamController.java b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/controller/TeamController.java
index 431e2d40f..698175ddd 100644
--- a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/controller/TeamController.java
+++ b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/controller/TeamController.java
@@ -25,8 +25,6 @@ import org.apache.streampark.console.system.service.TeamService;
 import org.apache.shiro.authz.annotation.RequiresPermissions;
 
 import com.baomidou.mybatisplus.core.metadata.IPage;
-import io.swagger.v3.oas.annotations.Operation;
-import io.swagger.v3.oas.annotations.tags.Tag;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.validation.annotation.Validated;
@@ -39,7 +37,6 @@ import org.springframework.web.bind.annotation.RestController;
 import javax.validation.Valid;
 import javax.validation.constraints.NotBlank;
 
-@Tag(name = "TEAM_TAG")
 @Slf4j
 @Validated
 @RestController
@@ -48,21 +45,18 @@ public class TeamController {
 
   @Autowired private TeamService teamService;
 
-  @Operation(summary = "List teams")
   @PostMapping("list")
   public RestResponse teamList(RestRequest restRequest, Team team) {
     IPage<Team> teamList = teamService.getPage(team, restRequest);
     return RestResponse.success(teamList);
   }
 
-  @Operation(summary = "Check the team name")
   @PostMapping("check/name")
   public RestResponse checkTeamName(@NotBlank(message = "{required}") String teamName) {
     Team result = this.teamService.getByName(teamName);
     return RestResponse.success(result == null);
   }
 
-  @Operation(summary = "Create team")
   @PostMapping("post")
   @RequiresPermissions("team:add")
   public RestResponse addTeam(@Valid Team team) {
@@ -70,7 +64,6 @@ public class TeamController {
     return RestResponse.success();
   }
 
-  @Operation(summary = "Delete team")
   @DeleteMapping("delete")
   @RequiresPermissions("team:delete")
   public RestResponse deleteTeam(Team team) {
@@ -78,7 +71,6 @@ public class TeamController {
     return RestResponse.success();
   }
 
-  @Operation(summary = "Update team")
   @PutMapping("update")
   @RequiresPermissions("team:update")
   public RestResponse updateTeam(Team team) {
diff --git a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/controller/UserController.java b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/controller/UserController.java
index 0d15b02c7..be2afe478 100644
--- a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/controller/UserController.java
+++ b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/controller/UserController.java
@@ -21,10 +21,9 @@ import org.apache.streampark.console.base.domain.ResponseCode;
 import org.apache.streampark.console.base.domain.RestRequest;
 import org.apache.streampark.console.base.domain.RestResponse;
 import org.apache.streampark.console.base.exception.ApiAlertException;
-import org.apache.streampark.console.core.annotation.PermissionAction;
+import org.apache.streampark.console.core.annotation.PermissionScope;
 import org.apache.streampark.console.core.enums.LoginTypeEnum;
-import org.apache.streampark.console.core.enums.PermissionTypeEnum;
-import org.apache.streampark.console.core.service.CommonService;
+import org.apache.streampark.console.core.service.ServiceHelper;
 import org.apache.streampark.console.system.entity.Team;
 import org.apache.streampark.console.system.entity.User;
 import org.apache.streampark.console.system.service.TeamService;
@@ -34,11 +33,10 @@ import org.apache.shiro.authz.annotation.Logical;
 import org.apache.shiro.authz.annotation.RequiresPermissions;
 
 import com.baomidou.mybatisplus.core.metadata.IPage;
-import io.swagger.v3.oas.annotations.Operation;
-import io.swagger.v3.oas.annotations.tags.Tag;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.DeleteMapping;
 import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.PutMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
@@ -50,7 +48,6 @@ import javax.validation.constraints.NotBlank;
 import java.util.List;
 import java.util.Map;
 
-@Tag(name = "USER_TAG")
 @Slf4j
 @Validated
 @RestController
@@ -61,9 +58,8 @@ public class UserController {
 
   @Autowired private TeamService teamService;
 
-  @Autowired private CommonService commonService;
+  @Autowired private ServiceHelper serviceHelper;
 
-  @Operation(summary = "List users")
   @PostMapping("list")
   @RequiresPermissions(
       value = {"user:view", "app:view"},
@@ -73,7 +69,6 @@ public class UserController {
     return RestResponse.success(userList);
   }
 
-  @Operation(summary = "Create user")
   @PostMapping("post")
   @RequiresPermissions("user:add")
   public RestResponse addUser(@Valid User user) throws Exception {
@@ -82,14 +77,13 @@ public class UserController {
     return RestResponse.success();
   }
 
-  @Operation(summary = "Update user")
   @PutMapping("update")
+  @PermissionScope(user = "#user.id")
   @RequiresPermissions("user:update")
   public RestResponse updateUser(@Valid User user) throws Exception {
     return this.userService.updateUser(user);
   }
 
-  @Operation(summary = "Transfer User's Resource")
   @PutMapping("transferResource")
   @RequiresPermissions("user:update")
   public RestResponse transferResource(Long userId, Long targetUserId) {
@@ -97,29 +91,33 @@ public class UserController {
     return RestResponse.success();
   }
 
-  @Operation(summary = "List without token users")
+  @DeleteMapping("delete")
+  @PermissionScope(user = "#userId")
+  @RequiresPermissions("user:delete")
+  public RestResponse deleteUser(Long userId) throws Exception {
+    this.userService.deleteUser(userId);
+    return RestResponse.success();
+  }
+
   @PostMapping("getNoTokenUser")
   public RestResponse getNoTokenUser() {
     List<User> userList = this.userService.listNoTokenUser();
     return RestResponse.success(userList);
   }
 
-  @Operation(summary = "Check the username")
   @PostMapping("check/name")
   public RestResponse checkUserName(@NotBlank(message = "{required}") String username) {
     boolean result = this.userService.getByUsername(username) == null;
     return RestResponse.success(result);
   }
 
-  @Operation(summary = "Update password")
-  @PermissionAction(id = "#user.userId", type = PermissionTypeEnum.USER)
   @PutMapping("password")
+  @PermissionScope(user = "#user.id")
   public RestResponse updatePassword(User user) throws Exception {
     userService.updatePassword(user);
     return RestResponse.success();
   }
 
-  @Operation(summary = "Reset password")
   @PutMapping("password/reset")
   @RequiresPermissions("user:reset")
   public RestResponse resetPassword(@NotBlank(message = "{required}") String username)
@@ -128,7 +126,6 @@ public class UserController {
     return RestResponse.success(newPass);
   }
 
-  @Operation(summary = "Init the user teams")
   @PostMapping("initTeam")
   public RestResponse initTeam(Long teamId, Long userId) {
     Team team = teamService.getById(teamId);
@@ -139,14 +136,13 @@ public class UserController {
     return RestResponse.success();
   }
 
-  @Operation(summary = "Set the current user teams")
   @PostMapping("setTeam")
   public RestResponse setTeam(Long teamId) {
     Team team = teamService.getById(teamId);
     if (team == null) {
       return RestResponse.fail(ResponseCode.CODE_FAIL_ALERT, "TeamId is invalid, set team failed.");
     }
-    User user = commonService.getCurrentUser();
+    User user = serviceHelper.getLoginUser();
     ApiAlertException.throwIfNull(user, "Current login user is null, set team failed.");
     // 1) set the latest team
     userService.setLastTeam(teamId, user.getUserId());
@@ -158,7 +154,6 @@ public class UserController {
     return new RestResponse().data(infoMap);
   }
 
-  @Operation(summary = "List the team users")
   @PostMapping("appOwners")
   public RestResponse appOwners(Long teamId) {
     List<User> userList = userService.listByTeamId(teamId);
diff --git a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/service/AccessTokenService.java b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/service/AccessTokenService.java
index 1030e16d6..a3408e4f4 100644
--- a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/service/AccessTokenService.java
+++ b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/service/AccessTokenService.java
@@ -32,13 +32,11 @@ public interface AccessTokenService extends IService<AccessToken> {
    * Generate token based on user ID's expiration time and description
    *
    * @param userId User id
-   * @param expireTime expiration
    * @param description more description
    * @return RestResponse
    * @throws InternalException
    */
-  RestResponse generateToken(Long userId, String expireTime, String description)
-      throws InternalException;
+  RestResponse create(Long userId, String description) throws InternalException;
 
   /**
    * Retrieves a page of {@link AccessToken} objects based on the provided parameters.
diff --git a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/service/UserService.java b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/service/UserService.java
index 745393f08..8f06eb7ae 100644
--- a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/service/UserService.java
+++ b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/service/UserService.java
@@ -166,4 +166,6 @@ public interface UserService extends IService<User> {
    * @return RestResponse
    */
   RestResponse getLoginUserInfo(User user);
+
+  void deleteUser(Long userId);
 }
diff --git a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/service/impl/AccessTokenServiceImpl.java b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/service/impl/AccessTokenServiceImpl.java
index 676c8dab3..ce022aeeb 100644
--- a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/service/impl/AccessTokenServiceImpl.java
+++ b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/service/impl/AccessTokenServiceImpl.java
@@ -17,12 +17,12 @@
 
 package org.apache.streampark.console.system.service.impl;
 
-import org.apache.streampark.common.util.DateUtils;
 import org.apache.streampark.console.base.domain.ResponseCode;
 import org.apache.streampark.console.base.domain.RestRequest;
 import org.apache.streampark.console.base.domain.RestResponse;
 import org.apache.streampark.console.base.mybatis.pager.MybatisPager;
 import org.apache.streampark.console.base.util.WebUtils;
+import org.apache.streampark.console.core.enums.AuthenticationType;
 import org.apache.streampark.console.system.authentication.JWTToken;
 import org.apache.streampark.console.system.authentication.JWTUtil;
 import org.apache.streampark.console.system.entity.AccessToken;
@@ -31,8 +31,6 @@ import org.apache.streampark.console.system.mapper.AccessTokenMapper;
 import org.apache.streampark.console.system.service.AccessTokenService;
 import org.apache.streampark.console.system.service.UserService;
 
-import org.apache.commons.lang3.StringUtils;
-
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
@@ -44,8 +42,6 @@ import org.springframework.transaction.annotation.Transactional;
 
 import java.util.Date;
 import java.util.List;
-import java.util.Objects;
-import java.util.TimeZone;
 
 @Slf4j
 @Service
@@ -56,24 +52,22 @@ public class AccessTokenServiceImpl extends ServiceImpl<AccessTokenMapper, Acces
   @Autowired private UserService userService;
 
   @Override
-  public RestResponse generateToken(Long userId, String expireTime, String description) {
+  public RestResponse create(Long userId, String description) {
     User user = userService.getById(userId);
-    if (Objects.isNull(user)) {
-      return RestResponse.success().put(RestResponse.CODE_KEY, 0).message("user not available");
-    }
-
-    if (StringUtils.isBlank(expireTime)) {
-      expireTime = AccessToken.DEFAULT_EXPIRE_TIME;
+    if (user == null) {
+      return RestResponse.success().put("code", 0).message("user not available");
     }
-    Long ttl = DateUtils.getTime(expireTime, DateUtils.fullFormat(), TimeZone.getDefault());
-    String token = WebUtils.encryptToken(JWTUtil.sign(user.getUserId(), user.getUsername(), ttl));
-    JWTToken jwtToken = new JWTToken(token, expireTime);
+    String token =
+        WebUtils.encryptToken(
+            JWTUtil.sign(
+                user.getUserId(), user.getUsername(), user.getSalt(), AuthenticationType.OPENAPI));
+    JWTToken jwtToken = new JWTToken(token, AccessToken.DEFAULT_EXPIRE_TIME);
 
     AccessToken accessToken = new AccessToken();
     accessToken.setToken(jwtToken.getToken());
     accessToken.setUserId(user.getUserId());
     accessToken.setDescription(description);
-    accessToken.setExpireTime(DateUtils.stringToDate(jwtToken.getExpireAt()));
+
     Date date = new Date();
     accessToken.setCreateTime(date);
     accessToken.setModifyTime(date);
@@ -101,7 +95,7 @@ public class AccessTokenServiceImpl extends ServiceImpl<AccessTokenMapper, Acces
   @Override
   public RestResponse toggleToken(Long tokenId) {
     AccessToken tokenInfo = baseMapper.selectById(tokenId);
-    if (Objects.isNull(tokenInfo)) {
+    if (tokenInfo == null) {
       return RestResponse.fail(ResponseCode.CODE_FAIL_ALERT, "accessToken could not be found!");
     }
 
@@ -116,8 +110,11 @@ public class AccessTokenServiceImpl extends ServiceImpl<AccessTokenMapper, Acces
             ? AccessToken.STATUS_DISABLE
             : AccessToken.STATUS_ENABLE;
 
-    tokenInfo.setStatus(status);
-    return RestResponse.success(this.updateById(tokenInfo));
+    AccessToken updateObj = new AccessToken();
+    updateObj.setStatus(status);
+    updateObj.setId(tokenId);
+    updateObj.setModifyTime(new Date());
+    return RestResponse.success(this.updateById(updateObj));
   }
 
   @Override
diff --git a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/service/impl/TeamServiceImpl.java b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/service/impl/TeamServiceImpl.java
index ac7142380..648ad9ebc 100644
--- a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/service/impl/TeamServiceImpl.java
+++ b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/service/impl/TeamServiceImpl.java
@@ -21,8 +21,8 @@ import org.apache.streampark.console.base.domain.RestRequest;
 import org.apache.streampark.console.base.exception.ApiAlertException;
 import org.apache.streampark.console.base.mybatis.pager.MybatisPager;
 import org.apache.streampark.console.core.enums.UserTypeEnum;
-import org.apache.streampark.console.core.service.CommonService;
 import org.apache.streampark.console.core.service.ProjectService;
+import org.apache.streampark.console.core.service.ServiceHelper;
 import org.apache.streampark.console.core.service.VariableService;
 import org.apache.streampark.console.core.service.application.ApplicationInfoService;
 import org.apache.streampark.console.system.entity.Team;
@@ -61,7 +61,7 @@ public class TeamServiceImpl extends ServiceImpl<TeamMapper, Team> implements Te
 
   @Autowired private VariableService variableService;
 
-  @Autowired private CommonService commonService;
+  @Autowired private ServiceHelper serviceHelper;
 
   @Override
   public IPage<Team> getPage(Team team, RestRequest request) {
@@ -93,7 +93,7 @@ public class TeamServiceImpl extends ServiceImpl<TeamMapper, Team> implements Te
 
   @Override
   public void removeById(Long teamId) {
-    log.info("{} Proceed delete team[Id={}]", commonService.getCurrentUser().getUsername(), teamId);
+    log.info("{} Proceed delete team[Id={}]", serviceHelper.getLoginUser().getUsername(), teamId);
     Team team = this.getById(teamId);
 
     ApiAlertException.throwIfNull(team, "The team[Id=%s] doesn't exist.", teamId);
diff --git a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/service/impl/UserServiceImpl.java b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/service/impl/UserServiceImpl.java
index 8ce251619..693ea809f 100644
--- a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/service/impl/UserServiceImpl.java
+++ b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/system/service/impl/UserServiceImpl.java
@@ -24,9 +24,9 @@ import org.apache.streampark.console.base.domain.RestRequest;
 import org.apache.streampark.console.base.domain.RestResponse;
 import org.apache.streampark.console.base.exception.ApiAlertException;
 import org.apache.streampark.console.base.mybatis.pager.MybatisPager;
-import org.apache.streampark.console.base.properties.ShiroProperties;
 import org.apache.streampark.console.base.util.ShaHashUtils;
 import org.apache.streampark.console.base.util.WebUtils;
+import org.apache.streampark.console.core.enums.AuthenticationType;
 import org.apache.streampark.console.core.enums.LoginTypeEnum;
 import org.apache.streampark.console.core.service.ResourceService;
 import org.apache.streampark.console.core.service.application.ApplicationInfoService;
@@ -80,8 +80,6 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
 
   @Autowired private ResourceService resourceService;
 
-  @Autowired private ShiroProperties shiroProperties;
-
   @Override
   public User getByUsername(String username) {
     LambdaQueryWrapper<User> queryWrapper =
@@ -239,34 +237,6 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
     return baseMapper.selectUsersByAppOwner(teamId);
   }
 
-  /**
-   * generate user info, contains: 1.token, 2.vue router, 3.role, 4.permission, 5.personalized
-   * config info of frontend
-   *
-   * @param user user
-   * @return UserInfo
-   */
-  @Override
-  public Map<String, Object> generateFrontendUserInfo(User user, Long teamId, JWTToken token) {
-    Map<String, Object> userInfo = new HashMap<>(8);
-
-    // 1) token & expire
-    if (token != null) {
-      userInfo.put("token", token.getToken());
-      userInfo.put("expire", token.getExpireAt());
-    }
-
-    // 2) user
-    user.dataMasking();
-    userInfo.put("user", user);
-
-    // 3) permissions
-    Set<String> permissions = this.listPermissions(user.getUserId(), teamId);
-    userInfo.put("permissions", permissions);
-
-    return userInfo;
-  }
-
   @Override
   public void transferResource(Long userId, Long targetUserId) {
     applicationManageService.changeOwnership(userId, targetUserId);
@@ -293,8 +263,11 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
     }
 
     updateLoginTime(user.getUsername());
-    String token = WebUtils.encryptToken(JWTUtil.sign(user.getUserId(), user.getUsername()));
-    LocalDateTime expireTime = LocalDateTime.now().plusSeconds(shiroProperties.getJwtTimeOut());
+    String token =
+        WebUtils.encryptToken(
+            JWTUtil.sign(
+                user.getUserId(), user.getUsername(), user.getSalt(), AuthenticationType.SIGN));
+    LocalDateTime expireTime = LocalDateTime.now().plusSeconds(JWTUtil.getTTLOfSecond());
     String expireTimeStr = DateUtils.formatFullTime(expireTime);
     JWTToken jwtToken = new JWTToken(token, expireTimeStr);
     String userId = RandomStringUtils.randomAlphanumeric(20);
@@ -302,4 +275,39 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
     Map<String, Object> userInfo = generateFrontendUserInfo(user, user.getLastTeamId(), jwtToken);
     return RestResponse.success(userInfo);
   }
+
+  @Override
+  @Transactional(rollbackFor = Exception.class)
+  public void deleteUser(Long userId) {
+    removeById(userId);
+    this.memberService.removeByUserId(userId);
+  }
+
+  /**
+   * generate user info, contains: 1.token, 2.vue router, 3.role, 4.permission, 5.personalized
+   * config info of frontend
+   *
+   * @param user user
+   * @return UserInfo
+   */
+  @Override
+  public Map<String, Object> generateFrontendUserInfo(User user, Long teamId, JWTToken token) {
+    Map<String, Object> userInfo = new HashMap<>(8);
+
+    // 1) token & expire
+    if (token != null) {
+      userInfo.put("token", token.getToken());
+      userInfo.put("expire", token.getExpireAt());
+    }
+
+    // 2) user
+    user.dataMasking();
+    userInfo.put("user", user);
+
+    // 3) permissions
+    Set<String> permissions = this.listPermissions(user.getUserId(), teamId);
+    userInfo.put("permissions", permissions);
+
+    return userInfo;
+  }
 }
diff --git a/streampark-console/streampark-console-service/src/main/resources/mapper/core/ApplicationMapper.xml b/streampark-console/streampark-console-service/src/main/resources/mapper/core/ApplicationMapper.xml
index 6ae24e824..5fc3f338c 100644
--- a/streampark-console/streampark-console-service/src/main/resources/mapper/core/ApplicationMapper.xml
+++ b/streampark-console/streampark-console-service/src/main/resources/mapper/core/ApplicationMapper.xml
@@ -27,7 +27,6 @@
         <result column="dynamic_properties" jdbcType="LONGVARCHAR" property="dynamicProperties"/>
         <result column="hot_params" jdbcType="VARCHAR" property="hotParams"/>
         <result column="job_name" jdbcType="VARCHAR" property="jobName"/>
-        <result column="app_id" jdbcType="VARCHAR" property="appId"/>
         <result column="version_id" jdbcType="BIGINT" property="versionId"/>
         <result column="cluster_id" jdbcType="VARCHAR" property="clusterId"/>
         <result column="flink_cluster_id" jdbcType="BIGINT" property="flinkClusterId"/>
@@ -119,15 +118,15 @@
 
     <select id="selectPage" resultType="org.apache.streampark.console.core.entity.Application" parameterType="org.apache.streampark.console.core.entity.Application">
         select
-            t.*,
-            p.name as projectName,
-            u.username,
-           case
-               when trim(u.nick_name) = ''
-                   then u.username
-               else u.nick_name
-            end as nickname,
-            v.version as flinkVersion
+        t.*,
+        p.name as projectName,
+        u.username,
+        case
+        when trim(u.nick_name) = ''
+        then u.username
+        else u.nick_name
+        end as nickname,
+        v.version as flinkVersion
         from t_flink_app t
         inner join t_user u
         on t.user_id = u.user_id
@@ -150,18 +149,24 @@
                 and t.execution_mode = #{app.executionMode}
             </if>
             <if test="app.jobName != null and app.jobName != ''">
-                and t.job_name like concat('%', '${app.jobName}', '%')
+                <if test="_databaseId == 'mysql'">
+                    and t.job_name like concat('%', #{app.jobName},'%')
+                </if>
+                <if test="_databaseId == 'pgsql'">
+                    and t.job_name like '%' || #{app.jobName} || '%'
+                </if>
             </if>
             <if test="app.projectName != null and app.projectName != ''">
-                and p.name like concat('%', '${app.projectName}', '%')
-            </if>
-            <if test="app.appId != null and app.appId != ''">
-                and t.app_id = #{app.appId}
+                <if test="_databaseId == 'mysql'">
+                    and p.name like concat('%', #{app.projectName},'%')
+                </if>
+                <if test="_databaseId == 'pgsql'">
+                    and p.name like '%' || #{app.projectName} || '%'
+                </if>
             </if>
             <if test="app.state != null and app.state != ''">
                 and t.state = #{app.state}
             </if>
-
             <if test="app.userId != null and app.userId != ''">
                 and t.user_id = #{app.userId}
             </if>
@@ -172,7 +177,12 @@
                 </foreach>
             </if>
             <if test="app.tags != null and app.tags != ''">
-                and t.tags like concat('%', '${app.tags}', '%')
+                <if test="_databaseId == 'mysql'">
+                    and t.tags like concat('%', #{app.tags},'%')
+                </if>
+                <if test="_databaseId == 'pgsql'">
+                    and t.tags like '%' || #{app.tags} || '%'
+                </if>
             </if>
         </where>
     </select>
@@ -273,12 +283,12 @@
     <update id="mapping" parameterType="org.apache.streampark.console.core.entity.Application">
         update t_flink_app
         <set>
+            <if test="app.clusterId != null">
+                cluster_id=#{app.clusterId},
+            </if>
             <if test="app.jobId != null">
                 job_id=#{app.jobId},
             </if>
-            <if test="app.appId != null">
-                app_id=#{app.appId},
-            </if>
             end_time=null,
             state=14,
             tracking=1
diff --git a/streampark-console/streampark-console-service/src/main/resources/mapper/core/ProjectMapper.xml b/streampark-console/streampark-console-service/src/main/resources/mapper/core/ProjectMapper.xml
index 35a081d96..4a44e82c1 100644
--- a/streampark-console/streampark-console-service/src/main/resources/mapper/core/ProjectMapper.xml
+++ b/streampark-console/streampark-console-service/src/main/resources/mapper/core/ProjectMapper.xml
@@ -82,7 +82,12 @@
         <where>
             t.team_id = #{project.teamId}
             <if test="project.name != null and project.name != ''">
-                and t.name like concat('%', '${project.name}', '%')
+                <if test="_databaseId == 'mysql'">
+                    and t.name like concat('%', #{project.name},'%')
+                </if>
+                <if test="_databaseId == 'pgsql'">
+                    and t.name like '%' || #{project.name} || '%'
+                </if>
             </if>
             <if test="project.buildState != null">
                 and t.build_state = #{project.buildState}
diff --git a/streampark-console/streampark-console-service/src/main/resources/mapper/core/VariableMapper.xml b/streampark-console/streampark-console-service/src/main/resources/mapper/core/VariableMapper.xml
index 8a6cd73dc..3b3c1e15a 100644
--- a/streampark-console/streampark-console-service/src/main/resources/mapper/core/VariableMapper.xml
+++ b/streampark-console/streampark-console-service/src/main/resources/mapper/core/VariableMapper.xml
@@ -31,17 +31,27 @@
 
     <select id="selectPage" resultType="org.apache.streampark.console.core.entity.Variable" parameterType="org.apache.streampark.console.core.entity.Variable">
         select
-            v.*,
-            u.username as creatorName
+        v.*,
+        u.username as creatorName
         from t_variable v
         inner join t_user u
         on v.creator_id = u.user_id
-        and v.team_id = ${variable.teamId}
+        and v.team_id = #{variable.teamId}
         <if test="variable.description != null and variable.description != ''">
-            and v.description like concat('%', '${variable.description}', '%')
+            <if test="_databaseId == 'mysql'">
+                and v.description like concat('%', #{variable.description},'%')
+            </if>
+            <if test="_databaseId == 'pgsql'">
+                and v.description like '%' || #{variable.description} || '%'
+            </if>
         </if>
         <if test="variable.variableCode != null and variable.variableCode != ''">
-            and v.variable_code like concat('%', '${variable.variableCode}', '%')
+            <if test="_databaseId == 'mysql'">
+                and v.variable_code like concat('%', #{variable.variableCode},'%')
+            </if>
+            <if test="_databaseId == 'pgsql'">
+                and v.variable_code like '%' || #{variable.variableCode} || '%'
+            </if>
         </if>
     </select>
 
@@ -61,7 +71,12 @@
         <where>
             team_id = #{teamId}
             <if test="keyword != null and keyword != ''">
-                and variable_code like concat('%', '${keyword}', '%') or description like concat('%', '${keyword}', '%')
+                <if test="_databaseId == 'mysql'">
+                    and variable_code like concat('%', #{keyword}, '%') or description like concat('%', #{keyword}, '%')
+                </if>
+                <if test="_databaseId == 'pgsql'">
+                    and variable_code like '%' || #{keyword} || '%' or description like '%' || #{keyword} || '%'
+                </if>
             </if>
         </where>
     </select>
diff --git a/streampark-console/streampark-console-service/src/main/resources/mapper/core/YarnQueueMapper.xml b/streampark-console/streampark-console-service/src/main/resources/mapper/core/YarnQueueMapper.xml
index 3ec49ac6b..93e2dff1a 100644
--- a/streampark-console/streampark-console-service/src/main/resources/mapper/core/YarnQueueMapper.xml
+++ b/streampark-console/streampark-console-service/src/main/resources/mapper/core/YarnQueueMapper.xml
@@ -33,7 +33,12 @@
                 team_id = #{yarnQueue.teamId}
             </if>
             <if test="yarnQueue.queueLabel != null and yarnQueue.queueLabel != ''">
-                and queue_label like concat('%', '${yarnQueue.queueLabel}', '%')
+                <if test="_databaseId == 'mysql'">
+                    and queue_label like concat('%', #{yarnQueue.queueLabel},'%')
+                </if>
+                <if test="_databaseId == 'pgsql'">
+                    and queue_label like '%' || #{yarnQueue.queueLabel} || '%'
+                </if>
             </if>
             <if test="yarnQueue.createTimeFrom != null and yarnQueue.createTimeFrom !=''">
                 and create_time &gt; #{yarnQueue.createTimeFrom}
diff --git a/streampark-console/streampark-console-service/src/main/resources/mapper/system/MemberMapper.xml b/streampark-console/streampark-console-service/src/main/resources/mapper/system/MemberMapper.xml
index 40f2b4136..df0f63f52 100644
--- a/streampark-console/streampark-console-service/src/main/resources/mapper/system/MemberMapper.xml
+++ b/streampark-console/streampark-console-service/src/main/resources/mapper/system/MemberMapper.xml
@@ -49,12 +49,17 @@
         join t_role r
         on r.role_id = tur.role_id
         <where>
-            tur.team_id = ${member.teamId}
+            tur.team_id = #{member.teamId}
             <if test="member.userName != null and member.userName != ''">
-                and u.username like concat('%', '${member.userName}', '%')
+                <if test="_databaseId == 'mysql'">
+                    and u.username like concat('%', #{member.userName},'%')
+                </if>
+                <if test="_databaseId == 'pgsql'">
+                    and u.username like '%' || #{member.userName} || '%'
+                </if>
             </if>
             <if test="member.roleName != null and member.roleName != ''">
-                and r.role_name = ${member.roleName}
+                and r.role_name = #{member.roleName}
             </if>
             <if test="member.createTimeFrom != null and member.createTimeFrom !=''">
                 and tur.create_time &gt; #{member.createTimeFrom}
diff --git a/streampark-console/streampark-console-service/src/main/resources/mapper/system/RoleMapper.xml b/streampark-console/streampark-console-service/src/main/resources/mapper/system/RoleMapper.xml
index 078181be0..f38c1ead9 100644
--- a/streampark-console/streampark-console-service/src/main/resources/mapper/system/RoleMapper.xml
+++ b/streampark-console/streampark-console-service/src/main/resources/mapper/system/RoleMapper.xml
@@ -29,7 +29,12 @@
         select * from t_role
         <where>
             <if test="role.roleName != null and role.roleName != ''">
-                and role_name like concat('%', '${role.roleName}', '%')
+                <if test="_databaseId == 'mysql'">
+                    and role_name like concat('%', #{role.roleName},'%')
+                </if>
+                <if test="_databaseId == 'pgsql'">
+                    and role_name like '%' || #{role.roleName} || '%'
+                </if>
             </if>
             <if test="role.createTimeFrom != null and role.createTimeFrom !=''">
                 and  create_time &gt; #{role.createTimeFrom}
diff --git a/streampark-console/streampark-console-service/src/main/resources/mapper/system/TeamMapper.xml b/streampark-console/streampark-console-service/src/main/resources/mapper/system/TeamMapper.xml
index a09de5bde..f06e222f4 100644
--- a/streampark-console/streampark-console-service/src/main/resources/mapper/system/TeamMapper.xml
+++ b/streampark-console/streampark-console-service/src/main/resources/mapper/system/TeamMapper.xml
@@ -29,7 +29,12 @@
         select * from t_team
         <where>
             <if test="team.teamName != null and team.teamName != ''">
-                and team_name like concat('%', '${team.teamName}', '%')
+                <if test="_databaseId == 'mysql'">
+                    and team_name like concat('%', #{team.teamName},'%')
+                </if>
+                <if test="_databaseId == 'pgsql'">
+                    and team_name like '%' || #{team.teamName} || '%'
+                </if>
             </if>
             <if test="team.createTimeFrom != null and team.createTimeFrom !=''">
                 and create_time &gt; #{team.createTimeFrom}
diff --git a/streampark-console/streampark-console-service/src/main/resources/mapper/system/UserMapper.xml b/streampark-console/streampark-console-service/src/main/resources/mapper/system/UserMapper.xml
index 3e8f158c3..317237d31 100644
--- a/streampark-console/streampark-console-service/src/main/resources/mapper/system/UserMapper.xml
+++ b/streampark-console/streampark-console-service/src/main/resources/mapper/system/UserMapper.xml
@@ -23,7 +23,6 @@
         <result column="nick_name" jdbcType="VARCHAR" property="nickName"/>
         <result column="password" jdbcType="VARCHAR" property="password"/>
         <result column="email" jdbcType="VARCHAR" property="email"/>
-        <result column="mobile" jdbcType="VARCHAR" property="mobile"/>
         <result column="status" jdbcType="CHAR" property="status"/>
         <result column="create_time" jdbcType="TIMESTAMP" property="createTime"/>
         <result column="modify_time" jdbcType="TIMESTAMP" property="modifyTime"/>
@@ -34,38 +33,87 @@
         <result column="login_type" jdbcType="INTEGER" property="loginType"/>
     </resultMap>
 
+    <sql id="userColumn">
+        u.user_id,
+        u.username,
+        u.nick_name,
+        u.user_type,
+        u.login_type,
+        u.status,
+        u.email,
+        u.create_time,
+        u.modify_time,
+        u.sex,
+        u.description
+    </sql>
+
     <select id="selectPage" resultType="org.apache.streampark.console.system.entity.User" parameterType="org.apache.streampark.console.system.entity.User">
-        select * from t_user
+        select <include refid="userColumn"></include>
+        from t_user u
+        <where>
+            <if test="user.username != null and user.username != ''">
+                <if test="_databaseId == 'mysql'">
+                    and u.username like concat('%', #{user.username},'%')
+                </if>
+                <if test="_databaseId == 'pgsql'">
+                    and u.username like '%' || #{user.username} || '%'
+                </if>
+            </if>
+            <if test="user.createTimeFrom != null and user.createTimeFrom !=''">
+                and u.create_time &gt; #{user.createTimeFrom}
+            </if>
+            <if test="user.createTimeTo!= null and user.createTimeTo !=''">
+                and u.create_time &lt; #{user.createTimeTo}
+            </if>
+            <if test="user.sex != null and user.sex != ''">
+                and u.sex = #{user.sex}
+            </if>
+            <if test="user.status != null and user.status != ''">
+                and u.status = #{user.status}
+            </if>
+        </where>
+    </select>
+
+    <select id="findUserDetail" resultType="org.apache.streampark.console.system.entity.User" parameterType="org.apache.streampark.console.system.entity.User">
+        select <include refid="userColumn"></include>
+        from t_user u
         <where>
             <if test="user.username != null and user.username != ''">
-                and username like concat('%', '${user.username}', '%')
+                <if test="_databaseId == 'mysql'">
+                    and u.username like concat('%', #{user.username},'%')
+                </if>
+                <if test="_databaseId == 'pgsql'">
+                    and u.username like '%' || #{user.username} || '%'
+                </if>
             </if>
             <if test="user.createTimeFrom != null and user.createTimeFrom !=''">
-                and create_time &gt; #{user.createTimeFrom}
+                and u.create_time &gt; #{user.createTimeFrom}
             </if>
             <if test="user.createTimeTo!= null and user.createTimeTo !=''">
-                and create_time &lt; #{user.createTimeTo}
+                and u.create_time &lt; #{user.createTimeTo}
             </if>
             <if test="user.sex != null and user.sex != ''">
-                and sex = #{user.sex}
+                and u.sex = #{user.sex}
             </if>
             <if test="user.status != null and user.status != ''">
-                and status = #{user.status}
+                and u.status = #{user.status}
             </if>
         </where>
     </select>
 
     <select id="selectNoTokenUsers" resultType="org.apache.streampark.console.system.entity.User" parameterType="org.apache.streampark.console.system.entity.User">
-        select u.* from t_user u left join t_access_token t
+        select <include refid="userColumn"></include>
+        from t_user u left join t_access_token t
         on u.user_id = t.user_id
         where t.user_id is null
     </select>
 
     <select id="selectUsersByAppOwner" resultType="org.apache.streampark.console.system.entity.User" parameterType="org.apache.streampark.console.system.entity.User">
-        select u.* from t_user u inner join (
-            select distinct(user_id) as user_id
-            from t_flink_app
-            where team_id = #{teamId}
+        select <include refid="userColumn"></include>
+        from t_user u inner join (
+        select distinct(user_id) as user_id
+        from t_flink_app
+        where team_id = #{teamId}
         ) t
         on u.user_id = t.user_id
     </select>
diff --git a/streampark-console/streampark-console-service/src/test/java/org/apache/streampark/console/core/service/AccessTokenServiceTest.java b/streampark-console/streampark-console-service/src/test/java/org/apache/streampark/console/core/service/AccessTokenServiceTest.java
index 8d8efed20..3793de6ef 100644
--- a/streampark-console/streampark-console-service/src/test/java/org/apache/streampark/console/core/service/AccessTokenServiceTest.java
+++ b/streampark-console/streampark-console-service/src/test/java/org/apache/streampark/console/core/service/AccessTokenServiceTest.java
@@ -43,7 +43,7 @@ public class AccessTokenServiceTest extends SpringUnitTestBase {
   void testCrudToken() throws Exception {
     Long mockUserId = 100000L;
     String expireTime = "9999-01-01 00:00:00";
-    RestResponse restResponse = accessTokenService.generateToken(mockUserId, expireTime, "");
+    RestResponse restResponse = accessTokenService.create(mockUserId, "");
     Assertions.assertNotNull(restResponse);
     Assertions.assertInstanceOf(AccessToken.class, restResponse.get(RestResponse.DATA_KEY));
 
@@ -57,7 +57,7 @@ public class AccessTokenServiceTest extends SpringUnitTestBase {
     Assertions.assertEquals("admin", username);
     User user = userService.getByUsername(username);
     Assertions.assertNotNull(user);
-    Assertions.assertTrue(JWTUtil.verify(jwtToken.getToken(), username));
+    Assertions.assertTrue(JWTUtil.verify(jwtToken.getToken(), username, user.getSalt()));
 
     // list
     AccessToken mockToken1 = new AccessToken();
diff --git a/streampark-console/streampark-console-service/src/test/java/org/apache/streampark/console/core/service/alert/AlertServiceTest.java b/streampark-console/streampark-console-service/src/test/java/org/apache/streampark/console/core/service/alert/AlertServiceTest.java
index c529e02bb..b44b4bf67 100644
--- a/streampark-console/streampark-console-service/src/test/java/org/apache/streampark/console/core/service/alert/AlertServiceTest.java
+++ b/streampark-console/streampark-console-service/src/test/java/org/apache/streampark/console/core/service/alert/AlertServiceTest.java
@@ -159,7 +159,7 @@ class AlertServiceTest {
     Application application = new Application();
     application.setStartTime(new Date());
     application.setJobName("Test My Job");
-    application.setAppId("1234567890");
+    application.setClusterId("1234567890");
     application.setAlertId(1L);
 
     application.setRestartCount(5);
@@ -202,7 +202,7 @@ class AlertServiceTest {
       duration = application.getEndTime().getTime() - application.getStartTime().getTime();
     }
     String format = "%s/proxy/%s/";
-    String url = String.format(format, YarnUtils.getRMWebAppURL(false), application.getAppId());
+    String url = String.format(format, YarnUtils.getRMWebAppURL(false), application.getClusterId());
 
     AlertTemplate template = new AlertTemplate();
     template.setJobName(application.getJobName());
diff --git a/streampark-console/streampark-console-service/src/test/java/org/apache/streampark/console/system/authentication/JWTTest.java b/streampark-console/streampark-console-service/src/test/java/org/apache/streampark/console/system/authentication/JWTTest.java
index e3501841f..c59cba3ed 100644
--- a/streampark-console/streampark-console-service/src/test/java/org/apache/streampark/console/system/authentication/JWTTest.java
+++ b/streampark-console/streampark-console-service/src/test/java/org/apache/streampark/console/system/authentication/JWTTest.java
@@ -19,6 +19,7 @@ package org.apache.streampark.console.system.authentication;
 
 import org.apache.streampark.common.util.DateUtils;
 import org.apache.streampark.console.SpringUnitTestBase;
+import org.apache.streampark.console.core.enums.AuthenticationType;
 import org.apache.streampark.console.system.entity.AccessToken;
 
 import com.auth0.jwt.JWT;
@@ -38,6 +39,8 @@ class JWTTest extends SpringUnitTestBase {
         JWTUtil.sign(
             10000L,
             userName,
+            "streampark",
+            AuthenticationType.SIGN,
             DateUtils.getTime(expireTime, DateUtils.fullFormat(), TimeZone.getDefault()));
 
     assert token != null;
diff --git a/streampark-console/streampark-console-webapp/src/api/flink/flinkSql.ts b/streampark-console/streampark-console-webapp/src/api/flink/flinkSql.ts
index 1ec71f79e..e4af1df51 100644
--- a/streampark-console/streampark-console-webapp/src/api/flink/flinkSql.ts
+++ b/streampark-console/streampark-console-webapp/src/api/flink/flinkSql.ts
@@ -43,7 +43,7 @@ export function fetchFlinkSqlList(data) {
   });
 }
 
-export function fetchRemoveFlinkSql(data: { id: string }): Promise<boolean> {
+export function fetchRemoveFlinkSql(data: { appId: any; id: any }): Promise<boolean> {
   return defHttp.post({
     url: FLINK_SQL_API.DELETE,
     data,
diff --git a/streampark-console/streampark-console-webapp/src/api/flink/savepoint.ts b/streampark-console/streampark-console-webapp/src/api/flink/savepoint.ts
index 359b53136..b4964f6e3 100644
--- a/streampark-console/streampark-console-webapp/src/api/flink/savepoint.ts
+++ b/streampark-console/streampark-console-webapp/src/api/flink/savepoint.ts
@@ -34,7 +34,7 @@ export function fetchSavePonitHistory(data: Recordable) {
  * @param data id
  * @returns {Promise<boolean>}
  */
-export function fetchRemoveSavePoint(data: { id: string }): Promise<boolean> {
+export function fetchRemoveSavePoint(data: { appId: any; id: any }): Promise<boolean> {
   return defHttp.post({
     url: SAVE_POINT_API.DELETE,
     data,
diff --git a/streampark-console/streampark-console-webapp/src/api/system/model/tokenModel.ts b/streampark-console/streampark-console-webapp/src/api/system/model/tokenModel.ts
index 6997d8e30..7805e6592 100644
--- a/streampark-console/streampark-console-webapp/src/api/system/model/tokenModel.ts
+++ b/streampark-console/streampark-console-webapp/src/api/system/model/tokenModel.ts
@@ -20,7 +20,6 @@ export interface TokenListRecord {
   userId: string;
   token: string;
   status: number;
-  expireTime: string;
   description: string;
   createTime: string;
   modifyTime: string;
@@ -32,6 +31,5 @@ export interface TokenListRecord {
 export interface TokenCreateParam {
   userId: number;
   description: string;
-  expireTime: string;
   teamId: string;
 }
diff --git a/streampark-console/streampark-console-webapp/src/components/Application/src/AppDarkModeToggle.vue b/streampark-console/streampark-console-webapp/src/components/Application/src/AppDarkModeToggle.vue
index 19ba3b151..d4e0ce164 100644
--- a/streampark-console/streampark-console-webapp/src/components/Application/src/AppDarkModeToggle.vue
+++ b/streampark-console/streampark-console-webapp/src/components/Application/src/AppDarkModeToggle.vue
@@ -63,7 +63,9 @@
       height: 18px;
       background-color: #fff;
       border-radius: 50%;
-      transition: transform 0.5s, background-color 0.5s;
+      transition:
+        transform 0.5s,
+        background-color 0.5s;
       will-change: transform;
     }
 
diff --git a/streampark-console/streampark-console-webapp/src/components/ContextMenu/src/ContextMenu.vue b/streampark-console/streampark-console-webapp/src/components/ContextMenu/src/ContextMenu.vue
index e08c25f36..78cac5c5b 100644
--- a/streampark-console/streampark-console-webapp/src/components/ContextMenu/src/ContextMenu.vue
+++ b/streampark-console/streampark-console-webapp/src/components/ContextMenu/src/ContextMenu.vue
@@ -179,7 +179,9 @@
     background-color: @component-background;
     border: 1px solid rgb(0 0 0 / 8%);
     border-radius: 0.25rem;
-    box-shadow: 0 2px 2px 0 rgb(0 0 0 / 14%), 0 3px 1px -2px rgb(0 0 0 / 10%),
+    box-shadow:
+      0 2px 2px 0 rgb(0 0 0 / 14%),
+      0 3px 1px -2px rgb(0 0 0 / 10%),
       0 1px 5px 0 rgb(0 0 0 / 6%);
     background-clip: padding-box;
     user-select: none;
diff --git a/streampark-console/streampark-console-webapp/src/components/Form/src/BasicForm.vue b/streampark-console/streampark-console-webapp/src/components/Form/src/BasicForm.vue
index 1cd7e3809..e5a9dacf6 100644
--- a/streampark-console/streampark-console-webapp/src/components/Form/src/BasicForm.vue
+++ b/streampark-console/streampark-console-webapp/src/components/Form/src/BasicForm.vue
@@ -113,7 +113,7 @@
       });
 
       const getBindValue = computed(
-        () => ({ ...attrs, ...props, ...unref(getProps) } as Recordable),
+        () => ({ ...attrs, ...props, ...unref(getProps) }) as Recordable,
       );
 
       const getSchema = computed((): FormSchema[] => {
diff --git a/streampark-console/streampark-console-webapp/src/components/Form/src/components/FormItem.vue b/streampark-console/streampark-console-webapp/src/components/Form/src/components/FormItem.vue
index 137ae94d6..9bbb5023f 100644
--- a/streampark-console/streampark-console-webapp/src/components/Form/src/components/FormItem.vue
+++ b/streampark-console/streampark-console-webapp/src/components/Form/src/components/FormItem.vue
@@ -333,8 +333,8 @@
             return slot
               ? getSlot(slots, slot, unref(getValues))
               : render
-              ? render(unref(getValues))
-              : renderComponent();
+                ? render(unref(getValues))
+                : renderComponent();
           };
 
           const showSuffix = !!suffix;
@@ -382,8 +382,8 @@
           return colSlot
             ? getSlot(slots, colSlot, values)
             : renderColContent
-            ? renderColContent(values)
-            : renderItem();
+              ? renderColContent(values)
+              : renderItem();
         };
 
         return (
diff --git a/streampark-console/streampark-console-webapp/src/components/Modal/src/components/ModalWrapper.vue b/streampark-console/streampark-console-webapp/src/components/Modal/src/components/ModalWrapper.vue
index 1b1b9a613..52c8b5eb8 100644
--- a/streampark-console/streampark-console-webapp/src/components/Modal/src/components/ModalWrapper.vue
+++ b/streampark-console/streampark-console-webapp/src/components/Modal/src/components/ModalWrapper.vue
@@ -153,8 +153,8 @@
             realHeightRef.value = props.height
               ? props.height
               : realHeight > maxHeight
-              ? maxHeight
-              : realHeight;
+                ? maxHeight
+                : realHeight;
           }
           emit('height-change', unref(realHeightRef));
         } catch (error) {
diff --git a/streampark-console/streampark-console-webapp/src/components/Page/src/PageFooter.vue b/streampark-console/streampark-console-webapp/src/components/Page/src/PageFooter.vue
index e89a6ce97..8fdbc8f41 100644
--- a/streampark-console/streampark-console-webapp/src/components/Page/src/PageFooter.vue
+++ b/streampark-console/streampark-console-webapp/src/components/Page/src/PageFooter.vue
@@ -39,7 +39,9 @@
     line-height: 44px;
     background-color: @component-background;
     border-top: 1px solid @border-color-base;
-    box-shadow: 0 -6px 16px -8px rgb(0 0 0 / 8%), 0 -9px 28px 0 rgb(0 0 0 / 5%),
+    box-shadow:
+      0 -6px 16px -8px rgb(0 0 0 / 8%),
+      0 -9px 28px 0 rgb(0 0 0 / 5%),
       0 -12px 48px 16px rgb(0 0 0 / 3%);
     transition: width 0.2s;
 
diff --git a/streampark-console/streampark-console-webapp/src/components/Table/src/components/HeaderCell.vue b/streampark-console/streampark-console-webapp/src/components/Table/src/components/HeaderCell.vue
index 35c080269..36ab854c5 100644
--- a/streampark-console/streampark-console-webapp/src/components/Table/src/components/HeaderCell.vue
+++ b/streampark-console/streampark-console-webapp/src/components/Table/src/components/HeaderCell.vue
@@ -22,7 +22,7 @@
     props: {
       column: {
         type: Object as PropType<BasicColumn>,
-        default: () => ({} as BasicColumn),
+        default: () => ({}) as BasicColumn,
       },
     },
     setup(props) {
diff --git a/streampark-console/streampark-console-webapp/src/hooks/setting/useMenuSetting.ts b/streampark-console/streampark-console-webapp/src/hooks/setting/useMenuSetting.ts
index 3566bfd27..f501c6e80 100644
--- a/streampark-console/streampark-console-webapp/src/hooks/setting/useMenuSetting.ts
+++ b/streampark-console/streampark-console-webapp/src/hooks/setting/useMenuSetting.ts
@@ -105,8 +105,8 @@ export function useMenuSetting() {
     return siderHidden
       ? 0
       : collapsedShowTitle
-      ? SIDE_BAR_SHOW_TIT_MINI_WIDTH
-      : SIDE_BAR_MINI_WIDTH;
+        ? SIDE_BAR_SHOW_TIT_MINI_WIDTH
+        : SIDE_BAR_MINI_WIDTH;
   });
 
   const getCalcContentWidth = computed(() => {
@@ -114,9 +114,9 @@ export function useMenuSetting() {
       unref(getIsTopMenu) || !unref(getShowMenu) || (unref(getSplit) && unref(getMenuHidden))
         ? 0
         : unref(getIsMixSidebar)
-        ? (unref(getCollapsed) ? SIDE_BAR_MINI_WIDTH : SIDE_BAR_SHOW_TIT_MINI_WIDTH) +
-          (unref(getMixSideFixed) && unref(mixSideHasChildren) ? unref(getRealWidth) : 0)
-        : unref(getRealWidth);
+          ? (unref(getCollapsed) ? SIDE_BAR_MINI_WIDTH : SIDE_BAR_SHOW_TIT_MINI_WIDTH) +
+            (unref(getMixSideFixed) && unref(mixSideHasChildren) ? unref(getRealWidth) : 0)
+          : unref(getRealWidth);
 
     return `calc(100% - ${unref(width)}px)`;
   });
diff --git a/streampark-console/streampark-console-webapp/src/hooks/web/useLockPage.ts b/streampark-console/streampark-console-webapp/src/hooks/web/useLockPage.ts
index c543be954..9a6607421 100644
--- a/streampark-console/streampark-console-webapp/src/hooks/web/useLockPage.ts
+++ b/streampark-console/streampark-console-webapp/src/hooks/web/useLockPage.ts
@@ -32,9 +32,12 @@ export function useLockPage() {
     }
     clear();
 
-    timeId = setTimeout(() => {
-      lockPage();
-    }, lockTime * 60 * 1000);
+    timeId = setTimeout(
+      () => {
+        lockPage();
+      },
+      lockTime * 60 * 1000,
+    );
   }
 
   function lockPage(): void {
diff --git a/streampark-console/streampark-console-webapp/src/locales/lang/en/flink/app.ts b/streampark-console/streampark-console-webapp/src/locales/lang/en/flink/app.ts
index 3126f4940..d13a4989f 100644
--- a/streampark-console/streampark-console-webapp/src/locales/lang/en/flink/app.ts
+++ b/streampark-console/streampark-console-webapp/src/locales/lang/en/flink/app.ts
@@ -206,18 +206,25 @@ export default {
     sqlCheck: 'SQL check error',
   },
   operation: {
-    edit: 'Edit Application',
-    release: 'Release Application',
+    edit: 'Edit Job',
+    release: 'Release Job',
     releaseDetail: 'Releasing Progress Detail',
-    start: 'Start Application',
-    cancel: 'Cancel Application',
+    start: 'Start Job',
+    cancel: 'Cancel Job',
     savepoint: 'Trigger Savepoint',
     detail: 'View Detail',
     startLog: 'See Flink Start log',
-    force: 'Forced Stop Application',
-    copy: 'Copy Application',
-    remapping: 'Remapping Application',
+    force: 'Forced Stop Job',
+    copy: 'Copy Job',
+    remapping: 'Remapping Job',
     deleteTip: 'Are you sure delete this job ?',
+    triggerSavePoint: 'Trigger savepoint',
+    enableSavePoint: 'Trigger savepoint before flink job cancel',
+    customSavepoint: 'Specify savepoint path to cancel the job ',
+    enableDrain: 'Send MAX_WATERMARK before taking the savepoint and stopping the pipeline',
+    invalidSavePoint: 'Custom savepoint path invalid: ',
+    canceling: 'The current job is canceling',
+    starting: 'The current job is starting',
   },
   dashboard: {
     availableTaskSlots: 'Available Task Slots',
diff --git a/streampark-console/streampark-console-webapp/src/locales/lang/en/system/token.ts b/streampark-console/streampark-console-webapp/src/locales/lang/en/system/token.ts
index 175de6a58..9cff6b27f 100644
--- a/streampark-console/streampark-console-webapp/src/locales/lang/en/system/token.ts
+++ b/streampark-console/streampark-console-webapp/src/locales/lang/en/system/token.ts
@@ -24,7 +24,6 @@ export default {
     title: 'Token List',
     userName: 'User Name',
     token: 'Token',
-    expireTime: 'Expire Time',
     status: 'Status',
   },
   operation: {
diff --git a/streampark-console/streampark-console-webapp/src/locales/lang/zh-CN/flink/app.ts b/streampark-console/streampark-console-webapp/src/locales/lang/zh-CN/flink/app.ts
index f571b49c1..01660a4dc 100644
--- a/streampark-console/streampark-console-webapp/src/locales/lang/zh-CN/flink/app.ts
+++ b/streampark-console/streampark-console-webapp/src/locales/lang/zh-CN/flink/app.ts
@@ -206,6 +206,13 @@ export default {
     copy: '复制作业',
     remapping: '重新映射作业',
     deleteTip: '你确定要删除这个作业?',
+    triggerSavePoint: '触发 savepoint',
+    enableSavePoint: '在 Flink 作业取消之前触发 savepoint',
+    customSavepoint: '指定 savepoint 保存路径',
+    enableDrain: '在触发 savepoint 和停止作业之前发送 MAX_WATERMARK',
+    invalidSavePoint: 'savepoint 路径无效: ',
+    canceling: '当前作业正在停止中',
+    starting: '当前作业正在启动中',
   },
   dashboard: {
     availableTaskSlots: '可用的任务槽数',
diff --git a/streampark-console/streampark-console-webapp/src/locales/lang/zh-CN/system/token.ts b/streampark-console/streampark-console-webapp/src/locales/lang/zh-CN/system/token.ts
index 863711168..8e332a64d 100644
--- a/streampark-console/streampark-console-webapp/src/locales/lang/zh-CN/system/token.ts
+++ b/streampark-console/streampark-console-webapp/src/locales/lang/zh-CN/system/token.ts
@@ -24,7 +24,6 @@ export default {
     title: 'Token 列表',
     userName: '用户名',
     token: 'Token',
-    expireTime: '过期时间',
     status: '状态',
   },
   operation: {
diff --git a/streampark-console/streampark-console-webapp/src/utils/props.ts b/streampark-console/streampark-console-webapp/src/utils/props.ts
index 4a15ec465..150dd01f4 100644
--- a/streampark-console/streampark-console-webapp/src/utils/props.ts
+++ b/streampark-console/streampark-console-webapp/src/utils/props.ts
@@ -15,9 +15,8 @@ type ResolveProp<T> = ExtractPropTypes<{
   key: { type: T; required: true };
 }>['key'];
 type ResolvePropType<T> = ResolveProp<T> extends { type: infer V } ? V : ResolveProp<T>;
-type ResolvePropTypeWithReadonly<T> = Readonly<T> extends Readonly<Array<infer A>>
-  ? ResolvePropType<A[]>
-  : ResolvePropType<T>;
+type ResolvePropTypeWithReadonly<T> =
+  Readonly<T> extends Readonly<Array<infer A>> ? ResolvePropType<A[]> : ResolvePropType<T>;
 
 type IfUnknown<T, V> = [unknown] extends [T] ? V : T;
 
@@ -28,8 +27,8 @@ export type BuildPropOption<T, D extends BuildPropType<T, V, C>, R, V, C> = {
   default?: R extends true
     ? never
     : D extends Record<string, unknown> | Array<any>
-    ? () => D
-    : (() => D) | D;
+      ? () => D
+      : (() => D) | D;
   validator?: ((val: any) => val is C) | ((val: any) => boolean);
 };
 
@@ -37,8 +36,8 @@ type _BuildPropType<T, V, C> =
   | (T extends PropWrapper<unknown>
       ? T[typeof wrapperKey]
       : [V] extends [never]
-      ? ResolvePropTypeWithReadonly<T>
-      : never)
+        ? ResolvePropTypeWithReadonly<T>
+        : never)
   | V
   | C;
 export type BuildPropType<T, V, C> = _BuildPropType<
@@ -53,8 +52,8 @@ type _BuildPropDefault<T, D> = [T] extends [
 ]
   ? D
   : D extends () => T
-  ? ReturnType<D>
-  : D;
+    ? ReturnType<D>
+    : D;
 
 export type BuildPropDefault<T, D, R> = R extends true
   ? { readonly default?: undefined }
@@ -146,12 +145,12 @@ export const buildProps = <
     [K in keyof O]: O[K] extends BuildPropReturn<any, any, any, any, any>
       ? O[K]
       : [O[K]] extends NativePropType
-      ? O[K]
-      : O[K] extends BuildPropOption<infer T, infer D, infer R, infer V, infer C>
-      ? D extends BuildPropType<T, V, C>
-        ? BuildPropOption<T, D, R, V, C>
-        : never
-      : never;
+        ? O[K]
+        : O[K] extends BuildPropOption<infer T, infer D, infer R, infer V, infer C>
+          ? D extends BuildPropType<T, V, C>
+            ? BuildPropOption<T, D, R, V, C>
+            : never
+          : never;
   },
 >(
   props: O,
@@ -162,20 +161,20 @@ export const buildProps = <
     [K in keyof O]: O[K] extends { [propKey]: boolean }
       ? O[K]
       : [O[K]] extends NativePropType
-      ? O[K]
-      : O[K] extends BuildPropOption<
-          infer T,
-          // eslint-disable-next-line @typescript-eslint/no-unused-vars
-          infer _D,
-          infer R,
-          infer V,
-          infer C
-        >
-      ? BuildPropReturn<T, O[K]['default'], R, V, C>
-      : never;
+        ? O[K]
+        : O[K] extends BuildPropOption<
+              infer T,
+              // eslint-disable-next-line @typescript-eslint/no-unused-vars
+              infer _D,
+              infer R,
+              infer V,
+              infer C
+            >
+          ? BuildPropReturn<T, O[K]['default'], R, V, C>
+          : never;
   };
 
-export const definePropType = <T>(val: any) => ({ [wrapperKey]: val } as PropWrapper<T>);
+export const definePropType = <T>(val: any) => ({ [wrapperKey]: val }) as PropWrapper<T>;
 
 export const keyOf = <T extends Object>(arr: T) => Object.keys(arr) as Array<keyof T>;
 export const mutable = <T extends readonly any[] | Record<string, unknown>>(val: T) =>
diff --git a/streampark-console/streampark-console-webapp/src/views/base/error-log/data.tsx b/streampark-console/streampark-console-webapp/src/views/base/error-log/data.tsx
index 3ffc2f453..73120a425 100644
--- a/streampark-console/streampark-console-webapp/src/views/base/error-log/data.tsx
+++ b/streampark-console/streampark-console-webapp/src/views/base/error-log/data.tsx
@@ -16,12 +16,12 @@ export function getColumns(): BasicColumn[] {
           text === ErrorTypeEnum.VUE
             ? 'green'
             : text === ErrorTypeEnum.RESOURCE
-            ? 'cyan'
-            : text === ErrorTypeEnum.PROMISE
-            ? 'blue'
-            : ErrorTypeEnum.AJAX
-            ? 'red'
-            : 'purple';
+              ? 'cyan'
+              : text === ErrorTypeEnum.PROMISE
+                ? 'blue'
+                : ErrorTypeEnum.AJAX
+                  ? 'red'
+                  : 'purple';
         return <Tag color={color}>{() => text}</Tag>;
       },
     },
diff --git a/streampark-console/streampark-console-webapp/src/views/base/login/Login.vue b/streampark-console/streampark-console-webapp/src/views/base/login/Login.vue
index d34791923..0a3858392 100644
--- a/streampark-console/streampark-console-webapp/src/views/base/login/Login.vue
+++ b/streampark-console/streampark-console-webapp/src/views/base/login/Login.vue
@@ -15,7 +15,15 @@
   limitations under the License.
 -->
 <template>
-  <div class="h-full bg-gradient-primary overflow-auto">
+  <div class="relative h-full bg-gradient-primary overflow-auto">
+    <div class="flex items-center locale-picker-border absolute right-15 top-10">
+      <AppLocalePicker
+        class="text-white enter-x locale-picker"
+        v-if="getShowLocalePicker"
+        :reload="true"
+        :showText="false"
+      />
+    </div>
     <div class="w-full relative h-[calc(100%-120px)] min-h-700px flex items-center section">
       <div class="scribble-box w-[80%] h-full absolute overflow-hidden">
         <figure class="scribble scale-2 !opacity-10 top-50 left-0">
@@ -59,8 +67,9 @@
         />
       </a>
       <p class="text-light-100 pt-10px" style="border-top: 1px solid #dad7d7">
-        Copyright © 2022 The Apache Software Foundation. Apache StreamPark, StreamPark, and its
-        feather logo are trademarks of The Apache Software Foundation.
+        Copyright © 2022-{{ `${new Date().getFullYear()}` }} The Apache Software Foundation. Apache
+        StreamPark, StreamPark, and its feather logo are trademarks of The Apache Software
+        Foundation.
       </p>
     </footer>
   </div>
@@ -71,6 +80,8 @@
   import { useDesign } from '/@/hooks/web/useDesign';
   import { Row, Col } from 'ant-design-vue';
   import { SvgIcon } from '/@/components/Icon';
+  import { useLocale } from '/@/locales/useLocale';
+  import { AppLocalePicker } from '/@/components/Application';
   defineProps({
     sessionTimeout: {
       type: Boolean,
@@ -78,6 +89,7 @@
   });
 
   // const globSetting = useGlobSetting();
+  const { getShowLocalePicker } = useLocale();
   const { prefixCls } = useDesign('login');
   sessionStorage.removeItem('appPageNo');
   // const title = computed(() => globSetting?.title ?? '');
@@ -138,4 +150,13 @@
       }
     }
   }
+
+  .locale-picker-border {
+    border: 1px solid rgba(255, 255, 255, 0.6);
+    border-radius: 6px;
+  }
+
+  .locale-picker {
+    padding: 6px;
+  }
 </style>
diff --git a/streampark-console/streampark-console-webapp/src/views/base/login/LoginForm.vue b/streampark-console/streampark-console-webapp/src/views/base/login/LoginForm.vue
index ca3bc116a..ce7b1307e 100644
--- a/streampark-console/streampark-console-webapp/src/views/base/login/LoginForm.vue
+++ b/streampark-console/streampark-console-webapp/src/views/base/login/LoginForm.vue
@@ -68,7 +68,7 @@
     </FormItem>
 
     <FormItem class="enter-x text-left">
-      <Button :href="BASE_ADDRESS+SSO_LOGIN_PATH" type="link" v-if="enableSSO">
+      <Button :href="BASE_ADDRESS + SSO_LOGIN_PATH" type="link" v-if="enableSSO">
         {{ t('sys.login.ssoSignIn') }}
       </Button>
       <Button type="link" class="float-right" @click="changeLoginType" v-if="enableLDAP">
@@ -117,7 +117,7 @@
     account: string;
     password: string;
   }
-  const BASE_ADDRESS= import.meta.env.VITE_BASE_ADDRESS;
+  const BASE_ADDRESS = import.meta.env.VITE_BASE_ADDRESS;
   const formRef = ref();
   const loading = ref(false);
   const userId = ref('');
diff --git a/streampark-console/streampark-console-webapp/src/views/flink/app/EditFlink.vue b/streampark-console/streampark-console-webapp/src/views/flink/app/EditFlink.vue
index 23a6b9106..1aec48dab 100644
--- a/streampark-console/streampark-console-webapp/src/views/flink/app/EditFlink.vue
+++ b/streampark-console/streampark-console-webapp/src/views/flink/app/EditFlink.vue
@@ -100,10 +100,6 @@
         },
         versionId: app.versionId || null,
         k8sRestExposedType: app.k8sRestExposedType,
-        clusterId: app.clusterId,
-        [app.executionMode == ExecModeEnum.YARN_SESSION
-          ? 'yarnSessionClusterId'
-          : 'flinkClusterId']: app.flinkClusterId,
         flinkImage: app.flinkImage,
         k8sNamespace: app.k8sNamespace,
         alertId: selectAlertId,
@@ -114,6 +110,19 @@
       if (!executionMode) {
         Object.assign(defaultParams, { executionMode: app.executionMode });
       }
+      switch (app.executionMode) {
+        case ExecModeEnum.REMOTE:
+          defaultParams['remoteClusterId'] = app.flinkClusterId;
+          break;
+        case ExecModeEnum.YARN_SESSION:
+          defaultParams['yarnSessionClusterId'] = app.flinkClusterId;
+          break;
+        case ExecModeEnum.KUBERNETES_SESSION:
+          defaultParams['k8sSessionClusterId'] = app.flinkClusterId;
+          break;
+        default:
+          break;
+      }
       setFieldsValue(defaultParams);
       app.args && programArgRef.value?.setContent(app.args);
       setTimeout(() => {
diff --git a/streampark-console/streampark-console-webapp/src/views/flink/app/EditStreamPark.vue b/streampark-console/streampark-console-webapp/src/views/flink/app/EditStreamPark.vue
index 6231939a6..266e12109 100644
--- a/streampark-console/streampark-console-webapp/src/views/flink/app/EditStreamPark.vue
+++ b/streampark-console/streampark-console-webapp/src/views/flink/app/EditStreamPark.vue
@@ -76,7 +76,6 @@
   const {
     alerts,
     flinkEnvs,
-    flinkClusters,
     flinkSql,
     getEditStreamParkFormSchema,
     registerDifferentDrawer,
@@ -121,14 +120,23 @@
           cpFailureRateInterval: app.cpFailureRateInterval,
           cpFailureAction: app.cpFailureAction,
         },
-        clusterId: app.clusterId,
-        [app.executionMode == ExecModeEnum.YARN_SESSION
-          ? 'yarnSessionClusterId'
-          : 'flinkClusterId']: app.flinkClusterId,
         flinkImage: app.flinkImage,
         k8sNamespace: app.k8sNamespace,
         ...resetParams,
       };
+      switch (app.executionMode) {
+        case ExecModeEnum.REMOTE:
+          defaultParams['remoteClusterId'] = app.flinkClusterId;
+          break;
+        case ExecModeEnum.YARN_SESSION:
+          defaultParams['yarnSessionClusterId'] = app.flinkClusterId;
+          break;
+        case ExecModeEnum.KUBERNETES_SESSION:
+          defaultParams['k8sSessionClusterId'] = app.flinkClusterId;
+          break;
+        default:
+          break;
+      }
       if (!executionMode) {
         Object.assign(defaultParams, { executionMode: app.executionMode });
       }
@@ -206,14 +214,13 @@
         flinkSql: values.flinkSql,
         config,
         format: values.isSetConfig ? 1 : null,
-        teamResource: JSON.stringify(values.teamResource),
         dependency:
           dependency.pom === undefined && dependency.jar === undefined
             ? null
             : JSON.stringify(dependency),
       };
       handleSubmitParams(params, values, k8sTemplate);
-      handleUpdateApp(params);
+      await handleUpdateApp(params);
     } catch (error) {
       createMessage.error('edit error');
       submitLoading.value = false;
@@ -249,16 +256,6 @@
 
   /* Send submission interface */
   async function handleUpdateApp(params: Recordable) {
-    if (params.executionMode == ExecModeEnum.KUBERNETES_SESSION) {
-      const cluster =
-        unref(flinkClusters).filter((c) => {
-          return c.id == params.flinkClusterId && c.clusterState === ClusterStateEnum.RUNNING;
-        })[0] || null;
-      if (cluster) {
-        Object.assign(params, { clusterId: cluster.clusterId });
-      }
-    }
-
     try {
       const updated = await fetchUpdate(params);
       if (updated) {
diff --git a/streampark-console/streampark-console-webapp/src/views/flink/app/View.vue b/streampark-console/streampark-console-webapp/src/views/flink/app/View.vue
index 66ebdfd16..bd9b9fc16 100644
--- a/streampark-console/streampark-console-webapp/src/views/flink/app/View.vue
+++ b/streampark-console/streampark-console-webapp/src/views/flink/app/View.vue
@@ -194,11 +194,6 @@
     optionApps,
   );
 
-  // build Detail
-  function openBuildProgressDetailDrawer(app: AppListRecord) {
-    openBuildDrawer(true, { appId: app.id });
-  }
-
   /* view */
   async function handleJobView(app: AppListRecord) {
     // Task is running, restarting, in savePoint
diff --git a/streampark-console/streampark-console-webapp/src/views/flink/app/components/AppConf.tsx b/streampark-console/streampark-console-webapp/src/views/flink/app/components/AppConf.tsx
index 2fb2a92d6..1ea33357c 100644
--- a/streampark-console/streampark-console-webapp/src/views/flink/app/components/AppConf.tsx
+++ b/streampark-console/streampark-console-webapp/src/views/flink/app/components/AppConf.tsx
@@ -1,4 +1,4 @@
-/* 
+/*
   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.
@@ -12,7 +12,7 @@
   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. 
+  limitations under the License.
 */
 
 import { defineComponent, toRefs, unref } from 'vue';
diff --git a/streampark-console/streampark-console-webapp/src/views/flink/app/components/AppDetail/DetailTab.vue b/streampark-console/streampark-console-webapp/src/views/flink/app/components/AppDetail/DetailTab.vue
index d5bedd15a..038d2e688 100644
--- a/streampark-console/streampark-console-webapp/src/views/flink/app/components/AppDetail/DetailTab.vue
+++ b/streampark-console/streampark-console-webapp/src/views/flink/app/components/AppDetail/DetailTab.vue
@@ -232,6 +232,7 @@
     try {
       const res = await fetchFlinkSql({
         id: record.id,
+        appId: record.appId,
       });
       openFlinkDrawer(true, {
         sql: decodeByBase64(res.sql),
@@ -246,13 +247,13 @@
   /* delete configuration */
   async function handleDeleteConf(record: Recordable) {
     await fetchRemoveConf({ id: record.id });
-    reloadConf();
+    await reloadConf();
   }
 
   /* delete flink sql */
   async function handleDeleteFlinkSql(record: Recordable) {
-    await fetchRemoveFlinkSql({ id: record.id });
-    reloadFlinkSql();
+    await fetchRemoveFlinkSql({ id: record.id, appId: record.appId });
+    await reloadFlinkSql();
   }
 
   function handleCompare(record: Recordable) {
@@ -344,18 +345,18 @@
 
   /* delete savePoint */
   async function handleDeleteSavePoint(record: Recordable) {
-    await fetchRemoveSavePoint({ id: record.id });
-    reloadSavePoint();
+    await fetchRemoveSavePoint({ id: record.id, appId: record.appId });
+    await reloadSavePoint();
   }
 
   async function handleDeleteBackup(record: Recordable) {
     await fetchRemoveBackup(record.id);
-    reloadBackup();
+    await reloadBackup();
   }
 
   async function handleDeleteOperationLog(record: Recordable) {
     await fetchDeleteOperationLog(record.id);
-    reloadOperationLog();
+    await reloadOperationLog();
   }
 
   /* copy path */
@@ -377,8 +378,43 @@
 </script>
 <template>
   <div>
-    <Tabs :defaultActiveKey="1" class="mt-15px" :animated="false" :tab-bar-gutter="0">
-      <TabPane key="1" tab="Option" force-render>
+    <Tabs :defaultActiveKey="1" class="mt-15px" :tab-bar-gutter="0">
+      <TabPane key="1" :tab="t('flink.app.detail.detailTab.detailTabName.operationLog')">
+        <BasicTable @register="registerLogsTable">
+          <template #bodyCell="{ column, record }">
+            <template v-if="column.dataIndex === 'optionName'">
+              <Tag color="blue" v-if="record.optionName === OperationEnum.RELEASE"> Release </Tag>
+              <Tag color="green" v-if="record.optionName === OperationEnum.START"> Start </Tag>
+              <Tag color="cyan" v-if="record.optionName === OperationEnum.SAVEPOINT">
+                Savepoint
+              </Tag>
+              <Tag color="orange" v-if="record.optionName === OperationEnum.CANCEL"> Cancel </Tag>
+            </template>
+            <template v-if="column.dataIndex === 'yarnAppId'">
+              <a type="link" @click="handleYarnUrl(record.yarnAppId)" target="_blank">
+                {{ record.yarnAppId }}
+              </a>
+            </template>
+            <template v-if="column.dataIndex === 'jobManagerUrl'">
+              <a type="link" :href="record.jobManagerUrl" target="_blank">
+                {{ record.jobManagerUrl }}
+              </a>
+            </template>
+            <template v-if="column.dataIndex === 'optionTime'">
+              <Icon icon="ant-design:clock-circle-outlined" />
+              {{ record.optionTime }}
+            </template>
+            <template v-if="column.dataIndex === 'success'">
+              <Tag class="bold-tag" color="#52c41a" v-if="record.success"> SUCCESS </Tag>
+              <Tag class="bold-tag" color="#f5222d" v-else> FAILED </Tag>
+            </template>
+            <template v-if="column.dataIndex === 'operation'">
+              <TableAction :actions="getOperationLogAction(record)" />
+            </template>
+          </template>
+        </BasicTable>
+      </TabPane>
+      <TabPane key="2" :tab="t('flink.app.detail.detailTab.detailTabName.option')">
         <Descriptions bordered size="middle" layout="vertical">
           <DescriptionItem v-for="(v, k) in JSON.parse(app.options || '{}')" :key="k" :label="k">
             {{ v }}
@@ -386,7 +422,7 @@
         </Descriptions>
       </TabPane>
       <TabPane
-        key="2"
+        key="3"
         :tab="t('flink.app.detail.detailTab.detailTabName.configuration')"
         v-if="app && app.appType === AppTypeEnum.STREAMPARK_FLINK && tabConf.showConf"
       >
@@ -424,7 +460,7 @@
         </BasicTable>
       </TabPane>
       <TabPane
-        key="3"
+        key="4"
         :tab="t('flink.app.detail.detailTab.detailTabName.flinkSql')"
         v-if="app.jobType === JobTypeEnum.SQL"
       >
@@ -472,7 +508,7 @@
         </BasicTable>
       </TabPane>
       <TabPane
-        key="4"
+        key="5"
         :tab="t('flink.app.detail.detailTab.detailTabName.savepoint')"
         v-if="tabConf.showSaveOption"
       >
@@ -500,7 +536,7 @@
         </BasicTable>
       </TabPane>
       <TabPane
-        key="5"
+        key="6"
         :tab="t('flink.app.detail.detailTab.detailTabName.backup')"
         v-if="tabConf.showBackup"
       >
@@ -517,45 +553,6 @@
           </template>
         </BasicTable>
       </TabPane>
-      <TabPane
-        key="6"
-        :tab="t('flink.app.detail.detailTab.detailTabName.operationLog')"
-        v-if="tabConf.showOptionLog"
-      >
-        <BasicTable @register="registerLogsTable">
-          <template #bodyCell="{ column, record }">
-            <template v-if="column.dataIndex === 'optionName'">
-              <Tag color="blue" v-if="record.optionName === OperationEnum.RELEASE"> Release </Tag>
-              <Tag color="green" v-if="record.optionName === OperationEnum.START"> Start </Tag>
-              <Tag color="cyan" v-if="record.optionName === OperationEnum.SAVEPOINT">
-                Savepoint
-              </Tag>
-              <Tag color="orange" v-if="record.optionName === OperationEnum.CANCEL"> Cancel </Tag>
-            </template>
-            <template v-if="column.dataIndex === 'yarnAppId'">
-              <a type="link" @click="handleYarnUrl(record.yarnAppId)" target="_blank">
-                {{ record.yarnAppId }}
-              </a>
-            </template>
-            <template v-if="column.dataIndex === 'jobManagerUrl'">
-              <a type="link" :href="record.jobManagerUrl" target="_blank">
-                {{ record.jobManagerUrl }}
-              </a>
-            </template>
-            <template v-if="column.dataIndex === 'optionTime'">
-              <Icon icon="ant-design:clock-circle-outlined" />
-              {{ record.optionTime }}
-            </template>
-            <template v-if="column.dataIndex === 'success'">
-              <Tag class="bold-tag" color="#52c41a" v-if="record.success"> SUCCESS </Tag>
-              <Tag class="bold-tag" color="#f5222d" v-else> FAILED </Tag>
-            </template>
-            <template v-if="column.dataIndex === 'operation'">
-              <TableAction :actions="getOperationLogAction(record)" />
-            </template>
-          </template>
-        </BasicTable>
-      </TabPane>
     </Tabs>
 
     <CompareModal @register="registerCompare" />
diff --git a/streampark-console/streampark-console-webapp/src/views/flink/app/components/AppDetail/FlinkSqlCompareModal.vue b/streampark-console/streampark-console-webapp/src/views/flink/app/components/AppDetail/FlinkSqlCompareModal.vue
index 0c5c28b3c..a99a9f287 100644
--- a/streampark-console/streampark-console-webapp/src/views/flink/app/components/AppDetail/FlinkSqlCompareModal.vue
+++ b/streampark-console/streampark-console-webapp/src/views/flink/app/components/AppDetail/FlinkSqlCompareModal.vue
@@ -40,6 +40,7 @@
   const submitLoading = ref<boolean>(false);
   const compareRecord = reactive<Recordable>({});
   const values = useDetailProviderContext();
+  const appId = ref<any>();
 
   const [registerFlinkSqlDifferentDrawer, { openDrawer: openFlinkSqlDiffDrawer }] = useDrawer();
   const [registerModal, { closeModal }] = useModalInner((data) => {
@@ -47,8 +48,9 @@
   });
 
   async function onReceiveModalData(data) {
+    appId.value = toRaw(values).app.id;
     const res = await fetchFlinkSqlList({
-      appId: toRaw(values).app.id,
+      appId: appId.value,
       pageNo: 1,
       pageSize: 999999,
     });
@@ -83,11 +85,13 @@
     try {
       const source = await fetchFlinkSql({
         id: compareRecord.id,
+        appId: appId.value,
       });
       const sourceSql = decodeByBase64(source.sql);
       const sourceVersion = source.version;
       const target = await fetchFlinkSql({
         id: values.target,
+        appId: appId.value,
       });
       const targetSql = decodeByBase64(target.sql);
       const targetVersion = target.version;
diff --git a/streampark-console/streampark-console-webapp/src/views/flink/app/components/AppView/AppDashboard.vue b/streampark-console/streampark-console-webapp/src/views/flink/app/components/AppView/AppDashboard.vue
index 6455f017a..e5cc43b69 100644
--- a/streampark-console/streampark-console-webapp/src/views/flink/app/components/AppView/AppDashboard.vue
+++ b/streampark-console/streampark-console-webapp/src/views/flink/app/components/AppView/AppDashboard.vue
@@ -32,6 +32,13 @@
       const res = await fetchDashboard();
       if (res) {
         Object.assign(dashBigScreenMap, {
+          runningJob: {
+            staticstics: { title: t('flink.app.dashboard.runningJobs'), value: res.runningJob },
+            footer: [
+              { title: t('flink.app.dashboard.totalTask'), value: res.task.total },
+              { title: t('flink.app.dashboard.runningTask'), value: res.task.running },
+            ],
+          },
           availiableTask: {
             staticstics: {
               title: t('flink.app.dashboard.availableTaskSlots'),
@@ -42,13 +49,6 @@
               { title: t('flink.app.dashboard.taskManagers'), value: res.totalTM },
             ],
           },
-          runningJob: {
-            staticstics: { title: t('flink.app.dashboard.runningJobs'), value: res.runningJob },
-            footer: [
-              { title: t('flink.app.dashboard.totalTask'), value: res.task.total },
-              { title: t('flink.app.dashboard.runningTask'), value: res.task.running },
-            ],
-          },
           jobManager: {
             staticstics: { title: t('flink.app.dashboard.jobManagerMemory'), value: res.jmMemory },
             footer: [
diff --git a/streampark-console/streampark-console-webapp/src/views/flink/app/components/AppView/StopApplicationModal.vue b/streampark-console/streampark-console-webapp/src/views/flink/app/components/AppView/StopApplicationModal.vue
index 1319542ca..58e68959b 100644
--- a/streampark-console/streampark-console-webapp/src/views/flink/app/components/AppView/StopApplicationModal.vue
+++ b/streampark-console/streampark-console-webapp/src/views/flink/app/components/AppView/StopApplicationModal.vue
@@ -47,41 +47,24 @@
     schemas: [
       {
         field: 'stopSavePointed',
-        label: 'Savepoint',
+        label: t('flink.app.operation.triggerSavePoint'),
         component: 'Switch',
         componentProps: {
           checkedChildren: 'ON',
           unCheckedChildren: 'OFF',
         },
         defaultValue: true,
-        afterItem: () => h('span', { class: 'tip-info' }, 'trigger savePoint before taking cancel'),
+        afterItem: () =>
+          h('span', { class: 'conf-switch' }, t('flink.app.operation.enableSavePoint')),
       },
       {
         field: 'customSavepoint',
-        label: 'Custom Savepoint',
+        label: 'Savepoint path',
         component: 'Input',
         componentProps: {
-          placeholder: 'Entry the custom savepoint path',
+          placeholder: t('flink.app.operation.customSavepoint'),
           allowClear: true,
         },
-        afterItem: () => h('span', { class: 'tip-info' }, 'cancel job with savepoint path'),
-        ifShow: ({ values }) => !!values.stopSavePointed,
-      },
-      {
-        field: 'nativeFormat',
-        label: 'NativeFormat',
-        component: 'Switch',
-        componentProps: {
-          checkedChildren: 'ON',
-          unCheckedChildren: 'OFF',
-        },
-        defaultValue: false,
-        afterItem: () =>
-          h(
-            'span',
-            { class: 'tip-info' },
-            'Note: native format savepoint is supported since flink 1.15',
-          ),
         ifShow: ({ values }) => !!values.stopSavePointed,
       },
       {
@@ -93,27 +76,26 @@
           unCheckedChildren: 'OFF',
         },
         defaultValue: false,
-        afterItem: () => h('span', { class: 'tip-info' }, 'Send max watermark before stopped'),
+        ifShow: ({ values }) => !!values.stopSavePointed,
+        afterItem: () => h('span', { class: 'conf-switch' }, t('flink.app.operation.enableDrain')),
       },
     ],
     colon: true,
     showActionButtonGroup: false,
     labelCol: { lg: { span: 7, offset: 0 }, sm: { span: 7, offset: 0 } },
     wrapperCol: { lg: { span: 16, offset: 0 }, sm: { span: 4, offset: 0 } },
-    baseColProps: { span: 24 },
+    baseColProps: { span: 23 },
   });
 
   /* submit */
   async function handleSubmit() {
     try {
-      const { stopSavePointed, customSavepoint, drain, nativeFormat } =
-        (await validate()) as Recordable;
+      const { stopSavePointed, customSavepoint, drain } = (await validate()) as Recordable;
       const stopReq = {
         id: app.id,
         savePointed: stopSavePointed,
         savePoint: customSavepoint,
         drain: drain,
-        nativeFormat: nativeFormat,
       };
 
       if (stopSavePointed) {
@@ -122,22 +104,22 @@
             savePoint: customSavepoint,
           });
           if (data.data === false) {
-            createErrorSwal('custom savepoint path is invalid, ' + data.message);
+            await createErrorSwal(t('flink.app.operation.invalidSavePoint') + data.message);
           } else {
-            handleStopAction(stopReq);
+            await handleStopAction(stopReq);
           }
         } else {
           const { data } = await fetchCheckSavepointPath({
             id: app.id,
           });
           if (data.data) {
-            handleStopAction(stopReq);
+            await handleStopAction(stopReq);
           } else {
-            createErrorSwal(data.message);
+            await createErrorSwal(data.message);
           }
         }
       } else {
-        handleStopAction(stopReq);
+        await handleStopAction(stopReq);
       }
       emit('updateOption', {
         type: 'stopping',
@@ -153,7 +135,7 @@
     await fetchCancel(stopReq);
     Swal.fire({
       icon: 'success',
-      title: 'The current job is canceling',
+      title: t('flink.app.operation.canceling'),
       showConfirmButton: false,
       timer: 2000,
     });
@@ -171,6 +153,6 @@
       <SvgIcon name="shutdown" style="color: red" />
       {{ t('flink.app.view.stop') }}
     </template>
-    <BasicForm @register="registerForm" class="!pt-30px" />
+    <BasicForm @register="registerForm" class="!pt-40px" />
   </BasicModal>
 </template>
diff --git a/streampark-console/streampark-console-webapp/src/views/flink/app/components/Dependency.vue b/streampark-console/streampark-console-webapp/src/views/flink/app/components/Dependency.vue
index 575ae643e..f120fdf37 100644
--- a/streampark-console/streampark-console-webapp/src/views/flink/app/components/Dependency.vue
+++ b/streampark-console/streampark-console-webapp/src/views/flink/app/components/Dependency.vue
@@ -33,6 +33,7 @@
   import { fetchUpload } from '/@/api/flink/app';
   import { fetchUploadJars } from '/@/api/flink/flinkHistory';
   import UploadJobJar from './UploadJobJar.vue';
+  import { fetchFlinkEnv } from '/@/api/flink/flinkEnv';
 
   interface DependencyType {
     artifactId: string;
@@ -89,10 +90,16 @@
       Swal.fire('Failed', t('flink.app.dependencyError'), 'error');
       return;
     }
-    const scalaVersion = props.flinkEnvs.find((v) => v.id === versionId)?.scalaVersion;
+
+    let flinkEnv = props.flinkEnvs || [];
+    if (props.flinkEnvs?.length == 0) {
+      flinkEnv = await fetchFlinkEnv();
+    }
+    const scalaVersion = flinkEnv.find((v) => v.id === versionId)?.scalaVersion;
     if (props.value == null || props.value.trim() === '') {
       return;
     }
+
     const groupExp = /<groupId>([\s\S]*?)<\/groupId>/;
     const artifactExp = /<artifactId>([\s\S]*?)<\/artifactId>/;
     const versionExp = /<version>([\s\S]*?)<\/version>/;
@@ -126,26 +133,23 @@
               mvnPom.classifier = classifier;
             }
             const id = getId(mvnPom);
-            const pomExclusion = {};
+            const pomExclusion = [];
             if (exclusion != null) {
               const exclusions = exclusion.split('<exclusion>');
               exclusions.forEach((e) => {
                 if (e != null && e.length > 0) {
                   const e_group = e.match(groupExp) ? groupExp.exec(e)![1].trim() : null;
                   const e_artifact = e.match(artifactExp) ? artifactExp.exec(e)![1].trim() : null;
-                  const id = e_group + '_' + e_artifact;
-                  pomExclusion[id] = {
+                  pomExclusion.push({
                     groupId: e_group,
                     artifactId: e_artifact,
-                  };
+                  });
                 }
               });
             }
             mvnPom.exclusions = pomExclusion;
             dependency.pom[id] = mvnPom;
           }
-        } else {
-          console.error('dependency error...');
         }
       });
 
@@ -214,8 +218,7 @@
   /* load history config records */
   async function handleReloadHistoryUploads() {
     selectedHistoryUploadJars.value = [];
-    const res = await fetchUploadJars();
-    historyUploadJars.value = res;
+    historyUploadJars.value = await fetchUploadJars();
   }
 
   const filteredHistoryUploadJarsOptions = computed(() => {
@@ -288,7 +291,7 @@
   <Tabs type="card" v-model:activeKey="activeTab" class="pom-card">
     <TabPane key="pom" tab="Maven pom">
       <div class="relative">
-        <div ref="pomBox" class="pom-box syntax-true" style="height: 300px"></div>
+        <div ref="pomBox" class="pom-box syntax-true" style="height: 330px"></div>
         <a-button type="primary" class="apply-pom" @click="handleApplyPom()">
           {{ t('common.apply') }}
         </a-button>
diff --git a/streampark-console/streampark-console-webapp/src/views/flink/app/components/FlinkSql.vue b/streampark-console/streampark-console-webapp/src/views/flink/app/components/FlinkSql.vue
index 3b9217c9f..865709c7f 100644
--- a/streampark-console/streampark-console-webapp/src/views/flink/app/components/FlinkSql.vue
+++ b/streampark-console/streampark-console-webapp/src/views/flink/app/components/FlinkSql.vue
@@ -39,7 +39,7 @@
   const { t } = useI18n();
 
   const flinkSql = ref();
-  const vertifyRes = reactive({
+  const verifyRes = reactive({
     errorMsg: '',
     verified: false,
     errorStart: 0,
@@ -55,6 +55,9 @@
       type: String,
       default: '',
     },
+    appId: {
+      type: String as PropType<Nullable<string>>,
+    },
     versionId: {
       type: String as PropType<Nullable<string>>,
     },
@@ -68,7 +71,7 @@
   /* verify */
   async function handleVerifySql() {
     if (isEmpty(props.value)) {
-      vertifyRes.errorMsg = 'empty sql';
+      verifyRes.errorMsg = 'empty sql';
       return false;
     }
 
@@ -83,22 +86,22 @@
         });
         const success = data.data === true || data.data === 'true';
         if (success) {
-          vertifyRes.verified = true;
-          vertifyRes.errorMsg = '';
+          verifyRes.verified = true;
+          verifyRes.errorMsg = '';
           syntaxError();
           return true;
         } else {
-          vertifyRes.errorStart = parseInt(data.start);
-          vertifyRes.errorEnd = parseInt(data.end);
+          verifyRes.errorStart = parseInt(data.start);
+          verifyRes.errorEnd = parseInt(data.end);
           switch (data.type) {
             case 4:
-              vertifyRes.errorMsg = 'Unsupported sql';
+              verifyRes.errorMsg = 'Unsupported sql';
               break;
             case 5:
-              vertifyRes.errorMsg = "SQL is not endWith ';'";
+              verifyRes.errorMsg = "SQL is not endWith ';'";
               break;
             default:
-              vertifyRes.errorMsg = data.message;
+              verifyRes.errorMsg = data.message;
               break;
           }
           syntaxError();
@@ -116,14 +119,14 @@
     if (editor) {
       const model = editor.getModel();
       const monaco = await getMonacoInstance();
-      if (vertifyRes.errorMsg) {
+      if (verifyRes.errorMsg) {
         try {
           monaco.editor.setModelMarkers(model, 'sql', [
             {
-              startLineNumber: vertifyRes.errorStart,
-              endLineNumber: vertifyRes.errorEnd,
+              startLineNumber: verifyRes.errorStart,
+              endLineNumber: verifyRes.errorEnd,
               severity: monaco.MarkerSeverity.Error,
-              message: vertifyRes.errorMsg,
+              message: verifyRes.errorMsg,
             },
           ]);
         } catch (e) {
@@ -173,7 +176,7 @@
   const flinkEditorClass = computed(() => {
     return {
       ...fullEditorClass.value,
-      ['syntax-' + (vertifyRes.errorMsg ? 'false' : 'true')]: true,
+      ['syntax-' + (verifyRes.errorMsg ? 'false' : 'true')]: true,
     };
   });
 
@@ -226,11 +229,11 @@
     </ButtonGroup>
     <div class="flex items-center justify-between" v-else>
       <div class="mt-10px flex-1 mr-10px overflow-hidden whitespace-nowrap">
-        <div class="text-red-600 overflow-ellipsis overflow-hidden" v-if="vertifyRes.errorMsg">
-          {{ vertifyRes.errorMsg }}
+        <div class="text-red-600 overflow-ellipsis overflow-hidden" v-if="verifyRes.errorMsg">
+          {{ verifyRes.errorMsg }}
         </div>
         <div v-else class="text-green-700">
-          <span v-if="vertifyRes.verified"> {{ t('flink.app.flinkSql.successful') }} </span>
+          <span v-if="verifyRes.verified"> {{ t('flink.app.flinkSql.successful') }} </span>
         </div>
       </div>
       <div class="flinksql-tool">
@@ -262,9 +265,9 @@
     </div>
   </div>
   <p class="conf-desc mt-10px" v-if="!fullScreenStatus">
-    <span class="text-red-600" v-if="vertifyRes.errorMsg"> {{ vertifyRes.errorMsg }} </span>
+    <span class="text-red-600" v-if="verifyRes.errorMsg"> {{ verifyRes.errorMsg }} </span>
     <span v-else class="text-green-700">
-      <span v-if="vertifyRes.verified"> {{ t('flink.app.flinkSql.successful') }} </span>
+      <span v-if="verifyRes.verified"> {{ t('flink.app.flinkSql.successful') }} </span>
     </span>
   </p>
 </template>
diff --git a/streampark-console/streampark-console-webapp/src/views/flink/app/components/State.tsx b/streampark-console/streampark-console-webapp/src/views/flink/app/components/State.tsx
index 564b32d01..8aae8b47e 100644
--- a/streampark-console/streampark-console-webapp/src/views/flink/app/components/State.tsx
+++ b/streampark-console/streampark-console-webapp/src/views/flink/app/components/State.tsx
@@ -78,22 +78,22 @@ export const stateMap = {
 export const optionStateMap = {
   [OptionStateEnum.RELEASING]: {
     color: '#1ABBDC',
-    title: 'RELEASING',
+    title: t('flink.app.releaseState.releasing'),
     class: 'status-processing-deploying',
   },
   [OptionStateEnum.CANCELLING]: {
     color: '#faad14',
-    title: 'CANCELLING',
+    title: t('flink.app.runState.cancelling'),
     class: 'status-processing-cancelling',
   },
   [OptionStateEnum.STARTING]: {
     color: '#1AB58E',
-    title: 'STARTING',
+    title: t('flink.app.runState.starting'),
     class: 'status-processing-starting',
   },
   [OptionStateEnum.SAVEPOINTING]: {
     color: '#faad14',
-    title: 'SAVEPOINT',
+    title: t('flink.app.runState.savepoint'),
     class: 'status-processing-cancelling',
   },
 };
diff --git a/streampark-console/streampark-console-webapp/src/views/flink/app/data/detail.data.ts b/streampark-console/streampark-console-webapp/src/views/flink/app/data/detail.data.ts
index fc5d884c7..7e71e2a69 100644
--- a/streampark-console/streampark-console-webapp/src/views/flink/app/data/detail.data.ts
+++ b/streampark-console/streampark-console-webapp/src/views/flink/app/data/detail.data.ts
@@ -132,7 +132,7 @@ export const getBackupColumns = (): BasicColumn[] => [
 
 export const getOptionLogColumns = (): BasicColumn[] => [
   { title: 'Operation Name', dataIndex: 'optionName', width: 150 },
-  { title: 'Application Id', dataIndex: 'yarnAppId' },
+  { title: 'Cluster Id', dataIndex: 'yarnAppId' },
   { title: 'JobManager URL', dataIndex: 'jobManagerUrl' },
   { title: 'Start Status', dataIndex: 'success', width: 120 },
   { title: 'Option Time', dataIndex: 'optionTime', width: 200 },
diff --git a/streampark-console/streampark-console-webapp/src/views/flink/app/data/index.ts b/streampark-console/streampark-console-webapp/src/views/flink/app/data/index.ts
index 0f86bf5a2..fa1eed09c 100644
--- a/streampark-console/streampark-console-webapp/src/views/flink/app/data/index.ts
+++ b/streampark-console/streampark-console-webapp/src/views/flink/app/data/index.ts
@@ -20,6 +20,7 @@ import { ExecModeEnum, FailoverStrategyEnum, ReleaseStateEnum } from '/@/enums/f
 export const getMonacoOptions = (readOnly: boolean) => {
   return {
     selectOnLineNumbers: false,
+    foldingStrategy: 'indentation', // code fragmentation
     overviewRulerBorder: false, // Don't scroll bar borders
     autoClosingBrackets: 'always',
     autoClosingDelete: 'always',
diff --git a/streampark-console/streampark-console-webapp/src/views/flink/app/hooks/useCreateAndEditSchema.ts b/streampark-console/streampark-console-webapp/src/views/flink/app/hooks/useCreateAndEditSchema.ts
index 3aab70a4d..871ed3fbe 100644
--- a/streampark-console/streampark-console-webapp/src/views/flink/app/hooks/useCreateAndEditSchema.ts
+++ b/streampark-console/streampark-console-webapp/src/views/flink/app/hooks/useCreateAndEditSchema.ts
@@ -28,6 +28,7 @@ import {
   renderStreamParkResource,
   renderTotalMemory,
   renderYarnQueue,
+  renderFlinkCluster,
 } from './useFlinkRender';
 
 import { fetchCheckName } from '/@/api/flink/app';
@@ -93,18 +94,10 @@ export const useCreateAndEditSchema = (
   /* filter cluster */
   const getExecutionCluster = (
     executionMode: number,
-    valueKey: string,
-  ): Array<{ label: string; value: string }> => {
+  ): Array<{ id: string; label: string; state: number }> => {
     return (unref(flinkClusters) || [])
-      .filter((o) => {
-        // Edit mode has one more filter condition
-        if (edit?.mode) {
-          return o.executionMode == executionMode && o.clusterState === ClusterStateEnum.RUNNING;
-        } else {
-          return o.executionMode == executionMode;
-        }
-      })
-      .map((i) => ({ label: i.clusterName, value: i[valueKey] }));
+      .filter((o) => o.executionMode == executionMode)
+      .map((item) => ({ id: item.id, label: item.clusterName, state: item.clusterState }));
   };
 
   const getFlinkSqlSchema = computed((): FormSchema[] => {
@@ -206,13 +199,10 @@ export const useCreateAndEditSchema = (
         ],
       },
       {
-        field: 'flinkClusterId',
+        field: 'remoteClusterId',
         label: t('flink.app.flinkCluster'),
         component: 'Select',
-        componentProps: {
-          placeholder: t('flink.app.flinkCluster'),
-          options: getExecutionCluster(ExecModeEnum.REMOTE, 'id'),
-        },
+        render: (param) => renderFlinkCluster(getExecutionCluster(ExecModeEnum.REMOTE), param),
         ifShow: ({ values }) => values.executionMode == ExecModeEnum.REMOTE,
         rules: [
           { required: true, message: t('flink.app.addAppTips.flinkClusterIsRequiredMessage') },
@@ -222,20 +212,29 @@ export const useCreateAndEditSchema = (
         field: 'yarnSessionClusterId',
         label: t('flink.app.flinkCluster'),
         component: 'Select',
-        componentProps: {
-          placeholder: t('flink.app.flinkCluster'),
-          options: getExecutionCluster(ExecModeEnum.YARN_SESSION, 'id'),
-        },
+        render: (param) =>
+          renderFlinkCluster(getExecutionCluster(ExecModeEnum.YARN_SESSION), param),
         ifShow: ({ values }) => values.executionMode == ExecModeEnum.YARN_SESSION,
         rules: [
           { required: true, message: t('flink.app.addAppTips.flinkClusterIsRequiredMessage') },
         ],
       },
+      {
+        field: 'k8sSessionClusterId',
+        label: t('flink.app.flinkCluster'),
+        component: 'Select',
+        render: (param) =>
+          renderFlinkCluster(getExecutionCluster(ExecModeEnum.KUBERNETES_SESSION), param),
+        ifShow: ({ values }) => values.executionMode == ExecModeEnum.KUBERNETES_SESSION,
+        rules: [
+          { required: true, message: t('flink.app.addAppTips.flinkClusterIsRequiredMessage') },
+        ],
+      },
       {
         field: 'k8sNamespace',
         label: t('flink.app.kubernetesNamespace'),
         component: 'Input',
-        ifShow: ({ values }) => isK8sExecMode(values.executionMode),
+        ifShow: ({ values }) => values.executionMode == ExecModeEnum.KUBERNETES_APPLICATION,
         render: ({ model, field }) =>
           renderInputDropdown(model, field, {
             placeholder: t('flink.app.addAppTips.kubernetesNamespacePlaceholder'),
@@ -243,39 +242,15 @@ export const useCreateAndEditSchema = (
           }),
       },
       {
-        field: 'clusterId',
-        label: t('flink.app.kubernetesClusterId'),
+        field: 'serviceAccount',
+        label: t('setting.flinkCluster.form.serviceAccount'),
         component: 'Input',
-        componentProps: ({ formModel }) => {
-          return {
-            placeholder: t('flink.app.addAppTips.kubernetesClusterIdRequire'),
-            onChange: (e: ChangeEvent) => (formModel.jobName = e.target.value),
-          };
-        },
         ifShow: ({ values }) => values.executionMode == ExecModeEnum.KUBERNETES_APPLICATION,
-        rules: [
-          {
-            required: true,
-            message: t('flink.app.addAppTips.kubernetesClusterIdRequire'),
-            pattern: /^(?=.{1,45}$)[a-z]([-a-z0-9]*[a-z0-9])$/,
-          },
-        ],
-      },
-      {
-        field: 'flinkClusterId',
-        label: t('flink.app.kubernetesClusterId'),
-        component: 'Select',
-        ifShow: ({ values }) => values.executionMode == ExecModeEnum.KUBERNETES_SESSION,
-        componentProps: {
-          placeholder: t('flink.app.addAppTips.kubernetesClusterIdPlaceholder'),
-          options: getExecutionCluster(ExecModeEnum.KUBERNETES_SESSION, 'id'),
-        },
-        rules: [
-          {
-            required: true,
-            message: t('flink.app.addAppTips.kubernetesClusterIdIsRequiredMessage'),
-          },
-        ],
+        render: ({ model, field }) =>
+          renderInputDropdown(model, field, {
+            placeholder: t('flink.app.addAppTips.serviceAccountPlaceholder'),
+            options: unref(historyRecord)?.k8sNamespace || [],
+          }),
       },
       {
         field: 'flinkImage',
@@ -523,12 +498,9 @@ export const useCreateAndEditSchema = (
                 ],
               },
             );
-          } else if (model.jobType == JobTypeEnum.SQL) {
+          } else {
             return getAlertSvgIcon('fql', 'Flink SQL');
-          } else if (model.jobType == JobTypeEnum.PYFLINK) {
-            return getAlertSvgIcon('py', 'Py Flink');
           }
-          return '';
         },
       },
       {
@@ -545,7 +517,6 @@ export const useCreateAndEditSchema = (
           } else if (model.appType == AppTypeEnum.STREAMPARK_SPARK) {
             return getAlertSvgIcon('spark', 'StreamPark Spark');
           }
-          return '';
         },
       },
     ];
diff --git a/streampark-console/streampark-console-webapp/src/views/flink/app/hooks/useDetail.ts b/streampark-console/streampark-console-webapp/src/views/flink/app/hooks/useDetail.ts
index 92a3b924e..15c98953c 100644
--- a/streampark-console/streampark-console-webapp/src/views/flink/app/hooks/useDetail.ts
+++ b/streampark-console/streampark-console-webapp/src/views/flink/app/hooks/useDetail.ts
@@ -108,7 +108,7 @@ export const userDetail = (
   }
   /* delete savePoint */
   async function handleDeleteSavePoint(record: Recordable) {
-    await fetchRemoveSavePoint({ id: record.id });
+    await fetchRemoveSavePoint({ id: record.id, appId: record.appId });
     reloadSavePoint();
   }
 
diff --git a/streampark-console/streampark-console-webapp/src/views/flink/app/hooks/useEditStreamPark.ts b/streampark-console/streampark-console-webapp/src/views/flink/app/hooks/useEditStreamPark.ts
index 6a7b004a7..0f4659e15 100644
--- a/streampark-console/streampark-console-webapp/src/views/flink/app/hooks/useEditStreamPark.ts
+++ b/streampark-console/streampark-console-webapp/src/views/flink/app/hooks/useEditStreamPark.ts
@@ -37,6 +37,7 @@ export const useEditStreamParkSchema = (
 ) => {
   const flinkSql = ref();
   const route = useRoute();
+  const appId = route.query.appId as string;
   const {
     alerts,
     flinkEnvs,
@@ -48,14 +49,14 @@ export const useEditStreamParkSchema = (
     getExecutionModeSchema,
     suggestions,
   } = useCreateAndEditSchema(dependencyRef, {
-    appId: route.query.appId as string,
+    appId: appId,
     mode: 'streampark',
   });
   const { createMessage } = useMessage();
   const [registerDifferentDrawer, { openDrawer: openDiffDrawer }] = useDrawer();
 
   async function handleChangeSQL(v: string) {
-    const res = await fetchFlinkSql({ id: v });
+    const res = await fetchFlinkSql({ id: v, appId: appId });
     flinkSql.value?.setContent(decodeByBase64(res.sql));
     console.log('res', flinkSql.value);
     unref(dependencyRef)?.setDefaultValue(JSON.parse(res.dependency || '{}'));
@@ -66,7 +67,7 @@ export const useEditStreamParkSchema = (
       createMessage.warning('Two versions must be selected for comparison');
       return Promise.reject('error, compareSQL array length less thatn 2');
     }
-    const res = await fetchFlinkSql({ id: compareSQL.join(',') });
+    const res = await fetchFlinkSql({ appId: appId, id: compareSQL.join(',') });
     const obj1 = res[0];
     const obj2 = res[1];
     const sql1 = decodeByBase64(obj1.sql);
diff --git a/streampark-console/streampark-console-webapp/src/views/flink/app/hooks/useFlinkRender.tsx b/streampark-console/streampark-console-webapp/src/views/flink/app/hooks/useFlinkRender.tsx
index 63da6a65a..505d7e2dc 100644
--- a/streampark-console/streampark-console-webapp/src/views/flink/app/hooks/useFlinkRender.tsx
+++ b/streampark-console/streampark-console-webapp/src/views/flink/app/hooks/useFlinkRender.tsx
@@ -39,7 +39,7 @@ import { handleConfTemplate } from '/@/api/flink/config';
 import { decodeByBase64 } from '/@/utils/cipher';
 import { useMessage } from '/@/hooks/web/useMessage';
 import { SelectValue } from 'ant-design-vue/lib/select';
-import { CandidateTypeEnum, FailoverStrategyEnum, RestoreModeEnum } from '/@/enums/flinkEnum';
+import { CandidateTypeEnum, FailoverStrategyEnum, RestoreModeEnum, ClusterStateEnum } from '/@/enums/flinkEnum';
 import { useI18n } from '/@/hooks/web/useI18n';
 import { fetchYarnQueueList } from '/@/api/setting/yarnQueue';
 import { ApiSelect } from '/@/components/Form';
@@ -262,6 +262,38 @@ export const renderYarnQueue = ({ model, field }: RenderCallbackParams) => {
   );
 };
 
+export const renderFlinkCluster = (clusters, { model, field }: RenderCallbackParams) => {
+  return (
+    <Select
+      placeholder={t('flink.app.flinkCluster')}
+      value={model[field]}
+      onChange={(value: any) => (model[field] = value)}
+    >
+      {clusters.map((item) => {
+        return (
+          <Select.Option key={item.id}>
+            {item.label}
+            <span style="margin-left: 50px;">
+              {item.state == ClusterStateEnum.CREATED && (
+                <Tag color="#108ee9">{t('flink.app.clusterState.created')}</Tag>
+              )}
+              {item.state == ClusterStateEnum.RUNNING && (
+                <Tag color="#52c41a">{t('flink.app.clusterState.started')}</Tag>
+              )}
+              {item.state == ClusterStateEnum.CANCELED && (
+                <Tag color="#fa8c16">{t('flink.app.clusterState.canceled')}</Tag>
+              )}
+              {item.state == ClusterStateEnum.LOST && (
+                <Tag color="#333333">{t('flink.app.clusterState.lost')}</Tag>
+              )}
+            </span>
+          </Select.Option>
+        );
+      })}
+    </Select>
+  );
+};
+
 /* render memory option */
 export const renderDynamicProperties = ({ model, field }: RenderCallbackParams) => {
   return (
@@ -269,7 +301,7 @@ export const renderDynamicProperties = ({ model, field }: RenderCallbackParams)
       <Input.TextArea
         rows={8}
         name="dynamicProperties"
-        placeholder="Enter $key=$value,if there are multiple parameters,you can enter them on the new line(-D <arg>)"
+        placeholder="$key=$value,If there are multiple parameters,you can new line enter them (-D <arg>)"
         value={model[field]}
         onInput={(e: ChangeEvent) => (model[field] = e?.target?.value)}
       />
@@ -278,7 +310,6 @@ export const renderDynamicProperties = ({ model, field }: RenderCallbackParams)
           <Tag color="#2db7f5" class="tag-note">
             {t('flink.app.noteInfo.note')}
           </Tag>
-          {t('flink.app.noteInfo.dynamicProperties')}
           <a
             href="https://ci.apache.org/projects/flink/flink-docs-stable/ops/config.html"
             target="_blank"
diff --git a/streampark-console/streampark-console-webapp/src/views/flink/app/styles/Add.less b/streampark-console/streampark-console-webapp/src/views/flink/app/styles/Add.less
index a45c73ed2..5159a19b8 100644
--- a/streampark-console/streampark-console-webapp/src/views/flink/app/styles/Add.less
+++ b/streampark-console/streampark-console-webapp/src/views/flink/app/styles/Add.less
@@ -28,9 +28,7 @@
   }
 }
 
-.sql-box,
 .pom-box {
-  height: 550px;
   width: 100%;
   overflow: hidden;
 }
@@ -160,7 +158,7 @@
 
   .big-screen:hover,
   .format-sql:hover {
-    color: #1677ff;
+    color: #1890ff;
   }
 
   .apply-pom,
diff --git a/streampark-console/streampark-console-webapp/src/views/flink/app/styles/View.less b/streampark-console/streampark-console-webapp/src/views/flink/app/styles/View.less
index 356ade71d..98852052f 100644
--- a/streampark-console/streampark-console-webapp/src/views/flink/app/styles/View.less
+++ b/streampark-console/streampark-console-webapp/src/views/flink/app/styles/View.less
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 .link {
-  color: #1677ff;
+  color: #1890ff;
   text-decoration: none;
   background-color: transparent;
   outline: none;
@@ -104,7 +104,7 @@
   .app_jar {
     border: 1px solid #06f;
     padding: 3px 5px;
-    background: #1677ff;
+    background: #1890ff;
     color: #f5f5f5;
     font-size: 14px;
     transform: scale(0.7);
diff --git a/streampark-console/streampark-console-webapp/src/views/flink/app/utils/Pom.ts b/streampark-console/streampark-console-webapp/src/views/flink/app/utils/Pom.ts
index 87b8ab397..1e0291fa8 100644
--- a/streampark-console/streampark-console-webapp/src/views/flink/app/utils/Pom.ts
+++ b/streampark-console/streampark-console-webapp/src/views/flink/app/utils/Pom.ts
@@ -22,65 +22,40 @@ export function toPomString(pom) {
   const classifier = pom.classifier;
   const exclusions = pom.exclusions || [];
   let exclusionString = '';
-  let pomString = '';
+  let classifierString = '';
   if (exclusions.length > 0) {
     exclusions.forEach((item) => {
       exclusionString +=
-        '        <exclusion>\n' +
-        '          <groupId>' +
+        '      <exclusion>\n' +
+        '        <groupId>' +
         item.groupId +
         '</groupId>\n' +
-        '          <artifactId>' +
+        '        <artifactId>' +
         item.artifactId +
         '</artifactId>\n' +
-        '        </exclusion>\n';
+        '      </exclusion>\n';
     });
-    pomString =
-      '  <dependency>\n' +
-      '     <groupId>' +
-      groupId +
-      '</groupId>\n' +
-      '     <artifactId>' +
-      artifactId +
-      '</artifactId>\n' +
-      '     <version>' +
-      version +
-      '</version>\n' +
-      '     <exclusions>\n' +
-      exclusionString +
-      '     </exclusions>\n' +
-      '   </dependency>';
-  } else {
-    if (classifier != null) {
-      pomString =
-        '  <dependency>\n' +
-        '    <groupId>' +
-        groupId +
-        '</groupId>\n' +
-        '    <artifactId>' +
-        artifactId +
-        '</artifactId>\n' +
-        '    <version>' +
-        version +
-        '</version>\n' +
-        '    <classifier>' +
-        classifier +
-        '</classifier>\n' +
-        '  </dependency>';
-    } else {
-      pomString =
-        '  <dependency>\n' +
-        '    <groupId>' +
-        groupId +
-        '</groupId>\n' +
-        '    <artifactId>' +
-        artifactId +
-        '</artifactId>\n' +
-        '    <version>' +
-        version +
-        '</version>\n' +
-        '  </dependency>';
-    }
+    exclusionString = '    <exclusions>\n' + exclusionString + '    </exclusions>\n';
   }
+
+  if (classifier != null) {
+    classifierString = '    <classifier>' + classifier + '</classifier>\n';
+  }
+
+  const pomString =
+    '  <dependency>\n' +
+    '    <groupId>' +
+    groupId +
+    '</groupId>\n' +
+    '    <artifactId>' +
+    artifactId +
+    '</artifactId>\n' +
+    '    <version>' +
+    version +
+    '</version>\n' +
+    classifierString +
+    exclusionString +
+    '  </dependency>';
+
   return pomString;
 }
diff --git a/streampark-console/streampark-console-webapp/src/views/flink/app/utils/index.ts b/streampark-console/streampark-console-webapp/src/views/flink/app/utils/index.ts
index f50c5cfac..40fd45ad1 100644
--- a/streampark-console/streampark-console-webapp/src/views/flink/app/utils/index.ts
+++ b/streampark-console/streampark-console-webapp/src/views/flink/app/utils/index.ts
@@ -115,9 +115,9 @@ export async function handleView(app: AppListRecord, yarn: Nullable<string>) {
   ) {
     if (!yarn) {
       const res = await fetchYarn();
-      window.open(res + '/proxy/' + app['appId'] + '/');
+      window.open(res + '/proxy/' + app['clusterId'] + '/');
     } else {
-      window.open(yarn + '/proxy/' + app['appId'] + '/');
+      window.open(yarn + '/proxy/' + app['clusterId'] + '/');
     }
   } else {
     if (app.flinkRestUrl) {
@@ -265,6 +265,19 @@ export function handleDependencyJsonToPom(json, pomMap, jarMap) {
   }
 }
 
+function getFlinkClusterId(values: Recordable) {
+  if (values.executionMode == ExecModeEnum.YARN_SESSION) {
+    return values.yarnSessionClusterId;
+  }
+  if (values.executionMode == ExecModeEnum.REMOTE) {
+    return values.remoteClusterId;
+  }
+  if (values.executionMode == ExecModeEnum.KUBERNETES_SESSION) {
+    return values.k8sSessionClusterId;
+  }
+  return null;
+}
+
 export function handleSubmitParams(
   params: Recordable,
   values: Recordable,
@@ -288,17 +301,14 @@ export function handleSubmitParams(
     restartSize: values.restartSize,
     alertId: values.alertId,
     description: values.description,
-    hadoopUser: values.hadoopUser,
     k8sNamespace: values.k8sNamespace || null,
     clusterId: values.clusterId || null,
-    flinkClusterId:
-      (values.executionMode == ExecModeEnum.YARN_SESSION
-        ? values.yarnSessionClusterId
-        : values.flinkClusterId) || null,
+    flinkClusterId: getFlinkClusterId(values),
     flinkImage: values.flinkImage || null,
   });
   if (params.executionMode == ExecModeEnum.KUBERNETES_APPLICATION) {
     Object.assign(params, {
+      serviceAccount: values.serviceAccount,
       k8sPodTemplate: k8sTemplate.podTemplate,
       k8sJmPodTemplate: k8sTemplate.jmPodTemplate,
       k8sTmPodTemplate: k8sTemplate.tmPodTemplate,
diff --git a/streampark-console/streampark-console-webapp/src/views/system/token/token.data.ts b/streampark-console/streampark-console-webapp/src/views/system/token/token.data.ts
index a75719dce..192a71112 100644
--- a/streampark-console/streampark-console-webapp/src/views/system/token/token.data.ts
+++ b/streampark-console/streampark-console-webapp/src/views/system/token/token.data.ts
@@ -51,11 +51,6 @@ export const columns: BasicColumn[] = [
     title: t('common.createTime'),
     dataIndex: 'createTime',
   },
-  {
-    title: t('system.token.table.expireTime'),
-    dataIndex: 'expireTime',
-    sorter: true,
-  },
   {
     title: t('system.token.table.status'),
     dataIndex: 'userStatus',
@@ -117,13 +112,4 @@ export const formSchema: FormSchema[] = [
     label: t('common.description'),
     component: 'InputTextArea',
   },
-  {
-    field: 'expireTime',
-    label: t('system.token.table.expireTime'),
-    component: 'DatePicker',
-    defaultValue: dayjs('9999-01-01'),
-    componentProps: {
-      disabled: true,
-    },
-  },
 ];
diff --git a/streampark-flink/streampark-flink-client/streampark-flink-client-api/src/main/scala/org/apache/streampark/flink/client/FlinkClient.scala b/streampark-flink/streampark-flink-client/streampark-flink-client-api/src/main/scala/org/apache/streampark/flink/client/FlinkClient.scala
index 7bc69db05..8f32085d5 100644
--- a/streampark-flink/streampark-flink-client/streampark-flink-client-api/src/main/scala/org/apache/streampark/flink/client/FlinkClient.scala
+++ b/streampark-flink/streampark-flink-client/streampark-flink-client-api/src/main/scala/org/apache/streampark/flink/client/FlinkClient.scala
@@ -29,8 +29,8 @@ import scala.reflect.ClassTag
 
 object FlinkClient extends Logger {
 
-  private[this] val FLINK_CLIENT_ENDPOINT_CLASS =
-    "org.apache.streampark.flink.client.FlinkClientEndpoint"
+  private[this] val FLINK_CLIENT_ENTRYPOINT_CLASS =
+    "org.apache.streampark.flink.client.FlinkClientEntrypoint"
 
   private[this] val SUBMIT_REQUEST =
     "org.apache.streampark.flink.client.bean.SubmitRequest" -> "submit"
@@ -81,7 +81,7 @@ object FlinkClient extends Logger {
     FlinkShimsProxy.proxy(
       flinkVersion,
       (classLoader: ClassLoader) => {
-        val submitClass = classLoader.loadClass(FLINK_CLIENT_ENDPOINT_CLASS)
+        val submitClass = classLoader.loadClass(FLINK_CLIENT_ENTRYPOINT_CLASS)
         val requestClass = classLoader.loadClass(requestBody._1)
         val method = submitClass.getDeclaredMethod(requestBody._2, requestClass)
         method.setAccessible(true)
diff --git a/streampark-flink/streampark-flink-client/streampark-flink-client-core/src/main/scala/org/apache/streampark/flink/client/FlinkClientEndpoint.scala b/streampark-flink/streampark-flink-client/streampark-flink-client-core/src/main/scala/org/apache/streampark/flink/client/FlinkClientEntrypoint.scala
similarity index 99%
rename from streampark-flink/streampark-flink-client/streampark-flink-client-core/src/main/scala/org/apache/streampark/flink/client/FlinkClientEndpoint.scala
rename to streampark-flink/streampark-flink-client/streampark-flink-client-core/src/main/scala/org/apache/streampark/flink/client/FlinkClientEntrypoint.scala
index 609d5cf66..eea26d4f4 100644
--- a/streampark-flink/streampark-flink-client/streampark-flink-client-core/src/main/scala/org/apache/streampark/flink/client/FlinkClientEndpoint.scala
+++ b/streampark-flink/streampark-flink-client/streampark-flink-client-core/src/main/scala/org/apache/streampark/flink/client/FlinkClientEntrypoint.scala
@@ -24,7 +24,7 @@ import org.apache.streampark.flink.client.`trait`.FlinkClientTrait
 import org.apache.streampark.flink.client.bean._
 import org.apache.streampark.flink.client.impl._
 
-object FlinkClientEndpoint {
+object FlinkClientEntrypoint {
 
   private[this] val clients: Map[FlinkExecutionMode, FlinkClientTrait] = Map(
     LOCAL -> LocalClient,