mirror of
https://gerrit.wikimedia.org/r/mediawiki/extensions/AbuseFilter.git
synced 2024-11-27 23:40:19 +00:00
Remove info leak
Oversighted/deleted edits and log actions were entirely accessible to non-oversighters via AbuseFilter/examine for RC, and via AbuseFilter/test. Now, we take into account the revision/log visibility and user permissions to determine what to show. Other changes in this patch: *Show the examine link if and only if the user can examine the given row *If a revision is hidden but the user can see it, don't hide its elements in ChangesList (only leave them striked/greyed) *Make APIs better understand revision visibility. *Make a clear distinction between deleted and suppressed edits/log entries. Co-authored with rxy <git@rxy.jp> Bug: T207085 Change-Id: Icfa48e366a7e5e3abd5d2155ecfddfc09b378088
This commit is contained in:
parent
428a73f7e4
commit
103dfa3b66
|
@ -23,6 +23,13 @@ class AbuseFilterChangesList extends OldChangesList {
|
|||
* @suppress PhanUndeclaredProperty for $rc->filterResult, which isn't a big deal
|
||||
*/
|
||||
public function insertExtra( &$s, &$rc, &$classes ) {
|
||||
if ( (int)$rc->getAttribute( 'rc_deleted' ) !== 0 ) {
|
||||
$s .= ' ' . $this->msg( 'abusefilter-log-hidden-implicit' )->parse();
|
||||
if ( !$this->userCan( $rc, Revision::SUPPRESSED_ALL ) ) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
$examineParams = [];
|
||||
if ( $this->testFilter ) {
|
||||
$examineParams['testfilter'] = $this->testFilter;
|
||||
|
@ -48,6 +55,64 @@ class AbuseFilterChangesList extends OldChangesList {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert links to user page, user talk page and eventually a blocking link.
|
||||
* Like the parent, but don't hide details if user can see them.
|
||||
*
|
||||
* @param string &$s HTML to update
|
||||
* @param RecentChange &$rc
|
||||
*/
|
||||
public function insertUserRelatedLinks( &$s, &$rc ) {
|
||||
$links = $this->getLanguage()->getDirMark() . Linker::userLink( $rc->mAttribs['rc_user'],
|
||||
$rc->mAttribs['rc_user_text'] ) .
|
||||
Linker::userToolLinks( $rc->mAttribs['rc_user'], $rc->mAttribs['rc_user_text'] );
|
||||
|
||||
if ( $this->isDeleted( $rc, Revision::DELETED_USER ) ) {
|
||||
if ( $this->userCan( $rc, Revision::DELETED_USER ) ) {
|
||||
$s .= ' <span class="history-deleted">' . $links . '</span>';
|
||||
} else {
|
||||
$s .= ' <span class="history-deleted">' .
|
||||
$this->msg( 'rev-deleted-user' )->escaped() . '</span>';
|
||||
}
|
||||
} else {
|
||||
$s .= $links;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert a formatted comment. Like the parent, but don't hide details if user can see them.
|
||||
* @param RecentChange $rc
|
||||
* @return string
|
||||
*/
|
||||
public function insertComment( $rc ) {
|
||||
if ( $this->isDeleted( $rc, Revision::DELETED_COMMENT ) ) {
|
||||
if ( $this->userCan( $rc, Revision::DELETED_COMMENT ) ) {
|
||||
return ' <span class="history-deleted">' .
|
||||
Linker::commentBlock( $rc->mAttribs['rc_comment'], $rc->getTitle() ) . '</span>';
|
||||
} else {
|
||||
return ' <span class="history-deleted">' .
|
||||
$this->msg( 'rev-deleted-comment' )->escaped() . '</span>';
|
||||
}
|
||||
} else {
|
||||
return Linker::commentBlock( $rc->mAttribs['rc_comment'], $rc->getTitle() );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert a formatted action. The same as parent, but with a different audience in LogFormatter
|
||||
*
|
||||
* @param RecentChange $rc
|
||||
* @return string
|
||||
*/
|
||||
public function insertLogEntry( $rc ) {
|
||||
$formatter = LogFormatter::newFromRow( $rc->mAttribs );
|
||||
$formatter->setContext( $this->getContext() );
|
||||
$formatter->setAudience( LogFormatter::FOR_THIS_USER );
|
||||
$formatter->setShowUserToolLinks( true );
|
||||
$mark = $this->getLanguage()->getDirMark();
|
||||
return $formatter->getActionText() . " $mark" . $formatter->getComment();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string &$s
|
||||
* @param RecentChange &$rc
|
||||
|
|
|
@ -112,6 +112,11 @@ class AbuseFilterViewExamine extends AbuseFilterView {
|
|||
return;
|
||||
}
|
||||
|
||||
if ( !ChangesList::userCan( RecentChange::newFromRow( $row ), Revision::SUPPRESSED_ALL ) ) {
|
||||
$out->addWikiMsg( 'abusefilter-log-details-hidden-implicit' );
|
||||
return;
|
||||
}
|
||||
|
||||
self::$examineType = 'rc';
|
||||
self::$examineId = $rcid;
|
||||
|
||||
|
@ -157,10 +162,12 @@ class AbuseFilterViewExamine extends AbuseFilterView {
|
|||
return;
|
||||
}
|
||||
|
||||
if ( SpecialAbuseLog::isHidden( $row ) === 'implicit' &&
|
||||
!$this->getUser()->isAllowed( 'deletedtext' ) ) {
|
||||
$out->addWikiMsg( 'abusefilter-log-details-hidden-implicit' );
|
||||
return;
|
||||
if ( SpecialAbuseLog::isHidden( $row ) === 'implicit' ) {
|
||||
$rev = Revision::newFromId( $row->afl_rev_id );
|
||||
if ( !$rev->userCan( Revision::SUPPRESSED_ALL, $this->getUser() ) ) {
|
||||
$out->addWikiMsg( 'abusefilter-log-details-hidden-implicit' );
|
||||
return;
|
||||
}
|
||||
}
|
||||
$vars = AbuseFilter::loadVarDump( $row->afl_var_dump );
|
||||
$out->addJsConfigVars( 'wgAbuseFilterVariables', $vars->dumpAllVars( true ) );
|
||||
|
|
|
@ -172,10 +172,14 @@ class ApiQueryAbuseLog extends ApiQueryBase {
|
|||
$this->setContinueEnumParameter( 'start', $ts->getTimestamp( TS_ISO_8601 ) );
|
||||
break;
|
||||
}
|
||||
if ( SpecialAbuseLog::isHidden( $row ) &&
|
||||
!SpecialAbuseLog::canSeeHidden()
|
||||
) {
|
||||
$hidden = SpecialAbuseLog::isHidden( $row );
|
||||
if ( $hidden === true && !SpecialAbuseLog::canSeeHidden() ) {
|
||||
continue;
|
||||
} elseif ( $hidden === 'implicit' ) {
|
||||
$rev = Revision::newFromId( $row->afl_rev_id );
|
||||
if ( !$rev->userCan( Revision::SUPPRESSED_ALL, $user ) ) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
$canSeeDetails = SpecialAbuseLog::canSeeDetails( $row->afl_filter );
|
||||
|
||||
|
@ -230,11 +234,8 @@ class ApiQueryAbuseLog extends ApiQueryBase {
|
|||
}
|
||||
}
|
||||
|
||||
if ( $fld_hidden ) {
|
||||
$val = SpecialAbuseLog::isHidden( $row );
|
||||
if ( $val ) {
|
||||
$entry['hidden'] = $val;
|
||||
}
|
||||
if ( $fld_hidden && $hidden ) {
|
||||
$entry['hidden'] = $hidden;
|
||||
}
|
||||
|
||||
if ( $entry ) {
|
||||
|
|
|
@ -54,7 +54,6 @@ class AbuseFilterExaminePager extends ReverseChronologicalPager {
|
|||
* @return string
|
||||
*/
|
||||
public function formatRow( $row ) {
|
||||
// Incompatible stuff.
|
||||
$rc = RecentChange::newFromRow( $row );
|
||||
$rc->counter = $this->mPage->mCounter++;
|
||||
return $this->mChangesList->recentChangesLine( $rc, false );
|
||||
|
|
|
@ -541,11 +541,13 @@ class SpecialAbuseLog extends SpecialPage {
|
|||
$out->addWikiMsg( 'abusefilter-log-details-hidden' );
|
||||
|
||||
return;
|
||||
} elseif ( self::isHidden( $row ) === 'implicit' &&
|
||||
!$this->getUser()->isAllowed( 'deletedtext' ) ) {
|
||||
} elseif ( self::isHidden( $row ) === 'implicit' ) {
|
||||
$rev = Revision::newFromId( $row->afl_rev_id );
|
||||
// The log is visible, but refers to a deleted revision
|
||||
$out->addWikiMsg( 'abusefilter-log-details-hidden-implicit' );
|
||||
return;
|
||||
if ( !$rev->userCan( Revision::SUPPRESSED_ALL, $this->getUser() ) ) {
|
||||
$out->addWikiMsg( 'abusefilter-log-details-hidden-implicit' );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
$output = Xml::element(
|
||||
|
@ -1100,7 +1102,7 @@ class SpecialAbuseLog extends SpecialPage {
|
|||
*
|
||||
* @param stdClass $row The abuse_filter_log row object.
|
||||
*
|
||||
* @return Mixed true if the item is explicitly hidden, false if it is not.
|
||||
* @return bool|string true if the item is explicitly hidden, false if it is not.
|
||||
* The string 'implicit' if it is hidden because the corresponding revision is hidden.
|
||||
*/
|
||||
public static function isHidden( $row ) {
|
||||
|
|
Loading…
Reference in a new issue