Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion www/webapp/src/components/Field/RRSetType.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
:label="label"
:disabled="disabled || readonly"
:error-messages="errorMessages"
hint="You can also enter other types. For a full list, check the documentation."
:hint="hint"
:placeholder="placeholder"
:persistent-hint="!readonly"
:value="value"
:items="types"
Expand Down Expand Up @@ -33,6 +34,14 @@ export default {
type: Boolean,
required: false,
},
hint: {
type: String,
default: 'You can also enter other types. For a full list, check the documentation.',
},
placeholder: {
type: String,
default: undefined,
},
required: {
type: Boolean,
default: false,
Expand Down Expand Up @@ -63,6 +72,7 @@ export default {
methods: {
input(event) {
this.$emit('input', event);
this.$emit('dirty');
},
},
};
Expand Down
6 changes: 6 additions & 0 deletions www/webapp/src/router/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,12 @@ const routes = [
component: () => import('@/views/CrudListToken.vue'),
meta: {guest: false},
},
{
path: '/tokens/:tokenId/policies',
name: 'tokenPolicies',
component: () => import('@/views/CrudListTokenPolicy.vue'),
meta: {guest: false},
},
{
path: '/domains',
name: 'domains',
Expand Down
13 changes: 13 additions & 0 deletions www/webapp/src/views/CrudListToken.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,23 @@ import GenericCheckbox from "@/components/Field/GenericCheckbox.vue";
import RecordList from "@/components/Field/RecordList.vue";
import GenericSwitchbox from "@/components/Field/GenericSwitchbox.vue";
import TimeAgo from "@/components/Field/TimeAgo.vue";
import {mdiShieldLock} from "@mdi/js";

export default {
name: 'CrudListToken',
extends: CrudList,
computed: {
actions() {
return {
policies: {
go: (item) => this.$router.push({ name: 'tokenPolicies', params: { tokenId: item.id }, query: item.name ? { name: item.name } : {} }),
if: this.showAdvanced,
icon: mdiShieldLock,
tooltip: 'Policies',
},
};
},
},
data() {
return {
creatable: true,
Expand Down
106 changes: 106 additions & 0 deletions www/webapp/src/views/CrudListTokenPolicy.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
<script>
import CrudList from './CrudList.vue';
import GenericText from '@/components/Field/GenericText.vue';
import GenericSwitchbox from '@/components/Field/GenericSwitchbox.vue';

export default {
name: 'CrudListTokenPolicy',
extends: CrudList,
data() {
const self = this;
return {
creatable: true,
updatable: true,
destroyable: true,
headlines: {
table: `Policies for token ${self.$route.query.name ? `${self.$route.query.name} (${self.$route.params.tokenId})` : self.$route.params.tokenId}`,
create: 'Add Policy',
destroy: 'Delete Policy',
},
texts: {
banner: () => (
'Policies restrict DNS write access for this token. A default policy (all fields empty) must exist before specific policies can be added. ' +
'<a href="https://desec.readthedocs.io/en/latest/auth/tokens.html#token-scoping-policies" target="_blank">Documentation</a>'
),
create: () => 'Add a policy. Leave domain, subname, and type empty to create the default (deny-all) policy.',
destroy: p => {
const domain = p.domain || 'any domain';
const subname = p.subname || 'any subname';
const type = p.type || 'any type';
const write = p.perm_write ? 'write allowed' : 'write denied';
return `Delete policy (${domain}, ${subname}, ${type}, ${write})?`;
},
},
columns: {
domain: {
name: 'item.domain',
text: 'Domain',
align: 'left',
sortable: true,
value: 'domain',
readonly: false,
required: false,
writeOnCreate: true,
datatype: GenericText.name,
searchable: true,
fieldProps: () => ({ placeholder: '(any domain)', hint: 'Leave empty to match any domain.' }),
},
subname: {
name: 'item.subname',
text: 'Subname',
align: 'left',
sortable: true,
value: 'subname',
readonly: false,
required: false,
writeOnCreate: true,
datatype: GenericText.name,
searchable: true,
fieldProps: () => ({ placeholder: '(any subname)', hint: 'Leave empty to match any subname.' }),
},
type: {
name: 'item.type',
text: 'Type',
align: 'left',
sortable: true,
value: 'type',
readonly: false,
required: false,
writeOnCreate: true,
datatype: 'RRSetType',
searchable: true,
fieldProps: (item) => ({ value: item.type || '', placeholder: '(any type)', hint: 'Leave empty to match any record type. You can also enter types not listed.' }),
},
perm_write: {
name: 'item.perm_write',
text: 'Write',
align: 'left',
sortable: true,
value: 'perm_write',
readonly: false,
writeOnCreate: true,
datatype: GenericSwitchbox.name,
searchable: false,
},
},
paths: {
list: 'auth/tokens/::{tokenId}/policies/rrsets/',
create: 'auth/tokens/::{tokenId}/policies/rrsets/',
delete: 'auth/tokens/::{tokenId}/policies/rrsets/:{id}/',
update: 'auth/tokens/::{tokenId}/policies/rrsets/:{id}/',
},
itemDefaults: () => ({ domain: '', subname: '', type: '', perm_write: false }),
precreate() {
this.createDialogItem.domain = this.createDialogItem.domain || null;
this.createDialogItem.subname = this.createDialogItem.subname || null;
this.createDialogItem.type = this.createDialogItem.type || null;
},
preupdate(item) {
item.domain = item.domain || null;
item.subname = item.subname || null;
item.type = item.type || null;
},
};
},
};
</script>