2020-07-22 02:58:25 +01:00
< ? php
namespace App\Controller ;
2020-07-23 15:08:31 +01:00
use App\Core\Controller ;
2020-07-25 03:06:55 +01:00
use App\Core\DB\DB ;
use App\Core\Form ;
use function App\Core\I18n\_m ;
2021-04-15 23:26:05 +01:00
use App\Core\VisibilityScope ;
2020-10-11 21:27:50 +01:00
use App\Entity\Follow ;
2020-08-13 02:23:22 +01:00
use App\Entity\GSActor ;
2020-07-25 03:06:55 +01:00
use App\Entity\LocalUser ;
2020-12-02 22:57:32 +00:00
use App\Entity\Note ;
2020-07-25 03:06:55 +01:00
use App\Security\Authenticator ;
use App\Security\EmailVerifier ;
use app\Util\Common ;
2021-04-11 12:03:32 +01:00
use App\Util\Exception\NicknameTakenException ;
2020-07-25 03:06:55 +01:00
use App\Util\Nickname ;
2021-04-11 12:03:32 +01:00
use Doctrine\DBAL\Exception\UniqueConstraintViolationException ;
2020-07-25 03:06:55 +01:00
use Symfony\Component\Form\Extension\Core\Type\EmailType ;
use Symfony\Component\Form\Extension\Core\Type\PasswordType ;
use Symfony\Component\Form\Extension\Core\Type\SubmitType ;
use Symfony\Component\Form\Extension\Core\Type\TextType ;
use Symfony\Component\HttpFoundation\Request ;
use Symfony\Component\Security\Guard\GuardAuthenticatorHandler ;
2020-07-22 02:58:25 +01:00
use Symfony\Component\Security\Http\Authentication\AuthenticationUtils ;
2020-07-25 03:06:55 +01:00
use Symfony\Component\Validator\Constraints\Length ;
use Symfony\Component\Validator\Constraints\NotBlank ;
2020-07-22 02:58:25 +01:00
2020-07-23 15:08:31 +01:00
class Security extends Controller
2020-07-22 02:58:25 +01:00
{
2020-11-06 19:47:15 +00:00
/**
* Log a user in
*/
2020-07-23 18:55:06 +01:00
public function login ( AuthenticationUtils $authenticationUtils )
2020-07-22 02:58:25 +01:00
{
if ( $this -> getUser ()) {
return $this -> redirectToRoute ( 'main_all' );
}
// get the login error if there is one
$error = $authenticationUtils -> getLastAuthenticationError ();
// last username entered by the user
2020-07-23 15:08:31 +01:00
$last_username = $authenticationUtils -> getLastUsername ();
2020-07-22 02:58:25 +01:00
2021-04-15 23:26:05 +01:00
return [ '_template' => 'security/login.html.twig' , 'last_username' => $last_username , 'error' => $error , 'notes' => Note :: getAllNotes ( VisibilityScope :: $instance_scope )];
2020-07-22 02:58:25 +01:00
}
public function logout ()
{
throw new \LogicException ( 'This method can be blank - it will be intercepted by the logout key on your firewall.' );
}
2020-07-25 03:06:55 +01:00
2020-11-06 19:47:15 +00:00
/**
* Register a user , making sure the nickname is not reserved and
* possibly sending a confirmation email
*/
2020-07-25 03:06:55 +01:00
public function register ( Request $request ,
EmailVerifier $email_verifier ,
GuardAuthenticatorHandler $guard_handler ,
Authenticator $authenticator )
{
$form = Form :: create ([
[ 'nickname' , TextType :: class , [
'label' => _m ( 'Nickname' ),
2021-07-28 22:06:10 +01:00
'constraints' => [
new NotBlank ([ 'message' => _m ( 'Please enter a nickname' )]),
new Length ([
2021-04-10 23:32:47 +01:00
'min' => Common :: config ( 'nickname' , 'min_length' ),
'minMessage' => _m ([ 'Your nickname must be at least # characters long' ], [ 'count' => Common :: config ( 'nickname' , 'min_length' )]),
'max' => Nickname :: MAX_LEN ,
'maxMessage' => _m ([ 'Your nickname must be at most # characters long' ], [ 'count' => Nickname :: MAX_LEN ]), ]),
2020-07-25 03:06:55 +01:00
],
]],
2021-07-28 22:06:10 +01:00
[ 'email' , EmailType :: class , [
'label' => _m ( 'Email' ),
'constraints' => [ new NotBlank ([ 'message' => _m ( 'Please enter an email' ) ])]
]],
2020-07-25 03:06:55 +01:00
[ 'password' , PasswordType :: class , [
'label' => _m ( 'Password' ),
'mapped' => false ,
'constraints' => [
new NotBlank ([ 'message' => _m ( 'Please enter a password' )]),
2021-07-28 22:06:10 +01:00
new Length ([ 'min' => Common :: config ( 'password' , 'min_length' ), 'minMessage' => _m ([ 'Your password should be at least # characters' ], [ 'count' => Common :: config ( 'password' , 'min_length' )]),
'max' => Common :: config ( 'password' , 'max_length' ), 'maxMessage' => _m ([ 'Your password should be at most # characters' ], [ 'count' => Common :: config ( 'password' , 'max_length' )]), ]),
2020-07-25 03:06:55 +01:00
],
]],
[ 'register' , SubmitType :: class , [ 'label' => _m ( 'Register' )]],
]);
$form -> handleRequest ( $request );
if ( $form -> isSubmitted () && $form -> isValid ()) {
$data = $form -> getData ();
$data [ 'password' ] = $form -> get ( 'password' ) -> getData ();
2021-04-10 23:32:47 +01:00
$valid_nickname = Nickname :: normalize ( $data [ 'nickname' ], check_already_used : true );
2020-07-25 03:06:55 +01:00
2021-04-11 12:03:32 +01:00
try {
2021-05-05 13:19:10 +01:00
$actor = GSActor :: create ([ 'nickname' => $data [ 'nickname' ], 'normalized_nickname' => Nickname :: normalize ( $data [ 'nickname' ], check_already_used : true )]);
2021-04-23 13:54:25 +01:00
$user = LocalUser :: create ([
2021-04-11 12:03:32 +01:00
'nickname' => $data [ 'nickname' ],
'outgoing_email' => $data [ 'email' ],
'incoming_email' => $data [ 'email' ],
'password' => LocalUser :: hashPassword ( $data [ 'password' ]),
]);
2021-04-23 13:54:25 +01:00
DB :: persistWithSameId (
$actor ,
$user ,
// Self follow
fn ( int $id ) => DB :: persist ( Follow :: create ([ 'follower' => $id , 'followed' => $id ]))
);
DB :: flush ();
2021-04-11 12:03:32 +01:00
} catch ( UniqueConstraintViolationException $e ) {
throw new NicknameTakenException ;
}
2020-07-25 03:06:55 +01:00
// generate a signed url and email it to the user
if ( Common :: config ( 'site' , 'use_email' )) {
$email_verifier -> sendEmailConfirmation (
'verify_email' ,
$user ,
( new TemplatedEmail ())
-> from ( new Address ( Common :: config ( 'site' , 'email' ), Common :: config ( 'site' , 'nickname' )))
-> to ( $user -> getOutgoingEmail ())
-> subject ( _m ( 'Please Confirm your Email' ))
-> htmlTemplate ( 'security/confirmation_email.html.twig' )
);
} else {
$user -> setIsEmailVerified ( true );
}
return $guard_handler -> authenticateUserAndHandleSuccess (
$user ,
$request ,
$authenticator ,
'main' // firewall name in security.yaml
);
}
return [
'_template' => 'security/register.html.twig' ,
'registration_form' => $form -> createView (),
2021-04-15 23:26:05 +01:00
'notes' => Note :: getAllNotes ( VisibilityScope :: $instance_scope ),
2020-07-25 03:06:55 +01:00
];
}
2020-07-22 02:58:25 +01:00
}