mirror of
https://github.com/jumpserver/lina.git
synced 2025-09-26 06:58:53 +00:00
merge: with remote
This commit is contained in:
@@ -161,8 +161,7 @@ export default {
|
|||||||
iAsset: this.asset,
|
iAsset: this.asset,
|
||||||
account: {},
|
account: {},
|
||||||
secretUrl: '',
|
secretUrl: '',
|
||||||
quickFilters: accountQuickFilters,
|
quickFilters: accountQuickFilters(this),
|
||||||
tabDeactivated: false,
|
|
||||||
tableConfig: {
|
tableConfig: {
|
||||||
url: this.url,
|
url: this.url,
|
||||||
permissions: {
|
permissions: {
|
||||||
|
@@ -112,7 +112,7 @@ export const accountOtherActions = (vm) => [
|
|||||||
{
|
{
|
||||||
name: 'SecretHistory',
|
name: 'SecretHistory',
|
||||||
// 密文历史
|
// 密文历史
|
||||||
title: vm.$t('SecretHistory'),
|
title: vm.$t('HistoryPassword'),
|
||||||
can: () => vm.$hasPerm('accounts.view_accountsecret'),
|
can: () => vm.$hasPerm('accounts.view_accountsecret'),
|
||||||
type: 'primary',
|
type: 'primary',
|
||||||
callback: ({ row }) => {
|
callback: ({ row }) => {
|
||||||
@@ -124,7 +124,7 @@ export const accountOtherActions = (vm) => [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'CopyToOther',
|
name: 'CopyToOther',
|
||||||
title: vm.$t('CopyToOther'),
|
title: vm.$t('CopyToAsset'),
|
||||||
type: 'primary',
|
type: 'primary',
|
||||||
divided: true,
|
divided: true,
|
||||||
callback: ({ row }) => {
|
callback: ({ row }) => {
|
||||||
@@ -137,7 +137,7 @@ export const accountOtherActions = (vm) => [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'MoveToOther',
|
name: 'MoveToOther',
|
||||||
title: vm.$t('MoveToOther'),
|
title: vm.$t('MoveToAsset'),
|
||||||
type: 'primary',
|
type: 'primary',
|
||||||
callback: ({ row }) => {
|
callback: ({ row }) => {
|
||||||
vm.accountCreateUpdateTitle = vm.$t('MoveToOther')
|
vm.accountCreateUpdateTitle = vm.$t('MoveToOther')
|
||||||
@@ -149,36 +149,36 @@ export const accountOtherActions = (vm) => [
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
export const accountQuickFilters = [
|
export const accountQuickFilters = (vm) => [
|
||||||
{
|
{
|
||||||
label: '最近(7天)',
|
label: vm.$t('Recent (7 days)'),
|
||||||
options: [
|
options: [
|
||||||
{
|
{
|
||||||
label: '最近发现',
|
label: vm.$t('RecentlyDiscovered'),
|
||||||
filter: {
|
filter: {
|
||||||
latest_discovery: '1'
|
latest_discovery: '1'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '最近被登录',
|
label: vm.$t('RecentlyLoggedIn'),
|
||||||
filter: {
|
filter: {
|
||||||
latest_accessed: '1'
|
latest_accessed: '1'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '最近修改',
|
label: vm.$t('RecentlyModified'),
|
||||||
filter: {
|
filter: {
|
||||||
latest_updated: '1'
|
latest_updated: '1'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '最近改密',
|
label: vm.$t('RecentlyChangedPassword'),
|
||||||
filter: {
|
filter: {
|
||||||
latest_secret_changed: '1'
|
latest_secret_changed: '1'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '最近改密失败',
|
label: vm.$t('RecentPasswordChangeFailed'),
|
||||||
filter: {
|
filter: {
|
||||||
latest_secret_changed_failed: '1'
|
latest_secret_changed_failed: '1'
|
||||||
}
|
}
|
||||||
@@ -186,40 +186,40 @@ export const accountQuickFilters = [
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '风险账号',
|
label: vm.$t('RiskyAccount'),
|
||||||
options: [
|
options: [
|
||||||
{
|
{
|
||||||
label: '僵尸账号',
|
label: vm.$t('LongTimeNoLogin'),
|
||||||
filter: {
|
filter: {
|
||||||
risk: 'long_time_no_login'
|
risk: 'long_time_no_login'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '幽灵账号',
|
label: vm.$t('UnmanagedAccount'),
|
||||||
filter: {
|
filter: {
|
||||||
risk: 'new_found'
|
risk: 'new_found'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '弱密码',
|
label: vm.$t('WeakPassword'),
|
||||||
filter: {
|
filter: {
|
||||||
risk: 'weak_password'
|
risk: 'weak_password'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '空密码',
|
label: vm.$t('EmptyPassword'),
|
||||||
filter: {
|
filter: {
|
||||||
has_secret: 'false'
|
has_secret: 'false'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '长时间未改密',
|
label: vm.$t('LongTimeNoChangeSecret'),
|
||||||
filter: {
|
filter: {
|
||||||
long_time_no_change_secret: 'true'
|
long_time_no_change_secret: 'true'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '长时间未验证',
|
label: vm.$t('LongTimeNoVerify'),
|
||||||
filter: {
|
filter: {
|
||||||
long_time_no_verify: 'true'
|
long_time_no_verify: 'true'
|
||||||
}
|
}
|
||||||
@@ -227,34 +227,34 @@ export const accountQuickFilters = [
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '账号类型',
|
label: vm.$t('AccountType'),
|
||||||
options: [
|
options: [
|
||||||
{
|
{
|
||||||
label: '全部',
|
label: vm.$t('All'),
|
||||||
filter: {
|
filter: {
|
||||||
category: ''
|
category: ''
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: ' 主机',
|
label: vm.$t('Host'),
|
||||||
filter: {
|
filter: {
|
||||||
category: 'host'
|
category: 'host'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '数据库',
|
label: vm.$t('Database'),
|
||||||
filter: {
|
filter: {
|
||||||
category: 'database'
|
category: 'database'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '云',
|
label: vm.$t('Cloud'),
|
||||||
filter: {
|
filter: {
|
||||||
category: 'cloud'
|
category: 'cloud'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '网络设备',
|
label: vm.$t('Device'),
|
||||||
filter: {
|
filter: {
|
||||||
category: 'device'
|
category: 'device'
|
||||||
}
|
}
|
||||||
@@ -266,7 +266,7 @@ export const accountQuickFilters = [
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '其他',
|
label: vm.$t('Other'),
|
||||||
filter: {
|
filter: {
|
||||||
category: 'custom'
|
category: 'custom'
|
||||||
}
|
}
|
||||||
|
150
src/components/Table/TableFormatters/AccountConnectFormatter.vue
Normal file
150
src/components/Table/TableFormatters/AccountConnectFormatter.vue
Normal file
@@ -0,0 +1,150 @@
|
|||||||
|
<template>
|
||||||
|
<el-dropdown
|
||||||
|
size="small"
|
||||||
|
trigger="hover"
|
||||||
|
:show-timeout="500"
|
||||||
|
@command="handleCommand"
|
||||||
|
@visible-change="visibleChange"
|
||||||
|
>
|
||||||
|
<el-button
|
||||||
|
plain
|
||||||
|
size="mini"
|
||||||
|
type="primary"
|
||||||
|
@click="handlePamConnect"
|
||||||
|
>
|
||||||
|
<i :class="IButtonIcon" />
|
||||||
|
</el-button>
|
||||||
|
<el-dropdown-menu slot="dropdown">
|
||||||
|
<el-dropdown-item command="Title" disabled>
|
||||||
|
{{ ITitleText }}
|
||||||
|
</el-dropdown-item>
|
||||||
|
<el-dropdown-item divided />
|
||||||
|
<el-dropdown-item
|
||||||
|
v-for="protocol in protocols"
|
||||||
|
:key="protocol.id"
|
||||||
|
:command="protocol.name"
|
||||||
|
>
|
||||||
|
{{ protocol.name }}
|
||||||
|
</el-dropdown-item>
|
||||||
|
</el-dropdown-menu>
|
||||||
|
</el-dropdown>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import BaseFormatter from './base.vue'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'AccountConnectFormatter',
|
||||||
|
extends: BaseFormatter,
|
||||||
|
props: {
|
||||||
|
buttonIcon: {
|
||||||
|
type: String,
|
||||||
|
default: 'fa fa-desktop'
|
||||||
|
},
|
||||||
|
titleText: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
url: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
connectUrlTemplate: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
protocols: []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
IButtonIcon() {
|
||||||
|
return this.buttonIcon
|
||||||
|
},
|
||||||
|
ITitleText() {
|
||||||
|
return this.titleText || this.$t('OptionalProtocol')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
handleCommand(protocol) {
|
||||||
|
if (protocol === 'Title') return
|
||||||
|
|
||||||
|
this.$store.commit('table/SET_PROTOCOL_MAP_ITEM', {
|
||||||
|
key: this.row.id,
|
||||||
|
value: protocol
|
||||||
|
})
|
||||||
|
|
||||||
|
this.handleWindowOpen(this.row, protocol)
|
||||||
|
},
|
||||||
|
visibleChange(visible) {
|
||||||
|
if (visible) {
|
||||||
|
this.getProtocols(this.row.asset.id)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
handleWindowOpen(row, protocol) {
|
||||||
|
const url = this.formatterArgs.connectUrlTemplate
|
||||||
|
.replace('{id}', row.id)
|
||||||
|
.replace('{username}', row.username)
|
||||||
|
.replace('{assetId}', row.asset.id)
|
||||||
|
.replace('{assetName}', row.asset.name)
|
||||||
|
.replace('{protocol}', protocol)
|
||||||
|
|
||||||
|
window.open(url, '_blank')
|
||||||
|
},
|
||||||
|
async handlePamConnect() {
|
||||||
|
const protocolMap = this.$store.getters.protocolMap
|
||||||
|
|
||||||
|
if (protocolMap.has(this.row.id)) {
|
||||||
|
const protocol = protocolMap.get(this.row.id)
|
||||||
|
this.handleWindowOpen(this.row, protocol)
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
const url = this.formatterArgs.url.replace('{id}', this.row.asset.id)
|
||||||
|
const res = await this.$axios.get(url)
|
||||||
|
|
||||||
|
if (res && res.protocols.length > 0) {
|
||||||
|
const protocol = res.protocols[0]
|
||||||
|
|
||||||
|
this.$store.commit('table/SET_PROTOCOL_MAP_ITEM', {
|
||||||
|
key: this.row.id,
|
||||||
|
value: protocol.name
|
||||||
|
})
|
||||||
|
|
||||||
|
this.handleWindowOpen(this.row, protocol.name)
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
throw new Error(`Error getting protocols: ${e}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async getProtocols(assetId) {
|
||||||
|
try {
|
||||||
|
const url = this.formatterArgs.url.replace('{id}', assetId)
|
||||||
|
const res = await this.$axios.get(url)
|
||||||
|
|
||||||
|
if (res) this.protocols = res.protocols
|
||||||
|
} catch (e) {
|
||||||
|
throw new Error(`Error getting protocols: ${e}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.el-dropdown-menu__item.is-disabled {
|
||||||
|
font-weight: 500;
|
||||||
|
color: var(--el-text-color-secondary);
|
||||||
|
}
|
||||||
|
|
||||||
|
::v-deep .el-dropdown-menu__item {
|
||||||
|
transition: height 0.3s ease-in-out, padding 0.3s ease-in-out;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
::v-deep .el-dropdown-menu {
|
||||||
|
transition: min-height 0.3s ease-in-out;
|
||||||
|
}
|
||||||
|
</style>
|
@@ -20,6 +20,7 @@ import SwitchFormatter from './SwitchFormatter.vue'
|
|||||||
import AccountInfoFormatter from './AccountInfoFormatter.vue'
|
import AccountInfoFormatter from './AccountInfoFormatter.vue'
|
||||||
import PlatformFormatter from './PlatformFormatter.vue'
|
import PlatformFormatter from './PlatformFormatter.vue'
|
||||||
import DiscoverConfirmFormatter from './DiscoverConfirmFormatter.vue'
|
import DiscoverConfirmFormatter from './DiscoverConfirmFormatter.vue'
|
||||||
|
import AccountConnectFormatter from './AccountConnectFormatter.vue'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
DetailFormatter,
|
DetailFormatter,
|
||||||
@@ -43,7 +44,8 @@ export default {
|
|||||||
SwitchFormatter,
|
SwitchFormatter,
|
||||||
PlatformFormatter,
|
PlatformFormatter,
|
||||||
AccountInfoFormatter,
|
AccountInfoFormatter,
|
||||||
DiscoverConfirmFormatter
|
DiscoverConfirmFormatter,
|
||||||
|
AccountConnectFormatter
|
||||||
}
|
}
|
||||||
|
|
||||||
export {
|
export {
|
||||||
@@ -68,5 +70,6 @@ export {
|
|||||||
SwitchFormatter,
|
SwitchFormatter,
|
||||||
PlatformFormatter,
|
PlatformFormatter,
|
||||||
DiscoverConfirmFormatter,
|
DiscoverConfirmFormatter,
|
||||||
AccountInfoFormatter
|
AccountInfoFormatter,
|
||||||
|
AccountConnectFormatter
|
||||||
}
|
}
|
||||||
|
@@ -75,20 +75,20 @@ export default {
|
|||||||
},
|
},
|
||||||
quickSummary: [
|
quickSummary: [
|
||||||
{
|
{
|
||||||
title: '最近一周发现',
|
title: this.$t('DateLastWeek'),
|
||||||
hasCount: true,
|
hasCount: true,
|
||||||
filter: {
|
filter: {
|
||||||
'days': '7'
|
'days': '7'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '最近一月发现',
|
title: this.$t('DateLastMonth'),
|
||||||
filter: {
|
filter: {
|
||||||
'days': '30'
|
'days': '30'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '待确认',
|
title: this.$t('Pending'),
|
||||||
filter: {
|
filter: {
|
||||||
status: '0'
|
status: '0'
|
||||||
}
|
}
|
||||||
|
@@ -22,13 +22,14 @@ export default {
|
|||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
config: {
|
config: {
|
||||||
title: this.$t('账号汇总'),
|
title: this.$t('AccountSummary'),
|
||||||
tip: this.$t('RealTimeData')
|
tip: this.$t('RealTimeData')
|
||||||
},
|
},
|
||||||
counter: {
|
counter: {
|
||||||
total_count_online_sessions: '.',
|
total_privileged_accounts: '',
|
||||||
total_count_online_users: '.',
|
total_ordinary_accounts: '',
|
||||||
total_count_today_failed_sessions: '.'
|
total_unmanaged_accounts: '',
|
||||||
|
total_unavailable_accounts: ''
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -36,32 +37,31 @@ export default {
|
|||||||
summaryItems() {
|
summaryItems() {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
title: this.$t('特权账号'),
|
title: this.$t('Privileged'),
|
||||||
body: {
|
body: {
|
||||||
route: { name: `SessionList`, params: { activeMenu: 'OnlineList' }},
|
route: { name: `SessionList`, params: { activeMenu: 'OnlineList' }},
|
||||||
count: 4932,
|
count: this.counter.total_privileged_accounts,
|
||||||
disabled: !this.$hasPerm('terminal.view_session')
|
disabled: !this.$hasPerm('terminal.view_session')
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: this.$t('普通账号'),
|
title: this.$t('GeneralAccounts'),
|
||||||
body: {
|
body: {
|
||||||
route: { name: `SessionList`, params: { activeMenu: 'OnlineList' }},
|
route: { name: `SessionList`, params: { activeMenu: 'OnlineList' }},
|
||||||
count: 2323,
|
count: this.counter.total_ordinary_accounts
|
||||||
disabled: !this.$hasPerm('terminal.view_session')
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: this.$t('未托管账号'),
|
title: this.$t('UnmanagedAccount'),
|
||||||
body: {
|
body: {
|
||||||
count: 1233,
|
count: this.counter.total_unmanaged_accounts,
|
||||||
disabled: true
|
disabled: true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: this.$t('不可用账号'),
|
title: this.$t('UnavailableAccount'),
|
||||||
body: {
|
body: {
|
||||||
count: 123,
|
count: this.counter.total_unavailable_accounts,
|
||||||
disabled: true
|
disabled: true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -74,12 +74,13 @@ export default {
|
|||||||
methods: {
|
methods: {
|
||||||
async getResourcesCount() {
|
async getResourcesCount() {
|
||||||
return this.$axios.get(
|
return this.$axios.get(
|
||||||
'/api/v1/index/',
|
'/api/v1/accounts/pam-dashboard/',
|
||||||
{
|
{
|
||||||
params: {
|
params: {
|
||||||
total_count_online_sessions: 1,
|
total_privileged_accounts: 1,
|
||||||
total_count_online_users: 1,
|
total_ordinary_accounts: 1,
|
||||||
total_count_today_failed_sessions: 1
|
total_unmanaged_accounts: 1,
|
||||||
|
total_unavailable_accounts: 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
<div>
|
<div>
|
||||||
<el-row :gutter="16">
|
<el-row :gutter="16">
|
||||||
<el-col :lg="24" :sm="12">
|
<el-col :lg="24" :sm="12">
|
||||||
<SummaryChart :config="userConfig" />
|
<SummaryChart :config="accountConfig" />
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
</div>
|
</div>
|
||||||
@@ -10,41 +10,22 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import SummaryChart from './SummaryChart.vue'
|
import SummaryChart from './SummaryChart.vue'
|
||||||
import Decimal from 'decimal.js'
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
SummaryChart
|
SummaryChart
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
const documentStyle = document.documentElement.style
|
|
||||||
const themeColor = documentStyle.getPropertyValue('--color-primary')
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
userConfig: {
|
accountConfig: {
|
||||||
title: this.$t('账号数据'),
|
title: this.$t('AccountData'),
|
||||||
tip: this.$t('UserData'),
|
tip: this.$t('UserData'),
|
||||||
subTitle: this.$t('账号总数'),
|
subTitle: this.$t('AccountTotal'),
|
||||||
icon: 'users',
|
icon: 'users',
|
||||||
subIcon: 'broken-line',
|
|
||||||
color: '#FFD260',
|
|
||||||
chartTitle: this.$t('LoginUserToday'),
|
|
||||||
data: [],
|
data: [],
|
||||||
route: { name: 'UserList' },
|
route: { name: 'PamAccounts' },
|
||||||
total: 0,
|
total: 0,
|
||||||
active: 0,
|
|
||||||
weekAdd: 0
|
weekAdd: 0
|
||||||
},
|
|
||||||
assetConfig: {
|
|
||||||
title: this.$t('AssetData'),
|
|
||||||
tip: this.$t('AssetData'),
|
|
||||||
subTitle: this.$t('AssetsTotal'),
|
|
||||||
icon: 'assets',
|
|
||||||
subIcon: 'broken-line',
|
|
||||||
color: themeColor,
|
|
||||||
chartTitle: this.$t('LoginAssetToday'),
|
|
||||||
data: [],
|
|
||||||
route: { name: 'AssetList' }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -53,52 +34,22 @@ export default {
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
async init() {
|
async init() {
|
||||||
const data = await this.$axios.get(`/api/v1/index/?total_count_users=1
|
const data = await this.$axios.get(
|
||||||
&total_count_users_this_week=1
|
'/api/v1/accounts/pam-dashboard/',
|
||||||
&total_count_login_users=1
|
{
|
||||||
&total_count_assets=1
|
params: {
|
||||||
&total_count_assets_this_week=1
|
total_accounts: 1,
|
||||||
&total_count_today_active_assets=1
|
total_week_add_accounts: 1
|
||||||
`)
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
const loginUserCountDecimal = data.total_count_login_users ? new Decimal(data.total_count_login_users) : new Decimal(0)
|
this.accountConfig.total = data.total_accounts
|
||||||
const userCountDecimal = data.total_count_users ? new Decimal(data.total_count_users) : new Decimal(0)
|
this.accountConfig.weekAdd = data.total_week_add_accounts
|
||||||
|
|
||||||
let userActive = loginUserCountDecimal.dividedBy(userCountDecimal).times(100)
|
|
||||||
userActive = isNaN(userActive) ? 0 : userActive
|
|
||||||
userActive = userActive.toFixed(2)
|
|
||||||
const userTotal = userActive === 100 ? 0 : 100 - userActive
|
|
||||||
const users = [
|
|
||||||
{ name: this.$t('ActiveUser'), value: userActive.toString() },
|
|
||||||
{ name: this.$t('InActiveUser'), value: userTotal.toString() }
|
|
||||||
]
|
|
||||||
this.$set(this.userConfig, 'data', users)
|
|
||||||
this.userConfig.total = data.total_count_users
|
|
||||||
this.userConfig.active = data.total_count_login_users
|
|
||||||
this.userConfig.weekAdd = data.total_count_users_this_week
|
|
||||||
|
|
||||||
const ActiveAssetCountDecimal = data.total_count_today_active_assets ? new Decimal(data.total_count_today_active_assets) : new Decimal(0)
|
|
||||||
const AssetCountDecimal = data.total_count_assets ? new Decimal(data.total_count_assets) : new Decimal(0)
|
|
||||||
|
|
||||||
let assetActive = ActiveAssetCountDecimal.dividedBy(AssetCountDecimal).times(100)
|
|
||||||
assetActive = isNaN(assetActive) ? 0 : assetActive
|
|
||||||
assetActive = assetActive.toFixed(2)
|
|
||||||
const assetTotal = assetActive === 100 ? 0 : 100 - assetActive
|
|
||||||
const assets = [
|
|
||||||
{ name: this.$t('ActiveAsset'), value: assetActive.toString() },
|
|
||||||
{ name: this.$t('InActiveAsset'), value: assetTotal.toString() }
|
|
||||||
]
|
|
||||||
this.$set(this.assetConfig, 'data', assets)
|
|
||||||
this.$set(this.assetConfig, 'total', data.total_count_assets)
|
|
||||||
this.$set(this.assetConfig, 'active', data.total_count_today_active_assets)
|
|
||||||
this.$set(this.assetConfig, 'weekAdd', data.total_count_assets_this_week)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.left, .right {
|
|
||||||
display: inline-block;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
@@ -22,13 +22,13 @@ export default {
|
|||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
config: {
|
config: {
|
||||||
title: this.$t('风险账号'),
|
title: this.$t('RiskyAccount'),
|
||||||
tip: this.$t('RealTimeData')
|
tip: this.$t('RealTimeData')
|
||||||
},
|
},
|
||||||
counter: {
|
counter: {
|
||||||
total_count_online_sessions: '.',
|
total_long_time_no_login_accounts: '.',
|
||||||
total_count_online_users: '.',
|
total_weak_password_accounts: '.',
|
||||||
total_count_today_failed_sessions: '.'
|
total_long_time_change_password_accounts: '.'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -36,32 +36,23 @@ export default {
|
|||||||
summaryItems() {
|
summaryItems() {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
title: this.$t('幽灵账号'),
|
title: this.$t('LongTimeNoLogin'),
|
||||||
body: {
|
body: {
|
||||||
route: { name: `SessionList`, params: { activeMenu: 'OnlineList' }},
|
route: { name: `SessionList`, params: { activeMenu: 'OnlineList' }},
|
||||||
count: 23,
|
count: this.counter.total_long_time_no_login_accounts
|
||||||
disabled: !this.$hasPerm('terminal.view_session')
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: this.$t('僵尸账号'),
|
title: this.$t('WeakPassword'),
|
||||||
body: {
|
body: {
|
||||||
route: { name: `SessionList`, params: { activeMenu: 'OnlineList' }},
|
count: this.counter.total_weak_password_accounts,
|
||||||
count: 293,
|
|
||||||
disabled: !this.$hasPerm('terminal.view_session')
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: this.$t('弱密码'),
|
|
||||||
body: {
|
|
||||||
count: 203,
|
|
||||||
disabled: true
|
disabled: true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: this.$t('长时未改密'),
|
title: this.$t('LongTimeNoChangeSecret'),
|
||||||
body: {
|
body: {
|
||||||
count: 1010,
|
count: this.counter.total_long_time_change_password_accounts,
|
||||||
disabled: true
|
disabled: true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -74,12 +65,16 @@ export default {
|
|||||||
methods: {
|
methods: {
|
||||||
async getResourcesCount() {
|
async getResourcesCount() {
|
||||||
return this.$axios.get(
|
return this.$axios.get(
|
||||||
'/api/v1/index/',
|
'/api/v1/accounts/pam-dashboard/',
|
||||||
{
|
{
|
||||||
params: {
|
params: {
|
||||||
total_count_online_sessions: 1,
|
total_privileged_accounts: 1,
|
||||||
total_count_online_users: 1,
|
total_ordinary_accounts: 1,
|
||||||
total_count_today_failed_sessions: 1
|
total_unmanaged_accounts: 1,
|
||||||
|
total_unavailable_accounts: 1,
|
||||||
|
total_long_time_no_login_accounts: 1,
|
||||||
|
total_weak_password_accounts: 1,
|
||||||
|
total_long_time_change_password_accounts: 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@@ -9,7 +9,7 @@
|
|||||||
<div>
|
<div>
|
||||||
<template v-if="config.route">
|
<template v-if="config.route">
|
||||||
<router-link :to="config.route">
|
<router-link :to="config.route">
|
||||||
<div class="num"> 1000 </div>
|
<div class="num"> {{ config.total }} </div>
|
||||||
</router-link>
|
</router-link>
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
|
@@ -3,9 +3,8 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { mapGetters } from 'vuex'
|
|
||||||
import { DetailFormatter } from '@/components/Table/TableFormatters'
|
|
||||||
import AccountListTable from '@/components/Apps/AccountListTable/AccountList.vue'
|
import AccountListTable from '@/components/Apps/AccountListTable/AccountList.vue'
|
||||||
|
import { DetailFormatter, AccountConnectFormatter } from '@/components/Table/TableFormatters'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'AssetAccountList',
|
name: 'AssetAccountList',
|
||||||
@@ -14,9 +13,6 @@ export default {
|
|||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
drawerTitle: '',
|
|
||||||
currentProtocol: '',
|
|
||||||
perm_protocols: [],
|
|
||||||
tableConfig: {
|
tableConfig: {
|
||||||
url: '/api/v1/accounts/accounts/',
|
url: '/api/v1/accounts/accounts/',
|
||||||
hasLeftActions: true,
|
hasLeftActions: true,
|
||||||
@@ -38,127 +34,21 @@ export default {
|
|||||||
connect: {
|
connect: {
|
||||||
label: this.$t('Connect'),
|
label: this.$t('Connect'),
|
||||||
width: '80px',
|
width: '80px',
|
||||||
formatter: row => {
|
formatter: AccountConnectFormatter,
|
||||||
return (
|
formatterArgs: {
|
||||||
<span class='connect'>
|
buttonIcon: 'fa fa-desktop',
|
||||||
<el-dropdown
|
titleText: '可选协议',
|
||||||
{...{
|
url: '/api/v1/assets/assets/{id}',
|
||||||
props: {
|
connectUrlTemplate: '/luna/pam_connect/{id}/{username}/{assetId}/{assetName}/{protocol}'
|
||||||
trigger: 'hover',
|
|
||||||
size: 'small',
|
|
||||||
showTimeout: 500
|
|
||||||
},
|
|
||||||
on: {
|
|
||||||
'visible-change': visible => {
|
|
||||||
if (visible) {
|
|
||||||
this.getPermdProtocols(row.asset.id)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
'command': protocol => {
|
|
||||||
this.$store.commit('table/SET_PROTOCOL_MAP_ITEM', {
|
|
||||||
key: row.id,
|
|
||||||
value: protocol
|
|
||||||
})
|
|
||||||
|
|
||||||
this.handleWindowOpen(row, protocol)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<el-button
|
|
||||||
plain
|
|
||||||
size='mini'
|
|
||||||
type='primary'
|
|
||||||
onClick={() => this.handlePamConnect(row)}
|
|
||||||
>
|
|
||||||
<i class='fa fa-desktop'/>
|
|
||||||
</el-button>
|
|
||||||
<el-dropdown-menu slot='dropdown'>
|
|
||||||
<el-dropdown-item command='Title' disabled>
|
|
||||||
可选协议
|
|
||||||
</el-dropdown-item>
|
|
||||||
<el-dropdown-item divided/>
|
|
||||||
{this.perm_protocols.map(protocol => {
|
|
||||||
return (
|
|
||||||
<el-dropdown-item command={protocol.name}>
|
|
||||||
{protocol.name}
|
|
||||||
</el-dropdown-item>
|
|
||||||
)
|
|
||||||
})}
|
|
||||||
</el-dropdown-menu>
|
|
||||||
</el-dropdown>
|
|
||||||
</span>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
mounted() {
|
||||||
...mapGetters(['protocolMap'])
|
|
||||||
},
|
|
||||||
async mounted() {
|
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
getAssetDetail(id) {
|
|
||||||
const detailUrl = `/api/v1/assets/assets/${id}`
|
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
this.$axios
|
|
||||||
.get(detailUrl)
|
|
||||||
.then(res => {
|
|
||||||
resolve(res)
|
|
||||||
})
|
|
||||||
.catch(err => {
|
|
||||||
reject(err)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
},
|
|
||||||
handleWindowOpen(row, protocol) {
|
|
||||||
window.open(
|
|
||||||
`/luna/pam_connect/${row.id}/${row.username}/${row.asset.id}/${
|
|
||||||
row.asset.name
|
|
||||||
}/${protocol}`,
|
|
||||||
'_blank'
|
|
||||||
)
|
|
||||||
},
|
|
||||||
async handlePamConnect(row) {
|
|
||||||
const protocolMap = this.protocolMap
|
|
||||||
|
|
||||||
if (protocolMap.has(row.id)) {
|
|
||||||
const protocol = protocolMap.get(row.id)
|
|
||||||
this.handleWindowOpen(row, protocol)
|
|
||||||
} else {
|
|
||||||
try {
|
|
||||||
const res = await this.getAssetDetail(row.asset.id)
|
|
||||||
|
|
||||||
if (res) {
|
|
||||||
const protocol = res.protocols[0]
|
|
||||||
|
|
||||||
this.$store.commit('table/SET_PROTOCOL_MAP_ITEM', {
|
|
||||||
key: row.id,
|
|
||||||
value: protocol.name
|
|
||||||
})
|
|
||||||
|
|
||||||
this.handleWindowOpen(row, protocol.name)
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
console.log(e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
async getPermdProtocols(assetId) {
|
|
||||||
try {
|
|
||||||
const res = await this.getAssetDetail(assetId)
|
|
||||||
|
|
||||||
if (res) {
|
|
||||||
this.perm_protocols = res.protocols
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
console.log(e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
@@ -208,9 +98,4 @@ export default {
|
|||||||
.asset-user-table {
|
.asset-user-table {
|
||||||
padding-left: 20px;
|
padding-left: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-dropdown-menu__item.is-disabled {
|
|
||||||
font-weight: 500;
|
|
||||||
color: var(--el-text-color-secondary);
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
@@ -60,19 +60,19 @@ export default {
|
|||||||
},
|
},
|
||||||
quickSummary: [
|
quickSummary: [
|
||||||
{
|
{
|
||||||
title: '最近一周发现',
|
title: this.$t('DateLastWeek'),
|
||||||
filter: {
|
filter: {
|
||||||
'days': '7'
|
'days': '7'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '最近一月发现',
|
title: this.$t('DateLastMonth'),
|
||||||
filter: {
|
filter: {
|
||||||
'days': '30'
|
'days': '30'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '待处理',
|
title: this.$t('Pending'),
|
||||||
filter: {
|
filter: {
|
||||||
status: '0'
|
status: '0'
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user