增加获取头像的API

master
落雨楓 2 years ago
parent cb158d7398
commit 9a10a6b5e7

@ -29,7 +29,8 @@
"UserLogoutComplete": "Isekai\\OIDC\\IsekaiOIDCAuthHooks::onLogout",
"GetPreferences": "Isekai\\OIDC\\IsekaiOIDCAuthHooks::onGetPreferences",
"SkinTemplateNavigation::Universal": "Isekai\\OIDC\\IsekaiOIDCAuthHooks::onSkinTemplateUniversalNavigation",
"ResourceLoaderGetConfigVars": "Isekai\\OIDC\\IsekaiOIDCAuthHooks::onResourceLoaderGetConfigVars"
"ResourceLoaderGetConfigVars": "Isekai\\OIDC\\IsekaiOIDCAuthHooks::onResourceLoaderGetConfigVars",
"Isekai::GetUserAvatar": "Isekai\\OIDC\\IsekaiOIDCAuthHooks::onGetUserAvatar"
},
"ExtensionMessagesFiles": {
"IsekaiOIDCAlias": "IsekaiOIDC.alias.php"
@ -50,7 +51,10 @@
}
},
"APIModules": {
"oidcwebhook": "Isekai\\OIDC\\ApiOidcWebhook"
"oidcwebhook": "Isekai\\OIDC\\ApiOIDCWebhook"
},
"APIPropModules": {
"oidcavatar": "Isekai\\OIDC\\ApiOIDCAvatar"
},
"config": {
"IsekaiOIDC": {

@ -10,6 +10,13 @@
"apihelp-oidcwebhook-param-provider": "Provider",
"apihelp-oidcwebhook-param-key": "Secret Key",
"apihelp-query+oidcavatar-summary": "Get user avatar from OpenID Connection Provider",
"apihelp-query+oidcavatar-param-username": "Username in local Wiki",
"apihelp-query+oidcavatar-param-userid": "User ID in local Wiki",
"apihelp-query+oidcavatar-param-size": "Avatar size",
"apihelp-query+oidcavatar-param-redirect": "Redirect to avatar URL",
"isekaioidc-api-example-isekaioidcavatar": "Get avatar of user 'Example' in size 128px",
"isekaioidc-api-provider-not-supported": "Provider Unsupported",
"isekaioidc-api-key-invalid": "API Key invalid",
"isekaioidc-api-post-body-invalid": "POST Body format invalid",

@ -10,6 +10,13 @@
"apihelp-oidcwebhook-param-provider": "Provider",
"apihelp-oidcwebhook-param-key": "Secret Key",
"apihelp-query+oidcavatar-summary": "从 OpenID Connection 用户中心获取用户头像",
"apihelp-query+oidcavatar-param-username": "本地Wiki用户名",
"apihelp-query+oidcavatar-param-userid": "本地Wiki用户ID",
"apihelp-query+oidcavatar-param-size": "头像大小",
"apihelp-query+oidcavatar-param-redirect": "重定向到头像URL",
"isekaioidc-api-example-isekaioidcavatar": "获取用户名为“Example”的用户的128px头像",
"isekaioidc-api-provider-not-supported": "不支持的Provider",
"isekaioidc-api-key-invalid": "API Key错误",
"isekaioidc-api-post-body-invalid": "POST Body格式错误",

@ -0,0 +1,97 @@
<?php
namespace Isekai\OIDC;
use ApiBase;
use ApiQueryBase;
use Exception;
use Exif;
use MediaWiki\MediaWikiServices;
use Wikimedia\ParamValidator\ParamValidator;
use User;
class ApiOIDCAvatar extends ApiQueryBase {
public function __construct( $main, $method ) {
parent::__construct( $main, $method );
}
public function execute() {
$services = MediaWikiServices::getInstance();
$config = $services->getMainConfig();
$wgIsekaiOIDC = $config->get('IsekaiOIDC');
//$this->requireOnlyOneParameter('username', 'userid');
$userid = $this->getParameter('userid');
$username = $this->getParameter('username');
$userFactory = $services->getUserFactory();
if ($userid) {
$user = $userFactory->newFromId($userid);
} else {
$user = $userFactory->newFromName($username);
}
if (!$user) {
$this->dieWithError('isekaioidc-api-user-not-found', 'isekaioidc-api-user-not-found');
}
$size = $this->getParameter('size');
$avatarUrl = '';
$hookContainer = $services->getHookContainer();
$hookContainer->run('Isekai::GetUserAvatar', [&$avatarUrl, $size, $user]);
if (empty($avatarUrl)) {
if (isset($wgIsekaiOIDC['defaultAvatarUrl'])) {
$avatarUrl = $wgIsekaiOIDC['defaultAvatarUrl'];
} else {
$this->dieWithError('isekaioidc-api-user-avatar-not-found', 'isekaioidc-api-user-avatar-not-found', [
'userid' => $userid,
'username' => $username,
]);
}
}
if ($this->getParameter('redirect')) {
header('HTTP/1.1 301 Moved Permanently');
header('Location: ' . $avatarUrl);
header('Cache-Control: public, max-age=86400');
exit();
} else {
$this->getResult()->addValue('query', 'oidcavatar', $avatarUrl);
}
}
public function getAllowedParams() {
return [
'username' => [
ParamValidator::PARAM_DEFAULT => null,
ParamValidator::PARAM_TYPE => 'string',
],
'userid' => [
ParamValidator::PARAM_DEFAULT => null,
ParamValidator::PARAM_TYPE => 'integer',
],
'size' => [
ParamValidator::PARAM_DEFAULT => 128,
ParamValidator::PARAM_TYPE => 'integer',
],
'redirect' => [
ParamValidator::PARAM_DEFAULT => false,
ParamValidator::PARAM_TYPE => 'boolean',
]
];
}
public function getExamplesMessages() {
return [
'action=query&prop=oidcavatar&username=Example&size=128' => 'isekaioidc-api-example-isekaioidcavatar',
];
}
public function getCacheMode($params) {
return 'public';
}
}

@ -6,13 +6,16 @@ use ApiBase;
use MediaWiki\MediaWikiServices;
use Wikimedia\ParamValidator\ParamValidator;
class ApiOidcWebhook extends ApiBase {
class ApiOIDCWebhook extends ApiBase {
public function __construct( $main, $method ) {
parent::__construct( $main->getMain(), $method );
}
public function execute() {
global $wgIsekaiOIDC;
$services = MediaWikiServices::getInstance();
$config = $services->getMainConfig();
$wgIsekaiOIDC = $config->get('IsekaiOIDC');
$queryValues = $this->getRequest()->getQueryValues();
$provider = '';
if (isset($queryValues['provider'])) {
@ -36,6 +39,10 @@ class ApiOidcWebhook extends ApiBase {
}
private function keycloakCallback() {
$services = MediaWikiServices::getInstance();
$config = $services->getMainConfig();
$wgIsekaiOIDC = $config->get('IsekaiOIDC');
if (!$this->getRequest()->wasPosted()) {
$this->addError('isekaioidc-api-post-body-invalid');
return;
@ -47,7 +54,6 @@ class ApiOidcWebhook extends ApiBase {
$this->addError('isekaioidc-api-post-body-invalid');
return;
}
global $wgIsekaiOIDC;
$realm = $wgIsekaiOIDC['realm'];
$apiMode = $wgIsekaiOIDC['apiMode'] ?? 'oauth';
@ -76,7 +82,7 @@ class ApiOidcWebhook extends ApiBase {
'phone' => $userInfo->phone_number,
];
$user = MediaWikiServices::getInstance()->getUserFactory()->newFromId($userId);
$user = $services->getUserFactory()->newFromId($userId);
IsekaiOIDCAuth::updateUserInfo($user, $newProfile);
}
$this->getResult()->addValue(null, 'webhook', 1);

@ -69,10 +69,13 @@ class IsekaiOIDCAuth extends AbstractPrimaryAuthenticationProvider {
* @inheritDoc
*/
public function continuePrimaryAuthentication( array $reqs ) {
global $wgIsekaiOIDC;
$config = $wgIsekaiOIDC;
$services = MediaWikiServices::getInstance();
$config = $services->getMainConfig()->get('IsekaiOIDC');
$oidc = self::getOpenIDConnectClient();
$requestCtx = RequestContext::getMain();
$oidc =self::getOpenIDConnectClient();
if ($oidc->authenticate()) {
$accessToken = $oidc->getAccessToken();
$refreshToken = $oidc->getRefreshToken();
@ -88,7 +91,7 @@ class IsekaiOIDCAuth extends AbstractPrimaryAuthenticationProvider {
}
$authManager = MediaWikiServices::getInstance()->getAuthManager();
$request = RequestContext::getMain()->getRequest();
$request = $requestCtx->getRequest();
$session = $request->getSession();
$session->clear('AuthManager::AutoCreateBlacklist'); // 防止缓存检测
@ -228,14 +231,15 @@ class IsekaiOIDCAuth extends AbstractPrimaryAuthenticationProvider {
}
public static function getOpenIDConnectClient() {
global $wgIsekaiOIDC;
if (!is_array($wgIsekaiOIDC)) {
$services = MediaWikiServices::getInstance();
$config = $services->getMainConfig()->get('IsekaiOIDC');
if (!is_array($config)) {
wfDebugLog( self::LOG_TAG, 'wgIsekaiOIDC not set' .
PHP_EOL );
throw new Exception('wgIsekaiOIDC not set');
}
$config = $wgIsekaiOIDC;
if (!isset($config['endpoint']) || !isset($config['clientID']) || !isset($config['clientSecret'])) {
wfDebugLog( self::LOG_TAG, 'wgIsekaiOIDC not valid' .
PHP_EOL );
@ -251,7 +255,7 @@ class IsekaiOIDCAuth extends AbstractPrimaryAuthenticationProvider {
$oidc->setRedirectURL( $redirectURL );
wfDebugLog( self::LOG_TAG, 'Redirect URL: ' . $redirectURL );
if ( isset( $_REQUEST['forcelogin'] ) ) {
if ( isset( $_REQUEST['force'] ) || isset( $_REQUEST['forcelogin'] ) ) {
$oidc->addAuthParam( [ 'prompt' => 'login' ] );
}
if ( isset( $config['authparam'] ) &&

@ -44,7 +44,8 @@ class IsekaiOIDCAuthHooks {
* @param OutputPage $out
*/
public static function onBeforePageDisplay($out) {
global $wgIsekaiOIDC;
$services = MediaWikiServices::getInstance();
$wgIsekaiOIDC = $services->getMainConfig()->get('IsekaiOIDC');
if (isset($wgIsekaiOIDC['syncLogout']) && $wgIsekaiOIDC['syncLogout']) {
$title = $out->getTitle();
@ -97,7 +98,9 @@ class IsekaiOIDCAuthHooks {
}
public static function onGetPreferences(\User $user, &$preferences) {
global $wgIsekaiOIDC;
$services = MediaWikiServices::getInstance();
$wgIsekaiOIDC = $services->getMainConfig()->get('IsekaiOIDC');
$profileUrl = $wgIsekaiOIDC['endpoint'] . 'account/';
$referrer = $wgIsekaiOIDC['clientID'];
$referrerUri = Title::newFromText('Special:Preferences')->getCanonicalURL();
@ -159,10 +162,45 @@ class IsekaiOIDCAuthHooks {
* @return bool
*/
public static function onResourceLoaderGetConfigVars(&$vars, $skin, $config) {
global $wgIsekaiOIDC;
$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;
}
}

Loading…
Cancel
Save