This is an automated email from the ASF dual-hosted git repository.
sijie 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 c50cff9 Display front end by different role (#238)
c50cff9 is described below
commit c50cff97715ce10453264f3930110f7d49f94c6e
Author: Guangning <[email protected]>
AuthorDate: Mon Jan 13 17:17:01 2020 +0800
Display front end by different role (#238)
### Motivation
This is the fourth pr of task #14.
After merge this pr, the platform will have complete multi-tenant
capability, the front end will display different contents according to the
user's role, and the back end route will filter resources according to
different roles.
### Modifications
* The front-end supports displaying different content according to
different roles.
* Super users can view everything
* Support to initialize superuser via rest api
### Verifying this change
Add unit test
---
front-end/src/api/users.js | 7 +
front-end/src/router/index.js | 180 ++++++++++---
front-end/src/store/modules/permission.js | 3 +-
front-end/src/store/modules/user.js | 40 ++-
front-end/src/views/login/index.vue | 8 +-
.../src/views/management/admin/tenants/tenant.vue | 290 +++++++++++++++++++++
.../src/views/management/clusters/cluster.vue | 5 +-
.../src/views/management/environments/index.vue | 19 +-
front-end/src/views/management/roles/index.vue | 17 +-
.../manager/controller/ClustersController.java | 18 +-
.../manager/controller/EnvironmentsController.java | 101 ++++++-
.../pulsar/manager/controller/LoginController.java | 31 ++-
.../manager/controller/RoleBindingController.java | 6 +
.../pulsar/manager/controller/RolesController.java | 41 +--
.../manager/controller/TenantsController.java | 76 +++++-
.../pulsar/manager/controller/UsersController.java | 153 ++++++++++-
.../manager/dao/EnvironmentsRepositoryImpl.java | 5 +
.../manager/dao/RoleBindingRepositoryImpl.java | 5 +
.../pulsar/manager/dao/RolesRepositoryImpl.java | 10 +
.../manager/entity/EnvironmentsRepository.java | 2 +
.../manager/entity/RoleBindingRepository.java | 6 +
.../pulsar/manager/entity/RolesRepository.java | 14 +-
.../apache/pulsar/manager/entity/TenantEntity.java | 3 +
.../interceptor/AdminHandlerInterceptor.java | 76 ++++--
.../manager/interceptor/WebAppConfigurer.java | 1 +
.../pulsar/manager/mapper/EnvironmentsMapper.java | 6 +
.../pulsar/manager/mapper/RoleBindingMapper.java | 4 +
.../apache/pulsar/manager/mapper/RolesMapper.java | 12 +
.../pulsar/manager/mapper/TenantsMapper.java | 19 +-
.../{PulsarEvent.java => PermissionsService.java} | 7 +-
.../apache/pulsar/manager/service/PulsarEvent.java | 4 +
.../pulsar/manager/service/RoleBindingService.java | 2 +
.../pulsar/manager/service/RolesService.java | 4 +-
.../PermissionsServiceImpl.java} | 10 +-
.../manager/service/impl/PulsarEventImpl.java | 110 +++++++-
.../service/impl/RoleBindingServiceImpl.java | 34 +++
.../manager/service/impl/RolesServiceImpl.java | 82 +++---
.../pulsar/manager/zuul/EnvironmentForward.java | 26 +-
src/main/resources/META-INF/sql/herddb-schema.sql | 28 +-
src/main/resources/META-INF/sql/mysql-schema.sql | 12 +-
.../resources/META-INF/sql/postgresql-schema.sql | 12 +-
src/main/resources/META-INF/sql/sqlite-schema.sql | 13 +-
.../manager/dao/NamespacesRepositoryImplTest.java | 3 +-
.../manager/dao/TenantsRepositoryImplTest.java | 8 +
.../manager/service/PulsarEventImplTest.java | 192 ++++++++++++++
45 files changed, 1470 insertions(+), 235 deletions(-)
diff --git a/front-end/src/api/users.js b/front-end/src/api/users.js
index 65e46a3..58d9538 100644
--- a/front-end/src/api/users.js
+++ b/front-end/src/api/users.js
@@ -53,3 +53,10 @@ export function deleteUser(data) {
})
}
+export function getUserInfo() {
+ return request({
+ headers: { 'Content-Type': 'application/json' },
+ url: SPRING_BASE_URL + '/users/userInfo',
+ method: 'get'
+ })
+}
diff --git a/front-end/src/router/index.js b/front-end/src/router/index.js
index dd253c5..e3f878c 100644
--- a/front-end/src/router/index.js
+++ b/front-end/src/router/index.js
@@ -68,11 +68,24 @@ export const constantRouterMap = [
path: '/401',
component: () => import('@/views/errorPage/401'),
hidden: true
- },
+ }
+]
+
+export default new Router({
+ // mode: 'history', // require service support
+ scrollBehavior: () => ({ y: 0 }),
+ routes: constantRouterMap
+})
+
+export const asyncRouterMap = [
+
{
path: '/environments',
component: () => import('@/views/management/environments/index'),
- hidden: true
+ hidden: true,
+ meta: {
+ roles: ['super', 'admin']
+ }
},
{
path: '',
@@ -80,7 +93,8 @@ export const constantRouterMap = [
redirect: 'management/tenants',
meta: {
title: 'Dashboard',
- icon: 'dashboard'
+ icon: 'dashboard',
+ roles: ['super']
},
hidden: true,
children: [
@@ -102,171 +116,260 @@ export const constantRouterMap = [
path: '/management',
component: Layout,
name: 'Management',
- redirect: 'management/tenants',
+ redirect: 'management/roles',
meta: {
title: 'Management',
- icon: 'component'
+ icon: 'component',
+ roles: ['super', 'admin']
},
children: [
{
path: 'clusters',
component: () => import('@/views/management/clusters/index'),
name: 'Clusters',
- meta: { title: 'Clusters', noCache: true }
+ meta: {
+ title: 'Clusters',
+ noCache: true,
+ roles: ['super']
+ }
},
{
path: 'clusters/:cluster/cluster',
component: () => import('@/views/management/clusters/cluster'),
name: 'ClusterInfo',
- meta: { title: 'ClusterInfo', noCache: true },
+ meta: {
+ title: 'ClusterInfo',
+ noCache: true,
+ roles: ['super']
+ },
hidden: true
},
{
path: 'clusters/:cluster/:failureDomainName/failureDomainName',
component: () => import('@/views/management/clusters/failureDomain'),
name: 'FailureDomainInfo',
- meta: { title: 'FailureDomainInfo', noCache: true },
+ meta: {
+ title: 'FailureDomainInfo',
+ noCache: true,
+ roles: ['super']
+ },
hidden: true
},
{
path: 'clusters/:cluster/:namespaceIsolation/namespaceIsolationPolicy',
component: () =>
import('@/views/management/namespaceIsolations/namespaceIsolationPolicy'),
name: 'NamespaceIsolationPolicy',
- meta: { title: 'NamespaceIsolationPolicy', noCache: true },
+ meta: {
+ title: 'NamespaceIsolationPolicy',
+ noCache: true,
+ roles: ['super']
+ },
hidden: true
},
{
path: 'brokers/:cluster/:broker/broker',
component: () => import('@/views/management/brokers/broker'),
name: 'BrokerInfo',
- meta: { title: 'BrokerInfo', noCache: true },
+ meta: {
+ title: 'BrokerInfo',
+ noCache: true,
+ roles: ['super']
+ },
hidden: true
},
{
path: 'tenants',
component: () => import('@/views/management/tenants/index'),
name: 'Tenants',
- meta: { title: 'Tenants', noCache: true }
+ meta: {
+ title: 'Tenants',
+ noCache: true,
+ roles: ['super']
+ }
},
{
path: 'tenants/tenantInfo/:tenant',
component: () => import('@/views/management/tenants/tenant'),
name: 'Tenant',
- meta: { title: 'TenantInfo', noCache: true },
+ meta: {
+ title: 'TenantInfo',
+ noCache: true,
+ roles: ['super']
+ },
hidden: true
},
{
+ path: 'admin/tenants/tenantInfo',
+ component: () => import('@/views/management/admin/tenants/tenant'),
+ name: 'Tenant Admin',
+ meta: {
+ title: 'TenantInfo',
+ noCache: true,
+ roles: ['super', 'admin']
+ }
+ },
+ {
path: 'tenants/tenantInfo/public?tab=namespaces',
name: 'Namespaces',
- meta: { title: 'Namespaces', noCache: true }
+ meta: {
+ title: 'Namespaces',
+ noCache: true,
+ roles: ['super']
+ }
},
{
path: 'namespaces/public/default/namespace?tab=topics',
name: 'Topics',
- meta: { title: 'Topics', noCache: true }
+ meta: {
+ title: 'Topics',
+ noCache: true,
+ roles: ['super']
+ }
},
{
path: 'topics/:persistent/:tenant/:namespace/:topic/topic',
component: () => import('@/views/management/topics/topic'),
name: 'TopicInfo',
- meta: { title: 'TopicInfo', noCache: true },
+ meta: {
+ title: 'TopicInfo',
+ noCache: true,
+ roles: ['super', 'admin']
+ },
hidden: true
},
{
path: 'topics/:persistent/:tenant/:namespace/:topic/partitionedTopic',
component: () => import('@/views/management/topics/partitionedTopic'),
name: 'ParititionTopicInfo',
- meta: { title: 'ParititionTopicInfo', noCache: true },
+ meta: {
+ title: 'ParititionTopicInfo',
+ noCache: true,
+ roles: ['super', 'admin']
+ },
hidden: true
},
{
path:
'subscriptions/:persistent/:tenant/:namespace/:topic/:subscription/subscription',
component: () =>
import('@/views/management/subscriptions/subscription'),
name: 'SubscriptionInfo',
- meta: { title: 'SubscriptionInfo', noCache: true },
+ meta: {
+ title: 'SubscriptionInfo',
+ noCache: true,
+ roles: ['super', 'admin']
+ },
hidden: true
},
{
path: 'namespaces/:tenant',
name: 'NamespacesTenant',
- meta: { title: 'Namespaces', noCache: true },
+ meta: {
+ title: 'Namespaces',
+ noCache: true,
+ roles: ['super']
+ },
hidden: true
},
{
path: 'namespaces/:tenant/:namespace/namespace',
component: () => import('@/views/management/namespaces/namespace'),
name: 'NamespacesInfo',
- meta: { title: 'NamespacesInfo', noCache: true },
+ meta: {
+ title: 'NamespacesInfo',
+ noCache: true,
+ roles: ['super', 'admin']
+ },
hidden: true
},
{
path: 'functions',
component: () => import('@/views/management/functions'),
name: 'Functions',
- meta: { title: 'Functions', noCache: true },
+ meta: {
+ title: 'Functions',
+ noCache: true,
+ roles: ['super']
+ },
hidden: true
},
{
path: 'sources',
component: () => import('@/views/management/sources'),
name: 'Sources',
- meta: { title: 'Sources', noCache: true },
+ meta: {
+ title: 'Sources',
+ noCache: true,
+ roles: ['super']
+ },
hidden: true
},
{
path: 'sinks',
component: () => import('@/views/management/sinks'),
name: 'Sinks',
- meta: { title: 'Sinks', noCache: true },
+ meta: {
+ title: 'Sinks',
+ noCache: true,
+ roles: ['super']
+ },
hidden: true
},
{
path: 'bookies',
component: () => import('@/views/management/bookies'),
name: 'Bookies',
- meta: { title: 'Bookies', noCache: true },
+ meta: {
+ title: 'Bookies',
+ noCache: true,
+ roles: ['super']
+ },
hidden: true
},
{
path: '/users',
component: () => import('@/views/management/users/index'),
name: 'Users',
- meta: { title: 'Users', noCache: true },
+ meta: {
+ title: 'Users',
+ noCache: true,
+ roles: ['super']
+ },
hidden: false
},
{
path: '/roles',
component: () => import('@/views/management/roles/index'),
name: 'Roles',
- meta: { title: 'Roles', noCache: true },
+ meta: {
+ title: 'Roles',
+ noCache: true,
+ roles: ['super', 'admin']
+ },
hidden: false
},
{
path: '/roleBinding',
component: () => import('@/views/management/roleBinding/index'),
name: 'RoleBinding',
- meta: { title: 'RoleBinding', noCache: true },
+ meta: {
+ title: 'RoleBinding',
+ noCache: true,
+ roles: ['super', 'admin']
+ },
hidden: false
},
{
path: '/tokens',
component: () => import('@/views/management/tokens/index'),
name: 'Tokens',
- meta: { title: 'Tokens', noCache: true },
+ meta: {
+ title: 'Tokens',
+ noCache: true,
+ roles: ['super', 'admin']
+ },
hidden: false
}
]
- }
-]
-
-export default new Router({
- // mode: 'history', // require service support
- scrollBehavior: () => ({ y: 0 }),
- routes: constantRouterMap
-})
-
-export const asyncRouterMap = [
-
+ },
{
path: 'external-link',
component: Layout,
@@ -277,6 +380,5 @@ export const asyncRouterMap = [
}
]
},
-
{ path: '*', redirect: '/404', hidden: true }
]
diff --git a/front-end/src/store/modules/permission.js
b/front-end/src/store/modules/permission.js
index f70d208..6461d88 100644
--- a/front-end/src/store/modules/permission.js
+++ b/front-end/src/store/modules/permission.js
@@ -12,6 +12,7 @@
* limitations under the License.
*/
import { asyncRouterMap, constantRouterMap } from '@/router'
+// import store from '@/store'
/**
* 通过meta.role判断是否与当前用户权限匹配
@@ -63,7 +64,7 @@ const permission = {
return new Promise(resolve => {
const { roles } = data
let accessedRouters
- if (roles.includes('admin')) {
+ if (roles.includes('super')) {
accessedRouters = asyncRouterMap
} else {
accessedRouters = filterAsyncRouter(asyncRouterMap, roles)
diff --git a/front-end/src/store/modules/user.js
b/front-end/src/store/modules/user.js
index 2f6cc3b..0bae227 100644
--- a/front-end/src/store/modules/user.js
+++ b/front-end/src/store/modules/user.js
@@ -11,12 +11,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-import { loginByUsername, logout, getUserInfo } from '@/api/login'
+import { loginByUsername, logout } from '@/api/login'
import { getToken, setToken, removeToken } from '@/utils/auth'
import { setName, removeName } from '@/utils/username'
import { removeEnvironment } from '@/utils/environment'
import { Message } from 'element-ui'
import { setTenant, removeTenant } from '../../utils/tenant'
+import { getUserInfo } from '@/api/users'
const user = {
state: {
@@ -87,19 +88,12 @@ const user = {
// 获取用户信息
GetUserInfo({ commit, state }) {
return new Promise((resolve, reject) => {
- // const response = getUserInfo(state.token)
- // const data = response.data
-
- commit('SET_ROLES', ['admin'])
- commit('SET_NAME', 'admin')
- // commit('SET_AVATAR', 'data.avatar')
- commit('SET_INTRODUCTION', 'Pulsar Manager')
- const response = {
- 'data': {
- 'roles': ['admin']
- }
- }
- resolve(response)
+ getUserInfo().then(response => {
+ commit('SET_ROLES', response.data.roles)
+ commit('SET_NAME', 'admin')
+ commit('SET_INTRODUCTION', 'Pulsar Manager')
+ resolve(response)
+ })
})
},
@@ -143,15 +137,15 @@ const user = {
return new Promise(resolve => {
commit('SET_TOKEN', role)
setToken(role)
- getUserInfo(role).then(response => {
- const data = response.data
- commit('SET_ROLES', data.roles)
- commit('SET_NAME', data.name)
- commit('SET_AVATAR', data.avatar)
- commit('SET_INTRODUCTION', data.introduction)
- dispatch('GenerateRoutes', data) // 动态修改权限后 重绘侧边菜单
- resolve()
- })
+ // getUserInfo(role).then(response => {
+ // const data = response.data
+ // commit('SET_ROLES', data.roles)
+ // commit('SET_NAME', data.name)
+ // commit('SET_AVATAR', data.avatar)
+ // commit('SET_INTRODUCTION', data.introduction)
+ // dispatch('GenerateRoutes', data) // 动态修改权限后 重绘侧边菜单
+ // resolve()
+ // })
})
}
}
diff --git a/front-end/src/views/login/index.vue
b/front-end/src/views/login/index.vue
index 3d95039..f94bb63 100644
--- a/front-end/src/views/login/index.vue
+++ b/front-end/src/views/login/index.vue
@@ -53,9 +53,9 @@
</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 class="thirdparty-button" type="primary"
@click="showDialog=true">
+ <!-- <el-button class="thirdparty-button" type="primary"
@click="showDialog=true">
Or connect with
- </el-button>
+ </el-button> -->
</el-form>
<el-dialog :title="$t('login.thirdparty')" :visible.sync="showDialog"
append-to-body>
@@ -120,7 +120,7 @@ export default {
// window.addEventListener('hashchange', this.afterQRScan)
},
destroyed() {
- // window.removeEventListener('hashchange', this.afterQRScan)
+ window.removeEventListener('hashchange', this.afterQRScan)
},
mounted() {
window.addEventListener('message', this.handleMessage)
@@ -145,7 +145,7 @@ export default {
this.loading = true
this.$store.dispatch('LoginByUsername', this.loginForm).then(() => {
this.loading = false
- this.$router.push({ path: this.redirect || '/management/clusters'
})
+ this.$router.push({ path: this.redirect || '/management/roles' })
}).catch(() => {
this.loading = false
})
diff --git a/front-end/src/views/management/admin/tenants/tenant.vue
b/front-end/src/views/management/admin/tenants/tenant.vue
new file mode 100644
index 0000000..f380924
--- /dev/null
+++ b/front-end/src/views/management/admin/tenants/tenant.vue
@@ -0,0 +1,290 @@
+<!--
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+-->
+<template>
+ <div class="app-container">
+ <div class="createPost-container">
+ <el-form :inline="true" :model="postForm" class="form-container">
+ <el-form-item class="postInfo-container-item" label="Tenant">
+ <el-select v-model="postForm.tenant"
:placeholder="$t('tenant.selectTenantMessage')"
@change="getNamespacesList(postForm.tenant)">
+ <el-option v-for="(item,index) in tenantsListOptions"
:key="item+index" :label="item" :value="item"/>
+ </el-select>
+ </el-form-item>
+ </el-form>
+ </div>
+ <el-tabs v-model="activeName">
+ <el-tab-pane :label="$t('tabs.namespace')" name="namespaces">
+ <div class="filter-container">
+ <el-input
+ :placeholder="$t('namespace.searchNamespaces')"
+ v-model="searchNamespace"
+ style="width: 200px;"
+ @keyup.enter.native="handleFilterNamespace"/>
+ <el-button type="primary" icon="el-icon-search"
@click="handleFilterNamespace"/>
+ <el-button type="primary" icon="el-icon-plus"
@click="handleCreateNamespace">{{ $t('namespace.newNamespace') }}</el-button>
+ </div>
+ <el-row :gutter="24">
+ <el-col :xs="{span: 24}" :sm="{span: 24}" :md="{span: 24}"
:lg="{span: 24}" :xl="{span: 24}">
+ <el-table
+ v-loading="listLoading"
+ :key="tableKey"
+ :data="listNamespaces"
+ border
+ fit
+ highlight-current-row
+ style="width: 100%;">
+ <el-table-column :label="$t('namespace.name')" align="center">
+ <template slot-scope="scope">
+ <router-link :to="'/management/namespaces/' +
scope.row.tenant +'/' + scope.row.namespace + '/namespace?tab=overview'"
class="link-type">
+ <span>{{ scope.row.namespace }}</span>
+ </router-link>
+ </template>
+ </el-table-column>
+ <el-table-column :label="$t('topic.topicNumber')" align="center">
+ <template slot-scope="scope">
+ <router-link :to="'/management/namespaces/' +
scope.row.tenant + '/' + scope.row.namespace + '/namespace?tab=topics'"
class="link-type">
+ <span>{{ scope.row.topics }}</span>
+ </router-link>
+ </template>
+ </el-table-column>
+ <el-table-column :label="$t('table.actions')" align="center"
class-name="small-padding fixed-width">
+ <template slot-scope="scope">
+ <router-link :to="'/management/namespaces/' +
scope.row.tenant +'/' + scope.row.namespace + '/namespace'">
+ <el-button type="primary" size="mini">{{ $t('table.edit')
}}</el-button>
+ </router-link>
+ <el-button v-if="scope.row.status!='deleted'" size="mini"
type="danger" @click="handleDeleteNamespace(scope.row)">{{ $t('table.delete')
}}</el-button>
+ </template>
+ </el-table-column>
+ </el-table>
+ </el-col>
+ </el-row>
+ </el-tab-pane>
+ </el-tabs>
+ <el-dialog :title="textMap[dialogStatus]"
:visible.sync="dialogFormVisible" width="30%">
+ <el-form ref="temp" :model="temp" :rules="rules" label-position="top">
+ <el-form-item v-if="dialogStatus==='createNamespace'"
:label="$t('table.namespace')" prop="namespace">
+ <el-input v-model="temp.namespace"
:placeholder="$t('namespace.inputNamespaceMessage')"/>
+ </el-form-item>
+ <el-form-item v-if="dialogStatus==='deleteNamespace'">
+ <h4>{{ $t('namespace.deleteNamespaceMessage') }}</h4>
+ </el-form-item>
+ <el-form-item v-if="dialogStatus==='deleteTenant'">
+ <h4>{{ $t('tenant.deleteTenantMessage') }}</h4>
+ </el-form-item>
+ <el-form-item>
+ <el-button type="primary" @click="handleOptions()">{{
$t('table.confirm') }}</el-button>
+ <el-button @click="dialogFormVisible=false">{{ $t('table.cancel')
}}</el-button>
+ </el-form-item>
+ </el-form>
+ </el-dialog>
+ </div>
+</template>
+
+<script>
+import { fetchTenants } from '@/api/tenants'
+import { getTenant } from '@/utils/tenant'
+import {
+ fetchNamespaces,
+ putNamespace,
+ deleteNamespace
+} from '@/api/namespaces'
+import { validateEmpty } from '@/utils/validate'
+
+const defaultForm = {
+ tenant: getTenant()
+}
+
+export default {
+ name: 'TenantInfo',
+ data() {
+ return {
+ postForm: Object.assign({}, defaultForm),
+ adminRoles: '',
+ tenantsListOptions: [],
+ listQuery: {
+ namespace: '',
+ page: 1,
+ limit: 20
+ },
+ activeName: 'namespaces',
+ listLoading: false,
+ tableKey: 0,
+ total: 0,
+ listNamespaces: [],
+ temp: {
+ tenant: '',
+ namespace: '',
+ limit: ''
+ },
+ dialogFormVisible: false,
+ dialogStatus: '',
+ rules: {
+ namespace: [{ required: true, message:
this.$i18n.t('namespace.namespaceNameIsRequired'), trigger: 'blur' }]
+ },
+ currentTabName: '',
+ textMap: {
+ createNamespace: this.$i18n.t('namespace.newNamespace'),
+ deleteNamespace: this.$i18n.t('namespace.deleteNamespace')
+ },
+ tempNamespacesList: [],
+ searchNamespace: '',
+ searchList: []
+ }
+ },
+ created() {
+ this.getRemoteTenantsList()
+ this.getNamespacesList()
+ },
+ methods: {
+ getRemoteTenantsList() {
+ fetchTenants().then(response => {
+ if (!response.data) return
+ for (var i = 0; i < response.data.total; i++) {
+ this.tenantsListOptions.push(response.data.data[i].tenant)
+ }
+ })
+ },
+ getNamespacesList() {
+ fetchNamespaces(this.postForm.tenant, this.listQuery).then(response => {
+ if (!response.data.data) return
+ this.listNamespaces = []
+ for (var i = 0; i < response.data.data.length; i++) {
+ this.listNamespaces.push({
+ 'tenant': this.postForm.tenant,
+ 'namespace': response.data.data[i].namespace,
+ 'topics': response.data.data[i].topics
+ })
+ }
+ this.total = this.listNamespaces.length
+ // Just to simulate the time of the request
+ setTimeout(() => {
+ this.listLoading = false
+ }, 1.5 * 1000)
+ })
+ },
+ handleFilterNamespace() {
+ if (this.tempNamespacesList.length <= 0) {
+ for (var t = 0; t < this.listNamespaces.length; t++) {
+ this.tempNamespacesList.push(this.listNamespaces[t])
+ }
+ }
+ if (!validateEmpty(this.searchNamespace)) {
+ this.searchList = []
+ for (var i = 0; i < this.listNamespaces.length; i++) {
+ if
(this.listNamespaces[i]['namespace'].indexOf(this.searchNamespace) !== -1) {
+ this.searchList.push(this.listNamespaces[i])
+ }
+ }
+ this.listNamespaces = this.searchList
+ } else {
+ this.listNamespaces = this.tempNamespacesList
+ }
+ },
+ handleCreateNamespace() {
+ this.temp.namespace = ''
+ this.dialogStatus = 'createNamespace'
+ this.dialogFormVisible = true
+ },
+ createNamespace() {
+ putNamespace(this.postForm.tenant, this.temp.namespace,
this.temp).then(() => {
+ this.listNamespaces = []
+ this.getNamespacesList()
+ this.dialogFormVisible = false
+ this.$notify({
+ title: 'success',
+ message: this.$i18n.t('namespace.createNsSuccessNotification'),
+ type: 'success',
+ duration: 2000
+ })
+ })
+ },
+ handleOptions() {
+ this.$refs['temp'].validate((valid) => {
+ if (valid) {
+ switch (this.dialogStatus) {
+ case 'createNamespace':
+ this.createNamespace()
+ break
+ case 'deleteNamespace':
+ this.deleteNamespace()
+ break
+ }
+ }
+ })
+ },
+ handleDeleteNamespace(row) {
+ this.dialogStatus = 'deleteNamespace'
+ this.dialogFormVisible = true
+ this.temp.tenant = row.tenant
+ this.temp.namespace = row.namespace
+ },
+ deleteNamespace() {
+ var tenantNamespace = this.temp.tenant + '/' + this.temp.namespace
+ deleteNamespace(tenantNamespace).then((response) => {
+ this.$notify({
+ title: 'success',
+ message: this.$i18n.t('namespace.deleteNsSuccessNotification'),
+ type: 'success',
+ duration: 2000
+ })
+ this.dialogFormVisible = false
+ this.listNamespaces = []
+ this.getNamespacesList()
+ })
+ }
+ }
+}
+</script>
+
+<style scoped>
+.el-tag + .el-tag {
+ margin-left: 10px;
+ }
+.button-new-tag {
+ margin-left: 10px;
+ height: 32px;
+ line-height: 30px;
+ padding-top: 0;
+ padding-bottom: 0;
+}
+.input-new-tag {
+ width: 90px;
+ margin-left: 10px;
+ vertical-align: bottom;
+}
+.section-content {
+ margin-top: 15px;
+}
+.confirm-button {
+ margin-top: 10px;
+}
+.section-title {
+ color: rgba(0,0,0,.45);
+ font-size: 16px;
+}
+.component-item{
+ min-height: 60px;
+}
+.split-line {
+ background: #e6e9f3;
+ border: none;
+ height: 1px;
+}
+.danger-line {
+ background: red;
+ border: none;
+ height: 1px;
+}
+</style>
diff --git a/front-end/src/views/management/clusters/cluster.vue
b/front-end/src/views/management/clusters/cluster.vue
index 7b59491..0cef36d 100644
--- a/front-end/src/views/management/clusters/cluster.vue
+++ b/front-end/src/views/management/clusters/cluster.vue
@@ -286,12 +286,14 @@ import MdInput from '@/components/MDinput'
import { validateEmpty, validateServiceUrl } from '@/utils/validate'
import { formatBytes, getQueryObject } from '@/utils/index'
import { numberFormatter } from '@/filters/index'
+import permission from '@/directive/permission/index.js'
const defaultForm = {
cluster: ''
}
export default {
name: 'ClusterInfo',
+ directives: { permission },
components: {
Pagination,
MdInput
@@ -358,7 +360,8 @@ export default {
deleteClusterMessage: this.$i18n.t('cluster.deleteClusterMessage'),
deleteFdMessage: this.$i18n.t('fd.deleteFdMessage'),
deletePolicyMessage: this.$i18n.t('ip.deletePolicyMessage'),
- currentActiveTab: ''
+ currentActiveTab: '',
+ key: 1
}
},
created() {
diff --git a/front-end/src/views/management/environments/index.vue
b/front-end/src/views/management/environments/index.vue
index 0e50f1a..fc2dfac 100644
--- a/front-end/src/views/management/environments/index.vue
+++ b/front-end/src/views/management/environments/index.vue
@@ -15,7 +15,7 @@
-->
<template>
<div class="app-container">
- <el-button type="primary" icon="el-icon-plus"
@click="handleCreateEnvironment">{{ $t('env.buttonNewEnv') }}</el-button>
+ <el-button v-if="superUser" type="primary" icon="el-icon-plus"
@click="handleCreateEnvironment">{{ $t('env.buttonNewEnv') }}</el-button>
<el-row :gutter="24">
<el-col :xs="{span: 24}" :sm="{span: 24}" :md="{span: 24}" :lg="{span:
24}" :xl="{span: 24}" style="margin-top:15px">
@@ -39,7 +39,7 @@
<span>{{ scope.row.broker }}</span>
</template>
</el-table-column>
- <el-table-column :label="$t('table.actions')" align="center"
class-name="small-padding fixed-width">
+ <el-table-column v-if="superUser" :label="$t('table.actions')"
align="center" class-name="small-padding fixed-width">
<template slot-scope="scope">
<el-button type="primary" size="mini"
@click="handleUpdateEnvironment(scope.row)">{{ $t('table.edit') }}</el-button>
<el-button size="mini" type="danger"
@click="handleDeleteEnvironment(scope.row)">{{ $t('table.delete') }}</el-button>
@@ -78,6 +78,7 @@
<script>
import { putEnvironment, fetchEnvironments, deleteEnvironment,
updateEnvironment } from '@/api/environments'
import { setEnvironment } from '@/utils/environment'
+import store from '@/store'
export default {
name: 'EnvironmentInfo',
@@ -101,6 +102,8 @@ export default {
'name': '',
'broker': ''
},
+ superUser: false,
+ roles: [],
rules: {
environment: [{ required: true, message:
this.$i18n.t('env.envNameIsRequired'), trigger: 'blur' }],
broker: [{ required: true, message:
this.$i18n.t('env.serviceUrlIsRequired'), trigger: 'blur' }]
@@ -109,6 +112,12 @@ export default {
},
created() {
this.getEnvironments()
+ this.roles = store.getters && store.getters.roles
+ if (this.roles.includes('super')) {
+ this.superUser = true
+ } else {
+ this.superUser = false
+ }
},
methods: {
getEnvironments() {
@@ -238,7 +247,11 @@ export default {
},
handleSetEnvironment(environment) {
setEnvironment(environment)
- this.$router.push({ path: '/management/tenants' })
+ if (this.roles.includes('super')) {
+ this.$router.push({ path: '/management/tenants' })
+ } else {
+ this.$router.push({ path: '/management/admin/tenants/tenantInfo' })
+ }
}
}
}
diff --git a/front-end/src/views/management/roles/index.vue
b/front-end/src/views/management/roles/index.vue
index 54c8519..9c442f9 100644
--- a/front-end/src/views/management/roles/index.vue
+++ b/front-end/src/views/management/roles/index.vue
@@ -57,7 +57,13 @@
<span>{{ scope.row.roleSource }}</span>
</template>
</el-table-column>
- <el-table-column :label="$t('table.actions')" align="center"
class-name="small-padding fixed-width">
+ <el-table-column v-if="superUser" :label="$t('table.actions')"
align="center" class-name="small-padding fixed-width">
+ <template slot-scope="scope">
+ <el-button type="primary" size="mini"
@click="handleUpdateRole(scope.row)">{{ $t('table.edit') }}</el-button>
+ <el-button size="mini" type="danger"
@click="handleDeleteRole(scope.row)">{{ $t('table.delete') }}</el-button>
+ </template>
+ </el-table-column>
+ <el-table-column v-if="superUser === false"
:label="$t('table.actions')" align="center" class-name="small-padding
fixed-width">
<template slot-scope="scope">
<el-button :disabled="scope.row.resourceType=='TENANTS'"
type="primary" size="mini" @click="handleUpdateRole(scope.row)">{{
$t('table.edit') }}</el-button>
<el-button :disabled="scope.row.resourceType=='TENANTS'"
size="mini" type="danger" @click="handleDeleteRole(scope.row)">{{
$t('table.delete') }}</el-button>
@@ -83,7 +89,7 @@
v-model="form.resourceType"
:placeholder="$t('role.resourceTypePlaceHolder')"
style="width:100%"
- @change="handleChangeResourceType(form.resourceType)">
+ @change="handleChangeResourceType(form)">
<el-option
v-for="item in resourceTypeListOptions"
:key="item.value"
@@ -172,6 +178,7 @@ import {
updateRole,
deleteRole
} from '@/api/roles'
+import store from '@/store'
export default {
name: 'RolesInfo',
@@ -222,6 +229,12 @@ export default {
}
},
created() {
+ const roles = store.getters && store.getters.roles
+ if (roles.includes('super')) {
+ this.superUser = true
+ } else {
+ this.superUser = false
+ }
this.getRoles()
this.getResourceType()
},
diff --git
a/src/main/java/org/apache/pulsar/manager/controller/ClustersController.java
b/src/main/java/org/apache/pulsar/manager/controller/ClustersController.java
index 92a3beb..54259e6 100644
--- a/src/main/java/org/apache/pulsar/manager/controller/ClustersController.java
+++ b/src/main/java/org/apache/pulsar/manager/controller/ClustersController.java
@@ -13,6 +13,7 @@
*/
package org.apache.pulsar.manager.controller;
+import com.google.common.collect.Maps;
import org.apache.pulsar.manager.service.ClustersService;
import org.apache.pulsar.manager.service.EnvironmentCacheService;
import io.swagger.annotations.Api;
@@ -20,6 +21,7 @@ import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
+import org.apache.pulsar.manager.service.RolesService;
import org.hibernate.validator.constraints.Range;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
@@ -31,6 +33,7 @@ import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import javax.validation.constraints.Min;
+import java.util.ArrayList;
import java.util.Map;
/**
@@ -56,6 +59,9 @@ public class ClustersController {
this.request = request;
}
+ @Autowired
+ private RolesService rolesService;
+
@ApiOperation(value = "Get the list of existing clusters, support paging,
the default is 10 per page")
@ApiResponses({
@ApiResponse(code = 200, message = "ok"),
@@ -72,7 +78,17 @@ public class ClustersController {
@Range(min = 1, max = 1000, message = "page_size is incorrect,
should be greater than 0 and less than 1000.")
Integer pageSize) {
String requestHost = environmentCacheService.getServiceUrl(request);
- Map<String, Object> result = clusterService.getClustersList(
+ String token = request.getHeader("token");
+ Map<String, Object> result = Maps.newHashMap();
+ if (!rolesService.isSuperUser(token)) {
+ result.put("isPage", false);
+ result.put("total", 0);
+ result.put("data", new ArrayList());
+ result.put("pageNum", 0);
+ result.put("pageSize", 0);
+ return ResponseEntity.ok(result);
+ }
+ result = clusterService.getClustersList(
pageNum, pageSize, requestHost, cluster -> {
String environment = request.getHeader("environment");
if (null == environment) {
diff --git
a/src/main/java/org/apache/pulsar/manager/controller/EnvironmentsController.java
b/src/main/java/org/apache/pulsar/manager/controller/EnvironmentsController.java
index f5a40b7..76a5024 100644
---
a/src/main/java/org/apache/pulsar/manager/controller/EnvironmentsController.java
+++
b/src/main/java/org/apache/pulsar/manager/controller/EnvironmentsController.java
@@ -13,11 +13,19 @@
*/
package org.apache.pulsar.manager.controller;
-import com.github.pagehelper.Page;
import com.google.common.collect.Maps;
import org.apache.pulsar.manager.entity.EnvironmentEntity;
import org.apache.pulsar.manager.entity.EnvironmentsRepository;
+import org.apache.pulsar.manager.entity.RoleBindingEntity;
+import org.apache.pulsar.manager.entity.RoleBindingRepository;
+import org.apache.pulsar.manager.entity.RoleInfoEntity;
+import org.apache.pulsar.manager.entity.RolesRepository;
+import org.apache.pulsar.manager.entity.TenantEntity;
+import org.apache.pulsar.manager.entity.TenantsRepository;
+import org.apache.pulsar.manager.entity.UserInfoEntity;
+import org.apache.pulsar.manager.entity.UsersRepository;
import org.apache.pulsar.manager.service.EnvironmentCacheService;
+import org.apache.pulsar.manager.service.RolesService;
import org.apache.pulsar.manager.utils.HttpUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
@@ -25,6 +33,7 @@ import io.swagger.annotations.ApiParam;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import org.apache.commons.lang3.StringUtils;
+import org.apache.pulsar.manager.utils.ResourceType;
import org.hibernate.validator.constraints.Range;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
@@ -36,7 +45,10 @@ import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
+import javax.servlet.http.HttpServletRequest;
import javax.validation.constraints.Min;
+import java.util.ArrayList;
+import java.util.List;
import java.util.Map;
import java.util.Optional;
@@ -53,14 +65,38 @@ public class EnvironmentsController {
private String pulsarJwtToken;
private final EnvironmentsRepository environmentsRepository;
+
private final EnvironmentCacheService environmentCacheService;
- @Autowired
+ private final UsersRepository usersRepository;
+
+ private final TenantsRepository tenantsRepository;
+
+ private final RolesRepository rolesRepository;
+
+ private final RoleBindingRepository roleBindingRepository;
+
+ private final RolesService rolesService;
+
+ private final HttpServletRequest request;
+
public EnvironmentsController(
+ HttpServletRequest request,
EnvironmentsRepository environmentsRepository,
- EnvironmentCacheService environmentCacheService) {
+ EnvironmentCacheService environmentCacheService,
+ UsersRepository usersRepository,
+ TenantsRepository tenantsRepository,
+ RolesRepository rolesRepository,
+ RoleBindingRepository roleBindingRepository,
+ RolesService rolesService) {
this.environmentsRepository = environmentsRepository;
this.environmentCacheService = environmentCacheService;
+ this.request = request;
+ this.usersRepository = usersRepository;
+ this.tenantsRepository = tenantsRepository;
+ this.rolesRepository = rolesRepository;
+ this.roleBindingRepository = roleBindingRepository;
+ this.rolesService = rolesService;
}
@ApiOperation(value = "Get the list of existing environments, support
paging, the default is 10 per page")
@@ -78,10 +114,42 @@ public class EnvironmentsController {
@RequestParam(name="page_size", defaultValue = "10")
@Range(min = 1, max = 1000, message = "page_size is incorrect,
should be greater than 0 and less than 1000.")
Integer pageSize) {
- Page<EnvironmentEntity> environmentEntityPage =
environmentsRepository.getEnvironmentsList(pageNum, pageSize);
+ String token = request.getHeader("token");
Map<String, Object> result = Maps.newHashMap();
- result.put("total", environmentEntityPage.getTotal());
- result.put("data", environmentEntityPage);
+ List<EnvironmentEntity> environmentEntities;
+ if (!rolesService.isSuperUser(token)) {
+ Optional<UserInfoEntity> userInfoEntityOptional =
usersRepository.findByAccessToken(token);
+ // There is no need to check whether the user exists again; the
user must exist.
+ UserInfoEntity userInfoEntity = userInfoEntityOptional.get();
+ long userId = userInfoEntity.getUserId();
+ List<RoleBindingEntity> roleBindingInfoEntities =
roleBindingRepository.findByUserId(userId);
+ List<Long> roleIdList = new ArrayList<>();
+ List<String> environmentList = new ArrayList<>();
+ for (RoleBindingEntity roleInfoEntity : roleBindingInfoEntities) {
+ roleIdList.add(roleInfoEntity.getRoleId());
+ }
+ if (!roleIdList.isEmpty()) {
+ List<RoleInfoEntity> roleInfoEntities =
rolesRepository.findAllRolesByMultiId(roleIdList);
+ List<Long> tenantsIdList = new ArrayList<>();
+ for (RoleInfoEntity roleInfoEntity : roleInfoEntities) {
+ if
(roleInfoEntity.getResourceType().equals(ResourceType.TENANTS.name())) {
+ tenantsIdList.add(roleInfoEntity.getResourceId());
+ }
+ }
+ if (!tenantsIdList.isEmpty()) {
+ List<TenantEntity> tenantEntities =
tenantsRepository.findByMultiId(tenantsIdList);
+ for (TenantEntity tenantEntity : tenantEntities) {
+ environmentList.add(tenantEntity.getEnvironmentName());
+ }
+ }
+ }
+ environmentEntities =
environmentsRepository.getAllEnvironments(environmentList);
+ } else {
+ environmentEntities = environmentsRepository.getAllEnvironments();
+ }
+
+ result.put("total", environmentEntities.size());
+ result.put("data", environmentEntities);
return ResponseEntity.ok(result);
}
@@ -93,9 +161,14 @@ public class EnvironmentsController {
@RequestMapping(value = "/environments/environment", method =
RequestMethod.PUT)
public ResponseEntity<Map<String, Object>> addEnvironment(
@RequestBody EnvironmentEntity environmentEntity) {
+ Map<String, Object> result = Maps.newHashMap();
+ String token = request.getHeader("token");
+ if (!rolesService.isSuperUser(token)) {
+ result.put("error", "User does not have permission to operate");
+ return ResponseEntity.ok(result);
+ }
Optional<EnvironmentEntity> environmentEntityBrokerOptional =
environmentsRepository
.findByBroker(environmentEntity.getBroker());
- Map<String, Object> result = Maps.newHashMap();
if (environmentEntityBrokerOptional.isPresent()) {
result.put("error", "Broker is exist");
return ResponseEntity.ok(result);
@@ -133,9 +206,14 @@ public class EnvironmentsController {
})
@RequestMapping(value = "/environments/environment", method =
RequestMethod.POST)
public ResponseEntity<Map<String, Object>> updateEnvironment(@RequestBody
EnvironmentEntity environmentEntity) {
+ Map<String, Object> result = Maps.newHashMap();
+ String token = request.getHeader("token");
+ if (!rolesService.isSuperUser(token)) {
+ result.put("error", "User does not have permission to operate");
+ return ResponseEntity.ok(result);
+ }
Optional<EnvironmentEntity> environmentEntityOptional =
environmentsRepository
.findByName(environmentEntity.getName());
- Map<String, Object> result = Maps.newHashMap();
if (!environmentEntityOptional.isPresent()) {
result.put("error", "Environment no exist");
return ResponseEntity.ok(result);
@@ -163,9 +241,14 @@ public class EnvironmentsController {
})
@RequestMapping(value = "/environments/environment", method =
RequestMethod.DELETE)
public ResponseEntity<Map<String, Object>> deleteEnvironment(@RequestBody
EnvironmentEntity environmentEntity) {
+ Map<String, Object> result = Maps.newHashMap();
+ String token = request.getHeader("token");
+ if (!rolesService.isSuperUser(token)) {
+ result.put("error", "User does not have permission to operate");
+ return ResponseEntity.ok(result);
+ }
Optional<EnvironmentEntity> environmentEntityOptional =
environmentsRepository
.findByName(environmentEntity.getName());
- Map<String, Object> result = Maps.newHashMap();
if (!environmentEntityOptional.isPresent()) {
result.put("error", "Environment no exist");
return ResponseEntity.ok(result);
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 f52e27d..4973a32 100644
--- a/src/main/java/org/apache/pulsar/manager/controller/LoginController.java
+++ b/src/main/java/org/apache/pulsar/manager/controller/LoginController.java
@@ -16,6 +16,10 @@ package org.apache.pulsar.manager.controller;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
+import org.apache.pulsar.manager.entity.RoleBindingEntity;
+import org.apache.pulsar.manager.entity.RoleBindingRepository;
+import org.apache.pulsar.manager.entity.RoleInfoEntity;
+import org.apache.pulsar.manager.entity.RolesRepository;
import org.apache.pulsar.manager.entity.UserInfoEntity;
import org.apache.pulsar.manager.entity.UsersRepository;
import org.apache.pulsar.manager.service.JwtService;
@@ -23,7 +27,6 @@ import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
-import org.apache.pulsar.manager.service.RolesService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpHeaders;
@@ -38,6 +41,8 @@ import
org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
+import java.util.ArrayList;
+import java.util.List;
import java.util.Map;
import java.util.Optional;
@@ -71,7 +76,10 @@ public class LoginController {
private UsersRepository usersRepository;
@Autowired
- private RolesService rolesService;
+ private RolesRepository rolesRepository;
+
+ @Autowired
+ private RoleBindingRepository roleBindingRepository;
@ApiOperation(value = "Login pulsar manager")
@ApiResponses({
@@ -106,9 +114,22 @@ public class LoginController {
headers.add("username", userAccount);
headers.add("tenant", userAccount);
jwtService.setToken(request.getSession().getId(), token);
- // Create default role and tenant
- rolesService.createDefaultRoleAndTenant(userAccount);
-
+ List<RoleBindingEntity> roleBindingEntities =
roleBindingRepository.
+ findByUserId(userInfoEntity.getUserId());
+ List<Long> roleIdList = new ArrayList<>();
+ for (RoleBindingEntity roleBindingEntity : roleBindingEntities) {
+ roleIdList.add(roleBindingEntity.getRoleId());
+ }
+ if (!roleIdList.isEmpty()) {
+ List<RoleInfoEntity> roleInfoEntities =
rolesRepository.findAllRolesByMultiId(roleIdList);
+ for (RoleInfoEntity roleInfoEntity : roleInfoEntities) {
+ if (roleInfoEntity.getFlag() == 0) {
+ // Super users can access all types
+ return new ResponseEntity<>(result, headers,
HttpStatus.OK);
+ }
+ }
+ }
+ headers.add("role", "admin");
return new ResponseEntity<>(result, headers, HttpStatus.OK);
}
if (userAccount.equals(account) && userPassword.equals(password)) {
diff --git
a/src/main/java/org/apache/pulsar/manager/controller/RoleBindingController.java
b/src/main/java/org/apache/pulsar/manager/controller/RoleBindingController.java
index a0937c4..5fb477d 100644
---
a/src/main/java/org/apache/pulsar/manager/controller/RoleBindingController.java
+++
b/src/main/java/org/apache/pulsar/manager/controller/RoleBindingController.java
@@ -86,6 +86,12 @@ public class RoleBindingController {
RequestContextHolder.getRequestAttributes()).getRequest();
String token = request.getHeader("token");
String tenant = request.getHeader("tenant");
+ if (rolesService.isSuperUser(token)) {
+ List<Map<String, Object>> roleBindingList =
roleBindingService.getAllRoleBindingList();
+ result.put("total", roleBindingList.size());
+ result.put("data", roleBindingList);
+ return ResponseEntity.ok(result);
+ }
Map<String, String> validateResult =
rolesService.validateCurrentTenant(token, tenant);
if (validateResult.get("error") != null) {
result.put("error", validateResult.get("error"));
diff --git
a/src/main/java/org/apache/pulsar/manager/controller/RolesController.java
b/src/main/java/org/apache/pulsar/manager/controller/RolesController.java
index ca5cef4..0f94ddb 100644
--- a/src/main/java/org/apache/pulsar/manager/controller/RolesController.java
+++ b/src/main/java/org/apache/pulsar/manager/controller/RolesController.java
@@ -27,7 +27,6 @@ import org.apache.pulsar.manager.entity.RolesRepository;
import org.apache.pulsar.manager.service.RolesService;
import org.apache.pulsar.manager.utils.ResourceType;
import org.hibernate.validator.constraints.Range;
-import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PathVariable;
@@ -36,8 +35,6 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
-import org.springframework.web.context.request.RequestContextHolder;
-import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import javax.validation.constraints.Min;
@@ -54,14 +51,24 @@ import java.util.Set;
@Validated
public class RolesController {
- @Autowired
- private RolesRepository rolesRepository;
+ private final RolesRepository rolesRepository;
- @Autowired
- private RolesService rolesService;
+ private final RolesService rolesService;
- @Autowired
- private NamespacesRepository namespacesRepository;
+ private final NamespacesRepository namespacesRepository;
+
+ private final HttpServletRequest request;
+
+ public RolesController(
+ RolesRepository rolesRepository,
+ RolesService rolesService,
+ NamespacesRepository namespacesRepository,
+ HttpServletRequest request) {
+ this.rolesRepository = rolesRepository;
+ this.rolesService = rolesService;
+ this.namespacesRepository = namespacesRepository;
+ this.request = request;
+ }
@ApiOperation(value = "Get the list of existing roles, support paging, the
default is 10 per page")
@ApiResponses({
@@ -79,11 +86,15 @@ public class RolesController {
@RequestParam(name = "page_size", defaultValue = "10")
@Range(min = 1, max = 1000, message = "page_size is incorrect,
should be greater than 0 and less than 1000.")
Integer pageSize) {
- HttpServletRequest request = ((ServletRequestAttributes)
- RequestContextHolder.getRequestAttributes()).getRequest();
String token = request.getHeader("token");
Map<String, Object> result = Maps.newHashMap();
String tenant = request.getHeader("tenant");
+ if (rolesService.isSuperUser(token)) {
+ List<RoleInfoEntity> roleInfoEntities =
rolesRepository.findAllRolesList();
+ result.put("total", roleInfoEntities.size());
+ result.put("data", roleInfoEntities);
+ return ResponseEntity.ok(result);
+ }
Map<String, String> validateResult =
rolesService.validateCurrentTenant(token, tenant);
if (validateResult.get("error") != null) {
result.put("error", validateResult.get("error"));
@@ -105,8 +116,6 @@ public class RolesController {
@RequestMapping(value = "/roles/role", method = RequestMethod.PUT)
public ResponseEntity<Map<String, Object>> addRole(
@RequestBody RoleInfoEntity roleInfoEntity) {
- HttpServletRequest request = ((ServletRequestAttributes)
- RequestContextHolder.getRequestAttributes()).getRequest();
String token = request.getHeader("token");
Map<String, Object> result = Maps.newHashMap();
String tenant = request.getHeader("tenant");
@@ -149,8 +158,6 @@ public class RolesController {
@RequestMapping(value = "/roles/role", method = RequestMethod.POST)
public ResponseEntity<Map<String, Object>> updateRole(@RequestBody
RoleInfoEntity roleInfoEntity) {
Map<String, Object> result = Maps.newHashMap();
- HttpServletRequest request = ((ServletRequestAttributes)
- RequestContextHolder.getRequestAttributes()).getRequest();
String token = request.getHeader("token");
String tenant = request.getHeader("tenant");
Map<String, String> validateResult =
rolesService.validateCurrentTenant(token, tenant);
@@ -192,8 +199,6 @@ public class RolesController {
@RequestMapping(value = "/roles/role", method = RequestMethod.DELETE)
public ResponseEntity<Map<String, Object>> deleteRole(@RequestBody
RoleInfoEntity roleInfoEntity) {
Map<String, Object> result = Maps.newHashMap();
- HttpServletRequest request = ((ServletRequestAttributes)
- RequestContextHolder.getRequestAttributes()).getRequest();
String token = request.getHeader("token");
String tenant = request.getHeader("tenant");
Map<String, String> validateResult =
rolesService.validateCurrentTenant(token, tenant);
@@ -240,8 +245,6 @@ public class RolesController {
@RequestMapping(value = "/role/resource/{resourceType}", method =
RequestMethod.GET)
public ResponseEntity<Map<String, Object>> getResource(@PathVariable
String resourceType) {
Map<String, Object> result = Maps.newHashMap();
- HttpServletRequest request = ((ServletRequestAttributes)
- RequestContextHolder.getRequestAttributes()).getRequest();
String token = request.getHeader("token");
String tenant = request.getHeader("tenant");
Map<String, String> validateResult =
rolesService.validateCurrentTenant(token, tenant);
diff --git
a/src/main/java/org/apache/pulsar/manager/controller/TenantsController.java
b/src/main/java/org/apache/pulsar/manager/controller/TenantsController.java
index 9fa86d6..1319048 100644
--- a/src/main/java/org/apache/pulsar/manager/controller/TenantsController.java
+++ b/src/main/java/org/apache/pulsar/manager/controller/TenantsController.java
@@ -13,13 +13,24 @@
*/
package org.apache.pulsar.manager.controller;
+import com.google.common.collect.Maps;
+import org.apache.pulsar.manager.entity.RoleBindingEntity;
+import org.apache.pulsar.manager.entity.RoleBindingRepository;
+import org.apache.pulsar.manager.entity.RoleInfoEntity;
+import org.apache.pulsar.manager.entity.RolesRepository;
+import org.apache.pulsar.manager.entity.TenantEntity;
+import org.apache.pulsar.manager.entity.TenantsRepository;
+import org.apache.pulsar.manager.entity.UserInfoEntity;
+import org.apache.pulsar.manager.entity.UsersRepository;
import org.apache.pulsar.manager.service.EnvironmentCacheService;
+import org.apache.pulsar.manager.service.RolesService;
import org.apache.pulsar.manager.service.TenantsService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
+import org.apache.pulsar.manager.utils.ResourceType;
import org.hibernate.validator.constraints.Range;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
@@ -31,7 +42,10 @@ import
org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import javax.validation.constraints.Min;
+import java.util.ArrayList;
+import java.util.List;
import java.util.Map;
+import java.util.Optional;
/**
* Tenant Query class.
@@ -43,17 +57,38 @@ import java.util.Map;
public class TenantsController {
private final TenantsService tenantsService;
+
private final EnvironmentCacheService environmentCacheService;
+
private final HttpServletRequest request;
- @Autowired
+ private final UsersRepository usersRepository;
+
+ private final RoleBindingRepository roleBindingRepository;
+
+ private final RolesRepository rolesRepository;
+
+ private final RolesService rolesService;
+
+ private final TenantsRepository tenantsRepository;
+
public TenantsController(
+ HttpServletRequest request,
TenantsService tenantsService,
EnvironmentCacheService environmentCacheService,
- HttpServletRequest request) {
+ UsersRepository usersRepository,
+ RoleBindingRepository roleBindingRepository,
+ RolesRepository rolesRepository,
+ RolesService rolesService,
+ TenantsRepository tenantsRepository) {
+ this.request = request;
this.tenantsService = tenantsService;
this.environmentCacheService = environmentCacheService;
- this.request = request;
+ this.usersRepository = usersRepository;
+ this.roleBindingRepository = roleBindingRepository;
+ this.rolesRepository = rolesRepository;
+ this.rolesService = rolesService;
+ this.tenantsRepository = tenantsRepository;
}
@ApiOperation(value = "Get the list of existing tenants, support paging,
the default is 10 per page")
@@ -72,8 +107,41 @@ public class TenantsController {
@RequestParam(name="page_size", defaultValue = "10")
@Range(min = 1, max = 1000, message = "page_size is incorrect, should
be greater than 0 and less than 1000.")
Integer pageSize) {
+ String token = request.getHeader("token");
+ Map<String, Object> result = Maps.newHashMap();
+ if (!rolesService.isSuperUser(token)) {
+ List<TenantEntity> tenantEntities = null;
+ Optional<UserInfoEntity> userInfoEntityOptional =
usersRepository.findByAccessToken(token);
+ // There is no need to check whether the user exists again; the
user must exist.
+ UserInfoEntity userInfoEntity = userInfoEntityOptional.get();
+ long userId = userInfoEntity.getUserId();
+ List<RoleBindingEntity> roleBindingInfoEntities =
roleBindingRepository.findByUserId(userId);
+ List<Long> roleIdList = new ArrayList<>();
+ for (RoleBindingEntity roleInfoEntity : roleBindingInfoEntities) {
+ roleIdList.add(roleInfoEntity.getRoleId());
+ }
+ if (!roleIdList.isEmpty()) {
+ List<RoleInfoEntity> roleInfoEntities =
rolesRepository.findAllRolesByMultiId(roleIdList);
+ List<Long> tenantsIdList = new ArrayList<>();
+ for (RoleInfoEntity roleInfoEntity : roleInfoEntities) {
+ tenantsIdList.add(roleInfoEntity.getResourceId());
+ }
+ if (!tenantsIdList.isEmpty()) {
+ tenantEntities =
tenantsRepository.findByMultiId(tenantsIdList);
+ }
+ }
+ if (tenantEntities != null) {
+ result.put("data", tenantEntities);
+ result.put("total", tenantEntities.size());
+ result.put("isPage", false);
+ return ResponseEntity.ok(result);
+ } else {
+ result.put("error", "Get tenant error");
+ return ResponseEntity.ok(result);
+ }
+ }
String requestHost = environmentCacheService.getServiceUrl(request);
- Map<String, Object> result = tenantsService.getTenantsList(pageNum,
pageSize, requestHost);
+ result = tenantsService.getTenantsList(pageNum, pageSize, requestHost);
return ResponseEntity.ok(result);
}
}
diff --git
a/src/main/java/org/apache/pulsar/manager/controller/UsersController.java
b/src/main/java/org/apache/pulsar/manager/controller/UsersController.java
index e740f16..df46f94 100644
--- a/src/main/java/org/apache/pulsar/manager/controller/UsersController.java
+++ b/src/main/java/org/apache/pulsar/manager/controller/UsersController.java
@@ -15,6 +15,7 @@ package org.apache.pulsar.manager.controller;
import com.github.pagehelper.Page;
import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
@@ -23,22 +24,36 @@ import io.swagger.annotations.ApiResponses;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.validator.routines.EmailValidator;
+import org.apache.pulsar.manager.entity.RoleBindingEntity;
+import org.apache.pulsar.manager.entity.RoleBindingRepository;
+import org.apache.pulsar.manager.entity.RoleInfoEntity;
+import org.apache.pulsar.manager.entity.RolesRepository;
import org.apache.pulsar.manager.entity.UserInfoEntity;
import org.apache.pulsar.manager.entity.UsersRepository;
+import org.apache.pulsar.manager.service.RolesService;
import org.apache.pulsar.manager.service.UsersService;
+import org.apache.pulsar.manager.utils.ResourceType;
+import org.apache.pulsar.manager.utils.ResourceVerbs;
import org.hibernate.validator.constraints.Range;
import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.context.request.RequestContextHolder;
+import org.springframework.web.context.request.ServletRequestAttributes;
+import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import javax.validation.constraints.Min;
+import java.util.ArrayList;
+import java.util.List;
import java.util.Map;
import java.util.Optional;
+import java.util.Set;
/**
* Users management controller.
@@ -48,11 +63,39 @@ import java.util.Optional;
@Api(description = "Functions under this class are available to super user.")
public class UsersController {
- @Autowired
- private UsersRepository usersRepository;
+ @Value("${user.management.enable}")
+ private boolean userManagementEnable;
+
+ @Value("${pulsar-manager.account}")
+ private String account;
+
+ private final UsersRepository usersRepository;
+
+ private final UsersService usersService;
+
+ private final RolesRepository rolesRepository;
+
+ private final RoleBindingRepository roleBindingRepository;
+
+ private final RolesService rolesService;
+
+ private final HttpServletRequest request;
@Autowired
- private UsersService usersService;
+ public UsersController(
+ UsersRepository usersRepository,
+ UsersService usersService,
+ RolesRepository rolesRepository,
+ RoleBindingRepository roleBindingRepository,
+ RolesService rolesService,
+ HttpServletRequest request) {
+ this.usersRepository = usersRepository;
+ this.usersService = usersService;
+ this.rolesRepository = rolesRepository;
+ this.roleBindingRepository = roleBindingRepository;
+ this.rolesService = rolesService;
+ this.request = request;
+ }
@ApiOperation(value = "Get users list")
@ApiResponses({
@@ -99,6 +142,13 @@ public class UsersController {
}
userInfoEntity.setPassword(DigestUtils.sha256Hex(userInfoEntity.getPassword()));
usersRepository.save(userInfoEntity);
+ // Create default role and tenant
+ Map<String, String> defaultRoleCreate =
rolesService.createDefaultRoleAndTenant(
+ userInfoEntity.getName(), request.getHeader("environment"));
+ if (defaultRoleCreate.get("error") != null) {
+ result.put("error", defaultRoleCreate.get("error"));
+ return ResponseEntity.ok(result);
+ }
result.put("message", "Create user success");
return ResponseEntity.ok(result);
}
@@ -151,4 +201,101 @@ public class UsersController {
result.put("message", "Delete a user success");
return ResponseEntity.ok(result);
}
+
+ @ApiOperation(value = "Get user info")
+ @ApiResponses({
+ @ApiResponse(code = 200, message = "ok"),
+ @ApiResponse(code = 404, message = "Not found"),
+ @ApiResponse(code = 500, message = "Internal server error")
+ })
+ @RequestMapping(value = "/users/userInfo", method = RequestMethod.GET)
+ public ResponseEntity<Map<String, Object>> getUserInfo() {
+ Map<String, Object> result = Maps.newHashMap();
+ Set<String> roles = Sets.newHashSet();
+ if (userManagementEnable) {
+ HttpServletRequest request = ((ServletRequestAttributes)
RequestContextHolder.getRequestAttributes()).getRequest();
+ String token = request.getHeader("token");
+ Optional<UserInfoEntity> userInfoEntityOptional =
usersRepository.findByAccessToken(token);
+ if (!userInfoEntityOptional.isPresent()) {
+ result.put("error", "User is no exist");
+ return ResponseEntity.ok(result);
+ }
+ UserInfoEntity userInfoEntity = userInfoEntityOptional.get();
+ List<RoleBindingEntity> roleBindingEntities =
roleBindingRepository.findByUserId(userInfoEntity.getUserId());
+ List<Long> roleIdList = new ArrayList<>();
+ for (RoleBindingEntity roleBindingEntity : roleBindingEntities) {
+ roleIdList.add(roleBindingEntity.getRoleId());
+ }
+ List<RoleInfoEntity> roleInfoEntities =
rolesRepository.findAllRolesByMultiId(roleIdList);
+ for (RoleInfoEntity roleInfoEntity : roleInfoEntities) {
+ if (roleInfoEntity.getFlag() == 0) {
+ result.put("message", "Get user info success");
+ result.put("userName", userInfoEntity.getName());
+ result.put("description", userInfoEntity.getDescription());
+ roles.add("super");
+ result.put("roles", roles);
+ return ResponseEntity.ok(result);
+ }
+ }
+ result.put("message", "Get user info success");
+ result.put("userName", userInfoEntity.getName());
+ result.put("description", userInfoEntity.getDescription());
+ roles.add("admin");
+ result.put("roles", roles);
+ return ResponseEntity.ok(result);
+ }
+ result.put("message", "Get user info success");
+ result.put("description", "This is super account");
+ result.put("userName", account);
+ roles.add("super");
+ result.put("roles", roles);
+ return ResponseEntity.ok(result);
+ }
+
+ @ApiOperation(value = "Add a super user, only used when the platform is
initialized for the first time.")
+ @ApiResponses({
+ @ApiResponse(code = 200, message = "ok"),
+ @ApiResponse(code = 404, message = "Not found"),
+ @ApiResponse(code = 500, message = "Internal server error")
+ })
+ @RequestMapping(value = "/users/superuser", method = RequestMethod.PUT)
+ public ResponseEntity<Map<String, Object>> createSuperUser(@RequestBody
UserInfoEntity userInfoEntity) {
+ Map<String, Object> result = Maps.newHashMap();
+ // 0 is super role
+ Optional<RoleInfoEntity> roleInfoEntityOptional =
rolesRepository.findByRoleFlag(0);
+ if (roleInfoEntityOptional.isPresent()) {
+ result.put("error", "Super user role is exist, this interface is
no longer available");
+ return ResponseEntity.ok(result);
+ }
+ Map<String, String> userValidateResult =
usersService.validateUserInfo(userInfoEntity);
+ if (userValidateResult.get("error") != null) {
+ result.put("error", userValidateResult.get("error"));
+ return ResponseEntity.ok(result);
+ }
+ if (StringUtils.isBlank(userInfoEntity.getPassword())) {
+ result.put("error", "Please provider password");
+ return ResponseEntity.ok(result);
+ }
+
+ RoleInfoEntity roleInfoEntity = new RoleInfoEntity();
+ roleInfoEntity.setRoleName(userInfoEntity.getName());
+ roleInfoEntity.setResourceId(0);
+ roleInfoEntity.setRoleSource(roleInfoEntity.getRoleName());
+ roleInfoEntity.setResourceType(ResourceType.ALL.name());
+ roleInfoEntity.setResourceName("superuser");
+ roleInfoEntity.setResourceVerbs(ResourceVerbs.SUPER_USER.name());
+ roleInfoEntity.setFlag(0);
+ roleInfoEntity.setDescription("This is super role");
+ long roleId = rolesRepository.save(roleInfoEntity);
+
userInfoEntity.setPassword(DigestUtils.sha256Hex(userInfoEntity.getPassword()));
+ long userId = usersRepository.save(userInfoEntity);
+ RoleBindingEntity roleBindingEntity = new RoleBindingEntity();
+ roleBindingEntity.setDescription("This is super role binding");
+ roleBindingEntity.setName("super_user_role_binding");
+ roleBindingEntity.setRoleId(roleId);
+ roleBindingEntity.setUserId(userId);
+ roleBindingRepository.save(roleBindingEntity);
+ result.put("message", "Add super user success, please login");
+ return ResponseEntity.ok(result);
+ }
}
diff --git
a/src/main/java/org/apache/pulsar/manager/dao/EnvironmentsRepositoryImpl.java
b/src/main/java/org/apache/pulsar/manager/dao/EnvironmentsRepositoryImpl.java
index a0b570a..0e4d943 100644
---
a/src/main/java/org/apache/pulsar/manager/dao/EnvironmentsRepositoryImpl.java
+++
b/src/main/java/org/apache/pulsar/manager/dao/EnvironmentsRepositoryImpl.java
@@ -64,6 +64,11 @@ public class EnvironmentsRepositoryImpl implements
EnvironmentsRepository {
}
@Override
+ public List<EnvironmentEntity> getAllEnvironments(List<String>
envonmentNameList) {
+ return
environmentsMapper.findEnvironmentsListByMultiName(envonmentNameList);
+ }
+
+ @Override
public void remove(String name) {
environmentsMapper.delete(name);
}
diff --git
a/src/main/java/org/apache/pulsar/manager/dao/RoleBindingRepositoryImpl.java
b/src/main/java/org/apache/pulsar/manager/dao/RoleBindingRepositoryImpl.java
index d1f64cd..f635f2f 100644
--- a/src/main/java/org/apache/pulsar/manager/dao/RoleBindingRepositoryImpl.java
+++ b/src/main/java/org/apache/pulsar/manager/dao/RoleBindingRepositoryImpl.java
@@ -63,6 +63,11 @@ public class RoleBindingRepositoryImpl implements
RoleBindingRepository {
}
@Override
+ public List<RoleBindingEntity> findAllRoleBindingList() {
+ return this.roleBindingMapper.findAllRoleBindinglist();
+ }
+
+ @Override
public List<RoleBindingEntity> findByMultiRoleId(List<Long> roleIdList) {
return this.roleBindingMapper.findByMultiRoleId(roleIdList);
}
diff --git
a/src/main/java/org/apache/pulsar/manager/dao/RolesRepositoryImpl.java
b/src/main/java/org/apache/pulsar/manager/dao/RolesRepositoryImpl.java
index 5071ea4..497afdc 100644
--- a/src/main/java/org/apache/pulsar/manager/dao/RolesRepositoryImpl.java
+++ b/src/main/java/org/apache/pulsar/manager/dao/RolesRepositoryImpl.java
@@ -46,12 +46,22 @@ public class RolesRepositoryImpl implements RolesRepository
{
}
@Override
+ public Optional<RoleInfoEntity> findByRoleFlag(int flag) {
+ return Optional.ofNullable(this.rolesMapper.findByRoleFlag(flag));
+ }
+
+ @Override
public Page<RoleInfoEntity> findRolesList(Integer pageNum, Integer
pageSize) {
PageHelper.startPage(pageNum, pageSize);
return this.rolesMapper.findRoleList();
}
@Override
+ public List<RoleInfoEntity> findAllRolesList() {
+ return this.rolesMapper.findAllRoleList();
+ }
+
+ @Override
public List<RoleInfoEntity> findRolesListByRoleSource(String roleSource) {
return this.rolesMapper.findRoleListByRoleSource(roleSource);
}
diff --git
a/src/main/java/org/apache/pulsar/manager/entity/EnvironmentsRepository.java
b/src/main/java/org/apache/pulsar/manager/entity/EnvironmentsRepository.java
index 7e65fd4..3f9a082 100644
--- a/src/main/java/org/apache/pulsar/manager/entity/EnvironmentsRepository.java
+++ b/src/main/java/org/apache/pulsar/manager/entity/EnvironmentsRepository.java
@@ -32,6 +32,8 @@ public interface EnvironmentsRepository {
List<EnvironmentEntity> getAllEnvironments();
+ List<EnvironmentEntity> getAllEnvironments(List<String> envonmentNameList);
+
void remove(String name);
void update(EnvironmentEntity environmentEntity);
diff --git
a/src/main/java/org/apache/pulsar/manager/entity/RoleBindingRepository.java
b/src/main/java/org/apache/pulsar/manager/entity/RoleBindingRepository.java
index c541cbf..38a44db 100644
--- a/src/main/java/org/apache/pulsar/manager/entity/RoleBindingRepository.java
+++ b/src/main/java/org/apache/pulsar/manager/entity/RoleBindingRepository.java
@@ -67,6 +67,12 @@ public interface RoleBindingRepository {
Page<RoleBindingEntity> getRoleBindingList(Integer pageNum, Integer
pageSize);
/**
+ * Get all role binding list.
+ * @return A list of RoleBindingEntity
+ */
+ List<RoleBindingEntity> findAllRoleBindingList();
+
+ /**
* Update a role binding information
* @param roleBindingEntity RoleInfoEntity
*/
diff --git
a/src/main/java/org/apache/pulsar/manager/entity/RolesRepository.java
b/src/main/java/org/apache/pulsar/manager/entity/RolesRepository.java
index e14c068..ce14ddf 100644
--- a/src/main/java/org/apache/pulsar/manager/entity/RolesRepository.java
+++ b/src/main/java/org/apache/pulsar/manager/entity/RolesRepository.java
@@ -36,6 +36,12 @@ public interface RolesRepository {
*/
Optional<RoleInfoEntity> findByRoleName(String roleName, String
roleSource);
+ /**
+ * Get a role information by role flag
+ * @param flag The role flag
+ * @return RoleInfoEntity
+ */
+ Optional<RoleInfoEntity> findByRoleFlag(int flag);
/**
* Get role list, support paging.
@@ -46,6 +52,12 @@ public interface RolesRepository {
Page<RoleInfoEntity> findRolesList(Integer pageNum, Integer pageSize);
/**
+ * Get all role list
+ * @return A list of RoleInfoEntity.
+ */
+ List<RoleInfoEntity> findAllRolesList();
+
+ /**
* Get role list.
* @param roleSource Role source, name of tenant
* @return A list of RoleInfoEntity.
@@ -62,7 +74,7 @@ public interface RolesRepository {
Page<RoleInfoEntity> findRolesMultiId(Integer pageNum, Integer pageSize,
List<Long> idList);
/**
- * Get all role list by role id, support paging.
+ * Get all role list by role id
* @param idList a list of role id
* @return A list of RoleInfoEntity.
*/
diff --git a/src/main/java/org/apache/pulsar/manager/entity/TenantEntity.java
b/src/main/java/org/apache/pulsar/manager/entity/TenantEntity.java
index 140be43..bb3e50f 100644
--- a/src/main/java/org/apache/pulsar/manager/entity/TenantEntity.java
+++ b/src/main/java/org/apache/pulsar/manager/entity/TenantEntity.java
@@ -40,4 +40,7 @@ public class TenantEntity {
private String adminRoles;
@SerializedName("allowed_clusters")
private String allowedClusters;
+
+ @SerializedName("environment_name")
+ private String environmentName;
}
\ No newline at end of file
diff --git
a/src/main/java/org/apache/pulsar/manager/interceptor/AdminHandlerInterceptor.java
b/src/main/java/org/apache/pulsar/manager/interceptor/AdminHandlerInterceptor.java
index e0e19f0..f59066c 100644
---
a/src/main/java/org/apache/pulsar/manager/interceptor/AdminHandlerInterceptor.java
+++
b/src/main/java/org/apache/pulsar/manager/interceptor/AdminHandlerInterceptor.java
@@ -21,10 +21,13 @@ import
org.apache.pulsar.manager.entity.EnvironmentsRepository;
import org.apache.pulsar.manager.entity.UserInfoEntity;
import org.apache.pulsar.manager.entity.UsersRepository;
import org.apache.pulsar.manager.service.JwtService;
+import org.apache.pulsar.manager.service.PulsarEvent;
+import org.apache.pulsar.manager.service.RolesService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Component;
+import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
@@ -52,33 +55,19 @@ public class AdminHandlerInterceptor extends
HandlerInterceptorAdapter {
@Value("${user.management.enable}")
private boolean userManagementEnable;
+ @Autowired
+ private RolesService rolesService;
+
+ @Autowired
+ private PulsarEvent pulsarEvent;
+
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse
response, Object handler) throws Exception {
String token = request.getHeader("token");
String saveToken = jwtService.getToken(request.getSession().getId());
Map<String, Object> map = Maps.newHashMap();
Gson gson = new Gson();
- if (saveToken == null ) {
- // Get token from database
- String username = request.getHeader("username");
- Optional<UserInfoEntity> userInfoEntityOptional =
usersRepository.findByUserName(username);
- if (!userInfoEntityOptional.isPresent()) {
- map.put("message", "Please login.");
- response.setStatus(401);
- response.getWriter().append(gson.toJson(map));
- return false;
- }
- UserInfoEntity userInfoEntity = userInfoEntityOptional.get();
- if (StringUtils.isBlank(userInfoEntity.getAccessToken())) {
- map.put("message", "The user token no find, please login");
- response.setStatus(401);
- response.getWriter().append(gson.toJson(map));
- return false;
- }
- jwtService.setToken(request.getSession().getId(),
userInfoEntity.getAccessToken());
- saveToken = jwtService.getToken(request.getSession().getId());
- }
- if (token == null && !token.equals(saveToken)) {
+ if (token == null || !token.equals(saveToken)) {
map.put("message", "Please login.");
response.setStatus(401);
response.getWriter().append(gson.toJson(map));
@@ -101,13 +90,44 @@ public class AdminHandlerInterceptor extends
HandlerInterceptorAdapter {
return false;
}
}
- String environment = request.getHeader("environment");
- Optional<EnvironmentEntity> environmentEntityOptional =
environmentsRepository.findByName(environment);
- if
(!request.getRequestURI().startsWith("/pulsar-manager/environments") &&
!environmentEntityOptional.isPresent()) {
- map.put("message", "Currently there is no active environment,
please set one");
- response.setStatus(400);
- response.getWriter().append(gson.toJson(map));
- return false;
+ String requestUri = request.getRequestURI();
+ if (!requestUri.equals("/pulsar-manager/users/userInfo")) {
+ String environment = request.getHeader("environment");
+ Optional<EnvironmentEntity> environmentEntityOptional =
environmentsRepository.findByName(environment);
+ if
(!request.getRequestURI().startsWith("/pulsar-manager/environments") &&
!environmentEntityOptional.isPresent()) {
+ map.put("message", "Currently there is no active environment,
please set one");
+ response.setStatus(400);
+ response.getWriter().append(gson.toJson(map));
+ return false;
+ }
+ }
+ if (!rolesService.isSuperUser(token)) {
+ if (requestUri.startsWith("/admin/v2/clusters")
+ || requestUri.startsWith("/admin/v2/brokers")) {
+ map.put("message", "This user no permissions for this
resource");
+ response.setStatus(401);
+ response.getWriter().append(gson.toJson(map));
+ return false;
+ }
+ if (requestUri.startsWith("/admin/v2/tenants")) {
+ if (request.getMethod() != "GET") {
+ map.put("message", "This user no permissions for this
resource");
+ response.setStatus(401);
+ response.getWriter().append(gson.toJson(map));
+ return false;
+ }
+ }
+ if (requestUri.startsWith("/pulsar-manager/admin/v2/namespaces")
+ ||
requestUri.startsWith("/pulsar-manager/admin/v2/persistent")
+ ||
requestUri.startsWith("/pulsar-manager/admin/v2/non-persistent")) {
+ Map<String, String> result =
pulsarEvent.validateTenantPermission(requestUri, token);
+ if (result.get("error") != null) {
+ map.put("message", result.get("error"));
+ response.setStatus(401);
+ response.getWriter().append(gson.toJson(map));
+ return false;
+ }
+ }
}
return true;
}
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 c79f4b8..c4d96b7 100644
--- a/src/main/java/org/apache/pulsar/manager/interceptor/WebAppConfigurer.java
+++ b/src/main/java/org/apache/pulsar/manager/interceptor/WebAppConfigurer.java
@@ -29,6 +29,7 @@ public class WebAppConfigurer implements WebMvcConfigurer {
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(adminHandlerInterceptor).addPathPatterns("/**")
.excludePathPatterns("/pulsar-manager/login")
+ .excludePathPatterns("/pulsar-manager/users/superuser")
.excludePathPatterns("/pulsar-manager/third-party-login/**");
}
}
diff --git
a/src/main/java/org/apache/pulsar/manager/mapper/EnvironmentsMapper.java
b/src/main/java/org/apache/pulsar/manager/mapper/EnvironmentsMapper.java
index 77abd91..74fb21b 100644
--- a/src/main/java/org/apache/pulsar/manager/mapper/EnvironmentsMapper.java
+++ b/src/main/java/org/apache/pulsar/manager/mapper/EnvironmentsMapper.java
@@ -34,6 +34,12 @@ public interface EnvironmentsMapper {
@Select("SELECT name,broker FROM environments")
Page<EnvironmentEntity> findEnvironmentsList();
+ @Select({"<script>",
+ "SELECT name,broker FROM environments",
+ "WHERE name IN <foreach collection='nameList' item='name' open='('
separator=',' close=')'> #{name} </foreach>" +
+ "</script>"})
+ Page<EnvironmentEntity> findEnvironmentsListByMultiName(@Param("nameList")
List<String> nameList);
+
@Select("SELECT name,broker FROM environments")
List<EnvironmentEntity> getAllEnvironments();
diff --git
a/src/main/java/org/apache/pulsar/manager/mapper/RoleBindingMapper.java
b/src/main/java/org/apache/pulsar/manager/mapper/RoleBindingMapper.java
index 728bec1..82cbf2f 100644
--- a/src/main/java/org/apache/pulsar/manager/mapper/RoleBindingMapper.java
+++ b/src/main/java/org/apache/pulsar/manager/mapper/RoleBindingMapper.java
@@ -58,6 +58,10 @@ public interface RoleBindingMapper {
"FROM role_binding")
Page<RoleBindingEntity> findRoleBindinglist();
+ @Select("SELECT name, role_binding_id as roleBindingId, description,
user_id as userId, role_id as roleId " +
+ "FROM role_binding")
+ List<RoleBindingEntity> findAllRoleBindinglist();
+
@Update("UPDATE role_binding " +
"SET description = #{description}, name = #{name},
role_id=#{roleId}, user_id=#{userId} " +
"Where role_binding_id=#{roleBindingId}")
diff --git a/src/main/java/org/apache/pulsar/manager/mapper/RolesMapper.java
b/src/main/java/org/apache/pulsar/manager/mapper/RolesMapper.java
index 95342b6..d2e8d87 100644
--- a/src/main/java/org/apache/pulsar/manager/mapper/RolesMapper.java
+++ b/src/main/java/org/apache/pulsar/manager/mapper/RolesMapper.java
@@ -42,6 +42,13 @@ public interface RolesMapper {
"WHERE role_name = #{roleName} and role_source = #{roleSource}")
RoleInfoEntity findByRoleName(@Param("roleName") String roleName,
@Param("roleSource") String roleSource);
+ @Select("SELECT role_id AS roleId, role_name AS roleName, description,
resource_type AS resourceType," +
+ "resource_name AS resourceName, resource_verbs AS resourceVerbs,
resource_id as resourceId," +
+ "role_source AS roleSource, flag " +
+ "FROM roles " +
+ "WHERE flag=#{flag} limit 1")
+ RoleInfoEntity findByRoleFlag(@Param("flag") int flag);
+
@Select("SELECT role_name AS roleName, role_id AS roleId, description,
resource_type AS resourceType," +
"resource_name AS resourceName, resource_verbs AS resourceVerbs,
resource_id as resourceId," +
"role_source AS roleSource, flag FROM roles")
@@ -49,6 +56,11 @@ public interface RolesMapper {
@Select("SELECT role_name AS roleName, role_id AS roleId, description,
resource_type AS resourceType," +
"resource_name AS resourceName, resource_verbs AS resourceVerbs,
resource_id as resourceId," +
+ "role_source AS roleSource, flag FROM roles")
+ List<RoleInfoEntity> findAllRoleList();
+
+ @Select("SELECT role_name AS roleName, role_id AS roleId, description,
resource_type AS resourceType," +
+ "resource_name AS resourceName, resource_verbs AS resourceVerbs,
resource_id as resourceId," +
"role_source AS roleSource, flag FROM roles WHERE
role_source=#{roleSource}")
List<RoleInfoEntity> findRoleListByRoleSource(String roleSource);
diff --git a/src/main/java/org/apache/pulsar/manager/mapper/TenantsMapper.java
b/src/main/java/org/apache/pulsar/manager/mapper/TenantsMapper.java
index 539de32..37fc2d1 100644
--- a/src/main/java/org/apache/pulsar/manager/mapper/TenantsMapper.java
+++ b/src/main/java/org/apache/pulsar/manager/mapper/TenantsMapper.java
@@ -29,33 +29,38 @@ import java.util.List;
@Mapper
public interface TenantsMapper {
- @Insert("INSERT INTO tenants (admin_roles, allowed_clusters, tenant) " +
- "VALUES (#{adminRoles}, #{allowedClusters}, #{tenant})")
+ @Insert("INSERT INTO tenants (admin_roles, allowed_clusters, tenant,
environment_name) " +
+ "VALUES (#{adminRoles}, #{allowedClusters}, #{tenant},
#{environmentName})")
@Options(useGeneratedKeys=true, keyProperty="tenantId",
keyColumn="tenant_id")
long insert(TenantEntity tenantEntity);
- @Select("SELECT tenant, tenant_id as tenantId, admin_roles as
adminRoles,allowed_clusters as allowedClusters " +
+ @Select("SELECT tenant, tenant_id as tenantId, admin_roles as
adminRoles,allowed_clusters as allowedClusters," +
+ "environment_name as environmentName " +
"FROM tenants WHERE tenant = #{tenant}")
TenantEntity findByName(String tenant);
- @Select("SELECT tenant, tenant_id as tenantId, admin_roles as
adminRoles,allowed_clusters as allowedClusters " +
+ @Select("SELECT tenant, tenant_id as tenantId, admin_roles as
adminRoles,allowed_clusters as allowedClusters," +
+ "environment_name as environmentName " +
"FROM tenants WHERE tenant_id = #{tenantId}")
TenantEntity findByTenantId(long tenantId);
- @Select("SELECT tenant, tenant_id as tenantId, admin_roles as
adminRoles,allowed_clusters as allowedClusters " +
+ @Select("SELECT tenant, tenant_id as tenantId, admin_roles as
adminRoles,allowed_clusters as allowedClusters," +
+ "environment_name as environmentName " +
"FROM tenants")
Page<TenantEntity> getTenantsList();
@Select({"<script>",
- "SELECT tenant, tenant_id as tenantId, admin_roles as
adminRoles,allowed_clusters as allowedClusters" +
+ "SELECT tenant, tenant_id as tenantId, admin_roles as
adminRoles,allowed_clusters as allowedClusters," +
+ "environment_name as environmentName " +
" FROM tenants ",
"WHERE tenant_id IN <foreach collection='tenantIdList'
item='tenantId' open='(' separator=',' close=')'> #{tenantId} </foreach>" +
"</script>"})
Page<TenantEntity> findByMultiId(@Param("tenantIdList") List<Long>
tenantIdList);
@Select({"<script>",
- "SELECT tenant, tenant_id as tenantId, admin_roles as
adminRoles,allowed_clusters as allowedClusters" +
+ "SELECT tenant, tenant_id as tenantId, admin_roles as
adminRoles,allowed_clusters as allowedClusters," +
+ "environment_name as environmentName " +
" FROM tenants ",
"WHERE tenant_id IN <foreach collection='tenantIdList'
item='tenantId' open='(' separator=',' close=')'> #{tenantId} </foreach>" +
"</script>"})
diff --git a/src/main/java/org/apache/pulsar/manager/service/PulsarEvent.java
b/src/main/java/org/apache/pulsar/manager/service/PermissionsService.java
similarity index 80%
copy from src/main/java/org/apache/pulsar/manager/service/PulsarEvent.java
copy to src/main/java/org/apache/pulsar/manager/service/PermissionsService.java
index 595c399..cf7f979 100644
--- a/src/main/java/org/apache/pulsar/manager/service/PulsarEvent.java
+++ b/src/main/java/org/apache/pulsar/manager/service/PermissionsService.java
@@ -13,10 +13,7 @@
*/
package org.apache.pulsar.manager.service;
-import javax.servlet.http.HttpServletRequest;
-
-public interface PulsarEvent {
-
- void parsePulsarEvent(String path, HttpServletRequest httpRequest);
+public interface PermissionsService {
+ boolean hasPermissions(String path);
}
diff --git a/src/main/java/org/apache/pulsar/manager/service/PulsarEvent.java
b/src/main/java/org/apache/pulsar/manager/service/PulsarEvent.java
index 595c399..93cbf2f 100644
--- a/src/main/java/org/apache/pulsar/manager/service/PulsarEvent.java
+++ b/src/main/java/org/apache/pulsar/manager/service/PulsarEvent.java
@@ -14,9 +14,13 @@
package org.apache.pulsar.manager.service;
import javax.servlet.http.HttpServletRequest;
+import java.util.Map;
public interface PulsarEvent {
void parsePulsarEvent(String path, HttpServletRequest httpRequest);
+ Map<String, String> validateTenantPermission(String path, String token);
+
+ boolean validateRoutePermission(String path, String token);
}
diff --git
a/src/main/java/org/apache/pulsar/manager/service/RoleBindingService.java
b/src/main/java/org/apache/pulsar/manager/service/RoleBindingService.java
index 60d7645..9e5766e 100644
--- a/src/main/java/org/apache/pulsar/manager/service/RoleBindingService.java
+++ b/src/main/java/org/apache/pulsar/manager/service/RoleBindingService.java
@@ -25,4 +25,6 @@ public interface RoleBindingService {
Map<String, Object> validateCreateRoleBinding(String token, String tenant,
String roleName, String userName);
List<Map<String, Object>> getRoleBindingList(String token, String tenant);
+
+ List<Map<String, Object>> getAllRoleBindingList();
}
diff --git a/src/main/java/org/apache/pulsar/manager/service/RolesService.java
b/src/main/java/org/apache/pulsar/manager/service/RolesService.java
index 55ee61c..6b430af 100644
--- a/src/main/java/org/apache/pulsar/manager/service/RolesService.java
+++ b/src/main/java/org/apache/pulsar/manager/service/RolesService.java
@@ -22,9 +22,11 @@ public interface RolesService {
Map<String, String> validateRoleInfoEntity(RoleInfoEntity roleInfoEntity);
- void createDefaultRoleAndTenant(String tenant);
+ Map<String, String> createDefaultRoleAndTenant(String tenant, String
environment);
Set<String> getResourceVerbs(String resourceVerbs);
Map<String, String> validateCurrentTenant(String token, String tenant);
+
+ boolean isSuperUser(String token);
}
diff --git a/src/main/java/org/apache/pulsar/manager/service/PulsarEvent.java
b/src/main/java/org/apache/pulsar/manager/service/impl/PermissionsServiceImpl.java
similarity index 69%
copy from src/main/java/org/apache/pulsar/manager/service/PulsarEvent.java
copy to
src/main/java/org/apache/pulsar/manager/service/impl/PermissionsServiceImpl.java
index 595c399..6733783 100644
--- a/src/main/java/org/apache/pulsar/manager/service/PulsarEvent.java
+++
b/src/main/java/org/apache/pulsar/manager/service/impl/PermissionsServiceImpl.java
@@ -11,12 +11,14 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.pulsar.manager.service;
+package org.apache.pulsar.manager.service.impl;
-import javax.servlet.http.HttpServletRequest;
+import org.apache.pulsar.manager.service.PermissionsService;
-public interface PulsarEvent {
+public class PermissionsServiceImpl implements PermissionsService {
- void parsePulsarEvent(String path, HttpServletRequest httpRequest);
+ public boolean hasPermissions(String path) {
+ return false;
+ }
}
diff --git
a/src/main/java/org/apache/pulsar/manager/service/impl/PulsarEventImpl.java
b/src/main/java/org/apache/pulsar/manager/service/impl/PulsarEventImpl.java
index 2042e66..b1b6a4d 100644
--- a/src/main/java/org/apache/pulsar/manager/service/impl/PulsarEventImpl.java
+++ b/src/main/java/org/apache/pulsar/manager/service/impl/PulsarEventImpl.java
@@ -13,13 +13,16 @@
*/
package org.apache.pulsar.manager.service.impl;
+import com.google.common.collect.Maps;
import org.apache.pulsar.manager.entity.NamespaceEntity;
import org.apache.pulsar.manager.entity.NamespacesRepository;
import org.apache.pulsar.manager.service.PulsarEvent;
+import org.apache.pulsar.manager.service.RolesService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.servlet.http.HttpServletRequest;
+import java.util.Map;
@Service
public class PulsarEventImpl implements PulsarEvent {
@@ -30,8 +33,31 @@ public class PulsarEventImpl implements PulsarEvent {
private static final String HTTP_DELETE = "DELETE";
+ private static final String TENANTS_PREFIX = "/admin/v2/tenants/";
+
+ private static final String CLUSTERS_PREFIX = "/admin/v2/clusters";
+
+ private static final String BROKERS_PREFIX = "/admin/v2/brokers";
+
+ private static final String BROKERS_STATS_PREFIX =
"/admin/v2/broker-stats";
+
+ private static final String RESOURCES_QUOTAS_PREFIX =
"/admin/v2/resource-quotas";
+
private static final String NAMESPACES_PREFIX = "/admin/v2/namespaces";
+ private static final String PULSAR_MANAGER_NAMESPACES_PREFIX =
"/pulsar-manager/admin/v2/namespaces";
+
+ private static final String PERSISTENT_TOPIC_PREFIX =
"/admin/v2/persistent";
+
+ private static final String NON_PERSISTENT_TOPIC_PREFIX =
"/admin/v2/non-persistent";
+
+ private static final String PULSAR_MANAGER_TOPIC_PREFIX =
"/pulsar-manager/admin/v2/topics";
+
+ private static final String PULSAR_MANAGER_PREFIX = "/pulsar-manager";
+
+ @Autowired
+ private RolesService rolesService;
+
@Autowired
private NamespacesRepository namespacesRepository;
@@ -42,16 +68,88 @@ public class PulsarEventImpl implements PulsarEvent {
return false;
}
+ private boolean isNamespace(String path) {
+ if (path.startsWith(NAMESPACES_PREFIX) ||
path.startsWith(PULSAR_MANAGER_NAMESPACES_PREFIX)) {
+ return true;
+ }
+ return false;
+ }
+
+ private boolean isTopic(String path) {
+ if (path.startsWith(PERSISTENT_TOPIC_PREFIX)
+ || path.startsWith(NON_PERSISTENT_TOPIC_PREFIX)
+ || path.startsWith(PULSAR_MANAGER_TOPIC_PREFIX)) {
+ return true;
+ }
+ return false;
+ }
+
+ private boolean isTenant(String path) {
+ if (path.startsWith(TENANTS_PREFIX)) {
+ return true;
+ }
+ return false;
+ }
+
+ private boolean isCluster(String path) {
+ if (path.startsWith(CLUSTERS_PREFIX)) {
+ return true;
+ }
+ return false;
+ }
+
+ private boolean isBroker(String path) {
+ if (path.startsWith(BROKERS_PREFIX)) {
+ return true;
+ }
+ return false;
+ }
+
+ private boolean isBrokerStats(String path) {
+ if (path.startsWith(BROKERS_STATS_PREFIX)) {
+ return true;
+ }
+ return false;
+ }
+
+ private boolean isResourceQuota(String path) {
+ if (path.startsWith(RESOURCES_QUOTAS_PREFIX)) {
+ return true;
+ }
+ return false;
+ }
+
+ public boolean validateRoutePermission(String path, String token) {
+ if (isCluster(path) || isBroker(path) || isBrokerStats(path) ||
isResourceQuota(path)) {
+ if (rolesService.isSuperUser(token)) {
+ return true;
+ }
+ return false;
+ }
+ return true;
+ }
+
+ public Map<String, String> validateTenantPermission(String path, String
token) {
+ Map<String, String> result = Maps.newHashMap();
+ if (isTenant(path) || isNamespace(path) || isTopic(path)) {
+ String[] pathList = path.split(SEPARATOR);
+ String tenant;
+ if (path.startsWith(PULSAR_MANAGER_PREFIX)) {
+ tenant = pathList[5];
+ } else {
+ tenant = pathList[4];
+ }
+ result = rolesService.validateCurrentTenant(token, tenant);
+ return result;
+ }
+ result.put("message", "This resource no need validate");
+ return result;
+ }
+
public void parsePulsarEvent(String path, HttpServletRequest request) {
if (isNamespace(path, request)) {
String[] tenantNamespace = path.split(SEPARATOR);
- System.out.println(tenantNamespace);
- System.out.println(tenantNamespace[0]);
- System.out.println(tenantNamespace[1]);
- System.out.println(tenantNamespace[2]);
NamespaceEntity namespaceEntity = new NamespaceEntity();
- System.out.println(tenantNamespace[4]);
- System.out.println(tenantNamespace[5]);
namespaceEntity.setTenant(tenantNamespace[4]);
namespaceEntity.setNamespace(tenantNamespace[5]);
namespacesRepository.save(namespaceEntity);
diff --git
a/src/main/java/org/apache/pulsar/manager/service/impl/RoleBindingServiceImpl.java
b/src/main/java/org/apache/pulsar/manager/service/impl/RoleBindingServiceImpl.java
index 2e0cfa6..af0aa59 100644
---
a/src/main/java/org/apache/pulsar/manager/service/impl/RoleBindingServiceImpl.java
+++
b/src/main/java/org/apache/pulsar/manager/service/impl/RoleBindingServiceImpl.java
@@ -140,4 +140,38 @@ public class RoleBindingServiceImpl implements
RoleBindingService {
});
return userRoleInfo;
}
+ public List<Map<String, Object>> getAllRoleBindingList() {
+ List<RoleBindingEntity> roleBindingEntityList =
roleBindingRepository.findAllRoleBindingList();
+ List<Long> roleIdList = new ArrayList<>();
+ List<Long> userIdList = new ArrayList<>();
+ roleBindingEntityList.forEach((roleBinding) -> {
+ roleIdList.add(roleBinding.getRoleId());
+ userIdList.add(roleBinding.getUserId());
+ });
+ List<UserInfoEntity> userInfoEntities =
usersRepository.findUsersListByMultiUserId(userIdList);
+ Map<Long, UserInfoEntity> userInfoEntityMap = Maps.newHashMap();
+ userInfoEntities.forEach((u) -> {
+ userInfoEntityMap.put(u.getUserId(), u);
+ });
+ List<RoleInfoEntity> roleInfoEntities =
rolesRepository.findAllRolesByMultiId(roleIdList);
+ Map<Long, RoleInfoEntity> roleInfoEntityMap = Maps.newHashMap();
+ roleInfoEntities.forEach((r) -> {
+ roleInfoEntityMap.put(r.getRoleId(), r);
+ });
+ List<Map<String, Object>> userRoleInfo = new ArrayList<>();
+ roleBindingEntityList.forEach((binding) -> {
+ RoleInfoEntity roleInfoEntity =
roleInfoEntityMap.get(binding.getRoleId());
+ Map<String, Object> map = Maps.newHashMap();
+ map.put("name", binding.getName());
+ map.put("description", binding.getDescription());
+ map.put("userId", binding.getUserId());
+ if (userInfoEntityMap.get(binding.getUserId()) != null) {
+ map.put("userName",
userInfoEntityMap.get(binding.getUserId()).getName());
+ }
+ map.put("roleId", binding.getRoleId());
+ map.put("roleName", roleInfoEntity.getRoleName());
+ userRoleInfo.add(map);
+ });
+ return userRoleInfo;
+ }
}
diff --git
a/src/main/java/org/apache/pulsar/manager/service/impl/RolesServiceImpl.java
b/src/main/java/org/apache/pulsar/manager/service/impl/RolesServiceImpl.java
index fb38855..cd6f61f 100644
--- a/src/main/java/org/apache/pulsar/manager/service/impl/RolesServiceImpl.java
+++ b/src/main/java/org/apache/pulsar/manager/service/impl/RolesServiceImpl.java
@@ -13,7 +13,6 @@
*/
package org.apache.pulsar.manager.service.impl;
-import com.github.pagehelper.Page;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import lombok.extern.slf4j.Slf4j;
@@ -152,8 +151,9 @@ public class RolesServiceImpl implements RolesService {
return validateResult;
}
- public void createDefaultRoleAndTenant(String tenant) {
+ public Map<String, String> createDefaultRoleAndTenant(String tenant,
String environment) {
Optional<RoleInfoEntity> roleInfoEntityOptional =
rolesRepository.findByRoleName(tenant, tenant);
+ Map<String, String> result = Maps.newHashMap();
if (!roleInfoEntityOptional.isPresent()) {
// Create role, create default tenant for user
RoleInfoEntity roleInfoEntity = new RoleInfoEntity();
@@ -163,38 +163,37 @@ public class RolesServiceImpl implements RolesService {
roleInfoEntity.setResourceName(tenant);
roleInfoEntity.setResourceVerbs(ResourceVerbs.ADMIN.name());
roleInfoEntity.setFlag(1);
- try {
- Page<EnvironmentEntity> environmentListPage =
- environmentsRepository.getEnvironmentsList(1, 1);
- EnvironmentEntity environmentEntity =
environmentListPage.get(0);
- String broker = environmentEntity.getBroker();
- List<String> clusterList =
clustersService.getClusterByAnyBroker(broker);
- tenantsService.createTenant(tenant, tenant,
clusterList.get(0), broker);
-
- // Cache default tenant
- TenantEntity tenantEntity = new TenantEntity();
- tenantEntity.setTenant(tenant);
- tenantEntity.setAdminRoles(tenant);
- tenantEntity.setAllowedClusters(clusterList.get(0));
- long tenantId = tenantsRepository.save(tenantEntity);
- roleInfoEntity.setResourceId(tenantId);
- long roleId = rolesRepository.save(roleInfoEntity);
- RoleBindingEntity roleBindingEntity = new RoleBindingEntity();
- roleBindingEntity.setName(tenant);
- roleBindingEntity.setDescription("This init binding for
tenant");
- roleBindingEntity.setRoleId(roleId);
- Optional<UserInfoEntity> userInfoEntity =
usersRepository.findByUserName(tenant);
- roleBindingEntity.setUserId(userInfoEntity.get().getUserId());
- roleBindingRepository.save(roleBindingEntity);
- } catch (Exception e) {
- /**
- * TO DO
- * Send a notification to the administrator so that the
administrator can complete subsequent
- * operations without blocking user login.
- */
- log.error("Create tenant failed: {}", e.getCause());
+ Optional<EnvironmentEntity> environmentEntityOptional =
environmentsRepository.findByName(environment);
+ EnvironmentEntity environmentEntity =
environmentEntityOptional.get();
+ if (!environmentEntityOptional.isPresent()) {
+ result.put("error", "Environment is no exist");
+ return result;
}
+ String broker = environmentEntity.getBroker();
+ List<String> clusterList =
clustersService.getClusterByAnyBroker(broker);
+ tenantsService.createTenant(tenant, tenant, clusterList.get(0),
broker);
+
+ // Cache default tenant
+ TenantEntity tenantEntity = new TenantEntity();
+ tenantEntity.setTenant(tenant);
+ tenantEntity.setAdminRoles(tenant);
+ tenantEntity.setEnvironmentName(environment);
+ tenantEntity.setAllowedClusters(clusterList.get(0));
+ long tenantId = tenantsRepository.save(tenantEntity);
+ roleInfoEntity.setResourceId(tenantId);
+ long roleId = rolesRepository.save(roleInfoEntity);
+ RoleBindingEntity roleBindingEntity = new RoleBindingEntity();
+ roleBindingEntity.setName(tenant);
+ roleBindingEntity.setDescription("This init binding for tenant");
+ roleBindingEntity.setRoleId(roleId);
+ Optional<UserInfoEntity> userInfoEntity =
usersRepository.findByUserName(tenant);
+ roleBindingEntity.setUserId(userInfoEntity.get().getUserId());
+ roleBindingRepository.save(roleBindingEntity);
+ result.put("message", "Create default success");
+ return result;
}
+ result.put("error", "Role is exist");
+ return result;
}
public Set<String> getResourceVerbs(String resourceType) {
@@ -248,4 +247,23 @@ public class RolesServiceImpl implements RolesService {
result.put("message", "Validate tenant success");
return result;
}
+ public boolean isSuperUser(String token) {
+ Optional<UserInfoEntity> userInfoEntityOptional =
usersRepository.findByAccessToken(token);
+ if (!userInfoEntityOptional.isPresent()) {
+ return false;
+ }
+ UserInfoEntity userInfoEntity = userInfoEntityOptional.get();
+ List<RoleBindingEntity> roleBindingEntities =
roleBindingRepository.findByUserId(userInfoEntity.getUserId());
+ List<Long> roleIdList = new ArrayList<>();
+ for (RoleBindingEntity roleBindingEntity : roleBindingEntities) {
+ roleIdList.add(roleBindingEntity.getRoleId());
+ }
+ List<RoleInfoEntity> roleInfoEntities =
rolesRepository.findAllRolesByMultiId(roleIdList);
+ for (RoleInfoEntity roleInfoEntity : roleInfoEntities) {
+ if (roleInfoEntity.getFlag() == 0) {
+ return true;
+ }
+ }
+ return false;
+ }
}
diff --git
a/src/main/java/org/apache/pulsar/manager/zuul/EnvironmentForward.java
b/src/main/java/org/apache/pulsar/manager/zuul/EnvironmentForward.java
index 068ce0f..e17f154 100644
--- a/src/main/java/org/apache/pulsar/manager/zuul/EnvironmentForward.java
+++ b/src/main/java/org/apache/pulsar/manager/zuul/EnvironmentForward.java
@@ -13,8 +13,6 @@
*/
package org.apache.pulsar.manager.zuul;
-import org.apache.pulsar.manager.entity.NamespaceEntity;
-import org.apache.pulsar.manager.entity.NamespacesRepository;
import org.apache.pulsar.manager.service.EnvironmentCacheService;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
@@ -30,6 +28,7 @@ import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import java.net.MalformedURLException;
import java.net.URL;
+import java.util.Map;
import static
org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.PRE_TYPE;
import static
org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.REQUEST_URI_KEY;
@@ -42,13 +41,13 @@ public class EnvironmentForward extends ZuulFilter {
private static final Logger log =
LoggerFactory.getLogger(EnvironmentForward.class);
- private final PulsarEvent pulsarEvent;
-
@Value("${backend.jwt.token}")
private String pulsarJwtToken;
private final EnvironmentCacheService environmentCacheService;
+ private final PulsarEvent pulsarEvent;
+
@Autowired
public EnvironmentForward(
EnvironmentCacheService environmentCacheService, PulsarEvent
pulsarEvent) {
@@ -78,6 +77,25 @@ public class EnvironmentForward extends ZuulFilter {
HttpServletRequest request = ctx.getRequest();
String redirect = request.getParameter("redirect");
+ String requestUri = request.getRequestURI();
+ String token = request.getHeader("token");
+
+ if (!pulsarEvent.validateRoutePermission(requestUri, token)) {
+ ctx.setResponseBody("This operation does not have permission");
+ return null;
+ }
+ if (requestUri.startsWith("/admin/v2/tenants/")
+ || requestUri.startsWith("/admin/v2/namespaces")
+ || requestUri.startsWith("/admin/v2/persistent")
+ || requestUri.startsWith("/admin/v2/non-persistent")) {
+ Map<String, String> result = pulsarEvent.validateTenantPermission(
+ requestUri, token);
+ if (result.get("error") != null) {
+ log.error("This operation does not have permission");
+ ctx.setResponseBody(result.get("error"));
+ return null;
+ }
+ }
if (redirect != null && redirect.equals("true")) {
String redirectScheme = request.getParameter("redirect.scheme");
String redirectHost = request.getParameter("redirect.host");
diff --git a/src/main/resources/META-INF/sql/herddb-schema.sql
b/src/main/resources/META-INF/sql/herddb-schema.sql
index 00d65f5..ddcebbb 100644
--- a/src/main/resources/META-INF/sql/herddb-schema.sql
+++ b/src/main/resources/META-INF/sql/herddb-schema.sql
@@ -143,32 +143,8 @@ CREATE TABLE IF NOT EXISTS tenants (
tenant_id BIGINT PRIMARY KEY AUTO_INCREMENT,
tenant varchar(255) NOT NULL,
admin_roles varchar(255),
- allowed_clusters varchar(255)
-);
-
-CREATE TABLE IF NOT EXISTS namespaces (
- namespace_id BIGINT PRIMARY KEY AUTO_INCREMENT,
- tenant varchar(255) NOT NULL,
- namespace varchar(255) NOT NULL
-);
-
-CREATE TABLE IF NOT EXISTS roles (
- role_id BIGINT PRIMARY KEY AUTO_INCREMENT,
- role_name varchar(256) NOT NULL,
- role_source varchar(256) NOT NULL,
- description varchar(128),
- resource_id BIGINT NOT NULL,
- resource_type varchar(48) NOT NULL,
- resource_name varchar(48) NOT NULL,
- resource_verbs varchar(256) NOT NULL,
- flag INT NOT NULL
-);
-
-CREATE TABLE IF NOT EXISTS tenants (
- tenant_id BIGINT PRIMARY KEY AUTO_INCREMENT,
- tenant varchar(255) NOT NULL,
- admin_roles varchar(255),
- allowed_clusters varchar(255)
+ allowed_clusters varchar(255),
+ environment_name varchar(255)
);
CREATE TABLE IF NOT EXISTS namespaces (
diff --git a/src/main/resources/META-INF/sql/mysql-schema.sql
b/src/main/resources/META-INF/sql/mysql-schema.sql
index f3727bc..5bc57e2 100644
--- a/src/main/resources/META-INF/sql/mysql-schema.sql
+++ b/src/main/resources/META-INF/sql/mysql-schema.sql
@@ -147,8 +147,7 @@ CREATE TABLE IF NOT EXISTS roles (
resource_type varchar(48) NOT NULL,
resource_name varchar(48) NOT NULL,
resource_verbs varchar(256) NOT NULL,
- flag INT NOT NULL,
- UNIQUE(role_name, role_source)
+ flag INT NOT NULL
)ENGINE=InnoDB CHARACTER SET utf8;
CREATE TABLE IF NOT EXISTS tenants (
@@ -156,6 +155,7 @@ CREATE TABLE IF NOT EXISTS tenants (
tenant varchar(255) NOT NULL,
admin_roles varchar(255),
allowed_clusters varchar(255),
+ environment_name varchar(255)
UNIQUE(tenant)
)ENGINE=InnoDB CHARACTER SET utf8;
@@ -164,4 +164,12 @@ CREATE TABLE IF NOT EXISTS namespaces (
tenant varchar(255) NOT NULL,
namespace varchar(255) NOT NULL,
UNIQUE(tenant, namespace)
+)ENGINE=InnoDB CHARACTER SET utf8;
+
+CREATE TABLE IF NOT EXISTS role_binding(
+ role_binding_id BIGINT PRIMARY KEY AUTO_INCREMENT,
+ name varchar(256) NOT NULL,
+ description varchar(256),
+ role_id BIGINT NOT NULL,
+ user_id BIGINT NOT NULL
)ENGINE=InnoDB CHARACTER SET utf8;
\ No newline at end of file
diff --git a/src/main/resources/META-INF/sql/postgresql-schema.sql
b/src/main/resources/META-INF/sql/postgresql-schema.sql
index e7e4183..8dcaa33 100644
--- a/src/main/resources/META-INF/sql/postgresql-schema.sql
+++ b/src/main/resources/META-INF/sql/postgresql-schema.sql
@@ -147,8 +147,7 @@ CREATE TABLE IF NOT EXISTS roles (
resource_type varchar(48) NOT NULL,
resource_name varchar(48) NOT NULL,
resource_verbs varchar(256) NOT NULL,
- flag INT NOT NULL,
- UNIQUE(role_name, role_source)
+ flag INT NOT NULL
);
CREATE TABLE IF NOT EXISTS tenants (
@@ -156,6 +155,7 @@ CREATE TABLE IF NOT EXISTS tenants (
tenant varchar(255) NOT NULL,
admin_roles varchar(255),
allowed_clusters varchar(255),
+ environment_name varchar(255),
UNIQUE(tenant)
);
@@ -164,4 +164,12 @@ CREATE TABLE IF NOT EXISTS namespaces (
tenant varchar(255) NOT NULL,
namespace varchar(255) NOT NULL,
UNIQUE(tenant, namespace)
+);
+
+CREATE TABLE IF NOT EXISTS role_binding(
+ role_binding_id BIGINT PRIMARY KEY AUTO_INCREMENT,
+ name varchar(256) NOT NULL,
+ description varchar(256),
+ role_id BIGINT NOT NULL,
+ user_id BIGINT NOT NULL
);
\ No newline at end of file
diff --git a/src/main/resources/META-INF/sql/sqlite-schema.sql
b/src/main/resources/META-INF/sql/sqlite-schema.sql
index 3dd24af..e1572a5 100644
--- a/src/main/resources/META-INF/sql/sqlite-schema.sql
+++ b/src/main/resources/META-INF/sql/sqlite-schema.sql
@@ -143,8 +143,7 @@ CREATE TABLE IF NOT EXISTS roles (
resource_type varchar(48) NOT NULL,
resource_name varchar(48) NOT NULL,
resource_verbs varchar(256) NOT NULL,
- flag INT NOT NULL,
- UNIQUE(role_name, role_source)
+ flag INT NOT NULL
);
CREATE TABLE IF NOT EXISTS tenants (
@@ -152,6 +151,7 @@ CREATE TABLE IF NOT EXISTS tenants (
tenant varchar(255) NOT NULL,
admin_roles varchar(255),
allowed_clusters varchar(255),
+ environment_name varchar(255),
UNIQUE(tenant)
);
@@ -161,3 +161,12 @@ CREATE TABLE IF NOT EXISTS namespaces (
namespace varchar(255) NOT NULL,
UNIQUE(tenant, namespace)
);
+
+CREATE TABLE IF NOT EXISTS role_binding(
+ role_binding_id BIGINT PRIMARY KEY AUTO_INCREMENT,
+ name varchar(256) NOT NULL,
+ description varchar(256),
+ role_id BIGINT NOT NULL,
+ user_id BIGINT NOT NULL,
+ UNIQUE(role_id, user_id)
+);
diff --git
a/src/test/java/org/apache/pulsar/manager/dao/NamespacesRepositoryImplTest.java
b/src/test/java/org/apache/pulsar/manager/dao/NamespacesRepositoryImplTest.java
index be96233..c8e2efe 100644
---
a/src/test/java/org/apache/pulsar/manager/dao/NamespacesRepositoryImplTest.java
+++
b/src/test/java/org/apache/pulsar/manager/dao/NamespacesRepositoryImplTest.java
@@ -81,7 +81,8 @@ public class NamespacesRepositoryImplTest {
public void prepareTenant() {
TenantEntity tenantsEntity = new TenantEntity(
- 1, "test-namespace-public", "testrole", "testCluster");
+ 1, "test-namespace-public",
+ "testrole", "testCluster", "test-environment");
tenantsRepository.save(tenantsEntity);
}
diff --git
a/src/test/java/org/apache/pulsar/manager/dao/TenantsRepositoryImplTest.java
b/src/test/java/org/apache/pulsar/manager/dao/TenantsRepositoryImplTest.java
index 54b09cf..d37d719 100644
--- a/src/test/java/org/apache/pulsar/manager/dao/TenantsRepositoryImplTest.java
+++ b/src/test/java/org/apache/pulsar/manager/dao/TenantsRepositoryImplTest.java
@@ -50,6 +50,7 @@ public class TenantsRepositoryImplTest {
tenantEntity.setTenant("test" + i);
tenantEntity.setAdminRoles("test" + i);
tenantEntity.setAllowedClusters("test-cluster");
+ tenantEntity.setEnvironmentName("test-environment");
tenantsRepository.save(tenantEntity);
}
Page<TenantEntity> tenantsEntities =
tenantsRepository.getTenantsList(1, 10);
@@ -61,6 +62,7 @@ public class TenantsRepositoryImplTest {
TenantEntity tenantEntity = tenantsEntityList.get(i);
Assert.assertEquals(tenantEntity.getTenant(),
tenantEntity.getAdminRoles());
Assert.assertEquals(tenantEntity.getAllowedClusters(),
"test-cluster");
+ Assert.assertEquals(tenantEntity.getEnvironmentName(),
"test-environment");
}
tenantsEntities.getResult().forEach((result) -> {
tenantsRepository.remove(result.getTenant());
@@ -75,6 +77,7 @@ public class TenantsRepositoryImplTest {
tenantEntity.setTenant("test" + i);
tenantEntity.setAdminRoles("test" + i);
tenantEntity.setAllowedClusters("test-cluster");
+ tenantEntity.setEnvironmentName("test-environment");
Long tenantId = tenantsRepository.save(tenantEntity);
idList.add(tenantId);
}
@@ -87,6 +90,7 @@ public class TenantsRepositoryImplTest {
TenantEntity tenantEntity = tenantsEntityList.get(i);
Assert.assertEquals(tenantEntity.getTenant(),
tenantEntity.getAdminRoles());
Assert.assertEquals(tenantEntity.getAllowedClusters(),
"test-cluster");
+ Assert.assertEquals(tenantEntity.getEnvironmentName(),
"test-environment");
}
tenantEntityPage.getResult().forEach((result) -> {
tenantsRepository.remove(result.getTenant());
@@ -99,12 +103,14 @@ public class TenantsRepositoryImplTest {
tenantEntity.setTenant("test");
tenantEntity.setAdminRoles("test-role");
tenantEntity.setAllowedClusters("test-cluster");
+ tenantEntity.setEnvironmentName("test-environment");
tenantsRepository.save(tenantEntity);
Optional<TenantEntity> result = tenantsRepository.findByName("test");
TenantEntity getTenantEntity = result.get();
Assert.assertEquals(getTenantEntity.getTenant(), "test");
Assert.assertEquals(getTenantEntity.getAdminRoles(), "test-role");
Assert.assertEquals(getTenantEntity.getAllowedClusters(),
"test-cluster");
+ Assert.assertEquals(getTenantEntity.getEnvironmentName(),
"test-environment");
tenantsRepository.remove("test");
}
@@ -114,11 +120,13 @@ public class TenantsRepositoryImplTest {
tenantEntity.setTenant("test");
tenantEntity.setAdminRoles("test-role");
tenantEntity.setAllowedClusters("test-cluster");
+ tenantEntity.setEnvironmentName("test-environment");
long tenantId = tenantsRepository.save(tenantEntity);
Optional<TenantEntity> result =
tenantsRepository.findByTenantId(tenantId);
TenantEntity getTenantEntity = result.get();
Assert.assertEquals(getTenantEntity.getTenant(), "test");
Assert.assertEquals(getTenantEntity.getAdminRoles(), "test-role");
Assert.assertEquals(getTenantEntity.getAllowedClusters(),
"test-cluster");
+ Assert.assertEquals(getTenantEntity.getEnvironmentName(),
"test-environment");
}
}
\ No newline at end of file
diff --git
a/src/test/java/org/apache/pulsar/manager/service/PulsarEventImplTest.java
b/src/test/java/org/apache/pulsar/manager/service/PulsarEventImplTest.java
new file mode 100644
index 0000000..df518ac
--- /dev/null
+++ b/src/test/java/org/apache/pulsar/manager/service/PulsarEventImplTest.java
@@ -0,0 +1,192 @@
+/**
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.pulsar.manager.service;
+
+import org.apache.pulsar.manager.PulsarManagerApplication;
+import org.apache.pulsar.manager.entity.NamespaceEntity;
+import org.apache.pulsar.manager.entity.NamespacesRepository;
+import org.apache.pulsar.manager.entity.RoleBindingEntity;
+import org.apache.pulsar.manager.entity.RoleBindingRepository;
+import org.apache.pulsar.manager.entity.RoleInfoEntity;
+import org.apache.pulsar.manager.entity.RolesRepository;
+import org.apache.pulsar.manager.entity.TenantEntity;
+import org.apache.pulsar.manager.entity.TenantsRepository;
+import org.apache.pulsar.manager.entity.UserInfoEntity;
+import org.apache.pulsar.manager.entity.UsersRepository;
+import org.apache.pulsar.manager.profiles.HerdDBTestProfile;
+import org.apache.pulsar.manager.utils.ResourceType;
+import org.apache.pulsar.manager.utils.ResourceVerbs;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PowerMockIgnore;
+import org.powermock.modules.junit4.PowerMockRunner;
+import org.powermock.modules.junit4.PowerMockRunnerDelegate;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.mock.web.MockHttpServletRequest;
+import org.springframework.test.context.ActiveProfiles;
+import org.springframework.test.context.junit4.SpringRunner;
+
+import java.util.Map;
+import java.util.Optional;
+
+
+@RunWith(PowerMockRunner.class)
+@PowerMockRunnerDelegate(SpringRunner.class)
+@PowerMockIgnore( {"javax.*", "sun.*", "com.sun.*", "org.xml.*", "org.w3c.*"})
+@SpringBootTest(
+ classes = {
+ PulsarManagerApplication.class,
+ HerdDBTestProfile.class
+ }
+)
+@ActiveProfiles("test")
+public class PulsarEventImplTest {
+
+ @Autowired
+ private PulsarEvent pulsarEvent;
+
+ @Autowired
+ private UsersRepository usersRepository;
+
+ @Autowired
+ private RolesRepository rolesRepository;
+
+ @Autowired
+ private RoleBindingRepository roleBindingRepository;
+
+ @Autowired
+ private TenantsRepository tenantsRepository;
+
+ @Autowired
+ private NamespacesRepository namespacesRepository;
+
+ private long superUserId, superRoleId, adminUserId, adminRoleId;
+
+ @Before
+ public void setup() {
+ // prepare super user
+ UserInfoEntity superUserInfoEntity = new UserInfoEntity();
+ superUserInfoEntity.setName("superuser");
+ superUserInfoEntity.setAccessToken("super-access-token");
+ superUserId = usersRepository.save(superUserInfoEntity);
+ TenantEntity superTenantEntity = new TenantEntity();
+ superTenantEntity.setTenant("superTenant");
+ superTenantEntity.setAdminRoles("super-admin-roles");
+ superTenantEntity.setAllowedClusters("super-allowed-clusters");
+ long superTenantId = tenantsRepository.save(superTenantEntity);
+ RoleInfoEntity superRoleInfoEntity = new RoleInfoEntity();
+ superRoleInfoEntity.setRoleName("super-role");
+ superRoleInfoEntity.setRoleSource("superTenant");
+ superRoleInfoEntity.setResourceId(superTenantId);
+ superRoleInfoEntity.setFlag(0);
+ superRoleInfoEntity.setResourceName("super-tenant-resource");
+ superRoleInfoEntity.setResourceType(ResourceType.TENANTS.name());
+ superRoleInfoEntity.setResourceVerbs(ResourceVerbs.ADMIN.name());
+ superRoleId = rolesRepository.save(superRoleInfoEntity);
+ RoleBindingEntity superRoleBindingEntity = new RoleBindingEntity();
+ superRoleBindingEntity.setDescription("This is role binding
description");
+ superRoleBindingEntity.setUserId(superUserId);
+ superRoleBindingEntity.setRoleId(superRoleId);
+ superRoleBindingEntity.setName("super-role-binding");
+ roleBindingRepository.save(superRoleBindingEntity);
+
+ // prepare admin user
+ UserInfoEntity adminUserInfoEntity = new UserInfoEntity();
+ adminUserInfoEntity.setName("admin");
+ adminUserInfoEntity.setAccessToken("admin-access-token");
+ adminUserId = usersRepository.save(adminUserInfoEntity);
+ TenantEntity adminTenantEntity = new TenantEntity();
+ adminTenantEntity.setTenant("adminTenant");
+ adminTenantEntity.setAdminRoles("super-admin-roles");
+ adminTenantEntity.setAllowedClusters("super-allowed-clusters");
+ long adminTenantId = tenantsRepository.save(adminTenantEntity);
+ RoleInfoEntity adminRoleInfoEntity = new RoleInfoEntity();
+ adminRoleInfoEntity.setRoleName("admin-role");
+ adminRoleInfoEntity.setRoleSource("adminTenant");
+ adminRoleInfoEntity.setResourceId(adminTenantId);
+ adminRoleInfoEntity.setFlag(1);
+ adminRoleInfoEntity.setResourceName("admin-tenant-resource");
+ adminRoleInfoEntity.setResourceType(ResourceType.TENANTS.name());
+ adminRoleInfoEntity.setResourceVerbs(ResourceVerbs.ADMIN.name());
+ adminRoleId = rolesRepository.save(adminRoleInfoEntity);
+ RoleBindingEntity adminRoleBindingEntity = new RoleBindingEntity();
+ adminRoleBindingEntity.setDescription("This is role binding
description");
+ adminRoleBindingEntity.setUserId(adminUserId);
+ adminRoleBindingEntity.setRoleId(adminRoleId);
+ adminRoleBindingEntity.setName("admin-role-binding");
+ roleBindingRepository.save(adminRoleBindingEntity);
+ }
+
+ @After
+ public void clear() {
+ usersRepository.delete("superuser");
+ usersRepository.delete("admin");
+ tenantsRepository.remove("superTenant");
+ tenantsRepository.remove("adminTenant");
+ rolesRepository.delete("super-role", "superTenant");
+ rolesRepository.delete("admin-role", "adminTenant");
+ roleBindingRepository.delete(superRoleId, adminUserId);
+ roleBindingRepository.delete(adminRoleId, adminUserId);
+ }
+
+ @Test
+ public void validateRoutePermissionTest() {
+
Assert.assertTrue(pulsarEvent.validateRoutePermission("/admin/v2/clusters",
"super-access-token"));
+
Assert.assertTrue(pulsarEvent.validateRoutePermission("/admin/v2/brokers",
"super-access-token"));
+ Assert.assertTrue(
+ pulsarEvent.validateRoutePermission("/admin/v2/broker-stats",
"super-access-token"));
+ Assert.assertTrue(
+
pulsarEvent.validateRoutePermission("/admin/v2/resource-quotas",
"super-access-token"));
+
+
Assert.assertFalse(pulsarEvent.validateRoutePermission("/admin/v2/clusters",
"admin-access-token"));
+
Assert.assertFalse(pulsarEvent.validateRoutePermission("/admin/v2/brokers",
"admin-access-token"));
+ Assert.assertFalse(
+ pulsarEvent.validateRoutePermission("/admin/v2/broker-stats",
"admin-access-token"));
+ Assert.assertFalse(
+
pulsarEvent.validateRoutePermission("/admin/v2/resource-quotas",
"admin-access-token"));
+
+
Assert.assertTrue(pulsarEvent.validateRoutePermission("/admin/v2/tenants",
"admin-access-token"));
+ }
+
+ @Test
+ public void validateTenantPermission() {
+ Map<String, String> result;
+ result =
pulsarEvent.validateTenantPermission("/admin/v2/tenants/superTenant",
"super-access-token");
+ Assert.assertEquals(result.get("message"), "Validate tenant success");
+ result =
pulsarEvent.validateTenantPermission("/admin/v2/tenants/adminTenant",
"super-access-token");
+ Assert.assertEquals(result.get("error"), "This user no include this
tenant");
+
+ result = pulsarEvent.validateTenantPermission(
+
"/pulsar-manager/admin/v2/schemas/adminTenant/default/test-topic",
"super-access-token");
+ Assert.assertEquals(result.get("message"), "This resource no need
validate");
+
+ result = pulsarEvent.validateTenantPermission(
+ "/pulsar-manager/admin/v2/namespaces/adminTenant/default",
"admin-access-token");
+ Assert.assertEquals(result.get("message"), "Validate tenant success");
+ }
+
+ @Test
+ public void parsePulsarEvent() {
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ request.setMethod("PUT");
+
pulsarEvent.parsePulsarEvent("/admin/v2/namespaces/adminTenant/default/test-topic",
request);
+ Optional<NamespaceEntity> namespaceEntity =
namespacesRepository.findByTenantNamespace(
+ "adminTenant", "default");
+ Assert.assertTrue(namespaceEntity.isPresent());
+ }
+}