diff --git a/src/client/client/constants.js b/src/client/client/constants.js index bee0a5a2..ec061be8 100644 --- a/src/client/client/constants.js +++ b/src/client/client/constants.js @@ -35,6 +35,7 @@ export const endpointVersionMap = { barbican: 'v1', zun: 'v1', magnum: 'v1', + designate: 'v2', }; export const endpointsDefault = { @@ -75,6 +76,7 @@ export const manilaBase = () => getOpenstackEndpoint('manilav2'); export const barbicanBase = () => getOpenstackEndpoint('barbican'); export const zunBase = () => getOpenstackEndpoint('zun'); export const magnumBase = () => getOpenstackEndpoint('magnum'); +export const designateBase = () => getOpenstackEndpoint('designate'); export const ironicOriginEndpoint = () => getOriginEndpoint('ironic'); export const vpnEndpoint = () => getOriginEndpoint('neutron_vpn'); diff --git a/src/client/designate/index.js b/src/client/designate/index.js new file mode 100644 index 00000000..d63bc172 --- /dev/null +++ b/src/client/designate/index.js @@ -0,0 +1,91 @@ +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import Base from '../client/base'; +import { designateBase } from '../client/constants'; + +export class DesignateClient extends Base { + get baseUrl() { + return designateBase(); + } + + get resources() { + return [ + { + name: 'zones', + key: 'zones', + responseKey: 'zone', + subResources: [ + { + key: 'recordsets', + responseKey: 'recordset', + }, + ] + }, + { + name: 'reverse', + key: 'reverse', + responseKey: 'reverse', + extendOperations: [ + { + key: 'reverseDetail', + generate: (data) => + this.request.get( + this.getSubResourceUrlById('reverse', data, 'floatingips'), + null, + { + headers: { + 'content-type': 'application/json', + }, + } + ), + }, + { + key: 'setReverse', + generate: (id, data) => + this.request.patch( + this.getSubResourceUrlById('reverse', id, 'floatingips'), data, + null, + { + headers: { + 'content-type': 'application/json', + }, + } + ), + }, + { + key: 'unsetReverse', + generate: (id, data) => + this.request.patch( + this.getSubResourceUrlById('reverse', id, 'floatingips'), data, + null, + { + headers: { + 'content-type': 'application/json', + }, + } + ), + }, + ], + subResources: [ + { + key: 'floatingips', + responseKey: 'floatingip', + }, + ] + } + ] + } +} + +const designateClient = new DesignateClient(); +export default designateClient; \ No newline at end of file diff --git a/src/layouts/menu.jsx b/src/layouts/menu.jsx index 4517afe6..84dcad98 100644 --- a/src/layouts/menu.jsx +++ b/src/layouts/menu.jsx @@ -448,6 +448,45 @@ const renderMenu = (t) => { }, ], }, + { + path: '/network/dns/zones', + name: t('DNS Zones'), + key: 'dnsZones', + endpoints: 'designate', + level: 1, + children: [ + { + path: /^\/network\/dns\/zones\/detail\/.[^/]+$/, + name: t('Zones Detail'), + key: 'dnsZonesDetail', + level: 2, + routePath: '/network/dns/zones/detail/:id', + }, + { + path: /^\/network\/dns\/zones\/detail\/.[^/]+\/recordsets\/.[^/]+$/, + name: t('Recordsets Detail'), + key: 'dnsRecordSetDetail', + level: 2, + routePath: '/network/dns/zones/detail/:id/recordsets/:recordset_id', + }, + ] + }, + { + path: '/network/dns/reverse', + name: t('DNS Reverse'), + key: 'dnsReverse', + endpoints: 'designate', + level: 1, + children: [ + { + path: /^\/network\/dns\/reverse\/detail\/.[^/]+$/, + name: t('Reverse DNS Detail'), + key: 'dnsReverseDetail', + level: 2, + routePath: '/network/dns/reverse/detail/:id', + }, + ] + } ], }, { diff --git a/src/pages/network/containers/DNS/Reverse/Detail/BaseDetail.jsx b/src/pages/network/containers/DNS/Reverse/Detail/BaseDetail.jsx new file mode 100644 index 00000000..b0384a24 --- /dev/null +++ b/src/pages/network/containers/DNS/Reverse/Detail/BaseDetail.jsx @@ -0,0 +1,61 @@ +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import { inject, observer } from 'mobx-react'; +import Base from 'containers/BaseDetail'; + +export class BaseDetail extends Base { + get leftCards() { + return [this.baseInfoCard]; + } + + get baseInfoCard() { + const options = [ + { + label: t('Address'), + dataIndex: 'address', + }, + { + label: t('PTR Domain Name'), + dataIndex: 'ptrdname', + }, + { + label: t('Description'), + dataIndex: 'description', + }, + { + label: t('ID'), + dataIndex: 'id', + }, + { + label: t('Time To Live'), + dataIndex: 'ttl', + }, + { + label: t('Status'), + dataIndex: 'status', + }, + { + label: t('Action'), + dataIndex: 'action', + }, + ]; + + return { + title: t('Base Info'), + options, + }; + } + +} + +export default inject('rootStore')(observer(BaseDetail)); \ No newline at end of file diff --git a/src/pages/network/containers/DNS/Reverse/Detail/index.jsx b/src/pages/network/containers/DNS/Reverse/Detail/index.jsx new file mode 100644 index 00000000..9a17d469 --- /dev/null +++ b/src/pages/network/containers/DNS/Reverse/Detail/index.jsx @@ -0,0 +1,53 @@ +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import { inject, observer } from 'mobx-react'; +import Base from 'containers/TabDetail'; +import BaseDetail from './BaseDetail'; +import actionConfigs from '../actions'; +import globalReverseStore from 'src/stores/designate/reverse'; + +export class ReverseDetail extends Base { + + init() { + this.store = globalReverseStore; + } + + get name() { + return t('Reverse Detail'); + } + + get policy() { + return 'get_image'; + } + + get listUrl() { + return this.getRoutePath('dns-reverse'); + } + + get actionConfigs() { + return actionConfigs; + } + + get tabs() { + const tabs = [ + { + title: t('Detail'), + key: 'detail', + component: BaseDetail, + }, + ]; + return tabs; + } +} + +export default inject('rootStore')(observer(ReverseDetail)); diff --git a/src/pages/network/containers/DNS/Reverse/actions/Set.jsx b/src/pages/network/containers/DNS/Reverse/actions/Set.jsx new file mode 100644 index 00000000..7d83431d --- /dev/null +++ b/src/pages/network/containers/DNS/Reverse/actions/Set.jsx @@ -0,0 +1,73 @@ +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import { ModalAction } from 'containers/Action'; +import { inject, observer } from 'mobx-react'; +import globalReverseStore from 'src/stores/designate/reverse'; + +export class Set extends ModalAction { + init() { + this.store = globalReverseStore; + } + + static id = 'set-reverse'; + + static title = t('Set'); + + static get modalSize() { + return 'small'; + } + + get name() { + return t('Set Domain Name PTR'); + } + + static policy = 'get_images'; + + static allowed() { + return Promise.resolve(true); + } + + get formItems() { + return [ + { + name: 'ptrdname', + label: t('Domain Name'), + type: 'input', + required: true, + placeholder: t('smtp.example.com'), + tip: ('Domain name ending in.') + }, + { + name: 'description', + label: t('Description'), + type: 'textarea', + tip: t('Details about the PTR record.') + }, + { + name: 'ttl', + label: t('TTL'), + type: 'input-number', + min: 0, + tip: t('Time To Live in seconds.'), + placeholder: t('3600'), + }, + ] + } + + onSubmit = (values) => { + const { id } = this.item; + return this.store.set({ id: id }, values); + }; +} + +export default inject('rootStore')(observer(Set)); diff --git a/src/pages/network/containers/DNS/Reverse/actions/Unset.jsx b/src/pages/network/containers/DNS/Reverse/actions/Unset.jsx new file mode 100644 index 00000000..e44dfe05 --- /dev/null +++ b/src/pages/network/containers/DNS/Reverse/actions/Unset.jsx @@ -0,0 +1,51 @@ +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import { ConfirmAction } from 'containers/Action'; +import globalReverseStore from 'src/stores/designate/reverse'; + +export default class Unset extends ConfirmAction { + get id() { + return 'usnet'; + } + + get title() { + return t('Unset'); + } + + get actionName() { + return t('Unset'); + } + + get buttonText() { + return t('Unset'); + } + + allowedCheckFunc = (item) => { + if (item.ptrdname !== null && item.status === 'ACTIVE') return true; + return false; + } + + policy = 'instance:delete'; + + confirmContext = (data) => { + const name = this.getName(data); + return t('Are you sure to {action}? (Zone: {name})', { + action: this.actionNameDisplay || this.title, + name, + }); + }; + + onSubmit = (item) => { + return globalReverseStore.unset({ id: item.id }, { 'ptrdname': null }); + }; +} \ No newline at end of file diff --git a/src/pages/network/containers/DNS/Reverse/actions/index.jsx b/src/pages/network/containers/DNS/Reverse/actions/index.jsx new file mode 100644 index 00000000..0f889e55 --- /dev/null +++ b/src/pages/network/containers/DNS/Reverse/actions/index.jsx @@ -0,0 +1,29 @@ +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import Set from './Set'; +import Unset from './Unset'; + +const actionConfigs = { + rowActions: { + moreActions: [ + { + action: Set, + }, + { + action: Unset, + }, + ] + }, +}; + +export default actionConfigs; diff --git a/src/pages/network/containers/DNS/Reverse/index.jsx b/src/pages/network/containers/DNS/Reverse/index.jsx new file mode 100644 index 00000000..f9d429ac --- /dev/null +++ b/src/pages/network/containers/DNS/Reverse/index.jsx @@ -0,0 +1,62 @@ +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import { observer, inject } from 'mobx-react'; +import Base from 'containers/List'; +import actionConfigs from './actions'; +import globalReverseStore, { ReverseStore } from 'src/stores/designate/reverse'; + +export class Reverse extends Base { + init() { + this.store = globalReverseStore; + this.downloadStore = new ReverseStore(); + } + + get policy() { + return 'get_images'; + } + + get name() { + return t('Reverse Dns'); + } + + get actionConfigs() { + return actionConfigs; + } + + getColumns = () => [ + { + title: t('Address'), + dataIndex: 'address', + isLink: true, + routeName: 'dnsReverseDetail', + routeParamsFunc: (data) => { + return { + id: data.id, + }; + }, + }, + { + title: t('PTR Domain Name'), + dataIndex: 'ptrdname', + isHideable: true, + }, + { + title: t('Status'), + dataIndex: 'status', + isHideable: true, + }, + ] + +} + +export default inject('rootStore')(observer(Reverse)); \ No newline at end of file diff --git a/src/pages/network/containers/DNS/Zones/Detail/BaseDetail/index.jsx b/src/pages/network/containers/DNS/Zones/Detail/BaseDetail/index.jsx new file mode 100644 index 00000000..819d2d8e --- /dev/null +++ b/src/pages/network/containers/DNS/Zones/Detail/BaseDetail/index.jsx @@ -0,0 +1,115 @@ +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import { inject, observer } from 'mobx-react'; +import Base from 'containers/BaseDetail'; + +export class BaseDetail extends Base { + get leftCards() { + return [this.baseInfoCard, this.modificationTimesCard]; + } + + get rightCards() { + return [this.attributesCard, this.associationsCard]; + } + + get baseInfoCard() { + const options = [ + { + label: t('Action'), + dataIndex: 'action', + }, + { + label: t('Serial'), + dataIndex: 'serial', + }, + { + label: t('TTL'), + dataIndex: 'ttl', + }, + { + label: t('Version'), + dataIndex: 'version', + }, + ]; + + return { + title: t('Base Info'), + options, + }; + } + + get modificationTimesCard() { + const options = [ + { + label: t('Created'), + dataIndex: 'created_at', + valueRender: 'toLocalTime' + }, + { + label: t('Updated'), + dataIndex: 'updated_at', + valueRender: 'toLocalTime' + }, + { + label: t('Transferred'), + dataIndex: 'transferred_at', + valueRender: 'toLocalTime' + }, + ]; + + return { + title: t('Modification Times'), + options, + }; + } + + get attributesCard() { + const options = [ + { + label: t('Attributes'), + dataIndex: 'attributes', + render: (value) => JSON.stringify(value) + } + ]; + + return { + title: t('Attributes'), + options, + }; + } + + get associationsCard() { + const options = [ + { + label: t('Pool ID'), + dataIndex: 'pool_id', + }, + { + label: t('Project ID'), + dataIndex: 'project_id', + }, + { + label: t('Masters'), + dataIndex: 'masters', + render: (value) => JSON.stringify(value) + } + ]; + + return { + title: t('Associations'), + options, + }; + } +} + +export default inject('rootStore')(observer(BaseDetail)); \ No newline at end of file diff --git a/src/pages/network/containers/DNS/Zones/Detail/RecordSets/Detail/BaseDetail/index.jsx b/src/pages/network/containers/DNS/Zones/Detail/RecordSets/Detail/BaseDetail/index.jsx new file mode 100644 index 00000000..1c3823c5 --- /dev/null +++ b/src/pages/network/containers/DNS/Zones/Detail/RecordSets/Detail/BaseDetail/index.jsx @@ -0,0 +1,105 @@ +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import React from 'react'; +import { inject, observer } from 'mobx-react'; +import Base from 'containers/BaseDetail'; + +export class BaseDetail extends Base { + get leftCards() { + return [this.baseInfoCard, this.modificationTimesCard]; + } + + get rightCards() { + return [this.associationsCard]; + } + + get baseInfoCard() { + const options = [ + { + label: t('Action'), + dataIndex: 'action', + }, + { + label: t('Records'), + dataIndex: 'records', + render: (value) => value.map((item) =>
{item}
) + // render: (value) => value.join(" - ") + }, + { + label: t('TTL'), + dataIndex: 'ttl', + }, + { + label: t('Version'), + dataIndex: 'version', + } + ]; + + return { + title: t('Base Info'), + labelCol: 6, + contentCol: 18, + options + }; + } + + get modificationTimesCard() { + const options = [ + { + label: t('Created'), + dataIndex: 'created_at', + valueRender: 'toLocalTime' + }, + { + label: t('Updated'), + dataIndex: 'updated_at', + valueRender: 'toLocalTime' + } + ]; + + return { + title: t('Modification Times'), + labelCol: 6, + contentCol: 18, + options + }; + } + + get associationsCard() { + const options = [ + { + label: t('Zone ID'), + dataIndex: 'zone_id', + copyable: true + }, + { + label: t('Zone Name'), + dataIndex: 'zone_name', + }, + { + label: t('Project ID'), + dataIndex: 'project_id', + copyable: true + } + ]; + + return { + title: t('Associations'), + // labelCol: 4, + // contentCol: 18, + options + }; + } +} + +export default inject('rootStore')(observer(BaseDetail)); \ No newline at end of file diff --git a/src/pages/network/containers/DNS/Zones/Detail/RecordSets/Detail/index.jsx b/src/pages/network/containers/DNS/Zones/Detail/RecordSets/Detail/index.jsx new file mode 100644 index 00000000..5ff5cfd5 --- /dev/null +++ b/src/pages/network/containers/DNS/Zones/Detail/RecordSets/Detail/index.jsx @@ -0,0 +1,76 @@ +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import { inject, observer } from 'mobx-react'; +import Base from 'containers/TabDetail'; +import BaseDetail from './BaseDetail'; +import { DNSRecordSetsStore } from 'src/stores/designate/recordSets'; +import { DNS_RECORD_TYPE } from 'src/utils/dns-rrtype'; + +export class RecordSetsDetail extends Base { + init() { + this.store = new DNSRecordSetsStore(); + } + + get titleValue() { + return this.detailData.id; + } + + get name() { + return t('Recordset Detail'); + } + + get listUrl() { + return this.getRoutePath('dnsZonesDetail', { id: this.detailData.zone_id }, { 'tab': 'record_sets' }); + } + + get policy() { + return 'get_images'; + } + + get detailInfos() { + return [ + { + title: t('Name'), + dataIndex: 'name', + }, + { + title: t('Description'), + dataIndex: 'description', + }, + { + title: t('Type'), + dataIndex: 'type', + render: (data) => data + (Object.keys(DNS_RECORD_TYPE).includes(data) ? " - " + DNS_RECORD_TYPE[data].name : "") + }, + { + title: t('Status'), + dataIndex: 'status', + } + ]; + } + + get tabs() { + const tabs = [ + { + title: t('Overview'), + key: 'overview', + component: BaseDetail, + } + ] + + return tabs; + } + +} + +export default inject('rootStore')(observer(RecordSetsDetail)); \ No newline at end of file diff --git a/src/pages/network/containers/DNS/Zones/Detail/RecordSets/actions/Delete.jsx b/src/pages/network/containers/DNS/Zones/Detail/RecordSets/actions/Delete.jsx new file mode 100644 index 00000000..8c52a19e --- /dev/null +++ b/src/pages/network/containers/DNS/Zones/Detail/RecordSets/actions/Delete.jsx @@ -0,0 +1,56 @@ +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import { ConfirmAction } from 'containers/Action'; +import globalDNSRecordSetsStore from 'src/stores/designate/recordSets'; + +export default class Delete extends ConfirmAction { + get id() { + return 'delete'; + } + + get title() { + return t('Delete Record Set'); + } + + get actionName() { + return t('Delete Record Set'); + } + + get buttonText() { + return t('Delete'); + } + + get isDanger() { + return true; + } + + allowedCheckFunction = () => true; + + policy = 'instance:delete'; + + confirmContext = (data) => { + const name = this.getName(data); + const id = this.getItemId(data); + return t('Are you sure to {action}? (Record Set: {name} - {id})', { + action: this.actionNameDisplay || this.title, + name, + id + }); + }; + + onSubmit = (item) => { + const zone_id = item.zone_id; + const recordset_id = item.id; + return globalDNSRecordSetsStore.delete({ zone_id, recordset_id }); + }; +} \ No newline at end of file diff --git a/src/pages/network/containers/DNS/Zones/Detail/RecordSets/actions/Update.jsx b/src/pages/network/containers/DNS/Zones/Detail/RecordSets/actions/Update.jsx new file mode 100644 index 00000000..ccf0fde2 --- /dev/null +++ b/src/pages/network/containers/DNS/Zones/Detail/RecordSets/actions/Update.jsx @@ -0,0 +1,84 @@ +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import { ModalAction } from 'containers/Action'; +import { inject, observer } from 'mobx-react'; +import { getRecordSetFormItem } from 'src/resources/dns/record'; +import globalDNSRecordSetsStore from 'src/stores/designate/recordSets'; +import { DNS_RECORD_TYPE } from 'src/utils/dns-rrtype'; + +export class Update extends ModalAction { + init() { + this.store = globalDNSRecordSetsStore; + this.state = { + ...this.state, + nameExtra: `Exp: ${DNS_RECORD_TYPE[this.item.type].nameExtra}`, + recordsExtra: `Exp: ${DNS_RECORD_TYPE[this.item.type].recordsExtra}`, + }; + } + + static id = 'create-record-set'; + + static title = t('Update Record Set'); + + get name() { + return t('Update Record Set'); + } + + static policy = 'get_images'; + + static allowed() { + return Promise.resolve(true); + } + + get defaultValue() { + const { ...values } = this.item; + + const recordsData = []; + values.records.map((item, index) => + recordsData.push({ index, value: item }) + ); + + return { + type: values.type, + name: values.name, + description: values.description, + ttl: values.ttl, + records: recordsData, + }; + } + + get formItems() { + return getRecordSetFormItem(this, this.currentFormValue); + } + + onSubmit = (values) => { + const zone_id = this.item.zone_id; + const recordset_id = this.item.id; + + const { records, ...val } = values; + + const recordsItem = []; + records.forEach((item) => { + recordsItem.push(item.value); + }); + + const body = { + records: recordsItem, + ...val, + }; + + return this.store.update(zone_id, recordset_id, body); + }; +} + +export default inject('rootStore')(observer(Update)); diff --git a/src/pages/network/containers/DNS/Zones/Detail/RecordSets/actions/index.jsx b/src/pages/network/containers/DNS/Zones/Detail/RecordSets/actions/index.jsx new file mode 100644 index 00000000..d254e9bd --- /dev/null +++ b/src/pages/network/containers/DNS/Zones/Detail/RecordSets/actions/index.jsx @@ -0,0 +1,32 @@ +// Copyright 2021 99cloud +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import Update from './Update'; +import Delete from './Delete'; + +const actionConfigs = { + rowActions: { + moreActions: [ + { + action: Update, + }, + { + action: Delete, + }, + ], + }, + batchActions: [Delete] +}; + +export default actionConfigs; diff --git a/src/pages/network/containers/DNS/Zones/Detail/RecordSets/index.jsx b/src/pages/network/containers/DNS/Zones/Detail/RecordSets/index.jsx new file mode 100644 index 00000000..f5f68c6d --- /dev/null +++ b/src/pages/network/containers/DNS/Zones/Detail/RecordSets/index.jsx @@ -0,0 +1,68 @@ +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import React from 'react'; +import Base from 'containers/List'; +import { inject, observer } from 'mobx-react'; +import globalDNSRecordSetsStore from "src/stores/designate/recordSets"; +import actionConfigs from './actions'; +import { Tag } from 'antd'; + +export class RecordSets extends Base { + init() { + this.store = globalDNSRecordSetsStore; + } + + get name() { + return t('recordsets'); + } + + get policy() { + return 'get_images'; + } + + get actionConfigs() { + return actionConfigs; + } + + getColumns() { + return [ + { + title: t('ID/Name'), + dataIndex: 'name', + routeName: this.getRouteName('dnsRecordSetDetail'), + routeParamsFunc: (data) => { + return { + id: data.zone_id, + recordset_id: data.id, + }; + }, + isLink: true, + }, + { + title: t('Type'), + dataIndex: 'type', + }, + { + title: t('Records'), + dataIndex: 'records', + render: (value) => value.map((item) => {item}) + }, + { + title: t('Status'), + dataIndex: 'status', + }, + ] + } +} + +export default inject('rootStore')(observer(RecordSets)); diff --git a/src/pages/network/containers/DNS/Zones/Detail/index.jsx b/src/pages/network/containers/DNS/Zones/Detail/index.jsx new file mode 100644 index 00000000..aaef3895 --- /dev/null +++ b/src/pages/network/containers/DNS/Zones/Detail/index.jsx @@ -0,0 +1,81 @@ +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import { inject, observer } from 'mobx-react'; +import Base from 'containers/TabDetail'; +import BaseDetail from './BaseDetail'; +import RecordSets from './RecordSets'; +import { DNSZonesStore } from 'src/stores/designate/zones'; + +export class ZonesDetail extends Base { + init() { + this.store = new DNSZonesStore(); + } + + get name() { + return t('DNS Zones Detail'); + } + + get listUrl() { + return this.getRoutePath('dnsZones'); + } + + get policy() { + return 'get_images'; + } + + get detailInfos() { + return [ + { + title: t('Name'), + dataIndex: 'name', + }, + { + title: t('Description'), + dataIndex: 'description', + }, + { + title: t('Type'), + dataIndex: 'type', + }, + { + title: t('Status'), + dataIndex: 'status', + }, + { + title: t('Email'), + dataIndex: 'email', + } + ]; + } + + get tabs() { + const tabs = [ + { + title: t('Overview'), + key: 'overview', + component: BaseDetail, + }, + { + title: t('Record Sets'), + key: 'record_sets', + component: RecordSets, + } + ] + + return tabs; + + } + +} + +export default inject('rootStore')(observer(ZonesDetail)); \ No newline at end of file diff --git a/src/pages/network/containers/DNS/Zones/actions/Create.jsx b/src/pages/network/containers/DNS/Zones/actions/Create.jsx new file mode 100644 index 00000000..9733dc77 --- /dev/null +++ b/src/pages/network/containers/DNS/Zones/actions/Create.jsx @@ -0,0 +1,91 @@ +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import { ModalAction } from 'containers/Action'; +import { inject, observer } from 'mobx-react'; +import globalDNSZonesStore from 'src/stores/designate/zones'; +import { emailValidate } from 'utils/validate'; +export class Create extends ModalAction { + init() { + this.store = globalDNSZonesStore; + } + + static id = 'create-dns-zone'; + + static title = t('Create Zone'); + + static get modalSize() { + return 'small'; + } + + get name() { + return t('Create Zone'); + } + + static policy = 'get_images'; + + static allowed() { + return Promise.resolve(true); + } + + get defaultValue() { + return { + ttl: 3600, + type: 'PRIMARY' + } + } + + get formItems() { + return [ + { + name: 'name', + label: t('Name'), + type: 'input', + required: true + }, + { + name: 'description', + label: t('Description'), + type: 'textarea' + }, + { + name: 'email', + label: t('Email Address'), + type: 'input', + required: true, + validator: emailValidate, + }, + { + name: 'ttl', + label: t('TTL'), + type: 'input-number', + min: 0, + required: true + }, + { + name: 'type', + label: t('Type'), + type: 'select', + options: [ + { label: t('Primary'), value: 'PRIMARY' }, + { label: t('Secondary'), value: 'SECONDARY' }, + ] + }, + ] + } + + onSubmit = (values) => { + return this.store.create(values); + }; +} + +export default inject('rootStore')(observer(Create)); diff --git a/src/pages/network/containers/DNS/Zones/actions/Delete.jsx b/src/pages/network/containers/DNS/Zones/actions/Delete.jsx new file mode 100644 index 00000000..77100b47 --- /dev/null +++ b/src/pages/network/containers/DNS/Zones/actions/Delete.jsx @@ -0,0 +1,52 @@ +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import { ConfirmAction } from 'containers/Action'; +import globalDNSZonesStore from 'src/stores/designate/zones'; + +export default class Delete extends ConfirmAction { + get id() { + return 'delete'; + } + + get title() { + return t('Delete Zone'); + } + + get actionName() { + return t('Delete Zone'); + } + + get buttonText() { + return t('Delete'); + } + + get isDanger() { + return true; + } + + allowedCheckFunction = () => true; + + policy = 'instance:delete'; + + confirmContext = (data) => { + const name = this.getName(data); + return t('Are you sure to {action}? (Zone: {name})', { + action: this.actionNameDisplay || this.title, + name, + }); + }; + + onSubmit = (item) => { + return globalDNSZonesStore.delete({ id: item.id }); + }; +} \ No newline at end of file diff --git a/src/pages/network/containers/DNS/Zones/actions/Records/Create.jsx b/src/pages/network/containers/DNS/Zones/actions/Records/Create.jsx new file mode 100644 index 00000000..87519dbc --- /dev/null +++ b/src/pages/network/containers/DNS/Zones/actions/Records/Create.jsx @@ -0,0 +1,70 @@ +// Copyright 2021 99cloud +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import { ModalAction } from 'containers/Action'; +import { inject, observer } from 'mobx-react'; +import globalDNSRecordSetsStore from 'src/stores/designate/recordSets'; +import { DNS_RECORD_TYPE } from 'src/utils/dns-rrtype'; +import { getRecordSetFormItem } from 'src/resources/dns/record'; + +export class Create extends ModalAction { + init() { + this.store = globalDNSRecordSetsStore; + this.state = { ...this.state, nameExtra: `Exp: ${DNS_RECORD_TYPE.A.nameExtra}`, recordsExtra: `Exp: ${DNS_RECORD_TYPE.A.recordsExtra}` }; + } + + static id = 'create-record-set'; + + static title = t('Create Record Set'); + + get name() { + return t('Create Record Set'); + } + + static policy = 'get_images'; + + static allowed() { + return Promise.resolve(true); + } + + get defaultValue() { + return { + ttl: 3600, + type: 'A', + }; + } + + get formItems() { + return getRecordSetFormItem(this, this.currentFormValue); + } + + onSubmit = (values) => { + const { id } = this.item; + const { records, ...val } = values; + + const recordsItem = []; + records.forEach((item) => { + recordsItem.push(item.value); + }); + + const body = { + records: recordsItem, + ...val, + }; + + return this.store.create({ id }, body); + }; +} + +export default inject('rootStore')(observer(Create)); diff --git a/src/pages/network/containers/DNS/Zones/actions/Update.jsx b/src/pages/network/containers/DNS/Zones/actions/Update.jsx new file mode 100644 index 00000000..b25d5afe --- /dev/null +++ b/src/pages/network/containers/DNS/Zones/actions/Update.jsx @@ -0,0 +1,95 @@ +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import { ModalAction } from 'containers/Action'; +import { inject, observer } from 'mobx-react'; +import globalDNSZonesStore from 'src/stores/designate/zones'; +import { emailValidate } from 'utils/validate'; +export class Update extends ModalAction { + init() { + this.store = globalDNSZonesStore; + } + + static id = 'update-dns-zone'; + + static title = t('Update Zone'); + + get name() { + return t('Update Zone'); + } + + static policy = 'get_images'; + + static allowed() { + return Promise.resolve(true); + } + + get defaultValue() { + + const { name, description, email, ttl, type } = this.props.item; + + return { + name: name, + description: description, + email: email, + ttl: ttl, + type: type + } + } + + get formItems() { + return [ + { + name: 'name', + label: t('Name'), + type: 'input', + disabled: true + }, + { + name: 'description', + label: t('Description'), + type: 'textarea' + }, + { + name: 'email', + label: t('Email Address'), + type: 'input', + required: true, + validator: emailValidate, + }, + { + name: 'ttl', + label: t('TTL'), + type: 'input-number', + required: true + }, + { + name: 'type', + label: t('Type'), + type: 'select', + options: [ + { label: t('Primary'), value: 'PRIMARY' }, + { label: t('Secondary'), value: 'SECONDARY' }, + ], + disabled: true + }, + ] + } + + onSubmit = (values) => { + const { id } = this.item; + const { name, type, ...val } = values; + return this.store.update({ id: id }, val); + }; +} + +export default inject('rootStore')(observer(Update)); diff --git a/src/pages/network/containers/DNS/Zones/actions/index.jsx b/src/pages/network/containers/DNS/Zones/actions/index.jsx new file mode 100644 index 00000000..9c0e680a --- /dev/null +++ b/src/pages/network/containers/DNS/Zones/actions/index.jsx @@ -0,0 +1,36 @@ +// Copyright 2021 99cloud +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import Create from './Create'; +import Update from './Update'; +import Delete from './Delete'; +import CreateRecords from './Records/Create'; + +const actionConfigs = { + rowActions: { + firstAction: CreateRecords, + moreActions: [ + { + action: Update, + }, + { + action: Delete, + }, + ], + }, + primaryActions: [Create], + batchActions: [Delete] +}; + +export default actionConfigs; diff --git a/src/pages/network/containers/DNS/Zones/index.jsx b/src/pages/network/containers/DNS/Zones/index.jsx new file mode 100644 index 00000000..6a3924ab --- /dev/null +++ b/src/pages/network/containers/DNS/Zones/index.jsx @@ -0,0 +1,60 @@ +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import { observer, inject } from 'mobx-react'; +import Base from 'containers/List'; +import globalDNSZonesStore, { DNSZonesStore } from 'src/stores/designate/zones'; +import actionConfigs from './actions'; + +export class Zones extends Base { + init() { + this.store = globalDNSZonesStore; + this.downloadStore = new DNSZonesStore(); + } + + get policy() { + return 'get_images'; + } + + get name() { + return t('dns zones'); + } + + get actionConfigs() { + return actionConfigs; + } + + getColumns = () => [ + { + title: t('Name'), + dataIndex: 'name', + isHideable: true, + isLink: true, + routeName: 'dnsZonesDetail' + }, + { + title: t('Type'), + dataIndex: 'type', + isHideable: true, + sorter: false + }, + { + title: t('Status'), + dataIndex: 'status', + isHideable: true, + sorter: false, + }, + ] + +} + +export default inject('rootStore')(observer(Zones)); \ No newline at end of file diff --git a/src/pages/network/routes/index.js b/src/pages/network/routes/index.js index bda54af5..bdfaa3ed 100644 --- a/src/pages/network/routes/index.js +++ b/src/pages/network/routes/index.js @@ -40,6 +40,11 @@ import SecurityGroupDetail from '../containers/SecurityGroup/Detail'; import Certificate from '../containers/Certificate'; import CertificateDetailContainer from '../containers/Certificate/Detail/Container'; import CertificateDetailSecret from '../containers/Certificate/Detail/Secret'; +import Reverse from '../containers/DNS/Reverse'; +import ReverseDetail from '../containers/DNS/Reverse/Detail'; +import Zones from '../containers/DNS/Zones'; +import ZonesDetail from '../containers/DNS/Zones/Detail'; +import RecordSetDetail from '../containers/DNS/Zones/Detail/RecordSets/Detail'; const PATH = '/network'; export default [ @@ -244,6 +249,11 @@ export default [ component: SecurityGroupDetail, exact: true, }, + { path: `${PATH}/dns/zones`, component: Zones, exact: true }, + { path: `${PATH}/dns/zones/detail/:id`, component: ZonesDetail, exact: true }, + { path: `${PATH}/dns/zones/detail/:id/recordsets/:recordset_id`, component: RecordSetDetail, exact: true }, + { path: `${PATH}/dns/reverse`, component: Reverse, exact: true }, + { path: `${PATH}/dns/reverse/detail/:id`, component: ReverseDetail, exact: true }, { path: '*', component: E404 }, ], }, diff --git a/src/resources/dns/record.jsx b/src/resources/dns/record.jsx new file mode 100644 index 00000000..dd1eb6b1 --- /dev/null +++ b/src/resources/dns/record.jsx @@ -0,0 +1,110 @@ +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import React from 'react'; +import { DNS_RECORD_TYPE } from 'src/utils/dns-rrtype'; +import { ipValidate } from 'utils/validate'; +import { isString } from 'lodash'; + +export const dnsRRTypeList = () => { + return Object.keys(DNS_RECORD_TYPE) + .sort() + .map((item) => ({ + label: `${item} - ${DNS_RECORD_TYPE[item].name}`, + value: item, + })); +} + +export const typeChange = (value) => { + if (Object.keys(DNS_RECORD_TYPE).includes(value)) { + this.setState({ + nameExtra: `Exp:${DNS_RECORD_TYPE[value].nameExtra}`, + recordsExtra: isString(DNS_RECORD_TYPE[value].recordsExtra) + ? `Exp: ${DNS_RECORD_TYPE[value].recordsExtra}` + : '', + }); + } +}; + +export const getRecordSetFormItem = (self, currentFormValue) => { + return [ + { + name: 'type', + label: t('Type'), + type: 'select', + options: dnsRRTypeList(), + onChange: (value) => { + if (Object.keys(DNS_RECORD_TYPE).includes(value)) { + self.setState({ + nameExtra: `Exp:${DNS_RECORD_TYPE[value].nameExtra}`, + recordsExtra: isString(DNS_RECORD_TYPE[value].recordsExtra) + ? `Exp: ${DNS_RECORD_TYPE[value].recordsExtra}` + : '', + }); + } + }, + required: true, + }, + { + name: 'name', + label: t('Name'), + type: 'input', + required: true, + tip: () => ( +
+ ), + extra: ( +
+ ), + }, + { + name: 'description', + label: t('Description'), + type: 'textarea', + }, + { + name: 'ttl', + label: t('TTL'), + type: 'input-number', + required: true, + }, + { + name: 'records', + label: t('Records'), + type: 'add-select', + isInput: true, + required: true, + width: 280, + tip: () => ( +
+ ), + extra: ( +
+ ), + validator: (rule, value) => { + const { type } = currentFormValue; + const { isIPv4, isIpv6 } = ipValidate; + + return new Promise((resolve) => { + value && value.forEach((item) => { + if (type === 'A' && !isIPv4(item.value)) { + throw new Error(t('Please enter a valid IPv4 value.')); + } else if (type === 'AAAA' && !isIpv6(item.value)) + throw new Error(t('Please enter a valid IPv6 value.')); + }); + + resolve(); + }); + } + }, + ]; +}; \ No newline at end of file diff --git a/src/stores/designate/recordSets.js b/src/stores/designate/recordSets.js new file mode 100644 index 00000000..667ee1a2 --- /dev/null +++ b/src/stores/designate/recordSets.js @@ -0,0 +1,51 @@ +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import client from 'client'; +import { action } from 'mobx'; +import Base from 'stores/base'; + +export class DNSRecordSetsStore extends Base { + + get client() { + return client.designate.zones.recordsets; + } + + get isSubResource() { + return true; + } + + detailFetchByClient(resourceParams) { + const { id, recordset_id } = resourceParams; + return this.client.show(id, recordset_id); + } + + get paramsFunc() { + return (params) => { + const { id, ...rest } = params; + return rest; + }; + } + + @action + delete = ({ zone_id, recordset_id }) => this.submitting(this.client.delete(zone_id, recordset_id)); + + @action + update = (zone_id, recordset_id, body) => this.submitting(this.client.update(zone_id, recordset_id, body)); + + @action + create = ({ id }, body) => this.submitting(this.client.create(id, body)); + +} + +const globalDNSRecordSetsStore = new DNSRecordSetsStore(); +export default globalDNSRecordSetsStore; \ No newline at end of file diff --git a/src/stores/designate/reverse.js b/src/stores/designate/reverse.js new file mode 100644 index 00000000..d36a723c --- /dev/null +++ b/src/stores/designate/reverse.js @@ -0,0 +1,49 @@ +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import { action } from 'mobx'; +import client from 'client'; +import Base from 'stores/base'; + +export class ReverseStore extends Base { + + get client() { + return client.designate.reverse.floatingips; + } + + get reverseClient() { + return client.designate.reverse; + } + + get isSubResource() { + return true; + } + + detailFetchByClient(resourceParams) { + const { id } = resourceParams; + return this.reverseClient.reverseDetail(id); + } + + get paramsFunc() { + return () => { }; + } + + @action + set = ({ id }, body) => this.submitting(this.reverseClient.setReverse(id, body)); + + @action + unset = ({ id }, body) => this.submitting(this.reverseClient.unsetReverse(id, body)); + +} + +const globalReverseStore = new ReverseStore(); +export default globalReverseStore; \ No newline at end of file diff --git a/src/stores/designate/zones.js b/src/stores/designate/zones.js new file mode 100644 index 00000000..109fc624 --- /dev/null +++ b/src/stores/designate/zones.js @@ -0,0 +1,37 @@ +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import { action } from 'mobx'; +import client from 'client'; +import Base from 'stores/base'; + +export class DNSZonesStore extends Base { + + get client() { + return client.designate.zones; + } + + @action + async create(newbody) { + return this.submitting(this.client.create(newbody)); + } + + @action + delete = ({ id }) => this.submitting(this.client.delete(id)); + + @action + update = ({ id }, body) => this.submitting(this.client.patch(id, body)); + +} + +const globalDNSZonesStore = new DNSZonesStore(); +export default globalDNSZonesStore; \ No newline at end of file diff --git a/src/utils/dns-rrtype.js b/src/utils/dns-rrtype.js new file mode 100644 index 00000000..e687b8bc --- /dev/null +++ b/src/utils/dns-rrtype.js @@ -0,0 +1,46 @@ +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +export const DNS_RECORD_TYPE = { + A: { name: t('Address Record'), nameExtra: 'example.com', recordsExtra: '192.168.1.1' }, + AAAA: { name: t('IPv6 Address Record'), nameExtra: 'example.com', recordsExtra: '2001:db8:3333:4444:5555:6666:7777:8888' }, + CAA: { + name: t('Certificate Authority Authorization Record'), + nameExtra: 'example.com', + recordsExtra: '0 iodef mailto:security@example.com
  • 0: is flag. An unsigned integer between 0-255.
  • iodef: An ASCII string that represents the identifier of the property represented by the record.
    Available Tags: "issue", "issuewild", "iodef"
  • mailto:security@example.com: The value associated with the tag.
' + }, + CNAME: { name: t('Canonical Name Record'), nameExtra: 'first.example.com', recordsExtra: 'other-example.com' }, + MX: { name: t('Mail Exchange Record'), nameExtra: 'example.com', recordsExtra: '10 mail.example.com
  • 10: Priority
  • mail.example.com: Value
' }, + NS: { name: t('Name Server'), nameExtra: 'example.com', recordsExtra: 'ns1.example.com' }, + PTR: { name: t('Pointer Record'), nameExtra: 'example.com', recordsExtra: '1.1.0.192.in-addr.arpa.' }, + SOA: { + name: t('Start Of Authority'), + nameExtra: 'example.com', + recordsExtra: 'ns1.example.com admin.example.com 2013022001 86400 7200 604800 300
  • The primary name server for the domain, which is ns1.example.com or the first name server in the vanity name server list.
  • The responsible party for the domain: admin.example.com.
  • A timestamp that changes whenever you update your domain.
  • The number of seconds before the zone should be refreshed.
  • The number of seconds before a failed refresh should be retried.
  • The upper limit in seconds before a zone is considered no longer authoritative.
  • The negative result TTL (for example, how long a resolver should consider a negative result for a subdomain to be valid before retrying).
', + }, + SPF: { + name: t('Sender Policy Framework'), + nameExtra: 'example.com', + recordsExtra: '"v=spf1 ipv4=192.1.1.1 include:examplesender.email +all"
  • v=spf1: Tells the server that this contains an SPF record. Every SPF record must begin with this string.
  • Guest List: Then comes the “guest list” portion of the SPF record or the list of authorized IP addresses. In this example, the SPF record is telling the server that ip4=192.0.2.0 and ip4=192.0.2.1 are authorized to send emails on behalf of the domain.
  • include:examplesender.net: is an example of the include tag, which tells the server what third-party organizations are authorized to send emails on behalf of the domain. This tag signals that the content of the SPF record for the included domain (examplesender.net) should be checked and the IP addresses it contains should also be considered authorized. Multiple domains can be included within an SPF record but this tag will only work for valid domains.
  • -all: Tells, the server that addresses not listed in the SPF record are not authorized to send emails and should be rejected.
' + }, + SRV: { + name: t('Service Locator'), + nameExtra: '_sip._tcp.example.com.
  • _sip: represents the name of the service.
  • _tcp: represents the protocol of the service, this is usually either TCP or UDP.
  • example.com: represents the domain in which this record is for.
', + recordsExtra: '10 0 5060 server1.example.com.
  • "10" is the priority of the record. The lower the value, the higher the priority.
  • 20 is the weight of the record. This is the weight of which this record has a chance to be used when there are multiple matching SRV records of the same priority.
  • 5060 is the port of the record. This specifies the port on which the application or service is running.
  • server1.example.com is the target of the record. This specifies the domain of the application or service the record is for. SRV records must specify a target which is either an A record or AAAA record, and may not use CNAME records.
' + }, + SSHFP: { + name: t('SSH Public Key Fingerprint'), + nameExtra: 'example.com', + recordsExtra: '4 2 123456789abcdef67890123456789abcdef67890123456789abcdef123456789
  • 4 is Algorithm: Algorithm (0: reserved; 1: RSA; 2: DSA, 3: ECDSA; 4: Ed25519; 6:Ed448)
  • 2 is Type: Algorithm used to hash the public key (0: reserved; 1: SHA-1; 2: SHA-256)
  • Last parameter is Fingerprint: Hexadecimal representation of the hash result, as text
' + }, + TXT: { name: t('Text Record'), nameExtra: 'example.com' }, +}; \ No newline at end of file