Installation:
composer require cethyworks/invitation-bundle
Add the bundle to AppKernel.php:
new Cethyworks\InvitationBundle\CethyworksInvitationBundle(),
Configure security.yml:
security:
providers:
in_memory_invitation_provider:
invitation_memory:
invitations:
- { code: "initial-code" }
firewalls:
invitation:
pattern: ^/private-route
provider: in_memory_invitation_provider
guard:
authenticator:
cethyworks_invitation.authenticator
anonymous: false
First Use Case:
Access /private-route?code=initial-code to test the protected route. Replace initial-code with your configured invitation code.
Define Invitation Codes:
security.yml (for testing) or use a database-backed provider (if extended).invitations:
- { code: "dev-team-2024", expires_at: "2024-12-31" }
Route Protection:
invitation firewall to any route prefix (e.g., ^/admin).anonymous: false to block unauthenticated access.Dynamic Invitation Management:
// src/Service/InvitationService.php
class InvitationService {
public function generateCode(): string {
return Str::random(16);
}
}
Post-Authentication Logic:
// src/EventListener/InvitationListener.php
class InvitationListener implements ContainerAwareInterface {
public function onAuthenticationSuccess(AuthenticationSuccessEvent $event) {
$user = $event->getAuthenticationToken()->getUser();
// Log, redirect, or assign roles dynamically.
}
}
Integration with Forms:
// src/Form/InvitationType.php
class InvitationType extends AbstractType {
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder->add('code', TextType::class);
}
}
Deprecated Bundle:
authenticator changes in Symfony 5+).In-Memory Provider Limitations:
# Example: Custom provider (hypothetical)
providers:
db_invitation_provider:
invitation_db:
connection: default
table: invitation_codes
InvitationProviderInterface to query your database.Firewall Configuration:
pattern in firewalls matches your route exactly (e.g., ^/private vs. ^/private/).Authentication Flow:
guard authentication. If you encounter issues, verify:
authenticator service (cethyworks_invitation.authenticator) is properly registered.CSRF and Invitation Codes:
Check Authentication Events:
SECURITY events during failed logins.AuthenticationFailureEvent or AuthenticationSuccessEvent.Log Invitation Codes:
// src/Authenticator/InvitationAuthenticator.php (custom)
public function getCredentials(Request $request) {
$code = $request->query->get('code');
$this->logger->debug('Invitation code attempted:', ['code' => $code]);
return ['code' => $code];
}
Test with curl:
curl "http://your-app.test/private-route?code=test123"
Database Backend:
InvitationProvider implements:
public function loadUserByInvitationCode($code);
public function refreshUser(UserInterface $user);
public function supportsClass($class);
Custom Invitation Provider:
Cethyworks\InvitationBundle\Security\Provider\InvitationProvider to support databases or APIs.class DatabaseInvitationProvider extends InvitationProvider {
public function loadUserByInvitationCode($code) {
return $this->entityManager->getRepository(User::class)
->findOneBy(['invitationCode' => $code]);
}
}
Role-Based Access:
// In your authenticator
$user->setRoles(['ROLE_INVITED_USER']);
return new Token($user, null, ['ROLE_INVITED_USER']);
Rate Limiting:
rate_limiter to prevent brute-force attacks on invitation codes.Email Integration:
// src/Command/SendInvitationCommand.php
class SendInvitationCommand extends Command {
protected function execute(InputInterface $input, OutputInterface $output) {
$code = $this->invitationService->generateCode();
$email = (new Email())
->to('user@example.com')
->subject('Your Invitation Code')
->text($code);
$this->mailer->send($email);
}
}
How can I help you explore Laravel packages today?