Commit fae1baf6 authored by Janis Streib's avatar Janis Streib 🦉
Browse files

UPD: new oe views and integrations (with @gj4210) #185)

parent a90dea29
Pipeline #152830 failed with stages
in 4 minutes and 47 seconds
import TransactionService from './transaction.service'
export default {
getOU(config, ou) {
const ta = [
{ name: 'org.unit.list', old: { do_subtree: true, short_name: ou } },
{ name: 'cntl.mgr2ou.list', join: { 0: 'api_fkey_cntl_mgr2ou_ou' } },
{ name: 'cntl.mgr.list', join: { 1: 'api_fkey_cntl_mgr2ou_mgr' } },
{ name: 'dns.fqdn2ou.list', join: { 0: 'api_fkey_dns_fqdn2ou_ou' } },
{ name: 'nd.bcd.list', join: { 0: 'api_fkey_nd_bcd_ou' } }
]
return TransactionService.execute(config, ta)
},
listOwn(config) {
const ta = [
{ name: 'cntl.mgr2ou.list', old: { is_own: true } },
......@@ -8,7 +18,8 @@ export default {
{ name: 'cntl.mgr2ou.list', join: { 1: 'api_fkey_cntl_mgr2ou_ou' } },
{ name: 'cntl.mgr.list', join: { 2: 'api_fkey_cntl_mgr2ou_mgr' } },
{ name: 'dns.fqdn2ou.list', join: { 1: 'api_fkey_dns_fqdn2ou_ou' } },
{ name: 'nd.bcd.list', join: { 1: 'api_fkey_nd_bcd_ou' } }
{ name: 'nd.bcd.list', join: { 1: 'api_fkey_nd_bcd_ou' } },
{ name: 'org.unit.list', join: { 0: 'api_fkey_cntl_mgr2ou_ou' }}
]
return TransactionService.execute(config, ta)
},
......
......@@ -23,6 +23,32 @@ export default {
]
return TransactionService.execute(config, ta)
},
searchOURegex(config, term, own) {
const ta = [
{
name: 'org.unit.list',
old: apiutil.denullify_dict({
name_regexp: checkRegex(term),
fetch_limit: 20,
sorting_params_list: ['short_name']
})
}
]
return TransactionService.execute(config, ta)
},
searchOUDirect(config, term) {
const ta = [
{
name: 'org.unit.list',
old: apiutil.denullify_dict({
short_name: term.toUpperCase(),
fetch_limit: 20,
sorting_params_list: ['short_name']
})
}
]
return TransactionService.execute(config, ta)
},
searchRecordRegex(config, term, own) {
const ta = [
{
......
......@@ -39,9 +39,9 @@
</div>
</template>
<template v-slot:cell(ou_short_name)="data">
<span :title="ous_by_short_name[data.item.ou_short_name].name" class="nowrap">{{
data.item.ou_short_name
}}</span>
<b-link :to="'/cntl/ou/'+data.item.ou_short_name"><span :title="ous_by_short_name[data.item.ou_short_name].name" class="nowrap">
{{data.item.ou_short_name}}
</span></b-link>
</template>
<template v-slot:cell(vlans)="data">
<ul>
......
......@@ -281,6 +281,35 @@ export default {
}
}
break
case 'org.unit':
compiled_term = item.term.name + ' (' + item.term.short_name + ')'
if (isRegex) {
suggestions.push({
name:
['',
compiled_term,
''
],
type: item.type,
url: '/cntl/ou/' + item.term.short_name
})
} else {
index = compiled_term.toLowerCase().indexOf(search.toLowerCase())
if (index !== -1) {
suggestions.push({
name:
[compiled_term.substring(0, index),
compiled_term
.substring(index, index + search.length),
compiled_term
.substring(index + search.length)
],
type: item.type,
url: '/cntl/ou/' + item.term.short_name
})
}
}
break
}
})
return suggestions
......@@ -300,6 +329,9 @@ export default {
if (type.startsWith('nd.')) {
return 'network-wired'
}
if (type.startsWith('org.')) {
return 'building'
}
return 'questions'
},
checkSearch() {
......@@ -385,6 +417,8 @@ export default {
} else {
this.dispatch_search(SearchService.searchBCDRegex(this.$store.state.netdb_axios_config, term, true), 'nd.bcd')
this.dispatch_search(SearchService.searchRecordRegex(this.$store.state.netdb_axios_config, term, true), 'dns.record')
this.dispatch_search(SearchService.searchOURegex(this.$store.state.netdb_axios_config, term, true), 'org.unit')
this.dispatch_search(SearchService.searchOUDirect(this.$store.state.netdb_axios_config, term), 'org.unit')
}
} else if (this.descriminator === 'dnsvs') {
if (termIsNumeric) {
......@@ -397,9 +431,12 @@ export default {
this.dispatch_search(SearchService.searchRecordRegex(this.$store.state.netdb_axios_config, term, null), 'dns.record')
this.dispatch_search(SearchService.searchRRDataRegex(this.$store.state.netdb_axios_config, term, null), 'dns.record')
}
} else if (this.descriminator === 'org') {
this.dispatch_search(SearchService.searchOURegex(this.$store.state.netdb_axios_config, term, true), 'org.unit')
this.dispatch_search(SearchService.searchOUDirect(this.$store.state.netdb_axios_config, term), 'org.unit')
}
this.descriminator = null
}
this.descriminator = null
}
},
suggestionClicked(e, suggestion) {
......
import Vue from 'vue'
import Router from 'vue-router'
// import OUService from '@/api-services.gen/org.unit'
Vue.use(Router)
export default new Router({
......@@ -37,6 +39,20 @@ export default new Router({
}
}
},
{
path: '/cntl/ou/:ou',
name: 'ou',
component: () => import('./views/cntl/OU'),
meta: {
resolveName: function (query) {
return query.ou.toUpperCase()
},
resolveParents: function (query) {
// const res = OUService.list(Vue.$store.state.netdb_axios_config, {do_rootpath: true, short_name: query.ou})
return ['/cntl/ou']
}
}
},
{
path: '/cntl/groups',
name: 'groups',
......@@ -171,7 +187,6 @@ export default new Router({
},
resolveParents (query) {
const domains = query.fqdn.split('.').reverse()
window.console.log(domains)
const res = ['/dnsvs/fqdns']
let buf = ''
for (let i = 0; i < domains.length - 1; i++) {
......@@ -185,7 +200,6 @@ export default new Router({
}
res.unshift({ text: (rbuf === '$') ? '.' : rbuf, to: '/dnsvs/fqdns/' + rbuf })
}
window.console.log(res)
return res
}
}
......
<template>
<div class="ou-overview">
<h1 v-if="is_entry">Organisationseinheiten</h1>
<h1 v-else>{{ou.name}} <small class="text-muted">Organisationseinheit</small></h1>
<b-checkbox v-if="is_entry" :value="true" :unchecked-value="false" v-model="only_own_ou" switch>Nur eigene Organisationseinheiten
anzeigen
</b-checkbox>
<template v-if="is_entry">
<h1>Organisationseinheiten</h1>
<b-checkbox :value="true" :unchecked-value="false" v-model="only_own_ou" switch>Nur eigene
Organisationseinheiten
anzeigen
</b-checkbox>
</template>
<template v-else>
<Loading :data="[ou, mgrs_by_login_name]">
<b-row>
<b-col>
<h1>{{ ou.name }} ({{ ou.short_name }}) <small class="text-muted">Organisationseinheit</small></h1>
</b-col>
<b-col lg="2">
<b-button-group class="d-flex">
<b-button variant="outline-secondary" :id="'show-evlog-ou-' + ou.short_name"
@click="show_ev_log(ou)" class="mt-3 shadow">
<font-awesome-icon icon="history"></font-awesome-icon>
Eventlog
</b-button>
<b-tooltip :target="'show-evlog-ou-' + ou.short_name" triggers="hover"
variant="secondary" placement="bottom">
Eventlog
</b-tooltip>
</b-button-group>
</b-col>
</b-row>
<b-card header-class="p-0" body-class="p-0" class="mb-3 shadow-sm">
<template v-slot:header>
<b-button block variant="outline-secondary" v-b-toggle="ou.short_name + '-collapse'">
OE-Betreuer
<b-badge pill v-if="mgrs2ou[ou.short_name]">{{
mgrs2ou[ou.short_name].length
}}
</b-badge>
<b-badge pill v-else>0</b-badge>
<br/>
<font-awesome-icon class="collapse-icon" :icon="['fas','chevron-down']"/>
</b-button>
</template>
<b-collapse :id="ou.short_name + '-collapse'">
<b-pagination :per-page="per_page" v-model="mgrs_list_page"
v-if="mgrs2ou[ou.short_name] && mgrs2ou[ou.short_name].length> per_page"
:total-rows="mgrs2ou[ou.short_name].length || 0" align="center" class="mt-3"/>
<b-table :items="mgrs2ou[ou.short_name]" :fields="ou_list_fields" class="m-0" per-page="25">
<template v-slot:cell(first_name)="data">
{{ mgrs_by_login_name[data.item.mgr_login_name].first_name }}
</template>
<template v-slot:cell(last_name)="data">
{{ mgrs_by_login_name[data.item.mgr_login_name].last_name }}
</template>
<template v-slot:cell(email)="data">
<b-link :href="'mailto:'+mgrs_by_login_name[data.item.mgr_login_name].email">
{{ mgrs_by_login_name[data.item.mgr_login_name].email }}
</b-link>
</template>
<template v-slot:head(actions)>
<b-button @click="create_mgr_assignment(ou.short_name)" block variant="outline-success"
:id="'button-assign-mgr-' + ou.short_name">
<font-awesome-icon :icon="['fas', 'plus']"/>
</b-button>
<b-tooltip :target="'button-assign-mgr-' + ou.short_name" triggers="hover"
variant="success" placement="left">
Neuen Account zuordnen
</b-tooltip>
</template>
<template v-slot:cell(actions)="data">
<b-button-group class="d-flex">
<b-button @click="delete_mgr_assignment(data.item)" variant="outline-danger"
:id="'button-unassign-mgr-' + data.item.bcd_name">
<font-awesome-icon :icon="['fas', 'unlink']"></font-awesome-icon>
</b-button>
<b-tooltip :target="'button-unassign-mgr-' + data.item.bcd_name" triggers="hover"
variant="danger" placement="left">
Zuweisung aufheben
</b-tooltip>
</b-button-group>
</template>
</b-table>
<div v-if="!mgrs2ou[ou.short_name] || mgrs2ou[ou.short_name].length === 0"
class="font-italic text-center my-3">
<span class="font-italic">Keine Domains zugewiesen</span><br/>
</div>
</b-collapse>
</b-card>
<b-card header-class="p-0" body-class="p-0" class="mb-3 shadow-sm">
<template v-slot:header>
<b-button block variant="outline-secondary"
v-b-toggle="ou.short_name + '-collapse-domains'">
Domains
<b-badge pill v-if="fqdns2ou[ou.short_name]">{{
fqdns2ou[ou.short_name].length
}}
</b-badge>
<b-badge pill v-else>0</b-badge>
<br/>
<font-awesome-icon class="collapse-icon" :icon="['fas','chevron-down']"/>
</b-button>
</template>
<b-collapse :id="ou.short_name + '-collapse-domains'">
<b-pagination :per-page="per_page" v-model="fqdn_list_page"
v-if="fqdns2ou[ou.short_name] && fqdns2ou[ou.short_name].length> per_page"
:total-rows="fqdns2ou[ou.short_name].length || 0" align="center" class="mt-3"/>
<b-table :items="fqdns2ou[ou.short_name]" :fields="fqdn_list_fields" class="m-0" per-page="25">
<template v-slot:head(actions)>
<b-button block variant="outline-success"
:id="'button-assign-fqdn-' + ou.short_name"
@click="create_fqdn_assignment(ou.short_name)">
<font-awesome-icon :icon="['fas', 'plus']"/>
</b-button>
<b-tooltip :target="'button-assign-fqdn-' + ou.short_name" triggers="hover"
variant="success" placement="left">
Neue Domain zuordnen
</b-tooltip>
</template>
<template v-slot:cell(actions)="data">
<b-button-group class="d-flex">
<b-button @click="delete_fqdn_assignment(data.item)" variant="outline-danger"
:id="'button-unassign-fqdn-' + data.item.fqdn_value">
<font-awesome-icon :icon="['fas', 'unlink']"></font-awesome-icon>
</b-button>
<b-tooltip :target="'button-unassign-fqdn-' + data.item.fqdn_value" triggers="hover"
variant="danger" placement="bottom">
Zuweisung aufheben
</b-tooltip>
</b-button-group>
</template>
</b-table>
<div v-if="!fqdns2ou[ou.short_name] || fqdns2ou[ou.short_name].length === 0"
class="font-italic text-center my-3">
<span class="font-italic">Keine Domains zugewiesen</span><br/>
</div>
</b-collapse>
</b-card>
<b-card header-class="p-0" body-class="p-0" class="shadow-sm">
<template v-slot:header>
<b-button block variant="outline-secondary"
v-b-toggle="ou.short_name + '-collapse-bcds'">
Broadcastdomains (BCDs)
<b-badge pill v-if="bcds2ou[ou.short_name]">{{
bcds2ou[ou.short_name].length
}}
</b-badge>
<b-badge pill v-else>0</b-badge>
<br/>
<font-awesome-icon class="collapse-icon" :icon="['fas','chevron-down']"/>
</b-button>
</template>
<b-collapse :id="ou.short_name + '-collapse-bcds'">
<b-pagination :per-page="per_page" v-model="bcd_list_page"
v-if="bcds2ou[ou.short_name] && bcds2ou[ou.short_name].length> per_page"
:total-rows="bcds2ou[ou.short_name].length || 0" align="center" class="mt-3"/>
<b-table :items="bcds2ou[ou.short_name]" :fields="bcd_list_fields" class="m-0" :per-page="per_page"
:current-page="bcd_list_page">
<template v-slot:cell(name)="item">
<b-link :to="'/dnsvs/bcds/' + item.item.name">{{ item.item.name }}</b-link>
</template>
</b-table>
<div v-if="!bcds2ou[ou.short_name] || bcds2ou[ou.short_name].length === 0"
class="font-italic text-center my-3">
<span class="font-italic">Keine BDCs zugewiesen</span><br/>
</div>
</b-collapse>
</b-card>
</Loading>
</template>
<hr>
<h2 v-if="!is_entry">Untergeordnete Organisationseinheiten</h2>
<Loading :data="[ous, mgrs]">
<Paginator :items="ous" items_per_page="15" no_items_text="Keine Organisationseinheiten vorhanden">
<template v-slot:item="card_data">
<OUCard :create_fqdn_assignment="create_fqdn_assignment"
:create_mgr_assignment="create_mgr_assignment"
:delete_fqdn_assignment="delete_fqdn_assignment"
:delete_mgr_assignment="delete_mgr_assignment"
:ou="card_data.item"
:mgrs_by_login_name="mgrs"
:ou_mgrs="mgrs2ou[card_data.item.short_name] || []"
:ou_fqdns="fqdns2ou[card_data.item.short_name] || []"
:ou_bcds="bcds2ou[card_data.item.short_name] || []"
:show_ev_log="show_ev_log"
>
</OUCard>
<Loading :data="[ous, ous_by_parent]">
<template v-if="ous_by_parent">
<template v-if="ou">
<div v-for="top_level_ou in ous_by_parent[ou.short_name]" :key="top_level_ou.short_name">
<OUTreeEntry :ou="top_level_ou" :ous_by_parent="ous_by_parent"/>
</div>
</template>
<template v-else>
<div v-for="top_level_ou in root_ous" :key="top_level_ou.short_name">
<OUTreeEntry :ou="top_level_ou" :ous_by_parent="ous_by_parent"/>
</div>
</template>
</Paginator>
</template>
</Loading>
<DBEditor modal_id="assign_user_to_oe" object_function="create" object_fq_name="cntl.mgr2ou"
:presets="db_editor_presets"
......@@ -41,34 +202,96 @@
<script>
import OUService from '@/api-services/ou.service'
import NativeOUService from '@/api-services.gen/org.unit'
import apiutil from '@/util/apiutil'
import transactionutil from '@/util/transactionutil'
import Mgr2OuService from '@/api-services.gen/cntl.mgr2ou'
import FQDN2OuService from '@/api-services.gen/dns.fqdn2ou'
import OUCard from '@/components/OUCard'
import Paginator from '@/components/Paginator'
import Loading from '@/components/Loading'
import DBEditor from '@/components/DBEditor'
import EVLogViewer from '@/components/EVLogViewer'
import OUTreeEntry from '@/components/OUTreeEntry'
import {EventBus} from '@/eventbus'
export default {
name: 'OUOverview',
components: {EVLogViewer, DBEditor, Loading, Paginator, OUCard},
components: {OUTreeEntry, EVLogViewer, DBEditor, Loading},
data() {
return {
ou: {name: 'Foo Bar'}, // dummy var, contains current ou (if not is_entry)
is_entry: true, // dummy var
root_ous: null,
ou: null,
evlog_ou: null,
only_own_ou: true,
mgrs2ou: null,
bcds2ou: null,
fqdns2ou: null,
mgrs: null,
mgrs_by_login_name: null,
ous: null,
db_editor_presets: {}
ous_by_name: null,
ous_by_parent: null,
db_editor_presets: {},
bcd_list_fields: [
{
key: 'name',
label: 'BCD',
sortable: true
},
{
key: 'description',
label: 'Beschreibung',
sortable: true
}
],
fqdn_list_fields: [
{
key: 'fqdn_value',
label: 'FQDN',
sortable: true
},
{
key: 'actions',
label: 'Aktionen',
sortable: false
}
],
ou_list_fields: [
{
key: 'mgr_login_name',
label: 'Login Name',
sortable: false
},
{
key: 'first_name',
label: 'Vorname',
sortable: false
},
{
key: 'last_name',
label: 'Nachname',
sortable: false
},
{
key: 'email',
label: 'E-Mail',
sortable: false
},
{
key: 'actions',
label: 'Aktionen',
sortable: false
}
],
mgrs_list_page: 0,
fqdn_list_page: 0,
bcd_list_page: 0,
per_page: 50
}
},
watch: {
$route() {
this.ou = this.ous = null
this.refresh()
},
only_own_ou: {
immediate: true,
async handler() {
......@@ -76,25 +299,63 @@ export default {
}
}
},
computed: {
is_entry() {
return this.ou === null
}
},
methods: {
async refresh() {
let ou_name_req = this.$route.params.ou || null
this.mgrs = this.mgrs2ou = this.ous = null
let res = null
if (this.only_own_ou) {
res = (await OUService.listOwn(this.$store.state.netdb_axios_config)).data
this.mgrs2ou = apiutil.dict_of_lists_by_value_of_array(res[2], 'ou_short_name')
this.fqdns2ou = apiutil.dict_of_lists_by_value_of_array(res[4], 'ou_short_name')
this.bcds2ou = apiutil.dict_of_lists_by_value_of_array(res[5], 'ou_short_name')
this.mgrs = apiutil.dict_by_value_of_array(res[3], 'login_name')
this.ous = res[1]
} else {
res = (await OUService.listAll(this.$store.state.netdb_axios_config)).data
if (ou_name_req) {
EventBus.$emit('overwrite_breadcrumbs', function () {
return ['/cntl/ou']
})
ou_name_req = ou_name_req.toUpperCase()
res = (await OUService.getOU(this.$store.state.netdb_axios_config, ou_name_req)).data
this.mgrs2ou = apiutil.dict_of_lists_by_value_of_array(res[1], 'ou_short_name')
this.mgrs = apiutil.dict_by_value_of_array(res[2], 'login_name')
this.mgrs_by_login_name = apiutil.dict_by_value_of_array(res[2], 'login_name')
this.fqdns2ou = apiutil.dict_of_lists_by_value_of_array(res[3], 'ou_short_name')
this.bcds2ou = apiutil.dict_of_lists_by_value_of_array(res[4], 'ou_short_name')
this.ous = res[0]
this.ous_by_name = apiutil.dict_by_value_of_array(res[0], 'short_name')
this.ou = this.ous_by_name[ou_name_req]
const rootpath = (await NativeOUService.list(this.$store.state.netdb_axios_config, {
do_rootpath: true,
short_name: ou_name_req,
sorting_params_list: ['tree_level ASC']
})).data[0]
EventBus.$emit('overwrite_breadcrumbs', function () {
const res = ['/cntl/ou']
for (const o of rootpath) {
res.push({to: '/cntl/ou/' + o.short_name, text: o.short_name})
}
res.pop()
res.reverse()
return res
})
} else {
if (this.only_own_ou) {
res = (await OUService.listOwn(this.$store.state.netdb_axios_config)).data
this.mgrs2ou = apiutil.dict_of_lists_by_value_of_array(res[2], 'ou_short_name')
this.fqdns2ou = apiutil.dict_of_lists_by_value_of_array(res[4], 'ou_short_name')
this.bcds2ou = apiutil.dict_of_lists_by_value_of_array(res[5], 'ou_short_name')
this.mgrs_by_login_name = apiutil.dict_by_value_of_array(res[3], 'login_name')
this.ous = res[1]
this.root_ous = res[6]
} else {
res = (await OUService.listAll(this.$store.state.netdb_axios_config)).data
this.mgrs2ou = apiutil.dict_of_lists_by_value_of_array(res[1], 'ou_short_name')
this.mgrs_by_login_name = apiutil.dict_by_value_of_array(res[2], 'login_name')
this.fqdns2ou = apiutil.dict_of_lists_by_value_of_array(res[3], 'ou_short_name')
this.bcds2ou = apiutil.dict_of_lists_by_value_of_array(res[4], 'ou_short_name')
this.ous = res[0]
this.root_ous = apiutil.dict_of_lists_by_value_of_array(this.ous, 'tree_level')['0']
}
}
this.ous_by_parent = apiutil.dict_of_lists_by_value_of_array(res[0], 'parent_short_name')
},
create_mgr_assignment(ou) {
this.db_editor_presets = {ou_short_name: ou}
......
......@@ -90,7 +90,7 @@
Organisationseinheit
</b-th>
<b-td>
{{ ou.name }} ({{ ou.short_name }})
<b-link :to="'/cntl/ou/'+ou.short_name">{{ ou.name }} ({{ ou.short_name }})</b-link>
</b-td>
</b-tr>
<b-tr>
......@@ -100,7 +100,7 @@
Durch (übergeordnete) OEs:
<ul>
<li v-for="pou in parent_ous" v-bind:key="pou.short_name">
<b>{{ pou.name }} ({{ pou.short_name }})</b>
<b><b-link :to="'/cntl/ou/'+pou.short_name">{{ pou.name }} ({{ pou.short_name }})</b-link></b>
<ul>
<li v-for="mgr in parent_oe2mgr[pou.short_name]" v-bind:key="mgr.mgr_login_name">
<b-link :href="'mailto:'+parent_oe_mgr[mgr.mgr_login_name].email">
......