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

guangning pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/pulsar-manager.git


The following commit(s) were added to refs/heads/master by this push:
     new 4ab8811  Add support for casdoor (#446)
4ab8811 is described below

commit 4ab8811a48ce7d2c8148f765f9cd9b62fbb76bfb
Author: Fabian Bao <baoyaol...@gmail.com>
AuthorDate: Wed Apr 13 09:54:09 2022 +0800

    Add support for casdoor (#446)
    
    feet: add support for casdoor
---
 build.gradle                                       |  1 +
 front-end/package.json                             |  4 +--
 front-end/src/api/login.js                         | 13 +++++++++
 front-end/src/lang/en.js                           |  1 +
 front-end/src/lang/zh.js                           |  1 +
 front-end/src/permission.js                        |  2 +-
 front-end/src/router/index.js                      |  7 ++++-
 front-end/src/store/modules/user.js                | 18 ++++++++++++
 front-end/src/views/callback/index.vue             | 18 ++++++++++++
 front-end/src/views/login/index.vue                | 13 +++++++--
 .../pulsar/manager/controller/LoginController.java | 34 ++++++++++++++++++++++
 .../manager/interceptor/WebAppConfigurer.java      |  1 +
 src/main/resources/application.properties          | 12 ++++++--
 13 files changed, 117 insertions(+), 8 deletions(-)

diff --git a/build.gradle b/build.gradle
index 0ccab9c..9a9dc9b 100644
--- a/build.gradle
+++ b/build.gradle
@@ -148,6 +148,7 @@ dependencies {
     compile group: 'org.glassfish.jersey.media', name: 
'jersey-media-json-jackson', version: jerseyVersion
     compile group: 'org.springframework.boot', name: 
'spring-boot-starter-security'
     compile group: 'org.springframework.security', name: 
'spring-security-config'
+    compile group: 'org.casbin', name: 'casdoor-spring-boot-starter', version: 
'1.2.0'
     compileOnly group: 'org.projectlombok', name: 'lombok', version: 
lombokVersion
     compileOnly group: 'org.springframework.boot', name: 
'spring-boot-devtools', version: springBootVersion
     testCompile group: 'org.springframework.boot', name: 
'spring-boot-starter-test', version: springBootVersion
diff --git a/front-end/package.json b/front-end/package.json
index 64225d6..eca0935 100644
--- a/front-end/package.json
+++ b/front-end/package.json
@@ -5,7 +5,7 @@
   "author": "<eguangn...@gmail.com>",
   "license": "Apache License 2.0",
   "scripts": {
-    "dev": "cross-env BABEL_ENV=development webpack-dev-server --inline 
--progress --config build/webpack.dev.conf.js",
+    "dev": "cross-env BABEL_ENV=development 
NODE_OPTIONS=--openssl-legacy-provider webpack-dev-server --inline --progress 
--config build/webpack.dev.conf.js",
     "build:prod": "cross-env NODE_ENV=production env_config=prod node 
build/build.js",
     "build:sit": "cross-env NODE_ENV=production env_config=sit node 
build/build.js",
     "lint": "eslint --ext .js,.vue src",
@@ -35,6 +35,7 @@
   },
   "dependencies": {
     "axios": "0.18.1",
+    "casdoor-js-sdk": "^0.2.5",
     "clipboard": "1.7.1",
     "codemirror": "5.39.2",
     "connect": "3.6.6",
@@ -97,7 +98,6 @@
     "request": "^2.88.0",
     "rimraf": "2.6.2",
     "sass-loader": "7.0.3",
-    "script-ext-html-webpack-plugin": "2.0.1",
     "script-loader": "0.7.2",
     "semver": "5.5.0",
     "serve-static": "1.13.2",
diff --git a/front-end/src/api/login.js b/front-end/src/api/login.js
index 0c3ca2e..7bfc6f4 100644
--- a/front-end/src/api/login.js
+++ b/front-end/src/api/login.js
@@ -26,6 +26,19 @@ export function loginByUsername(username, password) {
   })
 }
 
+export function loginByCasdoor(code, state) {
+  const data = {
+    code,
+    state
+  }
+  return request({
+    headers: { 'Content-Type': 'application/json' },
+    url: '/pulsar-manager/casdoor',
+    method: 'post',
+    data
+  })
+}
+
 export function logout() {
   return request({
     url: '/pulsar-manager/logout',
diff --git a/front-end/src/lang/en.js b/front-end/src/lang/en.js
index 6e359da..1161a62 100644
--- a/front-end/src/lang/en.js
+++ b/front-end/src/lang/en.js
@@ -104,6 +104,7 @@ export default {
     username: 'Username',
     password: 'Password',
     any: 'any',
+    casdoor: 'Login with casdoor',
     thirdparty: 'Or connect with',
     thirdpartyTips: 'Can not be simulated on local, so please combine you own 
business simulation! ! !'
   },
diff --git a/front-end/src/lang/zh.js b/front-end/src/lang/zh.js
index d466f8b..610d2ba 100644
--- a/front-end/src/lang/zh.js
+++ b/front-end/src/lang/zh.js
@@ -104,6 +104,7 @@ export default {
     username: 'Username',
     password: 'Password',
     any: 'any',
+    casdoor: 'Login with casdoor',
     thirdparty: 'Or connect with',
     thirdpartyTips: 'Can not be simulated on local, so please combine you own 
business simulation! ! !'
   },
diff --git a/front-end/src/permission.js b/front-end/src/permission.js
index 42b574e..b100d90 100644
--- a/front-end/src/permission.js
+++ b/front-end/src/permission.js
@@ -27,7 +27,7 @@ function hasPermission(roles, permissionRoles) {
   return roles.some(role => permissionRoles.indexOf(role) >= 0)
 }
 
-const whiteList = ['/login']// no redirect whitelist
+const whiteList = ['/login', '/callback']// no redirect whitelist
 
 router.beforeEach((to, from, next) => {
   NProgress.start() // start progress bar
diff --git a/front-end/src/router/index.js b/front-end/src/router/index.js
index 64f6339..e7be854 100644
--- a/front-end/src/router/index.js
+++ b/front-end/src/router/index.js
@@ -54,6 +54,11 @@ export const constantRouterMap = [
     component: () => import('@/views/login/index'),
     hidden: true
   },
+  {
+    path: '/callback',
+    component: () => import('@/views/callback/index'),
+    hidden: true
+  },
   {
     path: '/auth-redirect',
     component: () => import('@/views/login/authredirect'),
@@ -72,7 +77,7 @@ export const constantRouterMap = [
 ]
 
 export default new Router({
-  // mode: 'history', // require service support
+  mode: 'history', // require service support
   scrollBehavior: () => ({ y: 0 }),
   routes: constantRouterMap
 })
diff --git a/front-end/src/store/modules/user.js 
b/front-end/src/store/modules/user.js
index b2acd3c..9b2dc5d 100644
--- a/front-end/src/store/modules/user.js
+++ b/front-end/src/store/modules/user.js
@@ -19,6 +19,7 @@ import { removeCsrfToken } from '@/utils/csrfToken'
 import { Message } from 'element-ui'
 import { setTenant, removeTenant } from '../../utils/tenant'
 import { getUserInfo } from '@/api/users'
+import { loginByCasdoor } from '../../api/login'
 
 const user = {
   state: {
@@ -86,6 +87,23 @@ const user = {
       })
     },
 
+    LoginByCasdoor({ commit }, code, state) {
+      return new Promise((resolve, reject) => {
+        loginByCasdoor(code, state).then(response => {
+          if (response.data.hasOwnProperty('error') && 
response.data.error.length >= 0) {
+            reject('login error')
+          }
+          commit('SET_TOKEN', response.headers.token)
+          setToken(response.headers.token)
+          setName(response.headers.username)
+          setTenant(response.headers.tenant)
+          resolve()
+        }).catch(error => {
+          reject(error)
+        })
+      })
+    },
+
     // 获取用户信息
     GetUserInfo({ commit, state }) {
       return new Promise((resolve, reject) => {
diff --git a/front-end/src/views/callback/index.vue 
b/front-end/src/views/callback/index.vue
new file mode 100644
index 0000000..7e1068e
--- /dev/null
+++ b/front-end/src/views/callback/index.vue
@@ -0,0 +1,18 @@
+<script>
+export default {
+  name: 'Index',
+  watch: {
+    $route: {
+      handler: function(route) {
+        this.$store.dispatch('LoginByCasdoor', route.query.code, 
route.query.state).then(() => {
+          this.$router.push({ path: '/' })
+        }).catch(() => {
+          console.log('login error!!')
+        })
+      },
+      immediate: true
+    }
+
+  }
+}
+</script>
diff --git a/front-end/src/views/login/index.vue 
b/front-end/src/views/login/index.vue
index f4b79c3..cf0aa59 100644
--- a/front-end/src/views/login/index.vue
+++ b/front-end/src/views/login/index.vue
@@ -53,9 +53,10 @@
       </el-form-item>
 
       <el-button :loading="loading" type="primary" 
style="width:100%;margin-bottom:30px;" @click.native.prevent="handleLogin">{{ 
$t('login.logIn') }}</el-button>
+      <el-button :loading="loading" type="primary" 
style="width:100%;margin-left:0;" @click="loginWithCasdoor">{{ 
$t('login.casdoor') }}</el-button>
       <!-- <el-button class="thirdparty-button" type="primary" 
@click="showDialog=true">
-        Or connect with
-      </el-button> -->
+              Or connect with
+            </el-button> -->
     </el-form>
 
     <el-dialog :title="$t('login.thirdparty')" :visible.sync="showDialog" 
append-to-body>
@@ -180,6 +181,14 @@ export default {
       getCsrfToken().then(response => {
         setCsrfToken(response.headers['x-csrf-token'])
       })
+    },
+    loginWithCasdoor() {
+      window.location.href = 'http://localhost:7001/login/oauth/authorize' +
+        '?client_id=6ba06c1e1a30929fdda7' +
+        '&response_type=code' +
+        '&redirect_uri=http://localhost:9527/callback' +
+        '&scope=read' +
+        '&state=pulsar'
     }
   }
 }
diff --git 
a/src/main/java/org/apache/pulsar/manager/controller/LoginController.java 
b/src/main/java/org/apache/pulsar/manager/controller/LoginController.java
index 7e199ee..febf877 100644
--- a/src/main/java/org/apache/pulsar/manager/controller/LoginController.java
+++ b/src/main/java/org/apache/pulsar/manager/controller/LoginController.java
@@ -30,6 +30,10 @@ import io.swagger.annotations.ApiOperation;
 import io.swagger.annotations.ApiResponse;
 import io.swagger.annotations.ApiResponses;
 import org.apache.pulsar.manager.utils.ResourceType;
+import org.casbin.casdoor.entity.CasdoorUser;
+import org.casbin.casdoor.service.CasdoorAuthService;
+import org.casbin.casdoor.service.CasdoorResourceService;
+import org.casbin.casdoor.service.CasdoorUserService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.http.HttpHeaders;
@@ -81,6 +85,9 @@ public class LoginController {
     @Autowired
     private RolesRepository rolesRepository;
 
+    @Autowired
+    private CasdoorAuthService casdoorAuthService;
+
     @Autowired
     private RoleBindingRepository roleBindingRepository;
 
@@ -180,4 +187,31 @@ public class LoginController {
         jwtService.removeToken(request.getSession().getId());
         return ResponseEntity.ok(result);
     }
+
+    @ApiOperation(value = "Logout pulsar manager")
+    @ApiResponses({
+            @ApiResponse(code = 200, message = "ok"),
+            @ApiResponse(code = 500, message = "Internal server error")
+    })
+    @RequestMapping(value = "/casdoor", method =  RequestMethod.POST)
+    public ResponseEntity<Map<String, Object>> callback(
+            @RequestBody Map<String, String> body) {
+        Map<String, Object> result = Maps.newHashMap();
+        String code = body.get("code");
+        String state = body.get("state");
+        String token = casdoorAuthService.getOAuthToken(code, state);
+        if(!token.startsWith("error")){
+            result.put("error", token.substring(7));
+            return ResponseEntity.ok(result);
+        }
+        result.put("login", "success");
+        HttpHeaders headers = new HttpHeaders();
+        HttpServletRequest request = ((ServletRequestAttributes) 
RequestContextHolder.getRequestAttributes()).getRequest();
+        String jwtToken = jwtService.toToken(account + "-" + password);
+        jwtService.setToken(request.getSession().getId(), jwtToken);
+        headers.add("token", jwtToken);
+        headers.add("tenant","pulsar");
+        headers.add("username", "pulsar");
+        return new ResponseEntity<>(result, headers, HttpStatus.OK);
+    }
 }
diff --git 
a/src/main/java/org/apache/pulsar/manager/interceptor/WebAppConfigurer.java 
b/src/main/java/org/apache/pulsar/manager/interceptor/WebAppConfigurer.java
index ddfd79f..26adffc 100644
--- a/src/main/java/org/apache/pulsar/manager/interceptor/WebAppConfigurer.java
+++ b/src/main/java/org/apache/pulsar/manager/interceptor/WebAppConfigurer.java
@@ -34,6 +34,7 @@ public class WebAppConfigurer implements WebMvcConfigurer {
     public void addInterceptors(InterceptorRegistry registry) {
         registry.addInterceptor(adminHandlerInterceptor).addPathPatterns("/**")
                 .excludePathPatterns("/pulsar-manager/login")
+                .excludePathPatterns("/pulsar-manager/casdoor")
                 .excludePathPatterns("/pulsar-manager/users/superuser")
                 .excludePathPatterns("/pulsar-manager/csrf-token")
                 .excludePathPatterns("/pulsar-manager/third-party-login/**")
diff --git a/src/main/resources/application.properties 
b/src/main/resources/application.properties
index ba598eb..2781e4e 100644
--- a/src/main/resources/application.properties
+++ b/src/main/resources/application.properties
@@ -88,7 +88,7 @@ jwt.sessionTime=2592000
 pulsar-manager.account=pulsar
 pulsar-manager.password=pulsar
 # If true, the database is used for user management
-user.management.enable=true
+user.management.enable=false
 
 # Optional -> SECRET, PRIVATE, default -> PRIVATE, empty -> disable auth
 # SECRET mode -> bin/pulsar tokens create --secret-key 
file:///path/to/my-secret.key --subject test-user
@@ -154,5 +154,13 @@ tls.pulsar.admin.ca-certs=ca-client-path
 # support peek message, default false
 pulsar.peek.message=false
 
-# swagger configration
+# swagger configuration
 swagger.enabled=false
+
+# casdoor configuration
+casdoor.endpoint = http://localhost:8000
+casdoor.clientId = 6ba06c1e1a30929fdda7
+casdoor.clientSecret = df92bbf913225ebbae9af7ba8d41fe19507eb079
+casdoor.jwtPublicKey = -----BEGIN 
CERTIFICATE-----\nMIIE+TCCAuGgAwIBAgIDAeJAMA0GCSqGSIb3DQEBCwUAMDYxHTAbBgNVBAoTFENh\nc2Rvb3IgT3JnYW5pemF0aW9uMRUwEwYDVQQDEwxDYXNkb29yIENlcnQwHhcNMjEx\nMDE1MDgxMTUyWhcNNDExMDE1MDgxMTUyWjA2MR0wGwYDVQQKExRDYXNkb29yIE9y\nZ2FuaXphdGlvbjEVMBMGA1UEAxMMQ2FzZG9vciBDZXJ0MIICIjANBgkqhkiG9w0B\nAQEFAAOCAg8AMIICCgKCAgEAsInpb5E1/ym0f1RfSDSSE8IR7y+lw+RJjI74e5ej\nrq4b8zMYk7HeHCyZr/hmNEwEVXnhXu1P0mBeQ5ypp/QGo8vgEmjAETNmzkI1NjOQ\nCjCYwUrasO/f/MnI1C0j13vx6mV1kHZjSrKsMhYY1vax
 [...]
+casdoor.organizationName = built-in
+casdoor.applicationName = pulsar

Reply via email to