Disable types that are not compatible with a given source

This commit is contained in:
nemunaire 2020-07-26 20:54:53 +02:00
parent 0945bf2ecb
commit e627e6b5ea
18 changed files with 157 additions and 8 deletions

View File

@ -53,6 +53,8 @@ func init() {
router.DELETE("/api/sources/:sid", apiAuthHandler(sourceMetaHandler(deleteSource)))
router.GET("/api/sources/:sid/domains", apiAuthHandler(sourceHandler(getDomainsHostedBySource)))
router.GET("/api/sources/:sid/available_resource_types", apiAuthHandler(sourceHandler(getAvailableResourceTypes)))
}
func getSources(_ *config.Options, req *RequestResources, body io.Reader) Response {
@ -224,3 +226,17 @@ func getDomainsHostedBySource(_ *config.Options, req *RequestResources, body io.
}
}
}
func getAvailableResourceTypes(_ *config.Options, req *RequestResources, body io.Reader) Response {
lrt, ok := req.Source.Source.(sources.LimitedResourceTypesSource)
if !ok {
// Return all types known to be supported by happyDNS
return APIResponse{
response: sources.DefaultAvailableTypes,
}
} else {
return APIResponse{
response: lrt.ListAvailableTypes(),
}
}
}

View File

@ -137,6 +137,7 @@
<script>
import DomainCompare from '@/mixins/domainCompare'
import ServiceSpecsApi from '@/services/ServiceSpecsApi'
import SourcesApi from '@/services/SourcesApi'
import ZoneApi from '@/services/ZoneApi'
export default {
@ -166,6 +167,7 @@ export default {
data: function () {
return {
availableResourceTypes: [],
deleteServiceInProgress: false,
hideDomain: {},
modal: null,
@ -224,6 +226,16 @@ export default {
const svc = this.services[type]
if (svc.restrictions) {
// Handle NeedTypes restriction: hosting provider need to support given types.
if (svc.restrictions.needTypes) {
for (const k in svc.restrictions.needTypes) {
if (this.availableResourceTypes.indexOf(svc.restrictions.needTypes[k]) < 0) {
ret[type] = 'is not available on this domain name hosting provider.'
continue
}
}
}
// Handle Alone restriction: only nearAlone are allowed.
if (svc.restrictions.alone && this.myServices.services[this.modal.dn]) {
var found = false
@ -307,7 +319,7 @@ export default {
},
isLoading () {
return this.myServices == null && this.zoneId === undefined && this.services === {}
return this.myServices == null && this.availableResourceTypes.length > 0 && this.zoneId === undefined && this.services === {}
},
sortedDomains () {
@ -338,6 +350,13 @@ export default {
.then(
(response) => (this.services = response.data)
)
SourcesApi.getAvailableResourceTypes(this.domain.id_source)
.then(
(response) => {
this.availableResourceTypes = response.data
}
)
},
methods: {

View File

@ -213,6 +213,7 @@
"update": "Update service"
},
"source": {
"available-types": "Resources Types available",
"delete": "@:common.delete this @:source.kind",
"find": "Can't find your @:source.kind here?",
"name-your": "Name your @:source.kind",

View File

@ -36,6 +36,10 @@ export default {
return Api().get('/api/sources/' + encodeURIComponent(srcId))
},
getAvailableResourceTypes (srcId) {
return Api().get('/api/sources/' + encodeURIComponent(srcId) + '/available_resource_types')
},
getSources () {
return Api().get('/api/sources')
},

View File

@ -56,12 +56,21 @@
<span class="text-primary">{{ spec.label }}</span><br>
<strong>{{ source.Source[spec.id] }}</strong>
</p>
<p v-if="availableTypes.length">
<span class="text-primary">{{ $t('source.available-types') }}</span>
<ul style="column-count: 4;">
<li v-for="(t, i) in availableTypes" :key="i">
{{ t | nsrrtype }}
</li>
</ul>
</p>
</div>
</div>
</template>
<script>
import axios from 'axios'
import SourcesApi from '@/services/SourcesApi'
import SourceSpecsApi from '@/services/SourceSpecsApi'
export default {
@ -74,6 +83,7 @@ export default {
data: function () {
return {
availableTypes: [],
source: null,
source_specs: null,
specs: null
@ -93,8 +103,7 @@ export default {
},
mounted () {
axios
.get('/api/source_specs')
SourceSpecsApi.getSourceSpecs()
.then(response => {
this.specs = response.data
})
@ -108,17 +117,20 @@ export default {
if (this.domain === undefined || this.domain.id_source === undefined) {
return
}
axios
.get('/api/sources/' + encodeURIComponent(this.domain.id_source))
SourcesApi.getSource(this.domain.id_source)
.then(
(response) => {
this.source = response.data
axios
.get('/api/source_specs/' + encodeURIComponent(this.source._srctype))
SourceSpecsApi.getSourceSpecs(this.source._srctype)
.then(response => (
this.source_specs = response.data
))
SourcesApi.getAvailableResourceTypes(this.domain.id_source)
.then(response => (
this.availableTypes = response.data
))
})
}
}

View File

@ -133,6 +133,9 @@ func init() {
},
Restrictions: ServiceRestrictions{
NearAlone: true,
NeedTypes: []uint16{
dns.TypeCNAME,
},
},
},
99999997,
@ -151,6 +154,9 @@ func init() {
Restrictions: ServiceRestrictions{
Alone: true,
Single: true,
NeedTypes: []uint16{
dns.TypeCNAME,
},
},
},
99999998,

View File

@ -152,6 +152,9 @@ func init() {
Leaf: true,
ExclusiveRR: []string{"svcs.Origin"},
Single: true,
NeedTypes: []uint16{
dns.TypeNS,
},
},
},
1,

View File

@ -396,6 +396,9 @@ func init() {
Tabs: true,
Restrictions: ServiceRestrictions{
Single: true,
NeedTypes: []uint16{
dns.TypeMX,
},
},
},
1,

View File

@ -53,6 +53,9 @@ type ServiceRestrictions struct {
// NearAlone allows a service to be present along with Alone restricted services (eg. services that will create sub-subdomain from their given subdomain).
NearAlone bool `json:"nearAlone,omitempty"`
// NeedTypes restricts the service to sources that are compatibles with ALL the given types.
NeedTypes []uint16 `json:"needTypes,omitempty"`
// RootOnly restricts the service to be present at the root of the domain only.
RootOnly bool `json:"rootOnly,omitempty"`

View File

@ -134,6 +134,9 @@ func init() {
Restrictions: ServiceRestrictions{
NearAlone: true,
Single: true,
NeedTypes: []uint16{
dns.TypeSRV,
},
},
},
1,

View File

@ -194,6 +194,9 @@ func init() {
},
Restrictions: ServiceRestrictions{
NearAlone: true,
NeedTypes: []uint16{
dns.TypeOPENPGPKEY,
},
},
},
1,
@ -211,6 +214,9 @@ func init() {
},
Restrictions: ServiceRestrictions{
NearAlone: true,
NeedTypes: []uint16{
dns.TypeSMIMEA,
},
},
},
1,

View File

@ -145,6 +145,9 @@ func init() {
Restrictions: ServiceRestrictions{
RootOnly: true,
Single: true,
NeedTypes: []uint16{
dns.TypeSOA,
},
},
},
0,

View File

@ -157,6 +157,9 @@ func init() {
},
Restrictions: ServiceRestrictions{
NearAlone: true,
NeedTypes: []uint16{
dns.TypeSRV,
},
},
},
99999,

View File

@ -181,6 +181,9 @@ func init() {
Restrictions: ServiceRestrictions{
NearAlone: true,
Single: true,
NeedTypes: []uint16{
dns.TypeTLSA,
},
},
},
100,

View File

@ -160,6 +160,9 @@ func init() {
Restrictions: ServiceRestrictions{
NearAlone: true,
Single: true,
NeedTypes: []uint16{
dns.TypeSRV,
},
},
},
1,

View File

@ -102,6 +102,21 @@ func doTxt(req *http.Request) (txt []byte, err error) {
return
}
func (s *AlwaysdataAPI) ListAvailableTypes() (types []uint16) {
return []uint16{
dns.TypeA,
dns.TypeAAAA,
dns.TypeCAA,
dns.TypeCNAME,
dns.TypeMX,
dns.TypeNS,
dns.TypePTR,
dns.TypeSOA,
dns.TypeSRV,
dns.TypeTXT,
}
}
type alwaysdataInfo struct {
Id int64 `json:"id"`
Name string `json:"name"`

View File

@ -95,6 +95,30 @@ func doJSON(req *http.Request, v interface{}) (err error) {
}
func (s *GandiAPI) ListAvailableTypes() (types []uint16) {
types = []uint16{
dns.TypeA,
dns.TypeAAAA,
//dns.TypeALIAS,
dns.TypeCAA,
dns.TypeCDS,
dns.TypeCNAME,
dns.TypeDNAME,
dns.TypeDS,
dns.TypeKEY,
dns.TypeLOC,
dns.TypeMX,
dns.TypeNS,
dns.TypeOPENPGPKEY,
dns.TypePTR,
dns.TypeSPF,
dns.TypeSOA,
dns.TypeSRV,
dns.TypeSSHFP,
dns.TypeTLSA,
dns.TypeTXT,
//dns.TypeWKS,
}
req, err := s.newRequest("GET", "https://api.gandi.net/v5/livedns/dns/rrtypes", nil)
if err != nil {
return
@ -107,6 +131,7 @@ func (s *GandiAPI) ListAvailableTypes() (types []uint16) {
return
}
types = []uint16{}
for _, r := range rrtypes {
if t, ok := dns.StringToType[r]; ok {
types = append(types, t)

View File

@ -36,6 +36,9 @@ import (
"git.happydns.org/happydns/config"
"git.happydns.org/happydns/model"
"git.happydns.org/happydns/utils"
"github.com/miekg/dns"
)
// SourceInfos describes the purpose of a user usable source.
@ -53,6 +56,12 @@ type ListDomainsSource interface {
ListDomains() ([]string, error)
}
type LimitedResourceTypesSource interface {
ListAvailableTypes() []uint16
}
var DefaultAvailableTypes []uint16
// CustomForm is used to create a form with several steps when creating or updating source's settings.
type CustomForm struct {
// BeforeText is the text presented before the fields.
@ -116,6 +125,10 @@ func GetSourceCapabilities(src happydns.Source) (caps []string) {
caps = append(caps, "CustomSettingsForm")
}
if _, ok := src.(LimitedResourceTypesSource); ok {
caps = append(caps, "LimitedResourceTypes")
}
return
}
@ -131,3 +144,11 @@ func GenDefaultSettingsForm(src happydns.Source) *CustomForm {
PreviousButtonState: -1,
}
}
func init() {
for t := range dns.TypeToRR {
if !utils.IsDNSSECType(t) {
DefaultAvailableTypes = append(DefaultAvailableTypes, t)
}
}
}