Skip to content

Commit

Permalink
Improve organization invitation with registration/login flow
Browse files Browse the repository at this point in the history
  • Loading branch information
noniagriconomie committed Jan 29, 2021
1 parent 481a7be commit 2e6c771
Show file tree
Hide file tree
Showing 6 changed files with 49 additions and 10 deletions.
1 change: 1 addition & 0 deletions config/packages/security.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ security:

access_control:
- { path: ^/admin, roles: ROLE_ADMIN }
- { path: ^/user/invitation., roles: [ROLE_USER, IS_AUTHENTICATED_ANONYMOUSLY] }
- { path: ^/user, roles: ROLE_USER }
- { path: ^/$, roles: ROLE_USER }
- { path: ^/organization/.+/overview$, roles: ROLE_ORGANIZATION_ANONYMOUS_USER }
Expand Down
12 changes: 11 additions & 1 deletion src/Controller/IndexController.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,17 @@
use Buddy\Repman\Service\Telemetry;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Symfony\Component\Routing\Annotation\Route;

final class IndexController extends AbstractController
{
private SessionInterface $session;
private Telemetry $telemetry;

public function __construct(Telemetry $telemetry)
public function __construct(SessionInterface $session, Telemetry $telemetry)
{
$this->session = $session;
$this->telemetry = $telemetry;
}

Expand All @@ -23,6 +26,13 @@ public function __construct(Telemetry $telemetry)
*/
public function index(): Response
{
if ($this->session->has('organization-token')) {
$organizationToken = $this->session->get('organization-token');
$this->session->remove('organization-token');

return $this->redirectToRoute('organization_accept_invitation', ['token' => $organizationToken]);
}

$showTelemetryPrompt = !$this->telemetry->isInstanceIdPresent();

return $this->render('index.html.twig', [
Expand Down
16 changes: 14 additions & 2 deletions src/Controller/Organization/MembersController.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,19 @@
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;

final class MembersController extends AbstractController
{
private SessionInterface $session;
private OrganizationQuery $organizations;
private TokenStorageInterface $tokenStorage;

public function __construct(OrganizationQuery $organizations, TokenStorageInterface $tokenStorage)
public function __construct(SessionInterface $session, OrganizationQuery $organizations, TokenStorageInterface $tokenStorage)
{
$this->session = $session;
$this->organizations = $organizations;
$this->tokenStorage = $tokenStorage;
}
Expand All @@ -56,8 +59,16 @@ public function listMembers(Organization $organization, Request $request): Respo
*/
public function acceptInvitation(string $token): Response
{
/** @var User $user */
/** @var User|null $user */
$user = $this->getUser();
if (null === $user) {
$this->session->set('organization-token', $token);

$this->addFlash('info', 'You need to sign in or sign up to be able to accept this invitation.');

return $this->redirectToRoute('app_login');
}

$organization = $this->organizations->getByInvitation($token, $user->email());
if ($organization->isEmpty()) {
$this->addFlash('danger', 'Invitation not found or belongs to different user');
Expand All @@ -67,6 +78,7 @@ public function acceptInvitation(string $token): Response
}

$this->dispatchMessage(new AcceptInvitation($token, $user->id()));
$this->session->remove('organization-token');
$this->addFlash('success', sprintf('The invitation to %s organization has been accepted', $organization->get()->name()));

return $this->redirectToRoute('organization_overview', ['organization' => $organization->get()->alias()]);
Expand Down
18 changes: 16 additions & 2 deletions src/Controller/RegistrationController.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,19 @@
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\Routing\Annotation\Route;

class RegistrationController extends AbstractController
{
private SessionInterface $session;
private UserGuardHelper $guard;
private Config $config;

public function __construct(UserGuardHelper $guard, Config $config)
public function __construct(SessionInterface $session, UserGuardHelper $guard, Config $config)
{
$this->session = $session;
$this->guard = $guard;
$this->config = $config;
}
Expand Down Expand Up @@ -53,9 +56,20 @@ public function register(Request $request): Response
));

$this->addFlash('warning', "Please click the activation link for {$email} to verify your email.");
$this->addFlash('success', 'Your account has been created. Please create a new organization.');

$this->guard->authenticateUser($email, $request);

if ($this->session->has('organization-token')) {
$organizationToken = $this->session->get('organization-token');
$this->session->remove('organization-token');

$this->addFlash('success', 'Your account has been created.');

return $this->redirectToRoute('organization_accept_invitation', ['token' => $organizationToken]);
}

$this->addFlash('success', 'Your account has been created. Please create a new organization.');

return $this->redirectToRoute('organization_create');
}

Expand Down
10 changes: 6 additions & 4 deletions src/Controller/SecurityController.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,25 +18,27 @@

class SecurityController extends AbstractController
{
private AuthenticationUtils $authenticationUtils;
private Config $config;

public function __construct(Config $config)
public function __construct(AuthenticationUtils $authenticationUtils, Config $config)
{
$this->authenticationUtils = $authenticationUtils;
$this->config = $config;
}

/**
* @Route("/login", name="app_login")
*/
public function login(AuthenticationUtils $authenticationUtils): Response
public function login(): Response
{
if ($this->getUser() !== null) {
return $this->redirectToRoute('index');
}

return $this->render('security/login.html.twig', [
'last_username' => $authenticationUtils->getLastUsername(),
'error' => $authenticationUtils->getLastAuthenticationError(),
'last_username' => $this->authenticationUtils->getLastUsername(),
'error' => $this->authenticationUtils->getLastAuthenticationError(),
'localLoginEnabled' => $this->config->localLoginEnabled(),
]);
}
Expand Down
2 changes: 1 addition & 1 deletion templates/emails/organization-invitation.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
<div class="f-fallback">
<h1 style="margin-top: 0; color: #333333; font-size: 22px; font-weight: bold; text-align: left;" align="left">Hello,</h1>
<p style="font-size: 16px; line-height: 1.625; color: #51545E; margin: .4em 0 1.1875em;">
<strong>{{organizationName}}</strong> has invited you to use Repman to collaborate with them. Use the button below to accept invitation or set up your account and get started
<strong>{{organizationName}}</strong> has invited you to use Repman to collaborate with them. Use the button below to accept invitation or set up your account and get started.
</p>
<!-- Action -->
<table class="body-action" align="center" width="100%" cellpadding="0" cellspacing="0" role="presentation" style="width: 100%; -premailer-width: 100%; -premailer-cellpadding: 0; -premailer-cellspacing: 0; text-align: center; margin: 30px auto; padding: 0;">
Expand Down

0 comments on commit 2e6c771

Please sign in to comment.