mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2025-02-25 18:55:28 -06:00
Modifying DNS UI to benefit from new DNS API
DNS UI was modified to offer structured way of defining DNS records. https://fedorahosted.org/freeipa/ticket/2208
This commit is contained in:
parent
71f9343480
commit
1f3d8003f7
1316
install/ui/dns.js
1316
install/ui/dns.js
File diff suppressed because it is too large
Load Diff
@ -101,7 +101,7 @@ IPA.field = function(spec) {
|
|||||||
|
|
||||||
that.validate_required = function() {
|
that.validate_required = function() {
|
||||||
var values = that.save();
|
var values = that.save();
|
||||||
if (that.is_empty(values) && that.is_required()) {
|
if (that.is_empty(values) && that.is_required() && that.enabled) {
|
||||||
that.valid = false;
|
that.valid = false;
|
||||||
that.show_error(IPA.messages.widget.validation.required);
|
that.show_error(IPA.messages.widget.validation.required);
|
||||||
return false;
|
return false;
|
||||||
@ -118,6 +118,8 @@ IPA.field = function(spec) {
|
|||||||
that.hide_error();
|
that.hide_error();
|
||||||
that.valid = true;
|
that.valid = true;
|
||||||
|
|
||||||
|
if (!that.enabled) return that.valid;
|
||||||
|
|
||||||
var values = that.save();
|
var values = that.save();
|
||||||
|
|
||||||
if (that.is_empty(values)) {
|
if (that.is_empty(values)) {
|
||||||
|
@ -1456,3 +1456,15 @@ div.entity[name=hbactest] div.facet[name=run_test] .hbac-test-content {
|
|||||||
.hbac-test-navigation-buttons {
|
.hbac-test-navigation-buttons {
|
||||||
float: right;
|
float: right;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ---- DNS ---- */
|
||||||
|
|
||||||
|
.dnstype-table div[name=position] {
|
||||||
|
|
||||||
|
padding-right: 9px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dnstype-table td {
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
@ -1130,6 +1130,22 @@ IPA.limit_text = function(value, max_length) {
|
|||||||
return limited_text;
|
return limited_text;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
IPA.create_options = function(labels, values) {
|
||||||
|
|
||||||
|
if(!values) values = labels;
|
||||||
|
|
||||||
|
var options = [];
|
||||||
|
|
||||||
|
for (var i=0; i<labels.length; i++) {
|
||||||
|
options.push({
|
||||||
|
label: labels[i],
|
||||||
|
value: values[i]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return options;
|
||||||
|
};
|
||||||
|
|
||||||
IPA.config = {
|
IPA.config = {
|
||||||
default_priority: 500
|
default_priority: 500
|
||||||
};
|
};
|
||||||
|
@ -1,14 +1,65 @@
|
|||||||
{
|
{
|
||||||
"error": null,
|
"error": null,
|
||||||
"id": 12,
|
"id": null,
|
||||||
"result": {
|
"result": {
|
||||||
"result": {
|
"result": {
|
||||||
"arecord": [
|
"dn": "idnsname=my,idnsname=example.com,cn=dns,dc=dev,dc=example,dc=com",
|
||||||
"1.2.3.4"
|
"dnsrecords": [
|
||||||
|
{
|
||||||
|
"a_part_ip_address": "10.10.10.11",
|
||||||
|
"dnsdata": "10.10.10.11",
|
||||||
|
"dnstype": "A"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"a_part_ip_address": "10.10.10.12",
|
||||||
|
"dnsdata": "10.10.10.12",
|
||||||
|
"dnstype": "A"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"a_part_ip_address": "10.10.10.13",
|
||||||
|
"dnsdata": "10.10.10.13",
|
||||||
|
"dnstype": "A"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"a_part_ip_address": "10.10.10.14",
|
||||||
|
"dnsdata": "10.10.10.14",
|
||||||
|
"dnstype": "A"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"a_part_ip_address": "10.10.10.16",
|
||||||
|
"dnsdata": "10.10.10.16",
|
||||||
|
"dnstype": "A"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"a_part_ip_address": "10.10.10.15",
|
||||||
|
"dnsdata": "10.10.10.15",
|
||||||
|
"dnstype": "A"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"dnsdata": "10 abc",
|
||||||
|
"dnstype": "KX",
|
||||||
|
"kx_part_exchanger": "abc",
|
||||||
|
"kx_part_preference": "10"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"dnsdata": "11 foo",
|
||||||
|
"dnstype": "KX",
|
||||||
|
"kx_part_exchanger": "foo",
|
||||||
|
"kx_part_preference": "11"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"dnsdata": "data",
|
||||||
|
"dnstype": "TXT",
|
||||||
|
"txt_part_data": "data"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"aaaa_part_ip_address": "::1:2:3:4",
|
||||||
|
"dnsdata": "::1:2:3:4",
|
||||||
|
"dnstype": "AAAA"
|
||||||
|
}
|
||||||
],
|
],
|
||||||
"dn": "idnsname=a4,idnsname=example.com,cn=dns,dc=example,dc=com",
|
|
||||||
"idnsname": [
|
"idnsname": [
|
||||||
"a4"
|
"my"
|
||||||
],
|
],
|
||||||
"objectclass": [
|
"objectclass": [
|
||||||
"top",
|
"top",
|
||||||
@ -16,6 +67,6 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"summary": null,
|
"summary": null,
|
||||||
"value": "a4"
|
"value": "my"
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,10 +1,62 @@
|
|||||||
{
|
{
|
||||||
"error": null,
|
"error": null,
|
||||||
|
"id": null,
|
||||||
"result": {
|
"result": {
|
||||||
|
"result": {
|
||||||
|
"dnsrecords": [
|
||||||
|
{
|
||||||
|
"a_part_ip_address": "10.10.10.11",
|
||||||
|
"dnsdata": "10.10.10.11",
|
||||||
|
"dnstype": "A"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"a_part_ip_address": "10.10.10.12",
|
||||||
|
"dnsdata": "10.10.10.12",
|
||||||
|
"dnstype": "A"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"a_part_ip_address": "10.10.10.13",
|
||||||
|
"dnsdata": "10.10.10.13",
|
||||||
|
"dnstype": "A"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"a_part_ip_address": "10.10.10.14",
|
||||||
|
"dnsdata": "10.10.10.14",
|
||||||
|
"dnstype": "A"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"a_part_ip_address": "10.10.10.16",
|
||||||
|
"dnsdata": "10.10.10.16",
|
||||||
|
"dnstype": "A"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"dnsdata": "10 abc",
|
||||||
|
"dnstype": "KX",
|
||||||
|
"kx_part_exchanger": "abc",
|
||||||
|
"kx_part_preference": "10"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"dnsdata": "11 foo",
|
||||||
|
"dnstype": "KX",
|
||||||
|
"kx_part_exchanger": "foo",
|
||||||
|
"kx_part_preference": "11"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"dnsdata": "data",
|
||||||
|
"dnstype": "TXT",
|
||||||
|
"txt_part_data": "data"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"aaaa_part_ip_address": "::1:2:3:4",
|
||||||
|
"dnsdata": "::1:2:3:4",
|
||||||
|
"dnstype": "AAAA"
|
||||||
|
}
|
||||||
|
],
|
||||||
"idnsname": [
|
"idnsname": [
|
||||||
"@"
|
"my"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"summary": null,
|
"summary": null,
|
||||||
"value": "@"
|
"value": "my"
|
||||||
}
|
}
|
||||||
|
}
|
@ -3,16 +3,6 @@
|
|||||||
"id": null,
|
"id": null,
|
||||||
"result": {
|
"result": {
|
||||||
"result": {
|
"result": {
|
||||||
"aaaarecord": [
|
|
||||||
"feed:babe:beef:cafe::0001",
|
|
||||||
"feed:babe:beef:cafe::0002",
|
|
||||||
"feed:babe:beef:cafe::0004"
|
|
||||||
],
|
|
||||||
"arecord": [
|
|
||||||
"3.4.5.6",
|
|
||||||
"1.3.5.7",
|
|
||||||
"10.10.2.1"
|
|
||||||
],
|
|
||||||
"attributelevelrights": {
|
"attributelevelrights": {
|
||||||
"a6record": "rscwo",
|
"a6record": "rscwo",
|
||||||
"aaaarecord": "rscwo",
|
"aaaarecord": "rscwo",
|
||||||
@ -48,26 +38,70 @@
|
|||||||
"sshfprecord": "rscwo",
|
"sshfprecord": "rscwo",
|
||||||
"txtrecord": "rscwo"
|
"txtrecord": "rscwo"
|
||||||
},
|
},
|
||||||
"dn": "idnsname=testrec,idnsname=example.com,cn=dns,dc=example,dc=com",
|
"dn": "idnsname=my,idnsname=example.com,cn=dns,dc=dev,dc=example,dc=com",
|
||||||
"idnsname": [
|
"dnsrecords": [
|
||||||
"testrec"
|
{
|
||||||
|
"a_part_ip_address": "10.10.10.11",
|
||||||
|
"dnsdata": "10.10.10.11",
|
||||||
|
"dnstype": "A"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"a_part_ip_address": "10.10.10.12",
|
||||||
|
"dnsdata": "10.10.10.12",
|
||||||
|
"dnstype": "A"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"a_part_ip_address": "10.10.10.13",
|
||||||
|
"dnsdata": "10.10.10.13",
|
||||||
|
"dnstype": "A"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"a_part_ip_address": "10.10.10.14",
|
||||||
|
"dnsdata": "10.10.10.14",
|
||||||
|
"dnstype": "A"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"a_part_ip_address": "10.10.10.16",
|
||||||
|
"dnsdata": "10.10.10.16",
|
||||||
|
"dnstype": "A"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"a_part_ip_address": "10.10.10.10",
|
||||||
|
"dnsdata": "10.10.10.10",
|
||||||
|
"dnstype": "A"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"dnsdata": "10 abc",
|
||||||
|
"dnstype": "KX",
|
||||||
|
"kx_part_exchanger": "abc",
|
||||||
|
"kx_part_preference": "10"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"dnsdata": "11 foo",
|
||||||
|
"dnstype": "KX",
|
||||||
|
"kx_part_exchanger": "foo",
|
||||||
|
"kx_part_preference": "11"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"dnsdata": "data",
|
||||||
|
"dnstype": "TXT",
|
||||||
|
"txt_part_data": "data"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"aaaa_part_ip_address": "::1:2:3:4",
|
||||||
|
"dnsdata": "::1:2:3:4",
|
||||||
|
"dnstype": "AAAA"
|
||||||
|
}
|
||||||
],
|
],
|
||||||
"keyrecord": [
|
"idnsname": [
|
||||||
"key"
|
"my"
|
||||||
],
|
],
|
||||||
"objectclass": [
|
"objectclass": [
|
||||||
"top",
|
"top",
|
||||||
"idnsrecord"
|
"idnsrecord"
|
||||||
],
|
|
||||||
"srvrecord": [
|
|
||||||
"1 1 80 dev"
|
|
||||||
],
|
|
||||||
"txtrecord": [
|
|
||||||
"A Text Record",
|
|
||||||
"Another Text Record"
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"summary": null,
|
"summary": null,
|
||||||
"value": "testrec"
|
"value": "my"
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -48,6 +48,7 @@
|
|||||||
"add_many": "Add Many",
|
"add_many": "Add Many",
|
||||||
"cancel": "Cancel",
|
"cancel": "Cancel",
|
||||||
"close": "Close",
|
"close": "Close",
|
||||||
|
"edit": "Edit",
|
||||||
"find": "Find",
|
"find": "Find",
|
||||||
"get": "Get",
|
"get": "Get",
|
||||||
"issue": "Issue",
|
"issue": "Issue",
|
||||||
@ -78,6 +79,7 @@
|
|||||||
"confirmation": "Confirmation",
|
"confirmation": "Confirmation",
|
||||||
"dirty_message": "This page has unsaved changes. Please save or revert.",
|
"dirty_message": "This page has unsaved changes. Please save or revert.",
|
||||||
"dirty_title": "Unsaved Changes",
|
"dirty_title": "Unsaved Changes",
|
||||||
|
"edit_title": "Edit ${entity}",
|
||||||
"hide_details": "Hide details",
|
"hide_details": "Hide details",
|
||||||
"prospective": "Prospective",
|
"prospective": "Prospective",
|
||||||
"redirection": "Redirection",
|
"redirection": "Redirection",
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -744,6 +744,7 @@ IPA.radio_widget = function(spec) {
|
|||||||
|
|
||||||
var that = IPA.input_widget(spec);
|
var that = IPA.input_widget(spec);
|
||||||
|
|
||||||
|
that.default_value = spec.default_value;
|
||||||
that.options = spec.options;
|
that.options = spec.options;
|
||||||
|
|
||||||
that.create = function(container) {
|
that.create = function(container) {
|
||||||
@ -802,6 +803,9 @@ IPA.radio_widget = function(spec) {
|
|||||||
var input = $(that.selector+'[value="'+value+'"]', that.container);
|
var input = $(that.selector+'[value="'+value+'"]', that.container);
|
||||||
if (input.length) {
|
if (input.length) {
|
||||||
input.attr('checked', true);
|
input.attr('checked', true);
|
||||||
|
} else if (that.default_value) {
|
||||||
|
input = $(that.selector+'[value="'+that.default_value+'"]', that.container);
|
||||||
|
input.attr('checked', true);
|
||||||
}
|
}
|
||||||
|
|
||||||
that.value_changed.notify([that.save()], that);
|
that.value_changed.notify([that.save()], that);
|
||||||
@ -809,6 +813,11 @@ IPA.radio_widget = function(spec) {
|
|||||||
|
|
||||||
that.clear = function() {
|
that.clear = function() {
|
||||||
$(that.selector, that.container).attr('checked', false);
|
$(that.selector, that.container).attr('checked', false);
|
||||||
|
|
||||||
|
if (that.default_value) {
|
||||||
|
var input = $(that.selector+'[value="'+that.default_value+'"]', that.container);
|
||||||
|
input.attr('checked', true);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// methods that should be invoked by subclasses
|
// methods that should be invoked by subclasses
|
||||||
@ -1118,6 +1127,7 @@ IPA.table_widget = function (spec) {
|
|||||||
that.multivalued = spec.multivalued === undefined ? true : spec.multivalued;
|
that.multivalued = spec.multivalued === undefined ? true : spec.multivalued;
|
||||||
|
|
||||||
that.columns = $.ordered_map();
|
that.columns = $.ordered_map();
|
||||||
|
that.value_attr_name = spec.value_attribute || that.name;
|
||||||
|
|
||||||
that.get_columns = function() {
|
that.get_columns = function() {
|
||||||
return that.columns.values;
|
return that.columns.values;
|
||||||
@ -1430,13 +1440,27 @@ IPA.table_widget = function (spec) {
|
|||||||
|
|
||||||
that.empty();
|
that.empty();
|
||||||
|
|
||||||
that.values = result[that.name] || [];
|
that.values = result[that.value_attr_name] || [];
|
||||||
for (var i=0; i<that.values.length; i++) {
|
for (var i=0; i<that.values.length; i++) {
|
||||||
var record = that.get_record(result, i);
|
var record = that.get_record(result, i);
|
||||||
that.add_record(record);
|
that.add_record(record);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
that.update = function(records) {
|
||||||
|
|
||||||
|
that.empty();
|
||||||
|
|
||||||
|
that.values = [];
|
||||||
|
that.records = records;
|
||||||
|
|
||||||
|
for (var i=0; i<records.length; i++) {
|
||||||
|
var record = records[i];
|
||||||
|
that.values.push(record[that.value_attr_name]);
|
||||||
|
that.add_record(record);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
that.save = function() {
|
that.save = function() {
|
||||||
if (that.save_values) {
|
if (that.save_values) {
|
||||||
var values = [];
|
var values = [];
|
||||||
@ -1495,16 +1519,19 @@ IPA.table_widget = function (spec) {
|
|||||||
that.select_changed();
|
that.select_changed();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
var select_set = false;
|
||||||
|
var value;
|
||||||
var columns = that.columns.values;
|
var columns = that.columns.values;
|
||||||
|
|
||||||
for (var i=0; i<columns.length; i++){
|
for (var i=0; i<columns.length; i++){
|
||||||
var column = columns[i];
|
var column = columns[i];
|
||||||
|
|
||||||
var value = record[column.name];
|
value = record[column.name];
|
||||||
value = value ? value.toString() : '';
|
value = value ? value.toString() : '';
|
||||||
|
|
||||||
if (column.primary_key) {
|
if (column.primary_key) {
|
||||||
$('input[name="'+that.name+'"]', tr).val(value);
|
$('input[name="'+that.name+'"]', tr).val(value);
|
||||||
|
select_set = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
var div = $('div[name="'+column.name+'"]', tr);
|
var div = $('div[name="'+column.name+'"]', tr);
|
||||||
@ -1512,6 +1539,11 @@ IPA.table_widget = function (spec) {
|
|||||||
that.setup_column(column, div, record);
|
that.setup_column(column, div, record);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!select_set) {
|
||||||
|
value = record[that.value_attr_name];
|
||||||
|
$('input[name="'+that.name+'"]', tr).val(value);
|
||||||
|
}
|
||||||
|
|
||||||
return tr;
|
return tr;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1581,6 +1613,7 @@ IPA.table_widget = function (spec) {
|
|||||||
that.table_set_page = that.set_page;
|
that.table_set_page = that.set_page;
|
||||||
that.table_show_error = that.show_error;
|
that.table_show_error = that.show_error;
|
||||||
that.table_set_values = that.set_values;
|
that.table_set_values = that.set_values;
|
||||||
|
that.table_update = that.update;
|
||||||
|
|
||||||
return that;
|
return that;
|
||||||
};
|
};
|
||||||
@ -2370,17 +2403,21 @@ IPA.widget_builder = function(spec) {
|
|||||||
return that;
|
return that;
|
||||||
};
|
};
|
||||||
|
|
||||||
IPA.widget_factories['text'] = IPA.text_widget;
|
|
||||||
IPA.widget_factories['password'] = IPA.password_widget;
|
|
||||||
IPA.widget_factories['checkbox'] = IPA.checkbox_widget;
|
IPA.widget_factories['checkbox'] = IPA.checkbox_widget;
|
||||||
IPA.widget_factories['checkboxes'] = IPA.checkboxes_widget;
|
IPA.widget_factories['checkboxes'] = IPA.checkboxes_widget;
|
||||||
IPA.widget_factories['radio'] = IPA.radio_widget;
|
|
||||||
IPA.widget_factories['multivalued'] = IPA.multivalued_text_widget;
|
|
||||||
IPA.widget_factories['select'] = IPA.select_widget;
|
|
||||||
IPA.widget_factories['textarea'] = IPA.textarea_widget;
|
|
||||||
IPA.widget_factories['entity_select'] = IPA.entity_select_widget;
|
|
||||||
IPA.widget_factories['combobox'] = IPA.combobox_widget;
|
IPA.widget_factories['combobox'] = IPA.combobox_widget;
|
||||||
IPA.widget_factories['link'] = IPA.link_widget;
|
IPA.widget_factories['composite_widget'] = IPA.composite_widget;
|
||||||
IPA.widget_factories['details_table_section'] = IPA.details_table_section;
|
IPA.widget_factories['details_table_section'] = IPA.details_table_section;
|
||||||
IPA.widget_factories['details_table_section_nc'] = IPA.details_table_section_nc;
|
IPA.widget_factories['details_table_section_nc'] = IPA.details_table_section_nc;
|
||||||
IPA.widget_factories['enable'] = IPA.enable_widget;
|
IPA.widget_factories['enable'] = IPA.enable_widget;
|
||||||
|
IPA.widget_factories['entity_select'] = IPA.entity_select_widget;
|
||||||
|
IPA.widget_factories['header'] = IPA.header_widget;
|
||||||
|
IPA.widget_factories['link'] = IPA.link_widget;
|
||||||
|
IPA.widget_factories['multivalued'] = IPA.multivalued_text_widget;
|
||||||
|
IPA.widget_factories['password'] = IPA.password_widget;
|
||||||
|
IPA.widget_factories['radio'] = IPA.radio_widget;
|
||||||
|
IPA.widget_factories['select'] = IPA.select_widget;
|
||||||
|
IPA.widget_factories['textarea'] = IPA.textarea_widget;
|
||||||
|
IPA.widget_factories['text'] = IPA.text_widget;
|
||||||
|
@ -183,6 +183,7 @@ class i18n_messages(Command):
|
|||||||
"add_many": _("Add Many"),
|
"add_many": _("Add Many"),
|
||||||
"cancel": _("Cancel"),
|
"cancel": _("Cancel"),
|
||||||
"close": _("Close"),
|
"close": _("Close"),
|
||||||
|
"edit": _("Edit"),
|
||||||
"find": _("Find"),
|
"find": _("Find"),
|
||||||
"get": _("Get"),
|
"get": _("Get"),
|
||||||
"issue": _("Issue"),
|
"issue": _("Issue"),
|
||||||
@ -213,6 +214,7 @@ class i18n_messages(Command):
|
|||||||
"confirmation": _("Confirmation"),
|
"confirmation": _("Confirmation"),
|
||||||
"dirty_message": _("This page has unsaved changes. Please save or revert."),
|
"dirty_message": _("This page has unsaved changes. Please save or revert."),
|
||||||
"dirty_title": _("Unsaved Changes"),
|
"dirty_title": _("Unsaved Changes"),
|
||||||
|
"edit_title": _("Edit ${entity}"),
|
||||||
"hide_details": _("Hide details"),
|
"hide_details": _("Hide details"),
|
||||||
"prospective": _("Prospective"),
|
"prospective": _("Prospective"),
|
||||||
"redirection": _("Redirection"),
|
"redirection": _("Redirection"),
|
||||||
|
Loading…
Reference in New Issue
Block a user