diff --git a/config/packages/backoffice_menu.yaml b/config/packages/backoffice_menu.yaml index 615a277a9..7cf799e5d 100644 --- a/config/packages/backoffice_menu.yaml +++ b/config/packages/backoffice_menu.yaml @@ -8,12 +8,12 @@ parameters: - admin_home membres: nom: 'Membres' - niveau: 'ROLE_ADMIN' + niveau: 'ROLE_MEMBRES_READER' icon: 'user' elements: personnes_physiques: nom: 'Personnes physiques' - niveau: 'ROLE_ADMIN' + niveau: 'ROLE_MEMBRES_READER' url: '/admin/members/users' extra_routes: - admin_slack_members_check @@ -22,7 +22,7 @@ parameters: - admin_members_user_edit personnes_morales: nom: 'Personnes morales' - niveau: 'ROLE_ADMIN' + niveau: 'ROLE_MEMBRES_READER' url: '/admin/members/companies' extra_routes: - admin_members_company_list @@ -30,31 +30,31 @@ parameters: - admin_members_company_edit relances_personnes_physiques: nom: 'Relances cotisations' - niveau: 'ROLE_ADMIN' + niveau: 'ROLE_MEMBRES_READER' url: '/admin/association/relances/1' extra_routes: - admin_relances reporting: nom: 'Reporting' - niveau: 'ROLE_ADMIN' + niveau: 'ROLE_MEMBRES_READER' url: '/admin/members/reporting' extra_routes: - admin_members_reporting badges: nom: 'Badges' - niveau: 'ROLE_ADMIN' + niveau: 'ROLE_MEMBRES_READER' url: '/admin/members/badges' extra_routes: - admin_members_badges_index - admin_members_badges_new veille: nom: "Veille" - niveau: "ROLE_VEILLE" + niveau: 'ROLE_VEILLE_READER' icon: 'bullhorn' elements: veille_ generer_campagne: nom: "Campagnes" - niveau: "ROLE_VEILLE" + niveau: 'ROLE_VEILLE_WRITER' url: '/admin/techletter' extra_routes: - admin_techletter_index @@ -62,24 +62,24 @@ parameters: - admin_techletter_show techletter: nom: 'Abonnés' - niveau: 'ROLE_ADMIN' + niveau: 'ROLE_SUPER_ADMIN' url: '/admin/techletter/members' extra_routes: - admin_techletter_members history: nom: 'Historique' - niveau: 'ROLE_VEILLE' + niveau: 'ROLE_VEILLE_READER' url: '/admin/techletter/history' extra_routes: - admin_techletter_history site: nom: 'Site' - niveau: 'ROLE_SITE' + niveau: 'ROLE_SITE_READER' icon: "paint brush" elements: site_feuilles: nom: 'Feuilles' - niveau: 'ROLE_SITE' + niveau: 'ROLE_SITE_READER' url : '/admin/site/feuilles' extra_routes: - admin_site_feuilles_list @@ -87,7 +87,7 @@ parameters: - admin_site_feuilles_edit site_rubriques: nom: 'Rubriques' - niveau: 'ROLE_SITE' + niveau: 'ROLE_SITE_READER' url : '/admin/site/rubriques' extra_routes: - admin_site_rubriques_list @@ -95,7 +95,7 @@ parameters: - admin_site_rubriques_edit site_articles: nom: 'Articles' - niveau: 'ROLE_SITE' + niveau: 'ROLE_SITE_READER' url : '/admin/site/articles' extra_routes: - admin_site_articles_list @@ -103,7 +103,7 @@ parameters: - admin_site_articles_edit super_apero_infos: nom: 'Super Apéro' - niveau: 'ROLE_ADMIN' + niveau: 'ROLE_APERO_READER' url: '/admin/super-apero' extra_routes: - admin_super_apero_list @@ -111,12 +111,12 @@ parameters: - admin_super_apero_edit forum: nom: 'Évènements' - niveau: 'ROLE_FORUM' + niveau: 'ROLE_EVENT_READER' icon: "globe" elements: forum_gestion: nom: 'Liste' - niveau: 'ROLE_ADMIN' + niveau: 'ROLE_EVENT_READER' url: '/admin/event/list' extra_routes: - admin_event_list @@ -124,19 +124,19 @@ parameters: - admin_event_edit forum_salle: nom: 'Salles' - niveau: 'ROLE_ADMIN' + niveau: 'ROLE_EVENT_WRITER' url: '/admin/event/room' extra_routes: - admin_event_room forum_suivi: nom: 'Suivi' - niveau: 'ROLE_FORUM' + niveau: 'ROLE_EVENT_READER' url: '/admin/event/stats' extra_routes: - admin_event_stats forum_inscriptions: nom: 'Inscriptions' - niveau: 'ROLE_FORUM' + niveau: 'ROLE_EVENT_READER' url: '/admin/event/tickets' extra_routes: - admin_event_ticket_list @@ -144,25 +144,25 @@ parameters: - admin_event_ticket_edit forum_pending_bankwires: nom: 'Virements en attente' - niveau: 'ROLE_ADMIN' + niveau: 'ROLE_EVENT_WRITER' url: '/admin/event/bankwires' extra_routes: - admin_event_pending_bankwires admin_event_sponsor_ticket: nom: 'Tokens sponsors' - niveau: 'ROLE_ADMIN' + niveau: 'ROLE_EVENT_WRITER' url: '/admin/event/sponsor' extra_routes: - admin_event_sponsor_ticket admin_event_special_price: nom: 'Tokens visiteurs' - niveau: 'ROLE_ADMIN' + niveau: 'ROLE_EVENT_WRITER' url: '/admin/event/special_price' extra_routes: - admin_event_special_price admin_event_billeterie_privee: nom: 'Billeteries privées' - niveau: 'ROLE_ADMIN' + niveau: 'ROLE_EVENT_READER' url: '/admin/event/billeterie-privee' extra_routes: - admin_event_billeterie_privee @@ -171,7 +171,7 @@ parameters: - admin_event_billeterie_privee_delete admin_event_prices: nom: 'Tarifications' - niveau: 'ROLE_FORUM' + niveau: 'ROLE_EVENT_READER' url: '/admin/event/prices' extra_routes: - admin_event_prices @@ -179,13 +179,13 @@ parameters: - admin_event_prices_edit admin_event_factures: nom: "Factures d'évènement" - niveau: 'ROLE_ADMIN' + niveau: 'ROLE_EVENT_READER' url: '/admin/event/invoices' extra_routes: - admin_event_factures talks: nom: 'Conférences' - niveau: 'ROLE_FORUM' + niveau: 'ROLE_EVENT_READER' url: '/admin/talk/' extra_routes: - admin_talk_list @@ -193,7 +193,7 @@ parameters: - admin_talk_edit admin_event_themes_list: nom: 'Thèmes' - niveau: 'ROLE_FORUM' + niveau: 'ROLE_EVENT_WRITER' url: '/admin/event/themes' extra_routes: - admin_event_themes_list @@ -201,19 +201,19 @@ parameters: - admin_event_themes_edit admin_event_editorialization: nom: 'Éditorialisation' - niveau: 'ROLE_FORUM' + niveau: 'ROLE_EVENT_WRITER' url: '/admin/event/editorialization' extra_routes: - admin_event_editorialization forum_vote_github: nom: 'Votes visiteurs' - niveau: 'ROLE_FORUM' + niveau: 'ROLE_EVENT_READER' url: '/admin/event/votes/' extra_routes: - admin_event_votes forum_conferenciers: nom: 'Speakers' - niveau: 'ROLE_FORUM' + niveau: 'ROLE_EVENT_READER' url: '/admin/speaker/' extra_routes: - admin_speaker_list @@ -221,13 +221,13 @@ parameters: - admin_speaker_edit admin_event_speakers_management: nom: 'Infos speakers' - niveau: 'ROLE_FORUM' + niveau: 'ROLE_EVENT_READER' url: '/admin/event/speakers-management' extra_routes: - admin_event_speakers_management admin_event_interview_list: nom: 'Interviews' - niveau: 'ROLE_FORUM' + niveau: 'ROLE_EVENT_READER' url: '/admin/event/interviews' extra_routes: - admin_event_interview_list @@ -236,32 +236,33 @@ parameters: - admin_event_interview_config admin_event_speakers_expenses: nom: 'Justificatifs speakers' - niveau: 'ROLE_FORUM' + niveau: 'ROLE_EVENT_READER' url: '/admin/event/speakers-expenses' extra_routes: - admin_event_speakers_expenses forum_planning: nom: 'Planning' - niveau: 'ROLE_FORUM' + niveau: 'ROLE_EVENT_READER' url: '/admin/event/sessions' extra_routes: - admin_event_sessions - admin_event_sessions_edit admin_github_user_list: nom: 'Github Users' + niveau: 'ROLE_EVENT_READER' url: '/admin/event/github-user' extra_routes: - admin_github_user_add - admin_github_user_list tresorerie: nom: 'Trésorerie' - niveau: 'ROLE_ADMIN' + niveau: 'ROLE_COMPTA_READER' icon: "money bill alternate" elements: compta_devis: nom: 'Devis' url: '/admin/accounting/quotations/list' - niveau: 'ROLE_ADMIN' + niveau: 'ROLE_COMPTA_READER' extra_routes: - admin_accounting_quotations_list - admin_accounting_quotations_add @@ -269,14 +270,14 @@ parameters: compta_facture: nom: 'Factures' url: '/admin/accounting/invoices/list' - niveau: 'ROLE_ADMIN' + niveau: 'ROLE_COMPTA_READER' extra_routes: - admin_accounting_invoices_list - admin_accounting_invoices_edit compta_journal: nom: 'Journal' url: '/admin/accounting/journal/list' - niveau: 'ROLE_ADMIN' + niveau: 'ROLE_COMPTA_READER' extra_routes: - admin_accounting_journal_list - admin_accounting_journal_add @@ -284,7 +285,7 @@ parameters: - admin_accounting_journal_import compta_conf_evenement: nom: 'Configuration' - niveau: 'ROLE_ADMIN' + niveau: 'ROLE_COMPTA_READER' url: '/admin/accounting/configuration/events/list' extra_routes: - admin_accounting_events_list @@ -295,7 +296,7 @@ parameters: - admin_accounting_rules_list compta_produits: nom: 'Produits' - niveau: 'ROLE_ADMIN' + niveau: 'ROLE_COMPTA_READER' url: '/admin/accounting/produits' extra_routes: - admin_accounting_produits_list @@ -303,18 +304,18 @@ parameters: - admin_accounting_produits_edit compta_recherche: nom: 'Recherche comptable' - niveau: 'ROLE_ADMIN' + niveau: 'ROLE_COMPTA_READER' url: '/admin/accounting/search' extra_routes: - admin_accounting_search assemblee_generale: nom: 'Assemblée générale' - niveau: 'ROLE_ADMIN' + niveau: 'ROLE_AG_READER' icon: 'comments' elements: assemblee_generale_infos: nom: 'Informations' - niveau: 'ROLE_ADMIN' + niveau: 'ROLE_AG_READER' url: '/admin/members/general_meeting' extra_routes: - admin_members_general_meeting @@ -323,7 +324,7 @@ parameters: - admin_members_general_meeting_reports assemblee_generale_votes: nom: 'Votes' - niveau: 'ROLE_ADMIN' + niveau: 'ROLE_AG_WRITER' url: '/admin/members/general_meeting_vote' extra_routes: - admin_members_general_vote_list @@ -331,12 +332,12 @@ parameters: - admin_members_general_question_edit planete: nom: 'Planète PHP FR' - niveau: 'ROLE_ADMIN' + niveau: 'ROLE_PLANETE_READER' icon: "rss" elements: planete_flux: nom: 'Flux' - niveau: 'ROLE_ADMIN' + niveau: 'ROLE_PLANETE_READER' url: '/admin/planete/feeds' extra_routes: - admin_planete_feed_list @@ -345,41 +346,41 @@ parameters: planete_billet: nom: 'Billets' - niveau: 'ROLE_ADMIN' + niveau: 'ROLE_PLANETE_READER' url: '/admin/planete/feed-articles' extra_routes: - admin_planete_feed_article_list antenne: nom: 'Antennes' - niveau: 'ROLE_ADMIN' + niveau: 'ROLE_ANTENNES_READER' icon: 'map marker alternate piece' elements: antennes_index: nom: 'Liste' - niveau: 'ROLE_ADMIN' + niveau: 'ROLE_ANTENNES_READER' url: '/admin/antennes' extra_routes: - admin_antennes_list divers: nom: 'Divers' - niveau: 'ROLE_ADMIN' + niveau: 'ROLE_SUPER_ADMIN' icon: "tag" elements: membre_administrateur: nom: 'Administrateurs du site' - niveau: 'ROLE_ADMIN' + niveau: 'ROLE_SUPER_ADMIN' url: '/admin/administrators' extra_routes: - admin_administrators logs: nom: 'Logs' - niveau: 'ROLE_ADMIN' + niveau: 'ROLE_SUPER_ADMIN' url: '/admin/logs' extra_routes: - admin_logs healthcheck: nom: 'Healthcheck' - niveau: 'ROLE_ADMIN' + niveau: 'ROLE_SUPER_ADMIN' url: '/admin/healthcheck' extra_routes: - admin_healthcheck diff --git a/config/packages/security.yaml b/config/packages/security.yaml index 23c44f36d..8cc762dce 100644 --- a/config/packages/security.yaml +++ b/config/packages/security.yaml @@ -52,23 +52,15 @@ security: - { path: ^/event/vote/, roles: ROLE_GITHUB } - { path: ^(/event/.*/(vote|cfp|speaker-infos)|/connect/github/check|/event/speaker-infos), roles: ROLE_GITHUB } - { path: ^/(login|register|password-reset), roles: PUBLIC_ACCESS } - - { path: ^/admin/techletter/members, roles: ROLE_ADMIN } - - { path: ^/admin/techletter, roles: ROLE_VEILLE } - - { path: ^/admin/company, roles: ROLE_COMPANY_MANAGER } - - { path: ^/admin/members/badges, roles: ROLE_ADMIN } - - { path: ^/admin/members/users, roles: ROLE_ADMIN } - - { path: ^/admin/members/companies, roles: ROLE_ADMIN } - - { path: ^/admin/event/speakers-management, roles: ROLE_FORUM } - - { path: ^/admin/event/interviews, roles: ROLE_FORUM } - - { path: ^/admin/event, roles: ROLE_ADMIN } - - { path: ^/admin/members/general_meeting, roles: ROLE_ADMIN } - - { path: ^/admin/members/general_meeting_vote, roles: ROLE_ADMIN } - - { path: ^/admin/site, roles: ROLE_ADMIN } - - { path: ^/admin/planete, roles: ROLE_ADMIN } - - { path: ^/admin/accounting, roles: ROLE_ADMIN } - - { path: ^/admin/(members/reporting|association/relances|talk|slackmembers/check|healthcheck), roles: ROLE_ADMIN} - - { path: ^/member, roles: [ROLE_USER, ROLE_MEMBER_EXPIRED]} - - { path: ^/admin/, roles: ROLE_MEMBER_EXPIRED } + - { path: ^/member, roles: [ROLE_USER, ROLE_MEMBER_EXPIRED] } + # ─── Redirections legacy du domaine authentification (login/logout/password) : publiques ─── + - { path: ^/admin/(login|logout|password), roles: PUBLIC_ACCESS } + # ─── Console : toute personne ayant un rôle fonctionnel (READ ⩾) passe + # (dashboard /admin/ compris) ; anonymes → redirection login, + # membres simples → 403. ─── + - { path: ^/admin, roles: ROLE_ADMIN } + # ─── 4 pages SUPER_ADMIN (administrators, logs, healthcheck, techletter/members) : + # fermées par attributs #[IsGranted] en code, pas par YAML ─── - { path: ^/blog, allow_if: "request.getClientIp() in ['217.70.189.71', '127.0.0.1', '192.168.42.1'] or request.server.get('ALLOW_BLOG_FROM_ALL') == 1 or request.headers.get('x-afup-blog-api-key') == '%env(BLOG_API_KEY)%'" } - { path: ^/blog, roles: ROLE_NO_ACCESS } - { path: ^/(event/\w+/tickets|association)paybox-callback, roles: PUBLIC_ACCESS, ips: "%paybox_ips%" } @@ -78,5 +70,26 @@ security: role_hierarchy: ROLE_USER: [ROLE_MEMBER_EXPIRED] ROLE_COMPANY_MANAGER: [ROLE_USER] - ROLE_ADMIN: [ROLE_USER, ROLE_DEPLOY, ROLE_APERO, ROLE_ANNUAIRE, ROLE_FORUM, ROLE_SITE, ROLE_VEILLE] - ROLE_SUPER_ADMIN: [ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH] + # ─── Marqueur console vide : ne donne accès à rien ─── + ROLE_ADMIN: [] + # ─── READ ⇒ console + WRITE ⇒ READ ─── + ROLE_MEMBRES_READER: [ROLE_ADMIN] + ROLE_MEMBRES_WRITER: [ROLE_MEMBRES_READER] + ROLE_VEILLE_READER: [ROLE_ADMIN] + ROLE_VEILLE_WRITER: [ROLE_VEILLE_READER] + ROLE_SITE_READER: [ROLE_ADMIN] + ROLE_SITE_WRITER: [ROLE_SITE_READER] + ROLE_APERO_READER: [ROLE_ADMIN] + ROLE_APERO_WRITER: [ROLE_APERO_READER] + ROLE_EVENT_READER: [ROLE_ADMIN] + ROLE_EVENT_WRITER: [ROLE_EVENT_READER] + ROLE_COMPTA_READER: [ROLE_ADMIN] + ROLE_COMPTA_WRITER: [ROLE_COMPTA_READER] + ROLE_AG_READER: [ROLE_ADMIN] + ROLE_AG_WRITER: [ROLE_AG_READER] + ROLE_PLANETE_READER: [ROLE_ADMIN] + ROLE_PLANETE_WRITER: [ROLE_PLANETE_READER] + ROLE_ANTENNES_READER: [ROLE_ADMIN] + ROLE_ANTENNES_WRITER: [ROLE_ANTENNES_READER] + # ─── Super admin : tout READ via les WRITER + impersonation ─── + ROLE_SUPER_ADMIN: [ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH, ROLE_MEMBRES_WRITER, ROLE_VEILLE_WRITER, ROLE_SITE_WRITER, ROLE_APERO_WRITER, ROLE_EVENT_WRITER, ROLE_COMPTA_WRITER, ROLE_AG_WRITER, ROLE_PLANETE_WRITER, ROLE_ANTENNES_WRITER] diff --git a/config/routing/admin.yml b/config/routing/admin.yml index 7e5ed08d7..04c7f1ae4 100644 --- a/config/routing/admin.yml +++ b/config/routing/admin.yml @@ -36,7 +36,7 @@ admin_super_apero: admin_members_reporting: path: /members/reporting - defaults: {_controller: AppBundle\Controller\MembershipAdmin\ReportingAction} + defaults: {_controller: AppBundle\Controller\Admin\Members\ReportingAction} admin_members_general_meeting: path: /members/general_meeting diff --git a/db/migrations/20261021090000_roles_remplacent_niveau_modules.php b/db/migrations/20261021090000_roles_remplacent_niveau_modules.php new file mode 100644 index 000000000..9dc8321ff --- /dev/null +++ b/db/migrations/20261021090000_roles_remplacent_niveau_modules.php @@ -0,0 +1,43 @@ +table('afup_personnes_physiques') + ->changeColumn('roles', 'text', ['null' => false]) + ->save(); + + $this->table('afup_personnes_physiques') + ->removeColumn('niveau') + ->removeColumn('niveau_modules') + ->save(); + } + + public function down(): void + { + // Les anciens droits ne sont pas récupérables : le retour arrière ne remet que le schéma + if (!$this->table('afup_personnes_physiques')->hasColumn('niveau')) { + $this->table('afup_personnes_physiques') + ->addColumn('niveau', 'integer', ['limit' => 255, 'signed' => false, 'default' => 0, 'after' => 'mot_de_passe']) + ->addColumn('niveau_modules', 'char', ['limit' => 10, 'default' => '', 'after' => 'niveau']) + ->save(); + } + } +} diff --git a/db/seeds/Users.php b/db/seeds/Users.php index 91369930a..e4d57b391 100644 --- a/db/seeds/Users.php +++ b/db/seeds/Users.php @@ -15,6 +15,7 @@ class Users extends AbstractSeed public const ID_USER_PERSONNE_PHYSIQUE = 5; public const ID_USER_PERSONNE_PHYSIQUE_FIXED_COTISATIONS = 6; public const ID_USER_PERSONNE_LIE_PERSONNE_MORALE_FIXED_COTISATIONS = 7; + public const ID_USER_GESTIONNAIRE_MEMBRES = 8; public const ID_PERSONNE_MORALE_MY_CORP = 1; public const ID_PERSONNE_MORALE_HELIOS_AEROSPACE = 2; @@ -70,11 +71,10 @@ public function run(): void 'login' => 'admin', 'mot_de_passe' => md5('admin'), 'nom' => 'Admin', - 'niveau' => 2, // AFUP_DROITS_NIVEAU_ADMINISTRATEUR, 'prenom' => 'Admin', 'email' => 'admin@admin.fr', - 'niveau_modules' => '00000', - 'roles' => '', + // La hiérarchie (config/packages/security.yaml) donne tous les *_WRITER au super admin + 'roles' => json_encode(['ROLE_SUPER_ADMIN']), 'adresse' => '', ], // utilisateur ayant expiré, avec une date de cotisation fixe, utile pour les tests @@ -83,10 +83,8 @@ public function run(): void 'login' => 'userexpire', 'mot_de_passe' => md5('userexpire'), 'nom' => 'Maurice', - 'niveau' => 0, // AFUP_DROITS_NIVEAU_MEMBRE, 'prenom' => 'Jean', 'email' => 'userexpire@yahoo.fr', - 'niveau_modules' => '00000', 'roles' => '', 'adresse' => '', ], @@ -96,10 +94,8 @@ public function run(): void 'login' => 'cpike', 'mot_de_passe' => md5('cpike'), 'nom' => 'Pike', - 'niveau' => 0, // AFUP_DROITS_NIVEAU_MEMBRE, 'prenom' => 'Christopher', 'email' => 'cpike@strafleet.fr', - 'niveau_modules' => '00000', 'adresse' => '15, main road', 'code_postal' => '93501-1100', 'ville' => 'Mojave, CA', @@ -110,12 +106,10 @@ public function run(): void 'login' => 'dayesa', 'mot_de_passe' => md5('dayesa'), 'nom' => 'Ayesa', - 'niveau' => 0, // AFUP_DROITS_NIVEAU_MEMBRE, 'prenom' => 'Dev', 'email' => 'dev.ayesa@helios-aerospace.com', 'roles' => '["ROLE_COMPANY_MANAGER"]', 'id_personne_morale' => self::ID_PERSONNE_MORALE_HELIOS_AEROSPACE, - 'niveau_modules' => '00000', 'adresse' => '', ], [ @@ -123,12 +117,10 @@ public function run(): void 'login' => 'edmonddupont', 'mot_de_passe' => md5('edmonddupont'), 'nom' => 'Dupont', - 'niveau' => 0, // AFUP_DROITS_NIVEAU_MEMBRE, 'prenom' => 'Edmond', 'email' => 'edmond.dupont@mycorp.fr', 'roles' => '["ROLE_COMPANY_MANAGER"]', 'id_personne_morale' => self::ID_PERSONNE_MORALE_MY_CORP, - 'niveau_modules' => '00000', 'adresse' => '', ], [ @@ -136,12 +128,10 @@ public function run(): void 'login' => 'raoul', 'mot_de_passe' => md5('raoul'), 'nom' => 'Raoul', - 'niveau' => 0, // AFUP_DROITS_NIVEAU_MEMBRE, 'prenom' => 'Jan', 'email' => 'jean.raoul@mycorp.fr', 'roles' => '[]', 'id_personne_morale' => self::ID_PERSONNE_MORALE_MY_CORP, - 'niveau_modules' => '00000', 'etat' => 1, 'adresse' => '', ], @@ -151,11 +141,21 @@ public function run(): void 'mot_de_passe' => md5('paul'), 'nom' => 'Paul', 'prenom' => 'Personne', - 'niveau' => 0, // AFUP_DROITS_NIVEAU_MEMBRE, 'email' => 'paul.personne@mycorp.fr', 'roles' => '[]', 'etat' => User::STATUS_ACTIVE, - 'niveau_modules' => '00000', + 'adresse' => '', + ], + // gestionnaire du module Membres, sans être super admin + [ + 'id' => self::ID_USER_GESTIONNAIRE_MEMBRES, + 'login' => 'gestionmembres', + 'mot_de_passe' => md5('gestionmembres'), + 'nom' => 'Zorglub', + 'prenom' => 'Gestion', + 'email' => 'gestion.membres@afup.test', + 'roles' => json_encode(['ROLE_MEMBRES_WRITER']), + 'etat' => User::STATUS_ACTIVE, 'adresse' => '', ], ]; diff --git a/phpstan-baseline.php b/phpstan-baseline.php index 25e0bb74a..9bd71bd97 100644 --- a/phpstan-baseline.php +++ b/phpstan-baseline.php @@ -577,6 +577,18 @@ 'count' => 1, 'path' => __DIR__ . '/sources/AppBundle/AssembleeGenerale/Entity/Repository/PresenceRepository.php', ]; +$ignoreErrors[] = [ + 'message' => '#^Cannot cast mixed to int\\.$#', + 'identifier' => 'cast.int', + 'count' => 1, + 'path' => __DIR__ . '/sources/AppBundle/Association/CompanyMembership/AbstractCompanyReminder.php', +]; +$ignoreErrors[] = [ + 'message' => '#^Cannot cast mixed to string\\.$#', + 'identifier' => 'cast.string', + 'count' => 1, + 'path' => __DIR__ . '/sources/AppBundle/Association/CompanyMembership/AbstractCompanyReminder.php', +]; $ignoreErrors[] = [ 'message' => '#^Parameter \\#1 \\$email of class AppBundle\\\\Email\\\\Mailer\\\\MailUser constructor expects string, mixed given\\.$#', 'identifier' => 'argument.type', @@ -697,138 +709,6 @@ 'count' => 2, 'path' => __DIR__ . '/sources/AppBundle/Association/Form/UserBadgeType.php', ]; -$ignoreErrors[] = [ - 'message' => '#^Cannot cast mixed to string\\.$#', - 'identifier' => 'cast.string', - 'count' => 1, - 'path' => __DIR__ . '/sources/AppBundle/Association/Form/UserEditFormData.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Property AppBundle\\\\Association\\\\Form\\\\UserEditFormData\\:\\:\\$address has no type specified\\.$#', - 'identifier' => 'missingType.property', - 'count' => 1, - 'path' => __DIR__ . '/sources/AppBundle/Association/Form/UserEditFormData.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Property AppBundle\\\\Association\\\\Form\\\\UserEditFormData\\:\\:\\$alternateEmail has no type specified\\.$#', - 'identifier' => 'missingType.property', - 'count' => 1, - 'path' => __DIR__ . '/sources/AppBundle/Association/Form/UserEditFormData.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Property AppBundle\\\\Association\\\\Form\\\\UserEditFormData\\:\\:\\$cellphone has no type specified\\.$#', - 'identifier' => 'missingType.property', - 'count' => 1, - 'path' => __DIR__ . '/sources/AppBundle/Association/Form/UserEditFormData.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Property AppBundle\\\\Association\\\\Form\\\\UserEditFormData\\:\\:\\$city has no type specified\\.$#', - 'identifier' => 'missingType.property', - 'count' => 1, - 'path' => __DIR__ . '/sources/AppBundle/Association/Form/UserEditFormData.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Property AppBundle\\\\Association\\\\Form\\\\UserEditFormData\\:\\:\\$companyId has no type specified\\.$#', - 'identifier' => 'missingType.property', - 'count' => 1, - 'path' => __DIR__ . '/sources/AppBundle/Association/Form/UserEditFormData.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Property AppBundle\\\\Association\\\\Form\\\\UserEditFormData\\:\\:\\$directoryLevel has no type specified\\.$#', - 'identifier' => 'missingType.property', - 'count' => 1, - 'path' => __DIR__ . '/sources/AppBundle/Association/Form/UserEditFormData.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Property AppBundle\\\\Association\\\\Form\\\\UserEditFormData\\:\\:\\$email has no type specified\\.$#', - 'identifier' => 'missingType.property', - 'count' => 1, - 'path' => __DIR__ . '/sources/AppBundle/Association/Form/UserEditFormData.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Property AppBundle\\\\Association\\\\Form\\\\UserEditFormData\\:\\:\\$eventLevel has no type specified\\.$#', - 'identifier' => 'missingType.property', - 'count' => 1, - 'path' => __DIR__ . '/sources/AppBundle/Association/Form/UserEditFormData.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Property AppBundle\\\\Association\\\\Form\\\\UserEditFormData\\:\\:\\$firstname has no type specified\\.$#', - 'identifier' => 'missingType.property', - 'count' => 1, - 'path' => __DIR__ . '/sources/AppBundle/Association/Form/UserEditFormData.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Property AppBundle\\\\Association\\\\Form\\\\UserEditFormData\\:\\:\\$lastname has no type specified\\.$#', - 'identifier' => 'missingType.property', - 'count' => 1, - 'path' => __DIR__ . '/sources/AppBundle/Association/Form/UserEditFormData.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Property AppBundle\\\\Association\\\\Form\\\\UserEditFormData\\:\\:\\$level has no type specified\\.$#', - 'identifier' => 'missingType.property', - 'count' => 1, - 'path' => __DIR__ . '/sources/AppBundle/Association/Form/UserEditFormData.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Property AppBundle\\\\Association\\\\Form\\\\UserEditFormData\\:\\:\\$officeLevel has no type specified\\.$#', - 'identifier' => 'missingType.property', - 'count' => 1, - 'path' => __DIR__ . '/sources/AppBundle/Association/Form/UserEditFormData.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Property AppBundle\\\\Association\\\\Form\\\\UserEditFormData\\:\\:\\$password has no type specified\\.$#', - 'identifier' => 'missingType.property', - 'count' => 1, - 'path' => __DIR__ . '/sources/AppBundle/Association/Form/UserEditFormData.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Property AppBundle\\\\Association\\\\Form\\\\UserEditFormData\\:\\:\\$phone has no type specified\\.$#', - 'identifier' => 'missingType.property', - 'count' => 1, - 'path' => __DIR__ . '/sources/AppBundle/Association/Form/UserEditFormData.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Property AppBundle\\\\Association\\\\Form\\\\UserEditFormData\\:\\:\\$roles has no type specified\\.$#', - 'identifier' => 'missingType.property', - 'count' => 1, - 'path' => __DIR__ . '/sources/AppBundle/Association/Form/UserEditFormData.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Property AppBundle\\\\Association\\\\Form\\\\UserEditFormData\\:\\:\\$status has no type specified\\.$#', - 'identifier' => 'missingType.property', - 'count' => 1, - 'path' => __DIR__ . '/sources/AppBundle/Association/Form/UserEditFormData.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Property AppBundle\\\\Association\\\\Form\\\\UserEditFormData\\:\\:\\$username has no type specified\\.$#', - 'identifier' => 'missingType.property', - 'count' => 1, - 'path' => __DIR__ . '/sources/AppBundle/Association/Form/UserEditFormData.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Property AppBundle\\\\Association\\\\Form\\\\UserEditFormData\\:\\:\\$websiteLevel has no type specified\\.$#', - 'identifier' => 'missingType.property', - 'count' => 1, - 'path' => __DIR__ . '/sources/AppBundle/Association/Form/UserEditFormData.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Property AppBundle\\\\Association\\\\Form\\\\UserEditFormData\\:\\:\\$zipcode has no type specified\\.$#', - 'identifier' => 'missingType.property', - 'count' => 1, - 'path' => __DIR__ . '/sources/AppBundle/Association/Form/UserEditFormData.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Anonymous function should return array but returns mixed\\.$#', - 'identifier' => 'return.type', - 'count' => 1, - 'path' => __DIR__ . '/sources/AppBundle/Association/Form/UserEditType.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Anonymous function should return non\\-empty\\-string but returns non\\-empty\\-string\\|false\\.$#', - 'identifier' => 'return.type', - 'count' => 1, - 'path' => __DIR__ . '/sources/AppBundle/Association/Form/UserEditType.php', -]; $ignoreErrors[] = [ 'message' => '#^Cannot cast mixed to int\\.$#', 'identifier' => 'cast.int', @@ -838,7 +718,7 @@ $ignoreErrors[] = [ 'message' => '#^Cannot cast mixed to string\\.$#', 'identifier' => 'cast.string', - 'count' => 2, + 'count' => 1, 'path' => __DIR__ . '/sources/AppBundle/Association/Form/UserEditType.php', ]; $ignoreErrors[] = [ @@ -869,8 +749,8 @@ 'message' => '#^Parameter \\#2 \\$array of function implode expects array\\, list given\\.$#', 'identifier' => 'argument.type', 'count' => 1, - 'path' => __DIR__ . '/sources/AppBundle/Association/Model/CompanyMember.php', - ]; + 'path' => __DIR__ . '/sources/AppBundle/Association/Model/CompanyMember.php', +]; $ignoreErrors[] = [ 'message' => '#^Cannot access offset \'id\' on mixed\\.$#', 'identifier' => 'offsetAccess.nonOffsetAccessible', @@ -1114,7 +994,7 @@ $ignoreErrors[] = [ 'message' => '#^Cannot call method bindValue\\(\\) on mixed\\.$#', 'identifier' => 'method.nonObject', - 'count' => 5, + 'count' => 4, 'path' => __DIR__ . '/sources/AppBundle/Association/Model/Repository/UserRepository.php', ]; $ignoreErrors[] = [ @@ -1345,18 +1225,6 @@ 'count' => 1, 'path' => __DIR__ . '/sources/AppBundle/Association/Model/User.php', ]; -$ignoreErrors[] = [ - 'message' => '#^Method AppBundle\\\\Association\\\\Model\\\\User\\:\\:getDirectoryLevel\\(\\) has no return type specified\\.$#', - 'identifier' => 'missingType.return', - 'count' => 1, - 'path' => __DIR__ . '/sources/AppBundle/Association/Model/User.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method AppBundle\\\\Association\\\\Model\\\\User\\:\\:getEventLevel\\(\\) has no return type specified\\.$#', - 'identifier' => 'missingType.return', - 'count' => 1, - 'path' => __DIR__ . '/sources/AppBundle/Association/Model/User.php', -]; $ignoreErrors[] = [ 'message' => '#^Method AppBundle\\\\Association\\\\Model\\\\User\\:\\:getNearestOfficeLabel\\(\\) has no return type specified\\.$#', 'identifier' => 'missingType.return', @@ -1369,30 +1237,12 @@ 'count' => 1, 'path' => __DIR__ . '/sources/AppBundle/Association/Model/User.php', ]; -$ignoreErrors[] = [ - 'message' => '#^Method AppBundle\\\\Association\\\\Model\\\\User\\:\\:getOfficeLevel\\(\\) has no return type specified\\.$#', - 'identifier' => 'missingType.return', - 'count' => 1, - 'path' => __DIR__ . '/sources/AppBundle/Association/Model/User.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method AppBundle\\\\Association\\\\Model\\\\User\\:\\:getRoles\\(\\) should return array\\ but returns array\\.$#', - 'identifier' => 'return.type', - 'count' => 1, - 'path' => __DIR__ . '/sources/AppBundle/Association/Model/User.php', -]; $ignoreErrors[] = [ 'message' => '#^Method AppBundle\\\\Association\\\\Model\\\\User\\:\\:getUserIdentifier\\(\\) should return non\\-empty\\-string but returns string\\.$#', 'identifier' => 'return.type', 'count' => 1, 'path' => __DIR__ . '/sources/AppBundle/Association/Model/User.php', ]; -$ignoreErrors[] = [ - 'message' => '#^Method AppBundle\\\\Association\\\\Model\\\\User\\:\\:getWebsiteLevel\\(\\) has no return type specified\\.$#', - 'identifier' => 'missingType.return', - 'count' => 1, - 'path' => __DIR__ . '/sources/AppBundle/Association/Model/User.php', -]; $ignoreErrors[] = [ 'message' => '#^Method AppBundle\\\\Association\\\\Model\\\\User\\:\\:hasRole\\(\\) has parameter \\$role with no type specified\\.$#', 'identifier' => 'missingType.parameter', @@ -1405,54 +1255,12 @@ 'count' => 1, 'path' => __DIR__ . '/sources/AppBundle/Association/Model/User.php', ]; -$ignoreErrors[] = [ - 'message' => '#^Method AppBundle\\\\Association\\\\Model\\\\User\\:\\:setDirectoryLevel\\(\\) has parameter \\$level with no type specified\\.$#', - 'identifier' => 'missingType.parameter', - 'count' => 1, - 'path' => __DIR__ . '/sources/AppBundle/Association/Model/User.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method AppBundle\\\\Association\\\\Model\\\\User\\:\\:setEventLevel\\(\\) has parameter \\$level with no type specified\\.$#', - 'identifier' => 'missingType.parameter', - 'count' => 1, - 'path' => __DIR__ . '/sources/AppBundle/Association/Model/User.php', -]; $ignoreErrors[] = [ 'message' => '#^Method AppBundle\\\\Association\\\\Model\\\\User\\:\\:setNeedsUpToDateMembership\\(\\) has parameter \\$needsUpToDateMembership with no type specified\\.$#', 'identifier' => 'missingType.parameter', 'count' => 1, 'path' => __DIR__ . '/sources/AppBundle/Association/Model/User.php', ]; -$ignoreErrors[] = [ - 'message' => '#^Method AppBundle\\\\Association\\\\Model\\\\User\\:\\:setOfficeLevel\\(\\) has parameter \\$level with no type specified\\.$#', - 'identifier' => 'missingType.parameter', - 'count' => 1, - 'path' => __DIR__ . '/sources/AppBundle/Association/Model/User.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method AppBundle\\\\Association\\\\Model\\\\User\\:\\:setRoles\\(\\) has parameter \\$roles with no value type specified in iterable type array\\.$#', - 'identifier' => 'missingType.iterableValue', - 'count' => 1, - 'path' => __DIR__ . '/sources/AppBundle/Association/Model/User.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method AppBundle\\\\Association\\\\Model\\\\User\\:\\:setWebsiteLevel\\(\\) has parameter \\$level with no type specified\\.$#', - 'identifier' => 'missingType.parameter', - 'count' => 1, - 'path' => __DIR__ . '/sources/AppBundle/Association/Model/User.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Parameter \\#1 \\$array of function array_diff expects an array of values castable to string, array given\\.$#', - 'identifier' => 'argument.type', - 'count' => 1, - 'path' => __DIR__ . '/sources/AppBundle/Association/Model/User.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Parameter \\#1 \\$array of function array_unique expects an array of values castable to string, array given\\.$#', - 'identifier' => 'argument.type', - 'count' => 2, - 'path' => __DIR__ . '/sources/AppBundle/Association/Model/User.php', -]; $ignoreErrors[] = [ 'message' => '#^Property AppBundle\\\\Association\\\\Model\\\\User\\:\\:\\$alternateEmail \\(string\\|null\\) does not accept mixed\\.$#', 'identifier' => 'assign.propertyType', @@ -1471,12 +1279,6 @@ 'count' => 1, 'path' => __DIR__ . '/sources/AppBundle/Association/Model/User.php', ]; -$ignoreErrors[] = [ - 'message' => '#^Property AppBundle\\\\Association\\\\Model\\\\User\\:\\:\\$roles type has no value type specified in iterable type array\\.$#', - 'identifier' => 'missingType.iterableValue', - 'count' => 1, - 'path' => __DIR__ . '/sources/AppBundle/Association/Model/User.php', -]; $ignoreErrors[] = [ 'message' => '#^Method AppBundle\\\\Association\\\\NotifiableInterface\\:\\:getEmail\\(\\) has no return type specified\\.$#', 'identifier' => 'missingType.return', @@ -1489,6 +1291,18 @@ 'count' => 1, 'path' => __DIR__ . '/sources/AppBundle/Association/NotifiableInterface.php', ]; +$ignoreErrors[] = [ + 'message' => '#^Cannot cast mixed to int\\.$#', + 'identifier' => 'cast.int', + 'count' => 1, + 'path' => __DIR__ . '/sources/AppBundle/Association/UserMembership/AbstractUserReminder.php', +]; +$ignoreErrors[] = [ + 'message' => '#^Cannot cast mixed to string\\.$#', + 'identifier' => 'cast.string', + 'count' => 1, + 'path' => __DIR__ . '/sources/AppBundle/Association/UserMembership/AbstractUserReminder.php', +]; $ignoreErrors[] = [ 'message' => '#^Parameter \\#1 \\$email of class AppBundle\\\\Email\\\\Mailer\\\\MailUser constructor expects string, mixed given\\.$#', 'identifier' => 'argument.type', @@ -2467,18 +2281,18 @@ 'count' => 1, 'path' => __DIR__ . '/sources/AppBundle/Controller/Admin/Event/RemoveEventAction.php', ]; -$ignoreErrors[] = [ - 'message' => '#^Method AppBundle\\\\Controller\\\\Admin\\\\Event\\\\RoomAction\\:\\:getFormsForRooms\\(\\) return type with generic interface Symfony\\\\Component\\\\Form\\\\FormInterface does not specify its types\\: TData$#', - 'identifier' => 'missingType.generics', - 'count' => 1, - 'path' => __DIR__ . '/sources/AppBundle/Controller/Admin/Event/RoomAction.php', -]; $ignoreErrors[] = [ 'message' => '#^Cannot access property \\$name on mixed\\.$#', 'identifier' => 'property.nonObject', 'count' => 2, 'path' => __DIR__ . '/sources/AppBundle/Controller/Admin/Event/RoomAction.php', ]; +$ignoreErrors[] = [ + 'message' => '#^Method AppBundle\\\\Controller\\\\Admin\\\\Event\\\\RoomAction\\:\\:getFormsForRooms\\(\\) return type with generic interface Symfony\\\\Component\\\\Form\\\\FormInterface does not specify its types\\: TData$#', + 'identifier' => 'missingType.generics', + 'count' => 1, + 'path' => __DIR__ . '/sources/AppBundle/Controller/Admin/Event/RoomAction.php', +]; $ignoreErrors[] = [ 'message' => '#^Parameter \\#1 \\$entity of method AppBundle\\\\Doctrine\\\\EntityRepository\\\\:\\:delete\\(\\) expects AppBundle\\\\Event\\\\Entity\\\\Room, mixed given\\.$#', 'identifier' => 'argument.type', @@ -8467,30 +8281,6 @@ 'count' => 1, 'path' => __DIR__ . '/sources/AppBundle/VideoNotifier/StatusGenerator.php', ]; -$ignoreErrors[] = [ - 'message' => '#^Cannot cast mixed to string\\.$#', - 'identifier' => 'cast.string', - 'count' => 1, - 'path' => __DIR__ . '/sources/AppBundle/Association/CompanyMembership/AbstractCompanyReminder.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Cannot cast mixed to int\\.$#', - 'identifier' => 'cast.int', - 'count' => 1, - 'path' => __DIR__ . '/sources/AppBundle/Association/CompanyMembership/AbstractCompanyReminder.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Cannot cast mixed to string\\.$#', - 'identifier' => 'cast.string', - 'count' => 1, - 'path' => __DIR__ . '/sources/AppBundle/Association/UserMembership/AbstractUserReminder.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Cannot cast mixed to int\\.$#', - 'identifier' => 'cast.int', - 'count' => 1, - 'path' => __DIR__ . '/sources/AppBundle/Association/UserMembership/AbstractUserReminder.php', -]; $ignoreErrors[] = [ 'message' => '#^Parameter \\#1 \\$event of method AppBundle\\\\Event\\\\Entity\\\\Repository\\\\TicketEventTypeRepository\\:\\:getTicketsByEvent\\(\\) expects AppBundle\\\\Event\\\\Model\\\\Event, AppBundle\\\\Event\\\\Model\\\\Event\\|null given\\.$#', 'identifier' => 'argument.type', @@ -8505,4 +8295,3 @@ ]; return ['parameters' => ['ignoreErrors' => $ignoreErrors]]; - diff --git a/phpstan.neon b/phpstan.neon index 518a44700..3ea082328 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -22,5 +22,6 @@ parameters: rules: - AppBundle\StaticAnalysis\Rule\NoDebugFunctionsRule - AppBundle\StaticAnalysis\Rule\NoGetUserMethodRule + - AppBundle\StaticAnalysis\Rule\AdminControllerIsGrantedRule - AppBundle\StaticAnalysis\Rule\DoctrineRepositoryRule - AppBundle\StaticAnalysis\Rule\DoctrineDisableDQLRule diff --git a/sources/AppBundle/Association/Factory/UserFactory.php b/sources/AppBundle/Association/Factory/UserFactory.php index c5c1a5c1c..c2a039129 100644 --- a/sources/AppBundle/Association/Factory/UserFactory.php +++ b/sources/AppBundle/Association/Factory/UserFactory.php @@ -15,9 +15,7 @@ public function createForRegister(): User return $user ->setCountry('FR') - ->setLevel(User::LEVEL_MEMBER) ->setStatus(User::STATUS_ACTIVE) - ->setDirectoryLevel(User::LEVEL_MEMBER) ; } } diff --git a/sources/AppBundle/Association/Form/UserEditFormData.php b/sources/AppBundle/Association/Form/UserEditFormData.php deleted file mode 100644 index c6c495718..000000000 --- a/sources/AppBundle/Association/Form/UserEditFormData.php +++ /dev/null @@ -1,77 +0,0 @@ -roles, true))) { - $context->buildViolation('Les roles ne sont pas valides') - ->atPath('roles') - ->addViolation(); - } - } -} diff --git a/sources/AppBundle/Association/Form/UserEditType.php b/sources/AppBundle/Association/Form/UserEditType.php index 0b149f667..a02d46928 100644 --- a/sources/AppBundle/Association/Form/UserEditType.php +++ b/sources/AppBundle/Association/Form/UserEditType.php @@ -14,12 +14,15 @@ use Symfony\Component\Form\Extension\Core\Type\ChoiceType; use Symfony\Component\Form\Extension\Core\Type\EmailType; use Symfony\Component\Form\Extension\Core\Type\EnumType; +use Symfony\Component\Form\Extension\Core\Type\FormType; use Symfony\Component\Form\Extension\Core\Type\PasswordType; use Symfony\Component\Form\Extension\Core\Type\RepeatedType; 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\Form\FormEvent; +use Symfony\Component\Form\FormEvents; use Symfony\Component\OptionsResolver\OptionsResolver; use Symfony\Component\Validator\Constraints\Email; use Symfony\Component\Validator\Constraints\Length; @@ -27,6 +30,18 @@ class UserEditType extends AbstractType { + private const array MODULE_LEVEL_CHOICES = [ + 'Aucun' => User::LEVEL_NONE, + 'Lecteur' => User::LEVEL_READER, + 'Gestionnaire' => User::LEVEL_MANAGER, + ]; + + /** Rôles hors matrice des modules, attribuables par case à cocher. */ + private const array SPECIAL_ROLES = [ + 'Super administrateur' => 'ROLE_SUPER_ADMIN', + 'Gestionnaire de la personne morale' => 'ROLE_COMPANY_MANAGER', + ]; + public function __construct( private readonly CompanyMemberRepository $companyMemberRepository, private readonly Pays $pays, @@ -144,42 +159,6 @@ public function buildForm(FormBuilderInterface $builder, array $options): void 'maxlength' => 20, ], ]) - ->add('level', ChoiceType::class, [ - 'label' => 'Niveau', - 'choices' => [ - 'Membre' => User::LEVEL_MEMBER, - 'Rédacteur' => User::LEVEL_WRITER, - 'Administrateur' => User::LEVEL_ADMIN, - ], - ]) - ->add('directoryLevel', ChoiceType::class, [ - 'label' => 'Annuaire des prestataires', - 'choices' => [ - '--' => User::LEVEL_MEMBER, - 'Gestionnaire' => User::LEVEL_ADMIN, - ], - ]) - ->add('eventLevel', ChoiceType::class, [ - 'label' => 'Évènement', - 'choices' => [ - '--' => User::LEVEL_MEMBER, - 'Gestionnaire' => User::LEVEL_ADMIN, - ], - ]) - ->add('websiteLevel', ChoiceType::class, [ - 'label' => 'Site web', - 'choices' => [ - '--' => User::LEVEL_MEMBER, - 'Gestionnaire' => User::LEVEL_ADMIN, - ], - ]) - ->add('officeLevel', ChoiceType::class, [ - 'label' => 'Antenne AFUP', - 'choices' => [ - '--' => User::LEVEL_MEMBER, - 'Gestionnaire' => User::LEVEL_ADMIN, - ], - ]) ->add('status', ChoiceType::class, [ 'label' => 'État', 'choices' => [ @@ -198,21 +177,28 @@ public function buildForm(FormBuilderInterface $builder, array $options): void 'size' => 30, 'maxlength' => 30, ], - ]) - ->add('plainPassword', RepeatedType::class, [ + ]); + + if ($options['can_edit_password']) { + $builder->add('plainPassword', RepeatedType::class, [ 'mapped' => false, 'type' => PasswordType::class, 'required' => false, 'invalid_message' => 'The password fields must match', 'first_options' => ['label' => 'Password'], 'second_options' => ['label' => 'Repeat Password'], - ]) - ->add('roles', TextareaType::class, [ + ]); + } + + $builder + ->add('specialRoles', ChoiceType::class, [ 'label' => 'Rôles', - 'attr' => [ - 'cols' => 42, - 'rows' => 5, - ], + 'mapped' => false, + 'required' => false, + 'multiple' => true, + 'expanded' => true, + 'choices' => self::SPECIAL_ROLES, + 'choice_attr' => fn(string $role): array => $role === 'ROLE_SUPER_ADMIN' && !$options['can_grant_super_admin'] ? ['disabled' => 'disabled'] : [], ]) ->add('needsUpToDateMembership', CheckboxType::class, [ 'label' => 'Nécessite une cotisation à jour', @@ -220,10 +206,41 @@ public function buildForm(FormBuilderInterface $builder, array $options): void ]) ->add('save', SubmitType::class, ['label' => 'Ajouter']); - $builder->get('roles')->addModelTransformer(new CallbackTransformer( - fn($rolesAsArray): string => json_encode($rolesAsArray), - fn($rolesAsString): array => json_decode((string) $rolesAsString), - )); + $access = $builder->create('access', FormType::class, [ + 'label' => 'Accès aux modules', + 'inherit_data' => true, + // Un formulaire désactivé n'est pas soumis : les niveaux enregistrés sont conservés + 'disabled' => !$options['can_edit_modules'], + ]); + foreach (User::MODULES as $module => $label) { + $access->add($module, ChoiceType::class, [ + 'label' => $label, + 'expanded' => true, + 'choices' => self::MODULE_LEVEL_CHOICES, + 'getter' => fn(User $user): int => $user->getModuleLevel($module), + 'setter' => fn(User $user, ?int $level) => $user->setModuleLevel($module, (int) $level), + ]); + } + $builder->add($access); + + $builder->addEventListener(FormEvents::POST_SET_DATA, function (FormEvent $event): void { + /** @var User $user */ + $user = $event->getData(); + $event->getForm()->get('specialRoles')->setData(array_values(array_intersect(self::SPECIAL_ROLES, $user->getRoles()))); + }); + + $builder->addEventListener(FormEvents::POST_SUBMIT, function (FormEvent $event) use ($options): void { + /** @var User $user */ + $user = $event->getData(); + /** @var list $selectedRoles */ + $selectedRoles = $event->getForm()->get('specialRoles')->getData() ?? []; + foreach (self::SPECIAL_ROLES as $role) { + if ($role === 'ROLE_SUPER_ADMIN' && !$options['can_grant_super_admin']) { + continue; + } + $user->setRoleGranted($role, in_array($role, $selectedRoles, true)); + } + }); $builder ->get('companyId')->addModelTransformer(new CallbackTransformer( @@ -236,6 +253,12 @@ public function configureOptions(OptionsResolver $resolver): void { $resolver->setDefaults([ 'data_class' => User::class, + 'can_grant_super_admin' => false, + 'can_edit_password' => true, + 'can_edit_modules' => false, ]); + $resolver->setAllowedTypes('can_grant_super_admin', 'bool'); + $resolver->setAllowedTypes('can_edit_password', 'bool'); + $resolver->setAllowedTypes('can_edit_modules', 'bool'); } } diff --git a/sources/AppBundle/Association/Model/Repository/UserRepository.php b/sources/AppBundle/Association/Model/Repository/UserRepository.php index ca815d162..5ef2b1882 100644 --- a/sources/AppBundle/Association/Model/Repository/UserRepository.php +++ b/sources/AppBundle/Association/Model/Repository/UserRepository.php @@ -306,9 +306,9 @@ public function remove(User $user): void public function getAdministrators() { $queryBuilder = $this->getQueryBuilderWithCompleteUser() - ->where('niveau_modules <> 0 OR niveau = :level') + // "_" est un joker de LIKE : on l'échappe (\_ dans le SQL émis) pour ne cibler que les suffixes _READER / _WRITER + ->where('(app.roles LIKE \'%\\_READER"%\' OR app.roles LIKE \'%\\_WRITER"%\' OR app.roles LIKE \'%"ROLE_SUPER_ADMIN"%\')') ->orderBy(['nom', 'prenom']); - $queryBuilder->bindValue('level', User::LEVEL_ADMIN); return $this ->getQuery($queryBuilder->getStatement()) @@ -381,8 +381,8 @@ private function getQueryBuilderWithCompleteUser() return $this ->getQueryBuilderWithSubscriptions() ->cols([ - 'app.`id`', 'app.`id_personne_morale`', 'app.`login`', 'app.`mot_de_passe`', 'app.`niveau`', - 'app.`niveau_modules`', 'app.`roles`', 'app.`genre`', 'app.`nom`', 'app.`prenom`', 'app.`email`', + 'app.`id`', 'app.`id_personne_morale`', 'app.`login`', 'app.`mot_de_passe`', + 'app.`roles`', 'app.`genre`', 'app.`nom`', 'app.`prenom`', 'app.`email`', 'app.`adresse`', 'app.`code_postal`', 'app.`ville`', 'app.`id_pays`', 'app.`telephone_fixe`', 'app.`telephone_portable`', 'app.`etat`', 'app.`date_relance`', 'app.`compte_svn`', 'app.`slack_invite_status`', 'app.`slack_alternate_email`', 'app.`needs_up_to_date_membership`', @@ -538,16 +538,6 @@ public static function initMetadata(SerializerFactoryInterface $serializerFactor 'fieldName' => 'email', 'type' => 'string', ]) - ->addField([ - 'columnName' => 'niveau', - 'fieldName' => 'level', - 'type' => 'string', - ]) - ->addField([ - 'columnName' => 'niveau_modules', - 'fieldName' => 'levelModules', - 'type' => 'string', - ]) ->addField([ 'columnName' => 'roles', 'fieldName' => 'roles', diff --git a/sources/AppBundle/Association/Model/User.php b/sources/AppBundle/Association/Model/User.php index 8108f8ba7..b6224c73c 100644 --- a/sources/AppBundle/Association/Model/User.php +++ b/sources/AppBundle/Association/Model/User.php @@ -21,9 +21,25 @@ class User implements NotifyPropertyInterface, NotifiableInterface, UserInterfac { use NotifyProperty; - public const int LEVEL_MEMBER = 0; - public const int LEVEL_WRITER = 1; - public const int LEVEL_ADMIN = 2; + public const int LEVEL_NONE = 0; + public const int LEVEL_READER = 1; + public const int LEVEL_MANAGER = 2; + + /** + * Modules du back-office, dans l'ordre d'affichage. Le niveau d'accès à un module + * est porté par les rôles ROLE__READER (lecteur) et ROLE__WRITER (gestionnaire). + */ + public const array MODULES = [ + 'membres' => 'Membres', + 'veille' => 'Veille', + 'site' => 'Site', + 'apero' => 'Super-apéro', + 'event' => 'Évènements', + 'compta' => 'Trésorerie', + 'ag' => 'Assemblée générale', + 'planete' => 'Planète', + 'antennes' => 'Antennes', + ]; public const int STATUS_PENDING = -1; public const int STATUS_ACTIVE = 1; @@ -52,17 +68,7 @@ class User implements NotifyPropertyInterface, NotifiableInterface, UserInterfac private $password; /** - * @var int - */ - private $level = self::LEVEL_MEMBER; - - /** - * @var string - */ - private $levelModules = '00000'; - - /** - * @var array + * @var array */ private $roles = []; @@ -275,42 +281,6 @@ public function setPassword($password): self return $this; } - /** - * @return int - */ - public function getLevel() - { - return $this->level; - } - - /** - * @param int $level - */ - public function setLevel($level): self - { - $this->propertyChanged('level', $this->level, $level); - $this->level = $level; - return $this; - } - - /** - * @return string - */ - public function getLevelModules() - { - return $this->levelModules; - } - - /** - * @param string $levelModules - */ - public function setLevelModules($levelModules): self - { - $this->propertyChanged('levelModules', $this->levelModules, $levelModules); - $this->levelModules = $levelModules; - return $this; - } - public function getGenre(): ?Genre { return $this->genre; @@ -600,14 +570,36 @@ public function slackInviteRequested(): bool return $this->getSlackInviteStatus() === self::SLACK_INVITE_STATUS_REQUESTED; } - public function canAccessAdmin(): int + /** + * Niveau d'accès au module $module (clé de User::MODULES) : + * LEVEL_NONE, LEVEL_READER (ROLE__READER) ou LEVEL_MANAGER (ROLE__WRITER). + */ + public function getModuleLevel(string $module): int { - $roles = $this->getRoles(); + $prefix = 'ROLE_' . strtoupper($module); + + if (in_array($prefix . '_WRITER', $this->roles, true)) { + return self::LEVEL_MANAGER; + } + + if (in_array($prefix . '_READER', $this->roles, true)) { + return self::LEVEL_READER; + } + + return self::LEVEL_NONE; + } + + public function setModuleLevel(string $module, int $level): self + { + if (!array_key_exists($module, self::MODULES)) { + return $this; + } - // TODO ça serait mieux d'avoir une liste d'inclusion des roles admin au lieu d'avoir une liste d'exclusion - $diff = array_diff($roles, ['ROLE_USER', 'ROLE_COMPANY_MANAGER', 'ROLE_MEMBER_EXPIRED']); + $prefix = 'ROLE_' . strtoupper($module); - return count($diff); + return $this + ->setRoleGranted($prefix . '_READER', $level === self::LEVEL_READER) + ->setRoleGranted($prefix . '_WRITER', $level === self::LEVEL_MANAGER); } public function isMemberForCompany(): bool @@ -621,29 +613,9 @@ public function getRoles(): array if ($this->lastSubscription < new \DateTime()) { $defaultRoles = ['ROLE_MEMBER_EXPIRED']; } - if ($this->level === self::LEVEL_ADMIN) { - $defaultRoles[] = 'ROLE_SUPER_ADMIN'; - } - if (isset($this->levelModules[0]) && (int) $this->levelModules[0] > 0) { - $defaultRoles[] = 'ROLE_APERO'; - } - if (isset($this->levelModules[1]) && (int) $this->levelModules[1] > 0) { - $defaultRoles[] = 'ROLE_ANNUAIRE'; - } - if (isset($this->levelModules[2]) && (int) $this->levelModules[2] > 0) { - $defaultRoles[] = 'ROLE_SITE'; - } - if (isset($this->levelModules[3]) && (int) $this->levelModules[3] > 0) { - $defaultRoles[] = 'ROLE_FORUM'; - } - if (isset($this->levelModules[4]) && (int) $this->levelModules[4] > 0) { - $defaultRoles[] = 'ROLE_ANTENNE'; - } // On enlève le rôle ROLE_MEMBER_EXPIRED vu qu'il est défini en fonction de la cotisation dans les defaultRoles - // on fait de même avec tous les autres rôles définis en fonction des champs levelModules car ils peuvent se retrouver - // en base dans le tableau de rôle, et on ne veux pas que si on modifie le levelModules pour l'enlever, il reste via le roles - $userRoles = array_diff($this->roles, ['ROLE_MEMBER_EXPIRED', 'ROLE_SUPER_ADMIN', 'ROLE_APERO', 'ROLE_ANNUAIRE', 'ROLE_SITE', 'ROLE_FORUM', 'ROLE_ANTENNE']); + $userRoles = array_diff($this->roles, ['ROLE_MEMBER_EXPIRED']); return array_unique(array_merge($userRoles, $defaultRoles)); } @@ -657,6 +629,9 @@ public function hasRole($role): bool return in_array($role, $roles); } + /** + * @param array|null $roles + */ public function setRoles(?array $roles = null): self { if ($roles === null) { @@ -696,6 +671,21 @@ public function removeRole($role): self return $this; } + /** Ajoute ou retire $role des rôles enregistrés de la personne. */ + public function setRoleGranted(string $role, bool $granted): self + { + $roles = array_values(array_diff($this->roles, [$role])); + if ($granted) { + $roles[] = $role; + } + + if ($roles !== $this->roles) { + $this->setRoles($roles); + } + + return $this; + } + public function eraseCredentials(): void {} public function __serialize(): array @@ -717,56 +707,6 @@ public function __unserialize($serialized): void $this->password = $serialized['password']; } - public function getDirectoryLevel() - { - return $this->levelModules[1] ?? '0'; - } - - public function setDirectoryLevel($level): self - { - $oldLevelModules = $this->levelModules; - $this->levelModules[1] = $level; - $this->propertyChanged('levelModules', $oldLevelModules, $this->levelModules); - - return $this; - } - - public function getWebsiteLevel() - { - return $this->levelModules[2] ?? '0'; - } - - public function setWebsiteLevel($level): void - { - $oldLevelModules = $this->levelModules; - $this->levelModules[2] = $level; - $this->propertyChanged('levelModules', $oldLevelModules, $this->levelModules); - } - - public function getEventLevel() - { - return $this->levelModules[3] ?? '0'; - } - - public function setEventLevel($level): void - { - $oldLevelModules = $this->levelModules; - $this->levelModules[3] = $level; - $this->propertyChanged('levelModules', $oldLevelModules, $this->levelModules); - } - - public function getOfficeLevel() - { - return $this->levelModules[4] ?? '0'; - } - - public function setOfficeLevel($level): void - { - $oldLevelModules = $this->levelModules; - $this->levelModules[4] = $level; - $this->propertyChanged('levelModules', $oldLevelModules, $this->levelModules); - } - public function getAlternateEmail() { return $this->alternateEmail; diff --git a/sources/AppBundle/Command/ResetBackofficeRolesCommand.php b/sources/AppBundle/Command/ResetBackofficeRolesCommand.php new file mode 100644 index 000000000..51cbd67f4 --- /dev/null +++ b/sources/AppBundle/Command/ResetBackofficeRolesCommand.php @@ -0,0 +1,137 @@ +addOption('dry-run', null, InputOption::VALUE_NONE) + ->setHelp( + 'Tous les rôles ne correspondant pas aux rôles conservés sont retirés : ROLE_ADMIN, ROLE_SUPER_ADMIN,' + . ' les rôles legacy (ROLE_VEILLE, …) et les rôles des modules. Les accès sont ensuite réattribués' + . " depuis l'admin.\n\n" + . "Renseigner d'abord son propre compte (ROLE_SUPER_ADMIN via la DB) pour ne pas perdre l'accès à l'admin.", + ); + } + + protected function execute(InputInterface $input, OutputInterface $output): int + { + $io = new SymfonyStyle($input, $output); + $dryRun = (bool) $input->getOption('dry-run'); + + /** @var array}> $wipe */ + $wipe = []; + foreach ($this->userRepository->loadAll() as $user) { + $before = $this->storedRoles($user); + $kept = $this->keptRoles($before); + + if ($kept === $before) { + continue; + } + + $wipe[$user->getId()] = [$user, $kept]; + } + + $io->title($dryRun ? 'Wipe des droits back-office (dry-run)' : 'Wipe des droits back-office'); + + if (count($wipe) === 0) { + $io->success('Aucune personne physique concernée, rien à faire.'); + return Command::SUCCESS; + } + + $io->text('Personnes physiques impactées : ' . count($wipe)); + $this->writeRolesDiff($io, $wipe); + + if (!$dryRun && !$io->confirm('Wiper les rôles de ' . count($wipe) . ' personne(s) physique(s) ?', false)) { + $io->warning('Wipe annulé, aucun changement fait.'); + return Command::FAILURE; + } + + foreach ($wipe as [$user, $kept]) { + $user->setRoles($kept); + $this->userRepository->save($user); + } + + $io->success(sprintf('%d personne(s) physique(s) mise(s) à jour.%s', count($wipe), $dryRun ? ' (dry-run)' : '')); + + return Command::SUCCESS; + } + + /** + * Détail des rôles modifiés, une ligne par personne physique impactée. + * + * @param array}> $wipe + */ + private function writeRolesDiff(SymfonyStyle $io, array $wipe): void + { + $rows = []; + foreach ($wipe as [$user, $kept]) { + $before = $this->storedRoles($user); + $rows[] = [ + $user->getId(), + $user->getUsername(), + implode(', ', $before), + implode(', ', $kept) ?: '-', + ]; + } + + $io->table(['Id', 'Login', 'Avant', 'Après'], $rows); + } + + /** + * Rôles tels qu'ils sont stockés en base. Les défauts ajoutés par User::getRoles() + * (ROLE_USER et ROLE_MEMBER_EXPIRED, recalés dynamiquement) ne sont jamais persistés. + * + * @return list + */ + private function storedRoles(User $user): array + { + return array_values(array_diff($user->getRoles(), self::COMPUTED_ROLES)); + } + + /** + * Rôles conservés après le wipe : tout ce qui n'est pas admin, legacy ni rôles de modules. + * + * @param list $roles + * @return list + */ + private function keptRoles(array $roles): array + { + return array_values(array_filter( + $roles, + fn(string $role): bool => in_array($role, self::KEPT_ROLES, true) + || str_starts_with($role, self::KEPT_ROLES_PREFIX), + )); + } +} diff --git a/sources/AppBundle/Controller/Admin/Accounting/Configuration/AddAccountAction.php b/sources/AppBundle/Controller/Admin/Accounting/Configuration/AddAccountAction.php index 13d7a4b25..ae37735c3 100644 --- a/sources/AppBundle/Controller/Admin/Accounting/Configuration/AddAccountAction.php +++ b/sources/AppBundle/Controller/Admin/Accounting/Configuration/AddAccountAction.php @@ -11,7 +11,9 @@ use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_COMPTA_WRITER')] final class AddAccountAction extends AbstractController { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Accounting/Configuration/AddCategoryAction.php b/sources/AppBundle/Controller/Admin/Accounting/Configuration/AddCategoryAction.php index 64077bc19..20d939b42 100644 --- a/sources/AppBundle/Controller/Admin/Accounting/Configuration/AddCategoryAction.php +++ b/sources/AppBundle/Controller/Admin/Accounting/Configuration/AddCategoryAction.php @@ -11,7 +11,9 @@ use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_COMPTA_WRITER')] final class AddCategoryAction extends AbstractController { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Accounting/Configuration/AddEventAction.php b/sources/AppBundle/Controller/Admin/Accounting/Configuration/AddEventAction.php index 105c30230..6659e5f6e 100644 --- a/sources/AppBundle/Controller/Admin/Accounting/Configuration/AddEventAction.php +++ b/sources/AppBundle/Controller/Admin/Accounting/Configuration/AddEventAction.php @@ -11,7 +11,9 @@ use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_COMPTA_WRITER')] final class AddEventAction extends AbstractController { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Accounting/Configuration/AddOperationAction.php b/sources/AppBundle/Controller/Admin/Accounting/Configuration/AddOperationAction.php index c9eb60bf9..701eaee69 100644 --- a/sources/AppBundle/Controller/Admin/Accounting/Configuration/AddOperationAction.php +++ b/sources/AppBundle/Controller/Admin/Accounting/Configuration/AddOperationAction.php @@ -11,7 +11,9 @@ use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_COMPTA_WRITER')] final class AddOperationAction extends AbstractController { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Accounting/Configuration/AddPaymentAction.php b/sources/AppBundle/Controller/Admin/Accounting/Configuration/AddPaymentAction.php index 6e9f882cf..0b2e5d32a 100644 --- a/sources/AppBundle/Controller/Admin/Accounting/Configuration/AddPaymentAction.php +++ b/sources/AppBundle/Controller/Admin/Accounting/Configuration/AddPaymentAction.php @@ -11,7 +11,9 @@ use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_COMPTA_WRITER')] final class AddPaymentAction extends AbstractController { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Accounting/Configuration/AddRuleAction.php b/sources/AppBundle/Controller/Admin/Accounting/Configuration/AddRuleAction.php index 3b0f96a8f..34155fe72 100644 --- a/sources/AppBundle/Controller/Admin/Accounting/Configuration/AddRuleAction.php +++ b/sources/AppBundle/Controller/Admin/Accounting/Configuration/AddRuleAction.php @@ -11,7 +11,9 @@ use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_COMPTA_WRITER')] final class AddRuleAction extends AbstractController { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Accounting/Configuration/ArchiveAccountAction.php b/sources/AppBundle/Controller/Admin/Accounting/Configuration/ArchiveAccountAction.php index cd2d4b0e1..69e27cdb1 100644 --- a/sources/AppBundle/Controller/Admin/Accounting/Configuration/ArchiveAccountAction.php +++ b/sources/AppBundle/Controller/Admin/Accounting/Configuration/ArchiveAccountAction.php @@ -8,7 +8,9 @@ use AppBundle\Accounting\Entity\Repository\AccountRepository; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\RedirectResponse; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_COMPTA_WRITER')] final class ArchiveAccountAction extends AbstractController { public function __construct(private readonly AccountRepository $accountRepository) {} diff --git a/sources/AppBundle/Controller/Admin/Accounting/Configuration/EditAccountAction.php b/sources/AppBundle/Controller/Admin/Accounting/Configuration/EditAccountAction.php index a8c0fc892..d5eca2126 100644 --- a/sources/AppBundle/Controller/Admin/Accounting/Configuration/EditAccountAction.php +++ b/sources/AppBundle/Controller/Admin/Accounting/Configuration/EditAccountAction.php @@ -10,7 +10,9 @@ use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_COMPTA_WRITER')] final class EditAccountAction extends AbstractController { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Accounting/Configuration/EditCategoryAction.php b/sources/AppBundle/Controller/Admin/Accounting/Configuration/EditCategoryAction.php index cdde749f6..fc5b13834 100644 --- a/sources/AppBundle/Controller/Admin/Accounting/Configuration/EditCategoryAction.php +++ b/sources/AppBundle/Controller/Admin/Accounting/Configuration/EditCategoryAction.php @@ -10,7 +10,9 @@ use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_COMPTA_WRITER')] final class EditCategoryAction extends AbstractController { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Accounting/Configuration/EditEventAction.php b/sources/AppBundle/Controller/Admin/Accounting/Configuration/EditEventAction.php index 85540e2ba..5f981450c 100644 --- a/sources/AppBundle/Controller/Admin/Accounting/Configuration/EditEventAction.php +++ b/sources/AppBundle/Controller/Admin/Accounting/Configuration/EditEventAction.php @@ -10,7 +10,9 @@ use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_COMPTA_WRITER')] final class EditEventAction extends AbstractController { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Accounting/Configuration/EditOperationAction.php b/sources/AppBundle/Controller/Admin/Accounting/Configuration/EditOperationAction.php index cbe3394f0..21578a11d 100644 --- a/sources/AppBundle/Controller/Admin/Accounting/Configuration/EditOperationAction.php +++ b/sources/AppBundle/Controller/Admin/Accounting/Configuration/EditOperationAction.php @@ -10,7 +10,9 @@ use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_COMPTA_WRITER')] final class EditOperationAction extends AbstractController { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Accounting/Configuration/EditPaymentAction.php b/sources/AppBundle/Controller/Admin/Accounting/Configuration/EditPaymentAction.php index f416352ea..37259ad78 100644 --- a/sources/AppBundle/Controller/Admin/Accounting/Configuration/EditPaymentAction.php +++ b/sources/AppBundle/Controller/Admin/Accounting/Configuration/EditPaymentAction.php @@ -10,7 +10,9 @@ use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_COMPTA_WRITER')] final class EditPaymentAction extends AbstractController { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Accounting/Configuration/EditRuleAction.php b/sources/AppBundle/Controller/Admin/Accounting/Configuration/EditRuleAction.php index 210291e19..a6c1273c1 100644 --- a/sources/AppBundle/Controller/Admin/Accounting/Configuration/EditRuleAction.php +++ b/sources/AppBundle/Controller/Admin/Accounting/Configuration/EditRuleAction.php @@ -10,7 +10,9 @@ use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_COMPTA_WRITER')] final class EditRuleAction extends AbstractController { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Accounting/Configuration/ListAccountAction.php b/sources/AppBundle/Controller/Admin/Accounting/Configuration/ListAccountAction.php index 2023632d2..184ffc925 100644 --- a/sources/AppBundle/Controller/Admin/Accounting/Configuration/ListAccountAction.php +++ b/sources/AppBundle/Controller/Admin/Accounting/Configuration/ListAccountAction.php @@ -8,7 +8,9 @@ use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Twig\Environment; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_COMPTA_READER')] class ListAccountAction { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Accounting/Configuration/ListCategoryAction.php b/sources/AppBundle/Controller/Admin/Accounting/Configuration/ListCategoryAction.php index 0dceef00a..087ac0af6 100644 --- a/sources/AppBundle/Controller/Admin/Accounting/Configuration/ListCategoryAction.php +++ b/sources/AppBundle/Controller/Admin/Accounting/Configuration/ListCategoryAction.php @@ -8,7 +8,9 @@ use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Twig\Environment; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_COMPTA_READER')] final readonly class ListCategoryAction { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Accounting/Configuration/ListEventAction.php b/sources/AppBundle/Controller/Admin/Accounting/Configuration/ListEventAction.php index 321d0385f..005040c43 100644 --- a/sources/AppBundle/Controller/Admin/Accounting/Configuration/ListEventAction.php +++ b/sources/AppBundle/Controller/Admin/Accounting/Configuration/ListEventAction.php @@ -8,7 +8,9 @@ use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Twig\Environment; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_COMPTA_READER')] class ListEventAction { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Accounting/Configuration/ListOperationAction.php b/sources/AppBundle/Controller/Admin/Accounting/Configuration/ListOperationAction.php index 26c5c2a57..13842e95a 100644 --- a/sources/AppBundle/Controller/Admin/Accounting/Configuration/ListOperationAction.php +++ b/sources/AppBundle/Controller/Admin/Accounting/Configuration/ListOperationAction.php @@ -8,7 +8,9 @@ use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Twig\Environment; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_COMPTA_READER')] class ListOperationAction { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Accounting/Configuration/ListPaymentAction.php b/sources/AppBundle/Controller/Admin/Accounting/Configuration/ListPaymentAction.php index 948ea8f68..054ec3ac9 100644 --- a/sources/AppBundle/Controller/Admin/Accounting/Configuration/ListPaymentAction.php +++ b/sources/AppBundle/Controller/Admin/Accounting/Configuration/ListPaymentAction.php @@ -8,7 +8,9 @@ use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Twig\Environment; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_COMPTA_READER')] class ListPaymentAction { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Accounting/Configuration/ListRuleAction.php b/sources/AppBundle/Controller/Admin/Accounting/Configuration/ListRuleAction.php index a36888844..ee7c8a0bb 100644 --- a/sources/AppBundle/Controller/Admin/Accounting/Configuration/ListRuleAction.php +++ b/sources/AppBundle/Controller/Admin/Accounting/Configuration/ListRuleAction.php @@ -8,7 +8,9 @@ use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Twig\Environment; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_COMPTA_READER')] class ListRuleAction { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Accounting/Configuration/RestoreAccountAction.php b/sources/AppBundle/Controller/Admin/Accounting/Configuration/RestoreAccountAction.php index da71965db..fe0e56903 100644 --- a/sources/AppBundle/Controller/Admin/Accounting/Configuration/RestoreAccountAction.php +++ b/sources/AppBundle/Controller/Admin/Accounting/Configuration/RestoreAccountAction.php @@ -8,7 +8,9 @@ use AppBundle\Accounting\Entity\Repository\AccountRepository; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\RedirectResponse; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_COMPTA_WRITER')] final class RestoreAccountAction extends AbstractController { public function __construct(private readonly AccountRepository $accountRepository) {} diff --git a/sources/AppBundle/Controller/Admin/Accounting/Invoice/DownloadInvoiceAction.php b/sources/AppBundle/Controller/Admin/Accounting/Invoice/DownloadInvoiceAction.php index 8537169f6..8e31765d0 100644 --- a/sources/AppBundle/Controller/Admin/Accounting/Invoice/DownloadInvoiceAction.php +++ b/sources/AppBundle/Controller/Admin/Accounting/Invoice/DownloadInvoiceAction.php @@ -11,7 +11,9 @@ use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_COMPTA_READER')] class DownloadInvoiceAction extends AbstractController { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Accounting/Invoice/EditInvoiceAction.php b/sources/AppBundle/Controller/Admin/Accounting/Invoice/EditInvoiceAction.php index 364b043f6..a5398bb6f 100644 --- a/sources/AppBundle/Controller/Admin/Accounting/Invoice/EditInvoiceAction.php +++ b/sources/AppBundle/Controller/Admin/Accounting/Invoice/EditInvoiceAction.php @@ -10,7 +10,9 @@ use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_COMPTA_WRITER')] class EditInvoiceAction extends AbstractController { public function __construct(private readonly InvoicingRepository $invoicingRepository) {} diff --git a/sources/AppBundle/Controller/Admin/Accounting/Invoice/ListInvoiceAction.php b/sources/AppBundle/Controller/Admin/Accounting/Invoice/ListInvoiceAction.php index 0559731d6..a1c43afcc 100644 --- a/sources/AppBundle/Controller/Admin/Accounting/Invoice/ListInvoiceAction.php +++ b/sources/AppBundle/Controller/Admin/Accounting/Invoice/ListInvoiceAction.php @@ -14,7 +14,9 @@ use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Twig\Environment; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_COMPTA_READER')] class ListInvoiceAction extends AbstractController { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Accounting/Invoice/MarkFactureAsSentAction.php b/sources/AppBundle/Controller/Admin/Accounting/Invoice/MarkFactureAsSentAction.php index c51489f07..16020a560 100644 --- a/sources/AppBundle/Controller/Admin/Accounting/Invoice/MarkFactureAsSentAction.php +++ b/sources/AppBundle/Controller/Admin/Accounting/Invoice/MarkFactureAsSentAction.php @@ -14,7 +14,9 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; use Symfony\Component\Security\Csrf\CsrfToken; use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_COMPTA_WRITER')] class MarkFactureAsSentAction extends AbstractController { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Accounting/Invoice/SendInvoiceEmailAction.php b/sources/AppBundle/Controller/Admin/Accounting/Invoice/SendInvoiceEmailAction.php index 6968291fd..1cffd8c23 100644 --- a/sources/AppBundle/Controller/Admin/Accounting/Invoice/SendInvoiceEmailAction.php +++ b/sources/AppBundle/Controller/Admin/Accounting/Invoice/SendInvoiceEmailAction.php @@ -13,7 +13,9 @@ use Symfony\Component\HttpFoundation\Response; use Symfony\Bundle\SecurityBundle\Security; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_COMPTA_WRITER')] class SendInvoiceEmailAction extends AbstractController { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Accounting/Journal/AddTransactionAction.php b/sources/AppBundle/Controller/Admin/Accounting/Journal/AddTransactionAction.php index 163618caa..d35cb4dc0 100644 --- a/sources/AppBundle/Controller/Admin/Accounting/Journal/AddTransactionAction.php +++ b/sources/AppBundle/Controller/Admin/Accounting/Journal/AddTransactionAction.php @@ -12,7 +12,9 @@ use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_COMPTA_WRITER')] class AddTransactionAction extends AbstractController { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Accounting/Journal/AllocateAction.php b/sources/AppBundle/Controller/Admin/Accounting/Journal/AllocateAction.php index c7d1d178d..69c37cd87 100644 --- a/sources/AppBundle/Controller/Admin/Accounting/Journal/AllocateAction.php +++ b/sources/AppBundle/Controller/Admin/Accounting/Journal/AllocateAction.php @@ -12,7 +12,9 @@ use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_COMPTA_WRITER')] class AllocateAction extends AbstractController { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Accounting/Journal/DeleteAction.php b/sources/AppBundle/Controller/Admin/Accounting/Journal/DeleteAction.php index 2c5eac9e3..6aa822335 100644 --- a/sources/AppBundle/Controller/Admin/Accounting/Journal/DeleteAction.php +++ b/sources/AppBundle/Controller/Admin/Accounting/Journal/DeleteAction.php @@ -10,7 +10,9 @@ use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_COMPTA_WRITER')] class DeleteAction extends AbstractController { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Accounting/Journal/DownloadAttachmentAction.php b/sources/AppBundle/Controller/Admin/Accounting/Journal/DownloadAttachmentAction.php index 4938d3e79..d6c668150 100644 --- a/sources/AppBundle/Controller/Admin/Accounting/Journal/DownloadAttachmentAction.php +++ b/sources/AppBundle/Controller/Admin/Accounting/Journal/DownloadAttachmentAction.php @@ -11,7 +11,9 @@ use Symfony\Component\HttpFoundation\BinaryFileResponse; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_COMPTA_READER')] class DownloadAttachmentAction extends AbstractController { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Accounting/Journal/DownloadAttachmentsAction.php b/sources/AppBundle/Controller/Admin/Accounting/Journal/DownloadAttachmentsAction.php index 5f579488b..0c428c6f0 100644 --- a/sources/AppBundle/Controller/Admin/Accounting/Journal/DownloadAttachmentsAction.php +++ b/sources/AppBundle/Controller/Admin/Accounting/Journal/DownloadAttachmentsAction.php @@ -14,7 +14,9 @@ use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use ZipArchive; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_COMPTA_READER')] class DownloadAttachmentsAction extends AbstractController { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Accounting/Journal/EditTransactionAction.php b/sources/AppBundle/Controller/Admin/Accounting/Journal/EditTransactionAction.php index 52eb50b56..f6d89a39e 100644 --- a/sources/AppBundle/Controller/Admin/Accounting/Journal/EditTransactionAction.php +++ b/sources/AppBundle/Controller/Admin/Accounting/Journal/EditTransactionAction.php @@ -13,7 +13,9 @@ use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_COMPTA_WRITER')] class EditTransactionAction extends AbstractController { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Accounting/Journal/ExportAction.php b/sources/AppBundle/Controller/Admin/Accounting/Journal/ExportAction.php index 1f53e6f08..504074cb0 100644 --- a/sources/AppBundle/Controller/Admin/Accounting/Journal/ExportAction.php +++ b/sources/AppBundle/Controller/Admin/Accounting/Journal/ExportAction.php @@ -13,7 +13,9 @@ use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\ResponseHeaderBag; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_COMPTA_READER')] class ExportAction extends AbstractController { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Accounting/Journal/ImportAction.php b/sources/AppBundle/Controller/Admin/Accounting/Journal/ImportAction.php index e58b86fa4..b8961a5db 100644 --- a/sources/AppBundle/Controller/Admin/Accounting/Journal/ImportAction.php +++ b/sources/AppBundle/Controller/Admin/Accounting/Journal/ImportAction.php @@ -13,7 +13,9 @@ use Symfony\Component\HttpFoundation\File\UploadedFile; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_COMPTA_WRITER')] class ImportAction extends AbstractController { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Accounting/Journal/ListAction.php b/sources/AppBundle/Controller/Admin/Accounting/Journal/ListAction.php index 1a67ef05f..3ce576a31 100644 --- a/sources/AppBundle/Controller/Admin/Accounting/Journal/ListAction.php +++ b/sources/AppBundle/Controller/Admin/Accounting/Journal/ListAction.php @@ -14,7 +14,9 @@ use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_COMPTA_READER')] class ListAction extends AbstractController { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Accounting/Journal/UpdateInfoAction.php b/sources/AppBundle/Controller/Admin/Accounting/Journal/UpdateInfoAction.php index 04173c711..39db1a0d1 100644 --- a/sources/AppBundle/Controller/Admin/Accounting/Journal/UpdateInfoAction.php +++ b/sources/AppBundle/Controller/Admin/Accounting/Journal/UpdateInfoAction.php @@ -14,7 +14,9 @@ use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_COMPTA_WRITER')] class UpdateInfoAction extends AbstractController { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Accounting/Journal/UploadAttachmentAction.php b/sources/AppBundle/Controller/Admin/Accounting/Journal/UploadAttachmentAction.php index bb88076ba..d5b99c334 100644 --- a/sources/AppBundle/Controller/Admin/Accounting/Journal/UploadAttachmentAction.php +++ b/sources/AppBundle/Controller/Admin/Accounting/Journal/UploadAttachmentAction.php @@ -13,7 +13,9 @@ use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Validator\Constraints\File; use Symfony\Component\Validator\Validator\ValidatorInterface; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_COMPTA_WRITER')] class UploadAttachmentAction extends AbstractController { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Accounting/MembershipFee/AddMembershipFeeAction.php b/sources/AppBundle/Controller/Admin/Accounting/MembershipFee/AddMembershipFeeAction.php index d1ccb2179..ac775bbca 100644 --- a/sources/AppBundle/Controller/Admin/Accounting/MembershipFee/AddMembershipFeeAction.php +++ b/sources/AppBundle/Controller/Admin/Accounting/MembershipFee/AddMembershipFeeAction.php @@ -15,7 +15,9 @@ use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_COMPTA_WRITER')] class AddMembershipFeeAction extends AbstractController { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Accounting/MembershipFee/DeleteMembershipFeeAction.php b/sources/AppBundle/Controller/Admin/Accounting/MembershipFee/DeleteMembershipFeeAction.php index 6add1dfa2..d0c68a0d5 100644 --- a/sources/AppBundle/Controller/Admin/Accounting/MembershipFee/DeleteMembershipFeeAction.php +++ b/sources/AppBundle/Controller/Admin/Accounting/MembershipFee/DeleteMembershipFeeAction.php @@ -12,7 +12,9 @@ use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Security\Csrf\CsrfToken; use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_COMPTA_WRITER')] class DeleteMembershipFeeAction extends AbstractController { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Accounting/MembershipFee/DownloadMembershipFeeInvoiceAction.php b/sources/AppBundle/Controller/Admin/Accounting/MembershipFee/DownloadMembershipFeeInvoiceAction.php index cef89234d..5e85fe032 100644 --- a/sources/AppBundle/Controller/Admin/Accounting/MembershipFee/DownloadMembershipFeeInvoiceAction.php +++ b/sources/AppBundle/Controller/Admin/Accounting/MembershipFee/DownloadMembershipFeeInvoiceAction.php @@ -8,7 +8,9 @@ use AppBundle\Association\MemberType; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_COMPTA_READER')] class DownloadMembershipFeeInvoiceAction extends AbstractController { public function __construct(private readonly MembershipFeeInvoicePdfGenerator $pdfGenerator) {} diff --git a/sources/AppBundle/Controller/Admin/Accounting/MembershipFee/EditMembershipFeeAction.php b/sources/AppBundle/Controller/Admin/Accounting/MembershipFee/EditMembershipFeeAction.php index e42bcbbfa..45fa7895c 100644 --- a/sources/AppBundle/Controller/Admin/Accounting/MembershipFee/EditMembershipFeeAction.php +++ b/sources/AppBundle/Controller/Admin/Accounting/MembershipFee/EditMembershipFeeAction.php @@ -13,7 +13,9 @@ use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_COMPTA_WRITER')] class EditMembershipFeeAction extends AbstractController { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Accounting/MembershipFee/ListMembershipFeeAction.php b/sources/AppBundle/Controller/Admin/Accounting/MembershipFee/ListMembershipFeeAction.php index be3f49c9d..56ae8ae52 100644 --- a/sources/AppBundle/Controller/Admin/Accounting/MembershipFee/ListMembershipFeeAction.php +++ b/sources/AppBundle/Controller/Admin/Accounting/MembershipFee/ListMembershipFeeAction.php @@ -12,7 +12,9 @@ use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Security\Core\User\UserInterface; use Symfony\Component\Security\Http\Attribute\CurrentUser; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_COMPTA_READER')] class ListMembershipFeeAction extends AbstractController { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Accounting/MembershipFee/SendMembershipFeeInvoiceAction.php b/sources/AppBundle/Controller/Admin/Accounting/MembershipFee/SendMembershipFeeInvoiceAction.php index cab1504f0..befb8b89a 100644 --- a/sources/AppBundle/Controller/Admin/Accounting/MembershipFee/SendMembershipFeeInvoiceAction.php +++ b/sources/AppBundle/Controller/Admin/Accounting/MembershipFee/SendMembershipFeeInvoiceAction.php @@ -9,7 +9,9 @@ use AppBundle\AuditLog\Audit; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_COMPTA_WRITER')] class SendMembershipFeeInvoiceAction extends AbstractController { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Accounting/Produit/AddProduitAction.php b/sources/AppBundle/Controller/Admin/Accounting/Produit/AddProduitAction.php index 22378f5d6..96d9e942c 100644 --- a/sources/AppBundle/Controller/Admin/Accounting/Produit/AddProduitAction.php +++ b/sources/AppBundle/Controller/Admin/Accounting/Produit/AddProduitAction.php @@ -11,7 +11,9 @@ use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_COMPTA_WRITER')] final class AddProduitAction extends AbstractController { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Accounting/Produit/DeleteProduitAction.php b/sources/AppBundle/Controller/Admin/Accounting/Produit/DeleteProduitAction.php index d9b0e03ee..98ea43e49 100644 --- a/sources/AppBundle/Controller/Admin/Accounting/Produit/DeleteProduitAction.php +++ b/sources/AppBundle/Controller/Admin/Accounting/Produit/DeleteProduitAction.php @@ -10,7 +10,9 @@ use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_COMPTA_WRITER')] final class DeleteProduitAction extends AbstractController { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Accounting/Produit/EditProduitAction.php b/sources/AppBundle/Controller/Admin/Accounting/Produit/EditProduitAction.php index 3e512667e..b2d9408bf 100644 --- a/sources/AppBundle/Controller/Admin/Accounting/Produit/EditProduitAction.php +++ b/sources/AppBundle/Controller/Admin/Accounting/Produit/EditProduitAction.php @@ -11,7 +11,9 @@ use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_COMPTA_WRITER')] final class EditProduitAction extends AbstractController { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Accounting/Produit/ListProduitAction.php b/sources/AppBundle/Controller/Admin/Accounting/Produit/ListProduitAction.php index 451ab623d..c2dcfa22a 100644 --- a/sources/AppBundle/Controller/Admin/Accounting/Produit/ListProduitAction.php +++ b/sources/AppBundle/Controller/Admin/Accounting/Produit/ListProduitAction.php @@ -8,7 +8,9 @@ use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Twig\Environment; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_COMPTA_READER')] final readonly class ListProduitAction { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Accounting/Quotation/AddQuotationAction.php b/sources/AppBundle/Controller/Admin/Accounting/Quotation/AddQuotationAction.php index d84092380..2d8220dcc 100644 --- a/sources/AppBundle/Controller/Admin/Accounting/Quotation/AddQuotationAction.php +++ b/sources/AppBundle/Controller/Admin/Accounting/Quotation/AddQuotationAction.php @@ -15,7 +15,9 @@ use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_COMPTA_WRITER')] class AddQuotationAction extends AbstractController { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Accounting/Quotation/ConvertQuotationAction.php b/sources/AppBundle/Controller/Admin/Accounting/Quotation/ConvertQuotationAction.php index b1e7c7e0c..855a1d058 100644 --- a/sources/AppBundle/Controller/Admin/Accounting/Quotation/ConvertQuotationAction.php +++ b/sources/AppBundle/Controller/Admin/Accounting/Quotation/ConvertQuotationAction.php @@ -10,7 +10,9 @@ use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_COMPTA_WRITER')] class ConvertQuotationAction extends AbstractController { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Accounting/Quotation/DownloadQuotationAction.php b/sources/AppBundle/Controller/Admin/Accounting/Quotation/DownloadQuotationAction.php index 86bcdcbb7..d2a27cd60 100644 --- a/sources/AppBundle/Controller/Admin/Accounting/Quotation/DownloadQuotationAction.php +++ b/sources/AppBundle/Controller/Admin/Accounting/Quotation/DownloadQuotationAction.php @@ -10,7 +10,9 @@ use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_COMPTA_READER')] class DownloadQuotationAction extends AbstractController { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Accounting/Quotation/EditQuotationAction.php b/sources/AppBundle/Controller/Admin/Accounting/Quotation/EditQuotationAction.php index 58156dfec..3379d846a 100644 --- a/sources/AppBundle/Controller/Admin/Accounting/Quotation/EditQuotationAction.php +++ b/sources/AppBundle/Controller/Admin/Accounting/Quotation/EditQuotationAction.php @@ -12,7 +12,9 @@ use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_COMPTA_WRITER')] class EditQuotationAction extends AbstractController { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Accounting/Quotation/ListQuotationAction.php b/sources/AppBundle/Controller/Admin/Accounting/Quotation/ListQuotationAction.php index f4316f493..695528287 100644 --- a/sources/AppBundle/Controller/Admin/Accounting/Quotation/ListQuotationAction.php +++ b/sources/AppBundle/Controller/Admin/Accounting/Quotation/ListQuotationAction.php @@ -12,7 +12,9 @@ use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Twig\Environment; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_COMPTA_READER')] class ListQuotationAction extends AbstractController { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Accounting/SearchAction.php b/sources/AppBundle/Controller/Admin/Accounting/SearchAction.php index 4ea8d8849..c1c9639dc 100644 --- a/sources/AppBundle/Controller/Admin/Accounting/SearchAction.php +++ b/sources/AppBundle/Controller/Admin/Accounting/SearchAction.php @@ -9,7 +9,9 @@ use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_COMPTA_READER')] class SearchAction extends AbstractController { public function __construct(private readonly SearchResultProvider $searchResultProvider) {} diff --git a/sources/AppBundle/Controller/Admin/AdministratorsListAction.php b/sources/AppBundle/Controller/Admin/AdministratorsListAction.php index 88600ba96..5ae78a0a6 100644 --- a/sources/AppBundle/Controller/Admin/AdministratorsListAction.php +++ b/sources/AppBundle/Controller/Admin/AdministratorsListAction.php @@ -5,9 +5,12 @@ namespace AppBundle\Controller\Admin; use AppBundle\Association\Model\Repository\UserRepository; +use AppBundle\Association\Model\User; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_SUPER_ADMIN')] class AdministratorsListAction extends AbstractController { public function __construct(private readonly UserRepository $userRepository) {} @@ -16,6 +19,7 @@ public function __invoke(): Response { return $this->render('admin/administrators.html.twig', [ 'administrators' => $this->userRepository->getAdministrators(), + 'modules' => User::MODULES, ]); } } diff --git a/sources/AppBundle/Controller/Admin/Antennes/AntenneListAction.php b/sources/AppBundle/Controller/Admin/Antennes/AntenneListAction.php index 7db3e4291..323772c5a 100644 --- a/sources/AppBundle/Controller/Admin/Antennes/AntenneListAction.php +++ b/sources/AppBundle/Controller/Admin/Antennes/AntenneListAction.php @@ -9,7 +9,9 @@ use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Twig\Environment; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_ANTENNES_READER')] final readonly class AntenneListAction { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Audit/IndexAction.php b/sources/AppBundle/Controller/Admin/Audit/IndexAction.php index 62dd26f8c..1b8ea4109 100644 --- a/sources/AppBundle/Controller/Admin/Audit/IndexAction.php +++ b/sources/AppBundle/Controller/Admin/Audit/IndexAction.php @@ -7,7 +7,9 @@ use AppBundle\AuditLog\AuditLogRepository; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_SUPER_ADMIN')] final class IndexAction extends AbstractController { public function __construct(private readonly AuditLogRepository $auditLogRepository) {} diff --git a/sources/AppBundle/Controller/Admin/Event/AddBilleteriePriveeAction.php b/sources/AppBundle/Controller/Admin/Event/AddBilleteriePriveeAction.php index 172037e28..af34dca86 100644 --- a/sources/AppBundle/Controller/Admin/Event/AddBilleteriePriveeAction.php +++ b/sources/AppBundle/Controller/Admin/Event/AddBilleteriePriveeAction.php @@ -13,7 +13,9 @@ use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_EVENT_WRITER')] class AddBilleteriePriveeAction extends AbstractController { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Event/ArchiveAction.php b/sources/AppBundle/Controller/Admin/Event/ArchiveAction.php index 45e506aba..6a525f750 100644 --- a/sources/AppBundle/Controller/Admin/Event/ArchiveAction.php +++ b/sources/AppBundle/Controller/Admin/Event/ArchiveAction.php @@ -8,7 +8,9 @@ use AppBundle\Event\Model\Repository\EventRepository; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\RedirectResponse; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_EVENT_WRITER')] final class ArchiveAction extends AbstractController { public function __construct(private readonly EventRepository $eventRepository) {} diff --git a/sources/AppBundle/Controller/Admin/Event/BadgesGenerateAction.php b/sources/AppBundle/Controller/Admin/Event/BadgesGenerateAction.php index 93e1bb533..b7ce771c0 100644 --- a/sources/AppBundle/Controller/Admin/Event/BadgesGenerateAction.php +++ b/sources/AppBundle/Controller/Admin/Event/BadgesGenerateAction.php @@ -10,7 +10,9 @@ use Symfony\Component\HttpFoundation\BinaryFileResponse; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\ResponseHeaderBag; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_EVENT_READER')] class BadgesGenerateAction { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Event/BilleteriePriveeAction.php b/sources/AppBundle/Controller/Admin/Event/BilleteriePriveeAction.php index 265b69e9a..2e625118c 100644 --- a/sources/AppBundle/Controller/Admin/Event/BilleteriePriveeAction.php +++ b/sources/AppBundle/Controller/Admin/Event/BilleteriePriveeAction.php @@ -9,7 +9,9 @@ use AppBundle\Event\Entity\Repository\TicketTypeRepository; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_EVENT_READER')] class BilleteriePriveeAction extends AbstractController { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Event/DeleteBilleteriePriveeAction.php b/sources/AppBundle/Controller/Admin/Event/DeleteBilleteriePriveeAction.php index 6b40a4651..fc8e160a6 100644 --- a/sources/AppBundle/Controller/Admin/Event/DeleteBilleteriePriveeAction.php +++ b/sources/AppBundle/Controller/Admin/Event/DeleteBilleteriePriveeAction.php @@ -10,7 +10,9 @@ use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_EVENT_WRITER')] class DeleteBilleteriePriveeAction extends AbstractController { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Event/DeleteSponsorTicketAction.php b/sources/AppBundle/Controller/Admin/Event/DeleteSponsorTicketAction.php index 5b9469d12..daf16eac5 100644 --- a/sources/AppBundle/Controller/Admin/Event/DeleteSponsorTicketAction.php +++ b/sources/AppBundle/Controller/Admin/Event/DeleteSponsorTicketAction.php @@ -9,7 +9,9 @@ use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_EVENT_WRITER')] class DeleteSponsorTicketAction extends AbstractController { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Event/EditBilleteriePriveeAction.php b/sources/AppBundle/Controller/Admin/Event/EditBilleteriePriveeAction.php index 9192e199c..c4f985034 100644 --- a/sources/AppBundle/Controller/Admin/Event/EditBilleteriePriveeAction.php +++ b/sources/AppBundle/Controller/Admin/Event/EditBilleteriePriveeAction.php @@ -13,7 +13,9 @@ use Symfony\Component\Form\FormError; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_EVENT_WRITER')] class EditBilleteriePriveeAction extends AbstractController { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Event/EventAction.php b/sources/AppBundle/Controller/Admin/Event/EventAction.php index 3e1610b05..55f8759d9 100644 --- a/sources/AppBundle/Controller/Admin/Event/EventAction.php +++ b/sources/AppBundle/Controller/Admin/Event/EventAction.php @@ -13,7 +13,9 @@ use Symfony\Component\HttpFoundation\File\UploadedFile; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_EVENT_WRITER')] class EventAction extends AbstractController { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Event/EventEditorializationAction.php b/sources/AppBundle/Controller/Admin/Event/EventEditorializationAction.php index 937ebe31e..62316dab9 100644 --- a/sources/AppBundle/Controller/Admin/Event/EventEditorializationAction.php +++ b/sources/AppBundle/Controller/Admin/Event/EventEditorializationAction.php @@ -13,7 +13,9 @@ use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_EVENT_WRITER')] class EventEditorializationAction extends AbstractController { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Event/EventThemeAction.php b/sources/AppBundle/Controller/Admin/Event/EventThemeAction.php index 10431d338..3219c17e6 100644 --- a/sources/AppBundle/Controller/Admin/Event/EventThemeAction.php +++ b/sources/AppBundle/Controller/Admin/Event/EventThemeAction.php @@ -11,7 +11,9 @@ use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_EVENT_WRITER')] class EventThemeAction extends AbstractController { public function __construct(private readonly EventThemeRepository $eventThemeRepository) {} diff --git a/sources/AppBundle/Controller/Admin/Event/EventThemeAddEditAction.php b/sources/AppBundle/Controller/Admin/Event/EventThemeAddEditAction.php index 06e231f9e..ff11d7d37 100644 --- a/sources/AppBundle/Controller/Admin/Event/EventThemeAddEditAction.php +++ b/sources/AppBundle/Controller/Admin/Event/EventThemeAddEditAction.php @@ -13,7 +13,9 @@ use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_EVENT_WRITER')] class EventThemeAddEditAction extends AbstractController { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Event/ExtendSpecialPriceAction.php b/sources/AppBundle/Controller/Admin/Event/ExtendSpecialPriceAction.php index 07babef48..18960deef 100644 --- a/sources/AppBundle/Controller/Admin/Event/ExtendSpecialPriceAction.php +++ b/sources/AppBundle/Controller/Admin/Event/ExtendSpecialPriceAction.php @@ -9,7 +9,9 @@ use AppBundle\Event\Entity\TicketSpecialPrice; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_EVENT_WRITER')] class ExtendSpecialPriceAction extends AbstractController { public function __construct(private readonly TicketSpecialPriceRepository $ticketSpecialPriceRepository) {} diff --git a/sources/AppBundle/Controller/Admin/Event/Facturation/DeleteFactureAction.php b/sources/AppBundle/Controller/Admin/Event/Facturation/DeleteFactureAction.php index dc9fc8239..f8a2c9154 100644 --- a/sources/AppBundle/Controller/Admin/Event/Facturation/DeleteFactureAction.php +++ b/sources/AppBundle/Controller/Admin/Event/Facturation/DeleteFactureAction.php @@ -15,7 +15,9 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; use Symfony\Component\Security\Csrf\CsrfToken; use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_EVENT_WRITER')] class DeleteFactureAction extends AbstractController { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Event/Facturation/DownloadDevisAction.php b/sources/AppBundle/Controller/Admin/Event/Facturation/DownloadDevisAction.php index bd31c1b36..8ab7c0a6d 100644 --- a/sources/AppBundle/Controller/Admin/Event/Facturation/DownloadDevisAction.php +++ b/sources/AppBundle/Controller/Admin/Event/Facturation/DownloadDevisAction.php @@ -11,7 +11,9 @@ use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_EVENT_READER')] class DownloadDevisAction extends AbstractController { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Event/Facturation/DownloadFactureAction.php b/sources/AppBundle/Controller/Admin/Event/Facturation/DownloadFactureAction.php index 306ae6944..2b294ed59 100644 --- a/sources/AppBundle/Controller/Admin/Event/Facturation/DownloadFactureAction.php +++ b/sources/AppBundle/Controller/Admin/Event/Facturation/DownloadFactureAction.php @@ -11,7 +11,9 @@ use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_EVENT_READER')] class DownloadFactureAction extends AbstractController { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Event/Facturation/IssueFactureAction.php b/sources/AppBundle/Controller/Admin/Event/Facturation/IssueFactureAction.php index 06795b693..383ad6001 100644 --- a/sources/AppBundle/Controller/Admin/Event/Facturation/IssueFactureAction.php +++ b/sources/AppBundle/Controller/Admin/Event/Facturation/IssueFactureAction.php @@ -12,7 +12,9 @@ use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_EVENT_WRITER')] class IssueFactureAction extends AbstractController { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Event/Facturation/ListFacturesAction.php b/sources/AppBundle/Controller/Admin/Event/Facturation/ListFacturesAction.php index d8e8ad5db..4d4d8ece9 100644 --- a/sources/AppBundle/Controller/Admin/Event/Facturation/ListFacturesAction.php +++ b/sources/AppBundle/Controller/Admin/Event/Facturation/ListFacturesAction.php @@ -10,7 +10,9 @@ use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Webmozart\Assert\Assert; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_EVENT_READER')] class ListFacturesAction extends AbstractController { public const array VALID_SORTS = ['date_facture', 'reference', 'societe', 'montant', 'etat', 'facturation']; diff --git a/sources/AppBundle/Controller/Admin/Event/Facturation/SendFactureAction.php b/sources/AppBundle/Controller/Admin/Event/Facturation/SendFactureAction.php index 914aeb27f..cd5db1b17 100644 --- a/sources/AppBundle/Controller/Admin/Event/Facturation/SendFactureAction.php +++ b/sources/AppBundle/Controller/Admin/Event/Facturation/SendFactureAction.php @@ -12,7 +12,9 @@ use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_EVENT_WRITER')] class SendFactureAction extends AbstractController { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Event/Interview/AddOrEditAction.php b/sources/AppBundle/Controller/Admin/Event/Interview/AddOrEditAction.php index 3d66aa673..a5108ab82 100644 --- a/sources/AppBundle/Controller/Admin/Event/Interview/AddOrEditAction.php +++ b/sources/AppBundle/Controller/Admin/Event/Interview/AddOrEditAction.php @@ -21,7 +21,9 @@ use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_EVENT_WRITER')] class AddOrEditAction extends AbstractController { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Event/Interview/ConfigAction.php b/sources/AppBundle/Controller/Admin/Event/Interview/ConfigAction.php index 351bcda56..3e0efd6bb 100644 --- a/sources/AppBundle/Controller/Admin/Event/Interview/ConfigAction.php +++ b/sources/AppBundle/Controller/Admin/Event/Interview/ConfigAction.php @@ -10,7 +10,9 @@ use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_EVENT_WRITER')] final class ConfigAction extends AbstractController { public function __construct(private readonly EventRepository $eventRepository) {} diff --git a/sources/AppBundle/Controller/Admin/Event/Interview/ListAction.php b/sources/AppBundle/Controller/Admin/Event/Interview/ListAction.php index c5747ce54..3abc2b0ff 100644 --- a/sources/AppBundle/Controller/Admin/Event/Interview/ListAction.php +++ b/sources/AppBundle/Controller/Admin/Event/Interview/ListAction.php @@ -12,7 +12,9 @@ use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\DependencyInjection\Attribute\Autowire; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_EVENT_READER')] class ListAction extends AbstractController { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Event/ListAction.php b/sources/AppBundle/Controller/Admin/Event/ListAction.php index f5ee7536c..c93727aa0 100644 --- a/sources/AppBundle/Controller/Admin/Event/ListAction.php +++ b/sources/AppBundle/Controller/Admin/Event/ListAction.php @@ -7,7 +7,9 @@ use AppBundle\Event\Model\Repository\EventRepository; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_EVENT_READER')] class ListAction extends AbstractController { public function __construct(private readonly EventRepository $eventRepository) {} diff --git a/sources/AppBundle/Controller/Admin/Event/PendingBankwiresAction.php b/sources/AppBundle/Controller/Admin/Event/PendingBankwiresAction.php index cc838e9b2..fba2a0c6f 100644 --- a/sources/AppBundle/Controller/Admin/Event/PendingBankwiresAction.php +++ b/sources/AppBundle/Controller/Admin/Event/PendingBankwiresAction.php @@ -21,7 +21,9 @@ use Symfony\Component\HttpKernel\KernelEvents; use Symfony\Component\Security\Csrf\CsrfToken; use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_EVENT_WRITER')] class PendingBankwiresAction extends AbstractController { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Event/PreviousRegistrationsAction.php b/sources/AppBundle/Controller/Admin/Event/PreviousRegistrationsAction.php index e6283acb2..3b2500a55 100644 --- a/sources/AppBundle/Controller/Admin/Event/PreviousRegistrationsAction.php +++ b/sources/AppBundle/Controller/Admin/Event/PreviousRegistrationsAction.php @@ -10,7 +10,9 @@ use Symfony\Component\HttpFoundation\BinaryFileResponse; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\ResponseHeaderBag; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_EVENT_READER')] class PreviousRegistrationsAction { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Event/PricesAction.php b/sources/AppBundle/Controller/Admin/Event/PricesAction.php index a1a3b1db6..42e76148e 100644 --- a/sources/AppBundle/Controller/Admin/Event/PricesAction.php +++ b/sources/AppBundle/Controller/Admin/Event/PricesAction.php @@ -8,7 +8,9 @@ use AppBundle\Event\Entity\Repository\TicketEventTypeRepository; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_EVENT_READER')] class PricesAction extends AbstractController { public function __construct(private readonly TicketEventTypeRepository $ticketEventTypeRepository) {} diff --git a/sources/AppBundle/Controller/Admin/Event/PricesAddAction.php b/sources/AppBundle/Controller/Admin/Event/PricesAddAction.php index 13badc4d9..eb3b3b2f2 100644 --- a/sources/AppBundle/Controller/Admin/Event/PricesAddAction.php +++ b/sources/AppBundle/Controller/Admin/Event/PricesAddAction.php @@ -13,7 +13,9 @@ use Symfony\Component\Form\FormError; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_EVENT_WRITER')] class PricesAddAction extends AbstractController { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Event/PricesEditAction.php b/sources/AppBundle/Controller/Admin/Event/PricesEditAction.php index cf2b4f902..b45003fd9 100644 --- a/sources/AppBundle/Controller/Admin/Event/PricesEditAction.php +++ b/sources/AppBundle/Controller/Admin/Event/PricesEditAction.php @@ -14,7 +14,9 @@ use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_EVENT_WRITER')] class PricesEditAction extends AbstractController { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Event/RemoveEventAction.php b/sources/AppBundle/Controller/Admin/Event/RemoveEventAction.php index 0456a6ae4..b163f62fd 100644 --- a/sources/AppBundle/Controller/Admin/Event/RemoveEventAction.php +++ b/sources/AppBundle/Controller/Admin/Event/RemoveEventAction.php @@ -9,7 +9,9 @@ use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\Security\Csrf\CsrfToken; use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_EVENT_WRITER')] class RemoveEventAction extends AbstractController { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Event/ResendSponsorTokenAction.php b/sources/AppBundle/Controller/Admin/Event/ResendSponsorTokenAction.php index 63f5f8fcf..c9a064f51 100644 --- a/sources/AppBundle/Controller/Admin/Event/ResendSponsorTokenAction.php +++ b/sources/AppBundle/Controller/Admin/Event/ResendSponsorTokenAction.php @@ -10,7 +10,9 @@ use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_EVENT_WRITER')] class ResendSponsorTokenAction extends AbstractController { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Event/RestoreAction.php b/sources/AppBundle/Controller/Admin/Event/RestoreAction.php index a4b97cc82..f3bce631e 100644 --- a/sources/AppBundle/Controller/Admin/Event/RestoreAction.php +++ b/sources/AppBundle/Controller/Admin/Event/RestoreAction.php @@ -8,7 +8,9 @@ use AppBundle\Event\Model\Repository\EventRepository; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\RedirectResponse; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_EVENT_WRITER')] final class RestoreAction extends AbstractController { public function __construct(private readonly EventRepository $eventRepository) {} diff --git a/sources/AppBundle/Controller/Admin/Event/RoomAction.php b/sources/AppBundle/Controller/Admin/Event/RoomAction.php index 7beb92969..1422d87e4 100644 --- a/sources/AppBundle/Controller/Admin/Event/RoomAction.php +++ b/sources/AppBundle/Controller/Admin/Event/RoomAction.php @@ -14,7 +14,9 @@ use Symfony\Component\Form\FormInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_EVENT_WRITER')] class RoomAction extends AbstractController { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Event/SendLastCallSponsorTokenAction.php b/sources/AppBundle/Controller/Admin/Event/SendLastCallSponsorTokenAction.php index 2d6102019..cfab9da2c 100644 --- a/sources/AppBundle/Controller/Admin/Event/SendLastCallSponsorTokenAction.php +++ b/sources/AppBundle/Controller/Admin/Event/SendLastCallSponsorTokenAction.php @@ -11,7 +11,9 @@ use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_EVENT_WRITER')] class SendLastCallSponsorTokenAction extends AbstractController { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Event/SendTestInscriptionEmailAction.php b/sources/AppBundle/Controller/Admin/Event/SendTestInscriptionEmailAction.php index 8f153d696..029a4c441 100644 --- a/sources/AppBundle/Controller/Admin/Event/SendTestInscriptionEmailAction.php +++ b/sources/AppBundle/Controller/Admin/Event/SendTestInscriptionEmailAction.php @@ -9,7 +9,9 @@ use AppBundle\Email\Mailer\MailUserFactory; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\RedirectResponse; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_EVENT_WRITER')] class SendTestInscriptionEmailAction extends AbstractController { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Event/Session/CalendarAjaxAction.php b/sources/AppBundle/Controller/Admin/Event/Session/CalendarAjaxAction.php index f8d41cbdd..c0145f3a3 100644 --- a/sources/AppBundle/Controller/Admin/Event/Session/CalendarAjaxAction.php +++ b/sources/AppBundle/Controller/Admin/Event/Session/CalendarAjaxAction.php @@ -9,7 +9,9 @@ use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_EVENT_WRITER')] class CalendarAjaxAction extends AbstractController { public function __construct(private readonly PlanningRepository $planningRepository) {} diff --git a/sources/AppBundle/Controller/Admin/Event/Session/DeleteAction.php b/sources/AppBundle/Controller/Admin/Event/Session/DeleteAction.php index e6bdc1c46..2fdd0cbca 100644 --- a/sources/AppBundle/Controller/Admin/Event/Session/DeleteAction.php +++ b/sources/AppBundle/Controller/Admin/Event/Session/DeleteAction.php @@ -10,7 +10,9 @@ use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_EVENT_WRITER')] class DeleteAction extends AbstractController { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Event/Session/EditAction.php b/sources/AppBundle/Controller/Admin/Event/Session/EditAction.php index 746dbc611..3a4340c4e 100644 --- a/sources/AppBundle/Controller/Admin/Event/Session/EditAction.php +++ b/sources/AppBundle/Controller/Admin/Event/Session/EditAction.php @@ -20,7 +20,9 @@ use Symfony\Component\Form\FormInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_EVENT_WRITER')] class EditAction extends AbstractController { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Event/Session/IndexAction.php b/sources/AppBundle/Controller/Admin/Event/Session/IndexAction.php index 941258d7f..0b9014136 100644 --- a/sources/AppBundle/Controller/Admin/Event/Session/IndexAction.php +++ b/sources/AppBundle/Controller/Admin/Event/Session/IndexAction.php @@ -17,7 +17,9 @@ use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_EVENT_READER')] final class IndexAction extends AbstractController { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Event/SpeakerInfosAction.php b/sources/AppBundle/Controller/Admin/Event/SpeakerInfosAction.php index de6b65a53..0152ceb46 100644 --- a/sources/AppBundle/Controller/Admin/Event/SpeakerInfosAction.php +++ b/sources/AppBundle/Controller/Admin/Event/SpeakerInfosAction.php @@ -10,7 +10,9 @@ use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_EVENT_WRITER')] class SpeakerInfosAction { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Event/SpeakersExpensesAction.php b/sources/AppBundle/Controller/Admin/Event/SpeakersExpensesAction.php index 1ee63f8e4..29ebcca57 100644 --- a/sources/AppBundle/Controller/Admin/Event/SpeakersExpensesAction.php +++ b/sources/AppBundle/Controller/Admin/Event/SpeakersExpensesAction.php @@ -10,7 +10,9 @@ use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_EVENT_READER')] class SpeakersExpensesAction extends AbstractController { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Event/SpeakersManagementAction.php b/sources/AppBundle/Controller/Admin/Event/SpeakersManagementAction.php index a228eb26e..dacdc939c 100644 --- a/sources/AppBundle/Controller/Admin/Event/SpeakersManagementAction.php +++ b/sources/AppBundle/Controller/Admin/Event/SpeakersManagementAction.php @@ -9,7 +9,9 @@ use AppBundle\SpeakerInfos\SpeakersExpensesStorage; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_EVENT_READER')] class SpeakersManagementAction extends AbstractController { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Event/SpecialPriceAction.php b/sources/AppBundle/Controller/Admin/Event/SpecialPriceAction.php index 82af4de56..13f974a6c 100644 --- a/sources/AppBundle/Controller/Admin/Event/SpecialPriceAction.php +++ b/sources/AppBundle/Controller/Admin/Event/SpecialPriceAction.php @@ -13,7 +13,9 @@ use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_EVENT_WRITER')] class SpecialPriceAction extends AbstractController { public const int EXTEND_DAYS = 3; // jours diff --git a/sources/AppBundle/Controller/Admin/Event/SponsorTicketAction.php b/sources/AppBundle/Controller/Admin/Event/SponsorTicketAction.php index 9a1261aa4..2bf20eaf0 100644 --- a/sources/AppBundle/Controller/Admin/Event/SponsorTicketAction.php +++ b/sources/AppBundle/Controller/Admin/Event/SponsorTicketAction.php @@ -14,7 +14,9 @@ use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_EVENT_WRITER')] class SponsorTicketAction extends AbstractController { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Event/StatsAction.php b/sources/AppBundle/Controller/Admin/Event/StatsAction.php index f9a9ee9d1..0810af399 100644 --- a/sources/AppBundle/Controller/Admin/Event/StatsAction.php +++ b/sources/AppBundle/Controller/Admin/Event/StatsAction.php @@ -12,7 +12,9 @@ use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_EVENT_READER')] class StatsAction extends AbstractController { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Event/Ticket/AddAction.php b/sources/AppBundle/Controller/Admin/Event/Ticket/AddAction.php index 6257438d3..a47d3243e 100644 --- a/sources/AppBundle/Controller/Admin/Event/Ticket/AddAction.php +++ b/sources/AppBundle/Controller/Admin/Event/Ticket/AddAction.php @@ -18,7 +18,9 @@ use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_EVENT_WRITER')] final class AddAction extends AbstractController { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Event/Ticket/DeleteAction.php b/sources/AppBundle/Controller/Admin/Event/Ticket/DeleteAction.php index 5b60f430e..82b996fe6 100644 --- a/sources/AppBundle/Controller/Admin/Event/Ticket/DeleteAction.php +++ b/sources/AppBundle/Controller/Admin/Event/Ticket/DeleteAction.php @@ -11,7 +11,9 @@ use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_EVENT_WRITER')] final class DeleteAction extends AbstractController { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Event/Ticket/EditAction.php b/sources/AppBundle/Controller/Admin/Event/Ticket/EditAction.php index ad927fac1..2c027f280 100644 --- a/sources/AppBundle/Controller/Admin/Event/Ticket/EditAction.php +++ b/sources/AppBundle/Controller/Admin/Event/Ticket/EditAction.php @@ -16,7 +16,9 @@ use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_EVENT_WRITER')] final class EditAction extends AbstractController { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Event/Ticket/IndexAction.php b/sources/AppBundle/Controller/Admin/Event/Ticket/IndexAction.php index ee9cc6de6..edfa93829 100644 --- a/sources/AppBundle/Controller/Admin/Event/Ticket/IndexAction.php +++ b/sources/AppBundle/Controller/Admin/Event/Ticket/IndexAction.php @@ -23,7 +23,9 @@ use Symfony\Component\Form\FormInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_EVENT_READER')] class IndexAction extends AbstractController { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Event/VotesListeAction.php b/sources/AppBundle/Controller/Admin/Event/VotesListeAction.php index e1ca856ae..08a687dd7 100644 --- a/sources/AppBundle/Controller/Admin/Event/VotesListeAction.php +++ b/sources/AppBundle/Controller/Admin/Event/VotesListeAction.php @@ -9,7 +9,9 @@ use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_EVENT_READER')] final class VotesListeAction extends AbstractController { public function __construct(private readonly VoteRepository $voteRepository) {} diff --git a/sources/AppBundle/Controller/Admin/GetMenuAction.php b/sources/AppBundle/Controller/Admin/GetMenuAction.php index f4b20bb0d..5e6fa2ba4 100644 --- a/sources/AppBundle/Controller/Admin/GetMenuAction.php +++ b/sources/AppBundle/Controller/Admin/GetMenuAction.php @@ -9,7 +9,9 @@ use Symfony\Component\HttpFoundation\Response; use Twig\Environment; use Webmozart\Assert\Assert; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_ADMIN')] class GetMenuAction { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/GithubUser/GithubUserAddAction.php b/sources/AppBundle/Controller/Admin/GithubUser/GithubUserAddAction.php index 9e151a7c0..143c6afcc 100644 --- a/sources/AppBundle/Controller/Admin/GithubUser/GithubUserAddAction.php +++ b/sources/AppBundle/Controller/Admin/GithubUser/GithubUserAddAction.php @@ -11,7 +11,9 @@ use AppBundle\Github\GithubClient; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_EVENT_WRITER')] class GithubUserAddAction extends AbstractController { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/GithubUser/GithubUserListAction.php b/sources/AppBundle/Controller/Admin/GithubUser/GithubUserListAction.php index 4b915f977..26ab1cc1e 100644 --- a/sources/AppBundle/Controller/Admin/GithubUser/GithubUserListAction.php +++ b/sources/AppBundle/Controller/Admin/GithubUser/GithubUserListAction.php @@ -8,7 +8,9 @@ use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Twig\Environment; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_EVENT_READER')] class GithubUserListAction { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/HealthcheckController.php b/sources/AppBundle/Controller/Admin/HealthcheckController.php index f519f876a..eb4942b04 100644 --- a/sources/AppBundle/Controller/Admin/HealthcheckController.php +++ b/sources/AppBundle/Controller/Admin/HealthcheckController.php @@ -10,7 +10,9 @@ use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Kernel; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_SUPER_ADMIN')] class HealthcheckController extends AbstractController { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/HomeAction.php b/sources/AppBundle/Controller/Admin/HomeAction.php index 9cfea213c..650bbb72d 100644 --- a/sources/AppBundle/Controller/Admin/HomeAction.php +++ b/sources/AppBundle/Controller/Admin/HomeAction.php @@ -17,7 +17,9 @@ use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Generator\UrlGeneratorInterface; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_ADMIN')] class HomeAction extends AbstractController { public function __construct( @@ -37,7 +39,7 @@ public function __invoke(): Response { $nextevents = $this->eventRepository->getNextEvents(); $cards = []; - if ($this->isGranted('ROLE_FORUM') && $nextevents) { + if ($this->isGranted('ROLE_EVENT_READER') && $nextevents) { $cfp = [ 'title' => 'CFP', 'subtitle' => 'Talks et speakers', @@ -100,13 +102,19 @@ public function __invoke(): Response } } - if ($this->isGranted(('ROLE_ADMIN'))) { + // La liste des abonnés à la veille est une page réservée au super admin + if ($this->isGranted('ROLE_SUPER_ADMIN')) { $cards[] = [ 'title' => 'Abonnements à la veille', 'statistics' => ['Abonnements' => $this->newsletterInscriptionRepository->countAllSubscriptionsWithUser()], 'url' => $this->generateUrl('admin_techletter_members'), ]; + } + + // Statistiques partagées par les cartes Membres et Assemblée générale, calculées une seule fois + $statistics = null; + if ($this->isGranted('ROLE_MEMBRES_READER')) { $statistics = $this->statisticsComputer->computeStatistics(); $cards[] = [ 'title' => 'Membres', @@ -120,22 +128,23 @@ public function __invoke(): Response ], 'url' => $this->generateUrl('admin_members_reporting'), ]; + } + if ($this->isGranted('ROLE_AG_READER') && $this->assembleGeneraleRepository->hasPlanned()) { + $statistics ??= $this->statisticsComputer->computeStatistics(); $latestDate = $this->assembleGeneraleRepository->getLatestDate(); - if ($this->assembleGeneraleRepository->hasPlanned()) { - $cards[] = [ - 'title' => 'Assemblée générale', - 'statistics' => [ - 'Votes et pouvoirs' => $this->presenceRepository->countAttendeesAndPowers($latestDate), - 'Présences' => $this->presenceRepository->countAttendees($latestDate), - ], - 'main_statistic' => [ - 'label' => 'Quorum', - 'value' => $this->presenceRepository->obtenirEcartQuorum($latestDate, $statistics->usersCount), - ], - 'url' => $this->generateUrl('admin_members_general_meeting'), - ]; - } + $cards[] = [ + 'title' => 'Assemblée générale', + 'statistics' => [ + 'Votes et pouvoirs' => $this->presenceRepository->countAttendeesAndPowers($latestDate), + 'Présences' => $this->presenceRepository->countAttendees($latestDate), + ], + 'main_statistic' => [ + 'label' => 'Quorum', + 'value' => $this->presenceRepository->obtenirEcartQuorum($latestDate, $statistics->usersCount), + ], + 'url' => $this->generateUrl('admin_members_general_meeting'), + ]; } return $this->render('admin/home.html.twig', [ diff --git a/sources/AppBundle/Controller/Admin/Members/BadgeListAction.php b/sources/AppBundle/Controller/Admin/Members/BadgeListAction.php index fb93c22a5..4f4b7fa6b 100644 --- a/sources/AppBundle/Controller/Admin/Members/BadgeListAction.php +++ b/sources/AppBundle/Controller/Admin/Members/BadgeListAction.php @@ -9,7 +9,9 @@ use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Twig\Environment; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_MEMBRES_READER')] class BadgeListAction { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Members/BadgeNewAction.php b/sources/AppBundle/Controller/Admin/Members/BadgeNewAction.php index f85101093..2ecc0278b 100644 --- a/sources/AppBundle/Controller/Admin/Members/BadgeNewAction.php +++ b/sources/AppBundle/Controller/Admin/Members/BadgeNewAction.php @@ -12,7 +12,9 @@ use Symfony\Component\Filesystem\Filesystem; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_MEMBRES_WRITER')] final class BadgeNewAction extends AbstractController { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Members/CompanyAction.php b/sources/AppBundle/Controller/Admin/Members/CompanyAction.php index 02e17ce6b..c098bd16d 100644 --- a/sources/AppBundle/Controller/Admin/Members/CompanyAction.php +++ b/sources/AppBundle/Controller/Admin/Members/CompanyAction.php @@ -12,7 +12,9 @@ use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_MEMBRES_WRITER')] class CompanyAction extends AbstractController { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Members/CompanyDeleteAction.php b/sources/AppBundle/Controller/Admin/Members/CompanyDeleteAction.php index a0482b982..972ce932a 100644 --- a/sources/AppBundle/Controller/Admin/Members/CompanyDeleteAction.php +++ b/sources/AppBundle/Controller/Admin/Members/CompanyDeleteAction.php @@ -11,7 +11,9 @@ use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_MEMBRES_WRITER')] class CompanyDeleteAction extends AbstractController { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Members/CompanyListAction.php b/sources/AppBundle/Controller/Admin/Members/CompanyListAction.php index a42a1948d..c729b273b 100644 --- a/sources/AppBundle/Controller/Admin/Members/CompanyListAction.php +++ b/sources/AppBundle/Controller/Admin/Members/CompanyListAction.php @@ -8,7 +8,9 @@ use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Twig\Environment; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_MEMBRES_READER')] class CompanyListAction { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Members/GeneralMeeting/EditAction.php b/sources/AppBundle/Controller/Admin/Members/GeneralMeeting/EditAction.php index 6306aef43..cfcba2df6 100644 --- a/sources/AppBundle/Controller/Admin/Members/GeneralMeeting/EditAction.php +++ b/sources/AppBundle/Controller/Admin/Members/GeneralMeeting/EditAction.php @@ -10,7 +10,9 @@ use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_AG_WRITER')] class EditAction extends AbstractController { public function __construct(private readonly AssembleeGeneraleRepository $assembleGeneraleRepository) {} diff --git a/sources/AppBundle/Controller/Admin/Members/GeneralMeeting/ListAction.php b/sources/AppBundle/Controller/Admin/Members/GeneralMeeting/ListAction.php index cb96a4d02..670a55864 100644 --- a/sources/AppBundle/Controller/Admin/Members/GeneralMeeting/ListAction.php +++ b/sources/AppBundle/Controller/Admin/Members/GeneralMeeting/ListAction.php @@ -10,7 +10,9 @@ use Symfony\Component\HttpFoundation\Response; use Twig\Environment; use Webmozart\Assert\Assert; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_AG_READER')] class ListAction { public const array VALID_SORTS = ['nom', 'date_consultation', 'presence', 'personnes_avec_pouvoir_nom']; diff --git a/sources/AppBundle/Controller/Admin/Members/GeneralMeeting/ListingAction.php b/sources/AppBundle/Controller/Admin/Members/GeneralMeeting/ListingAction.php index f5fc20b6e..8d14b00b7 100644 --- a/sources/AppBundle/Controller/Admin/Members/GeneralMeeting/ListingAction.php +++ b/sources/AppBundle/Controller/Admin/Members/GeneralMeeting/ListingAction.php @@ -11,7 +11,9 @@ use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\ResponseHeaderBag; use Webmozart\Assert\Assert; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_AG_READER')] class ListingAction { public function __construct(private readonly PresenceRepository $presenceRepository) {} diff --git a/sources/AppBundle/Controller/Admin/Members/GeneralMeeting/PrepareAction.php b/sources/AppBundle/Controller/Admin/Members/GeneralMeeting/PrepareAction.php index 42d077304..c77c68b47 100644 --- a/sources/AppBundle/Controller/Admin/Members/GeneralMeeting/PrepareAction.php +++ b/sources/AppBundle/Controller/Admin/Members/GeneralMeeting/PrepareAction.php @@ -12,7 +12,9 @@ use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_AG_WRITER')] class PrepareAction extends AbstractController { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Members/GeneralMeeting/ReportsAction.php b/sources/AppBundle/Controller/Admin/Members/GeneralMeeting/ReportsAction.php index f4e8112b5..63a10d1ea 100644 --- a/sources/AppBundle/Controller/Admin/Members/GeneralMeeting/ReportsAction.php +++ b/sources/AppBundle/Controller/Admin/Members/GeneralMeeting/ReportsAction.php @@ -14,7 +14,9 @@ use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Validator\Constraints\File; use Symfony\Component\Validator\Constraints\NotBlank; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_AG_WRITER')] class ReportsAction extends AbstractController { public function __invoke(Request $request): Response diff --git a/sources/AppBundle/Controller/Admin/Members/GeneralMeetingQuestion/AddAction.php b/sources/AppBundle/Controller/Admin/Members/GeneralMeetingQuestion/AddAction.php index 948b831e0..f8fd3c884 100644 --- a/sources/AppBundle/Controller/Admin/Members/GeneralMeetingQuestion/AddAction.php +++ b/sources/AppBundle/Controller/Admin/Members/GeneralMeetingQuestion/AddAction.php @@ -11,7 +11,9 @@ use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_AG_WRITER')] class AddAction extends AbstractController { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Members/GeneralMeetingQuestion/DeleteAction.php b/sources/AppBundle/Controller/Admin/Members/GeneralMeetingQuestion/DeleteAction.php index eb090d558..761b1405e 100644 --- a/sources/AppBundle/Controller/Admin/Members/GeneralMeetingQuestion/DeleteAction.php +++ b/sources/AppBundle/Controller/Admin/Members/GeneralMeetingQuestion/DeleteAction.php @@ -8,7 +8,9 @@ use AppBundle\AssembleeGenerale\Entity\Repository\VoteRepository; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\RedirectResponse; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_AG_WRITER')] class DeleteAction extends AbstractController { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Members/GeneralMeetingQuestion/EditAction.php b/sources/AppBundle/Controller/Admin/Members/GeneralMeetingQuestion/EditAction.php index 83903fb6a..c5bb4009c 100644 --- a/sources/AppBundle/Controller/Admin/Members/GeneralMeetingQuestion/EditAction.php +++ b/sources/AppBundle/Controller/Admin/Members/GeneralMeetingQuestion/EditAction.php @@ -9,7 +9,9 @@ use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_AG_WRITER')] class EditAction extends AbstractController { public function __construct(private readonly QuestionRepository $questionRepository) {} diff --git a/sources/AppBundle/Controller/Admin/Members/GeneralMeetingVote/CloseAction.php b/sources/AppBundle/Controller/Admin/Members/GeneralMeetingVote/CloseAction.php index 72d7bb137..6f6a0bfe4 100644 --- a/sources/AppBundle/Controller/Admin/Members/GeneralMeetingVote/CloseAction.php +++ b/sources/AppBundle/Controller/Admin/Members/GeneralMeetingVote/CloseAction.php @@ -8,7 +8,9 @@ use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_AG_WRITER')] class CloseAction extends AbstractController { public function __construct(private readonly QuestionRepository $questionRepository) {} diff --git a/sources/AppBundle/Controller/Admin/Members/GeneralMeetingVote/ListAction.php b/sources/AppBundle/Controller/Admin/Members/GeneralMeetingVote/ListAction.php index dd7646173..fa4bf5bae 100644 --- a/sources/AppBundle/Controller/Admin/Members/GeneralMeetingVote/ListAction.php +++ b/sources/AppBundle/Controller/Admin/Members/GeneralMeetingVote/ListAction.php @@ -11,7 +11,9 @@ use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Twig\Environment; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_AG_WRITER')] class ListAction { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Members/GeneralMeetingVote/OpenAction.php b/sources/AppBundle/Controller/Admin/Members/GeneralMeetingVote/OpenAction.php index adbd02655..b52e3d7e5 100644 --- a/sources/AppBundle/Controller/Admin/Members/GeneralMeetingVote/OpenAction.php +++ b/sources/AppBundle/Controller/Admin/Members/GeneralMeetingVote/OpenAction.php @@ -8,7 +8,9 @@ use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_AG_WRITER')] class OpenAction extends AbstractController { public function __construct(private readonly QuestionRepository $questionRepository) {} diff --git a/sources/AppBundle/Controller/MembershipAdmin/ReportingAction.php b/sources/AppBundle/Controller/Admin/Members/ReportingAction.php similarity index 90% rename from sources/AppBundle/Controller/MembershipAdmin/ReportingAction.php rename to sources/AppBundle/Controller/Admin/Members/ReportingAction.php index 569aa0a1b..0a10c5a40 100644 --- a/sources/AppBundle/Controller/MembershipAdmin/ReportingAction.php +++ b/sources/AppBundle/Controller/Admin/Members/ReportingAction.php @@ -2,13 +2,15 @@ declare(strict_types=1); -namespace AppBundle\Controller\MembershipAdmin; +namespace AppBundle\Controller\Admin\Members; use AppBundle\Association\UserMembership\StatisticsComputer; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Twig\Environment; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_MEMBRES_READER')] class ReportingAction { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Members/UserAddAction.php b/sources/AppBundle/Controller/Admin/Members/UserAddAction.php index 17a5cb6a6..5110e8f62 100644 --- a/sources/AppBundle/Controller/Admin/Members/UserAddAction.php +++ b/sources/AppBundle/Controller/Admin/Members/UserAddAction.php @@ -13,7 +13,9 @@ use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_MEMBRES_WRITER')] class UserAddAction extends AbstractController { public function __construct( @@ -28,7 +30,11 @@ public function __invoke(Request $request): Response $user = new User(); $user->setRoles([]); - $form = $this->createForm(UserEditType::class, $user); + $form = $this->createForm(UserEditType::class, $user, [ + 'can_grant_super_admin' => $this->isGranted('ROLE_SUPER_ADMIN'), + // Attribuer des droits sur les modules revient à étendre ses propres accès : réservé au super admin + 'can_edit_modules' => $this->isGranted('ROLE_SUPER_ADMIN'), + ]); $form->handleRequest($request); if ($form->isSubmitted() && $form->isValid()) { if (!$user->getCompanyId()) { diff --git a/sources/AppBundle/Controller/Admin/Members/UserBadgeDeleteAction.php b/sources/AppBundle/Controller/Admin/Members/UserBadgeDeleteAction.php index ea7ae971d..3f4e9a30c 100644 --- a/sources/AppBundle/Controller/Admin/Members/UserBadgeDeleteAction.php +++ b/sources/AppBundle/Controller/Admin/Members/UserBadgeDeleteAction.php @@ -11,7 +11,9 @@ use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_MEMBRES_WRITER')] class UserBadgeDeleteAction { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Members/UserBadgeNewAction.php b/sources/AppBundle/Controller/Admin/Members/UserBadgeNewAction.php index c9ebb9834..3d1cb96cc 100644 --- a/sources/AppBundle/Controller/Admin/Members/UserBadgeNewAction.php +++ b/sources/AppBundle/Controller/Admin/Members/UserBadgeNewAction.php @@ -13,7 +13,9 @@ use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_MEMBRES_WRITER')] class UserBadgeNewAction { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Members/UserDeleteAction.php b/sources/AppBundle/Controller/Admin/Members/UserDeleteAction.php index b84c3615a..b45cc66f0 100644 --- a/sources/AppBundle/Controller/Admin/Members/UserDeleteAction.php +++ b/sources/AppBundle/Controller/Admin/Members/UserDeleteAction.php @@ -6,12 +6,15 @@ use AppBundle\Association\Model\Repository\UserRepository; use AppBundle\AuditLog\Audit; +use AppBundle\Security\ManageUserVoter; use Exception; use InvalidArgumentException; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_MEMBRES_WRITER')] class UserDeleteAction extends AbstractController { public function __construct( @@ -25,6 +28,7 @@ public function __invoke(Request $request): RedirectResponse if (null === $user) { throw $this->createNotFoundException('Utilisateur non trouvé'); } + $this->denyAccessUnlessGranted(ManageUserVoter::MANAGE_USER, $user); try { $this->userRepository->remove($user); diff --git a/sources/AppBundle/Controller/Admin/Members/UserEditAction.php b/sources/AppBundle/Controller/Admin/Members/UserEditAction.php index a4e8f15dd..8c76b2e34 100644 --- a/sources/AppBundle/Controller/Admin/Members/UserEditAction.php +++ b/sources/AppBundle/Controller/Admin/Members/UserEditAction.php @@ -8,12 +8,15 @@ use AppBundle\Association\Form\UserEditType; use AppBundle\Association\Model\Repository\UserRepository; use AppBundle\AuditLog\Audit; +use AppBundle\Security\ManageUserVoter; use AppBundle\Event\Entity\Repository\UserBadgeRepository; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_MEMBRES_WRITER')] class UserEditAction extends AbstractController { public function __construct( @@ -30,11 +33,19 @@ public function __invoke(Request $request): Response $this->addFlash('error', 'Utilisateur non trouvé'); return $this->redirectToRoute('admin_members_user_list'); } - $form = $this->createForm(UserEditType::class, $user); + $this->denyAccessUnlessGranted(ManageUserVoter::MANAGE_USER, $user); + + $form = $this->createForm(UserEditType::class, $user, [ + 'can_grant_super_admin' => $this->isGranted('ROLE_SUPER_ADMIN'), + // Changer le mot de passe d'un tiers permet de prendre son compte : réservé au super admin + 'can_edit_password' => $this->isGranted('ROLE_SUPER_ADMIN'), + // Attribuer des droits sur les modules revient à étendre ses propres accès : réservé au super admin + 'can_edit_modules' => $this->isGranted('ROLE_SUPER_ADMIN'), + ]); $form->handleRequest($request); if ($form->isSubmitted() && $form->isValid()) { // Save password if not empty - $newPassword = $form->get('plainPassword')->getViewData()['first']; + $newPassword = $form->has('plainPassword') ? $form->get('plainPassword')->getViewData()['first'] : null; if ($newPassword) { $user->setPassword($this->passwordHasher->hashPassword($user, $newPassword)); } diff --git a/sources/AppBundle/Controller/Admin/Members/UserExportAction.php b/sources/AppBundle/Controller/Admin/Members/UserExportAction.php index c30216dba..f4ddb550d 100644 --- a/sources/AppBundle/Controller/Admin/Members/UserExportAction.php +++ b/sources/AppBundle/Controller/Admin/Members/UserExportAction.php @@ -9,7 +9,9 @@ use Symfony\Component\HttpFoundation\BinaryFileResponse; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\ResponseHeaderBag; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_MEMBRES_READER')] class UserExportAction { public function __construct(private readonly UserRepository $userRepository) {} diff --git a/sources/AppBundle/Controller/Admin/Members/UserListAction.php b/sources/AppBundle/Controller/Admin/Members/UserListAction.php index 045eef848..06af4636d 100644 --- a/sources/AppBundle/Controller/Admin/Members/UserListAction.php +++ b/sources/AppBundle/Controller/Admin/Members/UserListAction.php @@ -9,7 +9,9 @@ use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Twig\Environment; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_MEMBRES_READER')] class UserListAction { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Members/UserResetPasswordAction.php b/sources/AppBundle/Controller/Admin/Members/UserResetPasswordAction.php index 641415316..f9c6409ad 100644 --- a/sources/AppBundle/Controller/Admin/Members/UserResetPasswordAction.php +++ b/sources/AppBundle/Controller/Admin/Members/UserResetPasswordAction.php @@ -7,10 +7,13 @@ use AppBundle\Association\Model\Repository\UserRepository; use AppBundle\Association\PasswordReset\PasswordResetService; use AppBundle\AuditLog\Audit; +use AppBundle\Security\ManageUserVoter; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_MEMBRES_WRITER')] class UserResetPasswordAction extends AbstractController { public function __construct( @@ -25,6 +28,7 @@ public function __invoke(Request $request): RedirectResponse if (null === $user) { throw $this->createNotFoundException('Utilisateur non trouvé'); } + $this->denyAccessUnlessGranted(ManageUserVoter::MANAGE_USER, $user); // Mailer::send() avale les exceptions et renvoie false : c'est la valeur de // retour, et non une exception, qui signale l'échec d'envoi. diff --git a/sources/AppBundle/Controller/Admin/Members/UserSendWelcomeAction.php b/sources/AppBundle/Controller/Admin/Members/UserSendWelcomeAction.php index 63119c55d..bcb0fabbd 100644 --- a/sources/AppBundle/Controller/Admin/Members/UserSendWelcomeAction.php +++ b/sources/AppBundle/Controller/Admin/Members/UserSendWelcomeAction.php @@ -7,11 +7,14 @@ use AppBundle\Association\Model\Repository\UserRepository; use AppBundle\Association\UserMembership\UserService; use AppBundle\AuditLog\Audit; +use AppBundle\Security\ManageUserVoter; use Exception; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_MEMBRES_WRITER')] class UserSendWelcomeAction extends AbstractController { public function __construct( @@ -26,6 +29,7 @@ public function __invoke(Request $request): RedirectResponse if (null === $user) { throw $this->createNotFoundException('Personne physique non trouvée'); } + $this->denyAccessUnlessGranted(ManageUserVoter::MANAGE_USER, $user); try { $this->userService->sendWelcomeEmail($user); $this->audit->log('Envoi d\'un message de bienvenue à la personne physique ' . $user->getId()); diff --git a/sources/AppBundle/Controller/Admin/Membership/ReminderLogAction.php b/sources/AppBundle/Controller/Admin/Membership/ReminderLogAction.php index 4206a5b88..a0d73447d 100644 --- a/sources/AppBundle/Controller/Admin/Membership/ReminderLogAction.php +++ b/sources/AppBundle/Controller/Admin/Membership/ReminderLogAction.php @@ -8,7 +8,9 @@ use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Twig\Environment; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_MEMBRES_READER')] class ReminderLogAction { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Planete/FeedAddAction.php b/sources/AppBundle/Controller/Admin/Planete/FeedAddAction.php index a09813f27..f504324b3 100644 --- a/sources/AppBundle/Controller/Admin/Planete/FeedAddAction.php +++ b/sources/AppBundle/Controller/Admin/Planete/FeedAddAction.php @@ -13,7 +13,9 @@ use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_PLANETE_WRITER')] class FeedAddAction extends AbstractController { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Planete/FeedArticleListAction.php b/sources/AppBundle/Controller/Admin/Planete/FeedArticleListAction.php index 82799b7c7..b927c2ae6 100644 --- a/sources/AppBundle/Controller/Admin/Planete/FeedArticleListAction.php +++ b/sources/AppBundle/Controller/Admin/Planete/FeedArticleListAction.php @@ -8,7 +8,9 @@ use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Twig\Environment; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_PLANETE_READER')] final readonly class FeedArticleListAction { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Planete/FeedDeleteAction.php b/sources/AppBundle/Controller/Admin/Planete/FeedDeleteAction.php index 34bc93fd7..e9563d08e 100644 --- a/sources/AppBundle/Controller/Admin/Planete/FeedDeleteAction.php +++ b/sources/AppBundle/Controller/Admin/Planete/FeedDeleteAction.php @@ -9,7 +9,9 @@ use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_PLANETE_WRITER')] class FeedDeleteAction extends AbstractController { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Planete/FeedEditAction.php b/sources/AppBundle/Controller/Admin/Planete/FeedEditAction.php index 7e17c9920..11fce7a3b 100644 --- a/sources/AppBundle/Controller/Admin/Planete/FeedEditAction.php +++ b/sources/AppBundle/Controller/Admin/Planete/FeedEditAction.php @@ -11,7 +11,9 @@ use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_PLANETE_WRITER')] class FeedEditAction extends AbstractController { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Planete/FeedListAction.php b/sources/AppBundle/Controller/Admin/Planete/FeedListAction.php index 6efc79802..1758fcaa2 100644 --- a/sources/AppBundle/Controller/Admin/Planete/FeedListAction.php +++ b/sources/AppBundle/Controller/Admin/Planete/FeedListAction.php @@ -11,7 +11,9 @@ use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Twig\Environment; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_PLANETE_READER')] final readonly class FeedListAction { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Site/AddRubriqueAction.php b/sources/AppBundle/Controller/Admin/Site/AddRubriqueAction.php index 3a3948bbf..ecd1a10a5 100644 --- a/sources/AppBundle/Controller/Admin/Site/AddRubriqueAction.php +++ b/sources/AppBundle/Controller/Admin/Site/AddRubriqueAction.php @@ -12,7 +12,9 @@ use Symfony\Component\DependencyInjection\Attribute\Autowire; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_SITE_WRITER')] final class AddRubriqueAction extends AbstractController { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Site/Article/AddArticleAction.php b/sources/AppBundle/Controller/Admin/Site/Article/AddArticleAction.php index f8b85423e..3a0cda7fa 100644 --- a/sources/AppBundle/Controller/Admin/Site/Article/AddArticleAction.php +++ b/sources/AppBundle/Controller/Admin/Site/Article/AddArticleAction.php @@ -14,7 +14,9 @@ use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\String\Slugger\AsciiSlugger; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_SITE_WRITER')] final class AddArticleAction extends AbstractController { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Site/Article/DeleteArticleAction.php b/sources/AppBundle/Controller/Admin/Site/Article/DeleteArticleAction.php index b44ee6769..015e0fd45 100644 --- a/sources/AppBundle/Controller/Admin/Site/Article/DeleteArticleAction.php +++ b/sources/AppBundle/Controller/Admin/Site/Article/DeleteArticleAction.php @@ -11,7 +11,9 @@ use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\Security\Csrf\CsrfToken; use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_SITE_WRITER')] class DeleteArticleAction extends AbstractController { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Site/Article/EditArticleAction.php b/sources/AppBundle/Controller/Admin/Site/Article/EditArticleAction.php index bea39e15e..ee9fc9f9c 100644 --- a/sources/AppBundle/Controller/Admin/Site/Article/EditArticleAction.php +++ b/sources/AppBundle/Controller/Admin/Site/Article/EditArticleAction.php @@ -12,7 +12,9 @@ use Symfony\Component\HttpFoundation\File\UploadedFile; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_SITE_WRITER')] final class EditArticleAction extends AbstractController { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Site/Article/ListArticlesAction.php b/sources/AppBundle/Controller/Admin/Site/Article/ListArticlesAction.php index f8248cf8b..25115cebd 100644 --- a/sources/AppBundle/Controller/Admin/Site/Article/ListArticlesAction.php +++ b/sources/AppBundle/Controller/Admin/Site/Article/ListArticlesAction.php @@ -8,7 +8,9 @@ use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Twig\Environment; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_SITE_READER')] final readonly class ListArticlesAction { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Site/DeleteRubriqueAction.php b/sources/AppBundle/Controller/Admin/Site/DeleteRubriqueAction.php index 18cc57d4b..365888ff6 100644 --- a/sources/AppBundle/Controller/Admin/Site/DeleteRubriqueAction.php +++ b/sources/AppBundle/Controller/Admin/Site/DeleteRubriqueAction.php @@ -10,7 +10,9 @@ use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\Security\Csrf\CsrfToken; use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_SITE_WRITER')] class DeleteRubriqueAction extends AbstractController { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Site/EditRubriqueAction.php b/sources/AppBundle/Controller/Admin/Site/EditRubriqueAction.php index d7ff6089e..7777d946f 100644 --- a/sources/AppBundle/Controller/Admin/Site/EditRubriqueAction.php +++ b/sources/AppBundle/Controller/Admin/Site/EditRubriqueAction.php @@ -11,7 +11,9 @@ use Symfony\Component\DependencyInjection\Attribute\Autowire; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_SITE_WRITER')] final class EditRubriqueAction extends AbstractController { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Site/Feuille/AddFeuilleAction.php b/sources/AppBundle/Controller/Admin/Site/Feuille/AddFeuilleAction.php index d5772b108..ac1d3c01c 100644 --- a/sources/AppBundle/Controller/Admin/Site/Feuille/AddFeuilleAction.php +++ b/sources/AppBundle/Controller/Admin/Site/Feuille/AddFeuilleAction.php @@ -13,7 +13,9 @@ use Symfony\Component\HttpFoundation\File\UploadedFile; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_SITE_WRITER')] final class AddFeuilleAction extends AbstractController { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Site/Feuille/DeleteFeuilleAction.php b/sources/AppBundle/Controller/Admin/Site/Feuille/DeleteFeuilleAction.php index fd43ae1b7..651681b04 100644 --- a/sources/AppBundle/Controller/Admin/Site/Feuille/DeleteFeuilleAction.php +++ b/sources/AppBundle/Controller/Admin/Site/Feuille/DeleteFeuilleAction.php @@ -10,7 +10,9 @@ use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\Security\Csrf\CsrfToken; use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_SITE_WRITER')] final class DeleteFeuilleAction extends AbstractController { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Site/Feuille/EditFeuilleAction.php b/sources/AppBundle/Controller/Admin/Site/Feuille/EditFeuilleAction.php index 9eabcedb3..59c0abcd4 100644 --- a/sources/AppBundle/Controller/Admin/Site/Feuille/EditFeuilleAction.php +++ b/sources/AppBundle/Controller/Admin/Site/Feuille/EditFeuilleAction.php @@ -12,7 +12,9 @@ use Symfony\Component\HttpFoundation\File\UploadedFile; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_SITE_WRITER')] final class EditFeuilleAction extends AbstractController { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Site/Feuille/ListFeuillesAction.php b/sources/AppBundle/Controller/Admin/Site/Feuille/ListFeuillesAction.php index bc2f3de3d..48e6345fe 100644 --- a/sources/AppBundle/Controller/Admin/Site/Feuille/ListFeuillesAction.php +++ b/sources/AppBundle/Controller/Admin/Site/Feuille/ListFeuillesAction.php @@ -8,7 +8,9 @@ use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Twig\Environment; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_SITE_READER')] final readonly class ListFeuillesAction { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Site/ListRubriquesAction.php b/sources/AppBundle/Controller/Admin/Site/ListRubriquesAction.php index 4b36d4a51..0a53aa9e1 100644 --- a/sources/AppBundle/Controller/Admin/Site/ListRubriquesAction.php +++ b/sources/AppBundle/Controller/Admin/Site/ListRubriquesAction.php @@ -8,7 +8,9 @@ use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Twig\Environment; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_SITE_READER')] class ListRubriquesAction { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/SlackMembers/CheckMembersAction.php b/sources/AppBundle/Controller/Admin/SlackMembers/CheckMembersAction.php index 33ca08645..dca0fc8ae 100644 --- a/sources/AppBundle/Controller/Admin/SlackMembers/CheckMembersAction.php +++ b/sources/AppBundle/Controller/Admin/SlackMembers/CheckMembersAction.php @@ -7,7 +7,9 @@ use AppBundle\Slack\UsersChecker; use Symfony\Component\HttpFoundation\Response; use Twig\Environment; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_MEMBRES_READER')] class CheckMembersAction { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Speaker/ExportAction.php b/sources/AppBundle/Controller/Admin/Speaker/ExportAction.php index 614149e4f..d99c96f93 100644 --- a/sources/AppBundle/Controller/Admin/Speaker/ExportAction.php +++ b/sources/AppBundle/Controller/Admin/Speaker/ExportAction.php @@ -11,7 +11,9 @@ use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\ResponseHeaderBag; use Webmozart\Assert\Assert; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_EVENT_READER')] class ExportAction { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Speaker/SpeakerAddAction.php b/sources/AppBundle/Controller/Admin/Speaker/SpeakerAddAction.php index 121e4c933..380bc141d 100644 --- a/sources/AppBundle/Controller/Admin/Speaker/SpeakerAddAction.php +++ b/sources/AppBundle/Controller/Admin/Speaker/SpeakerAddAction.php @@ -15,7 +15,9 @@ use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Webmozart\Assert\Assert; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_EVENT_WRITER')] class SpeakerAddAction extends AbstractController { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Speaker/SpeakerDeleteAction.php b/sources/AppBundle/Controller/Admin/Speaker/SpeakerDeleteAction.php index 099c2e007..d133351a7 100644 --- a/sources/AppBundle/Controller/Admin/Speaker/SpeakerDeleteAction.php +++ b/sources/AppBundle/Controller/Admin/Speaker/SpeakerDeleteAction.php @@ -11,7 +11,9 @@ use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_EVENT_WRITER')] class SpeakerDeleteAction extends AbstractController { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Speaker/SpeakerEditAction.php b/sources/AppBundle/Controller/Admin/Speaker/SpeakerEditAction.php index 7b69a3b03..715891ed7 100644 --- a/sources/AppBundle/Controller/Admin/Speaker/SpeakerEditAction.php +++ b/sources/AppBundle/Controller/Admin/Speaker/SpeakerEditAction.php @@ -16,7 +16,9 @@ use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Request; use Webmozart\Assert\Assert; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_EVENT_WRITER')] class SpeakerEditAction extends AbstractController { public const int ID_FORUM_PHOTO_STORAGE = 16; diff --git a/sources/AppBundle/Controller/Admin/Speaker/SpeakerLinkGravatarAction.php b/sources/AppBundle/Controller/Admin/Speaker/SpeakerLinkGravatarAction.php index acb495d9a..6cb9f06d2 100644 --- a/sources/AppBundle/Controller/Admin/Speaker/SpeakerLinkGravatarAction.php +++ b/sources/AppBundle/Controller/Admin/Speaker/SpeakerLinkGravatarAction.php @@ -10,7 +10,9 @@ use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_EVENT_WRITER')] class SpeakerLinkGravatarAction extends AbstractController { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Speaker/SpeakerListAction.php b/sources/AppBundle/Controller/Admin/Speaker/SpeakerListAction.php index e78dbe529..253853988 100644 --- a/sources/AppBundle/Controller/Admin/Speaker/SpeakerListAction.php +++ b/sources/AppBundle/Controller/Admin/Speaker/SpeakerListAction.php @@ -14,7 +14,9 @@ use Symfony\Component\HttpFoundation\Response; use Twig\Environment; use Webmozart\Assert\Assert; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_EVENT_READER')] class SpeakerListAction { public const array VALID_SORTS = ['name', 'company']; diff --git a/sources/AppBundle/Controller/Admin/Speaker/SpeakerRegisterAction.php b/sources/AppBundle/Controller/Admin/Speaker/SpeakerRegisterAction.php index 1243da411..79d8553ab 100644 --- a/sources/AppBundle/Controller/Admin/Speaker/SpeakerRegisterAction.php +++ b/sources/AppBundle/Controller/Admin/Speaker/SpeakerRegisterAction.php @@ -19,7 +19,9 @@ use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_EVENT_WRITER')] class SpeakerRegisterAction extends AbstractController { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/SuperApero/AddAction.php b/sources/AppBundle/Controller/Admin/SuperApero/AddAction.php index 15d1bc07e..4969b53e8 100644 --- a/sources/AppBundle/Controller/Admin/SuperApero/AddAction.php +++ b/sources/AppBundle/Controller/Admin/SuperApero/AddAction.php @@ -11,7 +11,9 @@ use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_APERO_WRITER')] final class AddAction extends AbstractController { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/SuperApero/DeleteAction.php b/sources/AppBundle/Controller/Admin/SuperApero/DeleteAction.php index bdcbb1cb3..13308a033 100644 --- a/sources/AppBundle/Controller/Admin/SuperApero/DeleteAction.php +++ b/sources/AppBundle/Controller/Admin/SuperApero/DeleteAction.php @@ -9,7 +9,9 @@ use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_APERO_WRITER')] final class DeleteAction extends AbstractController { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/SuperApero/EditAction.php b/sources/AppBundle/Controller/Admin/SuperApero/EditAction.php index c2836a502..75e8eaf37 100644 --- a/sources/AppBundle/Controller/Admin/SuperApero/EditAction.php +++ b/sources/AppBundle/Controller/Admin/SuperApero/EditAction.php @@ -11,7 +11,9 @@ use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_APERO_WRITER')] final class EditAction extends AbstractController { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/SuperApero/ListAction.php b/sources/AppBundle/Controller/Admin/SuperApero/ListAction.php index 5c790c91a..1bd82c81e 100644 --- a/sources/AppBundle/Controller/Admin/SuperApero/ListAction.php +++ b/sources/AppBundle/Controller/Admin/SuperApero/ListAction.php @@ -9,7 +9,9 @@ use Psr\Clock\ClockInterface; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_APERO_READER')] final class ListAction extends AbstractController { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Talk/AddAction.php b/sources/AppBundle/Controller/Admin/Talk/AddAction.php index dea560324..663bd57f9 100644 --- a/sources/AppBundle/Controller/Admin/Talk/AddAction.php +++ b/sources/AppBundle/Controller/Admin/Talk/AddAction.php @@ -13,7 +13,9 @@ use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_EVENT_WRITER')] class AddAction extends AbstractController { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Talk/DeleteAction.php b/sources/AppBundle/Controller/Admin/Talk/DeleteAction.php index be9e3279f..3122def3b 100644 --- a/sources/AppBundle/Controller/Admin/Talk/DeleteAction.php +++ b/sources/AppBundle/Controller/Admin/Talk/DeleteAction.php @@ -10,7 +10,9 @@ use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_EVENT_WRITER')] class DeleteAction extends AbstractController { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Talk/EditAction.php b/sources/AppBundle/Controller/Admin/Talk/EditAction.php index c07dc0303..985a55efe 100644 --- a/sources/AppBundle/Controller/Admin/Talk/EditAction.php +++ b/sources/AppBundle/Controller/Admin/Talk/EditAction.php @@ -15,7 +15,9 @@ use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_EVENT_WRITER')] class EditAction extends AbstractController { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Talk/ExportAction.php b/sources/AppBundle/Controller/Admin/Talk/ExportAction.php index 625200834..b4e4e10a4 100644 --- a/sources/AppBundle/Controller/Admin/Talk/ExportAction.php +++ b/sources/AppBundle/Controller/Admin/Talk/ExportAction.php @@ -10,7 +10,9 @@ use Symfony\Component\HttpFoundation\BinaryFileResponse; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\ResponseHeaderBag; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_EVENT_READER')] readonly class ExportAction { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Talk/ExportJoindInAction.php b/sources/AppBundle/Controller/Admin/Talk/ExportJoindInAction.php index b53c525d3..30c57fd41 100644 --- a/sources/AppBundle/Controller/Admin/Talk/ExportJoindInAction.php +++ b/sources/AppBundle/Controller/Admin/Talk/ExportJoindInAction.php @@ -9,7 +9,9 @@ use SplFileObject; use Symfony\Component\HttpFoundation\BinaryFileResponse; use Symfony\Component\HttpFoundation\ResponseHeaderBag; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_EVENT_READER')] readonly class ExportJoindInAction { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Talk/IndexAction.php b/sources/AppBundle/Controller/Admin/Talk/IndexAction.php index 3f49f87ef..13ab16649 100644 --- a/sources/AppBundle/Controller/Admin/Talk/IndexAction.php +++ b/sources/AppBundle/Controller/Admin/Talk/IndexAction.php @@ -16,7 +16,9 @@ use Symfony\Component\Form\FormInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_EVENT_READER')] final class IndexAction extends AbstractController { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/Talk/UpdateIndexationAction.php b/sources/AppBundle/Controller/Admin/Talk/UpdateIndexationAction.php index d35ecb332..81d90da59 100644 --- a/sources/AppBundle/Controller/Admin/Talk/UpdateIndexationAction.php +++ b/sources/AppBundle/Controller/Admin/Talk/UpdateIndexationAction.php @@ -8,7 +8,9 @@ use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_EVENT_WRITER')] class UpdateIndexationAction extends AbstractController { public function __construct(private readonly Runner $runner) {} diff --git a/sources/AppBundle/Controller/Admin/TechLetter/GenerateAction.php b/sources/AppBundle/Controller/Admin/TechLetter/GenerateAction.php index 8730685db..dc846a658 100644 --- a/sources/AppBundle/Controller/Admin/TechLetter/GenerateAction.php +++ b/sources/AppBundle/Controller/Admin/TechLetter/GenerateAction.php @@ -11,7 +11,9 @@ use Symfony\Component\DependencyInjection\Attribute\Autowire; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_VEILLE_WRITER')] final class GenerateAction extends AbstractController { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/TechLetter/HistoryAction.php b/sources/AppBundle/Controller/Admin/TechLetter/HistoryAction.php index 9d6468c9b..7ccf23683 100644 --- a/sources/AppBundle/Controller/Admin/TechLetter/HistoryAction.php +++ b/sources/AppBundle/Controller/Admin/TechLetter/HistoryAction.php @@ -9,7 +9,9 @@ use AppBundle\Veille\Entity\Repository\EnvoiRepository; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_VEILLE_READER')] final class HistoryAction extends AbstractController { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/TechLetter/IndexAction.php b/sources/AppBundle/Controller/Admin/TechLetter/IndexAction.php index fcf6b2336..23b2c68e7 100644 --- a/sources/AppBundle/Controller/Admin/TechLetter/IndexAction.php +++ b/sources/AppBundle/Controller/Admin/TechLetter/IndexAction.php @@ -9,7 +9,9 @@ use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_VEILLE_WRITER')] final class IndexAction extends AbstractController { public function __construct(private readonly EnvoiRepository $envoiRepository) {} diff --git a/sources/AppBundle/Controller/Admin/TechLetter/MembersAction.php b/sources/AppBundle/Controller/Admin/TechLetter/MembersAction.php index 2ded7a50a..8b7989335 100644 --- a/sources/AppBundle/Controller/Admin/TechLetter/MembersAction.php +++ b/sources/AppBundle/Controller/Admin/TechLetter/MembersAction.php @@ -7,7 +7,9 @@ use AppBundle\Veille\Entity\Repository\NewsletterInscriptionRepository; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_SUPER_ADMIN')] final class MembersAction extends AbstractController { public function __construct(private readonly NewsletterInscriptionRepository $newsletterInscriptionRepository) {} diff --git a/sources/AppBundle/Controller/Admin/TechLetter/PreviewAction.php b/sources/AppBundle/Controller/Admin/TechLetter/PreviewAction.php index 535a1c910..ef75ddb27 100644 --- a/sources/AppBundle/Controller/Admin/TechLetter/PreviewAction.php +++ b/sources/AppBundle/Controller/Admin/TechLetter/PreviewAction.php @@ -10,7 +10,9 @@ use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_VEILLE_WRITER')] final class PreviewAction extends AbstractController { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/TechLetter/RetrieveDataAction.php b/sources/AppBundle/Controller/Admin/TechLetter/RetrieveDataAction.php index acd4f442f..c313a0aa4 100644 --- a/sources/AppBundle/Controller/Admin/TechLetter/RetrieveDataAction.php +++ b/sources/AppBundle/Controller/Admin/TechLetter/RetrieveDataAction.php @@ -9,7 +9,9 @@ use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\Exception\BadRequestHttpException; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_VEILLE_WRITER')] final class RetrieveDataAction extends AbstractController { public function __invoke(Request $request): JsonResponse diff --git a/sources/AppBundle/Controller/Admin/TechLetter/SendTestAction.php b/sources/AppBundle/Controller/Admin/TechLetter/SendTestAction.php index 69f6880a2..84940cb67 100644 --- a/sources/AppBundle/Controller/Admin/TechLetter/SendTestAction.php +++ b/sources/AppBundle/Controller/Admin/TechLetter/SendTestAction.php @@ -13,7 +13,9 @@ use Symfony\Component\DependencyInjection\Attribute\Autowire; use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_VEILLE_WRITER')] final class SendTestAction extends AbstractController { public function __construct( diff --git a/sources/AppBundle/Controller/Admin/TechLetter/ShowAction.php b/sources/AppBundle/Controller/Admin/TechLetter/ShowAction.php index 2fbec9d2a..8d291f1c1 100644 --- a/sources/AppBundle/Controller/Admin/TechLetter/ShowAction.php +++ b/sources/AppBundle/Controller/Admin/TechLetter/ShowAction.php @@ -8,7 +8,9 @@ use AppBundle\Veille\Entity\Repository\EnvoiRepository; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Security\Http\Attribute\IsGranted; +#[IsGranted('ROLE_VEILLE_READER')] final class ShowAction extends AbstractController { public function __construct( diff --git a/sources/AppBundle/Controller/Website/Member/MembersAction.php b/sources/AppBundle/Controller/Website/Member/MembersAction.php index ba6ce43d2..d2727fc7a 100644 --- a/sources/AppBundle/Controller/Website/Member/MembersAction.php +++ b/sources/AppBundle/Controller/Website/Member/MembersAction.php @@ -45,7 +45,7 @@ public function __construct( public function __invoke(Request $request): Response { $id = $request->attributes->get('id'); - if ($id && $this->isGranted('ROLE_SUPER_ADMIN')) { + if ($id && $this->isGranted('ROLE_MEMBRES_WRITER')) { $companyId = $id; } else { $companyId = $this->authentication->getAfupUser()->getCompanyId(); @@ -85,7 +85,7 @@ public function __invoke(Request $request): Response } return $this->redirectToRoute('member_company_members', [ - 'id' => $this->isGranted('ROLE_SUPER_ADMIN') ? $companyId : null, + 'id' => $this->isGranted('ROLE_MEMBRES_WRITER') ? $companyId : null, ]); } diff --git a/sources/AppBundle/Security/ManageUserVoter.php b/sources/AppBundle/Security/ManageUserVoter.php new file mode 100644 index 000000000..75044e1bd --- /dev/null +++ b/sources/AppBundle/Security/ManageUserVoter.php @@ -0,0 +1,38 @@ + + */ +class ManageUserVoter extends Voter +{ + public const string MANAGE_USER = 'MANAGE_USER'; + + public function __construct(private readonly AccessDecisionManagerInterface $accessDecisionManager) {} + + protected function supports(string $attribute, mixed $subject): bool + { + return $attribute === self::MANAGE_USER && $subject instanceof User; + } + + protected function voteOnAttribute(string $attribute, mixed $subject, TokenInterface $token, ?Vote $vote = null): bool + { + if (!$subject->hasRole('ROLE_SUPER_ADMIN')) { + return true; + } + + return $this->accessDecisionManager->decide($token, ['ROLE_SUPER_ADMIN']); + } +} diff --git a/sources/AppBundle/StaticAnalysis/Rule/AdminControllerIsGrantedRule.php b/sources/AppBundle/StaticAnalysis/Rule/AdminControllerIsGrantedRule.php new file mode 100644 index 000000000..28679e7d8 --- /dev/null +++ b/sources/AppBundle/StaticAnalysis/Rule/AdminControllerIsGrantedRule.php @@ -0,0 +1,136 @@ + + */ +class AdminControllerIsGrantedRule implements Rule +{ + private const string ADMIN_CONTROLLER_NAMESPACE = 'AppBundle\Controller\Admin'; + + /** Controllers communs à toute la console, relatifs au namespace contrôlé. */ + private const array ROLE_ADMIN_ALLOWED_CONTROLLERS = ['HomeAction', 'GetMenuAction']; + + /** Surpropriété utilisée par les tests pour analyser des fixtures dans le namespace des stubs. */ + private string $controllerNamespace; + + public function __construct(?string $controllerNamespace = null) + { + $this->controllerNamespace = $controllerNamespace ?? self::ADMIN_CONTROLLER_NAMESPACE; + } + + public function getNodeType(): string + { + return Class_::class; + } + + public function processNode(Node $node, Scope $scope): array + { + $classFqn = $node->namespacedName?->toString() ?? ''; + if ($classFqn === '' || !str_starts_with($classFqn, $this->controllerNamespace . '\\')) { + return []; + } + + // Enums, traits et interfaces sont d'autres types de nœuds : seules les + // classes non abstraites sont des entry points HTTP. + if ($node->isAbstract()) { + return []; + } + + // Listeners noyau qui vivent dans ce namespace : pas des controllers. + if (str_ends_with($classFqn, 'Listener')) { + return []; + } + + $isGrantedAttributes = $this->findIsGrantedAttributes($node->attrGroups); + foreach ($node->stmts as $stmt) { + if ($stmt instanceof ClassMethod && $stmt->name->toString() === '__invoke') { + $isGrantedAttributes = [...$isGrantedAttributes, ...$this->findIsGrantedAttributes($stmt->attrGroups)]; + } + } + + if ($isGrantedAttributes === []) { + return [ + RuleErrorBuilder::message('Controller d\'administration sans attribut #[IsGranted] : ajoutez un rôle de la matrice READ/WRITE (ou ROLE_SUPER_ADMIN) au niveau de la classe ou sur __invoke.') + ->identifier('afup.missingIsGrantedOnAdminController') + ->build(), + ]; + } + + foreach ($isGrantedAttributes as $attribute) { + if (!$this->isRoleAdmin($attribute)) { + return []; + } + } + + $shortName = substr($classFqn, strlen($this->controllerNamespace) + 1); + if (in_array($shortName, self::ROLE_ADMIN_ALLOWED_CONTROLLERS, true)) { + return []; + } + + return [ + RuleErrorBuilder::message('Controller d\'administration protégé uniquement par #[IsGranted(\'ROLE_ADMIN\')] : ce rôle ne donne aucun droit fonctionnel, utilisez un rôle de la matrice READ/WRITE (ou ROLE_SUPER_ADMIN).') + ->identifier('afup.adminRoleOnAdminController') + ->build(), + ]; + } + + /** + * @param AttributeGroup[] $attributeGroups + * + * @return list + */ + private function findIsGrantedAttributes(array $attributeGroups): array + { + $attributes = []; + foreach ($attributeGroups as $attributeGroup) { + foreach ($attributeGroup->attrs as $attribute) { + if ((string) $attribute->name === 'IsGranted' || (string) $attribute->name === IsGranted::class) { + $attributes[] = $attribute; + } + } + } + + return $attributes; + } + + /** Le premier argument (positionnel ou nommé "attribute") est-il la chaîne 'ROLE_ADMIN' ? */ + private function isRoleAdmin(Attribute $attribute): bool + { + foreach ($attribute->args as $index => $arg) { + if (($arg->name === null && $index === 0) || $arg->name?->toString() === 'attribute') { + return $arg->value instanceof String_ && $arg->value->value === 'ROLE_ADMIN'; + } + } + + return false; + } +} diff --git a/templates/admin/administrators.html.twig b/templates/admin/administrators.html.twig index fdf79eeb4..d7b217385 100644 --- a/templates/admin/administrators.html.twig +++ b/templates/admin/administrators.html.twig @@ -9,11 +9,10 @@ Nom Prénom Etat - Administration site - Module annuaire - Module site - Module forum - Module Antenne + Super admin + {% for label in modules %} + {{ label }} + {% endfor %}   @@ -23,11 +22,14 @@ {{ administrator.lastName }} {{ administrator.firstName }} {% if administrator.status %}Actif{% else %}Inactif{% endif %} - {% if administrator.level == 2 %}Administrateur{% else %}---{% endif %} - {% if administrator.directoryLevel == 2 %}Gestionnaire{% else %}---{% endif %} - {% if administrator.websiteLevel == 2 %}Gestionnaire{% else %}---{% endif %} - {% if administrator.eventLevel == 2 %}Gestionnaire{% else %}---{% endif %} - {% if administrator.officeLevel == 2 %}Gestionnaire{% else %}---{% endif %} + {% if is_granted_for_user(administrator, 'ROLE_SUPER_ADMIN') %}Super admin{% else %}---{% endif %} + {# Droits effectifs (hiérarchie des rôles comprise), et non les seuls rôles enregistrés #} + {% for module, label in modules %} + {% set role_prefix = 'ROLE_' ~ module|upper %} + + {% if is_granted_for_user(administrator, role_prefix ~ '_WRITER') %}Gestionnaire{% elseif is_granted_for_user(administrator, role_prefix ~ '_READER') %}Lecteur{% else %}---{% endif %} + + {% endfor %} + {{ form_label(access) }} +
+ + + + + {% for level in access|first %} + + {% endfor %} + + + + {% for module in access %} + + + {% for level in module %} + + {% endfor %} + + {% endfor %} + +
{{ level.vars.label }}
{{ module.vars.label }} + {{ form_widget(level, {radio: true, inline_label: '', attr: {'aria-label': module.vars.label ~ ' : ' ~ level.vars.label}}) }} +
+ {{ form_errors(access) }} +
+ diff --git a/templates/admin/members/user_add.html.twig b/templates/admin/members/user_add.html.twig index 15775c081..997d215e1 100644 --- a/templates/admin/members/user_add.html.twig +++ b/templates/admin/members/user_add.html.twig @@ -29,11 +29,11 @@
- {{ form_row(form.level) }} - {{ form_row(form.directoryLevel) }} - {{ form_row(form.eventLevel) }} - {{ form_row(form.websiteLevel) }} - {{ form_row(form.officeLevel) }} + {% if form.access.vars.disabled %} +
Seul un super administrateur peut modifier les accès aux modules.
+ {% endif %} + {% include 'admin/members/_access_matrix.html.twig' with {access: form.access} only %} + {{ form_row(form.specialRoles) }} {{ form_row(form.status) }} {{ form_row(form.username, {attr: {'data-role': 'field-login'}}) }}
@@ -43,7 +43,6 @@
{{ form_row(form.plainPassword) }} - {{ form_row(form.roles) }} {{ form_row(form.needsUpToDateMembership) }}
diff --git a/templates/admin/members/user_edit.html.twig b/templates/admin/members/user_edit.html.twig index 8b0064e84..995603bdc 100644 --- a/templates/admin/members/user_edit.html.twig +++ b/templates/admin/members/user_edit.html.twig @@ -67,13 +67,17 @@
- {{ form_row(form.level) }} - {{ form_row(form.directoryLevel) }} - {{ form_row(form.eventLevel) }} - {{ form_row(form.websiteLevel) }} - {{ form_row(form.officeLevel) }} + {% if 'ROLE_SUPER_ADMIN' in user.roles %} +
Super administrateur : accès complet à tous les modules
+ {% endif %} + {% if form.access.vars.disabled %} +
Seul un super administrateur peut modifier les accès aux modules.
+ {% endif %} + {% include 'admin/members/_access_matrix.html.twig' with {access: form.access} only %} + {{ form_row(form.specialRoles) }} {{ form_row(form.status) }} {{ form_row(form.username, {attr: {'data-role': 'field-login'}}) }} + {% if form.plainPassword is defined %}
@@ -81,7 +85,7 @@
{{ form_row(form.plainPassword) }} - {{ form_row(form.roles) }} + {% endif %} {{ form_row(form.needsUpToDateMembership) }}
diff --git a/tests/behat/features/Admin/AccessCheckMembers.feature b/tests/behat/features/Admin/AccessCheckMembers.feature index 9e7d2408a..e53295044 100644 --- a/tests/behat/features/Admin/AccessCheckMembers.feature +++ b/tests/behat/features/Admin/AccessCheckMembers.feature @@ -27,3 +27,28 @@ Feature: Valider les accès depuis un compte membre When I go to "/admin/accounting/membership-fee/download/1/2/7" Then the response status code should be 403 + + @reloadDbWithTestData + Scenario: Un gestionnaire Membres ne peut pas gérer un compte super admin + Given I am logged-in with the user "gestionmembres" and the password "gestionmembres" + # Une personne sans rôle reste gérable + When I go to "/admin/members/users/edit?id=5" + Then the response status code should be 200 + # mais la matrice des accès aux modules est verrouillée + And I should see "Seul un super administrateur peut modifier les accès aux modules." + # Le compte super admin (admin) n'est ni modifiable, ni supprimable, ni réinitialisable + When I go to "/admin/members/users/edit?id=1" + Then the response status code should be 403 + When I go to "/admin/members/users/delete?id=1" + Then the response status code should be 403 + When I go to "/admin/members/users/reset-password?id=1" + Then the response status code should be 403 + When I go to "/admin/members/users/send-welcome?id=1" + Then the response status code should be 403 + # Les actions sont masquées dans la liste + # le compte admin des seeds n'est pas actif (état "non finalisé") + When I go to "/admin/members/users?filter=admin%40admin.fr&alsoDisplayInactive=1" + Then I should see an "#cotisations_1" element + And I should not see an "#modifier_1" element + And I should not see an "#supprimer_1" element + And I should not see an "#envoi_mdp_1" element diff --git a/tests/behat/features/Admin/AdminPersonnesPhysiques.feature b/tests/behat/features/Admin/AdminPersonnesPhysiques.feature index f9ee47dac..a35b1b6a1 100644 --- a/tests/behat/features/Admin/AdminPersonnesPhysiques.feature +++ b/tests/behat/features/Admin/AdminPersonnesPhysiques.feature @@ -9,6 +9,18 @@ Feature: Administration - Partie Personnes physiques When I follow "Ajouter" Then I should see "Ajouter une personne physique" Then The "user_edit[genre]" field should only contain the follow values '["Ne se prononce pas", "Femme", "Homme", "Non-binaire"]' + # Paramètres : matrice d'accès aux modules (Aucun / Lecteur / Gestionnaire) + # positionnée sur "Aucun" pour chaque module + And I should see "Accès aux modules" + And the "user_edit_access_membres_0" checkbox should be checked + And the "user_edit_access_veille_0" checkbox should be checked + And the "user_edit_access_site_0" checkbox should be checked + And the "user_edit_access_apero_0" checkbox should be checked + And the "user_edit_access_event_0" checkbox should be checked + And the "user_edit_access_compta_0" checkbox should be checked + And the "user_edit_access_ag_0" checkbox should be checked + And the "user_edit_access_planete_0" checkbox should be checked + And the "user_edit_access_antennes_0" checkbox should be checked When I press "Ajouter" Then I should see "Cette valeur ne doit pas être vide" When I fill in "user_edit[lastname]" with "Mon nom" @@ -18,16 +30,29 @@ Feature: Administration - Partie Personnes physiques And I fill in "user_edit[zipcode]" with "69001" And I fill in "user_edit[city]" with "LYON" And I fill in "user_edit[username]" with "monlogin" + And I select "2" from "user_edit[access][veille]" + And I select "1" from "user_edit[access][site]" + And I check "user_edit_specialRoles_1" And I press "Ajouter" Then I should not see "Cette valeur ne doit pas être vide" + # les droits sont relus depuis les rôles de la personne + # l'id 9 correspond à la personne créée ci-dessus : les seeds insèrent 8 personnes + # avec des identifiants explicites (cf. db/seeds/Users.php), le compteur auto-incrément + # est donc à 8 + When I am on "/admin/members/users/edit?id=9" + Then the "user_edit_access_veille_2" checkbox should be checked + And the "user_edit_access_site_1" checkbox should be checked + And the "user_edit_access_membres_0" checkbox should be checked + And the "user_edit_specialRoles_1" checkbox should be checked + And the "user_edit_specialRoles_0" checkbox should be unchecked # on vérifie qu'il est dans la liste When I follow "Personnes physiques" And I check "alsoDisplayInactive" And I press "Filtrer" Then I should see "Mon prénom" # on supprime la personne - When I follow "supprimer_3" + When I follow "supprimer_9" Then I should see "La personne physique a été supprimée" @reloadDbWithTestData diff --git a/tests/behat/features/Admin/Divers/Administrateurs.feature b/tests/behat/features/Admin/Divers/Administrateurs.feature index 1110a8b0b..d744df948 100644 --- a/tests/behat/features/Admin/Divers/Administrateurs.feature +++ b/tests/behat/features/Admin/Divers/Administrateurs.feature @@ -5,7 +5,9 @@ Feature: Administration - Administrateurs du site Given I am logged in as admin and on the Administration And I follow "Administrateurs du site" Then I should see "Administrateurs du site" - And I should see "Admin Admin Actif Administrateur" + # les droits affichés sont les droits effectifs : le super admin est gestionnaire de tous les modules + And I should see "Admin Admin Actif Super admin Gestionnaire Gestionnaire Gestionnaire" + And I should see "Zorglub Gestion Actif --- Gestionnaire --- ---" And I follow the button of tooltip "Modifier la fiche de Admin Admin" And I should see "Modifier une personne physique" And I fill in "user_edit_lastname" with "SuperLastnameAdmin" @@ -16,4 +18,4 @@ Feature: Administration - Administrateurs du site And I press "Modifier" Then the ".content .message" element should contain "La personne physique a été modifiée" And I follow "Administrateurs du site" - And I should see "SuperLastnameAdmin SuperFirstnameAdmin Actif Administrateur" + And I should see "SuperLastnameAdmin SuperFirstnameAdmin Actif Super admin Gestionnaire" diff --git a/tests/behat/features/Admin/Members/AdminMembersReporting.feature b/tests/behat/features/Admin/Members/AdminMembersReporting.feature index 7c6dba12d..d6b86b4a8 100644 --- a/tests/behat/features/Admin/Members/AdminMembersReporting.feature +++ b/tests/behat/features/Admin/Members/AdminMembersReporting.feature @@ -5,5 +5,5 @@ Feature: Administration - Partie Reporting Given I am logged in as admin and on the Administration And I follow "Reporting" Then the ".content h2" element should contain "Statistiques concernant les membres" - Then I should see "2 Personnes physiques totales*" - Then I should see "1 Personnes physiques non rattachées à une personne morale*" + Then I should see "3 Personnes physiques totales*" + Then I should see "2 Personnes physiques non rattachées à une personne morale*" diff --git a/tests/integration/AppBundle/Security/AdminAccessControlTest.php b/tests/integration/AppBundle/Security/AdminAccessControlTest.php new file mode 100644 index 000000000..5389b7493 --- /dev/null +++ b/tests/integration/AppBundle/Security/AdminAccessControlTest.php @@ -0,0 +1,293 @@ + 'ROLE_MEMBRES_READER', + 'ROLE_VEILLE_WRITER' => 'ROLE_VEILLE_READER', + 'ROLE_SITE_WRITER' => 'ROLE_SITE_READER', + 'ROLE_APERO_WRITER' => 'ROLE_APERO_READER', + 'ROLE_EVENT_WRITER' => 'ROLE_EVENT_READER', + 'ROLE_COMPTA_WRITER' => 'ROLE_COMPTA_READER', + 'ROLE_AG_WRITER' => 'ROLE_AG_READER', + 'ROLE_PLANETE_WRITER' => 'ROLE_PLANETE_READER', + 'ROLE_ANTENNES_WRITER' => 'ROLE_ANTENNES_READER', + ]; + + private const string MEMBER_ROLE = 'ROLE_MEMBER_EXPIRED'; + + private const array READER_ROLES = [ + 'ROLE_MEMBRES_READER', + 'ROLE_VEILLE_READER', + 'ROLE_SITE_READER', + 'ROLE_APERO_READER', + 'ROLE_EVENT_READER', + 'ROLE_COMPTA_READER', + 'ROLE_AG_READER', + 'ROLE_PLANETE_READER', + 'ROLE_ANTENNES_READER', + ]; + + /** Rôles WRITE légaux en attribut controller (clés de WRITE_TO_READ). */ + private const array WRITER_ROLES = [ + 'ROLE_MEMBRES_WRITER', + 'ROLE_VEILLE_WRITER', + 'ROLE_SITE_WRITER', + 'ROLE_APERO_WRITER', + 'ROLE_EVENT_WRITER', + 'ROLE_COMPTA_WRITER', + 'ROLE_AG_WRITER', + 'ROLE_PLANETE_WRITER', + 'ROLE_ANTENNES_WRITER', + ]; + + /** Entrée console : seule route autorisée à porter #[IsGranted('ROLE_ADMIN')] (marqueur, pas un garde fonctionnel). */ + private const string CONSOLE_ENTRY_ROUTE = 'admin_home'; + + /** Redirections legacy /admin/(login|logout|password) → pages publiques : publiques par design, pas de garde en code. */ + private const array LEGACY_AUTH_ROUTES = ['auth_old_login', 'auth_old_logout', 'auth_old_password']; + + private static ?KernelInterface $sharedKernel = null; + + public static function tearDownAfterClass(): void + { + self::$sharedKernel = null; + static::$kernel = null; + } + + /** @return iterable */ + public static function provideAdminRoutes(): iterable + { + /** @var RouterInterface $router */ + $router = self::sharedContainer()->get('router'); + + foreach ($router->getRouteCollection() as $name => $route) { + if (!str_starts_with($route->getPath(), '/admin')) { + continue; + } + + yield $name => [$name, $route]; + } + } + + #[DataProvider('provideAdminRoutes')] + public function testRouteIsGated(string $routeName, Route $route): void + { + $container = self::sharedContainer(); + /** @var AccessMapInterface $accessMap */ + $accessMap = $container->get('security.access_map'); + /** @var AuthorizationCheckerInterface $checker */ + $checker = $container->get('security.authorization_checker'); + /** @var TokenStorageInterface $tokenStorage */ + $tokenStorage = $container->get('security.token_storage'); + $path = $route->getPath(); + + // ── access_control : la première règle matchée est la règle console. + $request = $this->requestFor($path, $routeName); + [$attributes] = $accessMap->getPatterns($request); + self::assertNotEmpty($attributes, "La route {$routeName} ({$path}) n'est couverte par aucune règle console : elle n'est pas protégée par access_control (attendu : la règle ^/admin)."); + $mapRole = $attributes[0]; + if (in_array($routeName, self::LEGACY_AUTH_ROUTES, true)) { + // Redirections legacy du domaine auth : publiques par design, pas de garde en code. + self::assertSame('PUBLIC_ACCESS', $mapRole, "La route {$routeName} ({$path}) doit rester publique (redirection legacy vers une page d'authentification) ; premier rôle matché : '{$mapRole}'."); + + return; + } + self::assertContains( + $mapRole, + self::CONSOLE_ROLES, + "La route {$routeName} ({$path}) n'est pas couverte par la règle console : le premier rôle matché est '{$mapRole}', attendu ROLE_ADMIN ou ROLE_SUPER_ADMIN.", + ); + + // ── #[IsGranted] : présent sur le controller, et c'est lui le vrai garde. + $controllerRole = $this->controllerIsGrantedRole($route); + self::assertNotNull($controllerRole, "Pas d'attribut #[IsGranted] sur le controller de la route {$routeName} ({$path})."); + if ($routeName === self::CONSOLE_ENTRY_ROUTE) { + self::assertSame( + 'ROLE_ADMIN', + $controllerRole, + "L'entrée console ({$routeName}, {$path}) doit porter le marqueur #[IsGranted('ROLE_ADMIN')] ; valeur '{$controllerRole}' inattendue.", + ); + } else { + self::assertTrue( + in_array($controllerRole, self::READER_ROLES, true) + || in_array($controllerRole, self::WRITER_ROLES, true) + || $controllerRole === 'ROLE_SUPER_ADMIN', + "Attribut #[IsGranted] '{$controllerRole}' interdit sur le controller de la route {$routeName} ({$path}) : la matrice READ/WRITE ou ROLE_SUPER_ADMIN, jamais ROLE_ADMIN seul (cela réouvrirait l'accès aux simples comptes ROLE_ADMIN).", + ); + } + + // ── La hiérarchie (et elle seule) décide qui franchit l'attribut en code. + $expectedEffects = self::expectedMatrix($mapRole, $controllerRole); + foreach ($expectedEffects as $profile => $expected) { + $granted = $this->checkWithToken($checker, $tokenStorage, $profile, $mapRole, $controllerRole); + self::assertSame( + $expected, + $granted, + "Accès sur {$routeName} ({$path}) : le profil {$profile} doit " . ($expected ? 'passer' : 'être refusé') . ".", + ); + } + $tokenStorage->setToken(null); + } + + /** + * Matrice : profil => accès attendu, tenant compte des deux barrières + * (règle console access_control ET #[IsGranted] controllerRole), WRITE ⇒ READ. + * + * La règle console fait passer tout profil admin et bloque anonyme / + * adhérent expiré ; la discrimination fine (READ/WRITE, SUPER_ADMIN) + * vient de l'attribut en code. + * + * @return array + */ + private static function expectedMatrix(string $mapRole, string $controllerRole): array + { + $matrix = [ + 'anonymous' => false, + 'member (expired)' => false, + ]; + + foreach (self::ADMIN_ROLES as $role) { + $matrix[$role] = self::satisfies($role, $mapRole) && self::satisfies($role, $controllerRole); + } + + return $matrix; + } + + /** + * Le rôle candidat satisfait-il le rôle requis ? Grâce à la hiérarchie : + * READ ⇒ ROLE_ADMIN (marqueur console), WRITE ⇒ READ, SUPER_ADMIN ⇒ tous les WRITE et READ. + */ + private static function satisfies(string $candidate, string $required): bool + { + if ($candidate === 'ROLE_SUPER_ADMIN') { + // ROLE_SUPER_ADMIN possède la console et tous les READ et WRITE. + return $required === 'ROLE_SUPER_ADMIN' + || $required === 'ROLE_ADMIN' + || in_array($required, self::READER_ROLES, true) + || in_array($required, self::WRITER_ROLES, true); + } + + if ($required === 'ROLE_ADMIN') { + // Tout rôle fonctionnel (READ/WRITE) implique ROLE_ADMIN ; ROLE_ADMIN seul n'ouvre rien de fonctionnel. + return $candidate === 'ROLE_ADMIN' + || in_array($candidate, self::READER_ROLES, true) + || array_key_exists($candidate, self::WRITE_TO_READ); + } + + return $candidate === $required || (self::WRITE_TO_READ[$candidate] ?? null) === $required; + } + + private function checkWithToken(AuthorizationCheckerInterface $checker, TokenStorageInterface $tokenStorage, string $profile, string $mapRole, string $controllerRole): bool + { + $token = match ($profile) { + 'anonymous' => new UsernamePasswordToken(new InMemoryUser('anon.', null, ['IS_AUTHENTICATED_ANONYMOUSLY']), 'main', ['IS_AUTHENTICATED_ANONYMOUSLY']), + 'member (expired)' => new UsernamePasswordToken(new InMemoryUser('member', null, [self::MEMBER_ROLE]), 'main', [self::MEMBER_ROLE]), + default => new UsernamePasswordToken(new InMemoryUser('u', null, [$profile]), 'main', [$profile]), + }; + $tokenStorage->setToken($token); + + // Les deux barrières doivent être franchies simultanément : + // la règle console access_control ET l'attribut #[IsGranted] du controller. + return $checker->isGranted($mapRole) && $checker->isGranted($controllerRole); + } + + private function controllerIsGrantedRole(Route $route): ?string + { + $controller = $route->getDefault('_controller'); + if (!is_string($controller)) { + return null; + } + + if (str_contains($controller, ':') && !str_contains($controller, '::')) { + return null; // service:method, pas traité ici. + } + + [$class, $method] = array_pad(explode('::', $controller, 2), 2, null); + if (!class_exists($class)) { + return null; + } + + $reflected = new \ReflectionClass($class); + $attribute = $reflected->getAttributes(IsGranted::class)[0] ?? null; + if ($attribute === null && $method !== null) { + $attribute = $reflected->getMethod($method)->getAttributes(IsGranted::class)[0] ?? null; + } + + return $attribute === null ? null : $attribute->newInstance()->attribute; + } + + private function requestFor(string $path, string $routeName): Request + { + $request = Request::create($path); + $request->attributes->set('_route', $routeName); + + return $request; + } + + private static function sharedContainer(): ContainerInterface + { + if (self::$sharedKernel === null) { + self::$sharedKernel = self::createKernel(); + self::$sharedKernel->boot(); + } + + return self::$sharedKernel->getContainer()->get('test.service_container'); + } +} diff --git a/tests/integration/AppBundle/StaticAnalysis/Rule/AdminControllerIsGrantedRuleTest.php b/tests/integration/AppBundle/StaticAnalysis/Rule/AdminControllerIsGrantedRuleTest.php new file mode 100644 index 000000000..784257afd --- /dev/null +++ b/tests/integration/AppBundle/StaticAnalysis/Rule/AdminControllerIsGrantedRuleTest.php @@ -0,0 +1,56 @@ + */ +final class AdminControllerIsGrantedRuleTest extends RuleTestCase +{ + protected function getRule(): Rule + { + // Les fixtures vivent dans le namespace autoloadé des stubs. + return new AdminControllerIsGrantedRule('Afup\Tests\Stubs\PHPStan'); + } + + public function testRule(): void + { + $u = __DIR__ . '/../../../../stubs/phpstan'; + + $this->analyse([ + $u . '/ControllerWithoutIsGranted.php', + $u . '/InvokeWithoutIsGranted.php', + ], [ + [ + 'Controller d\'administration sans attribut #[IsGranted] : ajoutez un rôle de la matrice READ/WRITE (ou ROLE_SUPER_ADMIN) au niveau de la classe ou sur __invoke.', + 7, + ], + [ + 'Controller d\'administration sans attribut #[IsGranted] : ajoutez un rôle de la matrice READ/WRITE (ou ROLE_SUPER_ADMIN) au niveau de la classe ou sur __invoke.', + 7, + ], + ]); + } + + public function testRoleAdminAloneIsReported(): void + { + $u = __DIR__ . '/../../../../stubs/phpstan'; + + $this->analyse([ + $u . '/ControllerWithRoleAdmin.php', + $u . '/HomeAction.php', + $u . '/ControllerClassLevelIsGranted.php', + $u . '/ControllerInvokeLevelIsGranted.php', + $u . '/KernelAdminListener.php', + ], [ + [ + 'Controller d\'administration protégé uniquement par #[IsGranted(\'ROLE_ADMIN\')] : ce rôle ne donne aucun droit fonctionnel, utilisez un rôle de la matrice READ/WRITE (ou ROLE_SUPER_ADMIN).', + 9, + ], + ]); + } +} diff --git a/tests/stubs/phpstan/ControllerClassLevelIsGranted.php b/tests/stubs/phpstan/ControllerClassLevelIsGranted.php new file mode 100644 index 000000000..3c378716c --- /dev/null +++ b/tests/stubs/phpstan/ControllerClassLevelIsGranted.php @@ -0,0 +1,13 @@ + [$module, 'ROLE_' . strtoupper($module)]; + } + } + + private function user(): User + { + $user = new User(); + $user->setId(1); + $user->setStatus(User::STATUS_ACTIVE); + $user->setRoles([]); + $user->setLastSubscription((string) (new \DateTime('+1 year'))->getTimestamp()); + + return $user; + } + + #[DataProvider('provideModuleRoles')] + public function testNewUserHasNoAccess(string $module, string $rolePrefix): void + { + $user = $this->user(); + + self::assertSame(User::LEVEL_NONE, $user->getModuleLevel($module)); + self::assertNotContains($rolePrefix . '_READER', $user->getRoles()); + self::assertNotContains('ROLE_ADMIN', $user->getRoles()); + } + + #[DataProvider('provideModuleRoles')] + public function testReaderLevelGrantsReaderRole(string $module, string $rolePrefix): void + { + $user = $this->user(); + $user->setModuleLevel($module, User::LEVEL_READER); + + $roles = $user->getRoles(); + self::assertContains($rolePrefix . '_READER', $roles); + self::assertNotContains($rolePrefix . '_WRITER', $roles); + self::assertSame(User::LEVEL_READER, $user->getModuleLevel($module)); + } + + #[DataProvider('provideModuleRoles')] + public function testManagerLevelGrantsWriterRole(string $module, string $rolePrefix): void + { + $user = $this->user(); + $user->setModuleLevel($module, User::LEVEL_READER); + $user->setModuleLevel($module, User::LEVEL_MANAGER); + + $roles = $user->getRoles(); + self::assertContains($rolePrefix . '_WRITER', $roles); + self::assertNotContains($rolePrefix . '_READER', $roles, 'Le WRITER suffit via la hiérarchie WRITE ⇒ READ'); + self::assertSame(User::LEVEL_MANAGER, $user->getModuleLevel($module)); + } + + #[DataProvider('provideModuleRoles')] + public function testNoneLevelRemovesModuleRoles(string $module, string $rolePrefix): void + { + $user = $this->user(); + $user->setRoles([$rolePrefix . '_WRITER', 'ROLE_COMPANY_MANAGER']); + $user->setModuleLevel($module, User::LEVEL_NONE); + + $roles = $user->getRoles(); + self::assertNotContains($rolePrefix . '_READER', $roles); + self::assertNotContains($rolePrefix . '_WRITER', $roles); + self::assertContains('ROLE_COMPANY_MANAGER', $roles, 'Les rôles hors matrice doivent être conservés'); + } + + public function testModuleLevelIsReadFromStoredRoles(): void + { + $user = $this->user(); + $user->setRoles(['ROLE_SITE_READER', 'ROLE_ANTENNES_WRITER']); + + self::assertSame(User::LEVEL_READER, $user->getModuleLevel('site')); + self::assertSame(User::LEVEL_MANAGER, $user->getModuleLevel('antennes')); + self::assertSame(User::LEVEL_NONE, $user->getModuleLevel('compta')); + } + + public function testUnknownModuleIsIgnored(): void + { + $user = $this->user(); + $user->setModuleLevel('inconnu', User::LEVEL_MANAGER); + + self::assertSame([], array_values(array_diff($user->getRoles(), ['ROLE_USER']))); + } +} diff --git a/tests/unit/AppBundle/Security/ManageUserVoterTest.php b/tests/unit/AppBundle/Security/ManageUserVoterTest.php new file mode 100644 index 000000000..38230bb25 --- /dev/null +++ b/tests/unit/AppBundle/Security/ManageUserVoterTest.php @@ -0,0 +1,61 @@ + $currentUserRoles + * @param list $targetRoles + */ + #[DataProvider('provideCases')] + public function testVote(array $currentUserRoles, array $targetRoles, int $expected): void + { + $roleHierarchy = new RoleHierarchy([ + 'ROLE_MEMBRES_WRITER' => ['ROLE_MEMBRES_READER'], + 'ROLE_SUPER_ADMIN' => ['ROLE_ADMIN', 'ROLE_MEMBRES_WRITER'], + ]); + $voter = new ManageUserVoter(new AccessDecisionManager([new RoleHierarchyVoter($roleHierarchy)])); + + $token = new UsernamePasswordToken(new InMemoryUser('current', null, $currentUserRoles), 'main', $currentUserRoles); + + $target = new User(); + $target->setRoles($targetRoles); + + self::assertSame($expected, $voter->vote($token, $target, [ManageUserVoter::MANAGE_USER])); + } + + /** + * @return iterable, list, int}> + */ + public static function provideCases(): iterable + { + yield 'gestionnaire Membres sur une personne sans rôle' => [['ROLE_MEMBRES_WRITER'], [], VoterInterface::ACCESS_GRANTED]; + yield 'gestionnaire Membres sur un autre gestionnaire' => [['ROLE_MEMBRES_WRITER'], ['ROLE_COMPTA_WRITER'], VoterInterface::ACCESS_GRANTED]; + yield 'gestionnaire Membres sur un super admin' => [['ROLE_MEMBRES_WRITER'], ['ROLE_SUPER_ADMIN'], VoterInterface::ACCESS_DENIED]; + yield 'super admin sur un super admin' => [['ROLE_SUPER_ADMIN'], ['ROLE_SUPER_ADMIN'], VoterInterface::ACCESS_GRANTED]; + yield 'super admin sur une personne sans rôle' => [['ROLE_SUPER_ADMIN'], [], VoterInterface::ACCESS_GRANTED]; + } + + public function testAbstainsOnOtherAttributesAndSubjects(): void + { + $voter = new ManageUserVoter(new AccessDecisionManager([])); + $token = new UsernamePasswordToken(new InMemoryUser('current', null), 'main'); + + self::assertSame(VoterInterface::ACCESS_ABSTAIN, $voter->vote($token, new User(), ['OTHER'])); + self::assertSame(VoterInterface::ACCESS_ABSTAIN, $voter->vote($token, new \stdClass(), [ManageUserVoter::MANAGE_USER])); + } +}