MongoDbManagerTest.php 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524
  1. <?php
  2. namespace yiiunit\extensions\mongodb\rbac;
  3. use Yii;
  4. use yii\caching\ArrayCache;
  5. use yii\rbac\Item;
  6. use yii\rbac\Permission;
  7. use yii\rbac\Role;
  8. use yii\mongodb\rbac\MongoDbManager;
  9. use yiiunit\extensions\mongodb\data\rbac\ActionRule;
  10. use yiiunit\extensions\mongodb\data\rbac\AuthorRule;
  11. use yiiunit\extensions\mongodb\TestCase;
  12. class MongoDbManagerTest extends TestCase
  13. {
  14. /**
  15. * @var MongoDbManager
  16. */
  17. protected $auth;
  18. protected function setUp()
  19. {
  20. parent::setUp();
  21. $this->auth = $this->createManager();
  22. }
  23. protected function tearDown()
  24. {
  25. $this->dropCollection('auth_item');
  26. $this->dropCollection('auth_assignment');
  27. $this->dropCollection('auth_rule');
  28. parent::tearDown();
  29. }
  30. /**
  31. * @return MongoDbManager
  32. */
  33. protected function createManager()
  34. {
  35. return new MongoDbManager(['db' => $this->getConnection()]);
  36. }
  37. // Tests :
  38. public function testCreateRole()
  39. {
  40. $role = $this->auth->createRole('admin');
  41. $this->assertTrue($role instanceof Role);
  42. $this->assertEquals(Item::TYPE_ROLE, $role->type);
  43. $this->assertEquals('admin', $role->name);
  44. }
  45. public function testCreatePermission()
  46. {
  47. $permission = $this->auth->createPermission('edit post');
  48. $this->assertTrue($permission instanceof Permission);
  49. $this->assertEquals(Item::TYPE_PERMISSION, $permission->type);
  50. $this->assertEquals('edit post', $permission->name);
  51. }
  52. public function testAdd()
  53. {
  54. $role = $this->auth->createRole('admin');
  55. $role->description = 'administrator';
  56. $this->assertTrue($this->auth->add($role));
  57. $permission = $this->auth->createPermission('edit post');
  58. $permission->description = 'edit a post';
  59. $this->assertTrue($this->auth->add($permission));
  60. $rule = new AuthorRule(['name' => 'is author', 'reallyReally' => true]);
  61. $this->assertTrue($this->auth->add($rule));
  62. // todo: check duplication of name
  63. }
  64. public function testGetChildren()
  65. {
  66. $user = $this->auth->createRole('user');
  67. $this->auth->add($user);
  68. $this->assertCount(0, $this->auth->getChildren($user->name));
  69. $changeName = $this->auth->createPermission('changeName');
  70. $this->auth->add($changeName);
  71. $this->auth->addChild($user, $changeName);
  72. $this->assertCount(1, $this->auth->getChildren($user->name));
  73. }
  74. public function testGetRule()
  75. {
  76. $this->prepareData();
  77. $rule = $this->auth->getRule('isAuthor');
  78. $this->assertInstanceOf('yii\rbac\Rule', $rule);
  79. $this->assertEquals('isAuthor', $rule->name);
  80. $rule = $this->auth->getRule('nonExisting');
  81. $this->assertNull($rule);
  82. }
  83. public function testAddRule()
  84. {
  85. $this->prepareData();
  86. $ruleName = 'isReallyReallyAuthor';
  87. $rule = new AuthorRule(['name' => $ruleName, 'reallyReally' => true]);
  88. $this->auth->add($rule);
  89. $rule = $this->auth->getRule($ruleName);
  90. $this->assertEquals($ruleName, $rule->name);
  91. $this->assertEquals(true, $rule->reallyReally);
  92. }
  93. public function testUpdateRule()
  94. {
  95. $this->prepareData();
  96. $rule = $this->auth->getRule('isAuthor');
  97. $rule->name = "newName";
  98. $rule->reallyReally = false;
  99. $this->auth->update('isAuthor', $rule);
  100. $rule = $this->auth->getRule('isAuthor');
  101. $this->assertEquals(null, $rule);
  102. $rule = $this->auth->getRule('newName');
  103. $this->assertEquals("newName", $rule->name);
  104. $this->assertEquals(false, $rule->reallyReally);
  105. $rule->reallyReally = true;
  106. $this->auth->update('newName', $rule);
  107. $rule = $this->auth->getRule('newName');
  108. $this->assertEquals(true, $rule->reallyReally);
  109. $item = $this->auth->getPermission('createPost');
  110. $item->name = 'new createPost';
  111. $this->auth->update('createPost', $item);
  112. $item = $this->auth->getPermission('createPost');
  113. $this->assertEquals(null, $item);
  114. $item = $this->auth->getPermission('new createPost');
  115. $this->assertEquals('new createPost', $item->name);
  116. }
  117. public function testGetRules()
  118. {
  119. $this->prepareData();
  120. $rule = new AuthorRule(['name' => 'isReallyReallyAuthor', 'reallyReally' => true]);
  121. $this->auth->add($rule);
  122. $rules = $this->auth->getRules();
  123. $ruleNames = [];
  124. foreach ($rules as $rule) {
  125. $ruleNames[] = $rule->name;
  126. }
  127. $this->assertContains('isReallyReallyAuthor', $ruleNames);
  128. $this->assertContains('isAuthor', $ruleNames);
  129. }
  130. public function testRemoveRule()
  131. {
  132. $this->prepareData();
  133. $this->auth->remove($this->auth->getRule('isAuthor'));
  134. $rules = $this->auth->getRules();
  135. $this->assertEmpty($rules);
  136. $this->auth->remove($this->auth->getPermission('createPost'));
  137. $item = $this->auth->getPermission('createPost');
  138. $this->assertNull($item);
  139. }
  140. public function testCheckAccess()
  141. {
  142. $this->prepareData();
  143. $testSuites = [
  144. 'reader A' => [
  145. 'createPost' => false,
  146. 'readPost' => true,
  147. 'updatePost' => false,
  148. 'updateAnyPost' => false,
  149. ],
  150. 'author B' => [
  151. 'createPost' => true,
  152. 'readPost' => true,
  153. 'updatePost' => true,
  154. 'deletePost' => true,
  155. 'updateAnyPost' => false,
  156. ],
  157. 'admin C' => [
  158. 'createPost' => true,
  159. 'readPost' => true,
  160. 'updatePost' => false,
  161. 'updateAnyPost' => true,
  162. 'blablabla' => false,
  163. null => false,
  164. ],
  165. ];
  166. $params = ['authorID' => 'author B'];
  167. foreach ($testSuites as $user => $tests) {
  168. foreach ($tests as $permission => $result) {
  169. $this->assertEquals($result, $this->auth->checkAccess($user, $permission, $params), "Checking $user can $permission");
  170. }
  171. }
  172. }
  173. protected function prepareData()
  174. {
  175. $rule = new AuthorRule;
  176. $this->auth->add($rule);
  177. $uniqueTrait = $this->auth->createPermission('Fast Metabolism');
  178. $uniqueTrait->description = 'Your metabolic rate is twice normal. This means that you are much less resistant to radiation and poison, but your body heals faster.';
  179. $this->auth->add($uniqueTrait);
  180. $createPost = $this->auth->createPermission('createPost');
  181. $createPost->description = 'create a post';
  182. $this->auth->add($createPost);
  183. $readPost = $this->auth->createPermission('readPost');
  184. $readPost->description = 'read a post';
  185. $this->auth->add($readPost);
  186. $deletePost = $this->auth->createPermission('deletePost');
  187. $deletePost->description = 'delete a post';
  188. $this->auth->add($deletePost);
  189. $updatePost = $this->auth->createPermission('updatePost');
  190. $updatePost->description = 'update a post';
  191. $updatePost->ruleName = $rule->name;
  192. $this->auth->add($updatePost);
  193. $updateAnyPost = $this->auth->createPermission('updateAnyPost');
  194. $updateAnyPost->description = 'update any post';
  195. $this->auth->add($updateAnyPost);
  196. $withoutChildren = $this->auth->createRole('withoutChildren');
  197. $this->auth->add($withoutChildren);
  198. $reader = $this->auth->createRole('reader');
  199. $this->auth->add($reader);
  200. $this->auth->addChild($reader, $readPost);
  201. $author = $this->auth->createRole('author');
  202. $this->auth->add($author);
  203. $this->auth->addChild($author, $createPost);
  204. $this->auth->addChild($author, $updatePost);
  205. $this->auth->addChild($author, $reader);
  206. $admin = $this->auth->createRole('admin');
  207. $this->auth->add($admin);
  208. $this->auth->addChild($admin, $author);
  209. $this->auth->addChild($admin, $updateAnyPost);
  210. $this->auth->assign($uniqueTrait, 'reader A');
  211. $this->auth->assign($reader, 'reader A');
  212. $this->auth->assign($author, 'author B');
  213. $this->auth->assign($deletePost, 'author B');
  214. $this->auth->assign($admin, 'admin C');
  215. }
  216. public function testGetPermissionsByRole()
  217. {
  218. $this->prepareData();
  219. $permissions = $this->auth->getPermissionsByRole('admin');
  220. $expectedPermissions = ['createPost', 'updatePost', 'readPost', 'updateAnyPost'];
  221. $this->assertEquals(count($expectedPermissions), count($permissions));
  222. foreach ($expectedPermissions as $permissionName) {
  223. $this->assertTrue($permissions[$permissionName] instanceof Permission);
  224. }
  225. }
  226. public function testGetPermissionsByUser()
  227. {
  228. $this->prepareData();
  229. $permissions = $this->auth->getPermissionsByUser('author B');
  230. $expectedPermissions = ['deletePost', 'createPost', 'updatePost', 'readPost'];
  231. $this->assertEquals(count($expectedPermissions), count($permissions));
  232. foreach ($expectedPermissions as $permissionName) {
  233. $this->assertTrue($permissions[$permissionName] instanceof Permission);
  234. }
  235. }
  236. public function testGetRolesByUser()
  237. {
  238. $this->prepareData();
  239. $reader = $this->auth->getRole('reader');
  240. $this->auth->assign($reader, 0);
  241. $this->auth->assign($reader, 123);
  242. $roles = $this->auth->getRolesByUser('reader A');
  243. $this->assertTrue(reset($roles) instanceof Role);
  244. $this->assertEquals($roles['reader']->name, 'reader');
  245. $roles = $this->auth->getRolesByUser(0);
  246. $this->assertTrue(reset($roles) instanceof Role);
  247. $this->assertEquals($roles['reader']->name, 'reader');
  248. $roles = $this->auth->getRolesByUser(123);
  249. $this->assertTrue(reset($roles) instanceof Role);
  250. $this->assertEquals($roles['reader']->name, 'reader');
  251. $this->auth->defaultRoles = ['testDefaultRole'];
  252. $roles = $this->auth->getRolesByUser('default');
  253. $this->assertTrue(reset($roles) instanceof Role);
  254. $this->assertEquals($roles['testDefaultRole']->name, 'testDefaultRole');
  255. }
  256. public function testGetChildRoles()
  257. {
  258. $this->prepareData();
  259. $roles = $this->auth->getChildRoles('withoutChildren');
  260. $this->assertCount(1, $roles);
  261. $this->assertInstanceOf(Role::className(), reset($roles));
  262. $this->assertTrue(reset($roles)->name === 'withoutChildren');
  263. $roles = $this->auth->getChildRoles('reader');
  264. $this->assertCount(1, $roles);
  265. $this->assertInstanceOf(Role::className(), reset($roles));
  266. $this->assertTrue(reset($roles)->name === 'reader');
  267. $roles = $this->auth->getChildRoles('author');
  268. $this->assertCount(2, $roles);
  269. $this->assertArrayHasKey('author', $roles);
  270. $this->assertArrayHasKey('reader', $roles);
  271. $roles = $this->auth->getChildRoles('admin');
  272. $this->assertCount(3, $roles);
  273. $this->assertArrayHasKey('admin', $roles);
  274. $this->assertArrayHasKey('author', $roles);
  275. $this->assertArrayHasKey('reader', $roles);
  276. }
  277. public function testAssignMultipleRoles()
  278. {
  279. $this->prepareData();
  280. $reader = $this->auth->getRole('reader');
  281. $author = $this->auth->getRole('author');
  282. $this->auth->assign($reader, 'readingAuthor');
  283. $this->auth->assign($author, 'readingAuthor');
  284. $this->auth = $this->createManager();
  285. $roles = $this->auth->getRolesByUser('readingAuthor');
  286. $roleNames = [];
  287. foreach ($roles as $role) {
  288. $roleNames[] = $role->name;
  289. }
  290. $this->assertContains('reader', $roleNames, 'Roles should contain reader. Currently it has: ' . implode(', ', $roleNames));
  291. $this->assertContains('author', $roleNames, 'Roles should contain author. Currently it has: ' . implode(', ', $roleNames));
  292. }
  293. public function testAssignmentsToIntegerId()
  294. {
  295. $this->prepareData();
  296. $reader = $this->auth->getRole('reader');
  297. $author = $this->auth->getRole('author');
  298. $this->auth->assign($reader, 42);
  299. $this->auth->assign($author, 1337);
  300. $this->auth->assign($reader, 1337);
  301. $this->auth = $this->createManager();
  302. $this->assertEquals(0, count($this->auth->getAssignments(0)));
  303. $this->assertEquals(1, count($this->auth->getAssignments(42)));
  304. $this->assertEquals(2, count($this->auth->getAssignments(1337)));
  305. }
  306. public function testGetAssignmentsByRole()
  307. {
  308. $this->prepareData();
  309. $reader = $this->auth->getRole('reader');
  310. $this->auth->assign($reader, 123);
  311. $this->auth = $this->createManager();
  312. $this->assertEquals([], $this->auth->getUserIdsByRole('nonexisting'));
  313. $this->assertEquals(['reader A', '123'], $this->auth->getUserIdsByRole('reader'), '', 0.0, 10, true);
  314. $this->assertEquals(['author B'], $this->auth->getUserIdsByRole('author'));
  315. $this->assertEquals(['admin C'], $this->auth->getUserIdsByRole('admin'));
  316. }
  317. public function testCanAddChild()
  318. {
  319. $this->prepareData();
  320. $author = $this->auth->createRole('author');
  321. $reader = $this->auth->createRole('reader');
  322. $this->assertTrue($this->auth->canAddChild($author, $reader));
  323. $this->assertFalse($this->auth->canAddChild($reader, $author));
  324. }
  325. public function testRemoveAllRules()
  326. {
  327. $this->prepareData();
  328. $this->auth->removeAllRules();
  329. $this->assertEmpty($this->auth->getRules());
  330. $this->assertNotEmpty($this->auth->getRoles());
  331. $this->assertNotEmpty($this->auth->getPermissions());
  332. }
  333. public function testRemoveAllRoles()
  334. {
  335. $this->prepareData();
  336. $this->auth->removeAllRoles();
  337. $this->assertEmpty($this->auth->getRoles());
  338. $this->assertNotEmpty($this->auth->getRules());
  339. $this->assertNotEmpty($this->auth->getPermissions());
  340. }
  341. public function testRemoveAllPermissions()
  342. {
  343. $this->prepareData();
  344. $this->auth->removeAllPermissions();
  345. $this->assertEmpty($this->auth->getPermissions());
  346. $this->assertNotEmpty($this->auth->getRules());
  347. $this->assertNotEmpty($this->auth->getRoles());
  348. }
  349. public function testAssignRule()
  350. {
  351. $auth = $this->auth;
  352. $userId = 3;
  353. $auth->removeAll();
  354. $role = $auth->createRole('Admin');
  355. $auth->add($role);
  356. $auth->assign($role, $userId);
  357. $this->assertTrue($auth->checkAccess($userId, 'Admin'));
  358. // with normal register rule
  359. $auth->removeAll();
  360. $rule = new ActionRule();
  361. $auth->add($rule);
  362. $role = $auth->createRole('Reader');
  363. $role->ruleName = $rule->name;
  364. $auth->add($role);
  365. $auth->assign($role, $userId);
  366. $this->assertTrue($auth->checkAccess($userId, 'Reader', ['action' => 'read']));
  367. $this->assertFalse($auth->checkAccess($userId, 'Reader', ['action' => 'write']));
  368. // using rule class name
  369. $auth->removeAll();
  370. $role = $auth->createRole('Reader');
  371. $role->ruleName = 'yiiunit\extensions\mongodb\data\rbac\ActionRule';
  372. $auth->add($role);
  373. $auth->assign($role, $userId);
  374. $this->assertTrue($auth->checkAccess($userId, 'Reader', ['action' => 'read']));
  375. $this->assertFalse($auth->checkAccess($userId, 'Reader', ['action' => 'write']));
  376. // using DI
  377. \Yii::$container->set('write_rule', ['class' => 'yiiunit\extensions\mongodb\data\rbac\ActionRule', 'action' => 'write']);
  378. \Yii::$container->set('delete_rule', ['class' => 'yiiunit\extensions\mongodb\data\rbac\ActionRule', 'action' => 'delete']);
  379. \Yii::$container->set('all_rule', ['class' => 'yiiunit\extensions\mongodb\data\rbac\ActionRule', 'action' => 'all']);
  380. $role = $auth->createRole('Writer');
  381. $role->ruleName = 'write_rule';
  382. $auth->add($role);
  383. $auth->assign($role, $userId);
  384. $this->assertTrue($auth->checkAccess($userId, 'Writer', ['action' => 'write']));
  385. $this->assertFalse($auth->checkAccess($userId, 'Writer', ['action' => 'update']));
  386. $role = $auth->createRole('Deleter');
  387. $role->ruleName = 'delete_rule';
  388. $auth->add($role);
  389. $auth->assign($role, $userId);
  390. $this->assertTrue($auth->checkAccess($userId, 'Deleter', ['action' => 'delete']));
  391. $this->assertFalse($auth->checkAccess($userId, 'Deleter', ['action' => 'update']));
  392. $role = $auth->createRole('Author');
  393. $role->ruleName = 'all_rule';
  394. $auth->add($role);
  395. $auth->assign($role, $userId);
  396. $this->assertTrue($auth->checkAccess($userId, 'Author', ['action' => 'update']));
  397. // update role and rule
  398. $role = $auth->getRole('Reader');
  399. $role->name = 'AdminPost';
  400. $role->ruleName = 'all_rule';
  401. $auth->update('Reader', $role);
  402. $this->assertTrue($auth->checkAccess($userId, 'AdminPost', ['action' => 'print']));
  403. }
  404. public function testInvalidateCache()
  405. {
  406. $auth = $this->auth;
  407. $auth->cache = new ArrayCache();
  408. $this->prepareData();
  409. $auth->loadFromCache();
  410. $auth->getRule('reader');
  411. $auth->invalidateCache();
  412. $this->assertFalse($auth->cache->exists($auth->cacheKey));
  413. }
  414. }