/** * Ensure that current params make sense, specify an existing list, and the requesting user has * access to it. Die if that's not the case. * @param DatabaseBase $db * @param ApiBase $module * @param array $params module parameters * @param bool $isWatchlist Will be set to true if the requested list is a watchlist * @param int $ownerId Will be set to the user ID of the list's owner * @throws \UsageException In case access is not allowed */ public static function checkListAccess(DatabaseBase $db, ApiBase $module, array $params, &$isWatchlist, &$ownerId) { global $wgGatherAutohideFlagLimit; if (is_null($params['owner']) !== is_null($params['token'])) { $p = $module->getModulePrefix(); $module->dieUsage("Both {$p}owner and {$p}token must be given or missing", 'invalidparammix'); } if (!$params['id']) { // If collection id is not given (or equals to 0), this is a watchlist access; // ApiBase::getWatchlistUser does all the necessary checks $isWatchlist = true; $ownerId = $module->getWatchlistUser($params)->getId(); return; } // Id was given, this could be public or private list, legacy watchlist or regular // Allow access to any public list/watchlist, and to private with proper owner/self $listRow = $db->selectRow('gather_list', array('gl_label', 'gl_user', 'gl_perm', 'gl_perm_override', 'gl_flag_count', 'gl_needs_review'), array('gl_id' => $params['id']), __METHOD__); if ($listRow === false) { $module->dieUsage('List does not exist', 'badid'); } $listRow = ApiEditList::normalizeRow($listRow); if ($params['owner'] !== null) { // Caller supplied token: treat them as trusted, someone who could see even private // At the same time, owner param must match list's owner // TODO: if we allow non-matching owner, we could treat it as public-only, // but that might be unexpected behavior $user = $module->getWatchlistUser($params); if ($listRow->gl_user !== $user->getId()) { $module->dieUsage('The owner supplied does not match the list\'s owner', 'permissiondenied'); } $showPrivate = true; } else { $user = $module->getUser(); $showPrivate = $user->isLoggedIn() && $listRow->gl_user === $user->getId() && $user->isAllowed('viewmywatchlist'); } // Check if this is a public list (if required) if (!$showPrivate && ($listRow->gl_perm !== ApiEditList::PERM_PUBLIC || $listRow->gl_perm_override === ApiEditList::PERM_OVERRIDE_HIDDEN || $listRow->gl_flag_count >= $wgGatherAutohideFlagLimit && $listRow->gl_perm_override !== ApiEditList::PERM_OVERRIDE_APPROVED)) { $module->dieUsage('You have no rights to see this list', 'badid'); } // If true, this is actually a watchlist, and it is either public or belongs to current user $isWatchlist = $listRow->gl_label === ''; $ownerId = $listRow->gl_user; }
protected function doDBUpdates() { $this->output("Populating gl_perm column in gather_list table\n"); $db = wfGetDB(DB_MASTER); $totalCount = 0; $batchSize = $count = $this->mBatchSize; while ($batchSize === $count) { $count = 0; $res = $db->select('gather_list', array('gl_id', 'gl_info', 'gl_label'), array('gl_perm' => null), __METHOD__, array('LIMIT' => $batchSize)); foreach ($res as $row) { $count++; $info = ApiEditList::parseListInfo($row->gl_info, $row->gl_id, true); $perm = ApiEditList::isPublic($info) && $row->gl_label !== '' ? 1 : 0; unset($info->perm); unset($info->public); $db->update('gather_list', array('gl_perm' => $perm, 'gl_info' => FormatJson::encode($info, false, FormatJson::ALL_OK), 'gl_updated' => $db->timestamp(wfTimestampNow())), array('gl_id' => $row->gl_id), __METHOD__); } $totalCount += $count; wfWaitForSlaves(); } $this->output("Done, {$totalCount} rows updated.\n"); return true; }
/** * Process one row, even if that row is a fake watchlist. * @param object|null $row A result row, e.g. from iterating a ResultWrapper. Null for the * fake watchlist. * @param int $count Row count, will be incremented on each call. * @param string $mode Mode API parameter. * @param int $limit Row limit; used to detect when to set continuation parameters. * @param bool $useInfo True if one of the info fields was requested. * @param Title|null $title Title object corresponding to the title parameter of the API. * @param bool $fld_label True if the label property is requested. * @param bool $fld_description True if the description property is requested. * @param bool $fld_public True if the public property is requested. * @param bool $fld_review True if the review property is requested. * @param bool $fld_image True if the image property is requested. * @param bool $fld_updated True if the updated property is requested. * @param bool $fld_owner True if the owner property is requested. * @param array $path API module path. * @param User|null $owner The user whose lists are being shown. * @param callable $getContinueEnumParameter A function that receives $row and returns a * continuation key that corresponds to the ordering of the query. * @return bool */ private function processRow($row, &$count, $mode, $limit, $useInfo, $title, $fld_label, $fld_description, $fld_public, $fld_review, $fld_image, $fld_updated, $fld_owner, $path, $owner, $getContinueEnumParameter) { global $wgGatherAutohideFlagLimit; if ($row === null) { // Fake watchlist row $row = (object) array('gl_id' => 0, 'gl_label' => '', 'gl_perm' => ApiEditList::PERM_PRIVATE, 'gl_perm_override' => ApiEditList::PERM_OVERRIDE_NONE, 'gl_needs_review' => 0, 'gl_flag_count' => 0, 'gl_updated' => '', 'gl_info' => ''); } else { $row = ApiEditList::normalizeRow($row); } $count++; if ($count > $limit) { // We've reached the one extra which shows that there are // additional pages to be had. Stop here... $this->setContinueEnumParameter('continue', $getContinueEnumParameter($row)); return false; } $isWatchlist = property_exists($row, 'isWl') ? $row->isWl : $row->gl_label === ''; $data = array('id' => $row->gl_id); if ($isWatchlist) { $data['watchlist'] = true; } if ($fld_label) { // TODO: check if this is the right wfMessage to show $data['label'] = !$isWatchlist ? $row->gl_label : wfMessage('watchlist')->plain(); } if ($fld_owner) { $data['owner'] = property_exists($row, 'user_name') ? $row->user_name : $owner->getName(); } if ($title) { if ($isWatchlist) { $data['title'] = $this->isTitleInWatchlist($owner, $title); } else { $data['title'] = isset($row->isIn); } } if ($fld_public) { $permMap = array_flip(ApiEditList::$permMap); $permOverrideMap = self::$permOverrideApiMap; if (!array_key_exists($row->gl_perm, $permMap)) { $this->dieDebug(__METHOD__, "Unknown gather perm={$row->gl_perm} for id {$row->gl_id}"); } if (!array_key_exists($row->gl_perm_override, $permOverrideMap)) { $this->dieDebug(__METHOD__, "Unknown gather " . "perm_override={$row->gl_perm_override} for id {$row->gl_id}"); } $data['perm'] = $permMap[$row->gl_perm]; if ($permOverrideMap[$row->gl_perm_override]) { $data['perm_override'] = $permOverrideMap[$row->gl_perm_override]; } if ($row->gl_flag_count >= $wgGatherAutohideFlagLimit) { $data['flagged'] = true; } if ($row->gl_perm_override === ApiEditList::PERM_OVERRIDE_HIDDEN || $row->gl_perm_override === ApiEditList::PERM_OVERRIDE_NONE && $row->gl_flag_count >= $wgGatherAutohideFlagLimit) { $data['hidden'] = true; } } if ($fld_review) { if ($row->gl_needs_review || $row->gl_flag_count >= $wgGatherAutohideFlagLimit) { $data['review'] = true; } } if ($useInfo) { $info = ApiEditList::parseListInfo($row->gl_info, $row->gl_id, false); if ($fld_description) { $data['description'] = property_exists($info, 'description') ? $info->description : ''; } if ($fld_image) { if (property_exists($info, 'image') && $info->image) { $data['image'] = $info->image; $file = wfFindFile($info->image); if (!$file) { $data['badimage'] = true; } else { $data['imageurl'] = $file->getFullUrl(); $data['imagewidth'] = intval($file->getWidth()); $data['imageheight'] = intval($file->getHeight()); } } else { $data['image'] = false; } } } if ($fld_updated) { $data['updated'] = wfTimestamp(TS_ISO_8601, $row->gl_updated); } $fit = $this->getResult()->addValue($path, null, $data); if (!$fit) { $this->setContinueEnumParameter('continue', $getContinueEnumParameter($row)); return false; } return true; }