ActionController.php 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. <?php
  2. declare(strict_types=1);
  3. /**
  4. * MINZ - Copyright 2011 Marien Fressinaud
  5. * Sous licence AGPL3 <http://www.gnu.org/licenses/>
  6. */
  7. /**
  8. * The Minz_ActionController class is a controller in the MVC paradigm
  9. */
  10. abstract class Minz_ActionController {
  11. /** @var array<string,string> */
  12. private static array $csp_default = [
  13. 'default-src' => "'self'",
  14. 'frame-ancestors' => "'none'",
  15. ];
  16. /** @var array<string,string> */
  17. private array $csp_policies;
  18. /** @var Minz_View */
  19. protected $view;
  20. /**
  21. * Gives the possibility to override the default view model type.
  22. * @var class-string
  23. * @deprecated Use constructor with view type instead
  24. */
  25. public static string $defaultViewType = Minz_View::class;
  26. /**
  27. * @phpstan-param class-string|'' $viewType
  28. * @param string $viewType Name of the class (inheriting from Minz_View) to use for the view model
  29. */
  30. public function __construct(string $viewType = '') {
  31. $this->csp_policies = self::$csp_default;
  32. $view = null;
  33. if ($viewType !== '' && class_exists($viewType)) {
  34. $view = new $viewType();
  35. if (!($view instanceof Minz_View)) {
  36. $view = null;
  37. }
  38. }
  39. if ($view === null && class_exists(self::$defaultViewType)) {
  40. $view = new self::$defaultViewType();
  41. if (!($view instanceof Minz_View)) {
  42. $view = null;
  43. }
  44. }
  45. $this->view = $view ?? new Minz_View();
  46. $view_path = Minz_Request::controllerName() . '/' . Minz_Request::actionName() . '.phtml';
  47. $this->view->_path($view_path);
  48. $this->view->attributeParams();
  49. }
  50. /**
  51. * Getteur
  52. */
  53. public function view(): Minz_View {
  54. return $this->view;
  55. }
  56. /**
  57. * Set default CSP policies.
  58. * @param array<string,string> $policies An array where keys are directives and values are sources.
  59. */
  60. public static function _defaultCsp(array $policies): void {
  61. if (!isset($policies['default-src']) || !isset($policies['frame-ancestors'])) {
  62. Minz_Log::warning('Default CSP policy is not declared', ADMIN_LOG);
  63. }
  64. self::$csp_default = $policies;
  65. }
  66. /**
  67. * Set CSP policies.
  68. *
  69. * default-src and frame-ancestors directives should always be given.
  70. *
  71. * References:
  72. * - https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/CSP
  73. * - https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Content-Security-Policy/default-src
  74. * - https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Content-Security-Policy/frame-ancestors
  75. *
  76. * @param array<string,string> $policies An array where keys are directives and values are sources.
  77. */
  78. protected function _csp(array $policies): void {
  79. if (!isset($policies['default-src']) || !isset($policies['frame-ancestors'])) {
  80. $action = Minz_Request::controllerName() . '#' . Minz_Request::actionName();
  81. Minz_Log::warning(
  82. "Default CSP policy is not declared for action {$action}.",
  83. ADMIN_LOG
  84. );
  85. }
  86. $this->csp_policies = $policies;
  87. }
  88. /**
  89. * Send HTTP Content-Security-Policy header based on declared policies.
  90. */
  91. public function declareCspHeader(): void {
  92. $policies = [];
  93. foreach (Minz_ExtensionManager::listExtensions(true) as $extension) {
  94. $extension->amendCsp($this->csp_policies);
  95. }
  96. foreach ($this->csp_policies as $directive => $sources) {
  97. $policies[] = $directive . ' ' . $sources;
  98. }
  99. header('Content-Security-Policy: ' . implode('; ', $policies));
  100. }
  101. /**
  102. * Méthodes à redéfinir (ou non) par héritage
  103. * firstAction est la première méthode exécutée par le Dispatcher
  104. * lastAction est la dernière
  105. */
  106. public function init(): void { }
  107. public function firstAction(): void { }
  108. public function lastAction(): void { }
  109. }