diff --git a/extension.json b/extension.json index 698ecbb..f25cfb9 100644 --- a/extension.json +++ b/extension.json @@ -30,7 +30,7 @@ "GetPreferences": "Isekai\\OIDC\\IsekaiOIDCAuthHooks::onGetPreferences", "SkinTemplateNavigation::Universal": "Isekai\\OIDC\\IsekaiOIDCAuthHooks::onSkinTemplateUniversalNavigation", "ResourceLoaderGetConfigVars": "Isekai\\OIDC\\IsekaiOIDCAuthHooks::onResourceLoaderGetConfigVars", - "Isekai::GetUserAvatar": "Isekai\\OIDC\\IsekaiOIDCAuthHooks::onGetUserAvatar" + "Isekai::GetUsersAvatar": "Isekai\\OIDC\\IsekaiOIDCAuthHooks::onGetUsersAvatar" }, "ExtensionMessagesFiles": { "IsekaiOIDCAlias": "IsekaiOIDC.alias.php" diff --git a/includes/ApiOIDCAvatar.php b/includes/ApiOIDCAvatar.php index 06aa3eb..7d84ea4 100644 --- a/includes/ApiOIDCAvatar.php +++ b/includes/ApiOIDCAvatar.php @@ -38,12 +38,15 @@ class ApiOIDCAvatar extends ApiQueryBase { $size = $this->getParameter('size'); - $avatarUrl = ''; + $avatars = []; $hookContainer = $services->getHookContainer(); - $hookContainer->run('Isekai::GetUserAvatar', [&$avatarUrl, $size, $user]); + $hookContainer->run('Isekai::GetUsersAvatar', [&$avatars, [$user], $size]); - if (empty($avatarUrl)) { + $avatarUrl = ''; + if (isset($avatars[$user->getId()])) { + $avatarUrl = $avatars[$user->getId()]; + } else { if (isset($wgIsekaiOIDC['defaultAvatarUrl'])) { $avatarUrl = $wgIsekaiOIDC['defaultAvatarUrl']; } else { diff --git a/includes/IsekaiOIDCAuth.php b/includes/IsekaiOIDCAuth.php index 17a3ad5..4f5ae47 100644 --- a/includes/IsekaiOIDCAuth.php +++ b/includes/IsekaiOIDCAuth.php @@ -454,6 +454,28 @@ class IsekaiOIDCAuth extends AbstractPrimaryAuthenticationProvider { } } + public static function findOidcSubjectsByUserIds( array $userIds ) { + $dbr = MediaWikiServices::getInstance()->getDBLoadBalancer()->getMaintenanceConnectionRef( DB_REPLICA ); + $rows = $dbr->select( + [ + self::OIDC_TABLE + ], + [ + 'oidc_user', + 'oidc_subject' + ], + [ + 'oidc_user' => $userIds + ], + __METHOD__ + ); + $subjects = []; + foreach ( $rows as $row ) { + $subjects[$row->oidc_user] = $row->oidc_subject; + } + return $subjects; + } + private static function getPreferredUsername( $config, $oidc, $realname, $email ) { if ( isset( $config['preferred_username'] ) ) { wfDebugLog( self::LOG_TAG, 'Using ' . $config['preferred_username'] . @@ -555,18 +577,19 @@ class IsekaiOIDCAuth extends AbstractPrimaryAuthenticationProvider { $preferred_username = 'User'; } - if ( MediaWikiServices::getInstance() - ->getUserIdentityLookup() - ->getUserIdentityByName( $preferred_username ) ) { + $userIdentityLookup = MediaWikiServices::getInstance()->getUserIdentityLookup(); + $userIdentity = $userIdentityLookup->getUserIdentityByName( $preferred_username ); + if ( !$userIdentity || !$userIdentity->isRegistered() ) { return $preferred_username; } $count = 1; - while ( MediaWikiServices::getInstance() - ->getUserIdentityLookup() - ->getUserIdentityByName( $preferred_username . $count ) ) { - + while ( true ) { + $userIdentity = $userIdentityLookup->getUserIdentityByName( $preferred_username . $count ); + if ( !$userIdentity || !$userIdentity->isRegistered() ) { + break; + } $count ++; } return $preferred_username . $count; diff --git a/includes/IsekaiOIDCAuthHooks.php b/includes/IsekaiOIDCAuthHooks.php index ad39f61..3871c8c 100644 --- a/includes/IsekaiOIDCAuthHooks.php +++ b/includes/IsekaiOIDCAuthHooks.php @@ -171,33 +171,57 @@ class IsekaiOIDCAuthHooks { return true; } - public static function onGetUserAvatar(&$avatarUrl, $size, $user) { + /** + * Get avatar url for users + * @param array &$avatars + * @param \User[] $users + * @param int $size + */ + public static function onGetUsersAvatar(&$avatars, array $users, $size = 128) { + if (!is_array($avatars)) { + $avatars = []; + } + $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; + $userIds = array_map(function($user) { + return $user->getId(); + }, $users); + + $subjects = IsekaiOIDCAuth::findOidcSubjectsByUserIds($userIds); + + foreach ($users as $user) { + $subject = null; + if (isset($subjects[$user->getId()])) { + $subject = $subjects[$user->getId()]; } - } - 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"; + $avatarFinded = false; + if ($subject) { + $avatarUrl = str_replace(['{openid}', '{username}'], [urlencode($subject), urlencode($user->getName())], $wgIsekaiOIDC['avatarUrl']); + $avatarFinded = true; } else { - $avatarUrl = "$avatarUrl?size=xxl"; + 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"; + } + + $avatars[$user->getId()] = $avatarUrl; } } }