summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--_test/tests/inc/auth_deleteprofile.test.php179
-rw-r--r--inc/actions.php28
-rw-r--r--inc/auth.php39
-rw-r--r--inc/confutils.php5
-rw-r--r--inc/html.php17
-rw-r--r--inc/lang/de-informal/lang.php7
-rw-r--r--inc/lang/de/lang.php7
-rw-r--r--inc/lang/en/lang.php7
-rw-r--r--lib/plugins/config/lang/de-informal/lang.php1
-rw-r--r--lib/plugins/config/lang/de/lang.php1
-rw-r--r--lib/plugins/config/lang/en/lang.php1
-rw-r--r--lib/plugins/config/settings/config.metadata.php2
-rw-r--r--lib/tpl/dokuwiki/css/_forms.css5
13 files changed, 288 insertions, 11 deletions
diff --git a/_test/tests/inc/auth_deleteprofile.test.php b/_test/tests/inc/auth_deleteprofile.test.php
new file mode 100644
index 000000000..dc38fcd16
--- /dev/null
+++ b/_test/tests/inc/auth_deleteprofile.test.php
@@ -0,0 +1,179 @@
+<?php
+
+class Mock_Auth_Plugin extends DokuWiki_Auth_Plugin {
+
+ public $loggedOff = false;
+
+ public function __construct($canDeleteUser = true) {
+ $this->cando['delUser'] = $canDeleteUser;
+ }
+
+ public function checkPass($user, $pass) {
+ return $pass == 'password';
+ }
+
+ public function deleteUsers($users) {
+ return in_array($_SERVER['REMOTE_USER'], $users);
+ }
+
+ public function logoff() {
+ $this->loggedOff = true;
+ }
+
+}
+
+class auth_deleteprofile_test extends DokuWikiTest {
+
+ /*
+ * Tests:
+ *
+ * 1. It works and the user is logged off
+ * 2. Password matches when config requires it
+ * 3,4. Auth plugin can prevent & wiki config can prevent
+ * 5. Any of invalid security token, missing/not set 'delete' flag, missing/unchecked 'confirm_delete'
+ *
+ */
+
+ function test_success() {
+
+ global $ACT, $INPUT, $conf, $auth;
+
+ $ACT = 'profile_delete';
+ $conf['profileconfirm'] = false;
+ $_SERVER['REMOTE_USER'] = 'testuser';
+
+ $input = array(
+ 'do' => $ACT,
+ 'sectok' => getSecurityToken(),
+ 'delete' => '1',
+ 'confirm_delete' => '1',
+ );
+
+ $_POST = $input;
+ $_REQUEST = $input;
+ $INPUT = new Input();
+
+ $auth = new Mock_Auth_Plugin();
+
+ $this->assertTrue(auth_deleteprofile());
+ $this->assertTrue($auth->loggedOff);
+ }
+
+ function test_confirmation_required() {
+
+ global $ACT, $INPUT, $conf, $auth;
+
+ $ACT = 'profile_delete';
+ $conf['profileconfirm'] = true;
+ $_SERVER['REMOTE_USER'] = 'testuser';
+
+ $input = array(
+ 'do' => $ACT,
+ 'sectok' => getSecurityToken(),
+ 'delete' => '1',
+ 'confirm_delete' => '1',
+ 'oldpass' => 'wrong',
+ );
+
+ $_POST = $input;
+ $_REQUEST = $input;
+ $INPUT = new Input();
+
+ $auth = new Mock_Auth_Plugin();
+
+ // password check required - it fails, so don't delete profile
+ $this->assertFalse(auth_deleteprofile());
+
+ // now it passes, we're good to go
+ $INPUT->set('oldpass','password');
+ $INPUT->post->set('oldpass','password');
+ $this->assertTrue(auth_deleteprofile());
+ }
+
+ function test_authconfig_prevents() {
+
+ global $ACT, $INPUT, $conf, $auth;
+
+ $ACT = 'profile_delete';
+ $conf['profileconfirm'] = false;
+ $_SERVER['REMOTE_USER'] = 'testuser';
+
+ $input = array(
+ 'do' => $ACT,
+ 'sectok' => getSecurityToken(),
+ 'delete' => '1',
+ 'confirm_delete' => '1',
+ );
+
+ $_POST = $input;
+ $_REQUEST = $input;
+ $INPUT = new Input();
+
+ $auth = new Mock_Auth_Plugin(false);
+ $conf['disableactions'] = '';
+ $this->assertFalse(auth_deleteprofile());
+ }
+
+ function test_wikiconfig_prevents() {
+
+ global $ACT, $INPUT, $conf, $auth;
+
+ $ACT = 'profile_delete';
+ $conf['profileconfirm'] = false;
+ $_SERVER['REMOTE_USER'] = 'testuser';
+
+ $input = array(
+ 'do' => $ACT,
+ 'sectok' => getSecurityToken(),
+ 'delete' => '1',
+ 'confirm_delete' => '1',
+ );
+
+ $_POST = $input;
+ $_REQUEST = $input;
+ $INPUT = new Input();
+
+ $auth = new Mock_Auth_Plugin();
+ $conf['disableactions'] = 'profile_delete';
+
+ $this->assertFalse(actionOK('profile_delete'));
+ $this->assertTrue($auth->canDo('delUser'));
+
+ $this->assertFalse(auth_deleteprofile());
+ }
+
+ function test_basic_parameters() {
+
+ global $ACT, $INPUT, $conf, $auth;
+
+ $ACT = 'profile_delete';
+ $conf['profileconfirm'] = true;
+ $_SERVER['REMOTE_USER'] = 'testuser';
+
+ $input = array(
+ 'do' => $ACT,
+ 'sectok' => getSecurityToken(),
+ 'delete' => '1',
+ 'confirm_delete' => '1',
+ 'oldpass' => 'password',
+ );
+
+ $_POST = $input;
+ $_REQUEST = $input;
+ $input_foundation = new Input();
+
+ $auth = new Mock_Auth_Plugin();
+
+ $INPUT = clone $input_foundation;
+ $INPUT->remove('delete');
+ $this->assertFalse(auth_deleteprofile());
+
+ $INPUT = clone $input_foundation;
+ $INPUT->set('sectok','wrong');
+ $this->assertFalse(auth_deleteprofile());
+
+ $INPUT = clone $input_foundation;
+ $INPUT->remove('confirm_delete');
+ $this->assertFalse(auth_deleteprofile());
+ }
+} \ No newline at end of file
diff --git a/inc/actions.php b/inc/actions.php
index da3414eb2..bf124c887 100644
--- a/inc/actions.php
+++ b/inc/actions.php
@@ -92,14 +92,26 @@ function act_dispatch(){
$ACT = 'login';
}
- //update user profile
- if ($ACT == 'profile') {
+ // user profile changes
+ if (in_array($ACT, array('profile','profile_delete'))) {
if(!$_SERVER['REMOTE_USER']) {
$ACT = 'login';
} else {
- if(updateprofile()) {
- msg($lang['profchanged'],1);
- $ACT = 'show';
+ switch ($ACT) {
+ case 'profile' :
+ if(updateprofile()) {
+ msg($lang['profchanged'],1);
+ $ACT = 'show';
+ }
+ break;
+ case 'profile_delete' :
+ if(auth_deleteprofile()){
+ msg($lang['profdeleted'],1);
+ $ACT = 'show';
+ } else {
+ $ACT = 'profile';
+ }
+ break;
}
}
}
@@ -247,7 +259,7 @@ function act_validate($act) {
//disable all acl related commands if ACL is disabled
if(!$conf['useacl'] && in_array($act,array('login','logout','register','admin',
'subscribe','unsubscribe','profile','revert',
- 'resendpwd'))){
+ 'resendpwd','profile_delete'))){
msg('Command unavailable: '.htmlspecialchars($act),-1);
return 'show';
}
@@ -258,7 +270,7 @@ function act_validate($act) {
if(!in_array($act,array('login','logout','register','save','cancel','edit','draft',
'preview','search','show','check','index','revisions',
'diff','recent','backlink','admin','subscribe','revert',
- 'unsubscribe','profile','resendpwd','recover',
+ 'unsubscribe','profile','profile_delete','resendpwd','recover',
'draftdel','sitemap','media')) && substr($act,0,7) != 'export_' ) {
msg('Command unknown: '.htmlspecialchars($act),-1);
return 'show';
@@ -287,7 +299,7 @@ function act_permcheck($act){
}else{
$permneed = AUTH_CREATE;
}
- }elseif(in_array($act,array('login','search','recent','profile','index', 'sitemap'))){
+ }elseif(in_array($act,array('login','search','recent','profile','profile_delete','index', 'sitemap'))){
$permneed = AUTH_NONE;
}elseif($act == 'revert'){
$permneed = AUTH_ADMIN;
diff --git a/inc/auth.php b/inc/auth.php
index a1c92ec80..be6b7ebbe 100644
--- a/inc/auth.php
+++ b/inc/auth.php
@@ -1042,6 +1042,45 @@ function updateprofile() {
return false;
}
+function auth_deleteprofile(){
+ global $conf;
+ global $lang;
+ /* @var DokuWiki_Auth_Plugin $auth */
+ global $auth;
+ /* @var Input $INPUT */
+ global $INPUT;
+
+ if(!$INPUT->post->bool('delete')) return false;
+ if(!checkSecurityToken()) return false;
+
+ // action prevented or auth module disallows
+ if(!actionOK('profile_delete') || !$auth->canDo('delUser')) {
+ msg($lang['profnodelete'], -1);
+ return false;
+ }
+
+ if(!$INPUT->post->bool('confirm_delete')){
+ msg($lang['profconfdeletemissing'], -1);
+ return false;
+ }
+
+ if($conf['profileconfirm']) {
+ if(!$auth->checkPass($_SERVER['REMOTE_USER'], $INPUT->post->str('oldpass'))) {
+ msg($lang['badpassconfirm'], -1);
+ return false;
+ }
+ }
+
+ $deleted[] = $_SERVER['REMOTE_USER'];
+ if($auth->triggerUserMod('delete', array($deleted))) {
+ // force and immediate logout including removing the sticky cookie
+ auth_logoff();
+ return true;
+ }
+
+ return false;
+}
+
/**
* Send a new password
*
diff --git a/inc/confutils.php b/inc/confutils.php
index 404cc6050..0ac003b72 100644
--- a/inc/confutils.php
+++ b/inc/confutils.php
@@ -241,7 +241,7 @@ function getConfigFiles($type) {
*/
function actionOK($action){
static $disabled = null;
- if(is_null($disabled)){
+ if(is_null($disabled) || defined('SIMPLE_TEST')){
global $conf;
/** @var auth_basic $auth */
global $auth;
@@ -261,6 +261,9 @@ function actionOK($action){
if (is_null($auth) || !$auth->canDo('Profile')) {
$disabled[] = 'profile';
}
+ if (is_null($auth) || !$auth->canDo('delUser')) {
+ $disabled[] = 'profile_delete';
+ }
if (is_null($auth)) {
$disabled[] = 'login';
}
diff --git a/inc/html.php b/inc/html.php
index 614cf172c..be5ea7795 100644
--- a/inc/html.php
+++ b/inc/html.php
@@ -1390,6 +1390,23 @@ function html_updateprofile(){
$form->endFieldset();
html_form('updateprofile', $form);
+
+ if ($auth->canDo('delUser') && actionOK('profile_delete')) {
+ $form_profiledelete = new Doku_Form(array('id' => 'dw__profiledelete'));
+ $form_profiledelete->startFieldset($lang['profdeleteuser']);
+ $form_profiledelete->addHidden('do', 'profile_delete');
+ $form_profiledelete->addHidden('delete', '1');
+ $form_profiledelete->addElement(form_makeCheckboxField('confirm_delete', '1', $lang['profconfdelete'],'dw__confirmdelete','', array('required' => 'required')));
+ if ($conf['profileconfirm']) {
+ $form_profiledelete->addElement(form_makeTag('br'));
+ $form_profiledelete->addElement(form_makePasswordField('oldpass', $lang['oldpass'], '', 'block', array('size'=>'50', 'required' => 'required')));
+ }
+ $form_profiledelete->addElement(form_makeButton('submit', '', $lang['btn_deleteuser']));
+ $form_profiledelete->endFieldset();
+
+ html_form('profiledelete', $form_profiledelete);
+ }
+
print '</div>'.NL;
}
diff --git a/inc/lang/de-informal/lang.php b/inc/lang/de-informal/lang.php
index 9a6e6f72c..aaf92ef35 100644
--- a/inc/lang/de-informal/lang.php
+++ b/inc/lang/de-informal/lang.php
@@ -64,6 +64,7 @@ $lang['btn_revert'] = 'Wiederherstellen';
$lang['btn_register'] = 'Registrieren';
$lang['btn_apply'] = 'Übernehmen';
$lang['btn_media'] = 'Medien-Manager';
+$lang['btn_deleteuser'] = 'Benutzerprofil löschen';
$lang['loggedinas'] = 'Angemeldet als';
$lang['user'] = 'Benutzername';
$lang['pass'] = 'Passwort';
@@ -75,6 +76,7 @@ $lang['fullname'] = 'Voller Name';
$lang['email'] = 'E-Mail';
$lang['profile'] = 'Benutzerprofil';
$lang['badlogin'] = 'Nutzername oder Passwort sind falsch.';
+$lang['badpassconfirm'] = 'Das Passwort war falsch.';
$lang['minoredit'] = 'Kleine Änderung';
$lang['draftdate'] = 'Entwurf gespeichert am';
$lang['nosecedit'] = 'Diese Seite wurde in der Zwischenzeit geändert, da das Sektionsinfo veraltet ist. Die ganze Seite wird stattdessen geladen.';
@@ -91,6 +93,11 @@ $lang['profna'] = 'Änderung des Benutzerprofils in diesem Wiki n
$lang['profnochange'] = 'Keine Änderungen, nichts zu tun.';
$lang['profnoempty'] = 'Es muss ein Name oder eine E-Mail Adresse angegeben werden.';
$lang['profchanged'] = 'Benutzerprofil erfolgreich geändert.';
+$lang['profnodelete'] = 'Dieses Wiki unterstützt nicht das Löschen von Benutzern.';
+$lang['profdeleteuser'] = 'Benutzerprofil löschen';
+$lang['profdeleted'] = 'Dein Benutzerprofil wurde im Wiki gelöscht.';
+$lang['profconfdelete'] = 'Ich möchte mein Benutzerprofil löschen.<br/> Diese Aktion ist nicht umkehrbar.';
+$lang['profconfdeletemissing'] = 'Bestätigungs-Checkbox wurde nicht angehakt.';
$lang['pwdforget'] = 'Passwort vergessen? Fordere ein neues an';
$lang['resendna'] = 'Passwörter versenden ist in diesem Wiki nicht möglich.';
$lang['resendpwd'] = 'Neues Passwort setzen für';
diff --git a/inc/lang/de/lang.php b/inc/lang/de/lang.php
index aa0a3d3b2..f26a3cb49 100644
--- a/inc/lang/de/lang.php
+++ b/inc/lang/de/lang.php
@@ -65,6 +65,7 @@ $lang['btn_revert'] = 'Wiederherstellen';
$lang['btn_register'] = 'Registrieren';
$lang['btn_apply'] = 'Übernehmen';
$lang['btn_media'] = 'Medien-Manager';
+$lang['btn_deleteuser'] = 'Benutzerprofil löschen';
$lang['loggedinas'] = 'Angemeldet als';
$lang['user'] = 'Benutzername';
$lang['pass'] = 'Passwort';
@@ -76,6 +77,7 @@ $lang['fullname'] = 'Voller Name';
$lang['email'] = 'E-Mail';
$lang['profile'] = 'Benutzerprofil';
$lang['badlogin'] = 'Nutzername oder Passwort sind falsch.';
+$lang['badpassconfirm'] = 'Das Passwort war falsch.';
$lang['minoredit'] = 'kleine Änderung';
$lang['draftdate'] = 'Entwurf gespeichert am';
$lang['nosecedit'] = 'Diese Seite wurde in der Zwischenzeit geändert, Sektionsinfo ist veraltet, lade stattdessen volle Seite.';
@@ -92,6 +94,11 @@ $lang['profna'] = 'Änderung des Benutzerprofils in diesem Wiki n
$lang['profnochange'] = 'Keine Änderungen, nichts zu tun.';
$lang['profnoempty'] = 'Es muss ein Name und eine E-Mail-Adresse angegeben werden.';
$lang['profchanged'] = 'Benutzerprofil erfolgreich geändert.';
+$lang['profnodelete'] = 'Dieses Wiki unterstützt nicht das Löschen von Benutzern.';
+$lang['profdeleteuser'] = 'Benutzerprofil löschen';
+$lang['profdeleted'] = 'Ihr Benutzerprofil wurde im Wiki gelöscht.';
+$lang['profconfdelete'] = 'Ich möchte mein Benutzerprofil löschen.<br/> Diese Aktion ist nicht umkehrbar.';
+$lang['profconfdeletemissing'] = 'Bestätigungs-Checkbox wurde nicht angehakt.';
$lang['pwdforget'] = 'Passwort vergessen? Fordere ein neues an';
$lang['resendna'] = 'Passwörter versenden ist in diesem Wiki nicht möglich.';
$lang['resendpwd'] = 'Neues Passwort setzen für';
diff --git a/inc/lang/en/lang.php b/inc/lang/en/lang.php
index 00e71d254..630ccb3ff 100644
--- a/inc/lang/en/lang.php
+++ b/inc/lang/en/lang.php
@@ -51,6 +51,7 @@ $lang['btn_revert'] = 'Restore';
$lang['btn_register'] = 'Register';
$lang['btn_apply'] = 'Apply';
$lang['btn_media'] = 'Media Manager';
+$lang['btn_deleteuser'] = 'Remove My Account';
$lang['loggedinas'] = 'Logged in as';
$lang['user'] = 'Username';
@@ -63,6 +64,7 @@ $lang['fullname'] = 'Real name';
$lang['email'] = 'E-Mail';
$lang['profile'] = 'User Profile';
$lang['badlogin'] = 'Sorry, username or password was wrong.';
+$lang['badpassconfirm'] = 'Sorry, the password was wrong';
$lang['minoredit'] = 'Minor Changes';
$lang['draftdate'] = 'Draft autosaved on'; // full dformat date will be added
$lang['nosecedit'] = 'The page was changed in the meantime, section info was out of date loaded full page instead.';
@@ -81,6 +83,11 @@ $lang['profna'] = 'This wiki does not support profile modificatio
$lang['profnochange'] = 'No changes, nothing to do.';
$lang['profnoempty'] = 'An empty name or email address is not allowed.';
$lang['profchanged'] = 'User profile successfully updated.';
+$lang['profnodelete'] = 'This wiki does not support deleting users';
+$lang['profdeleteuser'] = 'Delete Account';
+$lang['profdeleted'] = 'Your user account has been deleted from this wiki';
+$lang['profconfdelete'] = 'I wish to remove my account from this wiki. <br/> This action can not be undone.';
+$lang['profconfdeletemissing'] = 'Confirmation check box not ticked';
$lang['pwdforget'] = 'Forgotten your password? Get a new one';
$lang['resendna'] = 'This wiki does not support password resending.';
diff --git a/lib/plugins/config/lang/de-informal/lang.php b/lib/plugins/config/lang/de-informal/lang.php
index 81cdc0e70..a499f1fc6 100644
--- a/lib/plugins/config/lang/de-informal/lang.php
+++ b/lib/plugins/config/lang/de-informal/lang.php
@@ -86,6 +86,7 @@ $lang['disableactions'] = 'Deaktiviere DokuWiki\'s Zugriffe';
$lang['disableactions_check'] = 'Check';
$lang['disableactions_subscription'] = 'Bestellen/Abbestellen';
$lang['disableactions_wikicode'] = 'Zeige Quelle/Exportiere Rohdaten';
+$lang['disableactions_profile_delete'] = 'Eigenes Benutzerprofil löschen';
$lang['disableactions_other'] = 'Weitere Aktionen (durch Komma getrennt)';
$lang['auth_security_timeout'] = 'Zeitüberschreitung bei der Authentifizierung (Sekunden)';
$lang['securecookie'] = 'Sollen Cookies, die via HTTPS gesetzt wurden nur per HTTPS versendet werden? Deaktiviere diese Option, wenn nur der Login deines Wikis mit SSL gesichert ist, aber das Betrachten des Wikis ungesichert geschieht.';
diff --git a/lib/plugins/config/lang/de/lang.php b/lib/plugins/config/lang/de/lang.php
index f2ada5f7b..a34348b61 100644
--- a/lib/plugins/config/lang/de/lang.php
+++ b/lib/plugins/config/lang/de/lang.php
@@ -98,6 +98,7 @@ $lang['disableactions'] = 'DokuWiki-Aktionen deaktivieren';
$lang['disableactions_check'] = 'Check';
$lang['disableactions_subscription'] = 'Seiten-Abonnements';
$lang['disableactions_wikicode'] = 'Quelltext betrachten/exportieren';
+$lang['disableactions_profile_delete'] = 'Eigenes Benutzerprofil löschen';
$lang['disableactions_other'] = 'Andere Aktionen (durch Komma getrennt)';
$lang['sneaky_index'] = 'Standardmäßig zeigt DokuWiki alle Namensräume in der Übersicht. Wenn diese Option aktiviert wird, werden alle Namensräume, für die der Benutzer keine Lese-Rechte hat, nicht angezeigt. Dies kann unter Umständen dazu führen, das lesbare Unter-Namensräume nicht angezeigt werden und macht die Übersicht evtl. unbrauchbar in Kombination mit bestimmten ACL Einstellungen.';
$lang['auth_security_timeout'] = 'Authentifikations-Timeout (Sekunden)';
diff --git a/lib/plugins/config/lang/en/lang.php b/lib/plugins/config/lang/en/lang.php
index 2d012701b..394c67eb3 100644
--- a/lib/plugins/config/lang/en/lang.php
+++ b/lib/plugins/config/lang/en/lang.php
@@ -104,6 +104,7 @@ $lang['disableactions'] = 'Disable DokuWiki actions';
$lang['disableactions_check'] = 'Check';
$lang['disableactions_subscription'] = 'Subscribe/Unsubscribe';
$lang['disableactions_wikicode'] = 'View source/Export Raw';
+$lang['disableactions_profile_delete'] = 'Delete Own Account';
$lang['disableactions_other'] = 'Other actions (comma separated)';
$lang['auth_security_timeout'] = 'Authentication Security Timeout (seconds)';
$lang['securecookie'] = 'Should cookies set via HTTPS only be sent via HTTPS by the browser? Disable this option when only the login of your wiki is secured with SSL but browsing the wiki is done unsecured.';
diff --git a/lib/plugins/config/settings/config.metadata.php b/lib/plugins/config/settings/config.metadata.php
index 2fb08037d..5d9b049a4 100644
--- a/lib/plugins/config/settings/config.metadata.php
+++ b/lib/plugins/config/settings/config.metadata.php
@@ -128,7 +128,7 @@ $meta['manager'] = array('string');
$meta['profileconfirm'] = array('onoff');
$meta['rememberme'] = array('onoff');
$meta['disableactions'] = array('disableactions',
- '_choices' => array('backlink','index','recent','revisions','search','subscription','register','resendpwd','profile','edit','wikicode','check'),
+ '_choices' => array('backlink','index','recent','revisions','search','subscription','register','resendpwd','profile','profile_delete','edit','wikicode','check'),
'_combine' => array('subscription' => array('subscribe','unsubscribe'), 'wikicode' => array('source','export_raw')));
$meta['auth_security_timeout'] = array('numeric');
$meta['securecookie'] = array('onoff');
diff --git a/lib/tpl/dokuwiki/css/_forms.css b/lib/tpl/dokuwiki/css/_forms.css
index 6744750ba..84b7db8e1 100644
--- a/lib/tpl/dokuwiki/css/_forms.css
+++ b/lib/tpl/dokuwiki/css/_forms.css
@@ -79,7 +79,10 @@
#dw__register fieldset {
padding-bottom: 0.7em;
}
-
+#dw__profiledelete {
+ display: block;
+ margin-top: 2.8em;
+}
/**
* Styles for the subscription page