diff --git a/composer.json b/composer.json index 3f3a888e8e412070292a6d408ae54a2fd53c9e22..d90a7e4ad9825d3c4ec232260b86f064a7a8fcea 100644 --- a/composer.json +++ b/composer.json @@ -6,6 +6,7 @@ "require": { "php": ">=7.2.5", "ext-ctype": "*", + "ext-curl": "*", "ext-iconv": "*", "ext-json": "*", "ext-openssl": "*", diff --git a/public/assets/css/app.css b/public/assets/css/app.css index 63693e43081a2327a8052889687aaab35612a35a..87d8314cfa738689cf26573563abb927b47493a3 100755 --- a/public/assets/css/app.css +++ b/public/assets/css/app.css @@ -737,4 +737,12 @@ ul.navbar-nav.flex-row > .nav-item { } .dropdown-toggle.caret-off::after { display: none; +} + +.alert-json { + text-align: left; +} +.alert-json > pre { + white-space: pre-wrap; + word-break: break-all; } \ No newline at end of file diff --git a/public/assets/js/app.js b/public/assets/js/app.js index 7f8e93d6d7241c2f18bbab1aad4569d7bb4d547f..06ea52694ddf67ac1d7c297b4ceb14b2f7f4964a 100755 --- a/public/assets/js/app.js +++ b/public/assets/js/app.js @@ -544,8 +544,10 @@ function initializeFlashes() { $flashes = $('#flashes'); if ($flashes.find('.alert').length) { $flashes.show(); - window.setTimeout(function () { - $flashes.fadeOut(1000); - }, 4000); + if (!$flashes.find('.alert-json').length) { + window.setTimeout(function () { + $flashes.fadeOut(1000); + }, 4000); + } } } \ No newline at end of file diff --git a/src/Controller/OauthClientController.php b/src/Controller/OauthClientController.php index 8b391f853b263557fb6affa54c6bff37eacfd945..2a86ea1c33d6dedcb49cd190a49145ced01d1ff8 100644 --- a/src/Controller/OauthClientController.php +++ b/src/Controller/OauthClientController.php @@ -6,6 +6,7 @@ use App\Entity\Entry; use App\Entity\Log; use App\Entity\OAuth2ClientProfile; use App\Form\ClientProfileType; +use App\Form\CreateTokenType; use App\Repository\OAuth2ClientProfileRepository; use League\Bundle\OAuth2ServerBundle\Model\Client; use Doctrine\Persistence\ManagerRegistry; @@ -19,6 +20,7 @@ use Symfony\Component\Form\FormInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Annotation\Route; +use Symfony\Component\Routing\Generator\UrlGeneratorInterface; /** * Paramétrage des applications clientes autorisées @@ -131,4 +133,63 @@ class OauthClientController extends AbstractController return $this->redirectToRoute('app_client_index'); } + /** + * @Route("/{id}/create-token", name="app_client_create_token", methods={"GET", "POST"}) + * + * Un formulaire permet de saisir un nom d'utilisateur et un mot de passe, qui seront utilisés pour obtenir un token d'accès + */ + public function createToken(Request $request, OAuth2ClientProfile $clientProfile): Response + { + $form = $this->createForm(CreateTokenType::class, [], [ + 'action' => $this->generateUrl('app_client_create_token', ['id' => $clientProfile->getId()]), + ]); + + $form->handleRequest($request); + if ($form->isSubmitted() && $form->isValid()) { + $response = $this->getToken($clientProfile, $form->get('pseudo')->getData(), $form->get('password')->getData()); +// dump(json_encode($response, JSON_PRETTY_PRINT));die(); + $this->addFlash('json', json_encode($response, JSON_PRETTY_PRINT)); + + return $this->render('closeModalAndRedirect.html.twig', [ + 'url' => $this->generateUrl('app_client_index'), + ]); + } + + return $this->render('genericModalForm.html.twig', [ + 'title' => "Créer un token", + 'form' => $form->createView(), + ]); + } + + + private function getToken(OAuth2ClientProfile $clientProfile, $pseudo, $password) + { + $client = $clientProfile->getClient(); + $params = [ + 'grant_type' => 'password', + 'client_id' => $client->getIdentifier(), + 'client_secret' => $client->getSecret(), + 'scope' => 'email pseudo uuid', + 'username' => $pseudo, + 'password' => $password, + ]; + + $uri = $this->generateUrl('oauth2_token', [], UrlGeneratorInterface::ABSOLUTE_URL); + + $ch = curl_init($uri); + + + $ch = curl_init($uri); + curl_setopt($ch, CURLOPT_POST, true); + curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($params)); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + $response = curl_exec($ch); + $response = json_decode($response, true); + if(curl_errno($ch)){ + dump('Curl error: ' . curl_error($ch));die(); + } + curl_close($ch); + + return $response; + } } diff --git a/src/Form/CreateTokenType.php b/src/Form/CreateTokenType.php new file mode 100644 index 0000000000000000000000000000000000000000..c6077417abc0e838d083b1dd460eb6983d227164 --- /dev/null +++ b/src/Form/CreateTokenType.php @@ -0,0 +1,53 @@ +<?php + +namespace App\Form; + +use App\Entity\Entry; +use App\Entity\Label; +use App\Entity\User; +use App\Languages\LanguagesIso; +use App\Repository\GroupRepository; +use Symfony\Bridge\Doctrine\Form\Type\EntityType; +use Symfony\Component\Form\AbstractType; +use Symfony\Component\Form\Extension\Core\Type\ChoiceType; +use Symfony\Component\Form\Extension\Core\Type\DateTimeType; +use Symfony\Component\Form\Extension\Core\Type\DateType; +use Symfony\Component\Form\Extension\Core\Type\PasswordType; +use Symfony\Component\Form\Extension\Core\Type\SubmitType; +use Symfony\Component\Form\Extension\Core\Type\TextareaType; +use Symfony\Component\Form\Extension\Core\Type\TextType; +use Symfony\Component\Form\FormBuilderInterface; +use Symfony\Component\OptionsResolver\OptionsResolver; +use Symfony\Component\Security\Core\Security; + +class CreateTokenType extends AbstractType +{ + public function buildForm(FormBuilderInterface $builder, array $options): void + { + $builder + ->add('pseudo', TextType::class, [ + 'label' => 'Pseudo', + ]) + ->add('password', PasswordType::class, [ + 'label' => 'Password', + ]) + ; + + + $builder + ->add('submit', SubmitType::class, [ + 'label' => 'submit', + ]); + } + + public function configureOptions(OptionsResolver $resolver): void + { + $resolver->setDefaults([ + 'attr' => [ + 'data-ajax-form' => '', + 'data-ajax-form-target' => '#bootstrap-modal .modal-content', + 'novalidate' => 'novalidate', + ], + ]); + } +} diff --git a/templates/_flashMessages.html.twig b/templates/_flashMessages.html.twig index 2f672d72303fd92d44e42069d5c98610799173ac..516f9fad59a5035edd2a78c9ae26234366bd51b9 100644 --- a/templates/_flashMessages.html.twig +++ b/templates/_flashMessages.html.twig @@ -1,9 +1,15 @@ {% if app.session.started %} {% for type, flashes in app.session.flashbag.all %} {% for message in flashes %} - <div class="alert alert-{{ type }}" role="alert"> - {{ message|trans|raw }} - </div> + {% if type == 'json' %} + <div class="alert alert-warning alert-{{ type }}" role="alert"> + <pre>{{ message|trans|raw }}</pre> + </div> + {% else %} + <div class="alert alert-{{ type }}" role="alert"> + {{ message|trans|raw }} + </div> + {% endif %} {% endfor %} {% endfor %} diff --git a/templates/oauth_client/index.html.twig b/templates/oauth_client/index.html.twig index d5998786518d04e1faecccba8e63e0aec2733fad..f112b68fcb9b1eb72655be83cd59e581298b2fea 100644 --- a/templates/oauth_client/index.html.twig +++ b/templates/oauth_client/index.html.twig @@ -7,6 +7,7 @@ <div class="row justify-content-center mt-5"> <div class="col-md-12"> + <h3 class="card-title d-flex justify-content-between"> Clients <a href="{{ path('app_client_new') }}" class="btn btn-dark"><i class="bi-plus"></i> Créer</a> @@ -41,10 +42,17 @@ <td>{{ client.grants|join('<br>')|raw }}</td> <td>{{ client.scopes|join('<br>')|raw }}</td> <td>{{ client.active ? 'Yes' : 'No' }}</td> - <td class="text-end"> + + <td class="text-nowrap text-end"> + + {% if 'password' in client.grants|join(',') %} + <a title="Obtenir un token" href="#" data-url="{{ path('app_client_create_token', {'id': clientProfile.id}) }}" class="modal-form btn btn-dark btn-xs">Token</a> + {% endif %} + <a href="{{ path('app_client_edit', {'id': clientProfile.id}) }}" class="btn btn-dark btn-xs">Modifier</a> <div class="d-inline-block">{{ include('oauth_client/_delete_form.html.twig') }}</div> </td> + </tr> {% else %} <tr>