Add restrictions on services

This commit is contained in:
nemunaire 2020-07-06 11:07:37 +02:00
parent 824108836d
commit 4481fc4923
12 changed files with 192 additions and 5 deletions

View File

@ -53,13 +53,19 @@
Fill the information for the {{ services[modal.svcSelected].name }} at <span class="text-monospace">{{ modal.dn | fqdn(domain.domain) }}</span>:
</p>
<b-list-group v-if="modal.step === 1" class="mb-2">
<b-list-group-item v-for="(svc, idx) in services" :key="idx" :active="modal.svcSelected === idx" button @click="modal.svcSelected = idx">
<b-list-group-item v-for="(svc, idx) in availableNewServices" :key="idx" :active="modal.svcSelected === idx" button @click="modal.svcSelected = idx">
{{ svc.name }}
<small class="text-muted">{{ svc.description }}</small>
<b-badge v-for="(categorie, idcat) in svc.categories" :key="idcat" variant="gray" class="float-right ml-1">
{{ categorie }}
</b-badge>
</b-list-group-item>
<b-list-group-item v-for="(svc, idx) in disabledNewServices" :key="idx" :active="modal.svcSelected === idx" disabled @click="modal.svcSelected = idx">
<span :title="svc.description">{{ svc.name }}</span> <small class="font-italic text-danger">{{ filteredNewServices[idx] }}</small>
<b-badge v-for="(categorie, idcat) in svc.categories" :key="idcat" variant="gray" class="float-right ml-1">
{{ categorie }}
</b-badge>
</b-list-group-item>
</b-list-group>
<h-resource-value v-else-if="modal.step === 2" v-model="modal.svcData" edit :services="services" :type="modal.svcSelected" @input="modal.svcData = $event" />
</form>
@ -139,6 +145,119 @@ export default {
return ret
},
availableNewServices () {
var ret = {}
for (const type in this.services) {
if (this.filteredNewServices[type] == null) {
ret[type] = this.services[type]
}
}
return ret
},
disabledNewServices () {
var ret = {}
for (const type in this.services) {
if (this.filteredNewServices[type] != null) {
ret[type] = this.services[type]
}
}
return ret
},
filteredNewServices () {
var ret = {}
for (const type in this.services) {
const svc = this.services[type]
if (svc.restrictions) {
// Handle Alone restriction: only nearAlone are allowed.
if (svc.restrictions.alone && this.myServices.services[this.modal.dn]) {
var found = false
for (const k in this.myServices.services[this.modal.dn]) {
const s = this.myServices.services[this.modal.dn][k]
if (s._svctype !== type && this.services[s._svctype].restrictions && !this.services[s._svctype].restrictions.nearAlone) {
found = true
break
}
}
if (found) {
ret[type] = 'has to be the only one in the subdomain.'
continue
}
}
// Handle Exclusive restriction: service can't be present along with another listed one.
if (svc.restrictions.exclusive && this.myServices.services[this.modal.dn]) {
found = null
for (const k in this.myServices.services[this.modal.dn]) {
const s = this.myServices.services[this.modal.dn][k]
for (const i in svc.restrictions.exclusive) {
if (s._svctype === svc.restrictions.exclusive[i]) {
found = s._svctype
break
}
}
}
if (found) {
ret[type] = 'cannot be present along with ' + this.services[found].name + '.'
continue
}
}
// Handle rootOnly restriction.
if (svc.restrictions.rootOnly && this.modal.dn !== '') {
ret[type] = 'can only be present at the root of your domain.'
continue
}
// Handle Single restriction: only one instance of the service per subdomain.
if (svc.restrictions.single && this.myServices.services[this.modal.dn]) {
found = false
for (const k in this.myServices.services[this.modal.dn]) {
const s = this.myServices.services[this.modal.dn][k]
if (s._svctype === type) {
found = true
break
}
}
if (found) {
ret[type] = 'can only be present once per subdomain.'
continue
}
}
// Handle presence of Alone and Leaf service in subdomain already.
var oneAlone = null
var oneLeaf = null
for (const k in this.myServices.services[this.modal.dn]) {
const s = this.myServices.services[this.modal.dn][k]
if (this.services[s._svctype].restrictions && this.services[s._svctype].restrictions.alone) {
oneAlone = s._svctype
}
if (this.services[s._svctype].restrictions && this.services[s._svctype].restrictions.leaf) {
oneLeaf = s._svctype
}
}
if (oneAlone && oneAlone !== type && !svc.restrictions.nearAlone) {
ret[type] = 'cannot be present along with ' + this.services[oneAlone].name + ', that requires to be the only one in this subdomain.'
continue
}
if (oneLeaf && oneLeaf !== type && !svc.restrictions.glue) {
ret[type] = 'cannot be present along with ' + this.services[oneAlone].name + ', that requires to don\'t have subdomains.'
continue
}
}
}
return ret
},
isLoading () {
return this.myServices == null && this.zoneId === undefined && this.services == null
},

View File

@ -131,6 +131,9 @@ func init() {
Categories: []string{
"internal",
},
Restrictions: ServiceRestrictions{
NearAlone: true,
},
},
99999997,
)
@ -145,6 +148,10 @@ func init() {
Categories: []string{
"internal",
},
Restrictions: ServiceRestrictions{
Alone: true,
Single: true,
},
},
99999998,
)

View File

@ -147,6 +147,12 @@ func init() {
Categories: []string{
"internal",
},
Restrictions: ServiceRestrictions{
Alone: true,
Leaf: true,
ExclusiveRR: []string{"svcs.Origin"},
Single: true,
},
},
1,
)

View File

@ -383,6 +383,9 @@ func init() {
"email",
},
Tabs: true,
Restrictions: ServiceRestrictions{
Single: true,
},
},
1,
)

View File

@ -37,11 +37,35 @@ import (
"git.happydns.org/happydns/model"
)
type ServiceRestrictions struct {
// Alone restricts the service to be the only one for a given subdomain.
Alone bool `json:"alone,omitempty"`
// ExclusiveRR restricts the service to be present along with others given types.
ExclusiveRR []string `json:"exclusive,omitempty"`
// GLUE allows a service to be present under Leaf, as GLUE record.
GLUE bool `json:"glue,omitempty"`
// Leaf restricts the creation of subdomains under this kind of service (blocks NearAlone).
Leaf bool `json:"leaf,omitempty"`
// 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"`
// RootOnly restricts the service to be present at the root of the domain only.
RootOnly bool `json:"rootOnly,omitempty"`
// Single restricts the service to be present only once per subdomain.
Single bool `json:"single,omitempty"`
}
type ServiceInfos struct {
Name string `json:"name"`
Description string `json:"description"`
Categories []string `json:"categories"`
Tabs bool `json:"tabs,omitempty"`
Name string `json:"name"`
Description string `json:"description"`
Categories []string `json:"categories"`
Tabs bool `json:"tabs,omitempty"`
Restrictions ServiceRestrictions `json:"restrictions,omitempty"`
}
type serviceCombined struct {

View File

@ -130,6 +130,10 @@ func init() {
Categories: []string{
"im",
},
Restrictions: ServiceRestrictions{
NearAlone: true,
Single: true,
},
},
1,
)

View File

@ -191,6 +191,9 @@ func init() {
Categories: []string{
"email",
},
Restrictions: ServiceRestrictions{
NearAlone: true,
},
},
1,
)
@ -205,6 +208,9 @@ func init() {
Categories: []string{
"email",
},
Restrictions: ServiceRestrictions{
NearAlone: true,
},
},
1,
)

View File

@ -142,6 +142,10 @@ func init() {
Categories: []string{
"internal",
},
Restrictions: ServiceRestrictions{
RootOnly: true,
Single: true,
},
},
0,
)

View File

@ -174,6 +174,9 @@ func init() {
Categories: []string{
"server",
},
Restrictions: ServiceRestrictions{
GLUE: true,
},
},
100,
)

View File

@ -155,6 +155,9 @@ func init() {
Categories: []string{
"service",
},
Restrictions: ServiceRestrictions{
NearAlone: true,
},
},
99999,
)

View File

@ -177,6 +177,10 @@ func init() {
Categories: []string{
"tls",
},
Restrictions: ServiceRestrictions{
NearAlone: true,
Single: true,
},
},
100,
)

View File

@ -156,6 +156,10 @@ func init() {
Categories: []string{
"im",
},
Restrictions: ServiceRestrictions{
NearAlone: true,
Single: true,
},
},
1,
)