diff options
| author | Mark Pemberton <mpemberton5@gmail.com> | 2011-05-13 14:26:51 -0400 | 
|---|---|---|
| committer | Mark Pemberton <mpemberton5@gmail.com> | 2011-05-13 14:26:51 -0400 | 
| commit | ec345f7a1343769abdf3f5920a0732b24726b733 (patch) | |
| tree | 1a65f2f0bea89b16f5c8e93264b67e2927570677 | |
| parent | 803b83fb7d051593066b5224a59fbf3ec6efc824 (diff) | |
| download | semanticscuttle-ec345f7a1343769abdf3f5920a0732b24726b733.tar.gz semanticscuttle-ec345f7a1343769abdf3f5920a0732b24726b733.tar.bz2 | |
new privatekey2 branch with privatekey changes
| -rw-r--r-- | data/schema/6.sql | 4 | ||||
| -rw-r--r-- | data/tables.sql | 3 | ||||
| -rw-r--r-- | data/templates/editprofile.tpl.php | 8 | ||||
| -rw-r--r-- | data/templates/rss.tpl.php | 4 | ||||
| -rw-r--r-- | data/templates/top.inc.php | 2 | ||||
| -rw-r--r-- | doc/UPGRADE.txt | 3 | ||||
| -rw-r--r-- | src/SemanticScuttle/Model/User.php | 26 | ||||
| -rw-r--r-- | src/SemanticScuttle/Service/Bookmark.php | 2 | ||||
| -rw-r--r-- | src/SemanticScuttle/Service/User.php | 211 | ||||
| -rw-r--r-- | tests/BookmarkTest.php | 46 | ||||
| -rw-r--r-- | tests/TestBase.php | 13 | ||||
| -rw-r--r-- | tests/UserTest.php | 333 | ||||
| -rw-r--r-- | www/index.php | 13 | ||||
| -rw-r--r-- | www/jsScuttle.php | 10 | ||||
| -rw-r--r-- | www/profile.php | 32 | ||||
| -rw-r--r-- | www/rss.php | 43 | 
16 files changed, 704 insertions, 49 deletions
| diff --git a/data/schema/6.sql b/data/schema/6.sql index 0c208ad..e4acd53 100644 --- a/data/schema/6.sql +++ b/data/schema/6.sql @@ -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`); + diff --git a/data/tables.sql b/data/tables.sql index d53945e..dd4e924 100644 --- a/data/tables.sql +++ b/data/tables.sql @@ -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;  --  diff --git a/data/templates/editprofile.tpl.php b/data/templates/editprofile.tpl.php index cc74f04..76f608a 100644 --- a/data/templates/editprofile.tpl.php +++ b/data/templates/editprofile.tpl.php @@ -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>    +        <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> diff --git a/data/templates/rss.tpl.php b/data/templates/rss.tpl.php index e6e66f7..6be5425 100644 --- a/data/templates/rss.tpl.php +++ b/data/templates/rss.tpl.php @@ -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> diff --git a/data/templates/top.inc.php b/data/templates/top.inc.php index bdd4b1a..738b71e 100644 --- a/data/templates/top.inc.php +++ b/data/templates/top.inc.php @@ -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] .'" />';  	}  } diff --git a/doc/UPGRADE.txt b/doc/UPGRADE.txt index 3be6654..fe8624a 100644 --- a/doc/UPGRADE.txt +++ b/doc/UPGRADE.txt @@ -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  ------------------------- diff --git a/src/SemanticScuttle/Model/User.php b/src/SemanticScuttle/Model/User.php index 500f5b1..3aa617b 100644 --- a/src/SemanticScuttle/Model/User.php +++ b/src/SemanticScuttle/Model/User.php @@ -35,6 +35,7 @@ class SemanticScuttle_Model_User      var $content;      var $datetime;      var $isAdmin; +    var $privateKey;      /**       * Create a new user object @@ -69,6 +70,29 @@ class SemanticScuttle_Model_User      }      /** +     * 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.       *       * @return string Full name @@ -182,4 +206,4 @@ class SemanticScuttle_Model_User      }  } -?>
\ No newline at end of file +?> diff --git a/src/SemanticScuttle/Service/Bookmark.php b/src/SemanticScuttle/Service/Bookmark.php index 919ca7a..e836cd8 100644 --- a/src/SemanticScuttle/Service/Bookmark.php +++ b/src/SemanticScuttle/Service/Bookmark.php @@ -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)';              } diff --git a/src/SemanticScuttle/Service/User.php b/src/SemanticScuttle/Service/User.php index 09a2cb1..c3633de 100644 --- a/src/SemanticScuttle/Service/User.php +++ b/src/SemanticScuttle/Service/User.php @@ -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) { @@ -280,6 +293,22 @@ class SemanticScuttle_Service_User extends SemanticScuttle_DbService      }      /** +     * 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       *       * @param boolean $refresh Reload the user from database @@ -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); @@ -510,6 +539,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       *       * @return void @@ -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; diff --git a/tests/BookmarkTest.php b/tests/BookmarkTest.php index b50dab2..44a82d9 100644 --- a/tests/BookmarkTest.php +++ b/tests/BookmarkTest.php @@ -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'])); + +    } +  }  ?> diff --git a/tests/TestBase.php b/tests/TestBase.php index 095f32d..1331ec6 100644 --- a/tests/TestBase.php +++ b/tests/TestBase.php @@ -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 +?> diff --git a/tests/UserTest.php b/tests/UserTest.php index 2f57112..230167d 100644 --- a/tests/UserTest.php +++ b/tests/UserTest.php @@ -35,6 +35,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 +?> diff --git a/www/index.php b/www/index.php index f6704ae..0977923 100644 --- a/www/index.php +++ b/www/index.php @@ -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().'&privatekey='.$currentUser->getPrivateKey()) +            ) +        ); +    } +} +  if ($usecache) {  	// Generate hash for caching on  	$hashtext = $_SERVER['REQUEST_URI']; diff --git a/www/jsScuttle.php b/www/jsScuttle.php index c166755..76b49dc 100644 --- a/www/jsScuttle.php +++ b/www/jsScuttle.php @@ -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 == '') { diff --git a/www/profile.php b/www/profile.php index ccdb7a8..e6894d0 100644 --- a/www/profile.php +++ b/www/profile.php @@ -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) { diff --git a/www/rss.php b/www/rss.php index 50240e5..8c81e0e 100644 --- a/www/rss.php +++ b/www/rss.php @@ -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); | 
