mirror of
https://github.com/jumpserver/lina.git
synced 2025-09-13 21:59:14 +00:00
@@ -792,6 +792,9 @@
|
||||
"OrgUser": "组织用户",
|
||||
"OrgAdmin": "组织管理员",
|
||||
"OrgAuditor": "组织审计员",
|
||||
"InviteUser": "邀请用户",
|
||||
"Invite": "邀请",
|
||||
"InviteUserInOrg": "邀请用户加入此组织",
|
||||
"Guide": "向导",
|
||||
"HelpText": {
|
||||
"MFAOfUserFirstLoginPersonalInformationImprovementPage": "启用多因子认证,使账号更加安全。<br/> 启用之后您将会在下次登录时进入多因子认证绑定流程;您也可以在(个人信息->快速修改->更改多因子设置)中直接绑定!",
|
||||
|
@@ -787,10 +787,14 @@
|
||||
"Email": "Email",
|
||||
"FingerPrint": "Fingerprint",
|
||||
"FirstLogin": "First login",
|
||||
"InviteUser": "Invite user",
|
||||
"InviteUserInOrg": "Invite user in this org",
|
||||
"Invite": "Invite",
|
||||
"Guide": "Guide",
|
||||
"OrgUser": "Org User",
|
||||
"OrgAdmin": "Org Admin",
|
||||
"OrgAuditor": "Org Auditor",
|
||||
|
||||
"HelpText": {
|
||||
"MFAOfUserFirstLoginPersonalInformationImprovementPage": "Enable multi-factor authentication to make the account more secure <br/> After is enabled, you will enter the multi-factor authentication binding process on your next login <br/> You can also bind directly in (personal information -> fast modifier -> modifier multiple factor Settings)",
|
||||
"MFAOfUserFirstLoginUserGuidePage": "To protect the security of you and the company <br/> please properly keep your account, password, key and other important and sensitive information <br/> (e.g., set a complex password and enable multi-factor authentication)",
|
||||
|
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<Page v-bind="$attrs">
|
||||
<ListTable v-bind="$attrs" />
|
||||
<ListTable ref="ListTable" v-bind="$attrs" />
|
||||
</Page>
|
||||
</template>
|
||||
|
||||
|
@@ -1,11 +1,16 @@
|
||||
<template>
|
||||
<div>
|
||||
<GenericListPage :table-config="tableConfig" :header-actions="headerActions" />
|
||||
<GenericListPage
|
||||
ref="GenericListPage"
|
||||
:table-config="tableConfig"
|
||||
:header-actions="headerActions"
|
||||
/>
|
||||
<GenericUpdateFormDialog
|
||||
:selected-rows="updateSelectedDialogSetting.selectedRows"
|
||||
:form-setting="updateSelectedDialogSetting.formSetting"
|
||||
:dialog-setting="updateSelectedDialogSetting.dialogSetting"
|
||||
/>
|
||||
<InviteUsersDialog :setting="InviteDialogSetting" @close="handleInviteDialogClose" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -15,9 +20,11 @@ import { GenericListPage } from '@/layout/components'
|
||||
import { GenericUpdateFormDialog } from '@/layout/components'
|
||||
import { createSourceIdCache } from '@/api/common'
|
||||
import { getDayFuture } from '@/utils/common'
|
||||
import InviteUsersDialog from '@/views/users/User/components/InviteUsersDialog'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
InviteUsersDialog,
|
||||
GenericListPage,
|
||||
GenericUpdateFormDialog
|
||||
},
|
||||
@@ -27,7 +34,13 @@ export default {
|
||||
tableConfig: {
|
||||
url: '/api/v1/users/users/',
|
||||
columns: [
|
||||
'name', 'username', 'groups_display', 'total_role_display', 'source', 'is_valid', 'actions'
|
||||
'name',
|
||||
'username',
|
||||
'groups_display',
|
||||
'total_role_display',
|
||||
'source',
|
||||
'is_valid',
|
||||
'actions'
|
||||
],
|
||||
columnsMeta: {
|
||||
username: {
|
||||
@@ -70,6 +83,17 @@ export default {
|
||||
},
|
||||
headerActions: {
|
||||
hasBulkDelete: false,
|
||||
extraActions: [
|
||||
{
|
||||
name: this.$t('users.InviteUser'),
|
||||
title: this.$t('users.InviteUser'),
|
||||
can:
|
||||
(JSON.parse(this.$cookie.get('jms_current_org'))
|
||||
? JSON.parse(this.$cookie.get('jms_current_org')).id
|
||||
: '') !== 'DEFAULT',
|
||||
callback: function() { this.InviteDialogSetting.InviteDialogVisible = true }.bind(this)
|
||||
}
|
||||
],
|
||||
extraMoreActions: [
|
||||
{
|
||||
title: this.$t('common.deleteSelected'),
|
||||
@@ -135,9 +159,7 @@ export default {
|
||||
initial: {
|
||||
date_expired: getDayFuture(36500, new Date()).toISOString()
|
||||
},
|
||||
fields: [
|
||||
'groups', 'date_expired', 'comment'
|
||||
],
|
||||
fields: ['groups', 'date_expired', 'comment'],
|
||||
url: '/api/v1/users/users/',
|
||||
fieldsMeta: {
|
||||
groups: {
|
||||
@@ -154,36 +176,36 @@ export default {
|
||||
date_expired: {
|
||||
label: this.$t('common.dateExpired'),
|
||||
hidden: () => false
|
||||
|
||||
},
|
||||
comment: {
|
||||
label: this.$t('common.Comment'),
|
||||
hidden: () => false
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
InviteDialogSetting: {
|
||||
InviteDialogVisible: false
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters([
|
||||
'currentOrg',
|
||||
'currentUser',
|
||||
'device'
|
||||
]),
|
||||
...mapGetters(['currentOrg', 'currentUser', 'device']),
|
||||
currentOrgIsDefault() {
|
||||
return this.currentOrg.id === 'DEFAULT' || this.currentOrg.id === ''
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
if (!this.currentOrgIsDefault) {
|
||||
this.headerActions.extraMoreActions[0].title = this.$t('common.removeSelected')
|
||||
this.headerActions.extraMoreActions[0].title = this.$t(
|
||||
'common.removeSelected'
|
||||
)
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
removeUserFromOrg({ row, col, reload }) {
|
||||
const msg = this.$t('users.removeFromOrgWarningMsg') + ' "' + row.name + '"'
|
||||
const msg =
|
||||
this.$t('users.removeFromOrgWarningMsg') + ' "' + row.name + '"'
|
||||
const title = this.$t('common.Info')
|
||||
const performDelete = function() {
|
||||
const url = `/api/v1/users/users/${row.id}/`
|
||||
@@ -214,7 +236,13 @@ export default {
|
||||
if (!this.currentOrgIsDefault) {
|
||||
msgPrefix = this.$t('common.removeWarningMsg')
|
||||
}
|
||||
const msg = msgPrefix + ' ' + selectedRows.length + ' ' + this.$t('common.rows') + ' ?'
|
||||
const msg =
|
||||
msgPrefix +
|
||||
' ' +
|
||||
selectedRows.length +
|
||||
' ' +
|
||||
this.$t('common.rows') +
|
||||
' ?'
|
||||
const title = this.$t('common.Info')
|
||||
const performDelete = this.performBulkDelete
|
||||
this.$alert(msg, title, {
|
||||
@@ -248,17 +276,30 @@ export default {
|
||||
})
|
||||
},
|
||||
async performBulkDelete(selectedRows) {
|
||||
const ids = selectedRows.map((v) => {
|
||||
const ids = selectedRows.map(v => {
|
||||
return v.id
|
||||
})
|
||||
const data = await createSourceIdCache(ids)
|
||||
const url = `${this.tableConfig.url}?spm=` + data.spm
|
||||
return this.$axios.delete(url)
|
||||
},
|
||||
handleInviteDialogClose() {
|
||||
this.InviteDialogSetting.InviteDialogVisible = false
|
||||
this.$refs.GenericListPage.$refs.ListTable.reloadTable()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.asset-select-dialog ::v-deep .transition-box:first-child {
|
||||
background-color: #f3f3f3;
|
||||
}
|
||||
.dialog ::v-deep .el-input {
|
||||
width: 25.5vw;
|
||||
}
|
||||
|
||||
.dialog ::v-deep .el-dialog__footer {
|
||||
padding: 0;
|
||||
}
|
||||
</style>
|
||||
|
154
src/views/users/User/components/InviteUsersDialog.vue
Normal file
154
src/views/users/User/components/InviteUsersDialog.vue
Normal file
@@ -0,0 +1,154 @@
|
||||
<template>
|
||||
<Dialog
|
||||
v-if="setting.InviteDialogVisible"
|
||||
:title="this.$t('users.InviteUserInOrg')"
|
||||
:visible.sync="setting.InviteDialogVisible"
|
||||
custom-class="asset-select-dialog"
|
||||
:show-cancel="false"
|
||||
:show-confirm="false"
|
||||
width="28%"
|
||||
top="15vh"
|
||||
after
|
||||
:destroy-on-close="true"
|
||||
@close="clearSelect"
|
||||
>
|
||||
<div>
|
||||
<el-select
|
||||
v-model="InviteValue"
|
||||
multiple
|
||||
filterable
|
||||
remote
|
||||
size="small"
|
||||
reserve-keyword
|
||||
:placeholder="this.$t('setting.usernamePlaceholder')"
|
||||
:remote-method="remoteMethod"
|
||||
:loading="selectLoading"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in InviteOptions"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
<el-collapse-transition>
|
||||
<div
|
||||
v-if="InviteValue.length > 0"
|
||||
style="margin-top:15px;
|
||||
display: flex;
|
||||
flex-direction:column;
|
||||
align-items:center;
|
||||
justify-content:center;"
|
||||
>
|
||||
<el-checkbox-group
|
||||
v-model="rulesList"
|
||||
size="small"
|
||||
style="display: flex;
|
||||
flex-direction:row;
|
||||
justify-content:center;"
|
||||
>
|
||||
<el-checkbox label="User" checked>{{ $t('users.OrgUser') }}</el-checkbox>
|
||||
<el-checkbox label="Auditor">{{ $t('users.OrgAuditor') }}</el-checkbox>
|
||||
<el-checkbox label="Admin">{{ $t('users.OrgAdmin') }}</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
|
||||
<el-button
|
||||
type="primary"
|
||||
:loading="InviteLoading"
|
||||
size="small"
|
||||
style="margin-top: 20px;width: 10vw"
|
||||
@click="InviteConfirm"
|
||||
>{{ $t('users.Invite') }}</el-button>
|
||||
</div>
|
||||
</el-collapse-transition>
|
||||
</div>
|
||||
</Dialog>
|
||||
</template>
|
||||
<script>
|
||||
import Dialog from '@/components/Dialog'
|
||||
import { mapGetters } from 'vuex'
|
||||
export default {
|
||||
components: {
|
||||
Dialog
|
||||
},
|
||||
props: {
|
||||
setting: {
|
||||
type: Object,
|
||||
default: () => {
|
||||
return { InviteDialogVisible: false }
|
||||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
selectLoading: false,
|
||||
InviteLoading: false,
|
||||
InviteOptions: [],
|
||||
InviteValue: [],
|
||||
rulesList: []
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['currentOrg', 'currentUser', 'device'])
|
||||
},
|
||||
methods: {
|
||||
remoteMethod(query) {
|
||||
if (query !== '') {
|
||||
this.InviteOptions = []
|
||||
this.selectLoading = true
|
||||
this.$axios
|
||||
.get(` /api/v1/users/users/?search=${query}&all=1`)
|
||||
.then(result => {
|
||||
console.log(result)
|
||||
for (let i = 0; i < result.length; i++) {
|
||||
this.InviteOptions.push({
|
||||
value: result[i].id,
|
||||
label: result[i].name + '(' + result[i].username + ')'
|
||||
})
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
this.selectLoading = false
|
||||
})
|
||||
} else {
|
||||
this.InviteOptions = []
|
||||
}
|
||||
},
|
||||
clearSelect() {
|
||||
this.InviteValue = []
|
||||
this.rulesList = []
|
||||
this.InviteOptions = []
|
||||
},
|
||||
InviteConfirm() {
|
||||
this.InviteLoading = true
|
||||
const data = []
|
||||
for (const rule of this.rulesList) {
|
||||
for (const user of this.InviteValue) {
|
||||
data.push({
|
||||
org: this.currentOrg.id,
|
||||
user: user,
|
||||
role: rule
|
||||
})
|
||||
}
|
||||
}
|
||||
this.$axios.post(`/api/v1/orgs/org-memeber-relation/?org_id=${this.currentOrg.id}&ignore_already_exist=1`, data).then(() => {
|
||||
this.$message.success(this.$t('common.AddSuccessMsg'))
|
||||
}).finally(() => {
|
||||
this.InviteLoading = false
|
||||
this.clearSelect()
|
||||
this.$emit('close')
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.dialog ::v-deep .el-input {
|
||||
width: 25.5vw;
|
||||
}
|
||||
|
||||
.dialog ::v-deep .el-dialog__footer {
|
||||
padding: 0;
|
||||
}
|
||||
</style>
|
Reference in New Issue
Block a user