MainConfiguration.php 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323
  1. <?php
  2. namespace Symfony\Bundle\SecurityBundle\DependencyInjection;
  3. use Symfony\Component\Config\Definition\Builder\TreeBuilder;
  4. use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition;
  5. use Symfony\Component\Config\Definition\ConfigurationInterface;
  6. /**
  7. * This class contains the configuration information for the following tags:
  8. *
  9. * * security.config
  10. * * security.acl
  11. *
  12. * This information is solely responsible for how the different configuration
  13. * sections are normalized, and merged.
  14. *
  15. * @author Johannes M. Schmitt <schmittjoh@gmail.com>
  16. */
  17. class MainConfiguration implements ConfigurationInterface
  18. {
  19. private $factories;
  20. /**
  21. * Constructor.
  22. *
  23. * @param array $factories
  24. */
  25. public function __construct(array $factories)
  26. {
  27. $this->factories = $factories;
  28. }
  29. /**
  30. * Generates the configuration tree builder.
  31. *
  32. * @return \Symfony\Component\Config\Definition\Builder\TreeBuilder The tree builder
  33. */
  34. public function getConfigTreeBuilder()
  35. {
  36. $tb = new TreeBuilder();
  37. $rootNode = $tb->root('security');
  38. $rootNode
  39. ->children()
  40. ->scalarNode('access_denied_url')->defaultNull()->end()
  41. ->scalarNode('session_fixation_strategy')->cannotBeEmpty()->defaultValue('migrate')->end()
  42. ->booleanNode('always_authenticate_before_granting')->defaultFalse()->end()
  43. ->arrayNode('access_decision_manager')
  44. ->addDefaultsIfNotSet()
  45. ->children()
  46. ->scalarNode('strategy')->defaultValue('affirmative')->end()
  47. ->booleanNode('allow_if_all_abstain')->defaultFalse()->end()
  48. ->booleanNode('allow_if_equal_granted_denied')->defaultTrue()->end()
  49. ->end()
  50. ->end()
  51. ->end()
  52. // add a faux-entry for factories, so that no validation error is thrown
  53. ->fixXmlConfig('factory', 'factories')
  54. ->children()
  55. ->arrayNode('factories')->ignoreExtraKeys()->end()
  56. ->end()
  57. ;
  58. $this->addAclSection($rootNode);
  59. $this->addEncodersSection($rootNode);
  60. $this->addProvidersSection($rootNode);
  61. $this->addFirewallsSection($rootNode, $this->factories);
  62. $this->addAccessControlSection($rootNode);
  63. $this->addRoleHierarchySection($rootNode);
  64. return $tb;
  65. }
  66. private function addAclSection(ArrayNodeDefinition $rootNode)
  67. {
  68. $rootNode
  69. ->children()
  70. ->arrayNode('acl')
  71. ->children()
  72. ->scalarNode('connection')->end()
  73. ->arrayNode('cache')
  74. ->addDefaultsIfNotSet()
  75. ->children()
  76. ->scalarNode('id')->end()
  77. ->scalarNode('prefix')->defaultValue('sf2_acl_')->end()
  78. ->end()
  79. ->end()
  80. ->scalarNode('provider')->end()
  81. ->arrayNode('tables')
  82. ->addDefaultsIfNotSet()
  83. ->children()
  84. ->scalarNode('class')->defaultValue('acl_classes')->end()
  85. ->scalarNode('entry')->defaultValue('acl_entries')->end()
  86. ->scalarNode('object_identity')->defaultValue('acl_object_identities')->end()
  87. ->scalarNode('object_identity_ancestors')->defaultValue('acl_object_identity_ancestors')->end()
  88. ->scalarNode('security_identity')->defaultValue('acl_security_identities')->end()
  89. ->end()
  90. ->end()
  91. ->arrayNode('voter')
  92. ->addDefaultsIfNotSet()
  93. ->children()
  94. ->booleanNode('allow_if_object_identity_unavailable')->defaultTrue()->end()
  95. ->end()
  96. ->end()
  97. ->end()
  98. ->end()
  99. ->end()
  100. ;
  101. }
  102. private function addRoleHierarchySection(ArrayNodeDefinition $rootNode)
  103. {
  104. $rootNode
  105. ->fixXmlConfig('role', 'role_hierarchy')
  106. ->children()
  107. ->arrayNode('role_hierarchy')
  108. ->useAttributeAsKey('id')
  109. ->prototype('array')
  110. ->performNoDeepMerging()
  111. ->beforeNormalization()->ifString()->then(function($v) { return array('value' => $v); })->end()
  112. ->beforeNormalization()
  113. ->ifTrue(function($v) { return is_array($v) && isset($v['value']); })
  114. ->then(function($v) { return preg_split('/\s*,\s*/', $v['value']); })
  115. ->end()
  116. ->prototype('scalar')->end()
  117. ->end()
  118. ->end()
  119. ->end()
  120. ;
  121. }
  122. private function addAccessControlSection(ArrayNodeDefinition $rootNode)
  123. {
  124. $rootNode
  125. ->fixXmlConfig('rule', 'access_control')
  126. ->children()
  127. ->arrayNode('access_control')
  128. ->cannotBeOverwritten()
  129. ->prototype('array')
  130. ->children()
  131. ->scalarNode('requires_channel')->defaultNull()->end()
  132. ->scalarNode('path')->defaultNull()->end()
  133. ->scalarNode('host')->defaultNull()->end()
  134. ->scalarNode('ip')->defaultNull()->end()
  135. ->arrayNode('methods')
  136. ->beforeNormalization()->ifString()->then(function($v) { return preg_split('/\s*,\s*/', $v); })->end()
  137. ->prototype('scalar')->end()
  138. ->end()
  139. ->end()
  140. ->fixXmlConfig('role')
  141. ->children()
  142. ->arrayNode('roles')
  143. ->beforeNormalization()->ifString()->then(function($v) { return preg_split('/\s*,\s*/', $v); })->end()
  144. ->prototype('scalar')->end()
  145. ->end()
  146. ->end()
  147. ->end()
  148. ->end()
  149. ->end()
  150. ;
  151. }
  152. private function addFirewallsSection(ArrayNodeDefinition $rootNode, array $factories)
  153. {
  154. $firewallNodeBuilder = $rootNode
  155. ->fixXmlConfig('firewall')
  156. ->children()
  157. ->arrayNode('firewalls')
  158. ->isRequired()
  159. ->requiresAtLeastOneElement()
  160. ->disallowNewKeysInSubsequentConfigs()
  161. ->useAttributeAsKey('name')
  162. ->prototype('array')
  163. ->children()
  164. ;
  165. $firewallNodeBuilder
  166. ->scalarNode('pattern')->end()
  167. ->booleanNode('security')->defaultTrue()->end()
  168. ->scalarNode('request_matcher')->end()
  169. ->scalarNode('access_denied_url')->end()
  170. ->scalarNode('access_denied_handler')->end()
  171. ->scalarNode('entry_point')->end()
  172. ->scalarNode('provider')->end()
  173. ->booleanNode('stateless')->defaultFalse()->end()
  174. ->scalarNode('context')->cannotBeEmpty()->end()
  175. ->arrayNode('logout')
  176. ->treatTrueLike(array())
  177. ->canBeUnset()
  178. ->children()
  179. ->scalarNode('path')->defaultValue('/logout')->end()
  180. ->scalarNode('target')->defaultValue('/')->end()
  181. ->scalarNode('success_handler')->end()
  182. ->booleanNode('invalidate_session')->defaultTrue()->end()
  183. ->end()
  184. ->fixXmlConfig('delete_cookie')
  185. ->children()
  186. ->arrayNode('delete_cookies')
  187. ->beforeNormalization()
  188. ->ifTrue(function($v) { return is_array($v) && is_int(key($v)); })
  189. ->then(function($v) { return array_map(function($v) { return array('name' => $v); }, $v); })
  190. ->end()
  191. ->useAttributeAsKey('name')
  192. ->prototype('array')
  193. ->children()
  194. ->scalarNode('path')->defaultNull()->end()
  195. ->scalarNode('domain')->defaultNull()->end()
  196. ->end()
  197. ->end()
  198. ->end()
  199. ->end()
  200. ->fixXmlConfig('handler')
  201. ->children()
  202. ->arrayNode('handlers')
  203. ->prototype('scalar')->end()
  204. ->end()
  205. ->end()
  206. ->end()
  207. ->arrayNode('anonymous')
  208. ->canBeUnset()
  209. ->children()
  210. ->scalarNode('key')->defaultValue(uniqid())->end()
  211. ->end()
  212. ->end()
  213. ->arrayNode('switch_user')
  214. ->canBeUnset()
  215. ->children()
  216. ->scalarNode('provider')->end()
  217. ->scalarNode('parameter')->defaultValue('_switch_user')->end()
  218. ->scalarNode('role')->defaultValue('ROLE_ALLOWED_TO_SWITCH')->end()
  219. ->end()
  220. ->end()
  221. ;
  222. foreach ($factories as $factoriesAtPosition) {
  223. foreach ($factoriesAtPosition as $factory) {
  224. $name = str_replace('-', '_', $factory->getKey());
  225. $factoryNode = $firewallNodeBuilder->arrayNode($name)
  226. ->canBeUnset()
  227. ;
  228. $factory->addConfiguration($factoryNode);
  229. }
  230. }
  231. }
  232. private function addProvidersSection(ArrayNodeDefinition $rootNode)
  233. {
  234. $rootNode
  235. ->fixXmlConfig('provider')
  236. ->children()
  237. ->arrayNode('providers')
  238. ->disallowNewKeysInSubsequentConfigs()
  239. ->isRequired()
  240. ->requiresAtLeastOneElement()
  241. ->useAttributeAsKey('name')
  242. ->prototype('array')
  243. ->children()
  244. ->scalarNode('id')->end()
  245. ->arrayNode('entity')
  246. ->children()
  247. ->scalarNode('class')->isRequired()->cannotBeEmpty()->end()
  248. ->scalarNode('property')->defaultNull()->end()
  249. ->end()
  250. ->end()
  251. ->end()
  252. ->fixXmlConfig('provider')
  253. ->children()
  254. ->arrayNode('providers')
  255. ->beforeNormalization()
  256. ->ifString()
  257. ->then(function($v) { return preg_split('/\s*,\s*/', $v); })
  258. ->end()
  259. ->prototype('scalar')->end()
  260. ->end()
  261. ->end()
  262. ->fixXmlConfig('user')
  263. ->children()
  264. ->arrayNode('users')
  265. ->useAttributeAsKey('name')
  266. ->prototype('array')
  267. ->children()
  268. ->scalarNode('password')->defaultValue(uniqid())->end()
  269. ->arrayNode('roles')
  270. ->beforeNormalization()->ifString()->then(function($v) { return preg_split('/\s*,\s*/', $v); })->end()
  271. ->prototype('scalar')->end()
  272. ->end()
  273. ->end()
  274. ->end()
  275. ->end()
  276. ->end()
  277. ->end()
  278. ->end()
  279. ->end()
  280. ;
  281. }
  282. private function addEncodersSection(ArrayNodeDefinition $rootNode)
  283. {
  284. $rootNode
  285. ->fixXmlConfig('encoder')
  286. ->children()
  287. ->arrayNode('encoders')
  288. ->requiresAtLeastOneElement()
  289. ->useAttributeAsKey('class')
  290. ->prototype('array')
  291. ->canBeUnset()
  292. ->performNoDeepMerging()
  293. ->beforeNormalization()->ifString()->then(function($v) { return array('algorithm' => $v); })->end()
  294. ->children()
  295. ->scalarNode('algorithm')->cannotBeEmpty()->end()
  296. ->booleanNode('ignore_case')->defaultFalse()->end()
  297. ->booleanNode('encode_as_base64')->defaultTrue()->end()
  298. ->scalarNode('iterations')->defaultValue(5000)->end()
  299. ->scalarNode('id')->end()
  300. ->end()
  301. ->end()
  302. ->end()
  303. ->end()
  304. ;
  305. }
  306. }