MyBB Community Forums

Full Version: How enable an user to easily delete his user (just with a link)
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Hi guys

I created my second Mybb Forum, which was created from my first one, which has already 12 thousand members.

So all of those members were registered automatically on this second one.

I wanted to give them a very easy way to cancel their account, even if they don't remember their password anymore. So I thought in sending them a link to a page (through a mass email) to enable them to cancel their account if they want to, in which they would confirm their email and have their account deleted (without deleting their threads and posts).

What would be the easiest way to do that? I don't want them to log into the forum to do that, as many wouldn't remember their passwords anymore.

I thought in creating a php page, they would open it already with their id hidden on it, and would have a field to confirm their email, and would post to another php which would effectively delete their account.

Is there already some api call to do that? Is there some example to start from?

This is exactly what I wanted to do:

1) Send email with link: A mass email is sent, it will contain a link to a php page on the forum domain. This link will carry the user id or the user login (I guess it would be the login, as mass emails don't have the userid as variable).

2) User clicks the link and opens the page: The user doesn't want to be a user on this forum, and then clicks on the link.

3) User fills the form with his email: The php page is opened, it informs that we are sorry he wants to unregister, but he can carry on removing the user filling a form so that he can put the email. This is to avoid people other than the user himself to remove other accounts which is not himself/herself.

4) Page processes the filled email and removes the user: The target of that form will be itself or another php page, which will take the user id, fetch the usermail and compare it with what the user filled on the form. If it matches it removes the user (that's what I don't know how to do) and sends to a page saying the removal has been done. It it doesn't match, it send it back to the form showing an error message.

Actually I'm not very good with PHP, but I think I can do everything except:


How to remove the user based on the user login?. I will need this on step 4, so that if the email of the user fetched from DB matches the email informed by the user I would then remove the user, without removing his posts.

I noticed on the code of the admin CP that on the delete user option I have:

Quote:index.php?module=user-users&action=delete&uid=48&my_post_key=...

and looking at the delete action inside the module/user/users.php we have a routine, which I modified a bit and came up with the following:

still missing changing the query to use the username
Quote:

$query = $db->simple_select("users", "*", "uid='".intval($mybb->input['uid'])."'");
$user = $db->fetch_array($query);

// Does the user not exist?
if(!$user['uid'])
{
echo('error: no user');
return;
}

// Delete the user
$db->delete_query("userfields", "ufid='{$user['uid']}'");
$db->delete_query("privatemessages", "uid='{$user['uid']}'");
$db->delete_query("events", "uid='{$user['uid']}'");
$db->delete_query("forumsubscriptions", "uid='{$user['uid']}'");
$db->delete_query("threadsubscriptions", "uid='{$user['uid']}'");
$db->delete_query("sessions", "uid='{$user['uid']}'");
$db->delete_query("banned", "uid='{$user['uid']}'");
$db->delete_query("threadratings", "uid='{$user['uid']}'");
$db->delete_query("users", "uid='{$user['uid']}'");
$db->delete_query("joinrequests", "uid='{$user['uid']}'");
$db->delete_query("warnings", "uid='{$user['uid']}'");
$db->delete_query("reputation", "uid='{$user['uid']}' OR adduid='{$user['uid']}'");
$db->delete_query("awaitingactivation", "uid='{$user['uid']}'");
//$db->delete_query("posts", "uid = '{$user['uid']}' AND visible = '-2'");
//$db->delete_query("threads", "uid = '{$user['uid']}' AND visible = '-2'");

// Update forum stats
update_stats(array('numusers' => '-1'));

// Update forums & threads if user is the lastposter
$db->update_query("posts", array('uid' => 0), "uid='{$user['uid']}'");
$db->update_query("forums", array("lastposteruid" => 0), "lastposteruid = '{$user['uid']}'");
$db->update_query("threads", array("lastposteruid" => 0), "lastposteruid = '{$user['uid']}'");

// Did this user have an uploaded avatar?
if($user['avatartype'] == "upload")
{
// Removes the ./ at the beginning the timestamp on the end...
@unlink("../".substr($user['avatar'], 2, -20));
}

// Was this user a moderator?
if(is_moderator($user['uid']))
{
$db->delete_query("moderators", "id='{$user['uid']}' AND isgroup = '0'");
$cache->update_moderators();
}


flash_message($lang->success_user_deleted, 'success');

Is this feasible to do? It doesn't necessarily needs to be a plugin. As I said, I could just drop a php page which would receive request, ask use the email for confirmation and then run the deletion and show confirmation.
I think I got it, here it is:

Quote:<?php

define("IN_MYBB",1);

require_once("global.php");

global $mybb, $db;

if ($_REQUEST['action']=="remover"){
$username=$_REQUEST['username'];
echo("<h2>Warning ".$username.": you will now remove your user from the Forum XX</h2>");

echo("</br>Please confirm your email on the field below and click the button remove user");
?>
<form action="http://localhost/mybb/removerusuario.php" method="GET">
<input type="text" name="email" value="">
<INPUT TYPE = "hidden" Name = "action" VALUE = "verificarEmail">
<INPUT TYPE = "hidden" Name = "username" VALUE = "<?php echo($username);?>">
<INPUT TYPE = "Submit" Name = "" VALUE = "Remove user ">
</form>
<?php
} else
if ($_REQUEST['action']=="verificarEmail"){
$email=$_REQUEST['email'];
$username=$_REQUEST['username'];
//debug: echo("email from db: ".getEmail($username));
if (getEmail($username)==$email)
{
echo("<br/>Email verified ok");
removeUser($username);
echo("<h2>Your user from forum XX has been removed</h2>");
} else {
echo("Email incorrect, try again");
?>
<form action="http://localhost/mybb/removerusuario.php" method="GET">
<input type="text" name="email" value="">
<INPUT TYPE = "hidden" Name = "action" VALUE = "verificarEmail">
<INPUT TYPE = "hidden" Name = "username" VALUE = "<?php echo($username);?>">
<INPUT TYPE = "Submit" Name = "" VALUE = "Remove user">
</form>
<?php

}
}

function getEmail($username){
global $mybb, $db;
$query = $db->simple_select("users", "*", "username='".$username."'");
$user = $db->fetch_array($query);
return $user['email'];
}

function removeUser($username){
global $mybb, $db;
$query = $db->simple_select("users", "*", "username='".$username."'");
$user = $db->fetch_array($query);

// Does the user not exist?
if(!$user['uid'])
{
echo('Erro, usuário inexistente');
return;
}

// Delete the user
$db->delete_query("userfields", "ufid='{$user['uid']}'");
$db->delete_query("privatemessages", "uid='{$user['uid']}'");
$db->delete_query("events", "uid='{$user['uid']}'");
$db->delete_query("forumsubscriptions", "uid='{$user['uid']}'");
$db->delete_query("threadsubscriptions", "uid='{$user['uid']}'");
$db->delete_query("sessions", "uid='{$user['uid']}'");
$db->delete_query("banned", "uid='{$user['uid']}'");
$db->delete_query("threadratings", "uid='{$user['uid']}'");
$db->delete_query("users", "uid='{$user['uid']}'");
$db->delete_query("joinrequests", "uid='{$user['uid']}'");
$db->delete_query("warnings", "uid='{$user['uid']}'");
$db->delete_query("reputation", "uid='{$user['uid']}' OR adduid='{$user['uid']}'");
$db->delete_query("awaitingactivation", "uid='{$user['uid']}'");

// Update forum stats
update_stats(array('numusers' => '-1'));

// Update forums & threads if user is the lastposter
$db->update_query("posts", array('uid' => 0), "uid='{$user['uid']}'");
$db->update_query("forums", array("lastposteruid" => 0), "lastposteruid = '{$user['uid']}'");
$db->update_query("threads", array("lastposteruid" => 0), "lastposteruid = '{$user['uid']}'");

// Did this user have an uploaded avatar?
if($user['avatartype'] == "upload")
{
// Removes the ./ at the beginning the timestamp on the end...
@unlink("../".substr($user['avatar'], 2, -20));
}

}

?>

Is this ok? Is it dangerous in anyway? It would just remove the user if the email is correct.

it worked here, and it seems nothing else were affected. It even kept all threads and replies from the user.

I could even create a table to register all deleted users, just to know who removed themselves.

what you guys think?
It is vulnerable to SQL injection, I think.
(2014-02-26, 02:39 AM)Omar G. Wrote: [ -> ]It is vulnerable to SQL injection, I think.

Would you have any suggestion on how to make it safe?

right now it is working. I will leave it only for a few days after all users receive the mass email.

Any suggestions would be really appreciated.
$username should be escaped before using it in query with $db->escape_string(). Next thing - htmlspecialchars_uni() should be used on it before outputting it to HTML to prevent XSS attacks.

Moreover, your method is highly insecure in general. What if someone knows your E-mail? He can easily delete your account too.
Is not the password the same for both forums? If they are, just install a plugin on forum "B" to allow users to delete their accounts directly from their UCP. You could allow this for a limited time if you want.
Thanks Omar G. But many people would have forgotten their passwords, and I wanted to make as easy as possible for them to remove their users, and this way would need them to reset their passwords, which has been a cause of problems for many users already.

This way I had already almost 70 users that chose to remove their users in the new forum Smile
I will also leave for a limited time this page available.