public inbox for pve-devel@lists.proxmox.com
 help / color / mirror / Atom feed
* [pve-devel] [PATCH 0/5] fix #4442: Firewall log filtering
@ 2023-03-23 14:42 Christian Ebner
  2023-03-23 14:42 ` [pve-devel] [PATCH widget-toolkit 1/3] DateTimeField: fix typo in xtype Christian Ebner
                   ` (4 more replies)
  0 siblings, 5 replies; 8+ messages in thread
From: Christian Ebner @ 2023-03-23 14:42 UTC (permalink / raw)
  To: pve-devel

This patch series extends the log view panel for date-time filtering and
introduces the configs needed to allow the user to switch between the
livemode and the filter mode, analogous to the journal view panel.

The existing date time field was extended to publish state changes for value
bindings to be updated.

pve-manager:

Christian Ebner (1):
  fix #4442: Add date-time filtering for firewall logs

 www/manager6/node/Config.js | 2 ++
 www/manager6/qemu/Config.js | 2 ++
 2 files changed, 4 insertions(+)

pmg-gui:

Christian Ebner (1):
  DateTimeField: fix typo in xtype

 js/MailTracker.js | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

proxmox-widget-toolkit:

Christian Ebner (3):
  DateTimeField: fix typo in xtype
  DateTimeField: Extend and refactor to make field value bindable
  fix #4442: Extend LogView for firewall datetime filtering

 src/form/DateTimeField.js | 107 +++++++++++++++++++++++++++++---------
 src/panel/LogView.js      |  83 +++++++++++++++++++++++++----
 2 files changed, 156 insertions(+), 34 deletions(-)

-- 
2.30.2





^ permalink raw reply	[flat|nested] 8+ messages in thread

* [pve-devel] [PATCH widget-toolkit 1/3] DateTimeField: fix typo in xtype
  2023-03-23 14:42 [pve-devel] [PATCH 0/5] fix #4442: Firewall log filtering Christian Ebner
@ 2023-03-23 14:42 ` Christian Ebner
  2023-06-06 14:47   ` [pve-devel] applied: " Thomas Lamprecht
  2023-03-23 14:42 ` [pve-devel] [PATCH widget-toolkit 2/3] DateTimeField: Extend and refactor to make field value bindable Christian Ebner
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 8+ messages in thread
From: Christian Ebner @ 2023-03-23 14:42 UTC (permalink / raw)
  To: pve-devel

Signed-off-by: Christian Ebner <c.ebner@proxmox.com>
---
 src/form/DateTimeField.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/form/DateTimeField.js b/src/form/DateTimeField.js
index a061e15..87bb1ef 100644
--- a/src/form/DateTimeField.js
+++ b/src/form/DateTimeField.js
@@ -1,6 +1,6 @@
 Ext.define('Proxmox.DateTimeField', {
     extend: 'Ext.form.FieldContainer',
-    xtype: 'promxoxDateTimeField',
+    xtype: 'proxmoxDateTimeField',
 
     layout: 'hbox',
 
-- 
2.30.2





^ permalink raw reply	[flat|nested] 8+ messages in thread

* [pve-devel] [PATCH widget-toolkit 2/3] DateTimeField: Extend and refactor to make field value bindable
  2023-03-23 14:42 [pve-devel] [PATCH 0/5] fix #4442: Firewall log filtering Christian Ebner
  2023-03-23 14:42 ` [pve-devel] [PATCH widget-toolkit 1/3] DateTimeField: fix typo in xtype Christian Ebner
@ 2023-03-23 14:42 ` Christian Ebner
  2023-06-06 14:47   ` [pve-devel] applied: " Thomas Lamprecht
  2023-03-23 14:42 ` [pve-devel] [PATCH widget-toolkit 3/3] fix #4442: Extend LogView for firewall datetime filtering Christian Ebner
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 8+ messages in thread
From: Christian Ebner @ 2023-03-23 14:42 UTC (permalink / raw)
  To: pve-devel

Extends the date time field so that bindings are updated on value changes.
Also adds a config to disable child components and avoid modification of
current values by cloning the referenced object for min/max value calculation.

Signed-off-by: Christian Ebner <c.ebner@proxmox.com>
---
 src/form/DateTimeField.js | 105 +++++++++++++++++++++++++++++---------
 1 file changed, 81 insertions(+), 24 deletions(-)

diff --git a/src/form/DateTimeField.js b/src/form/DateTimeField.js
index 87bb1ef..e12fc91 100644
--- a/src/form/DateTimeField.js
+++ b/src/form/DateTimeField.js
@@ -6,21 +6,34 @@ Ext.define('Proxmox.DateTimeField', {
 
     referenceHolder: true,
 
-    submitFormat: 'U',
+    config: {
+	submitFormat: 'U',
+	disabled: false,
+    },
 
-    getValue: function() {
+    setValue: function(value) {
 	let me = this;
-	let d = me.lookupReference('dateentry').getValue();
+	me.setDate(value);
+	me.setTime(value);
 
-	if (d === undefined || d === null) { return null; }
+	// Notify all 'value' bindings of state change
+	me.publishState('value', value);
+    },
 
-	let t = me.lookupReference('timeentry').getValue();
+    getValue: function() {
+	let me = this;
+	let date = me.lookupReference('dateentry').getValue();
+
+	if (date === undefined || date === null) { return null; }
 
-	if (t === undefined || t === null) { return null; }
+	let time = me.lookupReference('timeentry').getValue();
 
-	let offset = (t.getHours() * 3600 + t.getMinutes() * 60) * 1000;
+	if (time === undefined || time === null) { return null; }
 
-	return new Date(d.getTime() + offset);
+	date.setHours(time.getHours());
+	date.setMinutes(time.getMinutes());
+	date.setSeconds(time.getSeconds());
+	return date;
     },
 
     getSubmitValue: function() {
@@ -31,6 +44,20 @@ Ext.define('Proxmox.DateTimeField', {
         return value ? Ext.Date.format(value, format) : null;
     },
 
+    setDate: function(date) {
+	let me = this;
+	let dateEntry = me.lookupReference('dateentry');
+	dateEntry.setValue(date);
+	dateEntry.publishState('value', date);
+    },
+
+    setTime: function(time) {
+	let me = this;
+	let timeEntry = me.lookupReference('timeentry');
+	timeEntry.setValue(time);
+	timeEntry.publishState('value', time);
+    },
+
     items: [
 	{
 	    xtype: 'datefield',
@@ -38,6 +65,17 @@ Ext.define('Proxmox.DateTimeField', {
 	    reference: 'dateentry',
 	    flex: 1,
 	    format: 'Y-m-d',
+	    bind: {
+		disabled: '{disabled}',
+	    },
+	    listeners: {
+		'change': function(field, newValue, oldValue) {
+		    let dateTimeField = field.up('fieldcontainer');
+		    dateTimeField.setDate(newValue);
+		    let value = dateTimeField.getValue();
+		    dateTimeField.publishState('value', value);
+		},
+	    },
 	},
 	{
 	    xtype: 'timefield',
@@ -46,6 +84,17 @@ Ext.define('Proxmox.DateTimeField', {
 	    width: 80,
 	    value: '00:00',
 	    increment: 60,
+	    bind: {
+		disabled: '{disabled}',
+	    },
+	    listeners: {
+		'change': function(field, newValue, oldValue) {
+		    let dateTimeField = field.up('fieldcontainer');
+		    dateTimeField.setTime(newValue);
+		    let value = dateTimeField.getValue();
+		    dateTimeField.publishState('value', value);
+		},
+	    },
 	},
     ],
 
@@ -56,21 +105,23 @@ Ext.define('Proxmox.DateTimeField', {
 	    return;
 	}
 
-	let minhours = value.getHours();
-	let minminutes = value.getMinutes();
+	// Clone to avoid modifying the referenced value
+	let clone = new Date(value);
+	let minhours = clone.getHours();
+	let minminutes = clone.getMinutes();
 
 	let hours = current.getHours();
 	let minutes = current.getMinutes();
 
-	value.setHours(0);
-	value.setMinutes(0);
-	value.setSeconds(0);
+	clone.setHours(0);
+	clone.setMinutes(0);
+	clone.setSeconds(0);
 	current.setHours(0);
 	current.setMinutes(0);
 	current.setSeconds(0);
 
 	let time = new Date();
-	if (current-value > 0) {
+	if (current-clone > 0) {
 	    time.setHours(0);
 	    time.setMinutes(0);
 	    time.setSeconds(0);
@@ -84,9 +135,9 @@ Ext.define('Proxmox.DateTimeField', {
 	// current time is smaller than the time part of the new minimum
 	// so we have to add 1 to the day
 	if (minhours*60+minminutes > hours*60+minutes) {
-	    value.setDate(value.getDate()+1);
+	    clone.setDate(clone.getDate()+1);
 	}
-	me.lookup('dateentry').setMinValue(value);
+	me.lookup('dateentry').setMinValue(clone);
     },
 
     setMaxValue: function(value) {
@@ -96,19 +147,25 @@ Ext.define('Proxmox.DateTimeField', {
 	    return;
 	}
 
-	let maxhours = value.getHours();
-	let maxminutes = value.getMinutes();
+	// Clone to avoid modifying the referenced value
+	let clone = new Date(value);
+	let maxhours = clone.getHours();
+	let maxminutes = clone.getMinutes();
 
 	let hours = current.getHours();
 	let minutes = current.getMinutes();
 
-	value.setHours(0);
-	value.setMinutes(0);
+	clone.setHours(0);
+	clone.setMinutes(0);
+	clone.setSeconds(0);
+	clone.setMilliseconds(0);
 	current.setHours(0);
 	current.setMinutes(0);
+	current.setSeconds(0);
+	current.setMilliseconds(0);
 
 	let time = new Date();
-	if (value-current > 0) {
+	if (clone-current > 0) {
 	    time.setHours(23);
 	    time.setMinutes(59);
 	    time.setSeconds(59);
@@ -118,13 +175,13 @@ Ext.define('Proxmox.DateTimeField', {
 	}
 	me.lookup('timeentry').setMaxValue(time);
 
-	// current time is biger than the time part of the new maximum
+	// current time is bigger than the time part of the new maximum
 	// so we have to subtract 1 to the day
 	if (maxhours*60+maxminutes < hours*60+minutes) {
-	    value.setDate(value.getDate()-1);
+	    clone.setDate(clone.getDate()-1);
 	}
 
-	me.lookup('dateentry').setMaxValue(value);
+	me.lookup('dateentry').setMaxValue(clone);
     },
 
     initComponent: function() {
-- 
2.30.2





^ permalink raw reply	[flat|nested] 8+ messages in thread

* [pve-devel] [PATCH widget-toolkit 3/3] fix #4442: Extend LogView for firewall datetime filtering
  2023-03-23 14:42 [pve-devel] [PATCH 0/5] fix #4442: Firewall log filtering Christian Ebner
  2023-03-23 14:42 ` [pve-devel] [PATCH widget-toolkit 1/3] DateTimeField: fix typo in xtype Christian Ebner
  2023-03-23 14:42 ` [pve-devel] [PATCH widget-toolkit 2/3] DateTimeField: Extend and refactor to make field value bindable Christian Ebner
@ 2023-03-23 14:42 ` Christian Ebner
  2023-03-23 14:42 ` [pve-devel] [PATCH pmg-gui 4/4] DateTimeField: fix typo in xtype Christian Ebner
  2023-03-23 14:42 ` [pve-devel] [PATCH manager 5/5] fix #4442: Add date-time filtering for firewall logs Christian Ebner
  4 siblings, 0 replies; 8+ messages in thread
From: Christian Ebner @ 2023-03-23 14:42 UTC (permalink / raw)
  To: pve-devel

Extends the current panels date filtering capability to date-time
based filtering, and adds a config option to switch between livemode
and filter mode, analogous to the JournalView panel.

The `submitFormat` config is introduced to adapt the formatting of
params values for their corresponding api calls.

Signed-off-by: Christian Ebner <c.ebner@proxmox.com>
---
 src/panel/LogView.js | 83 +++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 74 insertions(+), 9 deletions(-)

diff --git a/src/panel/LogView.js b/src/panel/LogView.js
index 44aa8e3..cd17603 100644
--- a/src/panel/LogView.js
+++ b/src/panel/LogView.js
@@ -22,19 +22,28 @@ Ext.define('Proxmox.panel.LogView', {
 	updateParams: function() {
 	    let me = this;
 	    let viewModel = me.getViewModel();
-	    let since = viewModel.get('since');
-	    let until = viewModel.get('until');
-	    if (viewModel.get('hide_timespan')) {
+
+	    if (viewModel.get('hide_timespan') || viewModel.get('livemode')) {
 		return;
 	    }
 
+	    let since = viewModel.get('since');
+	    let until = viewModel.get('until');
+
 	    if (since > until) {
 		Ext.Msg.alert('Error', 'Since date must be less equal than Until date.');
 		return;
 	    }
 
-	    viewModel.set('params.since', Ext.Date.format(since, 'Y-m-d'));
-	    viewModel.set('params.until', Ext.Date.format(until, 'Y-m-d') + ' 23:59:59');
+	    let submitFormat = viewModel.get('submitFormat');
+
+	    viewModel.set('params.since', Ext.Date.format(since, submitFormat));
+	    if (submitFormat === 'Y-m-d') {
+		viewModel.set('params.until', Ext.Date.format(until, submitFormat) + ' 23:59:59');
+	    } else {
+		viewModel.set('params.until', Ext.Date.format(until, submitFormat));
+	    }
+
 	    me.getView().loadTask.delay(200);
 	},
 
@@ -175,6 +184,27 @@ Ext.define('Proxmox.panel.LogView', {
 	    }
 	},
 
+	onLiveMode: function() {
+	    let me = this;
+	    let viewModel = me.getViewModel();
+	    viewModel.set('livemode', true);
+	    viewModel.set('params', { start: 0, limit: 510 });
+
+	    let view = me.getView();
+	    delete view.content;
+	    view.scrollToEnd = true;
+	    me.updateView([], true, false);
+	},
+
+	onTimespan: function() {
+	    let me = this;
+	    me.getViewModel().set('livemode', false);
+	    me.updateView([], false);
+	    // Directly apply currently selected values without update
+	    // button click.
+	    me.updateParams();
+	},
+
 	init: function(view) {
 	    let me = this;
 
@@ -189,6 +219,7 @@ Ext.define('Proxmox.panel.LogView', {
 	    viewModel.set('since', since);
 	    viewModel.set('params.limit', view.pageSize);
 	    viewModel.set('hide_timespan', !view.log_select_timespan);
+	    viewModel.set('submitFormat', view.submitFormat);
 	    me.lookup('content').setStyle('line-height', `${view.lineHeight}px`);
 
 	    view.loadTask = new Ext.util.DelayedTask(me.doLoad, me);
@@ -224,6 +255,8 @@ Ext.define('Proxmox.panel.LogView', {
 	data: {
 	    until: null,
 	    since: null,
+	    submitFormat: 'Y-m-d',
+	    livemode: true,
 	    hide_timespan: false,
 	    data: {
 		start: 0,
@@ -263,32 +296,64 @@ Ext.define('Proxmox.panel.LogView', {
 	},
 	items: [
 	    '->',
-	    'Since: ',
 	    {
-		xtype: 'datefield',
+		xtype: 'segmentedbutton',
+		items: [
+		    {
+			text: gettext('Live Mode'),
+			bind: {
+			    pressed: '{livemode}',
+			},
+			handler: 'onLiveMode',
+		    },
+		    {
+			text: gettext('Select Timespan'),
+			bind: {
+			    pressed: '{!livemode}',
+			},
+			handler: 'onTimespan',
+		    },
+		],
+	    },
+	    {
+		xtype: 'box',
+		autoEl: { cn: gettext('Since') + ':' },
+	    },
+	    {
+		xtype: 'proxmoxDateTimeField',
 		name: 'since_date',
 		reference: 'since',
 		format: 'Y-m-d',
 		bind: {
+		    disabled: '{livemode}',
 		    value: '{since}',
 		    maxValue: '{until}',
+		    submitFormat: '{submitFormat}',
 		},
 	    },
-	    'Until: ',
 	    {
-		xtype: 'datefield',
+		xtype: 'box',
+		autoEl: { cn: gettext('Until') + ':' },
+	    },
+	    {
+		xtype: 'proxmoxDateTimeField',
 		name: 'until_date',
 		reference: 'until',
 		format: 'Y-m-d',
 		bind: {
+		    disabled: '{livemode}',
 		    value: '{until}',
 		    minValue: '{since}',
+		    submitFormat: '{submitFormat}',
 		},
 	    },
 	    {
 		xtype: 'button',
 		text: 'Update',
 		handler: 'updateParams',
+		bind: {
+		    disabled: '{livemode}',
+		},
 	    },
 	],
     },
-- 
2.30.2





^ permalink raw reply	[flat|nested] 8+ messages in thread

* [pve-devel] [PATCH pmg-gui 4/4] DateTimeField: fix typo in xtype
  2023-03-23 14:42 [pve-devel] [PATCH 0/5] fix #4442: Firewall log filtering Christian Ebner
                   ` (2 preceding siblings ...)
  2023-03-23 14:42 ` [pve-devel] [PATCH widget-toolkit 3/3] fix #4442: Extend LogView for firewall datetime filtering Christian Ebner
@ 2023-03-23 14:42 ` Christian Ebner
  2023-03-23 14:42 ` [pve-devel] [PATCH manager 5/5] fix #4442: Add date-time filtering for firewall logs Christian Ebner
  4 siblings, 0 replies; 8+ messages in thread
From: Christian Ebner @ 2023-03-23 14:42 UTC (permalink / raw)
  To: pve-devel

Signed-off-by: Christian Ebner <c.ebner@proxmox.com>
---
 js/MailTracker.js | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/js/MailTracker.js b/js/MailTracker.js
index 52641a4..ce1a487 100644
--- a/js/MailTracker.js
+++ b/js/MailTracker.js
@@ -106,7 +106,7 @@ Ext.define('PMG.MailTrackerFilter', {
 			let now = new Date();
 			return new Date(now.getTime() - 3600000);
 		    }()),
-		    xtype: 'promxoxDateTimeField',
+		    xtype: 'proxmoxDateTimeField',
 		},
 		{
 		    fieldLabel: gettext('End'),
@@ -126,7 +126,7 @@ Ext.define('PMG.MailTrackerFilter', {
 			tomorrow.setSeconds(0);
 			return tomorrow;
 		    }()),
-		    xtype: 'promxoxDateTimeField',
+		    xtype: 'proxmoxDateTimeField',
 		},
 		{
 		    layout: {
-- 
2.30.2





^ permalink raw reply	[flat|nested] 8+ messages in thread

* [pve-devel] [PATCH manager 5/5] fix #4442: Add date-time filtering for firewall logs
  2023-03-23 14:42 [pve-devel] [PATCH 0/5] fix #4442: Firewall log filtering Christian Ebner
                   ` (3 preceding siblings ...)
  2023-03-23 14:42 ` [pve-devel] [PATCH pmg-gui 4/4] DateTimeField: fix typo in xtype Christian Ebner
@ 2023-03-23 14:42 ` Christian Ebner
  4 siblings, 0 replies; 8+ messages in thread
From: Christian Ebner @ 2023-03-23 14:42 UTC (permalink / raw)
  To: pve-devel

Extend the current firewall log view to add date time based filtering.
The user can switch between live view, which shows logs from the
unrotated log file, or to filter mode, where date time based filtering,
including rotated logs can be performed.

Signed-off-by: Christian Ebner <c.ebner@proxmox.com>
---
 www/manager6/node/Config.js | 2 ++
 www/manager6/qemu/Config.js | 2 ++
 2 files changed, 4 insertions(+)

diff --git a/www/manager6/node/Config.js b/www/manager6/node/Config.js
index 0cc23fb4..337c8cc1 100644
--- a/www/manager6/node/Config.js
+++ b/www/manager6/node/Config.js
@@ -397,6 +397,8 @@ Ext.define('PVE.node.Config', {
 		    onlineHelp: 'chapter_pve_firewall',
 		    url: '/api2/extjs/nodes/' + nodename + '/firewall/log',
 		    itemId: 'firewall-fwlog',
+		    log_select_timespan: true,
+		    submitFormat: 'U',
 		},
 		{
 		    xtype: 'cephLogView',
diff --git a/www/manager6/qemu/Config.js b/www/manager6/qemu/Config.js
index 94c540c5..326a54e3 100644
--- a/www/manager6/qemu/Config.js
+++ b/www/manager6/qemu/Config.js
@@ -385,6 +385,8 @@ Ext.define('PVE.qemu.Config', {
 		    itemId: 'firewall-fwlog',
 		    xtype: 'proxmoxLogView',
 		    url: '/api2/extjs' + base_url + '/firewall/log',
+		    log_select_timespan: true,
+		    submitFormat: 'U',
 		},
 	    );
 	}
-- 
2.30.2





^ permalink raw reply	[flat|nested] 8+ messages in thread

* [pve-devel] applied: [PATCH widget-toolkit 1/3] DateTimeField: fix typo in xtype
  2023-03-23 14:42 ` [pve-devel] [PATCH widget-toolkit 1/3] DateTimeField: fix typo in xtype Christian Ebner
@ 2023-06-06 14:47   ` Thomas Lamprecht
  0 siblings, 0 replies; 8+ messages in thread
From: Thomas Lamprecht @ 2023-06-06 14:47 UTC (permalink / raw)
  To: Proxmox VE development discussion, Christian Ebner

Am 23/03/2023 um 15:42 schrieb Christian Ebner:
> Signed-off-by: Christian Ebner <c.ebner@proxmox.com>
> ---
>  src/form/DateTimeField.js | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
>

applied, but added the misspelled variant back as alias in a follow-up, that 
allows us to upgrade the use sites later, without requiring a Breaks for older
pmg-gui now, thanks!




^ permalink raw reply	[flat|nested] 8+ messages in thread

* [pve-devel] applied: [PATCH widget-toolkit 2/3] DateTimeField: Extend and refactor to make field value bindable
  2023-03-23 14:42 ` [pve-devel] [PATCH widget-toolkit 2/3] DateTimeField: Extend and refactor to make field value bindable Christian Ebner
@ 2023-06-06 14:47   ` Thomas Lamprecht
  0 siblings, 0 replies; 8+ messages in thread
From: Thomas Lamprecht @ 2023-06-06 14:47 UTC (permalink / raw)
  To: Proxmox VE development discussion, Christian Ebner

Am 23/03/2023 um 15:42 schrieb Christian Ebner:
> Extends the date time field so that bindings are updated on value changes.
> Also adds a config to disable child components and avoid modification of
> current values by cloning the referenced object for min/max value calculation.
> 
> Signed-off-by: Christian Ebner <c.ebner@proxmox.com>
> ---
>  src/form/DateTimeField.js | 105 +++++++++++++++++++++++++++++---------
>  1 file changed, 81 insertions(+), 24 deletions(-)
> 
>

applied, thanks!




^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2023-06-06 14:47 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-03-23 14:42 [pve-devel] [PATCH 0/5] fix #4442: Firewall log filtering Christian Ebner
2023-03-23 14:42 ` [pve-devel] [PATCH widget-toolkit 1/3] DateTimeField: fix typo in xtype Christian Ebner
2023-06-06 14:47   ` [pve-devel] applied: " Thomas Lamprecht
2023-03-23 14:42 ` [pve-devel] [PATCH widget-toolkit 2/3] DateTimeField: Extend and refactor to make field value bindable Christian Ebner
2023-06-06 14:47   ` [pve-devel] applied: " Thomas Lamprecht
2023-03-23 14:42 ` [pve-devel] [PATCH widget-toolkit 3/3] fix #4442: Extend LogView for firewall datetime filtering Christian Ebner
2023-03-23 14:42 ` [pve-devel] [PATCH pmg-gui 4/4] DateTimeField: fix typo in xtype Christian Ebner
2023-03-23 14:42 ` [pve-devel] [PATCH manager 5/5] fix #4442: Add date-time filtering for firewall logs Christian Ebner

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal