From 5ac764f3e5a68df896e6c4bc3e3408a4b6f4d84f Mon Sep 17 00:00:00 2001 From: Diogo Peralta Cordeiro Date: Sun, 16 Jan 2022 17:56:54 +0000 Subject: [PATCH] move to plugin --- plugins/OAuth2/OAuth2.php | 85 ++++++++++++++++++++++++++++++++++++++- src/Core/GNUsocial.php | 78 +---------------------------------- src/Util/Common.php | 8 ++++ 3 files changed, 94 insertions(+), 77 deletions(-) diff --git a/plugins/OAuth2/OAuth2.php b/plugins/OAuth2/OAuth2.php index d383e88497..46bf0c19b9 100644 --- a/plugins/OAuth2/OAuth2.php +++ b/plugins/OAuth2/OAuth2.php @@ -33,10 +33,23 @@ declare(strict_types = 1); namespace Plugin\OAuth2; use App\Core\Event; +use App\Core\Log; use App\Core\Modules\Plugin; use App\Core\Router\RouteLoader; use App\Core\Router\Router; +use App\Util\Common; +use App\Util\Exception\NoLoggedInUser; +use App\Util\Formatting; +use Nyholm\Psr7\Response; use Plugin\OAuth2\Controller\Apps; +use Symfony\Component\EventDispatcher\EventSubscriberInterface; +use Symfony\Component\HttpFoundation\Exception\BadRequestException; +use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface; +use Symfony\Component\Security\Core\User\UserProviderInterface; +use Trikoder\Bundle\OAuth2Bundle\Event\AuthorizationRequestResolveEvent; +use Trikoder\Bundle\OAuth2Bundle\Event\UserResolveEvent; +use Trikoder\Bundle\OAuth2Bundle\OAuth2Events; +use Trikoder\Bundle\OAuth2Bundle\OAuth2Grants; use XML_XRD_Element_Link; /** @@ -45,7 +58,7 @@ use XML_XRD_Element_Link; * @copyright 2021 Free Software Foundation, Inc http://www.fsf.org * @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later */ -class OAuth2 extends Plugin +class OAuth2 extends Plugin implements EventSubscriberInterface { public const OAUTH_ACCESS_TOKEN_REL = 'http://apinamespace.org/oauth/access_token'; public const OAUTH_REQUEST_TOKEN_REL = 'http://apinamespace.org/oauth/request_token'; @@ -80,4 +93,74 @@ class OAuth2 extends Plugin $links[] = new XML_XRD_Element_link(self::OAUTH_ACCESS_TOKEN_REL, Router::url('oauth2_token', type: Router::ABSOLUTE_URL)); return Event::next; } + + public function userResolve(UserResolveEvent $event, UserProviderInterface $userProvider, UserPasswordEncoderInterface $userPasswordEncoder): void + { + Log::debug('cenas: ', [$event, $userProvider, $userPasswordEncoder]); + $user = $userProvider->loadUserByUsername($event->getUsername()); + + if (\is_null($user)) { + return; + } + + if (!$userPasswordEncoder->isPasswordValid($user, $event->getPassword())) { + return; + } + + $event->setUser($user); + } + + public function authorizeRequestResolve(AuthorizationRequestResolveEvent $event): void + { + $request = Common::getRequest(); + try { + $user = Common::ensureLoggedIn(); + // get requests will be intercepted and shown the login form + // other verbs we will handle as an authorization denied + // and this implementation ensures a user is set at this point already + if ($request->getMethod() !== 'POST') { + $event->resolveAuthorization(AuthorizationRequestResolveEvent::AUTHORIZATION_DENIED); + return; + } else { + if (!$request->request->has('action')) { + // 1. successful login, goes to grant page + $content = Formatting::twigRenderFile('security/grant.html.twig', [ + 'scopes' => $event->getScopes(), + 'client' => $event->getClient(), + 'grant' => OAuth2Grants::AUTHORIZATION_CODE, + // very simple way to ensure user gets to this point in the + // flow when granting or denying is to pre-add their credentials + 'email' => $request->request->get('email'), + 'password' => $request->request->get('password'), + ]); + $response = new Response(200, [], $content); + $event->setResponse($response); + } else { + // 2. grant operation, either grants or denies + if ($request->request->get('action') === OAuth2Grants::AUTHORIZATION_CODE) { + $event->setUser($user); + $event->resolveAuthorization(AuthorizationRequestResolveEvent::AUTHORIZATION_APPROVED); + } else { + $event->resolveAuthorization(AuthorizationRequestResolveEvent::AUTHORIZATION_DENIED); + } + } + } + // Whoops! + throw new BadRequestException(); + } catch (NoLoggedInUser) { + $event->setResponse(new Response(302, [ + 'Location' => Router::url('security_login', [ + 'returnUrl' => $request->getUri(), + ]), + ])); + } + } + + public static function getSubscribedEvents(): array + { + return [ + OAuth2Events::USER_RESOLVE => 'userResolve', + OAuth2Events::AUTHORIZATION_REQUEST_RESOLVE => 'authorizeRequestResolve', + ]; + } } diff --git a/src/Core/GNUsocial.php b/src/Core/GNUsocial.php index d2b09b0929..e4a38fab66 100644 --- a/src/Core/GNUsocial.php +++ b/src/Core/GNUsocial.php @@ -52,12 +52,10 @@ use App\Kernel; use App\Security\EmailVerifier; use App\Util\Common; use App\Util\Exception\ConfigurationException; -use App\Util\Exception\NoLoggedInUser; use App\Util\Formatting; use App\Util\HTML; use Doctrine\ORM\EntityManagerInterface; use HtmlSanitizer\SanitizerInterface; -use Nyholm\Psr7\Response; use Psr\Log\LoggerInterface; use Symfony\Component\Config\Loader\LoaderInterface; use Symfony\Component\Console\Event\ConsoleCommandEvent; @@ -66,7 +64,6 @@ use Symfony\Component\DependencyInjection\ParameterBag\ContainerBagInterface; use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\Form\FormFactoryInterface; -use Symfony\Component\HttpFoundation\Exception\BadRequestException; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\HttpFoundation\Session\SessionInterface; @@ -75,18 +72,12 @@ use Symfony\Component\HttpKernel\KernelEvents; use Symfony\Component\Mailer\MailerInterface; use Symfony\Component\Messenger\MessageBusInterface; use Symfony\Component\Routing\RouterInterface; -use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface; use Symfony\Component\Security\Core\Security as SSecurity; -use Symfony\Component\Security\Core\User\UserProviderInterface; use Symfony\Component\Security\Http\Util\TargetPathTrait; use Symfony\Contracts\HttpClient\HttpClientInterface; use Symfony\Contracts\Translation\TranslatorInterface; use SymfonyCasts\Bundle\ResetPassword\ResetPasswordHelperInterface; use SymfonyCasts\Bundle\VerifyEmail\VerifyEmailHelperInterface; -use Trikoder\Bundle\OAuth2Bundle\Event\AuthorizationRequestResolveEvent; -use Trikoder\Bundle\OAuth2Bundle\Event\UserResolveEvent; -use Trikoder\Bundle\OAuth2Bundle\OAuth2Events; -use Trikoder\Bundle\OAuth2Bundle\OAuth2Grants; use Twig\Environment; /** @@ -275,69 +266,6 @@ class GNUsocial implements EventSubscriberInterface $container->setParameter('gnusocial_defaults', $defaults); } - public function userResolve(UserResolveEvent $event, UserProviderInterface $userProvider, UserPasswordEncoderInterface $userPasswordEncoder): void - { - Log::debug('cenas: ', [$event, $userProvider, $userPasswordEncoder]); - $user = $userProvider->loadUserByUsername($event->getUsername()); - - if (\is_null($user)) { - return; - } - - if (!$userPasswordEncoder->isPasswordValid($user, $event->getPassword())) { - return; - } - - $event->setUser($user); - } - - public function authorizeRequestResolve(AuthorizationRequestResolveEvent $event): void - { - $request = $this->request; - - try { - $user = Common::ensureLoggedIn(); - // get requests will be intercepted and shown the login form - // other verbs we will handle as an authorization denied - // and this implementation ensures a user is set at this point already - if ($request->getMethod() !== 'POST') { - $event->resolveAuthorization(AuthorizationRequestResolveEvent::AUTHORIZATION_DENIED); - return; - } else { - if (!$request->request->has('action')) { - // 1. successful login, goes to grant page - $content = $this->twig->render('security/grant.html.twig', [ - 'scopes' => $event->getScopes(), - 'client' => $event->getClient(), - 'grant' => OAuth2Grants::AUTHORIZATION_CODE, - // very simple way to ensure user gets to this point in the - // flow when granting or denying is to pre-add their credentials - 'email' => $request->request->get('email'), - 'password' => $request->request->get('password'), - ]); - $response = new Response(200, [], $content); - $event->setResponse($response); - } else { - // 2. grant operation, either grants or denies - if ($request->request->get('action') === OAuth2Grants::AUTHORIZATION_CODE) { - $event->setUser($user); - $event->resolveAuthorization(AuthorizationRequestResolveEvent::AUTHORIZATION_APPROVED); - } else { - $event->resolveAuthorization(AuthorizationRequestResolveEvent::AUTHORIZATION_DENIED); - } - } - } - // Whoops! - throw new BadRequestException(); - } catch (NoLoggedInUser) { - $event->setResponse(new Response(302, [ - 'Location' => Router::url('security_login', [ - 'returnUrl' => $request->getUri(), - ]), - ])); - } - } - /** * Tell Symfony which events we want to listen to, which Symfony detects and auto-wires * due to this implementing the `EventSubscriberInterface` @@ -345,10 +273,8 @@ class GNUsocial implements EventSubscriberInterface public static function getSubscribedEvents(): array { return [ - KernelEvents::REQUEST => 'onKernelRequest', - 'console.command' => 'onCommand', - OAuth2Events::USER_RESOLVE => 'userResolve', - OAuth2Events::AUTHORIZATION_REQUEST_RESOLVE => 'authorizeRequestResolve', + KernelEvents::REQUEST => 'onKernelRequest', + 'console.command' => 'onCommand', ]; } } diff --git a/src/Util/Common.php b/src/Util/Common.php index 9a0c005bd1..afb9b0211f 100644 --- a/src/Util/Common.php +++ b/src/Util/Common.php @@ -67,6 +67,14 @@ abstract class Common self::$request = $req; } + /** + * Don't use this + */ + public static function getRequest(): ?Request + { + return self::$request; + } + public static function route() { return self::$request->attributes->get('_route');