|
|
|
<?php
|
|
|
|
namespace Isekai\OIDC;
|
|
|
|
|
|
|
|
use Html;
|
|
|
|
use MediaWiki\MediaWikiServices;
|
|
|
|
use OutputPage;
|
|
|
|
use RequestContext;
|
|
|
|
use Title;
|
|
|
|
|
|
|
|
class IsekaiOIDCAuthHooks {
|
|
|
|
const SYNLOGIN_SESSIONKEY = 'IsekaiOIDCSyncLogin';
|
|
|
|
const SYNLOGOUT_SESSIONKEY = 'IsekaiOIDCSyncLogout';
|
|
|
|
|
|
|
|
public static function onRegistration() {
|
|
|
|
$passwordProviders = [
|
|
|
|
'MediaWiki\Auth\LocalPasswordPrimaryAuthenticationProvider',
|
|
|
|
'MediaWiki\Auth\TemporaryPasswordPrimaryAuthenticationProvider'
|
|
|
|
];
|
|
|
|
$providers = $GLOBALS['wgAuthManagerAutoConfig'];
|
|
|
|
if ( isset( $providers['primaryauth'] ) ) {
|
|
|
|
$primaries = $providers['primaryauth'];
|
|
|
|
foreach ( $primaries as $key => $provider ) {
|
|
|
|
if ( in_array( $provider['class'], $passwordProviders ) ) {
|
|
|
|
unset( $GLOBALS['wgAuthManagerAutoConfig']['primaryauth'][$key] );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Implements LoadExtensionSchemaUpdates hook.
|
|
|
|
*
|
|
|
|
* @param \DatabaseUpdater $updater
|
|
|
|
*/
|
|
|
|
public static function loadExtensionSchemaUpdates( $updater ) {
|
|
|
|
$dir = dirname(__DIR__) . '/sql/';
|
|
|
|
$type = $updater->getDB()->getType();
|
|
|
|
$updater->addExtensionTable( 'isekai_oidc',
|
|
|
|
$dir . $type . '/AddTable.sql' );
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Implements PageBeforeDisplay hook.
|
|
|
|
* @param OutputPage $out
|
|
|
|
*/
|
|
|
|
public static function onBeforePageDisplay($out) {
|
|
|
|
$services = MediaWikiServices::getInstance();
|
|
|
|
$wgIsekaiOIDC = $services->getMainConfig()->get('IsekaiOIDC');
|
|
|
|
|
|
|
|
if (isset($wgIsekaiOIDC['syncLogout']) && $wgIsekaiOIDC['syncLogout']) {
|
|
|
|
$title = $out->getTitle();
|
|
|
|
$request = RequestContext::getMain()->getRequest();
|
|
|
|
$needLogout = $request->getCookie(self::SYNLOGOUT_SESSIONKEY);
|
|
|
|
$isLogoutPage = $title != null && $title->isSpecial('Userlogout');
|
|
|
|
if ($isLogoutPage || $needLogout) { // 需要重定向到用户退出页面
|
|
|
|
$oldName = $request->getCookie('UserName');
|
|
|
|
wfDebugLog('IsekaiOIDC', 'oldUser: ' . $oldName);
|
|
|
|
|
|
|
|
$oldUser = MediaWikiServices::getInstance()->getUserFactory()->newFromName($oldName);
|
|
|
|
if ( $oldUser === false ) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
list($subject, $accessToken, $refreshToken) = IsekaiOIDCAuth::findOidcDataByUserId($oldUser->getId());
|
|
|
|
if ($subject != null) {
|
|
|
|
$redirectUri = '';
|
|
|
|
if ($isLogoutPage) {
|
|
|
|
$returnto = $request->getVal('returnto');
|
|
|
|
$returntoquery = $request->getVal('returntoquery');
|
|
|
|
if ($returnto) {
|
|
|
|
$returnto = Title::newFromText($returnto);
|
|
|
|
} else {
|
|
|
|
$returnto = Title::newMainPage();
|
|
|
|
}
|
|
|
|
if (!$returnto) {
|
|
|
|
$returnto = Title::newMainPage();
|
|
|
|
}
|
|
|
|
$redirectUri = Title::newMainPage()->getFullURL($returntoquery);
|
|
|
|
} else if ($title != null) {
|
|
|
|
$redirectUri = $title->getFullURL();
|
|
|
|
} else {
|
|
|
|
$redirectUri = Title::newMainPage()->getFullURL();
|
|
|
|
}
|
|
|
|
|
|
|
|
$url = $wgIsekaiOIDC['endpoint'] . 'protocol/openid-connect/logout?' .
|
|
|
|
http_build_query([ 'redirect_uri' => $redirectUri ]);
|
|
|
|
wfDebugLog('IsekaiOIDC', 'logout url: ' . $url);
|
|
|
|
$response = $request->response();
|
|
|
|
$response->clearCookie(self::SYNLOGOUT_SESSIONKEY);
|
|
|
|
$response->header('Location: ' . $url);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public static function onLogout($user, &$injected_html) {
|
|
|
|
$request = RequestContext::getMain()->getRequest();
|
|
|
|
$request->response()->setCookie(self::SYNLOGOUT_SESSIONKEY, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
public static function onGetPreferences(\User $user, &$preferences) {
|
|
|
|
$services = MediaWikiServices::getInstance();
|
|
|
|
$wgIsekaiOIDC = $services->getMainConfig()->get('IsekaiOIDC');
|
|
|
|
|
|
|
|
$profileUrl = $wgIsekaiOIDC['endpoint'] . 'account/';
|
|
|
|
$referrer = $wgIsekaiOIDC['clientID'];
|
|
|
|
$referrerUri = Title::newFromText('Special:Preferences')->getCanonicalURL();
|
|
|
|
$profileUrl .= '?' . http_build_query([
|
|
|
|
'referrer' => $referrer,
|
|
|
|
'referrer_uri' => $referrerUri
|
|
|
|
]);
|
|
|
|
|
|
|
|
$preferences['global-profile'] = array(
|
|
|
|
'type' => 'info',
|
|
|
|
'raw' => true,
|
|
|
|
'label-message' => 'prefs-global-profile',
|
|
|
|
'help-message' => 'prefs-help-golbal-profile',
|
|
|
|
'default' => strval(new \OOUI\ButtonWidget([
|
|
|
|
'id' => 'global-profile-link',
|
|
|
|
'href' => $profileUrl,
|
|
|
|
'label' => wfMessage('btn-idp-profile-settings')->text(),
|
|
|
|
])),
|
|
|
|
'section' => 'personal/info',
|
|
|
|
);
|
|
|
|
|
|
|
|
if (isset($wgIsekaiOIDC['avatarUrl'])) {
|
|
|
|
list($subject, $accessToken, $refreshToken) = IsekaiOIDCAuth::findOidcDataByUserId($user->getId());
|
|
|
|
$avatarLink = str_replace(['{openid}', '{username}'], [urlencode($subject), urlencode($user->getName())], $wgIsekaiOIDC['avatarUrl']);
|
|
|
|
$preferences['editavatar'] = array(
|
|
|
|
'type' => 'info',
|
|
|
|
'raw' => true,
|
|
|
|
'label-message' => 'prefs-editavatar',
|
|
|
|
'default' => Html::openElement('a', [
|
|
|
|
'href' => $profileUrl,
|
|
|
|
]) .
|
|
|
|
'<img src="' . $avatarLink . '" alt="avatar" width="64" height="64">' .
|
|
|
|
Html::closeElement('a'),
|
|
|
|
'section' => 'personal/info',
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param \SkinTemplate $skinTemplate
|
|
|
|
* @param $links
|
|
|
|
* @return void
|
|
|
|
*/
|
|
|
|
public static function onSkinTemplateUniversalNavigation(\SkinTemplate $skinTemplate, &$links) {
|
|
|
|
if (isset($links['user-menu']['createaccount'])) {
|
|
|
|
unset($links['user-menu']['createaccount']);
|
|
|
|
}
|
|
|
|
if (isset($links['user-menu']['login'])) {
|
|
|
|
$links['user-menu']['login']['text'] = wfMessage('nav-login-createaccount')->text();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param $vars
|
|
|
|
* @param string $skin
|
|
|
|
* @param \Config $config
|
|
|
|
* @return bool
|
|
|
|
*/
|
|
|
|
public static function onResourceLoaderGetConfigVars(&$vars, $skin, $config) {
|
|
|
|
$services = MediaWikiServices::getInstance();
|
|
|
|
$wgIsekaiOIDC = $services->getMainConfig()->get('IsekaiOIDC');
|
|
|
|
|
|
|
|
if (isset($wgIsekaiOIDC['avatarUrl'])) {
|
|
|
|
$vars['wgAvatarTemplate'] = $wgIsekaiOIDC['avatarUrl'];
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
public static function onGetUserAvatar(&$avatarUrl, $size, $user) {
|
|
|
|
$services = MediaWikiServices::getInstance();
|
|
|
|
$config = $services->getMainConfig();
|
|
|
|
$wgIsekaiOIDC = $config->get('IsekaiOIDC');
|
|
|
|
|
|
|
|
if (isset($wgIsekaiOIDC['avatarUrl'])) {
|
|
|
|
list($subject, $accessToken, $refreshToken) = IsekaiOIDCAuth::findOidcDataByUserId($user->getId());
|
|
|
|
$avatarFinded = false;
|
|
|
|
if ($subject) {
|
|
|
|
$avatarUrl = str_replace(['{openid}', '{username}'], [urlencode($subject), urlencode($user->getName())], $wgIsekaiOIDC['avatarUrl']);
|
|
|
|
$avatarFinded = true;
|
|
|
|
} else {
|
|
|
|
if (isset($wgIsekaiOIDC['defaultAvatarUrl'])) {
|
|
|
|
$avatarUrl = $wgIsekaiOIDC['defaultAvatarUrl'];
|
|
|
|
$avatarFinded = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($avatarFinded) {
|
|
|
|
if ($size <= 64) {
|
|
|
|
$avatarUrl = "$avatarUrl?size=md";
|
|
|
|
} else if ($size <= 128) {
|
|
|
|
$avatarUrl = "$avatarUrl?size=lg";
|
|
|
|
} else if ($size <= 256) {
|
|
|
|
$avatarUrl = "$avatarUrl?size=xl";
|
|
|
|
} else {
|
|
|
|
$avatarUrl = "$avatarUrl?size=xxl";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|