feat(api kaz): Connexion à l'api kaz.

- Suppression des migrations, templates et configurations inutiles (ex. `compose.override.yaml`).
- Mise à jour de l'entité `User` :
  - Renommage des attributs pour correspondre aux conventions (`emailDeSecours` → `alternateEmail`, etc.).
  - Implémentation d'un mapper `updateFromKazUser` pour synchroniser les données depuis l'API Kaz.
- Refactorisation des migrations pour aligner les changements de schéma.
- Mise à jour du formulaire utilisateur et des fixtures en conséquence.
- Ajout du template Twig `profil_infos.html.twig` pour afficher les informations utilisateur. (A supprimer)
This commit is contained in:
MLeveque
2026-03-29 13:45:07 +02:00
parent 23789ab33e
commit e7e6d7c1af
16 changed files with 153 additions and 159 deletions

View File

@@ -27,7 +27,7 @@ class UserController extends AbstractController
* Permet de vérifier si un utilisateur existe dans le ldap.
*
* @param string $email L'adresse e-mail de l'utilisateur.
* @param KazApiService $apiClient Le service utilisé pour récupérer les données utilisateur.
* @param KazApiService $apiKazService Le service utilisé pour récupérer les données utilisateur.
*
* @return Response La page index utilisateur rendue.
* @throws ClientExceptionInterface
@@ -37,29 +37,32 @@ class UserController extends AbstractController
* @throws TransportExceptionInterface
*/
# #[Route('/user/{email}', name: 'app_user', methods: ['GET'])]
# public function index(string $email, KazApiService $apiClient): Response
# {
# $exist = $apiClient->getUserData($email);
#
# return $this->render('user/index.html.twig', [
# 'exist' => $exist,
# ]);
# }
#[Route('/user/{email}', name: 'app_user_by_mail', methods: ['GET'])]
public function index(string $email, KazApiService $apiKazService): Response
{
$user = $apiKazService->getUserData($email);
return $this->render('user/profil_infos.html.twig', [
'user' => $user,
]);
}
/* TODO : Param l'API avec un Serializer pour la lecture du fichier JSON ? */
/* TODO : Param l'API avec un Serializer pour la lecture du fichier JSON ? */
#[Route('/mon-profil', name: 'app_user', methods: ['GET', 'POST'])]
#[IsGranted('ROLE_USER')]
public function showProfile(
Request $request,
EntityManagerInterface $entityManager,
FileUploader $fileUploader
FileUploader $fileUploader,
KazApiService $apiKazService
): Response {
# Récupération de l'utilisateur actuellement connecté
$user = $this->getUser();
/* Utilisation des fixtures pour vérifier la mise en page.
TODO: modifier pour que ça communique avec l'API */
$kazUser = $apiKazService->getUserData($user->getEmail());
$user = $user->updateFromKazUser($kazUser);
//TODO: modifier pour que ça communique avec l'API */
# Création du formulaire lié à l'utilisateur connecté
$form = $this->createForm(UserProfileType::class, $user);
@@ -82,6 +85,22 @@ class UserController extends AbstractController
$user->setPhoto($newFilename);
}
$alternateEmail = $form->get('alternateEmail')->getData();
$regexEmail = '/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/';
if(isset($alternateEmail) && preg_match($regexEmail, $alternateEmail)) {
$user->setAlternateEmail($form->get('alternateEmail')->getData());
} else {
$alternateEmail->addError(new FormError('L\'adresse e-mail n\'est pas valide.'));
}
$telephone = $form->get('telephone')->getData();
$regexTelephone = '/^[0-9\+\s\.\-\(\)]+$/';
if(isset($telephone) && preg_match($regexTelephone, $telephone)) {
$user->setTelephone($telephone);
} else {
$telephone->addError(new FormError('Le numéro de téléphone n\'est pas valide.'));
}
# Sauvegarde en base de données
$entityManager->flush();
@@ -105,9 +124,6 @@ class UserController extends AbstractController
EntityManagerInterface $entityManager
): Response
{
# Récupération de l'utilisateur actuellement connecté
$user = $this->getUser();
# Création du formulaire
$form = $this->createForm(ChangePasswordType::class);

View File

@@ -42,37 +42,55 @@ class AppFixtures extends Fixture
$user->setNextcloudQuota($faker->numberBetween(1, 20) . 'G');
$user->setQuota($faker->numberBetween(1, 10) . 'G');
$user->setEmailQuota('1G');
$user->setEmailDeSecours($faker->unique()->safeEmail());
$user->setAlternateEmail($faker->unique()->safeEmail());
$user->setHasAgoraAccess($faker->boolean(70)); // 70% de chance d'avoir accès
$user->setHasMobilizon($faker->boolean(50));
$user->setHasNextcloudAccess($faker->boolean(90));
$user->setIdentifiantKaz($faker->uuid());
}
// Création d'un compte de test fixe
$admin = new User();
$admin->setEmail('admin@kaz.bzh');
$admin->setRoles(['ROLE_USER', 'ROLE_ADMIN', 'ROLE_ORGANISATION']);
$admin->setPassword($this->hasher->hashPassword($admin, 'password'));
$admin->setFirstName('Admin');
$admin->setLastName('KAZ');
// Remplissage des champs obligatoires restants pour éviter les erreurs SQL
$admin->setEmailDeSecours('secours@kaz.bzh');
$admin->setIdentifiantKaz('ADMIN-KAZ-001');
$admin->setQuota('5G');
$admin->setEmailQuota('1G');
$admin->setNextcloudQuota('10G');
$admin->setHasNextcloudAccess(true);
$admin->setHasMobilizon(true);
$admin->setHasAgoraAccess(true);
$manager->persist($admin);
# Préparation de l'enregistrement de l'objet en base de données
$manager->persist($user);
# Exécution réelle des requêtes SQL (envoi vers la base), une fois la bouche finie
$manager->flush();
}
// Création d'un compte de test fixe
$admin = new User();
$admin->setEmail('admin@kaz.bzh');
$admin->setRoles(['ROLE_USER', 'ROLE_ADMIN', 'ROLE_ORGANISATION']);
$admin->setPassword($this->hasher->hashPassword($admin, 'password'));
$admin->setFirstName('Admin');
$admin->setLastName('KAZ');
// Remplissage des champs obligatoires restants pour éviter les erreurs SQL
$admin->setAlternateEmail('secours@kaz.bzh');
$admin->setIdentifiantKaz('ADMIN-KAZ-001');
$admin->setQuota('5G');
$admin->setEmailQuota('1G');
$admin->setNextcloudQuota('10G');
$admin->setHasNextcloudAccess(true);
$admin->setHasMobilizon(true);
$admin->setHasAgoraAccess(true);
$manager->persist($admin);
// Création d'un compte de test fixe
$melvin = new User();
$melvin->setEmail('melvin.leveque@kazkouil.fr');
$melvin->setRoles(['ROLE_USER', 'ROLE_ADMIN', 'ROLE_ORGANISATION']);
$melvin->setPassword($this->hasher->hashPassword($melvin, 'password'));
$melvin->setFirstName('');
$melvin->setLastName('');
$melvin->setAlternateEmail('');
$melvin->setIdentifiantKaz('MELVIN-KAZ-001');
$melvin->setQuota('5G');
$melvin->setEmailQuota('1G');
$melvin->setNextcloudQuota('10G');
$melvin->setHasNextcloudAccess(true);
$melvin->setHasMobilizon(true);
$melvin->setHasAgoraAccess(true);
$manager->persist($melvin);
# Exécution réelle des requêtes SQL (envoi vers la base), une fois la bouche finie
$manager->flush();
}
}

View File

@@ -12,14 +12,16 @@ use Symfony\Component\Uid\Uuid;
#[ORM\Entity(repositoryClass: UserRepository::class)]
#[ORM\Table(name: '`user`')]
#[ORM\UniqueConstraint(name: 'UNIQ_IDENTIFIER_EMAIL', fields: ['email'])]
#[UniqueEntity(fields: ['email'], message: 'There is already an account with this email')]
class User implements UserInterface, PasswordAuthenticatedUserInterface
{
public const string EMAIL_QUOTA_DEFAULT = '1G';
#[ORM\Id]
#[ORM\GeneratedValue(strategy: 'CUSTOM')]
#[ORM\CustomIdGenerator(class: 'doctrine.uuid_generator')]
#[ORM\Column(type: 'uuid', unique: true)]
#[ORM\Column(type: 'uuid', unique: true, name: 'id')]
private ?Uuid $id;
#[ORM\Column(length: 180, unique: true)]
@@ -28,51 +30,56 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface
/**
* @var list<string> The user roles
*/
#[ORM\Column]
#[ORM\Column(name: 'roles')]
private array $roles = [];
/**
* @var ?string The hashed password
*/
#[ORM\Column]
#[ORM\Column(name: 'password')]
private ?string $password = null;
#[ORM\Column(length: 255)]
private ?string $emailQuota = '1G';
#[ORM\Column(length: 255, name: 'email_quota')]
private ?string $emailQuota = null;
#[ORM\Column(length: 255)]
private ?string $emailDeSecours = null;
#[ORM\Column(length: 255, name: 'alternate_email')]
private ?string $alternateEmail = null;
#[ORM\Column(length: 255)]
#[ORM\Column(length: 255, name: 'identifiant_kaz')]
private ?string $identifiantKaz = null;
#[ORM\Column(length: 255)]
#[ORM\Column(length: 255, name: 'quota')]
private ?string $quota = null;
#[ORM\Column]
#[ORM\Column(name: 'has_nextcloud_access')]
private ?bool $hasNextcloudAccess = null;
#[ORM\Column(length: 255)]
#[ORM\Column(length: 255, name: 'nextcloud_quota')]
private ?string $nextcloudQuota = null;
#[ORM\Column]
#[ORM\Column(name: 'has_mobilizon')]
private ?bool $hasMobilizon = null;
#[ORM\Column]
#[ORM\Column(name: 'has_agora_access')]
private ?bool $hasAgoraAccess = null;
#[ORM\Column(length: 255)]
#[ORM\Column(length: 255, name: 'last_name')]
private ?string $lastName = null;
#[ORM\Column(length: 255)]
#[ORM\Column(length: 255, name: 'first_name')]
private ?string $firstName = null;
#[ORM\Column(length: 255, nullable: true)]
// TODO: Modifier "photo" par "image"
#[ORM\Column(length: 255, nullable: true, name: 'photo')]
private ?string $photo = null;
#[ORM\Column(length: 20, nullable: true)]
#[ORM\Column(length: 20, nullable: true, name: 'telephone')]
private ?string $telephone = null;
public function __construct() {
$this->emailQuota = self::EMAIL_QUOTA_DEFAULT;
}
public function getId(): ?Uuid
{
return $this->id;
@@ -175,14 +182,14 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface
return $this;
}
public function getEmailDeSecours(): ?string
public function getAlternateEmail(): ?string
{
return $this->emailDeSecours;
return $this->alternateEmail;
}
public function setEmailDeSecours(string $emailDeSecours): static
public function setAlternateEmail(string $alternateEmail): static
{
$this->emailDeSecours = $emailDeSecours;
$this->alternateEmail = $alternateEmail;
return $this;
}
@@ -306,4 +313,19 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface
return $this;
}
public function updateFromKazUser($kazUser) : User
{
$this->setEmail($kazUser['mail']);
// Création du firstname et lastname
$name = explode(' ', $kazUser['sn']);
$this->setFirstName($name[0]);
// Récupération des valeurs du tableau moins la première
$aLastname = array_slice($name, 1);
$this->setLastName(implode(' ', $aLastname));
//TODO: Ajouter les champs manquants de l'objet User dans l'api kaz.
return $this;
}
}

View File

@@ -31,7 +31,7 @@ class UserProfileType extends AbstractType
'label' => 'E-mail',
'disabled' => true,
])
->add('emailDeSecours', EmailType::class, ['label' => 'E-mail de secours'])
->add('alternateEmail', EmailType::class, ['label' => 'E-mail de secours'])
->add('telephone', TelType::class, [
'label'=>'Téléphone',
'required' => false,

View File

@@ -34,7 +34,7 @@ class FileUploader
public function delete(?string $fileName): void
{
if ($fileName) {
$filePath = $this->getTargetDirectory() . '/' . $fileName;
$filePath = $this->getTargetDirectory() . 'FileUploader.php/' . $fileName;
if (file_exists($filePath)) {
unlink($filePath);
}

View File

@@ -14,12 +14,18 @@ use Symfony\Contracts\HttpClient\HttpClientInterface;
class KazApiService
{
private ?string $token = null;
private HttpClientInterface $httpClient;
public function __construct(
private readonly HttpClientInterface $kazApiClient,
private readonly string $apiUser,
private readonly string $apiPassword
) {}
) {
$this->httpClient = $kazApiClient->withOptions([
'auth_basic' => [$apiUser, $apiPassword]
]);
}
/**
* Récupère le token JWT via l'authentification Basic
@@ -37,16 +43,14 @@ class KazApiService
return $this->token;
}
$response = $this->kazApiClient->request('POST', '/get_token', [
'auth_basic' => [$this->apiUser, $this->apiPassword]
]);
$response = $this->httpClient->request('GET', '/get_token');
if ($response->getStatusCode() !== 200) {
throw new Exception('Impossible de récupérer le token JWT');
throw new Exception('Impossible de récupérer le token JWT'.$response->getStatusCode());
}
$data = $response->toArray();
$this->token = $data['token']; // Ajustez la clé selon le format de votre API
$this->token = $data['access_token']; // Ajustez la clé selon le format de votre API
return $this->token;
}
@@ -68,7 +72,6 @@ class KazApiService
public function getUserData(string $email): array
{
$options['headers']['Authorization'] = 'Bearer ' . $this->getToken();
$response = $this->kazApiClient->request('GET', "/ldap/user/$email", $options);
if ($response->getStatusCode() !== 200) {
@@ -77,4 +80,4 @@ class KazApiService
return $response->toArray();
}
}
}