Skip to content

Commit 5b072fa

Browse files
authored
Merge pull request #11 from iMattPro/updates
Delete consent logs
2 parents b540ad1 + 0582cfb commit 5b072fa

11 files changed

Lines changed: 438 additions & 123 deletions

File tree

.github/workflows/merge-master-to-develop.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ jobs:
2323
name: Merge main into develop branch
2424
# Keep this named after the GitHub repository.
2525
# GitHub Actions does not allow workflow env values in jobs.<job_id>.if.
26-
if: github.repository == 'phpbb-extensions/consentmanager' && github.event.repository.fork == false
26+
if: github.repository == 'phpbb-extensions/consent-manager' && github.event.repository.fork == false
2727
runs-on: ubuntu-latest
2828

2929
steps:

acp/consentmanager_module.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ public function main($id, $mode)
2929
case 'export':
3030
$this->tpl_name = 'consentmanager_acp_export';
3131
$this->page_title = 'ACP_CONSENTMANAGER_EXPORT';
32-
$controller->handle_export();
32+
$controller->handle_logs();
3333
break;
3434

3535
default:

adm/style/consentmanager_acp_export.html

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,8 @@ <h3>{{ lang('WARNING') }}</h3>
4242
</fieldset>
4343

4444
<fieldset class="submit-buttons">
45-
<input class="button1" type="submit" name="download_csv" value="{{ lang('ACP_CONSENTMANAGER_EXPORT_DOWNLOAD') }}">
45+
<input class="button1" type="submit" name="download_csv" value="{{ lang('ACP_CONSENTMANAGER_EXPORT_DOWNLOAD') }}">&nbsp;
46+
<input class="button2" type="submit" name="delete_logs" value="{{ lang('ACP_CONSENTMANAGER_DELETE') }}">
4647
{{ S_FORM_TOKEN }}
4748
</fieldset>
4849
</form>

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"type": "phpbb-extension",
44
"description": "Centralized GDPR-compliant consent and deferred script loading for phpBB forums.",
55
"homepage": "https://www.phpbb.com/",
6-
"version": "0.2.0-dev",
6+
"version": "0.3.0-dev",
77
"keywords": ["phpbb", "extension", "gdpr", "consent", "cookies"],
88
"license": "GPL-2.0-only",
99
"authors": [

controller/acp_controller.php

Lines changed: 66 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ public function handle()
8989
return;
9090
}
9191

92-
$this->acp_manager->log_admin_settings_updated();
92+
$this->acp_manager->log_admin_action('LOG_CONSENTMANAGER_UPDATED');
9393
trigger_error($this->language->lang('CONFIG_UPDATED') . adm_back_link($this->u_action));
9494
}
9595

@@ -98,7 +98,7 @@ public function handle()
9898
$this->validate_form_key('phpbb_consentmanager_acp');
9999

100100
$this->acp_manager->reset_consent_version();
101-
$this->acp_manager->log_admin_reprompt();
101+
$this->acp_manager->log_admin_action('LOG_CONSENTMANAGER_REPROMPT');
102102

103103
trigger_error($this->language->lang('ACP_CONSENTMANAGER_REPROMPT_SUCCESS') . adm_back_link($this->u_action));
104104
}
@@ -107,50 +107,79 @@ public function handle()
107107
}
108108

109109
/**
110-
* Handle the ACP export page request.
111-
*
112-
* Displays the filter form on GET. On POST with download_csv, streams a
113-
* CSV file of consent log records matching the supplied filters.
110+
* Handle the ACP consent logs page request.
114111
*
115112
* @return void
116113
*/
117-
public function handle_export()
114+
public function handle_logs()
118115
{
119116
add_form_key('phpbb_consentmanager_export');
117+
$form_data = $this->get_logs_form_data();
120118

121119
if ($this->request->is_set_post('download_csv'))
122120
{
123121
$this->validate_form_key('phpbb_consentmanager_export');
124122

125123
$errors = [];
126-
$filters = $this->parse_export_filters($errors);
124+
$filters = $this->parse_export_filters($form_data, $errors);
127125

128126
if (!empty($errors))
129127
{
130-
$this->assign_export_template_vars($errors);
128+
$this->assign_export_template_vars($form_data, $errors);
131129
return;
132130
}
133131

134-
$this->acp_manager->log_admin_export();
132+
$this->acp_manager->log_admin_action('LOG_CONSENTMANAGER_EXPORT');
135133
$this->send_csv_download($filters);
136134
}
135+
else if ($this->request->is_set_post('delete_logs'))
136+
{
137+
$errors = [];
138+
$filters = $this->parse_export_filters($form_data, $errors);
139+
140+
if (!empty($errors))
141+
{
142+
$this->assign_export_template_vars($form_data, $errors);
143+
return;
144+
}
145+
146+
if (confirm_box(true))
147+
{
148+
$this->acp_manager->delete_logs($filters);
149+
$this->acp_manager->log_admin_action('LOG_CONSENTMANAGER_DELETE');
150+
151+
trigger_error($this->language->lang('ACP_CONSENTMANAGER_DELETE_SUCCESS') . adm_back_link($this->u_action));
152+
}
153+
else
154+
{
155+
confirm_box(
156+
false,
157+
$this->language->lang('ACP_CONSENTMANAGER_DELETE_CONFIRM'),
158+
build_hidden_fields(array_merge([
159+
'mode' => 'export',
160+
'delete_logs' => 1,
161+
], $form_data))
162+
);
163+
}
164+
}
137165

138-
$this->assign_export_template_vars();
166+
$this->assign_export_template_vars($form_data);
139167
}
140168

141169
/**
142170
* Parse and validate filter inputs from the export form.
143171
*
172+
* @param array $form_data Array of form field values
144173
* @param array $errors Reference — validation errors are appended here
145174
*
146175
* @return array Validated filter map (date_from, date_to, user_id, consent_version)
147176
*/
148-
protected function parse_export_filters(array &$errors)
177+
protected function parse_export_filters(array $form_data, array &$errors)
149178
{
150-
$date_from_str = trim($this->request->variable('export_date_from', ''));
151-
$date_to_str = trim($this->request->variable('export_date_to', ''));
152-
$user_id = $this->request->variable('export_user_id', 0);
153-
$consent_ver = $this->request->variable('export_consent_version', 0);
179+
$date_from_str = trim($form_data['export_date_from']);
180+
$date_to_str = trim($form_data['export_date_to']);
181+
$user_id = $form_data['export_user_id'];
182+
$consent_ver = $form_data['export_consent_version'];
154183

155184
$filters = [];
156185
$date_from = $this->acp_manager->parse_date_filter($date_from_str);
@@ -205,7 +234,7 @@ protected function send_csv_download(array $filters)
205234
}
206235

207236
header('Content-Type: text/csv; charset=UTF-8');
208-
header('Content-Disposition: attachment; filename="consent_logs.csv"');
237+
header('Content-Disposition: attachment; filename="consent_logs_' . gmdate('Y-m-d_His') . '.csv"');
209238
header('Cache-Control: no-cache, no-store, must-revalidate');
210239
header('Pragma: no-cache');
211240
header('Expires: 0');
@@ -219,17 +248,14 @@ protected function send_csv_download(array $filters)
219248
exit;
220249
}
221250

222-
protected function assign_export_template_vars(array $errors = [])
251+
protected function get_logs_form_data()
223252
{
224-
$this->template->assign_vars([
225-
'S_ERROR' => !empty($errors),
226-
'ERROR_MSG' => implode('<br>', $errors),
227-
'EXPORT_DATE_FROM' => $this->request->variable('export_date_from', ''),
228-
'EXPORT_DATE_TO' => $this->request->variable('export_date_to', ''),
229-
'EXPORT_USER_ID' => $this->request->variable('export_user_id', 0),
230-
'EXPORT_CONSENT_VER' => $this->request->variable('export_consent_version', 0),
231-
'U_ACTION' => $this->u_action,
232-
]);
253+
return [
254+
'export_date_from' => $this->request->variable('export_date_from', ''),
255+
'export_date_to' => $this->request->variable('export_date_to', ''),
256+
'export_user_id' => $this->request->variable('export_user_id', 0),
257+
'export_consent_version' => $this->request->variable('export_consent_version', 0),
258+
];
233259
}
234260

235261
protected function assign_template_vars(array $errors = [])
@@ -244,6 +270,19 @@ protected function assign_template_vars(array $errors = [])
244270
));
245271
}
246272

273+
protected function assign_export_template_vars(array $form_data, array $errors = [])
274+
{
275+
$this->template->assign_vars([
276+
'S_ERROR' => !empty($errors),
277+
'ERROR_MSG' => implode('<br>', $errors),
278+
'EXPORT_DATE_FROM' => $form_data['export_date_from'],
279+
'EXPORT_DATE_TO' => $form_data['export_date_to'],
280+
'EXPORT_USER_ID' => $form_data['export_user_id'],
281+
'EXPORT_CONSENT_VER' => $form_data['export_consent_version'],
282+
'U_ACTION' => $this->u_action,
283+
]);
284+
}
285+
247286
protected function validate_form_key($form_key)
248287
{
249288
if (!check_form_key($form_key))

language/en/acp_consentmanager.php

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,17 +37,20 @@
3737
'ACP_CONSENTMANAGER_INVALID_INTEGRATION_ENTRY' => 'Integration entry %1$s is invalid. Each entry must include a safe id, supported category, and valid script source URL.',
3838
'EXAMPLE' => 'Example',
3939

40-
// Export consent logs
41-
'ACP_CONSENTMANAGER_EXPORT_EXPLAIN' => 'Download a CSV file of stored consent log records. All fields are optional; leave them blank to export the full log.',
42-
'ACP_CONSENTMANAGER_EXPORT_FILTERS' => 'Export filters',
40+
// Consent logs
41+
'ACP_CONSENTMANAGER_EXPORT_EXPLAIN' => 'Download a CSV file of stored consent log records or permanently delete matching records from the database. All fields are optional; leave them blank to work with the full log.',
42+
'ACP_CONSENTMANAGER_EXPORT_FILTERS' => 'Consent log filters',
4343
'ACP_CONSENTMANAGER_EXPORT_DATE_FROM' => 'Date from',
4444
'ACP_CONSENTMANAGER_EXPORT_DATE_TO' => 'Date to',
4545
'ACP_CONSENTMANAGER_EXPORT_DATE_EXPLAIN' => 'Use the browser date picker when available. If you cannot pick a date, enter it in YYYY-MM-DD format. Dates are interpreted in UTC. Leave blank to omit this boundary.',
4646
'ACP_CONSENTMANAGER_EXPORT_USER_ID' => 'User ID',
47-
'ACP_CONSENTMANAGER_EXPORT_USER_ID_EXPLAIN' => 'Enter a registered user ID to restrict the export to that user\'s consent records. Leave blank to include all users. Note: records for guests use a session-based identifier and cannot be filtered by user ID.',
47+
'ACP_CONSENTMANAGER_EXPORT_USER_ID_EXPLAIN' => 'Enter a registered user ID to restrict the export (or delete) to that users consent records. Leave blank to include all users.',
4848
'ACP_CONSENTMANAGER_EXPORT_VERSION' => 'Consent version',
49-
'ACP_CONSENTMANAGER_EXPORT_VERSION_EXPLAIN' => 'Restrict the export to a specific consent version. Leave blank for all versions.',
49+
'ACP_CONSENTMANAGER_EXPORT_VERSION_EXPLAIN' => 'Restrict the export (or delete) to a specific consent version. Leave blank for all versions.',
5050
'ACP_CONSENTMANAGER_EXPORT_DOWNLOAD' => 'Download CSV',
51+
'ACP_CONSENTMANAGER_DELETE' => 'Delete logs',
52+
'ACP_CONSENTMANAGER_DELETE_CONFIRM' => 'Are you sure you want to permanently delete the selected consent log records?',
53+
'ACP_CONSENTMANAGER_DELETE_SUCCESS' => 'The selected consent log records have been deleted.',
5154
'ACP_CONSENTMANAGER_EXPORT_INVALID_DATE_FROM' => 'The "Date from" value is not a valid date. Use the browser date picker when available, or enter the date in YYYY-MM-DD format.',
5255
'ACP_CONSENTMANAGER_EXPORT_INVALID_DATE_TO' => 'The "Date to" value is not a valid date. Use the browser date picker when available, or enter the date in YYYY-MM-DD format.',
5356
'ACP_CONSENTMANAGER_EXPORT_DATE_RANGE_INVALID' => '"Date from" must not be later than "Date to".',

language/en/info_acp_consentmanager.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,9 @@
2121
$lang = array_merge($lang, [
2222
'ACP_CONSENTMANAGER' => 'Consent Manager',
2323
'ACP_CONSENTMANAGER_SETTINGS' => 'Settings',
24-
'ACP_CONSENTMANAGER_EXPORT' => 'Export Consent Logs',
24+
'ACP_CONSENTMANAGER_EXPORT' => 'Consent Logs',
2525
'LOG_CONSENTMANAGER_UPDATED' => '<strong>Updated Consent Manager settings</strong>',
2626
'LOG_CONSENTMANAGER_REPROMPT' => '<strong>Forced Consent Manager re-prompt by increasing the consent version</strong>',
2727
'LOG_CONSENTMANAGER_EXPORT' => '<strong>Exported Consent Manager logs as CSV</strong>',
28+
'LOG_CONSENTMANAGER_DELETE' => '<strong>Deleted Consent Manager log records</strong>',
2829
]);

service/acp_manager.php

Lines changed: 52 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,21 @@ public function stream_logs_csv($handle, array $filters = [], $batch_size = 500)
215215
while ($count === $batch_size);
216216
}
217217

218+
/**
219+
* Delete consent log rows matching the supplied filters.
220+
*
221+
* @param array $filters Optional: date_from, date_to, user_id, consent_version
222+
*
223+
* @return int Number of deleted rows
224+
*/
225+
public function delete_logs(array $filters = [])
226+
{
227+
$sql = 'DELETE FROM ' . $this->consent_logs_table . $this->build_delete_filter_where($filters);
228+
$this->db->sql_query($sql);
229+
230+
return (int) $this->db->sql_affectedrows();
231+
}
232+
218233
/**
219234
* Compute the anonymized identifier for a given registered user ID.
220235
*
@@ -234,33 +249,14 @@ public function hash_user_id($user_id)
234249
}
235250

236251
/**
237-
* Add an admin log entry for consent settings changes.
238-
*
239-
* @return void
240-
*/
241-
public function log_admin_settings_updated()
242-
{
243-
$this->log->add('admin', $this->user->data['user_id'], $this->user->ip, 'LOG_CONSENTMANAGER_UPDATED');
244-
}
245-
246-
/**
247-
* Add an admin log entry when users are re-prompted for consent.
248-
*
249-
* @return void
250-
*/
251-
public function log_admin_reprompt()
252-
{
253-
$this->log->add('admin', $this->user->data['user_id'], $this->user->ip, 'LOG_CONSENTMANAGER_REPROMPT');
254-
}
255-
256-
/**
257-
* Add an admin log entry when consent logs are exported.
252+
* Add an admin log entry for an admin action in the settings.
258253
*
254+
* @param $message string Language key for the log message
259255
* @return void
260256
*/
261-
public function log_admin_export()
257+
public function log_admin_action($message)
262258
{
263-
$this->log->add('admin', $this->user->data['user_id'], $this->user->ip, 'LOG_CONSENTMANAGER_EXPORT');
259+
$this->log->add('admin', $this->user->data['user_id'], $this->user->ip, $message);
264260
}
265261

266262
/**
@@ -342,7 +338,38 @@ protected function get_integrations_json()
342338
*/
343339
protected function build_filter_where(array $filters, $last_id = 0)
344340
{
345-
$where = ['consent_log_id > ' . (int) $last_id];
341+
$where = array_merge(
342+
['consent_log_id > ' . (int) $last_id],
343+
$this->build_filter_conditions($filters)
344+
);
345+
346+
return ' WHERE ' . implode(' AND ', $where);
347+
}
348+
349+
/**
350+
* Build a WHERE clause for deleting consent logs.
351+
*
352+
* @param array $filters Filter map from parse_export_filters
353+
*
354+
* @return string SQL WHERE clause, or an empty string when no filters are set
355+
*/
356+
protected function build_delete_filter_where(array $filters)
357+
{
358+
$where = $this->build_filter_conditions($filters);
359+
360+
return empty($where) ? '' : ' WHERE ' . implode(' AND ', $where);
361+
}
362+
363+
/**
364+
* Build SQL filter conditions shared by export and delete operations.
365+
*
366+
* @param array $filters Filter map from parse_export_filters
367+
*
368+
* @return array
369+
*/
370+
protected function build_filter_conditions(array $filters)
371+
{
372+
$where = [];
346373

347374
if (!empty($filters['date_from']))
348375
{
@@ -365,7 +392,7 @@ protected function build_filter_where(array $filters, $last_id = 0)
365392
$where[] = 'consent_version = ' . (int) $filters['consent_version'];
366393
}
367394

368-
return ' WHERE ' . implode(' AND ', $where);
395+
return $where;
369396
}
370397

371398
protected function sanitize_csv_value($value)

tests/acp/acp_module_test.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ public function test_main_module()
121121

122122
public function test_main_module_export_mode()
123123
{
124-
$this->expect_controller_method('handle_export');
124+
$this->expect_controller_method('handle_logs');
125125

126126
$module = new \phpbb\consentmanager\acp\consentmanager_module();
127127
$module->u_action = 'adm.php?i=test&mode=export';

0 commit comments

Comments
 (0)