bug: Fix checking permissions during tag handling

This commit is contained in:
H. C. Kruse 2023-02-11 11:45:35 +01:00
parent f39205d140
commit 04e204f0c1
No known key found for this signature in database
GPG key ID: 0EADE441303A09B4
3 changed files with 62 additions and 38 deletions

View file

@ -47,7 +47,8 @@
"Hooks": { "Hooks": {
"TemplateStylesPropertySanitizer": "MediaWiki\\Extension\\TemplateStylesExtender\\Hooks\\PropertySanitizerHook::onSanitize", "TemplateStylesPropertySanitizer": "MediaWiki\\Extension\\TemplateStylesExtender\\Hooks\\PropertySanitizerHook::onSanitize",
"TemplateStylesStylesheetSanitizer": "MediaWiki\\Extension\\TemplateStylesExtender\\Hooks\\StylesheetSanitizerHook::onSanitize", "TemplateStylesStylesheetSanitizer": "MediaWiki\\Extension\\TemplateStylesExtender\\Hooks\\StylesheetSanitizerHook::onSanitize",
"ParserFirstCallInit": "MainHooks" "ParserFirstCallInit": "MainHooks",
"EditPage::attemptSave": "MainHooks"
}, },
"manifest_version": 2 "manifest_version": 2
} }

View file

@ -1,3 +1,4 @@
{ {
"ext-templatestylesextender-desc": "Extends [https://www.mediawiki.org/wiki/Extension:TemplateStyles TemplateStyles] with new selectors and matchers." "ext-templatestylesextender-desc": "Extends [https://www.mediawiki.org/wiki/Extension:TemplateStyles TemplateStyles] with new selectors and matchers.",
"templatestylesextender-unscope-no-permisson": "Only users with 'editinterface' permissions can unscope css."
} }

View file

@ -2,50 +2,72 @@
namespace MediaWiki\Extension\TemplateStylesExtender\Hooks; namespace MediaWiki\Extension\TemplateStylesExtender\Hooks;
use Html;
use MediaWiki\Extension\TemplateStyles\Hooks; use MediaWiki\Extension\TemplateStyles\Hooks;
use MediaWiki\Hook\EditPage__attemptSaveHook;
use MediaWiki\Hook\ParserFirstCallInitHook; use MediaWiki\Hook\ParserFirstCallInitHook;
use MediaWiki\MediaWikiServices; use MediaWiki\MediaWikiServices;
use MediaWiki\Revision\SlotRecord;
use MWException;
use PermissionsError;
class MainHooks implements ParserFirstCallInitHook { class MainHooks implements ParserFirstCallInitHook, EditPage__attemptSaveHook {
/** /**
* @throws \MWException * @throws MWException
*/ */
public function onParserFirstCallInit( $parser ) { public function onParserFirstCallInit( $parser ) {
$parser->setHook( 'templatestyles', [ __CLASS__, 'handleTag' ] ); $parser->setHook( 'templatestyles', [ __CLASS__, 'handleTag' ] );
} }
/** /**
* This is a wrapper for <templatestyles> tags, that allows unscoping of css for users with 'edit-interface' permissions * This is a wrapper for <templatestyles> tags, that allows unscoping of css for users with 'editinterface' permissions
* @see Hooks::handleTag() * @see Hooks::handleTag()
*/ */
public static function handleTag( $text, $params, $parser, $frame ): string public static function handleTag( $text, $params, $parser, $frame ): string {
{ if ( $parser->getOptions() === null || !MediaWikiServices::getInstance()->getMainConfig()->get( 'TemplateStylesExtenderEnableUnscopingSupport' ) ) {
if ( $parser->getOptions() === null || !MediaWikiServices::getInstance()->getMainConfig()->get( 'TemplateStylesExtenderEnableUnscopingSupport' ) ) { return Hooks::handleTag( $text, $params, $parser, $frame );
return Hooks::handleTag( $text, $params, $parser, $frame ); }
}
$options = $parser->getOptions(); $options = $parser->getOptions();
$wrapClass = $options->getWrapOutputClass(); $wrapClass = $options->getWrapOutputClass();
if ( isset( $params['wrapclass'] ) ) { if ( isset( $params['wrapclass'] ) ) {
$permManager = MediaWikiServices::getInstance()->getPermissionManager(); $options->setOption( 'wrapclass', $params['wrapclass'] );
$user = MediaWikiServices::getInstance()->getUserFactory()->newFromUserIdentity( $parser->getUserIdentity() ); }
if ( $permManager->userHasRight( $user, 'editinterface' ) || $permManager->userCan( 'editinterface', $user, $frame->getTitle() ) ) { $out = Hooks::handleTag( $text, $params, $parser, $frame );
$options->setOption( 'wrapclass', $params['wrapclass'] ); $options->setOption( 'wrapclass', $wrapClass );
} else {
return Html::element(
'p',
[ 'class' => 'mw-message-box mw-message-box-error' ],
'User is not allowed to unscope this css. Needs "editinterface" rights.'
);
}
}
$out = Hooks::handleTag( $text, $params, $parser, $frame );
$options->setOption( 'wrapclass', $wrapClass );
return $out; return $out;
} }
/**
* Check if 'wrapclass' was used in the page, if so only users with 'editinterface' permissions may save the page
*
* @param $editpage_Obj
* @return true
* @throws PermissionsError
*/
public function onEditPage__attemptSave( $editpage_Obj ): bool {
$revision = $editpage_Obj->getExpectedParentRevision();
if ( $revision === null || !MediaWikiServices::getInstance()->getMainConfig()->get( 'TemplateStylesExtenderEnableUnscopingSupport' ) ) {
return true;
}
$content = $revision->getContent( SlotRecord::MAIN );
if ( $content === null ) {
return true;
}
$permManager = MediaWikiServices::getInstance()->getPermissionManager();
$user = MediaWikiServices::getInstance()->getUserFactory()->newFromUserIdentity( $editpage_Obj->getContext()->getUser() );
$userCan = $permManager->userHasRight( $user, 'editinterface' ) || $permManager->userCan( 'editinterface', $user, $editpage_Obj->getTitle() );
if ( strpos( $content->getText(), 'wrapclass' ) !== false && !$userCan ) {
throw new PermissionsError( 'editinterface', [ 'templatestylesextender-unscope-no-permisson' ] );
}
return true;
}
} }