m140506_102106_rbac_init.php 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. <?php
  2. /**
  3. * @link http://www.yiiframework.com/
  4. * @copyright Copyright (c) 2008 Yii Software LLC
  5. * @license http://www.yiiframework.com/license/
  6. */
  7. use yii\base\InvalidConfigException;
  8. use yii\rbac\DbManager;
  9. /**
  10. * Initializes RBAC tables
  11. *
  12. * @author Alexander Kochetov <creocoder@gmail.com>
  13. * @since 2.0
  14. */
  15. class m140506_102106_rbac_init extends \yii\db\Migration
  16. {
  17. /**
  18. * @throws yii\base\InvalidConfigException
  19. * @return DbManager
  20. */
  21. protected function getAuthManager()
  22. {
  23. $authManager = Yii::$app->getAuthManager();
  24. if (!$authManager instanceof DbManager) {
  25. throw new InvalidConfigException('You should configure "authManager" component to use database before executing this migration.');
  26. }
  27. return $authManager;
  28. }
  29. /**
  30. * @return bool
  31. */
  32. protected function isMSSQL()
  33. {
  34. return $this->db->driverName === 'mssql' || $this->db->driverName === 'sqlsrv' || $this->db->driverName === 'dblib';
  35. }
  36. /**
  37. * @inheritdoc
  38. */
  39. public function up()
  40. {
  41. $authManager = $this->getAuthManager();
  42. $this->db = $authManager->db;
  43. $tableOptions = null;
  44. if ($this->db->driverName === 'mysql') {
  45. // http://stackoverflow.com/questions/766809/whats-the-difference-between-utf8-general-ci-and-utf8-unicode-ci
  46. $tableOptions = 'CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE=InnoDB';
  47. }
  48. $this->createTable($authManager->ruleTable, [
  49. 'name' => $this->string(64)->notNull(),
  50. 'data' => $this->binary(),
  51. 'created_at' => $this->integer(),
  52. 'updated_at' => $this->integer(),
  53. 'PRIMARY KEY (name)',
  54. ], $tableOptions);
  55. $this->createTable($authManager->itemTable, [
  56. 'name' => $this->string(64)->notNull(),
  57. 'type' => $this->smallInteger()->notNull(),
  58. 'description' => $this->text(),
  59. 'rule_name' => $this->string(64),
  60. 'data' => $this->binary(),
  61. 'created_at' => $this->integer(),
  62. 'updated_at' => $this->integer(),
  63. 'PRIMARY KEY (name)',
  64. 'FOREIGN KEY (rule_name) REFERENCES ' . $authManager->ruleTable . ' (name)'.
  65. ($this->isMSSQL() ? '' : ' ON DELETE SET NULL ON UPDATE CASCADE'),
  66. ], $tableOptions);
  67. $this->createIndex('idx-auth_item-type', $authManager->itemTable, 'type');
  68. $this->createTable($authManager->itemChildTable, [
  69. 'parent' => $this->string(64)->notNull(),
  70. 'child' => $this->string(64)->notNull(),
  71. 'PRIMARY KEY (parent, child)',
  72. 'FOREIGN KEY (parent) REFERENCES ' . $authManager->itemTable . ' (name)'.
  73. ($this->isMSSQL() ? '' : ' ON DELETE CASCADE ON UPDATE CASCADE'),
  74. 'FOREIGN KEY (child) REFERENCES ' . $authManager->itemTable . ' (name)'.
  75. ($this->isMSSQL() ? '' : ' ON DELETE CASCADE ON UPDATE CASCADE'),
  76. ], $tableOptions);
  77. $this->createTable($authManager->assignmentTable, [
  78. 'item_name' => $this->string(64)->notNull(),
  79. 'user_id' => $this->string(64)->notNull(),
  80. 'created_at' => $this->integer(),
  81. 'PRIMARY KEY (item_name, user_id)',
  82. 'FOREIGN KEY (item_name) REFERENCES ' . $authManager->itemTable . ' (name) ON DELETE CASCADE ON UPDATE CASCADE',
  83. ], $tableOptions);
  84. if ($this->isMSSQL()) {
  85. $this->execute("CREATE TRIGGER dbo.trigger_auth_item_child
  86. ON dbo.{$authManager->itemTable}
  87. INSTEAD OF DELETE, UPDATE
  88. AS
  89. DECLARE @old_name VARCHAR (64) = (SELECT name FROM deleted)
  90. DECLARE @new_name VARCHAR (64) = (SELECT name FROM inserted)
  91. BEGIN
  92. IF COLUMNS_UPDATED() > 0
  93. BEGIN
  94. IF @old_name <> @new_name
  95. BEGIN
  96. ALTER TABLE {$authManager->itemChildTable} NOCHECK CONSTRAINT FK__auth_item__child;
  97. UPDATE {$authManager->itemChildTable} SET child = @new_name WHERE child = @old_name;
  98. END
  99. UPDATE {$authManager->itemTable}
  100. SET name = (SELECT name FROM inserted),
  101. type = (SELECT type FROM inserted),
  102. description = (SELECT description FROM inserted),
  103. rule_name = (SELECT rule_name FROM inserted),
  104. data = (SELECT data FROM inserted),
  105. created_at = (SELECT created_at FROM inserted),
  106. updated_at = (SELECT updated_at FROM inserted)
  107. WHERE name IN (SELECT name FROM deleted)
  108. IF @old_name <> @new_name
  109. BEGIN
  110. ALTER TABLE {$authManager->itemChildTable} CHECK CONSTRAINT FK__auth_item__child;
  111. END
  112. END
  113. ELSE
  114. BEGIN
  115. DELETE FROM dbo.{$authManager->itemChildTable} WHERE parent IN (SELECT name FROM deleted) OR child IN (SELECT name FROM deleted);
  116. DELETE FROM dbo.{$authManager->itemTable} WHERE name IN (SELECT name FROM deleted);
  117. END
  118. END;");
  119. }
  120. }
  121. /**
  122. * @inheritdoc
  123. */
  124. public function down()
  125. {
  126. $authManager = $this->getAuthManager();
  127. $this->db = $authManager->db;
  128. if ($this->isMSSQL()) {
  129. $this->execute('DROP TRIGGER dbo.trigger_auth_item_child;');
  130. }
  131. $this->dropTable($authManager->assignmentTable);
  132. $this->dropTable($authManager->itemChildTable);
  133. $this->dropTable($authManager->itemTable);
  134. $this->dropTable($authManager->ruleTable);
  135. }
  136. }