diff --git a/frontend/public/bundled_json_templates/prepend_dns_record_create_dualstack.json b/frontend/public/bundled_json_templates/prepend_dns_record_create_dualstack.json new file mode 100644 index 0000000000000000000000000000000000000000..9861f08dd6106e9e23a4233aa23c841a3f0e6bb6 --- /dev/null +++ b/frontend/public/bundled_json_templates/prepend_dns_record_create_dualstack.json @@ -0,0 +1,138 @@ +{ + "variables": { + "fqdn_description": { + "friendly_name": { + "de": "FQDN-Beschreibung", + "en": "FQDN description" + }, + "optional": true, + "default": "", + "nullable": true, + "description": { + "de": "Nur falls der FQDN noch nicht extistiert: Beschreibung des FQDN. Die FQDN-Beschreibung kann später über die Bereibitungsfunktion des FQDNs geändert werden.", + "en": "Only if FQDN does not exist yet: Description of FQDN. The description can be changed later via the FQDN's edit function." + }, + "type": "str" + }, + "fqdn_description_overwrite": { + "friendly_name": { + "de": "FQDN-Beschreibung überschreiben", + "en": "Overwrite FQDN description" + }, + "optional": false, + "default": false, + "nullable": false, + "description": { + "de": "Nur falls der FQDN bereits existiert: Beschreibung des exsitierenden FQDN überschreiben.", + "en": "Only if FQDN does already exist: Overwrite Description of existing FQDN." + }, + "type": "bool" + }, + "ipv6_data": { + "friendly_name": { + "de": "Datenteil des AAAA-Records", + "en": "Data of the AAAA-record" + }, + "optional": false, + "default": false, + "nullable": false, + "description": { + "de": "Datenteil des AAAA-Records", + "en": "Data of the AAAA-record" + } + } + }, + "transaction": [ + { + "idx": "check_fqdn", + "name": "dns.fqdn.list", + "old": { + "value_list": [ + "{{ fqdn }}" + ] + } + }, + { + "idx": "rec_type_def", + "name": "dnscfg.record_type.list", + "old": { + "name": "{{type}}" + }, + "when": { + "returns_no_data": [ + "check_fqdn" + ] + } + }, + { + "idx": "fqdn_type", + "name": "dnscfg.fqdn_type.list", + "inner_join_ref": { + "rec_type_def": "api_fkey_dnscfg_record_type_dflt_fqdn_type" + }, + "when": { + "returns_no_data": [ + "check_fqdn" + ] + } + }, + { + "idx": "crt_fqdn", + "name": "dns.fqdn.create", + "new": { + "value": "{{fqdn}}", + "description": "{{fqdn_description}}" + }, + "new_ref_params": [ + { + "idx": "fqdn_type", + "params": { + "type": "name" + } + } + ], + "when": { + "returns_no_data": [ + "check_fqdn" + ] + } + }, + { + "idx": "upd_fqdn", + "name": "dns.fqdn.update", + "new": { + "description": "{{fqdn_description}}" + }, + "old": { + "value": "{{fqdn}}" + }, + "when": { + "and": [ + { + "and": [ + true, + "{{fqdn_description_overwrite}}" + ] + }, + { + "returns_data": [ + "check_fqdn" + ] + } + ] + } + }, + { + "idx": "create_aaaa", + "name": "dns.record.create", + "new": { + "fqdn": "{{fqdn}}", + "type": "AAAA", + "data": "{{ipv6_data}}", + "target_is_singleton": "{{target_is_singleton}}", + "target_is_reverse_unique": "{{target_is_reverse_unique}}" + } + } + ], + "returning": [] +} \ No newline at end of file diff --git a/frontend/src/components/DNSRecordTypeCard.vue b/frontend/src/components/DNSRecordTypeCard.vue index 9db16964367344b71d23d2c38b780682b3bdb394..a5cc31c822fbe1b99ca4dee4ede0048724f1fa79 100644 --- a/frontend/src/components/DNSRecordTypeCard.vue +++ b/frontend/src/components/DNSRecordTypeCard.vue @@ -55,11 +55,20 @@ </b-th> <b-th> <b-btn-group class="d-flex" role="group"> - <b-button variant="outline-success" - :id="'button-create-record-' + record_type" @click="createRecord(record_type)" - v-if="user_possible_record_types.includes(record_type)"> - <netvs-icon icon="create"></netvs-icon> - </b-button> + <template v-if="user_possible_record_types.includes(record_type)"> + <b-button variant="outline-success" :id="'button-create-record-' + record_type" + @click="createRecord(record_type)" v-if="!isDualstackType(record_type)"> + <netvs-icon icon="create"></netvs-icon> + </b-button> + <b-dropdown split variant="outline-success" :id="'button-create-record-' + record_type" @click="createRecord(record_type)" v-else> + <template v-slot:button-content> + <netvs-icon icon="create"></netvs-icon> + </template> + <b-dropdown-item @click="createRecordDualstack()"> + <netvs-icon icon="create"></netvs-icon> TODO:LANG: Dualstack + </b-dropdown-item> + </b-dropdown> + </template> <b-button variant="outline-primary" :id="'button-export-record-' + record_type" @click="exportCSV()"> <netvs-icon icon="export"></netvs-icon> @@ -173,6 +182,13 @@ :loose_data="'data' in db_editor_presets?db_editor_presets.data:null" :fixed_fqdn="'fqdn' in db_editor_presets?db_editor_presets.fqdn:null" /> + <CreateDNSRecordDualstack + v-if="user_possible_record_types.includes(record_type) && isDualstackType(record_type)" + :modal_id="`create_record_dualstack-${record_type}`" + :loose_data="'data' in db_editor_presets?db_editor_presets.data:null" + :loose_v6_data="'ipv6_data' in db_editor_presets?db_editor_presets.ipv6_data:null" + :fixed_fqdn="'fqdn' in db_editor_presets?db_editor_presets.fqdn:null" + /> <DBEditor :presets="db_editor_presets" :input_reducer="create_record_reducer" :modal_id="`update_record-${record_type}`" @@ -194,10 +210,12 @@ import DBEditor from '@/components/db-editor/APIObjectDBEditor.vue' import CreateDNSRecord from '@/db-editors/CreateDNSRecord.vue' import RecordDeleteButton from '@/components/RecordDeleteButton.vue' import Paginator from '@/components/Paginator.vue' +import CreateDNSRecordDualstack from '@/db-editors/CreateDNSRecordDualstack.vue' export default { name: 'DNSRecordTypeCard', components: { + CreateDNSRecordDualstack, Paginator, RecordDeleteButton, CreateDNSRecord, @@ -519,14 +537,24 @@ export default { this.create_record_reducer.type = false this.$root.$emit('bv::show::modal', `update_record-${this.record_type}`) }, - createRecord: function (record_type, data, fqdn) { - this.db_editor_function = 'create' + createRecordTemplates(record_type, data, fqdn, dualstack = false) { this.db_editor_presets = { type: record_type, data: data, fqdn: fqdn, } - if (record_type === 'AAAA') { + if ((record_type === 'A' && (!data)) || dualstack) { + for (const bl of this.reverseIfAsc(this.asc_v4_blocklist)) { + for (const b of bl.containing_blocks) { + if (b.type === 'free') { + this.db_editor_presets.data = b.first + break + } + } + } + data = this.db_editor_presets.data + } + if (record_type === 'AAAA' || dualstack) { let sub = null let multi = false this.subnets.forEach((item) => { @@ -537,30 +565,36 @@ export default { sub = item } }) + let tmp_data = '' if (sub !== null && !multi) { const split = sub.cidr.split('/') - this.db_editor_presets.data = split[0] - if (split[1] === '64') { - this.db_editor_presets.data += data + tmp_data = split[0] + if (split[1] === '64' && data) { + tmp_data += data } - } else if (multi) { - this.db_editor_presets.data = '' } - } - if (record_type === 'A' && (!data)) { - for (const bl of this.reverseIfAsc(this.asc_v4_blocklist)) { - for (const b of bl.containing_blocks) { - if (b.type === 'free') { - this.db_editor_presets.data = b.first - break - } - } + if (!dualstack) { + this.db_editor_presets.data = tmp_data + } else { + this.db_editor_presets.ipv6_data = tmp_data + console.log('V6', this.db_editor_presets.ipv6_data) } } + }, + createRecord: function (record_type, data, fqdn) { + this.db_editor_function = 'create' + this.createRecordTemplates(record_type, data, fqdn) const record_reducer = Object.assign({ '': { display_name: this.$t('views.dnsvs.bcd_records.automatic_handling') } }, this.full_edit_fqdn_reducer.type) this.create_record_reducer = { type: false, fqdn_type: record_reducer } this.$root.$emit('bv::show::modal', `create_record-${this.record_type}`) }, + createRecordDualstack: function () { + this.createRecordTemplates('A', undefined, undefined, true) + this.$root.$emit('bv::show::modal', `create_record_dualstack-${this.record_type}`) + }, + isDualstackType: function (record_type) { + return (record_type === 'A' || record_type === 'AAAA') + } }, computed: { filtered_records() { diff --git a/frontend/src/components/FlatRecordTable.vue b/frontend/src/components/FlatRecordTable.vue index 1dfbd291d0bd4bbdea7d05479aeb662c55942e06..0d9d225edc2c5c8a8e05f29a9bb12f2b7cacf845 100644 --- a/frontend/src/components/FlatRecordTable.vue +++ b/frontend/src/components/FlatRecordTable.vue @@ -64,6 +64,10 @@ </template> <template v-slot:head(actions)> <b-btn-group class="d-flex" role="group"> + <b-button variant="outline-success" + :id="'button-create-record-dualstack'" @click="createItemDualstack()"> + fooooooooooo + </b-button> <b-button variant="outline-success" v-if="!fixed_record_types" :id="'button-create-record'" @click="createItem()"> <netvs-icon icon="create"></netvs-icon> @@ -95,6 +99,8 @@ <CreateDNSRecord modal_id="create_record" :fixed_fqdn="fixed_fqdn" :fixed_record_type="fixed_record_types?type_select:(ip?(ip.includes('.')?'A':'AAAA'):null)" :fixed_data="ip"/> + <CreateDNSRecordDualstack modal_id="create_record_dualstack" :fixed_fqdn="fixed_fqdn" + :fixed_data="ip"/> <DBEditor :presets="db_editor_presets" :input_reducer="create_record_reducer" modal_id="edit_record" :object_title="object_title" :object_function="db_editor_function" object_fq_name="dns.record" :old_data="db_editor_old_data" @@ -120,10 +126,12 @@ import RRDataView from '@/components/RRDataView' import RecordInfo from '@/components/RecordInfo' import CreateDNSRecord from '@/db-editors/CreateDNSRecord.vue' import RecordDeleteButton from '@/components/RecordDeleteButton.vue' +import CreateDNSRecordDualstack from '@/db-editors/CreateDNSRecordDualstack.vue' export default { name: 'FlatRecordTable', components: { + CreateDNSRecordDualstack, RecordDeleteButton, CreateDNSRecord, RecordInfo, @@ -254,6 +262,12 @@ export default { } this.$root.$emit('bv::show::modal', 'create_record') }, + createItemDualstack: function (t = null) { + if (t) { + this.type_select = t + } + this.$root.$emit('bv::show::modal', 'create_record_dualstack') + }, editFQDN: function (item) { this.db_editor_function = 'update' this.db_editor_old_data = this.fqdns[item] diff --git a/frontend/src/db-editors/CreateDNSRecordDualstack.vue b/frontend/src/db-editors/CreateDNSRecordDualstack.vue new file mode 100644 index 0000000000000000000000000000000000000000..ded037f14806d35b80a72f115b346477a26f8205 --- /dev/null +++ b/frontend/src/db-editors/CreateDNSRecordDualstack.vue @@ -0,0 +1,128 @@ +<template> + <BundledDBEditor v-if="template && record_types_by_name" object_function="create" object_fq_name="dns.record" + :modal_id="modal_id" + :template="template" + :presets="presets" + :input_reducer="reducer" + :prepend="true" + :non_optionals_order="['fqdn', 'data', 'ipv6_data', 'fqdn_description', 'fqdn_description_overwrite', 'target_is_reverse_unique']"/> +</template> + +<script> +import BundledDBEditor from '@/components/db-editor/BundledDBEditor.vue' +import TypeService from '@/api-services/dnscfg_types.service' +import apiutil from '@/util/apiutil' +import Axios from 'axios' + +export default { + name: 'CreateDNSRecordDualstack', + components: { BundledDBEditor }, + async created() { + this.template = (await Axios.get('/bundled_json_templates/prepend_dns_record_create_dualstack.json')).data + const typeQuery = await TypeService.getTypes(this.$store.state.netdb_axios_config) + this.record_types_by_name = apiutil.dict_by_value_of_array(typeQuery.data.my_record_types, 'name') + const types = typeQuery.data.my_record_types + const selections = {} + const fqdnSelections = {} + for (const t of types) { + selections[t.record_type] = { display_name: t.record_type } + } + for (const t of typeQuery.data.fqdn_type_list) { + let disp_name = t.description + disp_name += ' [' + disp_name += t.is_nonterminal ? this.$t('views.dnsvs.bcd_records.non-terminal') : this.$t('views.dnsvs.bcd_records.terminal') + disp_name += ']' + fqdnSelections[t.name] = { display_name: disp_name } + } + this.full_create_record_reducer = { + type: selections + } + }, + computed: { + reducer() { + const ret = this.full_create_record_reducer + if (this.fixed_record_type) { + ret.type = false + } + if (this.fixed_fqdn) { + ret.fqdn = false + } + if (this.fixed_data) { + ret.data = false + } + return ret + }, + presets() { + const ret = {} + if (this.fixed_record_type) { + ret.type = this.fixed_record_type + ret.target_is_reverse_unique = this.record_types_by_name[this.fixed_record_type].target_is_reverse_unique_dflt + ret.target_is_singleton = this.record_types_by_name[this.fixed_record_type].target_is_singleton_dflt + } + if (this.fixed_fqdn) { + ret.fqdn = this.fixed_fqdn + } + if (this.fixed_data || this.loose_data) { + ret.data = this.fixed_data ? this.fixed_data : this.loose_data + } + if (this.fixed_v6_data || this.loose_v6_data) { + ret.ipv6_data = this.fixed_v6_data ? this.fixed_v6_data : this.loose_v6_data + } + return ret + }, + }, + data() { + return { + template: null, + full_create_record_reducer: {}, + record_types_by_name: null, + fixed_record_type: 'A' + } + }, + props: { + modal_id: { + type: String, + required: true + }, + fixed_fqdn: { + type: String, + required: false, + default() { + return null + } + }, + fixed_data: { + type: String, + required: false, + default() { + return null + } + }, + loose_data: { + type: String, + required: false, + default() { + return null + } + }, + fixed_v6_data: { + type: String, + required: false, + default() { + return null + } + }, + loose_v6_data: { + type: String, + required: false, + default() { + return null + } + }, + } +} +</script> + +<style scoped> + +</style>