]> gitweb.fluxo.info Git - semanticscuttle.git/commitdiff
new privatekey2 branch with privatekey changes
authorMark Pemberton <mpemberton5@gmail.com>
Fri, 13 May 2011 18:26:51 +0000 (14:26 -0400)
committerMark Pemberton <mpemberton5@gmail.com>
Fri, 13 May 2011 18:26:51 +0000 (14:26 -0400)
16 files changed:
data/schema/6.sql
data/tables.sql
data/templates/editprofile.tpl.php
data/templates/rss.tpl.php
data/templates/top.inc.php
doc/UPGRADE.txt
src/SemanticScuttle/Model/User.php
src/SemanticScuttle/Service/Bookmark.php
src/SemanticScuttle/Service/User.php
tests/BookmarkTest.php
tests/TestBase.php
tests/UserTest.php
www/index.php
www/jsScuttle.php
www/profile.php
www/rss.php

index 0c208ad417eca98690be4bdffd92ce418fb20999..e4acd53515934d99c9268d1a5404113b6d06b690 100644 (file)
@@ -13,3 +13,7 @@ CREATE TABLE `sc_users_sslclientcerts` (
   PRIMARY KEY ( `id` ) ,
   UNIQUE (`id`)
 ) CHARACTER SET utf8 COLLATE utf8_general_ci;
+
+ALTER TABLE `sc_users` ADD `privateKey` VARCHAR(33) NULL;
+CREATE INDEX `privateKey` ON `sc_users` (`privateKey`);
+
index d53945e60d0c4560dde96d3f53fb41fb3a7900a6..dd4e924287e2a4a6753dd27ef8d1a0ff1151203d 100644 (file)
@@ -84,8 +84,9 @@ CREATE TABLE `sc_users_sslclientcerts` (
   `sslClientIssuerDn` VARCHAR( 1024 ) NOT NULL ,
   `sslName` VARCHAR( 64 ) NOT NULL ,
   `sslEmail` VARCHAR( 64 ) NOT NULL ,
+  `privateKey` varchar(33) default NULL,
   PRIMARY KEY ( `id` ) ,
-  UNIQUE (`id`)
+  UNIQUE KEY `privateKey` (`privateKey`)
 ) CHARACTER SET utf8 COLLATE utf8_general_ci;
 
 -- 
index cc74f04660454b7e1d2441a722bfe65530e65d80..76f608a346d34b87e0c4877436e031e5c2d80f58 100644 (file)
@@ -28,6 +28,14 @@ $this->includeTemplate($GLOBALS['top_include']);
     <td><input type="text" name="pMail" size="75" value="<?php echo filter($objectUser->getEmail(), 'xml'); ?>" /></td>
     <td>← <?php echo T_('Required'); ?></td>
 </tr>
+<tr>
+    <th align="left"><?php echo T_('Private RSS Feed'); ?></th>
+    <td><input type="checkbox" id="pEnablePrivateKey" name="pEnablePrivateKey" value="true" <?php echo $privateKeyIsEnabled;?> />
+        <label for="pEnablePrivateKey"><?php echo T_('Enable'); ?></label>&nbsp;&nbsp;&nbsp;
+        <input type="text" id="pPrivateKey" name="pPrivateKey" size="40" value="<?php echo $privateKey;?>" readonly="readonly" />
+        <input type="submit" name="submittedPK" value="<?php echo T_('Generate New Key'); ?>" />
+    </td>
+</tr>
 </table>
 
 <h3><?php echo T_('Personal Details'); ?></h3>
index e6e66f764c69ac13c70ce0a6ee188e9550a5d98c..6be542520db3f76c2b4b13533c38b8a8f606948d 100644 (file)
@@ -3,7 +3,7 @@ echo '<' . '?xml version="1.0" encoding="utf-8" ?' . ">\n";
 ?>
 <rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/">
 <channel>
-    <title><?php echo htmlspecialchars($feedtitle); ?></title>
+    <title><?php echo $feedtitle; ?></title>
     <link><?php echo htmlspecialchars($feedlink); ?></link>
     <description><?php echo htmlspecialchars($feeddescription); ?></description>
     <pubDate><?php echo date('r'); ?></pubDate>
@@ -23,4 +23,4 @@ echo '<' . '?xml version="1.0" encoding="utf-8" ?' . ">\n";
     </item>
 <?php endforeach; ?>
 </channel>
-</rss>
\ No newline at end of file
+</rss>
index bdd4b1a9a53d68623f2b6f23aa1b1c5db54b799d..738b71e6a0333bc416faa9b05ea87cb67ba33512 100644 (file)
@@ -12,7 +12,7 @@ if (isset($rsschannels)) {
        $size = count($rsschannels);
        for ($i = 0; $i < $size; $i++) {
                echo '  <link rel="alternate" type="application/rss+xml" title="'
-            . htmlspecialchars($rsschannels[$i][0]) . '"'
+            . $rsschannels[$i][0] . '"'
             . ' href="'. $rsschannels[$i][1] .'" />';
        }
 }
index 3be6654835ad5438721d3b77b62850c3ad6f466e..fe8624a36d0240b910535e129ccb35227de3873d 100644 (file)
@@ -12,6 +12,9 @@ Database updates: Apply data/schema/6.sql or do the following:
 
     INSERT INTO `sc_version` (`schema_version`) VALUES ('6');
 
+    ALTER TABLE `sc_users` ADD `privateKey` VARCHAR(33) NULL;
+    CREATE INDEX `privateKey` ON `sc_users` (`privateKey`);
+
 
 From version 0.96 to 0.97
 -------------------------
index 500f5b1f9aa11d7ec1ba3c346a5c97e7fc51e361..3aa617b404c1498c64ddbffae2085cd5acaadb67 100644 (file)
@@ -35,6 +35,7 @@ class SemanticScuttle_Model_User
     var $content;
     var $datetime;
     var $isAdmin;
+    var $privateKey;
 
     /**
      * Create a new user object
@@ -68,6 +69,29 @@ class SemanticScuttle_Model_User
         return $this->username;
     }
 
+    /**
+     * Returns private key
+     *
+     * @param boolean return sanitized value which basically drops
+     *                leading dash if exists
+     *
+     * @return string private key
+     */
+    public function getPrivateKey($sanitized = false)
+    {
+        // Look for value only if not already set
+        if (!isset($this->privateKey)) {
+            $us = SemanticScuttle_Service_Factory::get('User');
+            $user = $us->getUser($this->id);
+            $this->privateKey = $user['privateKey'];
+        }
+        if ($sanitized == true) {
+            return substr($this->privateKey, -32);
+        } else {
+            return $this->privateKey;
+        }
+    }
+
     /**
      * Returns full user name as specified in the profile.
      *
@@ -182,4 +206,4 @@ class SemanticScuttle_Model_User
     }
 
 }
-?>
\ No newline at end of file
+?>
index 919ca7a8a3c304bd3e2f81c3c15869d05546d4ab..e836cd8502b569a48b5f86371063eab72225b8af 100644 (file)
@@ -717,7 +717,7 @@ class SemanticScuttle_Service_Bookmark extends SemanticScuttle_DbService
             // All public bookmarks, user's own bookmarks
             // and any shared with user
             $privacy = ' AND ((B.bStatus = 0) OR (B.uId = '. $sId .')';
-            $watchnames = $userservice->getWatchNames($sId, true);
+            $watchnames = $userservice->getWatchNames($sId);
             foreach ($watchnames as $watchuser) {
                 $privacy .= ' OR (U.username = "'. $watchuser .'" AND B.bStatus = 1)';
             }
index 09a2cb19ab8486df6cc41f0bda29fab3737887f1..c3633de86cf89625b27afd818dffeba4a1f20de9 100644 (file)
@@ -48,9 +48,10 @@ class SemanticScuttle_Service_User extends SemanticScuttle_DbService
     protected $currentuser = null;
 
     protected $fields = array(
-        'primary'   =>  'uId',
-        'username'  =>  'username',
-        'password'  =>  'password'
+        'primary'    => 'uId',
+        'username'   => 'username',
+        'password'   => 'password',
+        'privatekey' => 'privatekey'
     );
 
     protected $profileurl;
@@ -215,6 +216,18 @@ class SemanticScuttle_Service_User extends SemanticScuttle_DbService
         return $this->_getuser($this->getFieldName('username'), $username);
     }
 
+    /**
+     * Returns user row from database.
+     *
+     * @param string $privatekey Private Key
+     *
+     * @return array User array from database, false if no user was found
+     */
+    public function getUserByPrivateKey($privatekey)
+    {
+        return $this->_getuser($this->getFieldName('privatekey'), $privatekey);
+    }
+
     function getObjectUserByUsername($username) {
         $user = $this->_getuser($this->getFieldName('username'), $username);
         if($user != false) {
@@ -279,6 +292,22 @@ class SemanticScuttle_Service_User extends SemanticScuttle_DbService
         return ($this->getCurrentUserId() !== false);
     }
 
+    /**
+     * Tells you if the private key is enabled and valid
+     *
+     * @param string $privateKey Private Key
+     *
+     * @return boolean True if enabled and valid
+     */
+    public function isPrivateKeyValid($privateKey)
+    {
+        // check length of private key
+        if (strlen($privateKey) == 32) {
+            return true;
+        }
+        return false;
+    }
+
     /**
      * Returns the current user object
      *
@@ -293,7 +322,7 @@ class SemanticScuttle_Service_User extends SemanticScuttle_DbService
     {
         if (!is_null($newval)) {
             //internal use only: reset currentuser
-            $currentuser = $newval;
+            $this->currentuser = $newval;
         } else if ($refresh || !isset($this->currentuser)) {
             if ($id = $this->getCurrentUserId()) {
                 $this->currentuser = $this->getUser($id);
@@ -509,6 +538,47 @@ class SemanticScuttle_Service_User extends SemanticScuttle_DbService
         }
     }
 
+    /**
+     * Try to authenticate via the privatekey
+     *
+     * @param string $privatekey Private Key
+     *
+     * @return boolean true if the user could be authenticated,
+     *                 false if not.
+     */
+    public function loginPrivateKey($privatekey)
+    {
+        /* Check if private key valid and enabled */
+        if (!$this->isPrivateKeyValid($privatekey)) {
+            return false;
+        }
+
+        $query = 'SELECT '. $this->getFieldName('primary') .' FROM '
+            . $this->getTableName() .' WHERE '
+            . $this->getFieldName('privatekey') .' = "'
+            . $this->db->sql_escape($privatekey) .'"';
+
+        if (!($dbresult = $this->db->sql_query($query))) {
+            message_die(
+                GENERAL_ERROR,
+                'Could not get user',
+                '', __LINE__, __FILE__, $query, $this->db
+            );
+            return false;
+        }
+
+        $row = $this->db->sql_fetchrow($dbresult);
+        $this->db->sql_freeresult($dbresult);
+
+        if ($row) {
+            $id = $_SESSION[$this->getSessionKey()]
+                = $row[$this->getFieldName('primary')];
+            return true;
+        } else {
+            return false;
+        }
+    }
+
     /**
      * Logs the user off
      *
@@ -519,7 +589,8 @@ class SemanticScuttle_Service_User extends SemanticScuttle_DbService
         @setcookie($this->getCookiekey(), '', time() - 1, '/');
         unset($_COOKIE[$this->getCookiekey()]);
         session_unset();
-        $this->getCurrentUser(TRUE, false);
+        $this->currentuserId = null;
+        $this->currentuser = null;
     }
 
     function getWatchlist($uId) {
@@ -646,24 +717,26 @@ class SemanticScuttle_Service_User extends SemanticScuttle_DbService
      * No checks are done in here - you ought to have checked
      * everything before calling this method!
      *
-     * @param string $username Username to use
-     * @param string $password Password to use
-     * @param string $email    Email to use
+     * @param string $username   Username to use
+     * @param string $password   Password to use
+     * @param string $email      Email to use
+     * @param string $privateKey Key for RSS auth
      *
      * @return mixed Integer user ID if all is well,
      *               boolean false if an error occured
      */
-    public function addUser($username, $password, $email)
+    public function addUser($username, $password, $email, $privateKey = null)
     {
         // Set up the SQL UPDATE statement.
         $datetime = gmdate('Y-m-d H:i:s', time());
         $password = $this->sanitisePassword($password);
         $values   = array(
-            'username'  => $username,
-            'password'  => $password,
-            'email'     => $email,
-            'uDatetime' => $datetime,
-            'uModified' => $datetime
+            'username'   => $username,
+            'password'   => $password,
+            'email'      => $email,
+            'uDatetime'  => $datetime,
+            'uModified'  => $datetime,
+            'privateKey' => $privateKey
         );
         $sql = 'INSERT INTO '. $this->getTableName()
             . ' '. $this->db->sql_build_array('INSERT', $values);
@@ -687,40 +760,64 @@ class SemanticScuttle_Service_User extends SemanticScuttle_DbService
     /**
      * Updates the given user
      *
-     * @param integer $uId      ID of user to change
-     * @param string  $password Password to use
-     * @param string  $name     Realname to use
-     * @param string  $email    Email to use
-     * @param string  $homepage User's homepage
-     * @param string  $uContent User note
+     * @param integer $uId              ID of user to change
+     * @param string  $password         Password to use
+     * @param string  $name             Realname to use
+     * @param string  $email            Email to use
+     * @param string  $homepage         User's homepage
+     * @param string  $uContent         User note
+     * @param string  $privateKey       RSS Private Key
+     * @param boolean $enablePrivateKey RSS Private Key Flag
      *
      * @return boolean True when all is well, false if not
      */
     public function updateUser(
-        $uId, $password, $name, $email, $homepage, $uContent
+        $uId, $password, $name, $email, $homepage, $uContent,
+        $privateKey = null, $enablePrivateKey = false
     ) {
         if (!is_numeric($uId)) {
             return false;
         }
 
+        // prepend '-' to privateKey if disabled
+        if ($privateKey != null && strlen($privateKey) == 32
+            && $enablePrivateKey == false
+        ) {
+            $privateKey = '-' . $privateKey;
+        }
+
+        // remove '-' from privateKey if enabling
+        if ($privateKey != null && strlen($privateKey) == 33
+            && $enablePrivateKey == true
+        ) {
+            $privateKey = substr($privateKey, 1, 32);
+        }
+
+        // if new user is enabling Private Key, create new key
+        if ($privateKey == null && $enablePrivateKey == true) {
+            $privateKey = $this->getNewPrivateKey();
+        }
+
         // Set up the SQL UPDATE statement.
         $moddatetime = gmdate('Y-m-d H:i:s', time());
         if ($password == '') {
             $updates = array(
-                'uModified' => $moddatetime,
-                'name'      => $name,
-                'email'     => $email,
-                'homepage'  => $homepage,
-                'uContent'  => $uContent
+                'uModified'  => $moddatetime,
+                'name'       => $name,
+                'email'      => $email,
+                'homepage'   => $homepage,
+                'uContent'   => $uContent,
+                'privateKey' => $privateKey
             );
         } else {
             $updates = array(
-                'uModified' => $moddatetime,
-                'password'  => $this->sanitisePassword($password),
-                'name'      => $name,
-                'email'     => $email,
-                'homepage'  => $homepage,
-                'uContent'  => $uContent
+                'uModified'  => $moddatetime,
+                'password'   => $this->sanitisePassword($password),
+                'name'       => $name,
+                'email'      => $email,
+                'homepage'   => $homepage,
+                'uContent'   => $uContent,
+                'privateKey' => $privateKey
             );
         }
         $sql = 'UPDATE '. $this->getTableName()
@@ -837,6 +934,56 @@ class SemanticScuttle_Service_User extends SemanticScuttle_DbService
         }
     }
 
+    /**
+     * Generates a new private key and confirms it isn't being used.
+     * Private key is 32 characters long, consisting of lowercase and
+     * numeric characters.
+     *
+     * @return string the new key value
+     */
+    public function getNewPrivateKey()
+    {
+        do {
+            $newKey = md5(uniqid('SemanticScuttle', true));
+        } while ($this->privateKeyExists($newKey));
+
+        return $newKey;
+    }
+
+    /**
+     * Checks if a private key already exists
+     *
+     * @param string $privateKey key that has been generated
+     *
+     * @return boolean true when the private key exists,
+     *                 False if not.
+     */
+    public function privateKeyExists($privateKey)
+    {
+        if (!$privateKey) {
+            return false;
+        }
+        $crit = array('privateKey' => $privateKey);
+
+        $sql = 'SELECT COUNT(*) as "0" FROM '
+            . $GLOBALS['tableprefix'] . 'users'
+            . ' WHERE '. $this->db->sql_build_array('SELECT', $crit);
+
+        if (!($dbresult = $this->db->sql_query($sql))) {
+            message_die(
+                GENERAL_ERROR, 'Could not get vars', '',
+                __LINE__, __FILE__, $sql, $this->db
+            );
+        }
+        if ($this->db->sql_fetchfield(0, 0) > 0) {
+            $exists = true;
+        } else {
+            $exists = false;
+        }
+        $this->db->sql_freeresult($dbresult);
+        return $exists;
+    }
+
     function isReserved($username) {
         if (in_array($username, $GLOBALS['reservedusers'])) {
             return true;
index b50dab203ce9b782039b032d221954780c29f79a..44a82d9026d6aeff6d2eb452f1f0f5f4edf77c91 100644 (file)
@@ -1330,5 +1330,51 @@ class BookmarkTest extends TestBase
 
 
 
+    /**
+     * Test private bookmarks
+     *
+     * @return void
+     */
+    public function testPrivateBookmarks()
+    {
+        $uid = $this->addUser();
+        /* create private bookmark */
+        $this->bs->addBookmark(
+            'http://test', 'test', 'desc', 'note',
+            2,//private
+            array(), null, null, false, false, $uid
+        );
+        /* create public bookmark */
+        $this->bs->addBookmark(
+            'http://example.org', 'title', 'desc', 'priv',
+            0,//public
+            array(), null, null, false, false, $uid
+        );
+
+        $this->assertEquals(1, $this->bs->countBookmarks($uid, 'public'));
+        $this->assertEquals(1, $this->bs->countBookmarks($uid, 'private'));
+        $this->assertEquals(0, $this->bs->countBookmarks($uid, 'shared'));
+        $this->assertEquals(2, $this->bs->countBookmarks($uid, 'all'));
+
+        $this->us->setCurrentUserId($uid);
+        $bookmarks = $this->bs->getBookmarks();
+        // first record should be private bookmark
+        $b0 = $bookmarks['bookmarks'][0];
+        $this->assertEquals('test', $b0['bTitle']);
+        // second record should be public bookmark
+        $b0 = $bookmarks['bookmarks'][1];
+        $this->assertEquals('title', $b0['bTitle']);
+
+        // test non authenticated query
+        $this->us->setCurrentUserId(null);
+        $bookmarks = $this->bs->getBookmarks();
+        // should only result in one link - public
+        $b2 = $bookmarks['bookmarks'][0];
+        $this->assertEquals('title', $b2['bTitle']);
+        // there should be no second record
+        $this->assertEquals(1,count($bookmarks['bookmarks']));
+
+    }
+
 }
 ?>
index 095f32db0a60dc3685e29098f5538bd1742cb193..1331ec6e3e02a98aaca6ba444bbf28e006454744 100644 (file)
@@ -78,14 +78,15 @@ class TestBase extends PHPUnit_Framework_TestCase
      *
      * @param string $username Username
      * @param string $password Password
+     * @param string $pkey     Private Key
      *
      * @return integer ID of user
      *
      * @uses addUserData()
      */
-    protected function addUser($username = null, $password = null)
+    protected function addUser($username = null, $password = null, $pkey = null)
     {
-        return reset($this->addUserData($username, $password));
+        return reset($this->addUserData($username, $password, $pkey));
     }
 
 
@@ -95,10 +96,11 @@ class TestBase extends PHPUnit_Framework_TestCase
      *
      * @param string $username Username
      * @param string $password Password
+     * @param string $pkey     Private Key
      *
      * @return array ID of user, Name of user, password of user
      */
-    protected function addUserData($username = null, $password = null)
+    protected function addUserData($username = null, $password = null, $pkey = null)
     {
         $us   = SemanticScuttle_Service_Factory::get('User');
         $rand = rand();
@@ -113,7 +115,8 @@ class TestBase extends PHPUnit_Framework_TestCase
         $uid  = $us->addUser(
             $username,
             $password,
-            'unittest-' . $rand . '@example.org'
+            'unittest-' . $rand . '@example.org',
+            $pkey
         );
         return array($uid, $username, $password);
     }
@@ -148,4 +151,4 @@ class TestBase extends PHPUnit_Framework_TestCase
     }
 }
 
-?>
\ No newline at end of file
+?>
index 2f5711256a674fd9396fe05dc153e134d18cac75..230167d7e8731f13fef80e539e840aee53b1cb3c 100644 (file)
@@ -34,6 +34,157 @@ class UserTest extends TestBase
 
 
 
+    /**
+     * @covers SemanticScuttle_Service_User::addUser
+     */
+    public function testAddUserPrivateKey()
+    {
+        $name = substr(md5(uniqid()), 0, 6);
+        $pkey = 'my-privatekey';
+        $id   = $this->us->addUser(
+            $name, uniqid(), 'foo@example.org', $pkey
+        );
+        $this->assertNotEquals(false, $id);
+        $this->assertInternalType('integer', $id);
+
+        $arUser = $this->us->getUserByPrivateKey($pkey);
+        $this->assertNotEquals(false, $arUser, 'user not found by private key');
+        $this->assertEquals($id, $arUser['uId'], 'wrong user loaded');
+    }
+
+
+    /**
+     * @covers SemanticScuttle_Service_User::updateUser
+     */
+    public function testUpdateUserFalseWhenIdNotNumeric()
+    {
+        $this->assertFalse(
+            $this->us->updateUser('foo', null, null, null, null, null)
+        );
+    }
+
+
+    /**
+     * @covers SemanticScuttle_Service_User::updateUser
+     */
+    public function testUpdateUserPrivateKeyNewKeyEnabled()
+    {
+        $pkey = 'testUpdateUserPrivateKeyNewKey12';
+        $uid  = $this->addUser();
+
+        $this->assertTrue(
+            $this->us->updateUser(
+                $uid, 'password', 'name', 'test@example.org', '', '',
+                $pkey, true
+            )
+        );
+        $arUser = $this->us->getUser($uid);
+        $this->assertInternalType('array', $arUser);
+        $this->assertEquals($pkey, $arUser['privateKey']);
+    }
+
+
+    /**
+     * @covers SemanticScuttle_Service_User::updateUser
+     */
+    public function testUpdateUserPrivateKeyNewKeyDisabled()
+    {
+        $pkey = 'testUpdateUserPrivateKeyNewKeyDi';
+        $uid  = $this->addUser();
+
+        $this->assertTrue(
+            $this->us->updateUser(
+                $uid, 'password', 'name', 'test@example.org', '', '',
+                $pkey, false
+            )
+        );
+        $arUser = $this->us->getUser($uid);
+        $this->assertInternalType('array', $arUser);
+        $this->assertEquals(
+            '-' . $pkey, $arUser['privateKey'],
+            'private key did not get disabled'
+        );
+    }
+
+
+    /**
+     * Passing an empty string / NULL as key but enabling it
+     * should automatically create a new key.
+     *
+     * @covers SemanticScuttle_Service_User::updateUser
+     */
+    public function testUpdateUserPrivateKeyNoKeyEnabled()
+    {
+        $pkey = 'testUpdateUserPrivateKeyNoKeyEna';
+        $uid  = $this->addUser();
+
+        $this->assertTrue(
+            $this->us->updateUser(
+                $uid, 'password', 'name', 'test@example.org', '', '',
+                null, true
+            )
+        );
+        $arUser = $this->us->getUser($uid);
+        $this->assertInternalType('array', $arUser);
+        $this->assertNotEquals(
+            '', $arUser['privateKey'], 'private key was not created'
+        );
+    }
+
+
+    /**
+     * Passing an empty string / NULL as key and disabling it
+     * should keep no key
+     *
+     * @covers SemanticScuttle_Service_User::updateUser
+     */
+    public function testUpdateUserPrivateKeyNoKeyDisabled()
+    {
+        $pkey = 'testUpdateUserPrivateKeyNoKeyDis';
+        $uid  = $this->addUser();
+
+        $this->assertTrue(
+            $this->us->updateUser(
+                $uid, 'password', 'name', 'test@example.org', '', '',
+                null, false
+            )
+        );
+        $arUser = $this->us->getUser($uid);
+        $this->assertInternalType('array', $arUser);
+        $this->assertEquals(
+            '', $arUser['privateKey'], 'private key was set'
+        );
+    }
+
+
+    /**
+     * Passing an empty string / NULL as key and disabling it
+     * should keep no key
+     *
+     * @covers SemanticScuttle_Service_User::updateUser
+     */
+    public function testUpdateUserPrivateKeyExistingKeyEnabled()
+    {
+        $pkey = '12345678901234567890123456789012';
+        $uid  = $this->addUser();
+
+        $this->assertTrue(
+            $this->us->updateUser(
+                $uid, 'password', 'name', 'test@example.org', '', '',
+                '-' . $pkey, true
+            )
+        );
+        $arUser = $this->us->getUser($uid);
+        $this->assertInternalType('array', $arUser);
+        $this->assertEquals(
+            $pkey, $arUser['privateKey'], 'private key was not enabled'
+        );
+    }
+
+    //FIXME: verify I cannot re-use private key of different user
+
+
+
     /**
      * Test that setting the current user ID is permanent.
      * and that the current user array is the same ID
@@ -176,5 +327,185 @@ class UserTest extends TestBase
         );
     }
 
+
+    public function testGetUserByPrivateKeyEmptyKey()
+    {
+        $arUser = $this->us->getUserByPrivateKey(null);
+        $this->assertFalse($arUser);
+    }
+
+
+    public function testGetUserByPrivateKeyInvalid()
+    {
+        $arUser = $this->us->getUserByPrivateKey('foobar');
+        $this->assertFalse($arUser);
+
+        $arUser = $this->us->getUserByPrivateKey('%');
+        $this->assertFalse($arUser);
+    }
+
+
+    public function testGetUserByPrivateKeyValidKey()
+    {
+        $pkey = $this->us->getNewPrivateKey();
+        $uId = $this->addUser(null, null, $pkey);
+
+        $arUser = $this->us->getUserByPrivateKey($pkey);
+        $this->assertInternalType('array', $arUser);
+        $this->assertArrayHasKey('uId', $arUser);
+        $this->assertArrayHasKey('username', $arUser);
+
+        $this->assertEquals($uId, $arUser['uId']);
+    }
+
+
+    /**
+     * @covers SemanticScuttle_Service_User::privateKeyExists
+     */
+    public function testPrivateKeyExistsEmpty()
+    {
+        $this->assertFalse($this->us->privateKeyExists(null));
+        $this->assertFalse($this->us->privateKeyExists(''));
+    }
+
+
+    /**
+     * @covers SemanticScuttle_Service_User::privateKeyExists
+     */
+    public function testPrivateKeyExistsInvalid()
+    {
+        $this->assertFalse($this->us->privateKeyExists('-1'));
+    }
+
+
+    /**
+     * @covers SemanticScuttle_Service_User::privateKeyExists
+     */
+    public function testPrivateKeyExists()
+    {
+        $randKey = $this->us->getNewPrivateKey();
+        $this->assertFalse($this->us->privateKeyExists($randKey));
+        $uid = $this->addUser(null, null, $randKey);
+
+        $this->us->setCurrentUserId($uid);
+        $this->assertEquals($uid, $this->us->getCurrentUserId());
+
+        $this->assertTrue($this->us->privateKeyExists($randKey));
+    }
+
+
+    /**
+     * @covers SemanticScuttle_Service_User::isPrivateKeyValid
+     */
+    public function testIsPrivateKeyValid()
+    {
+        $this->assertFalse(
+            $this->us->isPrivateKeyValid(null),
+            'NULL is an invalid private key'
+        );
+
+        $randKey = $this->us->getNewPrivateKey();
+        $this->assertTrue(
+            $this->us->isPrivateKeyValid($randKey),
+            'generated key should be valid'
+        );
+
+        $randKey2 = '-'.$this->us->getNewPrivateKey();
+        $this->assertFalse(
+            $this->us->isPrivateKeyValid($randKey2),
+            'disabled privatekey should return false'
+        );
+    }
+
+
+    public function testLoginPrivateKeyInvalid()
+    {
+        /* normal user with enabled privatekey */
+        $randKey = $this->us->getNewPrivateKey();
+        $uid1 = $this->addUser('testusername', 'passw0rd', $randKey);
+        /* user that has disabled privatekey */
+        $randKey2 = '-'.$this->us->getNewPrivateKey();
+        $uid2 = $this->addUser('seconduser', 'passw0RD', $randKey2);
+
+        /* test invalid private key */
+        $this->assertFalse(
+            $this->us->loginPrivateKey('02848248084082408240824802408248')
+        );
+    }
+
+
+    public function testLoginPrivateKeyValidEnabledKey()
+    {
+        /* normal user with enabled privatekey */
+        $randKey = $this->us->getNewPrivateKey();
+        $uid1 = $this->addUser('testusername', 'passw0rd', $randKey);
+        /* user that has disabled privatekey */
+        $randKey2 = '-'.$this->us->getNewPrivateKey();
+        $uid2 = $this->addUser('seconduser', 'passw0RD', $randKey2);
+
+
+        /* test valid credentials with private key enabled */
+        $this->assertTrue(
+            $this->us->loginPrivateKey($randKey)
+        );
+    }
+
+
+    public function testLoginPrivateKeyInvalidEnabledKey()
+    {
+        /* normal user with enabled privatekey */
+        $randKey = $this->us->getNewPrivateKey();
+        $uid1 = $this->addUser('testusername', 'passw0rd', $randKey);
+        /* user that has disabled privatekey */
+        $randKey2 = '-'.$this->us->getNewPrivateKey();
+        $uid2 = $this->addUser('seconduser', 'passw0RD', $randKey2);
+
+
+        /* test valid credentials with private key enabled but invalid key */
+        $this->assertFalse(
+            $this->us->loginPrivateKey('123')
+        );
+    }
+
+
+    public function testLoginPrivateKeyValidDisabledKey()
+    {
+        /* normal user with enabled privatekey */
+        $randKey = $this->us->getNewPrivateKey();
+        $uid1 = $this->addUser('testusername', 'passw0rd', $randKey);
+        /* user that has disabled privatekey */
+        $randKey2 = '-'.$this->us->getNewPrivateKey();
+        $uid2 = $this->addUser('seconduser', 'passw0RD', $randKey2);
+
+        /* confirm user exists so future fails should be due to randkey */
+        $this->assertTrue(
+            $this->us->login('seconduser', 'passw0RD', false)
+        );
+
+        /* test valid credentials with private key disabled */
+        $this->assertFalse(
+            $this->us->loginPrivateKey($randKey2)
+        );
+    }
+
+
+    public function testLoginPrivateKeyInvalidDisabled()
+    {
+        /* normal user with enabled privatekey */
+        $randKey = $this->us->getNewPrivateKey();
+        $uid1 = $this->addUser('testusername', 'passw0rd', $randKey);
+        /* user that has disabled privatekey */
+        $randKey2 = '-'.$this->us->getNewPrivateKey();
+        $uid2 = $this->addUser('seconduser', 'passw0RD', $randKey2);
+
+        /* test valid credentials with private key disabled and invalid key */
+        $this->assertFalse(
+            $this->us->loginPrivateKey('-1')
+        );
+        $this->assertFalse(
+            $this->us->loginPrivateKey(null)
+        );
+    }
+
 }
-?>
\ No newline at end of file
+?>
index f6704ae8c809c6d0c42cbb5991b393d17b451575..09779239bd4c04b899f76b66f2a2fa7ffc200416 100644 (file)
@@ -45,6 +45,19 @@ $tplVars['rsschannels'] = array(
 array(sprintf(T_('%s: Recent bookmarks'), $sitename), createURL('rss').'?sort='.getSortOrder())
 );
 
+if ($userservice->isLoggedOn()) {
+    $currentUsername = $currentUser->getUsername();
+    if ($userservice->isPrivateKeyValid($currentUser->getPrivateKey())) {
+        array_push(
+            $tplVars['rsschannels'],
+            array(
+                filter($sitename . sprintf(T_(': (private) ')) . $currentUsername),
+                createURL('rss', filter($currentUsername, 'url') . '?sort='.getSortOrder().'&amp;privatekey='.$currentUser->getPrivateKey())
+            )
+        );
+    }
+}
+
 if ($usecache) {
        // Generate hash for caching on
        $hashtext = $_SERVER['REQUEST_URI'];
index c16675535b2c9769620f4ed679b27f9f2549ae70..76b49dc084e8312135d11e63423c76ccb0b24cab 100644 (file)
@@ -89,6 +89,16 @@ function useAddress(ele) {
     }
 }
 
+function getNewPrivateKey(input, response){
+    var pk = document.getElementById('pPrivateKey');
+    if (response != null) {
+        pk.value = response.trim();
+    } else {
+        loadXMLDocProc('<?php echo ROOT; ?>ajaxGetNewPrivateKey.php');
+    }
+    return false;
+}
+
 function getTitle(input, response){
     var title = document.getElementById('titleField');
     if (title.value == '') {
index ccdb7a80a15e9bb703b78bdb7cb6c10623bb3f2d..e6894d03442a5b3278f94c7ad3d96b736b479286 100644 (file)
@@ -25,10 +25,13 @@ require_once 'www-header.php';
 // No specific services
 
 /* Managing all possible inputs */
+isset($_POST['submittedPK']) ? define('POST_SUBMITTEDPK', $_POST['submittedPK']): define('POST_SUBMITTEDPK', '');
 isset($_POST['submitted']) ? define('POST_SUBMITTED', $_POST['submitted']): define('POST_SUBMITTED', '');
 isset($_POST['pPass']) ? define('POST_PASS', $_POST['pPass']): define('POST_PASS', '');
 isset($_POST['pPassConf']) ? define('POST_PASSCONF', $_POST['pPassConf']): define('POST_PASSCONF', '');
 isset($_POST['pName']) ? define('POST_NAME', $_POST['pName']): define('POST_NAME', '');
+isset($_POST['pPrivateKey']) ? define('POST_PRIVATEKEY', $_POST['pPrivateKey']): define('POST_PRIVATEKEY', '');
+isset($_POST['pEnablePrivateKey']) ? define('POST_ENABLEPRIVATEKEY', $_POST['pEnablePrivateKey']): define('POST_ENABLEPRIVATEKEY', '');
 isset($_POST['pMail']) ? define('POST_MAIL', $_POST['pMail']): define('POST_MAIL', '');
 isset($_POST['pPage']) ? define('POST_PAGE', $_POST['pPage']): define('POST_PAGE', '');
 isset($_POST['pDesc']) ? define('POST_DESC', $_POST['pDesc']): define('POST_DESC', '');
@@ -61,10 +64,19 @@ if ($user) {
        exit();
 }
 
+$tplVars['privateKeyIsEnabled'] = '';
 if ($userservice->isLoggedOn() && $user == $currentUser->getUsername()) {
-       $title = T_('My Profile');
+    $title = T_('My Profile');
+    $tplVars['privateKey'] = $currentUser->getPrivateKey(true);
+
+    if ($userservice->isPrivateKeyValid($currentUser->getPrivateKey())) {
+        $tplVars['privateKeyIsEnabled'] = 'checked="checked"';
+    } else {
+        $tplVars['privateKeyIsEnabled'] = '';
+    }
 } else {
-       $title = T_('Profile') .': '. $user;
+    $title = T_('Profile') .': '. $user;
+    $tplVars['privateKey'] = '';
 }
 $tplVars['pagetitle'] = $title;
 $tplVars['subtitle'] = $title;
@@ -72,11 +84,19 @@ $tplVars['subtitle'] = $title;
 $tplVars['user'] = $user;
 $tplVars['userid'] = $userid;
 
+/* Update Private Key */
+if (POST_SUBMITTEDPK!='' && $currentUser->getId() == $userid) {
+    $userinfo = $userservice->getObjectUserByUsername($user);
+    $tplVars['privateKey'] = $userservice->getNewPrivateKey();
+}
+
 if (POST_SUBMITTED!='' && $currentUser->getId() == $userid) {
        $error = false;
        $detPass = trim(POST_PASS);
        $detPassConf = trim(POST_PASSCONF);
        $detName = trim(POST_NAME);
+       $detPrivateKey = trim(POST_PRIVATEKEY);
+       $detEnablePrivateKey = trim(POST_ENABLEPRIVATEKEY);
        $detMail = trim(POST_MAIL);
        $detPage = trim(POST_PAGE);
        $detDesc = filter(POST_DESC);
@@ -102,13 +122,19 @@ if (POST_SUBMITTED!='' && $currentUser->getId() == $userid) {
                $tplVars['error'] = T_('E-mail address is not valid.');
        }
        if (!$error) {
-               if (!$userservice->updateUser($userid, $detPass, $detName, $detMail, $detPage, $detDesc)) {
+               if (!$userservice->updateUser($userid, $detPass, $detName, $detMail, $detPage, $detDesc, $detPrivateKey, $detEnablePrivateKey)) {
                        $tplVars['error'] = T_('An error occurred while saving your changes.');
                } else {
                        $tplVars['msg'] = T_('Changes saved.');
                }
        }
        $userinfo = $userservice->getObjectUserByUsername($user);
+       $tplVars['privateKey'] = $userinfo->getPrivateKey(true);
+       if ($userservice->isPrivateKeyValid($userinfo->getPrivateKey())) {
+               $tplVars['privateKeyIsEnabled'] = 'checked="checked"';
+       } else {
+               $tplVars['privateKeyIsEnabled'] = '';
+       }
 }
 
 if (!$userservice->isLoggedOn() || $currentUser->getId() != $userid) {
index 50240e563df9de8da8224a88b3bfd04680acaadd..8c81e0eb81ab8b075083fdaed5a7a8163d43a95a 100644 (file)
@@ -64,9 +64,14 @@ if (!isset($rssEntries) || $rssEntries <= 0) {
     $rssEntries = $maxRssEntries;
 }
 
+$privatekey = null;
+if (isset($_GET['privatekey'])) {
+    $privatekey = $_GET['privatekey'];
+}
 
 $watchlist = null;
 $pagetitle = '';
+$isTempLogin = false;
 if ($user && $user != 'all') {
     if ($user == 'watchlist') {
         $user = $cat;
@@ -78,8 +83,24 @@ if ($user && $user != 'all') {
     } else {
         if ($userinfo = $userservice->getUserByUsername($user)) {
             $userid =& $userinfo[$userservice->getFieldName('primary')];
+            /* if user is not logged in and has valid privatekey */
+            if (!$userservice->isLoggedOn()) {
+                if ($privatekey != null) {
+                    if ($userservice->loginPrivateKey($privatekey)) {
+                        $isTempLogin = true;
+                    } else {
+                        $tplVars['error'] = sprintf(T_('Failed to Autenticate User with username %s using private key'), $user);
+                        header('Content-type: text/html; charset=utf-8');
+                        $templateservice->loadTemplate('error.404.tpl', $tplVars);
+                        //throw a 404 error
+                        exit();
+                    }
+                }
+            }
+
         } else {
             $tplVars['error'] = sprintf(T_('User with username %s was not found'), $user);
+            header('Content-type: text/html; charset=utf-8');
             $templateservice->loadTemplate('error.404.tpl', $tplVars);
             //throw a 404 error
             exit();
@@ -87,7 +108,19 @@ if ($user && $user != 'all') {
     }
     $pagetitle .= ": ". $user;
 } else {
-    $userid = null;
+    if ($privatekey != null) {
+        if ($userservice->loginPrivateKey($privatekey)) {
+            $isTempLogin = true;
+        } else {
+            $tplVars['error'] = sprintf(T_('Failed to Autenticate User with username %s using private key'), $user);
+            header('Content-type: text/html; charset=utf-8');
+            $templateservice->loadTemplate('error.404.tpl', $tplVars);
+            //throw a 404 error
+            exit();
+        }
+    } else {
+        $userid = null;
+    }
 }
 
 if ($cat) {
@@ -100,7 +133,8 @@ $tplVars['feeddescription'] = sprintf(T_('Recent bookmarks posted to %s'), $GLOB
 
 $bookmarks = $bookmarkservice->getBookmarks(
     0, $rssEntries, $userid, $cat,
-    null, getSortOrder(), $watchlist
+    null, getSortOrder(), $watchlist,
+    null, null, null
 );
 
 $bookmarks_tmp = filter($bookmarks['bookmarks']);
@@ -134,6 +168,11 @@ $tplVars['feedlastupdate'] = date('r', strtotime($latestdate));
 
 $templateservice->loadTemplate('rss.tpl', $tplVars);
 
+/* If temporary login, please log out */
+if ($isTempLogin) {
+    $userservice->logout();
+}
+
 if ($usecache) {
     // Cache output if existing copy has expired
     $cacheservice->End($hash);