misuzu/database/2023_08_30_213930_new_permissions_system.php

125 lines
6 KiB
PHP

<?php
use Index\Data\IDbConnection;
use Index\Data\Migration\IDbMigration;
final class NewPermissionsSystem_20230830_213930 implements IDbMigration {
public function migrate(IDbConnection $conn): void {
// make sure cron doesn't fuck us over
$conn->execute('DELETE FROM msz_config WHERE config_name = "perms.needsRecalc"');
$conn->execute('
CREATE TABLE msz_perms (
user_id INT(10) UNSIGNED NULL DEFAULT NULL,
role_id INT(10) UNSIGNED NULL DEFAULT NULL,
forum_id INT(10) UNSIGNED NULL DEFAULT NULL,
perms_category VARBINARY(64) NOT NULL,
perms_allow BIGINT(20) UNSIGNED NOT NULL,
perms_deny BIGINT(20) UNSIGNED NOT NULL,
UNIQUE KEY perms_unique (user_id, role_id, forum_id, perms_category),
KEY perms_user_foreign (user_id),
KEY perms_role_foreign (role_id),
KEY perms_forum_foreign (forum_id),
KEY perms_category_index (perms_category),
CONSTRAINT perms_user_foreign
FOREIGN KEY (user_id)
REFERENCES msz_users (user_id)
ON UPDATE CASCADE
ON DELETE CASCADE,
CONSTRAINT perms_role_foreign
FOREIGN KEY (role_id)
REFERENCES msz_roles (role_id)
ON UPDATE CASCADE
ON DELETE CASCADE,
CONSTRAINT perms_forum_foreign
FOREIGN KEY (forum_id)
REFERENCES msz_forum_categories (forum_id)
ON UPDATE CASCADE
ON DELETE CASCADE
) ENGINE=InnoDB COLLATE=utf8mb4_bin
');
$conn->execute('
ALTER TABLE msz_perms
ADD CONSTRAINT perms_53bit
CHECK (perms_allow >= 0 AND perms_deny >= 0 AND perms_allow <= 9007199254740991 AND perms_deny <= 9007199254740991),
ADD CONSTRAINT perms_only_user_or_role
CHECK ((user_id IS NULL AND role_id IS NULL) OR (user_id IS NULL AND role_id IS NOT NULL) OR (user_id IS NOT NULL AND role_id IS NULL))
');
$conn->execute('
CREATE TABLE msz_perms_calculated (
user_id INT(10) UNSIGNED NULL DEFAULT NULL,
forum_id INT(10) UNSIGNED NULL DEFAULT NULL,
perms_category VARBINARY(64) NOT NULL,
perms_calculated BIGINT(20) UNSIGNED NOT NULL,
UNIQUE KEY perms_calculated_unique (user_id, forum_id, perms_category),
KEY perms_calculated_user_foreign (user_id),
KEY perms_calculated_forum_foreign (forum_id),
KEY perms_calculated_category_index (perms_category),
CONSTRAINT perms_calculated_user_foreign
FOREIGN KEY (user_id)
REFERENCES msz_users (user_id)
ON UPDATE CASCADE
ON DELETE CASCADE,
CONSTRAINT perms_calculated_forum_foreign
FOREIGN KEY (forum_id)
REFERENCES msz_forum_categories (forum_id)
ON UPDATE CASCADE
ON DELETE CASCADE
) ENGINE=InnoDB COLLATE=utf8mb4_bin
');
$conn->execute('
ALTER TABLE msz_perms_calculated
ADD CONSTRAINT perms_calculated_53bit
CHECK (perms_calculated >= 0 AND perms_calculated <= 9007199254740991)
');
$insert = $conn->prepare('INSERT INTO msz_perms (user_id, role_id, forum_id, perms_category, perms_allow, perms_deny) VALUES (?, ?, ?, ?, ?, ?)');
$result = $conn->query('SELECT user_id, role_id, general_perms_allow, general_perms_deny, user_perms_allow, user_perms_deny, changelog_perms_allow, changelog_perms_deny, news_perms_allow, news_perms_deny, forum_perms_allow, forum_perms_deny, comments_perms_allow, comments_perms_deny FROM msz_permissions');
while($result->next()) {
$insert->addParameter(1, $result->isNull(0) ? null : $result->getString(0));
$insert->addParameter(2, $result->isNull(1) ? null : $result->getString(1));
$insert->addParameter(3, null);
$insert->addParameter(4, 'user');
$insert->addParameter(5, $result->getInteger(4));
$insert->addParameter(6, $result->getInteger(5));
$insert->execute();
$allow = $result->getInteger(2);
$allow |= $result->getInteger(6) << 8;
$allow |= $result->getInteger(8) << 16;
$allow |= $result->getInteger(10) << 24;
$allow |= $result->getInteger(12) << 32;
$deny = $result->getInteger(3);
$deny |= $result->getInteger(7) << 8;
$deny |= $result->getInteger(9) << 16;
$deny |= $result->getInteger(11) << 24;
$deny |= $result->getInteger(13) << 32;
$insert->addParameter(4, 'global');
$insert->addParameter(5, $allow);
$insert->addParameter(6, $deny);
$insert->execute();
}
$result = $conn->query('SELECT user_id, role_id, forum_id, forum_perms_allow, forum_perms_deny FROM msz_forum_permissions');
while($result->next()) {
$insert->addParameter(1, $result->isNull(0) ? null : $result->getString(0));
$insert->addParameter(2, $result->isNull(1) ? null : $result->getString(1));
$insert->addParameter(3, $result->getString(2));
$insert->addParameter(4, 'forum');
$insert->addParameter(5, $result->getInteger(3));
$insert->addParameter(6, $result->getInteger(4));
$insert->execute();
}
$conn->execute('DROP TABLE msz_forum_permissions');
$conn->execute('DROP TABLE msz_permissions');
// schedule recalc
$conn->execute('INSERT INTO msz_config (config_name, config_value) VALUES ("perms.needsRecalc", "b:1;")');
}
}