mirror of
https://github.com/jumpserver/lina.git
synced 2025-09-23 20:17:54 +00:00
[Update] merge
This commit is contained in:
9
src/api/sessions.js
Normal file
9
src/api/sessions.js
Normal file
@@ -0,0 +1,9 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
export function terminateSession(data) {
|
||||
return request({
|
||||
url: '/api/v1/terminal/tasks/kill-session/',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
@@ -1,7 +1,5 @@
|
||||
<template>
|
||||
<ElDatableTable ref="table" class="el-table" v-bind="tableConfig" v-on="$listeners">
|
||||
<slot />
|
||||
</ElDatableTable>
|
||||
<ElDatableTable ref="table" class="el-table" v-bind="tableConfig" v-on="$listeners" />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
@@ -7,8 +7,8 @@
|
||||
<slot />
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<slot name="footer">
|
||||
<el-button size="small" @click="onCancel">{{ $t('Cancel') }}</el-button>
|
||||
<el-button type="primary" size="small" @click="onConfirm">{{ $tc('Ok') }}</el-button>
|
||||
<el-button size="small" @click="onCancel">{{ $tc('Cancel') }}</el-button>
|
||||
<el-button type="primary" size="small" @click="onConfirm">{{ $tc('Confirm') }}</el-button>
|
||||
</slot>
|
||||
</div>
|
||||
</el-dialog>
|
||||
|
23
src/components/ListTable/formatters/LengthFormatter.vue
Normal file
23
src/components/ListTable/formatters/LengthFormatter.vue
Normal file
@@ -0,0 +1,23 @@
|
||||
<template>
|
||||
<span>{{ getCellValueLength }}</span>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import BaseFormatter from './base'
|
||||
export default {
|
||||
name: 'LengthFormatter',
|
||||
extends: BaseFormatter,
|
||||
computed: {
|
||||
getCellValueLength() {
|
||||
if (this.cellValue instanceof Array) {
|
||||
return this.cellValue.length
|
||||
}
|
||||
return this.cellValue
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
@@ -19,7 +19,7 @@ export default {
|
||||
default: () => ({})
|
||||
},
|
||||
cellValue: {
|
||||
type: [String, Boolean, Number, Object],
|
||||
type: [String, Boolean, Number, Object, Array],
|
||||
default: null
|
||||
},
|
||||
tableData: {
|
||||
|
@@ -3,3 +3,4 @@ export { default as DisplayFormatter } from './DisplayFormatter'
|
||||
export { default as BooleanFormatter } from './ChoicesFormatter'
|
||||
export { default as ActionsFormatter } from './ActionsFormatter'
|
||||
export { default as ExpandPreFormatter } from './ExpandPreFormatter'
|
||||
export { default as LengthFormatter } from './LengthFormatter'
|
||||
|
@@ -3,35 +3,35 @@
|
||||
<TableAction :table-url="tableConfig.url" :search-table="search" v-bind="headerActions" :selected-rows="selectedRows" :reload-table="reloadTable" />
|
||||
<el-card class="table-content" shadow="never">
|
||||
<AutoDataTable ref="dataTable" :config="tableConfig" @selection-change="handleSelectionChange" />
|
||||
<Dialog :title="$t('Export')" :visible.sync="showExportDialog" @comfirm="handleDialogConfirm('export')" @cancel="handleDialogCancel('export')">
|
||||
<Dialog :title="$tc('Export')" :visible.sync="showExportDialog" center @comfirm="handleDialogConfirm('export')" @cancel="handleDialogCancel('export')">
|
||||
<el-form>
|
||||
<el-form-item label="导出范围" :label-width="'100px'">
|
||||
<p>{{ $d(new Date(), 'short') }}</p>
|
||||
<el-radio v-model="exportOption" class="export-item" label="1">导出全部</el-radio>
|
||||
<el-radio v-model="exportOption" class="export-item" label="2">仅导出选中项</el-radio>
|
||||
<el-radio v-model="exportOption" class="export-item" label="3">仅导出搜索项</el-radio>
|
||||
<!-- <el-radio v-model="exportOption" class="export-item" label="3">仅导出搜索项</el-radio> -->
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</Dialog>
|
||||
<Dialog :title="$t('Import')" :visible.sync="showImportDialog" @comfirm="handleDialogConfirm('import')" @cancel="handleDialogCancel('import')">
|
||||
<Dialog :title="importtitle" :visible.sync="showImportDialog" center @comfirm="handleDialogConfirm('import')" @cancel="handleDialogCancel('import')">
|
||||
<el-form>
|
||||
<el-form-item label="导入/更新" :label-width="'100px'">
|
||||
<el-radio v-model="importOption" class="export-item" label="1">导出全部</el-radio>
|
||||
<el-radio v-model="importOption" class="export-item" label="2">仅导出选中项</el-radio>
|
||||
<el-radio v-model="importOption" class="export-item" label="3">仅导出搜索项</el-radio>
|
||||
<el-form-item :label="importtitle" :label-width="'100px'">
|
||||
<el-radio v-model="importOption" class="export-item" label="1">导入新资产</el-radio>
|
||||
<el-radio v-model="importOption" class="export-item" label="2">更新资产</el-radio>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div>
|
||||
<div v-if="importOption==='1'" style="margin-bottom:20px;margin-left: 55px;">下载导入的模板或使用导出的csv格式 <a style="color: #428bca;" :href="downloadImportTempUrl">下载导入模板</a></div>
|
||||
<div v-else style="margin-bottom:20px;margin-left: 55px;">下载更新的模板或使用导出的csv格式 <a style="color: #428bca;" @click="downloadUpdateTempUrl">下载更新模板</a></div>
|
||||
|
||||
<div style="margin-left:55px;">
|
||||
<el-upload
|
||||
class="upload-card"
|
||||
:action="upLoadUrl"
|
||||
:on-preview="handlePreview"
|
||||
:on-remove="handleRemove"
|
||||
:before-remove="beforeRemove"
|
||||
:on-exceed="handleExceed"
|
||||
action="string"
|
||||
:http-request="upload"
|
||||
list-type="text/csv"
|
||||
:limit="1"
|
||||
>
|
||||
<el-button size="small" type="primary">点击上传</el-button>
|
||||
<div slot="tip" class="el-upload__tip">只能上传jpg/png文件,且不超过500kb</div>
|
||||
<div slot="tip" class="el-upload__tip">只能上传CSV文件</div>
|
||||
</el-upload>
|
||||
</div>
|
||||
</Dialog>
|
||||
@@ -81,7 +81,13 @@ export default {
|
||||
return this.selectedRows.length > 0
|
||||
},
|
||||
upLoadUrl() {
|
||||
return process.env.VUE_APP_BASE_API + this.tableConfig.url
|
||||
return this.tableConfig.url
|
||||
},
|
||||
importtitle() {
|
||||
if (this.importOption === '1') { return this.$tc('Import') } else { return this.$tc('Update') }
|
||||
},
|
||||
downloadImportTempUrl() {
|
||||
return process.env.VUE_APP_BASE_API + this.tableConfig.url + '?format=csv&template=import&limit=1'
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
@@ -93,6 +99,15 @@ export default {
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
upload(item) {
|
||||
console.log(item)
|
||||
this.$axios.put(
|
||||
this.upLoadUrl,
|
||||
item.file
|
||||
).then((res) =>
|
||||
console.log(res)
|
||||
)
|
||||
},
|
||||
downloadCsv(url) {
|
||||
const a = document.createElement('a')
|
||||
a.href = url
|
||||
@@ -103,16 +118,16 @@ export default {
|
||||
this.selectedRows = val
|
||||
},
|
||||
reloadTable() {
|
||||
this.$refs.dataTable.getList()
|
||||
this.$refs.dataTable.$refs.dataTable.getList()
|
||||
},
|
||||
search(attrs) {
|
||||
return this.$refs.dataTable.search(attrs)
|
||||
return this.$refs.dataTable.$refs.dataTable.search(attrs)
|
||||
},
|
||||
async handleExport() {
|
||||
let data
|
||||
var resources = []
|
||||
if (this.exportOption === '1') {
|
||||
data = this.$refs.dataTable.getData()
|
||||
data = this.$refs.dataTable.$refs.dataTable.getData()
|
||||
} else if (this.exportOption === '2') {
|
||||
data = this.selectedRows
|
||||
} else {
|
||||
@@ -127,6 +142,16 @@ export default {
|
||||
},
|
||||
handleImport() {
|
||||
|
||||
},
|
||||
async downloadUpdateTempUrl() {
|
||||
var resources = []
|
||||
const data = this.$refs.dataTable.$refs.dataTable.getData()
|
||||
for (let index = 0; index < data.length; index++) {
|
||||
resources.push(data[index].id)
|
||||
}
|
||||
const spm = await createSourceIdCache(resources)
|
||||
const url = process.env.VUE_APP_BASE_API + `${this.tableConfig.url}?format=csv&template=update&spm=` + spm.spm
|
||||
return this.downloadCsv(url)
|
||||
},
|
||||
async handleDialogConfirm(val) {
|
||||
switch (val) {
|
||||
|
@@ -52,6 +52,12 @@ const cn = {
|
||||
'Reset': '重置',
|
||||
'This field is required': '这个字段是必填项',
|
||||
'Validity': '有效性',
|
||||
'confirm': '确认',
|
||||
'Confirm': '确认',
|
||||
'Cancel': '取消',
|
||||
'cancel': '取消',
|
||||
'Import': '导入',
|
||||
'Export': '导出',
|
||||
'Other': '其它'
|
||||
},
|
||||
route: {
|
||||
@@ -73,8 +79,11 @@ const cn = {
|
||||
'DatabaseApp': '数据库应用',
|
||||
'Perms': '权限管理',
|
||||
'AssetPermission': '资产授权',
|
||||
'AssetPermissionCreate': '创建资产授权规则',
|
||||
'RemoteAppPermission': '远程应用授权',
|
||||
'RemoteAppPermissionCreate': '创建远程应用授权规则',
|
||||
'DatabaseAppPermission': '数据库应用授权',
|
||||
'DatabaseAppPermissionCreate': '创建数据库应用授权规则',
|
||||
'Sessions': '会话管理',
|
||||
'SessionOnline': '在线会话',
|
||||
'SessionOffline': '历史会话',
|
||||
@@ -339,20 +348,14 @@ const cn = {
|
||||
'active': '激活中',
|
||||
'users_and_user_groups': '用户或用户组',
|
||||
'assets_and_node': '资产或节点',
|
||||
'Basic': '基本',
|
||||
'User': '用户',
|
||||
'Asset': '资产',
|
||||
'Actions': '动作',
|
||||
//
|
||||
'RemoteApp': '远程应用',
|
||||
'remote_app_permission_list': '远程应用授权列表',
|
||||
'remote_app_permission_detail': '远程应用授权详情',
|
||||
'create_remote_app_permission': '创建远程应用授权规则',
|
||||
'update_remote_app_permission': '更新远程应用授权规则',
|
||||
'remote_app_count': '远程应用数量',
|
||||
//
|
||||
'DatabaseApp': '数据库应用',
|
||||
'database_app_permission_list': '数据库应用授权列表',
|
||||
'database_app_permission_detail': '数据库应用授权详情',
|
||||
'create_database_app_permission': '创建数据库应用授权规则',
|
||||
'update_database_app_permission': '更新数据库应用授权规则',
|
||||
'database_app_count': '数据库应用数量'
|
||||
'DatabaseApp': '数据库应用'
|
||||
},
|
||||
sessions: {
|
||||
'id': 'ID',
|
||||
@@ -376,7 +379,8 @@ const cn = {
|
||||
'addr': '地址',
|
||||
'active': '激活中',
|
||||
'alive': '在线',
|
||||
'StorageConfiguration': '存储配置'
|
||||
'StorageConfiguration': '存储配置',
|
||||
'join': '加入'
|
||||
},
|
||||
jobcenter: {
|
||||
'RunTimes': '执行次数',
|
||||
|
@@ -288,7 +288,8 @@ const en = {
|
||||
'quick_modify': 'Quick modify',
|
||||
'terminate_session': 'Terminate session',
|
||||
'confirm': 'Confirm',
|
||||
'commands': 'Commands'
|
||||
'commands': 'Commands',
|
||||
'join': 'join'
|
||||
},
|
||||
setting: {
|
||||
'setting': 'System Setting',
|
||||
|
@@ -214,17 +214,38 @@ export const constantRoutes = [
|
||||
component: () => import('@/views/perms/AssetPermissionList'),
|
||||
meta: { title: 'AssetPermission' }
|
||||
},
|
||||
{
|
||||
path: 'asset-permissions/create',
|
||||
component: () => import('@/views/perms/AssetPermissionCreateUpdate'), // Parent router-view
|
||||
name: 'AssetPermissionCreate',
|
||||
hidden: true,
|
||||
meta: { title: 'AssetPermissionCreate', activeMenu: '/perms/asset-permissions' }
|
||||
},
|
||||
{
|
||||
path: 'remote-app-permissions',
|
||||
name: 'RemoteAppPermissionList',
|
||||
component: () => import('@/views/perms/RemoteAppPermissionList'),
|
||||
meta: { title: 'RemoteAppPermission' }
|
||||
},
|
||||
{
|
||||
path: 'remote-app-permissions/create',
|
||||
component: () => import('@/views/perms/RemoteAppPermissionCreateUpdate'), // Parent router-view
|
||||
name: 'RemoteAppPermissionCreate',
|
||||
hidden: true,
|
||||
meta: { title: 'RemoteAppPermissionCreate', activeMenu: '/perms/remote-app-permissions' }
|
||||
},
|
||||
{
|
||||
path: 'database-app-permissions',
|
||||
name: 'DatabaseAppPermissionList',
|
||||
component: () => import('@/views/perms/DatabaseAppPermissionList'),
|
||||
meta: { title: 'DatabaseAppPermission' }
|
||||
},
|
||||
{
|
||||
path: 'database-app-permissions/create',
|
||||
component: () => import('@/views/perms/DatabaseAppPermissionCreateUpdate'), // Parent router-view
|
||||
name: 'DatabaseAppPermissionCreate',
|
||||
hidden: true,
|
||||
meta: { title: 'DatabaseAppPermissionCreate', activeMenu: '/perms/database-app-permissions' }
|
||||
}
|
||||
]
|
||||
},
|
||||
|
78
src/utils/common.js
Normal file
78
src/utils/common.js
Normal file
@@ -0,0 +1,78 @@
|
||||
function getTimeUnits(u) {
|
||||
const units = {
|
||||
'd': '天',
|
||||
'h': '时',
|
||||
'm': '分',
|
||||
's': '秒'
|
||||
}
|
||||
if (getUserLang() === 'zh-CN') {
|
||||
return units[u]
|
||||
}
|
||||
return u
|
||||
}
|
||||
|
||||
export function timeOffset(a, b) {
|
||||
const start = safeDate(a)
|
||||
const end = safeDate(b)
|
||||
const offset = (end - start) / 1000
|
||||
return readableSecond(offset)
|
||||
}
|
||||
|
||||
function readableSecond(offset) {
|
||||
const days = offset / 3600 / 24
|
||||
const hours = offset / 3600
|
||||
const minutes = offset / 60
|
||||
const seconds = offset
|
||||
|
||||
if (days > 1) {
|
||||
return days.toFixed(1) + ' ' + getTimeUnits('d')
|
||||
} else if (hours > 1) {
|
||||
return hours.toFixed(1) + ' ' + getTimeUnits('h')
|
||||
} else if (minutes > 1) {
|
||||
return minutes.toFixed(1) + ' ' + getTimeUnits('m')
|
||||
} else if (seconds > 1) {
|
||||
return seconds.toFixed(1) + ' ' + getTimeUnits('s')
|
||||
}
|
||||
return ''
|
||||
}
|
||||
|
||||
function getUserLang() {
|
||||
const userLangEN = document.cookie.indexOf('django_language=en')
|
||||
if (userLangEN === -1) {
|
||||
return 'zh-CN'
|
||||
} else {
|
||||
return 'en-US'
|
||||
}
|
||||
}
|
||||
|
||||
function safeDate(s) {
|
||||
s = cleanDateStr(s)
|
||||
return new Date(s)
|
||||
}
|
||||
|
||||
function cleanDateStr(d) {
|
||||
for (let i = 0; i < 3; i++) {
|
||||
if (!isNaN(Date.parse(d))) {
|
||||
return d
|
||||
}
|
||||
if (!isNaN(Number(d))) {
|
||||
return d
|
||||
}
|
||||
switch (i) {
|
||||
case 0:
|
||||
d = d.replaceAll('-', '/')
|
||||
break
|
||||
case 1:
|
||||
d = d.split('+')[0].trimRight()
|
||||
break
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
export function toSafeLocalDateStr(d) {
|
||||
const date = safeDate(d)
|
||||
// var date_s = date.toLocaleString(getUserLang(), {hour12: false});
|
||||
const date_s = date.toLocaleString(getUserLang(), { hourCycle: 'h23' })
|
||||
return date_s.split('/').join('-')
|
||||
}
|
69
src/views/perms/AssetPermissionCreateUpdate.vue
Normal file
69
src/views/perms/AssetPermissionCreateUpdate.vue
Normal file
@@ -0,0 +1,69 @@
|
||||
<template>
|
||||
<GenericCreateUpdatePage :fields="fields" :form="form" :fields-meta="fieldsMeta" :url="url" />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { GenericCreateUpdatePage } from '@/layout/components'
|
||||
export default {
|
||||
components: {
|
||||
GenericCreateUpdatePage
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
form: {
|
||||
date_expired: '2099-12-31 00:00:00 +0800'
|
||||
},
|
||||
fields: [
|
||||
[this.$t('perms.' + 'Basic'), ['name']],
|
||||
[this.$t('perms.' + 'User'), ['users', 'user_groups']],
|
||||
[this.$t('perms.' + 'Asset'), ['assets', 'nodes', 'system_users']],
|
||||
[this.$tc('Action'), ['actions']],
|
||||
[this.$tc('Other'), ['is_active', 'date_expired', 'comment']]
|
||||
],
|
||||
url: '/api/v1/perms/asset-permissions/',
|
||||
fieldsMeta: {
|
||||
users: {
|
||||
el: {
|
||||
value: [],
|
||||
url: '/api/v1/users/users/'
|
||||
}
|
||||
},
|
||||
user_groups: {
|
||||
el: {
|
||||
value: [],
|
||||
url: '/api/v1/users/groups/'
|
||||
}
|
||||
},
|
||||
assets: {
|
||||
el: {
|
||||
value: [],
|
||||
url: '/api/v1/assets/nodes/children/tree/'
|
||||
}
|
||||
},
|
||||
nodes: {
|
||||
el: {
|
||||
value: [],
|
||||
url: '/api/v1/assets/nodes/'
|
||||
}
|
||||
},
|
||||
system_users: {
|
||||
el: {
|
||||
value: [],
|
||||
url: '/api/v1/assets/system-users/'
|
||||
}
|
||||
},
|
||||
actions: {
|
||||
label: this.$t('perms.Actions')
|
||||
},
|
||||
is_active: {
|
||||
type: 'checkbox'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
@@ -4,7 +4,7 @@
|
||||
|
||||
<script>
|
||||
import { GenericListPage } from '@/layout/components'
|
||||
import { DetailFormatter, ActionsFormatter, BooleanFormatter } from '@/components/ListTable/formatters/index'
|
||||
import { LengthFormatter } from '@/components/ListTable/formatters/index'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
@@ -14,59 +14,23 @@ export default {
|
||||
return {
|
||||
tableConfig: {
|
||||
url: '/api/v1/perms/asset-permissions/',
|
||||
columns: [
|
||||
{
|
||||
prop: 'name',
|
||||
label: this.$t('common.name'),
|
||||
formatter: DetailFormatter,
|
||||
sortable: true,
|
||||
route: 'AssetPermissionDetail'
|
||||
columns: ['name', 'users', 'user_groups', 'assets', 'nodes', 'system_users', 'is_active', 'actions'],
|
||||
columnsMeta: {
|
||||
users: {
|
||||
formatter: LengthFormatter
|
||||
},
|
||||
{
|
||||
prop: 'users.length',
|
||||
label: this.$t('perms.user')
|
||||
user_groups: {
|
||||
formatter: LengthFormatter
|
||||
},
|
||||
{
|
||||
prop: 'user_groups.length',
|
||||
label: this.$t('perms.userGroup')
|
||||
assets: {
|
||||
formatter: LengthFormatter
|
||||
},
|
||||
{
|
||||
prop: 'assets.length',
|
||||
label: this.$t('perms.asset')
|
||||
nodes: {
|
||||
formatter: LengthFormatter
|
||||
},
|
||||
{
|
||||
prop: 'nodes.length',
|
||||
label: this.$t('perms.node')
|
||||
},
|
||||
{
|
||||
prop: 'system_users.length',
|
||||
label: this.$t('perms.systemUser')
|
||||
},
|
||||
{
|
||||
prop: 'is_active',
|
||||
label: this.$t('perms.validity'),
|
||||
formatter: BooleanFormatter,
|
||||
align: 'center',
|
||||
width: '80px'
|
||||
},
|
||||
{
|
||||
prop: 'id',
|
||||
label: this.$tc('Action'),
|
||||
align: 'center',
|
||||
formatter: ActionsFormatter,
|
||||
width: '200px',
|
||||
actions: {
|
||||
performDelete: ({ row, col }) => {
|
||||
const id = row.id
|
||||
const url = `/api/v1/perms/asset-permissions/${id}/`
|
||||
return this.$axios.delete(url)
|
||||
}
|
||||
}
|
||||
system_users: {
|
||||
formatter: LengthFormatter
|
||||
}
|
||||
],
|
||||
tableActions: {
|
||||
hasEdit: true,
|
||||
editRoute: '404'
|
||||
}
|
||||
},
|
||||
headerActions: {
|
||||
|
63
src/views/perms/DatabaseAppPermissionCreateUpdate.vue
Normal file
63
src/views/perms/DatabaseAppPermissionCreateUpdate.vue
Normal file
@@ -0,0 +1,63 @@
|
||||
<template>
|
||||
<GenericCreateUpdatePage :fields="fields" :form="form" :fields-meta="fieldsMeta" :url="url" />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { GenericCreateUpdatePage } from '@/layout/components'
|
||||
export default {
|
||||
components: {
|
||||
GenericCreateUpdatePage
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
form: {
|
||||
is_active: true,
|
||||
date_expired: '2099-12-31 00:00:00 +0800'
|
||||
},
|
||||
fields: [
|
||||
[this.$t('perms.' + 'Basic'), ['name']],
|
||||
[this.$t('perms.' + 'User'), ['users', 'user_groups']],
|
||||
[this.$t('perms.' + 'DatabaseApp'), ['database_apps', 'system_users']],
|
||||
[this.$tc('Other'), ['is_active', 'date_expired', 'comment']]
|
||||
],
|
||||
url: '/api/v1/perms/database-app-permissions/',
|
||||
fieldsMeta: {
|
||||
users: {
|
||||
el: {
|
||||
value: [],
|
||||
url: '/api/v1/users/users/'
|
||||
}
|
||||
},
|
||||
user_groups: {
|
||||
el: {
|
||||
value: [],
|
||||
url: '/api/v1/users/groups/'
|
||||
}
|
||||
},
|
||||
database_apps: {
|
||||
el: {
|
||||
value: [],
|
||||
url: '/api/v1/applications/database-apps/'
|
||||
}
|
||||
},
|
||||
system_users: {
|
||||
el: {
|
||||
value: [],
|
||||
url: '/api/v1/assets/system-users/'
|
||||
}
|
||||
},
|
||||
actions: {
|
||||
label: this.$t('perms.Actions')
|
||||
},
|
||||
is_active: {
|
||||
type: 'checkbox'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
@@ -4,8 +4,7 @@
|
||||
|
||||
<script>
|
||||
import { GenericListPage } from '@/layout/components'
|
||||
import { DetailFormatter, ActionsFormatter, BooleanFormatter } from '@/components/ListTable/formatters/index'
|
||||
|
||||
import { LengthFormatter } from '@/components/ListTable/formatters/index'
|
||||
export default {
|
||||
components: {
|
||||
GenericListPage
|
||||
@@ -14,52 +13,21 @@ export default {
|
||||
return {
|
||||
tableConfig: {
|
||||
url: '/api/v1/perms/database-app-permissions/',
|
||||
columns: [
|
||||
{
|
||||
prop: 'name',
|
||||
label: this.$t('perms.name'),
|
||||
formatter: DetailFormatter,
|
||||
sortable: true,
|
||||
route: 'DatabaseAppPermissionDetail'
|
||||
columns: ['name', 'users', 'user_groups', 'database_apps', 'system_users', 'is_valid', 'actions'],
|
||||
columnsMeta: {
|
||||
users: {
|
||||
formatter: LengthFormatter
|
||||
},
|
||||
{
|
||||
prop: 'users.length',
|
||||
label: this.$t('perms.user')
|
||||
user_groups: {
|
||||
formatter: LengthFormatter
|
||||
},
|
||||
{
|
||||
prop: 'user_groups.length',
|
||||
label: this.$t('perms.userGroup')
|
||||
database_apps: {
|
||||
formatter: LengthFormatter
|
||||
},
|
||||
{
|
||||
prop: 'database_apps.length',
|
||||
label: this.$t('perms.DatabaseApp')
|
||||
},
|
||||
{
|
||||
prop: 'system_users.length',
|
||||
label: this.$t('perms.systemUser')
|
||||
},
|
||||
{
|
||||
prop: 'is_valid',
|
||||
label: this.$t('perms.validity'),
|
||||
formatter: BooleanFormatter,
|
||||
align: 'center',
|
||||
width: '80px'
|
||||
},
|
||||
{
|
||||
prop: 'id',
|
||||
label: this.$tc('Action'),
|
||||
align: 'center',
|
||||
formatter: ActionsFormatter,
|
||||
width: '200px',
|
||||
actions: {
|
||||
performDelete: ({ row, col }) => {
|
||||
const id = row.id
|
||||
const url = `/api/v1/perms/database-app-permissions/${id}/`
|
||||
return this.$axios.delete(url)
|
||||
}
|
||||
}
|
||||
system_users: {
|
||||
formatter: LengthFormatter
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
headerActions: {
|
||||
hasBulkDelete: false,
|
||||
|
63
src/views/perms/RemoteAppPermissionCreateUpdate.vue
Normal file
63
src/views/perms/RemoteAppPermissionCreateUpdate.vue
Normal file
@@ -0,0 +1,63 @@
|
||||
<template>
|
||||
<GenericCreateUpdatePage :fields="fields" :form="form" :fields-meta="fieldsMeta" :url="url" />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { GenericCreateUpdatePage } from '@/layout/components'
|
||||
export default {
|
||||
components: {
|
||||
GenericCreateUpdatePage
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
form: {
|
||||
is_active: true,
|
||||
date_expired: '2099-12-31 00:00:00 +0800'
|
||||
},
|
||||
fields: [
|
||||
[this.$t('perms.' + 'Basic'), ['name']],
|
||||
[this.$t('perms.' + 'User'), ['users', 'user_groups']],
|
||||
[this.$t('perms.' + 'RemoteApp'), ['remote_apps', 'system_users']],
|
||||
[this.$tc('Other'), ['is_active', 'date_expired', 'comment']]
|
||||
],
|
||||
url: '/api/v1/perms/remote-app-permissions/',
|
||||
fieldsMeta: {
|
||||
users: {
|
||||
el: {
|
||||
value: [],
|
||||
url: '/api/v1/users/users/'
|
||||
}
|
||||
},
|
||||
user_groups: {
|
||||
el: {
|
||||
value: [],
|
||||
url: '/api/v1/users/groups/'
|
||||
}
|
||||
},
|
||||
remote_apps: {
|
||||
el: {
|
||||
value: [],
|
||||
url: '/api/v1/applications/remote-apps/'
|
||||
}
|
||||
},
|
||||
system_users: {
|
||||
el: {
|
||||
value: [],
|
||||
url: '/api/v1/assets/system-users/'
|
||||
}
|
||||
},
|
||||
actions: {
|
||||
label: this.$t('perms.Actions')
|
||||
},
|
||||
is_active: {
|
||||
type: 'checkbox'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
@@ -4,7 +4,7 @@
|
||||
|
||||
<script>
|
||||
import { GenericListPage } from '@/layout/components'
|
||||
import { DetailFormatter, ActionsFormatter, BooleanFormatter } from '@/components/ListTable/formatters/index'
|
||||
import { LengthFormatter } from '@/components/ListTable/formatters/index'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
@@ -14,52 +14,21 @@ export default {
|
||||
return {
|
||||
tableConfig: {
|
||||
url: '/api/v1/perms/remote-app-permissions/',
|
||||
columns: [
|
||||
{
|
||||
prop: 'name',
|
||||
label: this.$t('perms.name'),
|
||||
formatter: DetailFormatter,
|
||||
sortable: true,
|
||||
route: 'RemoteAppPermissionDetail'
|
||||
columns: ['name', 'users', 'user_groups', 'remote_apps', 'system_users', 'is_valid', 'actions'],
|
||||
columnsMeta: {
|
||||
users: {
|
||||
formatter: LengthFormatter
|
||||
},
|
||||
{
|
||||
prop: 'users.length',
|
||||
label: this.$t('perms.user')
|
||||
user_groups: {
|
||||
formatter: LengthFormatter
|
||||
},
|
||||
{
|
||||
prop: 'user_groups.length',
|
||||
label: this.$t('perms.userGroup')
|
||||
remote_apps: {
|
||||
formatter: LengthFormatter
|
||||
},
|
||||
{
|
||||
prop: 'remote_apps.length',
|
||||
label: this.$t('perms.RemoteApp')
|
||||
},
|
||||
{
|
||||
prop: 'system_users.length',
|
||||
label: this.$t('perms.systemUser')
|
||||
},
|
||||
{
|
||||
prop: 'is_valid',
|
||||
label: this.$t('perms.validity'),
|
||||
formatter: BooleanFormatter,
|
||||
align: 'center',
|
||||
width: '80px'
|
||||
},
|
||||
{
|
||||
prop: 'id',
|
||||
label: this.$tc('Action'),
|
||||
align: 'center',
|
||||
formatter: ActionsFormatter,
|
||||
width: '200px',
|
||||
actions: {
|
||||
performDelete: ({ row, col }) => {
|
||||
const id = row.id
|
||||
const url = `/api/v1/perms/database-app-permissions/${id}/`
|
||||
return this.$axios.delete(url)
|
||||
}
|
||||
}
|
||||
system_users: {
|
||||
formatter: LengthFormatter
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
headerActions: {
|
||||
hasBulkDelete: false,
|
||||
|
@@ -3,6 +3,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { timeOffset, toSafeLocalDateStr } from '@/utils/common'
|
||||
import { GenericListPage } from '@/layout/components'
|
||||
import { ActionsFormatter } from '@/components/ListTable/formatters/index'
|
||||
|
||||
@@ -13,80 +14,72 @@ export default {
|
||||
data() {
|
||||
return {
|
||||
tableConfig: {
|
||||
axiosConfig: {
|
||||
raw: 1,
|
||||
params: {
|
||||
display: 1,
|
||||
is_finished: 1
|
||||
}
|
||||
},
|
||||
url: '/api/v1/terminal/sessions/',
|
||||
hasSelection: false,
|
||||
url: '/api/v1/terminal/sessions/?is_finished=1',
|
||||
columns: [
|
||||
{
|
||||
label: this.$t('sessions.id'),
|
||||
type: 'index'
|
||||
'index', 'user', 'asset', 'system_user', 'remote_addr', 'protocol', 'login_from',
|
||||
'command_amount', 'date_start', 'duration', 'actions'
|
||||
],
|
||||
columnsMeta: {
|
||||
index: {
|
||||
type: 'index',
|
||||
label: this.$t('sessions.id')
|
||||
},
|
||||
{
|
||||
prop: 'user',
|
||||
label: this.$t('sessions.user'),
|
||||
sortable: 'custom'
|
||||
},
|
||||
{
|
||||
prop: 'asset',
|
||||
label: this.$t('sessions.asset'),
|
||||
sortable: 'custom'
|
||||
},
|
||||
{
|
||||
prop: 'system_user',
|
||||
label: this.$t('sessions.systemUser'),
|
||||
sortable: 'custom'
|
||||
},
|
||||
{
|
||||
prop: 'remote_addr',
|
||||
label: this.$t('sessions.remoteAddr'),
|
||||
sortable: 'custom'
|
||||
},
|
||||
{
|
||||
prop: 'protocol',
|
||||
label: this.$t('sessions.protocol'),
|
||||
sortable: 'custom'
|
||||
},
|
||||
{
|
||||
prop: 'login_from_display',
|
||||
label: this.$t('sessions.loginForm')
|
||||
},
|
||||
{
|
||||
prop: 'command',
|
||||
command_amount: {
|
||||
label: this.$t('sessions.command')
|
||||
},
|
||||
{
|
||||
prop: 'date_start',
|
||||
label: this.$t('sessions.dateStart'),
|
||||
sortable: 'custom'
|
||||
login_from: {
|
||||
label: this.$t('sessions.loginForm')
|
||||
},
|
||||
{
|
||||
prop: 'duration',
|
||||
label: this.$t('sessions.duration')
|
||||
protocol: {
|
||||
label: this.$t('sessions.protocol'),
|
||||
formatter: null
|
||||
},
|
||||
{
|
||||
date_start: {
|
||||
formatter: function(row) {
|
||||
return toSafeLocalDateStr(row.date_start)
|
||||
}
|
||||
},
|
||||
duration: {
|
||||
label: this.$t('sessions.duration'),
|
||||
formatter: function(row) {
|
||||
return timeOffset(row.date_start, row.date_end)
|
||||
}
|
||||
},
|
||||
actions: {
|
||||
prop: 'id',
|
||||
label: this.$tc('Action'),
|
||||
align: 'center',
|
||||
formatter: ActionsFormatter,
|
||||
width: '200px',
|
||||
actions: {
|
||||
hasEdit: false,
|
||||
hasDelete: false,
|
||||
hasUpdate: false,
|
||||
extraActions: [
|
||||
{
|
||||
name: 'terminate',
|
||||
title: this.$t('sessions.terminate'),
|
||||
type: 'primary'
|
||||
name: 'replay',
|
||||
title: this.$t('sessions.replay'),
|
||||
type: 'warning',
|
||||
callback: function({ cellValue, tableData }) {
|
||||
// 跳转到luna页面
|
||||
const replayUrl = '/luna/replay/' + cellValue
|
||||
window.open(replayUrl)
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'download',
|
||||
title: this.$t('sessions.download'),
|
||||
type: 'primary',
|
||||
callback: function({ cellValue, tableData }) {
|
||||
// 跳转下载页面
|
||||
const downloadUrl = 'terminal/session/00000000-0000-0000-0000-000000000000/replay/download/'
|
||||
.replace('00000000-0000-0000-0000-000000000000', cellValue)
|
||||
window.open(downloadUrl)
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
headerActions: {
|
||||
hasCreate: false,
|
||||
|
@@ -5,6 +5,8 @@
|
||||
<script>
|
||||
import { GenericListPage } from '@/layout/components'
|
||||
import { ActionsFormatter } from '@/components/ListTable/formatters/index'
|
||||
import { toSafeLocalDateStr } from '@/utils/common'
|
||||
import { terminateSession } from '@/api/sessions'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
@@ -13,85 +15,73 @@ export default {
|
||||
data() {
|
||||
return {
|
||||
tableConfig: {
|
||||
axiosConfig: {
|
||||
raw: 1,
|
||||
params: {
|
||||
display: 1,
|
||||
is_finished: 0
|
||||
}
|
||||
},
|
||||
url: '/api/v1/terminal/sessions/',
|
||||
url: '/api/v1/terminal/sessions/?is_finished=0',
|
||||
columns: [
|
||||
{
|
||||
label: this.$t('sessions.id'),
|
||||
type: 'index'
|
||||
'index', 'user', 'asset', 'system_user', 'remote_addr', 'protocol', 'login_from',
|
||||
'command_amount', 'date_start', 'duration', 'actions'
|
||||
],
|
||||
columnsMeta: {
|
||||
index: {
|
||||
type: 'index',
|
||||
label: this.$t('sessions.id')
|
||||
},
|
||||
{
|
||||
prop: 'user',
|
||||
label: this.$t('sessions.user'),
|
||||
sortable: 'custom'
|
||||
},
|
||||
{
|
||||
prop: 'asset',
|
||||
label: this.$t('sessions.asset'),
|
||||
sortable: 'custom'
|
||||
},
|
||||
{
|
||||
prop: 'system_user',
|
||||
label: this.$t('sessions.systemUser'),
|
||||
sortable: 'custom'
|
||||
},
|
||||
{
|
||||
prop: 'remote_addr',
|
||||
label: this.$t('sessions.remoteAddr'),
|
||||
sortable: 'custom'
|
||||
},
|
||||
{
|
||||
prop: 'protocol',
|
||||
label: this.$t('sessions.protocol'),
|
||||
sortable: 'custom'
|
||||
},
|
||||
{
|
||||
prop: 'login_from_display',
|
||||
label: this.$t('sessions.loginForm')
|
||||
},
|
||||
{
|
||||
prop: 'command',
|
||||
command_amount: {
|
||||
label: this.$t('sessions.command')
|
||||
},
|
||||
{
|
||||
prop: 'date_start',
|
||||
label: this.$t('sessions.dateStart'),
|
||||
sortable: 'custom'
|
||||
login_from: {
|
||||
label: this.$t('sessions.loginForm')
|
||||
},
|
||||
{
|
||||
prop: 'duration',
|
||||
label: this.$t('sessions.duration')
|
||||
protocol: {
|
||||
label: this.$t('sessions.protocol'),
|
||||
formatter: null
|
||||
},
|
||||
{
|
||||
date_start: {
|
||||
formatter: function(row) {
|
||||
return toSafeLocalDateStr(row.date_start)
|
||||
}
|
||||
},
|
||||
duration: {
|
||||
label: this.$t('sessions.duration'),
|
||||
formatter: null
|
||||
},
|
||||
actions: {
|
||||
prop: 'id',
|
||||
label: this.$tc('Action'),
|
||||
align: 'center',
|
||||
formatter: ActionsFormatter,
|
||||
width: '200px',
|
||||
actions: {
|
||||
hasEdit: false,
|
||||
hasDelete: false,
|
||||
hasUpdate: false,
|
||||
extraActions: [
|
||||
{
|
||||
name: 'replay',
|
||||
title: this.$t('sessions.replay'),
|
||||
type: 'primary'
|
||||
name: 'terminate',
|
||||
title: this.$t('sessions.terminate'),
|
||||
type: 'danger',
|
||||
callback: function({ reload, cellValue, tableData }) {
|
||||
// 终断 session reload
|
||||
const data = [cellValue]
|
||||
terminateSession(data).then(res => {
|
||||
window.setTimeout(function() {
|
||||
reload()
|
||||
}, 50000)
|
||||
}
|
||||
)
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'replay',
|
||||
title: this.$t('sessions.download'),
|
||||
type: 'warning'
|
||||
name: 'join',
|
||||
title: this.$t('sessions.join'),
|
||||
type: 'primary',
|
||||
callback: function({ cellValue, tableData }) {
|
||||
// 跳转到luna页面
|
||||
const joinUrl = '/luna/join/?shareroom=' + cellValue
|
||||
window.open(joinUrl, 'height=600, width=800, top=400, left=400, toolbar=no, menubar=no, scrollbars=no, location=no, status=no')
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
headerActions: {
|
||||
hasCreate: false,
|
||||
|
@@ -4,7 +4,6 @@
|
||||
|
||||
<script>
|
||||
import { GenericListPage } from '@/layout/components'
|
||||
import { ExpandPreFormatter } from '@/components/ListTable/formatters'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
@@ -18,10 +17,6 @@ export default {
|
||||
columnsMeta: {
|
||||
users_amount: {
|
||||
label: this.$t('users.Users')
|
||||
},
|
||||
name: {
|
||||
type: 'expand',
|
||||
formatter: ExpandPreFormatter
|
||||
}
|
||||
},
|
||||
detailRoute: 'UserGroupDetail'
|
||||
|
Reference in New Issue
Block a user