Ejemplo n.º 1
0
 /**
  * @method afterRemoveExcecute
  * @param {Db_Result} $result
  * @param {Db_Query} $query
  * @return {Db_Result}
  */
 function afterRemoveExecute($result, $query)
 {
     $stream = $this;
     // if the above call threw an exception, then we will not be doing the following.
     Q_Utils::sendToNode(array("Q/method" => "Streams/Stream/remove", "stream" => Q::json_encode($stream->toArray())));
     /**
      * @event Streams/remove/$streamType {after}
      * @param {Streams_Stream} stream
      * @param {string} asUserId
      */
     Q::event("Streams/remove/{$stream->type}", compact('stream', 'result'), 'after');
     if ($this->name !== 'Streams/user/firstName' and $this->name !== 'Streams/user/lastName') {
         return $result;
     }
     // Update all avatars corresponding to access rows for this stream
     $taintedAccess = Streams_Access::select('*')->where(array('publisherId' => $this->publisherId, 'streamName' => $this->name))->fetchDbRows();
     Streams::updateAvatars($this->publisherId, $taintedAccess, $this, true);
     return $result;
 }
Ejemplo n.º 2
0
/**
 * Access tool
 * @class Streams access
 * @constructor
 * @param {array} $options Options for the tool
 * @param {string} [$options.publisherId] the id of the user who is publishing the stream
 * @param {string} [$options.streamName] the name of the stream for which to edit access levels
 * @param {array} [$options.tabs] array of tab name => title. Defaults to read, write, admin tabs.
 * @param {array} [$options.ranges] associative array with keys "read", "write", "admin" and values as associative arrays of ($min, $max) for the displayed levels.
 * @param {boolean} [$options.controls] optionally set this to true to render only the controls
 */
function Streams_access_tool($options)
{
    $tabs = array('read' => 'visible to', 'write' => 'editable by', 'admin' => 'members');
    extract($options);
    $user = Users::loggedInUser(true);
    /**
     * @var string $streamName
     */
    if (empty($streamName)) {
        $streamName = Streams::requestedName(true);
    }
    if (empty($publisherId)) {
        $publisherId = Streams::requestedPublisherId();
        if (empty($publisherId)) {
            $publisherId = $user->id;
        }
    }
    reset($tabs);
    $tab = Q::ifset($_REQUEST, 'tab', key($tabs));
    $stream = Streams::fetchOne($user->id, $publisherId, $streamName);
    if (!$stream) {
        throw new Q_Exception_MissingRow(array('table' => 'stream', 'criteria' => 'with that name'));
    }
    $stream->addPreloaded($user->id);
    if (!$stream->testAdminLevel('own')) {
        throw new Users_Exception_NotAuthorized();
    }
    $access_array = Streams_Access::select('*')->where(array('publisherId' => $stream->publisherId, 'streamName' => $stream->name))->andWhere("{$tab}Level != -1")->fetchDbRows();
    $labelRows = Users_Label::fetch($stream->publisherId, '', true);
    $labels = array();
    $icons = array();
    foreach ($labelRows as $label => $row) {
        $labels[$label] = $row->title;
        $icons[$label] = "labels/{$label}";
    }
    $userId_list = array();
    foreach ($access_array as $a) {
        if ($a->ofUserId) {
            $userId_list[] = $a->ofUserId;
        }
    }
    $avatar_array = empty($userId_list) ? array() : Streams_Avatar::fetch($user->id, $userId_list);
    switch ($tab) {
        case 'read':
            $levels = Q_Config::get('Streams', 'readLevelOptions', array());
            break;
        case 'write':
            $levels = Q_Config::get('Streams', 'writeLevelOptions', array());
            break;
        case 'admin':
            $levels = Q_Config::get('Streams', 'adminLevelOptions', array());
            break;
    }
    if (isset($ranges[$tab])) {
        $range_min = reset($ranges[$tab]);
        $range_max = end($ranges[$tab]);
        foreach ($levels as $k => $v) {
            if ($k < $range_min) {
                unset($levels[$k]);
            }
            if ($k > $range_max) {
                unset($levels[$k]);
            }
        }
    }
    $accessActionUrl = Q_Uri::url("Streams/access?publisherId={$publisherId}&streamName={$streamName}");
    $dir = Q_Config::get('Users', 'paths', 'icons', 'files/Users/icons');
    $accessArray = Db::exportArray($access_array);
    $avatarArray = Db::exportArray($avatar_array);
    if (empty($controls)) {
        Q_Response::addScript("plugins/Streams/js/Streams.js");
        Q_Response::addScript("plugins/Streams/js/tools/access.js");
        Q_Response::setToolOptions(compact('accessArray', 'avatarArray', 'labels', 'icons', 'tab', 'publisherId', 'streamName'));
    } else {
        Q_Response::setSlot('extra', array('stream' => $stream->exportArray(), 'accessArray' => $accessArray, 'avatarArray' => $avatarArray, 'labels' => $labels, 'icons' => $icons));
    }
    return Q::view('Streams/tool/access.php', compact('stream', 'tabs', 'tab', 'labels', 'icons', 'levels', 'dir', 'publisherId', 'streamName', 'accessActionUrl', 'controls'));
}
Ejemplo n.º 3
0
 /**
  * Calculates the access for one or more streams by querying the database
  * Modifies the objects in the $streams array, setting their access levels.
  * After the function returns, you will be able to call the methods
  * testReadLevel(), testWriteLevel() and testAdminLevel()
  * on these streams before using them on the user's behalf.
  * @method fetch
  * @static
  * @param {string} $asUserId
  *  Set this to the user relative to whom access is calculated.
  *  If this matches the publisherId, just sets full access and calls publishedByFetcher(true).
  *  If this is '', only returns the streams anybody can see.
  *  If this is null, the logged-in user's id is used, or '' if no one is logged in
  * @param {string} $publisherId
  *  The id of the user publishing these streams
  * @param {array} $streams
  *  An array of streams, obtained for example by Streams::fetch
  * @param {boolean} $recalculate=false
  *  Pass true here to force recalculating access to streams for which access was already calculated
  * @return {integer}
  *  The number of streams that were recalculated
  */
 static function calculateAccess($asUserId, $publisherId, $streams, $recalculate = false)
 {
     if (!isset($asUserId)) {
         $asUserId = Users::loggedInUser();
         if (!$asUserId) {
             $asUserId = "";
         }
     }
     if ($asUserId instanceof Users_User) {
         $asUserId = $asUserId->id;
     }
     if ($publisherId instanceof Users_User) {
         $publisherId = $publisherId->id;
     }
     if ($recalculate) {
         $streams2 = $streams;
     } else {
         $streams2 = array();
         foreach ($streams as $k => $s) {
             if ($s->get('readLevel', null) === null) {
                 $streams2[$k] = $s;
             }
         }
     }
     if (empty($streams2)) {
         return 0;
     }
     $public_source = Streams::$ACCESS_SOURCES['public'];
     $contact_source = Streams::$ACCESS_SOURCES['contact'];
     $direct_source = Streams::$ACCESS_SOURCES['direct'];
     $streams3 = array();
     $names = array();
     foreach ($streams2 as $s) {
         if ($s->get('asUserId', null) === $asUserId) {
             continue;
         }
         $s->set('asUserId', $asUserId);
         if ($asUserId and $asUserId == $publisherId) {
             // The publisher should have full access to every one of their streams.
             // Streams which are "required", though, won't be deleted by the system.
             $required = Q_Config::get('Streams', 'requiredUserStreams', $s->name, false);
             $s->set('isRequired', $required);
             $s->set('readLevel', Streams::$READ_LEVEL['max']);
             $s->set('writeLevel', Streams::$WRITE_LEVEL['max']);
             $s->set('adminLevel', Streams::$ADMIN_LEVEL['max']);
             $s->set('readLevel_source', $direct_source);
             $s->set('writeLevel_source', $direct_source);
             $s->set('adminLevel_source', $direct_source);
             $s->publishedByFetcher(true);
             continue;
         }
         $s->set('readLevel', $s->readLevel);
         $s->set('writeLevel', $s->writeLevel);
         $s->set('adminLevel', $s->adminLevel);
         $s->set('readLevel_source', $public_source);
         $s->set('writeLevel_source', $public_source);
         $s->set('adminLevel_source', $public_source);
         if (empty($asUserId)) {
             continue;
             // No need to fetch further access info.
         }
         $names[] = $s->name;
         $names[] = $s->type . "*";
         $streams3[] = $s;
     }
     if (empty($names)) {
         return count($streams2);
     }
     // Get the per-label access data
     // Avoid making a join to allow more flexibility for sharding
     $accesses = Streams_Access::select('*')->where(array('publisherId' => $publisherId, 'streamName' => $names, 'ofUserId' => array('', $asUserId)))->fetchDbRows();
     $labels = array();
     foreach ($accesses as $access) {
         if ($access->ofContactLabel) {
             $labels[] = $access->ofContactLabel;
         }
     }
     if (!empty($labels)) {
         $labels = array_unique($labels);
         $contacts = Users_Contact::select('*')->where(array('userId' => $publisherId, 'label' => $labels, 'contactUserId' => $asUserId))->fetchDbRows();
         foreach ($contacts as $contact) {
             foreach ($accesses as $access) {
                 if ($access->ofContactLabel !== $contact->label) {
                     continue;
                 }
                 foreach ($streams3 as $stream) {
                     $tail = substr($access->streamName, -1);
                     $head = substr($access->streamName, 0, -1);
                     if ($stream->name !== $access->streamName and ($tail !== '*' or $head !== $stream->type)) {
                         continue;
                     }
                     $readLevel = $stream->get('readLevel', 0);
                     $writeLevel = $stream->get('writeLevel', 0);
                     $adminLevel = $stream->get('adminLevel', 0);
                     if ($access->readLevel >= 0 and $access->readLevel > $readLevel) {
                         $stream->set('readLevel', $access->readLevel);
                         $stream->set('readLevel_source', $contact_source);
                     }
                     if ($access->writeLevel >= 0 and $access->writeLevel > $writeLevel) {
                         $stream->set('writeLevel', $access->writeLevel);
                         $stream->set('writeLevel_source', $contact_source);
                     }
                     if ($access->adminLevel >= 0 and $access->adminLevel > $adminLevel) {
                         $stream->set('adminLevel', $access->adminLevel);
                         $stream->set('adminLevel_source', $contact_source);
                     }
                 }
             }
         }
     }
     // Override with per-user access data
     foreach ($accesses as $access) {
         foreach ($streams3 as $stream) {
             $tail = substr($access->streamName, -1);
             $head = substr($access->streamName, 0, -1);
             if ($stream->name !== $access->streamName and ($tail !== '*' or $head !== $stream->type)) {
                 continue;
             }
             if ($access->ofUserId === $asUserId) {
                 if ($access->readLevel >= 0) {
                     $stream->set('readLevel', $access->readLevel);
                     $stream->set('readLevel_source', $direct_source);
                 }
                 if ($access->writeLevel >= 0) {
                     $stream->set('writeLevel', $access->writeLevel);
                     $stream->set('writeLevel_source', $direct_source);
                 }
                 if ($access->adminLevel >= 0) {
                     $stream->set('adminLevel', $access->adminLevel);
                     $stream->set('adminLevel_source', $direct_source);
                 }
             }
         }
     }
     return count($streams2);
 }
Ejemplo n.º 4
0
 /**
  * Keeps Access table consistent on row deletion and update avatar
  * @method afterRemoveExecute
  * @param {Db_Result} $result
  *	Query result
  * @param {array} $query
  *	The query which has been excecuted
  * @return {Db_Result}
  */
 function afterRemoveExecute($result, $query)
 {
     if (!empty($this->ofUserId)) {
         // Removed an access for a specific user
         Streams::updateAvatar($this->ofUserId, $this->publisherId);
         return $result;
     }
     if (empty($this->ofContactLabel)) {
         return $result;
     }
     // Update all avatars corresponding to access rows for this stream
     $tainted_access = Streams_Access::select('*')->where(array('publisherId' => $this->publisherId, 'streamName' => $this->streamName))->fetchDbRows();
     $found = false;
     foreach ($tainted_access as $ca) {
         if ($ca->ofContactLabel === $this->ofContactLabel) {
             // this should never really happen, since the row was just deleted
             $found = true;
             $ca->set('removed', true);
         }
     }
     if (!$found) {
         $this->set('removed', true);
         $tainted_access[] = $this;
     }
     Streams::updateAvatars($this->publisherId, $tainted_access, $this->streamName);
     return $result;
 }