This page looks best with JavaScript enabled

Scuttle - Enable 'Approve User' Component

 ·  ☕ 10 min read

Background

This post shows how to implement a much needed (IMHO) Approve User component to Scuttle.

Shortly after I deployed my scuttle instance I started getting lots of new users. A little investigation found that spammers like this type of service to post links to and then refer people to those links. One of the main reasons being that they can bookmark a link such as http://spam.com/a-big-spam-page.html) and then pass on the link to the bookmark which looks like a legit link (most people would know http://spam.com/a-big-spam-page.html is spam and not go to the site but pointing someone to http://bookmarks.adercon.com/drad/ where they see a set of links may trick some people into believing it is a more legit site.

Needless to say, spammers like the site/feature that scuttle offers and were signing up in droves. My first few attempts were to blacklist spammers. This approach works well but requires a lot of management as you need to add email addresses or domains to a list. Upon signing up that list is consulted, if the new user has an email listed in the blocked list they are not allowed to create a new account. Works well, but most spammers simply get another email account…and its not feasible to block all @yahoo.com email address domains. This is where my second attempt came in (re: Removing Spam Accounts). It also works well, a little easier to manage but still a lot of work.

The first two attempts leverage work/patches provided through the scuttle forum, which were helpful but didn’t address my issues completely, which lead to the current approach - the Approve User component.

The Goal

As mentioned above, the goal is to add an Approve User component to Scuttle. This component still allows any user to request a new account; however, the user is not automatically granted an account but rather a request is submitted for a new account. The scuttle admin will receive the request and can then approve or reject the new account. If the new user’s account is approved, the new user is allowed access to the scuttle application and can then act like a normal scuttle user.
Implementing this component does require working with code (php) in several files but the process is not overly complicated and most who are willing / able to set up their own scuttle instance should have no problem deploying the mods for this feature.
Notice: I’ve updated this post (2011-04-10) to add in “User’s Registration IP Address”

Details

The Approve User component leverages the Admin Interface, more specific, the Removing Spam Accounts mod so please perform this task first.
The following list provides a brief overview of the changes needed to implement the Approve User component, refer to the link for each item for details on how to implement each task:

  • admin.php
    • add an approve and unapprove case to the $action switch which handles the approve/unapprove web requests
    • send the notification to the new user upon approval
  • services/userservice.php
    • add the approveUser and unapproveUser functions which carry out the approve/unapprove web request
    • disallow ‘unapproved’ users the ability to log in
  • templates/usrlist.tpl.php
    • customize the ‘manage users’ view/template that displays each user in the admin.php page (add the verified text and Approve / Unapprove links
  • register.php
    • notify site admin of new user request
    • get user’s IP/domain to pass this info along in the ‘approve user’ email request
  • database (sc_users table)
    • add the xVerified column to the table
    • set the admin user’s account to be ‘verified’ (allow admin user to log in)

Add Verified Column to Users Table

Issue the following SQL on your Scuttle database or add the equivalent column through your GUI DB editor of choice to add the ‘Verified’ column to the user’s table:

1
alter table sc_users, add column: xVerified, int, default 0, nullable, comment = Extension: account for verified (1) and unverified (0 or null) users.

Set Admin User Account to ‘Verified’

Issue the following SQL on your Scuttle database to ‘approve’/verify your ‘admin’ user. This will allow the admin user to log in after you’ve implemented the Approve User component but all other users will not be allowed to log in until you have approved them.

Note: if you have other user’s you wish to verify in bulk you can easily change the SQL below to approve other user’s.

1
UPDATE sc_users SET xVerified=1 WHERE uId = 1;

note: admin user is typically uId=1, please double check on your instance

If you would like to approve a set of users simply use and IN() such as:

1
UPDATE sc_users SET xVerified=1 WHERE uId IN(1,2,5,9,100,111);

Getting New User’s IP/Domain

As a new user signs up the scuttle admin will be notified via email. The user enters in a Username and Email address which is sent to the admin but it is often necessary to have the user’s IP address and/or domain. This allows you to check the IP/domain to ensure it is not a recognized spammers IP or domain. To add this functionality, add the following code to your register.php file near the top (I put it after $completed = FALSE;):

1
2
3
4
5
6
//get user's IP/domain for verification purposes.
if ($_SERVER['HTTP_X_FORWARD_FOR']) {
    $ip = $_SERVER['HTTP_X_FORWARD_FOR'];
} else {
    $ip = $_SERVER['REMOTE_ADDR'];
}

Email Site Admin of New User Request

This step notifies the site admin of the New User request. To add the functionality, add the following code to your register.php file inside the elseif ($userservice->addUser($posteduser, $_POST['password'], $postedmail,$ip)) { which is inside the if (!$completed) { which is inside the if ($_POST['submitted']) {, add the following code (I added it just before the ‘Your application has been submitted…’ message):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
if ( !$userservice->isBlockedEmail($postedmail)) {
    $headers = 'From: '. $adminemail;
    $message = wordwrap($message,70);</code>
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $message = sprintf(T_('%s New user registered: %s'), $sitename, $posteduser);
    $message .= '\n\n'.sprintf(T_('E-mail: %s'), $_POST['email']);
    $message .= '\n'.sprintf(T_('IP: %s'), $ip);
    $message .= '\n'.sprintf(T_('Domain: %s'), $domain);
    $message .= '\n'.sprintf(T_('UserId: %s'), $posteduser);
    $message = wordwrap($message, 70);
    $headers = 'From: '. $adminemail;
    $mail = mail($adminemail, sprintf(T_('%s New user registered: %s'),$sitename, $posteduser),$message, $headers);
}

Notice: I also modified the templates/register.tpl.php file and added a notice that all accounts require approval by site admin. I’d suggesting adding something to the page to let users know their account will not be active immediately and it lets spammers know there are more stringent rules in place on your site.

Customize Manage Users Template

In order for the site admin to be able to approve or unapprove users we need to modify the Manage Users template. Open the templates/userlist.tpl.php file and add the following code (note: I’ve added the full code for the &lt;div class='link'&gt; and &lt;div class='meta'&gt; so you can replace these two divs and all contents completely or customize as you see fit):

echo '&lt;div class='link'&gt;';
echo '&lt;a href=''.createURL('profile',$users[$key][$userservice-&gt;getFieldname('username')]).''&gt;'.$users[$key][$userservice-&gt;getFieldName('username')].'&lt;/a&gt;';
echo ' &lt;br/&gt;&amp;nbsp;&amp;nbsp;verified: '.$users[$key][$userservice-&gt;getFieldname('verified')].'';
echo ' &lt;br/&gt;&amp;nbsp;&amp;nbsp;email: '.$users[$key][$userservice-&gt;getFieldname('email')].'';
echo ' &lt;br/&gt;&amp;nbsp;&amp;nbsp;name: '.$users[$key][$userservice-&gt;getFieldname('name')].'';
echo ' &lt;br/&gt;&amp;nbsp;&amp;nbsp;homepage: '.$users[$key][$userservice-&gt;getFieldname('homepage')].'';
echo ' &lt;br/&gt;&amp;nbsp;&amp;nbsp;description: '.$users[$key][$userservice-&gt;getFieldname('description')].'';
echo '&lt;/div&gt;';
echo '&lt;div class='meta'&gt;';
echo '&lt;a<br />href=''.createURL('admin','delete/'.$users[$key][$userservice-&gt;getFieldname('username')]).''onclick='return confirm(\''.T_('Are you sure?').'\');'&gt;'.T_('Delete').'&lt;/a&gt;';
echo '&amp;nbsp;|&amp;nbsp;';if ( $users[$key][$userservice-&gt;getFieldname('verified')] == 0 ) {
echo '&lt;a<br />href=''.createURL('admin','approve/'.$users[$key][$userservice-&gt;getFieldname('username')]).'' onclick='return confirm(\''.T_('Are you sure?').'\');'&gt;'.T_('Approve').'&lt;/a&gt;'; } else {
echo '&lt;a<br />href=''.createURL('admin','unapprove/'.$users[$key][$userservice-&gt;getFieldname('username')]).'' onclick='return confirm(\''.T_('Are you sure?').'\');'&gt;'.T_('Unapprove').'&lt;/a&gt;'; }
echo '&lt;/div&gt;';

Disallow Unapproved Users Login

In order for the entire Approve User component to work we must require all user’s be ‘approved’ before letting them log in. To accomplish this, open the services/userservice.php file and modify the login function. The $query should be as follows:

1
$query = 'SELECT '. $this-&gt;getFieldName('primary') .' FROM '. $this-&gt;getTableName() .' WHERE '. $this-&gt;getFieldName('username') .' = ''. $this-&gt;db-&gt;sql_escape($username) .'' AND '.$this-&gt;getFieldName('password') .' = ''. $this-&gt;db-&gt;sql_escape($password) .'' AND xVerified = 1';

Add Approved/Unapproved User Functions

The approve/unapprove user functions handle the web request and actually perform the approve user/unapprove user call to the database. To implement the two functions open the services/userservice.php file and add the two functions:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
function approveUser($uId) {
    $query = 'UPDATE '. $this-&gt;getTableName() .' SET xVerified=1 WHERE uId = '.intval($uId);</code>
        if ( !($dbresult = &amp; $this-&gt;db-&gt;sql_query($query)) ) {
            message_die(GENERAL_ERROR, 'Could not approve user', '', __LINE__, __FILE__, $query, $this-&gt;db);
            return false;
        }
        return true;
}
function unapproveUser($uId) {
    $query = 'UPDATE '. $this-&gt;getTableName() .' SET xVerified=0 WHERE uId = '.intval($uId);
        if ( !($dbresult = &amp; $this-&gt;db-&gt;sql_query($query)) ) {
            message_die(GENERAL_ERROR, 'Could not unapprove user', '', __LINE__, __FILE__, $query, $this-&gt;db);
            return false;
        }
        return true;
}

Add Approve/Unapprove User Handlers

The approve/unapprove user handlers initiate the web request which calls the approve/unapprove user functions. To implement the two handlers open the admin.php file and the following two ‘case’ statements to the switch ( $action) {:

case 'unapprove':
    if ( $user &amp;&amp; ($userinfo = $userservice-&gt;getUserByUsername($user)) ) {
        $uId = $userinfo['uId'];
        $unapvd=$userservice-&gt;unapproveUser($uId);
        $tplVars['msg'] = sprintf(T_('User %s has been unapproved.'), $user);
    } else {
        echo('couldnt find user ('.$user.'), attempting lookup...');
        $userinfo = $userservice-&gt;getUserByUsername($user);
        $uId = $userinfo['uId'];
        echo('uId=['.$uId.']');
    }
    break;
case 'approve':
    if ( $user &amp;&amp; ($userinfo = $userservice-&gt;getUserByUsername($user)) ) {
        $uId = $userinfo['uId'];
        $apvd=$userservice-&gt;approveUser($uId);
        $tplVars['msg'] = sprintf(T_('User %s has been approved.'), $user);
        //send user email saying their account has been approved.
        $userEmail = $userinfo['email'];
        $message = 'Your registration has been approved. Please take this time to update your profile with your website and other info.';
        $message .= '';
        $message .= 'We do not sell or redistribute your information in any form; however, it is useful if we need to contact you.';
        $message .= '';
        $message .= 'If you have any issues or concerns please contact the site admin ('.$adminemail.')';
        $message .= '';
        $message .= 'Thank you and welcome to AC Bookmarks!';
        $message = wordwrap($message, 70);
        $headers = 'From: '. $adminemail;
        $mail = mail($userEmail, sprintf(T_('%s Registeration Approved %s'),$sitename,$posteduser),$message, $headers);
    } else {
        echo('couldnt find user ('.$user.'), attempting lookup...');
        $userinfo = $userservice-&gt;getUserByUsername($user);
        $uId = $userinfo['uId'];
        echo('uId=['.$uId.']');
    }
    break;

Send Approved Notification to New User

After the admin ‘approves’ a new user we want to notify the new user that their account has been approved. This has already been set for you in the Add Approve/Unapprove User Handlers, in specific, see the ‘approve’ case. You can customize the message to your liking.

Capture User’s Registeration IP Address

It is also useful to capture the user’s registration IP address for spam checking/reporting. This step is an easy task as the IP address of the user from registration is already captured (see above). To store this information you need to make the following changes (note: this is a high-level summary, if you need more details write in the comments):

  • Add the Database Column (xRegisteredFromIP)
    • alter table sc_users, add column: xRegisteredFromIP, VARCHA(20), default 0, nullable, comment = Extension: contains the IP address with which the user registered from.
  • Add registered IP to addUser function in services/userservice.php
  • Add register IP (registeredip) to addUser function call in register.php
  • Add IP to the admin.php for displaying Registered IP address echo ' &lt;br/&gt;&amp;nbsp;&amp;nbsp;&lt;span title='IP address from which the user registered' &gt;IP&lt;/span&gt;:<br />'.$users[$key][$userservice-&gt;getFieldname('registeredip')].'';
  • Add registeredip to userService getFieldname
    • this goes in the var $fields = array(

After you have implemented the above changes view your admin page and you will see the ‘IP’ column (note: user’s signed up prior to this change will not have an IP address shown).

Sample View

Manage Users Page

example of the approve user component's manage users page

Register Page

example of the approve user component's register page

Admin Notification Email

example of the approve user component's admin notification email

User Notification Email

example of the approve user component's user notification email

Source Code

The following source files have been provided:

If you experience any issues or problems please contact us and we’ll get back to you!

Share on

drad
WRITTEN BY
drad
Sr. Consultant