Shortly after joining Redbooth as an employee, I began playing with the collaboration platform’s application user interface. As a writer who also writes code, I was curious to see whether I could come up with something useful.
The Redbooth API makes use of the OAuth2 authentication method, which provides a standard way for a user of one application to give permission for another application to access protected resources. For example, once the test is past, an external application that has received the user’s blessing can retrieve access files stored in a Redbooth workspace or add tasks to a task list. The application retrieves a cryptographic authentication token from Redbooth, which it then uses as proof of its right to access these resources.
One of the first ideas I had was to display some sort of interactive user directory. I can imagine a few different scenarios where it might be handy to store some supplemental information about employee performance or vacation schedules in your own app, using the data structure you define rather than one provided within Redbooth.
This version shown below (which you can access live here) pulls the names and profile photos for all the other users in your organization and allows you to add notes to each of these mini-profiles.
Note that you’re welcome to use this application for real, as long as you’re willing to do so at your own risk; it’s not running on Redbooth’s secure infrastructure, and the data you add goes into a MySQL database on my server. If you have a serious application for something like this, you could use the code shown below as a starting point (if you’re working in PHP) or as inspiration for an app you might implement in the language of your choice, on your own server.

The preliminary setup starts in initialize.php, which sends a request to redbooth.com to start the OAuth authentication process:
initialize.php
<?php $apikey = 'KEY_GOES_HERE'; // make sure to url encode the redirect URL $q = urlencode('http://tabmgr.com/rb/auth.php'); //provide the url for auth.php on your server // construct the authorization query with our apikey and the redirect URL $endpoint = 'https://redbooth.com/oauth2/authorize?client_id=' . $apikey . '&redirect_uri=' . $q . '&response_type=code'; //redirect to authorization URL header("Location: " . $endpoint); exit; ?>
The main workhorse functions are in auth.php. In the previous step, we queried redbooth.com for a code to be used to kick off the authentication process. The code is returned as a GET query parameter appended to the redirect uri specified in initialize.php. The API key and API secret are used to verify that the user has given permission for access to his or her redbooth.com account. The remainder of the code in this script is devoted to sorting the user records by last name, formatting them for display, and setting up a JQuery/AJAX routine to post notes about each user to a local database.
Any existing notes are retrieved as part of a database routine that runs right before we start iterating through the user records retrieved from redbooth.com.
auth.php
<?php session_start(); ?> <!doctype html> <html> <head> <meta charset="utf-8"> <title>User Directory Demo</title> <style> textarea { width: 600px; border: thin solid blue; height: 2em; } body { background-color: #CC0000; } #content { width: 700px; padding-left: 15px; padding-right: 15px; margin-left: auto; margin-right: auto; background-color: #eee; } </style> </head> <body> <div id="content"> <h1>Dave's unofficial API demo</h1> <p>Once authorized, the app pulls a list of the other users in your organization from Redbooth. You can add a note to any user record by typing it into the blank and pressing enter.</p> <?php function rb_authorize () { $code = $_GET["code"]; $apikey = 'KEY_GOES_HERE'; $appsecret = 'SECRET_GOES_HERE'; // make sure to url encode the return URL $q = urlencode('http://tabmgr.com/rb/auth.php'); //ex: http://www.mytest.com/auth.php // construct the authorization query with our apikey and the returned code to get the access_token $endpoint = 'https://redbooth.com/oauth2/token?client_id=' . $apikey . '&client_secret=' . $appsecret . '&code=' . $code . '&grant_type=authorization_code&redirect_uri=' . $q; // setup curl to make a call to the endpoint $session = curl_init($endpoint); // indicates that we want the response back curl_setopt($session, CURLOPT_RETURNTRANSFER, true); // post curl_setopt($session, CURLOPT_POST, true); // exec curl and get the data back $data = curl_exec($session); // remember to close the curl session once we are finished retrieveing the data curl_close($session); // decode the json data to make it easier to parse the php $auth_result = json_decode($data); // check for empty data if ($auth_result === NULL) die('Error parsing json for auth result'); // Get the access_token $_SESSION["access_token"] = $access_token = $auth_result->access_token; return $access_token; } function get_me($access_token) { // construct the query with the access_token to get the user's account details $endpoint = 'https://redbooth.com/api/3/me?access_token=' . $access_token; // setup curl to make a call to the endpoint $session = curl_init($endpoint); // indicates that we want the response back curl_setopt($session, CURLOPT_RETURNTRANSFER, true); // exec curl and get the data back $data = curl_exec($session); // remember to close the curl session once we are finished retrieveing the data curl_close($session); // decode the json data to make it easier to parse the php $me = json_decode($data); return $me; } if($_SESSION["access_token"] && !$_GET["new"]) $access_token = $_SESSION["access_token"]; // todo - check expiration else { // Get the returned code $access_token = rb_authorize (); } $me = get_me($access_token); // check for empty data if ($me === NULL) { // try again to get current user data $access_token = rb_authorize (); $me = get_me($access_token); } if ($me === NULL) die('Error parsing json for /me'); // construct the query with the access_token to get the user's account details $endpoint = 'https://redbooth.com/api/3/users?access_token=' . $access_token; // setup curl to make a call to the endpoint $session = curl_init($endpoint); // indicates that we want the response back curl_setopt($session, CURLOPT_RETURNTRANSFER, true); // exec curl and get the data back $data = curl_exec($session); // remember to close the curl session once we are finished retrieveing the data curl_close($session); // decode the json data to make it easier to parse the php $users = json_decode($data); // check for empty data if ($users === NULL) die('Error parsing json for users listing: '.$data); $count = sizeof($users); echo "<p><em>Fetched $count users</em></p>"; // get any status notes about the users from the database and put them in an array // keyed to the redbooth username include "db.php"; $sql = "SELECT * FROM status ORDER BY timestamp DESC"; foreach ($conn->query($sql) as $row) { $stat[$row['username']] .= '<p>'.$row['text'] . "<br /><em>posted by @" . $row["by"] .' at ' . date('F j, Y',strtotime($row["timestamp"]))."</em><p>\n"; } foreach($users as $user) { $uindex = strtolower(preg_replace('/[^A-Za-z]/','',$user->last_name.$user->first_name.$user->email)); $user_directory[$uindex] = sprintf(" <div style=\"float: right; clear:both\"><img src=\"%s\"></div> <p> <strong>First Name</strong>: %s<br /> <strong>Last Name</strong>: %s<br /> <strong>Email</strong>: %s </p> <p> <textarea class=\"status\" id=\"get_%s\" subject_username=\"%s\" me_username=\"%s\"></textarea> </p> <div id=\"postresult_%s\" ></div> %s ",$user->avatar_url, $user->first_name, $user->last_name, $user->email, $user->username, $user->username, $me->username, $user->username, $stat[$user->username]); } ksort($user_directory); foreach ($user_directory as $profile) echo $profile; ?> </div> <script src="https://code.jquery.com/jquery-1.10.2.js"></script> <script> $( ".status" ) .keypress(function() { if(event.keyCode == 13) { PostRbStatus(this.getAttribute("subject_username"), this.getAttribute("me_username"), this.value) } }) function PostRbStatus(subject_username, me_username, message) { $.post( "/rb/poststatus.php", {subject_username: subject_username, me_username: me_username, message: message}) .done(function( data ) { $( "#postresult_" + subject_username).html( data ) }) .error(function( ) { alert("error"); }); $('#get_' + subject_username).blur(); $('#get_' + subject_username).value(''); } $( "textarea" ) .on( "mouseenter", function() { $( this ).css({ "border": "medium solid #CC0000", "height": "5em" }); }) .on( "mouseleave", function() { var styles = { "border": "thin solid blue", "height": "2em" }; $( this ).css( styles ); }); </script> </body> </html>
The db.php file is a standard database initialization using the PDO class.
<?php $servername = "localhost"; $username = "USERNAME_GOES_HERE"; $password = "PASSWORD_GOES_HERE"; try { $conn = new PDO("mysql:host=$servername;dbname=tabmgr_rb", $username, $password); // set the PDO error mode to exception $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); //echo "Connected successfully"; } catch(PDOException $e) { echo "Database connection failed: " . $e->getMessage(); } ?>
The database access a simple table with this structure.
CREATE TABLE IF NOT EXISTS `status` ( `id` int(11) NOT NULL AUTO_INCREMENT, `username` varchar(255) NOT NULL, `by` varchar(255) NOT NULL, `text` text NOT NULL, `timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
Here is the server-side script that processes the data submitted for notes on each user. The output is captured by the client-side JavaScript and placed in a div above the previous entries in the database.
<?php include "db.php"; if($_POST["subject_username"]) { $username = $_POST["subject_username"]; $by = $_POST["me_username"]; $message = $_POST["message"]; $sql = sprintf("INSERT INTO status (`username`, `by`, `text`) VALUES('%s', '%s', '%s') ", $username, $by, $message); $count = $conn->exec($sql); if($count) printf('<p>%s <br /><em>added by %s %s</em></p>',$message,$by,date('F j, Y')); else echo "<p>Error adding note</p>"; } ?>