blob: 8c97b6a2dc5b71590fc34c7046e38811f569bae2 [file] [log] [blame]
<template>
<div>
<div class="w-100">
<h2>Manage Users</h2>
</div>
<b-container class="w-100">
<form class="userSearchBar mb-5" v-on:submit.prevent="searchResult">
<b-input-group>
<b-form-input size="sm" v-model="searchUsername" placeholder="Search"></b-form-input>
<b-input-group-append>
<b-button size="sm" type="submit">
<b-icon icon="search"></b-icon>
</b-button>
</b-input-group-append>
</b-input-group>
</form>
<div v-if="this.userloading" class="d-flex justify-content-center w-100">
<b-spinner variant="primary" label="Text Centered"></b-spinner>
</div>
<b-table striped hover responsive :items="items" :fields="fields" selectable small
ref="selectableTable"
select-mode="single"
:per-page="perPage"
:current-page="currentPage"
@row-selected="onRowSelected">
<template v-slot:cell(status)="data">
<b-badge v-if="data.value == 'ACTIVE'" variant="success">Active</b-badge>
<b-badge v-else-if="data.value == 'DEACTIVE'" variant="danger">Inactive</b-badge>
<b-badge v-else-if="data.value == 'PENDING'" variant="warning">Pending</b-badge>
</template>
</b-table>
<div>
<b-pagination
size="sm"
class="float-right"
v-model="currentPage"
:total-rows="rows"
:per-page="perPage"
aria-controls="my-table"
></b-pagination>
</div>
</b-container>
<b-modal ref="usermodel" id="user-modal" scrollable title="User Profile">
<div class="user-profile">
<div class="p-2">
<label class="form-input-label" for="form-input-username">Username</label>
<b-form-input id="form-input-username" size="sm" v-model="selectedUsername"
disabled></b-form-input>
</div>
<div class="p-2">
<label class="form-input-label" for="form-input-first-name">First Name</label>
<b-form-input id="form-input-first-name" size="sm" v-model="selectedFirstName"></b-form-input>
</div>
<div class="p-2">
<label class="form-input-label" for="form-input-last-name">Last Name</label>
<b-form-input id="form-input-last-name" size="sm" v-model="selectedLastName"></b-form-input>
</div>
<div class="p-2">
<label class="form-input-label" for="form-input-email">Email</label>
<b-form-input id="form-input-email" size="sm" v-model="selectedEmail"></b-form-input>
</div>
<div class="p-2">
<label class="form-input-label" for="form-input-email">Status</label>
<b-form-select id="form-input-status" size="sm" v-model="selectedStatus">
<option v-for="(selectOption, indexOpt) in statusOptions"
:key="indexOpt"
:value="selectOption"
>
{{ selectOption }}
</option>
</b-form-select>
</div>
<div v-if="!this.operationCompleted" class="d-flex justify-content-center mb-3">
<b-spinner variant="primary" label="Text Centered"></b-spinner>
</div>
<div class="w-100 mt-5">
<strong>Attributes</strong>
<b-button variant="link" v-on:click="addAttribute">+ Add Attributes</b-button>
<div class="w-100">
<small v-if="selectedAttributes.length === 0">There are no attributes created. </small>
</div>
<b-table small striped hover responsive :items="selectedAttributes" class="mt-2" selectable
select-mode="single"
@row-selected="onAtrSelected">
</b-table>
</div>
<div class="w-100 mt-5">
<strong>Roles</strong>
<b-button variant="link" v-on:click="addRole" :disabled="this.isAdminUser==false">+ Add Role
</b-button>
<div class="w-100">
<small v-if="selectedRoles.length === 0">There are no roles assigned. </small>
</div>
<b-table small striped hover responsive :items="selectedRoles" class="mt-2" selectable
select-mode="single"
@row-selected="onRoleSelected">
<template v-slot:head(name)>Role</template>
</b-table>
</div>
</div>
<template v-slot:modal-footer>
<b-button size="sm" class="mr-2" @click="$bvModal.hide('user-modal')">
Cancel
</b-button>
<b-button size="sm" variant="primary" v-on:click="updateUserProfile"
@click="$bvModal.hide('user-modal')">
Save
</b-button>
</template>
</b-modal>
<b-modal ref="atrModel" id="user-attribute-modal" scrollable title="Add Attribute">
<div class="userform">
<div class="p-2">
<label class="form-input-label" for="form-input-attribute-key">Key</label>
<b-form-input id="form-input-attribute-key" size="sm" v-model="newKey"></b-form-input>
</div>
<div class="p-2">
<label class="form-input-label" for="form-input-attribute-value">Value</label>
<b-form-input id="form-input-attribute-value" size="sm" v-model="newValue"></b-form-input>
</div>
</div>
<template v-slot:modal-footer>
<b-button size="sm" class="mr-2" @click="$bvModal.hide('user-attribute-modal')">
Cancel
</b-button>
<b-button :disabled="!newKey || !newValue" size="sm" variant="primary" v-on:click="addAtrOkPressed"
@click="$bvModal.hide('user-attribute-modal')">
Add
</b-button>
</template>
</b-modal>
<b-modal ref="atrModelSelected" id="user-attribute-view-modal" scrollable title="Attribute">
<div class="userform">
<div class="p-2">
<label class="form-input-label" for="form-input-attribute-key">Key</label>
<b-form-input id="form-input-attribute-key" size="sm" disabled
v-model="selectedKey"></b-form-input>
</div>
<div class="p-2">
<label class="form-input-label" for="form-input-attribute-value">Value</label>
<b-form-input id="form-input-attribute-value" size="sm" disabled
v-model="selectedValue"></b-form-input>
</div>
</div>
<template v-slot:modal-footer>
<b-button size="sm" class="mr-2" @click="$bvModal.hide('user-attribute-view-modal')">
Cancel
</b-button>
<b-button size="sm" variant="danger" v-on:click="addAtrDeletePressed"
@click="$bvModal.hide('user-attribute-view-modal')">
Delete
</b-button>
</template>
</b-modal>
<b-modal ref="roleModel" id="user-role-modal" scrollable title="Add Role">
<div class="userform">
<div class="p-2">
<label class="form-input-label" for="form-input-role-scope">Scope</label>
<b-form-select id="form-input-role-scope" size="sm" v-model="selectedScope">
<option v-for="(selectOption, indexOpt) in scopes"
:key="indexOpt"
:value="selectOption"
>
{{ selectOption }}
</option>
</b-form-select>
</div>
<div class="p-2">
<label class="form-input-label" for="form-input-role">Role</label>
<b-form-select v-if="selectedScope==='TENANT'" id="form-input-role" size="sm"
v-model="selectedRole">
<option v-for="(selectOption, indexOpt) in tenantroles"
:key="indexOpt"
:value="selectOption"
>
{{ selectOption }}
</option>
</b-form-select>
<b-form-select v-if="selectedScope==='CLIENT'" id="form-input-role" size="sm"
v-model="selectedRole">
<option v-for="(selectOption, indexOpt) in clientroles"
:key="indexOpt"
:value="selectOption"
>
{{ selectOption }}
</option>
</b-form-select>
</div>
</div>
<template v-slot:modal-footer>
<b-button size="sm" class="mr-2" @click="$bvModal.hide('user-role-modal')">
Cancel
</b-button>
<b-button :disabled="!selectedScope || !selectedRole" size="sm" variant="primary"
v-on:click="addRoleOkPressed" @click="$bvModal.hide('user-role-modal')">
Add
</b-button>
</template>
</b-modal>
<b-modal ref="roleModelSelected" id="user-role-view-modal" scrollable title="Role">
<div class="userform">
<div class="p-2">
<label class="form-input-label" for="form-input-role">Role</label>
<b-form-input id="form-input-role" size="sm" disabled v-model="rowSelectedRole"></b-form-input>
</div>
<div class="p-2">
<label class="form-input-label" for="form-input-role-scope">Scope</label>
<b-form-input id="form-input-role-scope" size="sm" disabled
v-model="rowSelectedScope"></b-form-input>
</div>
</div>
<template v-slot:modal-footer>
<b-button size="sm" class="mr-2" @click="$bvModal.hide('user-role-view-modal')">
Cancel
</b-button>
<b-button size="sm" variant="danger" v-on:click="deleteRoleOkPressed"
@click="$bvModal.hide('user-role-view-modal')">
Delete
</b-button>
</template>
</b-modal>
</div>
</template>
<script>
import config from "@/config";
export default {
name: "Users",
data: function () {
return {
fields: ['username', 'first_name', 'last_name', 'email', 'status'],
community_fields: ['id'],
items: [],
communityAccounts: [{
id: 'asdfcvrfg',
attributes: [{key: "work", vaule: 8123456789}, {key: "phone", vaule: 8123456789}],
roles: [{name: 'agentAdmin', scope: 'TENANT'}]
},
{
id: 'zxsdcfvtghy',
attributes: [{key: "work", vaule: 8123456789}, {key: "phone", vaule: 8123456789}],
roles: [{name: 'user', scope: 'TENANT'}]
}
],
statusOptions: ['ACTIVE', 'DEACTIVE'],
scopes: ['TENANT', 'CLIENT'],
tenantroles: [],
clientroles: [],
selectedItem: null,
searchUsername: null,
selectedUsername: null,
selectedFirstName: null,
selectedLastName: null,
selectedEmail: null,
selectedStatus: null,
selectedAttributes: [],
selectedRoles: [],
selectedKey: null,
selectedValue: null,
newKey: null,
newValue: null,
selectedAtr: null,
selectedRoleItem: null,
selectedRole: null,
selectedScope: null,
rowSelectedRole: null,
rowSelectedScope: null,
newScope: null,
newRole: null,
checked: false,
newAccountName: null,
exAccountId: null,
exAccount: null,
accSelectedAttributes: [],
accSelectedRoles: [],
exAccountAtr: null,
exAccountRole: null,
exAccountAtrKey: null,
exAccountAtrValue: null,
exAccountRoleKey: null,
exAccountRoleValue: null,
custosId: null,
custosSec: null,
isAdminUser: false,
perPage: 5,
currentPage: 0,
userloading: true,
operationCompleted: true,
searchUsers: true,
currentUserName: null
}
},
methods: {
onRowSelected: function (items) {
if (items != null && items.length > 0) {
this.selectedItem = items
this.selectedUsername = this.selectedItem[0].username
this.selectedFirstName = this.selectedItem[0].first_name
this.selectedLastName = this.selectedItem[0].last_name
this.selectedEmail = this.selectedItem[0].email
this.selectedStatus = this.selectedItem[0].status
this.selectedAttributes = this.selectedItem[0].attributes
this.selectedRoles = this.selectedItem[0].roles
if ((this.selectedUsername === this.currentUserName || this.isAdminUser) && this.selectedUsername != 'admin') {
this.$refs.usermodel.show()
}
}
},
clearSelected: function () {
this.$refs.selectableTable.clearSelected()
},
async searchResult() {
this.searchUsers = false
if (this.searchUsername == null || this.searchUsername == "") {
await this.loadUsers()
} else {
let data = {
offset: 0, limit: 15, client_id: this.custosId, client_sec: this.custosSec,
username: this.searchUsername
}
await this.$store.dispatch('user/users', data)
let resp = await this.$store.getters['user/getUsers']
this.items = []
if (Array.isArray(resp) && resp.length > 0) {
resp.forEach(obj => {
let user = {
username: obj.username,
first_name: obj.first_name,
last_name: obj.last_name,
email: obj.email,
status: obj.state,
attributes: [],
roles: []
}
let rr = obj.realm_roles
let cr = obj.client_roles
let attribs = obj.attributes
attribs.forEach(r => {
let newAt = {
key: r.key,
value: r.values.join(",")
}
user.attributes.push(newAt)
})
rr.forEach(r => {
let rel_role = {
name: r,
scope: 'TENANT'
}
user.roles.push(rel_role)
})
cr.forEach(r => {
let cl_role = {
name: r,
scope: 'CLIENT'
}
user.roles.push(cl_role)
})
this.items.push(user)
});
}
}
this.searchUsers = true
},
async addAttribute() {
this.$refs.atrModel.show()
},
onAtrSelected: function (items) {
if (items != null && items.length > 0) {
this.selectedAtr = items
this.selectedKey = this.selectedAtr[0].key
this.selectedValue = this.selectedAtr[0].value
this.$refs.atrModelSelected.show()
}
},
addRole: function () {
this.$refs.roleModel.show()
},
onRoleSelected: function (items) {
if (items != null && items.length > 0) {
this.selectedRoleItem = items
if (this.isAdminUser) {
this.rowSelectedScope = this.selectedRoleItem[0].scope
this.rowSelectedRole = this.selectedRoleItem[0].name
if (this.rowSelectedRole !== 'offline_access' && this.rowSelectedRole !== 'uma_authorization') {
this.$refs.roleModelSelected.show()
}
}
}
},
async addAtrOkPressed() {
this.operationCompleted = false
let accessToken = await this.$store.getters['identity/getAccessToken']
let bd = {
user_token: accessToken, body: {
attributes: [{
key: this.newKey,
values: [this.newValue]
}],
users: [this.selectedUsername]
}
}
let userAtr = await this.$store.dispatch('user/addUserAttributes', bd)
if (userAtr) {
let atr = {key: this.newKey, value: this.newValue}
this.selectedAttributes.push(atr)
}
this.operationCompleted = true
this.newKey = null
this.newValue = null
this.loadUsers()
},
async deleteAttribute(key, value) {
this.operationCompleted = false
let accessToken = await this.$store.getters['identity/getAccessToken']
let bd = {
user_token: accessToken, body: {
attributes: [{
key: key,
values: [value]
}],
users: [this.selectedUsername]
}
}
let userAtr = await this.$store.dispatch('user/deleteUserAttributes', bd)
if (userAtr) {
let newAtr = []
this.selectedAttributes.forEach(atr => {
if (atr.key != this.selectedKey) {
newAtr.push(atr)
}
this.selectedAttributes = newAtr
})
}
this.operationCompleted = true
this.selectedKey = null
this.selectedValue = null
this.loadUsers()
},
async addAtrDeletePressed() {
this.operationCompleted = false
let accessToken = await this.$store.getters['identity/getAccessToken']
let bd = {
user_token: accessToken, body: {
attributes: [{
key: this.selectedKey,
values: [this.selectedValue]
}],
users: [this.selectedUsername]
}
}
let userAtr = await this.$store.dispatch('user/deleteUserAttributes', bd)
if (userAtr) {
let newAtr = []
this.selectedAttributes.forEach(atr => {
if (atr.key != this.selectedKey) {
newAtr.push(atr)
}
this.selectedAttributes = newAtr
})
}
this.operationCompleted = true
this.selectedKey = null
this.selectedValue = null
this.loadUsers()
},
async addRoleOkPressed() {
this.operationCompleted = false
let accessToken = await this.$store.getters['identity/getAccessToken']
if (this.selectedScope === 'TENANT' && this.selectedRole === 'admin'){
let bd = {
user_token: accessToken,
body: {
username: this.selectedUsername,
}
}
await this.$store.dispatch('user/grantAdminPrivilages', bd)
let role = {name: this.selectedRole, scope: "TENANT"}
this.selectedRoles.push(role)
} else {
let bd = {
user_token: accessToken,
body: {
roles: [this.selectedRole],
usernames: [this.selectedUsername],
client_level: (this.selectedScope === 'CLIENT')
}
}
let userAtr = await this.$store.dispatch('user/addRoleToUser', bd)
if (userAtr) {
if (this.selectedScope === 'CLIENT') {
let role = {name: this.selectedRole, scope: "CLIENT"}
this.selectedRoles.push(role)
} else {
let role = {name: this.selectedRole, scope: "TENANT"}
this.selectedRoles.push(role)
}
}
}
this.operationCompleted = true
this.selectedRole = null
this.selectedScope = null
this.loadUsers()
},
async deleteRoleOkPressed() {
this.operationCompleted = false
let accessToken = await this.$store.getters['identity/getAccessToken']
let bd = {};
let deleted = false
if (this.rowSelectedScope === 'TENANT' && this.rowSelectedRole === 'admin'){
let bd = {
user_token: accessToken,
body: {
username: this.selectedUsername,
}
}
deleted = await this.$store.dispatch('user/removeAdminPrivilages', bd)
} else {
if (this.rowSelectedScope === 'TENANT') {
bd = {
user_token: accessToken,
body: {
roles: [this.rowSelectedRole],
username: this.selectedUsername
}
}
} else {
bd = {
user_token: accessToken,
body: {
client_roles: [this.rowSelectedRole],
username: this.selectedUsername
}
}
}
deleted = await this.$store.dispatch('user/deleteRoleFromUser', bd)
}
if (deleted) {
let newRoles = []
this.selectedRoles.forEach(atr => {
if (atr.name != this.rowSelectedRole) {
newRoles.push(atr)
}
})
this.selectedRoles = newRoles
}
this.operationCompleted = true
this.loadUsers()
},
async loadUsers() {
let data = {offset: 0, limit: 5, client_id: this.custosId, client_sec: this.custosSec}
let resp = await this.$store.dispatch('user/users', data)
this.userloading = false
this.items = []
let newUsersCount = this.parseUsers(this.items, resp)
if (newUsersCount == 5) {
let offset = 5
while (newUsersCount >= 5) {
newUsersCount = await this.loadUsersR(offset, this.items)
offset = offset + 5
}
}
},
async loadUsersR(offset, items) {
let data = {offset: offset, limit: 5, client_id: this.custosId, client_sec: this.custosSec}
let resp = await this.$store.dispatch('user/users', data)
return this.parseUsers(items, resp)
},
async goToWorkspace() {
await this.$router.push('/workspace')
},
parseUsers(items, resp) {
if (Array.isArray(resp) && resp.length > 0) {
resp.forEach(obj => {
let user = {
username: obj.username,
first_name: obj.first_name,
last_name: obj.last_name,
email: obj.email,
status: (obj.state == 'ACTIVE') ? obj.state : 'DEACTIVE',
attributes: [],
roles: []
}
let rr = obj.realm_roles
let cr = obj.client_roles
let attribs = obj.attributes
attribs.forEach(r => {
let newAt = {
key: r.key,
value: r.values.join(",")
}
user.attributes.push(newAt)
})
rr.forEach(r => {
let rel_role = {
name: r,
scope: 'TENANT'
}
user.roles.push(rel_role)
})
cr.forEach(r => {
let cl_role = {
name: r,
scope: 'CLIENT'
}
user.roles.push(cl_role)
})
items.push(user)
});
}
return resp.length
},
async updateUserProfile() {
this.operationCompleted = false
let params = {client_id: this.custosId, client_sec: this.custosSec, username: this.selectedUsername}
if (this.selectedStatus === 'ACTIVE') {
await this.$store.dispatch('user/enableUser', params)
} else {
await this.$store.dispatch('user/disableUser', params)
}
let data = {
client_id: this.custosId,
client_sec: this.custosSec,
body: {
username: this.selectedUsername,
first_name: this.selectedFirstName,
last_name: this.selectedLastName,
email: this.selectedEmail
}
}
await this.$store.dispatch('user/updateUserProfile', data)
this.operationCompleted = true
this.loadUsers()
},
}
,
async mounted() {
this.custosId = config.value('clientId')
this.custosSec = config.value('clientSec')
this.tenantModeactivated = await this.$store.dispatch('tenant/isTenantModeActivated')
if (this.tenantModeactivated) {
this.custosId = await this.$store.dispatch('tenant/getActivatedClientId')
this.custosSec = await this.$store.dispatch('tenant/getActivatedClientSecret');
} else {
await this.$router.push({name:'tenants'})
}
this.isAdminUser = await this.$store.dispatch('identity/isLoggedUserHasAdminAccess')
this.currentUserName = await this.$store.dispatch('identity/getCurrentUserName')
await this.loadUsers()
let params = {client_id: this.custosId, client_sec: this.custosSec}
this.tenantroles = await this.$store.dispatch('user/getTenantLevelRoles', params)
this.clientroles = await this.$store.dispatch('user/getClientLevelRoles', params)
}
,
computed: {
rows() {
return this.items.length
}
}
}
</script>
<style scoped>
h2 {
font-family: Avenir;
font-size: 20px;
font-weight: 600;
text-align: left;
color: #203a43;
}
.userSearchBar {
border-radius: 5px;
border: solid 1px #afafae;
width: 300px;
float: right;
}
.userSearchBar .form-control {
border: none;
}
.userSearchBar input.form-control:focus {
outline: none;
box-shadow: none;
}
.userSearchBar button {
background: none;
color: black;
border: none;
}
</style>