github.com/dolthub/dolt/go@v0.40.5-0.20240520175717-68db7794bea6/libraries/doltcore/sqle/enginetest/branch_control_test.go (about) 1 // Copyright 2022 Dolthub, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package enginetest 16 17 import ( 18 "testing" 19 20 "github.com/dolthub/go-mysql-server/enginetest" 21 "github.com/dolthub/go-mysql-server/sql" 22 "github.com/dolthub/go-mysql-server/sql/mysql_db" 23 "github.com/dolthub/go-mysql-server/sql/plan" 24 "github.com/dolthub/go-mysql-server/sql/types" 25 "github.com/stretchr/testify/assert" 26 "github.com/stretchr/testify/require" 27 "gopkg.in/src-d/go-errors.v1" 28 29 "github.com/dolthub/dolt/go/libraries/doltcore/branch_control" 30 ) 31 32 // BranchControlTest is used to define a test using the branch control system. The root account is used with any queries 33 // in the SetUpScript. 34 type BranchControlTest struct { 35 Name string 36 SetUpScript []string 37 Assertions []BranchControlTestAssertion 38 } 39 40 // BranchControlTestAssertion is within a BranchControlTest to assert functionality. 41 type BranchControlTestAssertion struct { 42 User string 43 Host string 44 Query string 45 Expected []sql.Row 46 ExpectedErr *errors.Kind 47 ExpectedErrStr string 48 } 49 50 // BranchControlBlockTest are tests for quickly verifying that a command is blocked before the appropriate entry is 51 // added to the "dolt_branch_control" table. The `TestUserSetUpScripts` are automatically run before every test, 52 // therefore any set up here is essentially appended to `TestUserSetUpScripts`. In addition, the test user is 53 // `testuser`@`localhost`. 54 type BranchControlBlockTest struct { 55 Name string 56 SetUpScript []string 57 Query string 58 ExpectedErr *errors.Kind 59 SkipMessage string 60 } 61 62 // TestUserSetUpScripts creates a user named "testuser@localhost", and grants them privileges on all databases and 63 // tables. In addition, creates a committed table named "test" with a single value, along with a mirror branch named 64 // "other". 65 var TestUserSetUpScripts = []string{ 66 "DELETE FROM dolt_branch_control WHERE user = '%';", 67 "INSERT INTO dolt_branch_control VALUES ('%', '%', 'root', 'localhost', 'admin');", 68 "CREATE USER testuser@localhost;", 69 "GRANT ALL ON *.* TO testuser@localhost;", 70 "REVOKE SUPER ON *.* FROM testuser@localhost;", 71 "CREATE TABLE test (pk BIGINT PRIMARY KEY, v1 BIGINT);", 72 "INSERT INTO test VALUES (1, 1);", 73 "CALL DOLT_ADD('-A');", 74 "CALL DOLT_COMMIT('-m', 'setup commit');", 75 "CALL DOLT_BRANCH('other');", 76 } 77 78 var BranchControlBlockTests = []BranchControlBlockTest{ 79 { 80 Name: "INSERT", 81 Query: "INSERT INTO test VALUES (2, 2);", 82 ExpectedErr: branch_control.ErrIncorrectPermissions, 83 }, 84 { 85 Name: "INSERT on branch db", 86 Query: "INSERT INTO `mydb/other`.test VALUES (2, 2);", 87 ExpectedErr: branch_control.ErrIncorrectPermissions, 88 }, 89 { 90 Name: "REPLACE", 91 Query: "REPLACE INTO test VALUES (2, 2);", 92 ExpectedErr: branch_control.ErrIncorrectPermissions, 93 }, 94 { 95 Name: "UPDATE", 96 Query: "UPDATE test SET pk = 2;", 97 ExpectedErr: branch_control.ErrIncorrectPermissions, 98 }, 99 { 100 Name: "UPDATE on branch db", 101 Query: "UPDATE `mydb/other`.test SET pk = 2;", 102 ExpectedErr: branch_control.ErrIncorrectPermissions, 103 }, 104 { 105 Name: "DELETE", 106 Query: "DELETE FROM test WHERE pk >= 0;", 107 ExpectedErr: branch_control.ErrIncorrectPermissions, 108 }, 109 { 110 Name: "DELETE from branch table", 111 Query: "DELETE FROM `mydb/other`.test WHERE pk >= 0;", 112 ExpectedErr: branch_control.ErrIncorrectPermissions, 113 }, 114 { 115 Name: "TRUNCATE", 116 Query: "TRUNCATE TABLE test;", 117 ExpectedErr: branch_control.ErrIncorrectPermissions, 118 }, 119 { 120 Name: "ALTER TABLE AUTO_INCREMENT", 121 SetUpScript: []string{ 122 "CREATE TABLE test2(pk BIGINT PRIMARY KEY AUTO_INCREMENT);", 123 }, 124 Query: "ALTER TABLE test2 AUTO_INCREMENT = 20;", 125 ExpectedErr: branch_control.ErrIncorrectPermissions, 126 }, 127 { 128 Name: "ALTER TABLE ADD CHECK", 129 Query: "ALTER TABLE test ADD CONSTRAINT check_1 CHECK (pk > 0);", 130 ExpectedErr: branch_control.ErrIncorrectPermissions, 131 }, 132 { 133 Name: "ALTER TABLE DROP CHECK", 134 SetUpScript: []string{ 135 "ALTER TABLE test ADD CONSTRAINT check_1 CHECK (pk > 0);", 136 }, 137 Query: "ALTER TABLE test DROP CHECK check_1;", 138 ExpectedErr: branch_control.ErrIncorrectPermissions, 139 }, 140 { 141 Name: "ALTER TABLE ALTER COLUMN SET DEFAULT", 142 Query: "ALTER TABLE test ALTER COLUMN v1 SET DEFAULT (5);", 143 ExpectedErr: branch_control.ErrIncorrectPermissions, 144 }, 145 { 146 Name: "ALTER TABLE ALTER COLUMN DROP DEFAULT", 147 SetUpScript: []string{ 148 "ALTER TABLE test ALTER COLUMN v1 SET DEFAULT (5);", 149 }, 150 Query: "ALTER TABLE test ALTER COLUMN v1 DROP DEFAULT;", 151 ExpectedErr: branch_control.ErrIncorrectPermissions, 152 }, 153 { 154 Name: "ALTER TABLE ADD FOREIGN KEY", 155 SetUpScript: []string{ 156 "ALTER TABLE test ADD INDEX idx_v1 (v1);", 157 "CREATE TABLE test2 (pk BIGINT PRIMARY KEY, v1 BIGINT UNIQUE);", 158 }, 159 Query: "ALTER TABLE test2 ADD CONSTRAINT fk_1 FOREIGN KEY (v1) REFERENCES test (v1);", 160 ExpectedErr: branch_control.ErrIncorrectPermissions, 161 }, 162 { 163 Name: "ALTER TABLE DROP FOREIGN KEY", 164 SetUpScript: []string{ 165 "ALTER TABLE test ADD INDEX idx_v1 (v1);", 166 "CREATE TABLE test2 (pk BIGINT PRIMARY KEY, v1 BIGINT UNIQUE, CONSTRAINT fk_1 FOREIGN KEY (v1) REFERENCES test (v1));", 167 }, 168 Query: "ALTER TABLE test2 DROP FOREIGN KEY fk_1;", 169 ExpectedErr: branch_control.ErrIncorrectPermissions, 170 }, 171 { 172 Name: "ALTER TABLE ADD INDEX", 173 Query: "ALTER TABLE test ADD INDEX idx_v1 (v1);", 174 ExpectedErr: branch_control.ErrIncorrectPermissions, 175 }, 176 { 177 Name: "ALTER TABLE DROP INDEX", 178 SetUpScript: []string{ 179 "ALTER TABLE test ADD INDEX idx_v1 (v1);", 180 }, 181 Query: "ALTER TABLE test DROP INDEX idx_v1;", 182 ExpectedErr: branch_control.ErrIncorrectPermissions, 183 }, 184 { 185 Name: "ALTER TABLE RENAME INDEX", 186 SetUpScript: []string{ 187 "ALTER TABLE test ADD INDEX idx_v1 (v1);", 188 }, 189 Query: "ALTER TABLE test RENAME INDEX idx_v1 TO idx_v1_new;", 190 ExpectedErr: branch_control.ErrIncorrectPermissions, 191 }, 192 { 193 Name: "ALTER TABLE ADD PRIMARY KEY", 194 SetUpScript: []string{ 195 "CREATE TABLE test2 (v1 BIGINT, v2 BIGINT);", 196 }, 197 Query: "ALTER TABLE test2 ADD PRIMARY KEY (v1, v2);", 198 ExpectedErr: branch_control.ErrIncorrectPermissions, 199 }, 200 { 201 Name: "ALTER TABLE DROP PRIMARY KEY", 202 Query: "ALTER TABLE test DROP PRIMARY KEY;", 203 ExpectedErr: branch_control.ErrIncorrectPermissions, 204 }, 205 { 206 Name: "ALTER TABLE RENAME", 207 Query: "ALTER TABLE test RENAME TO test_new;", 208 ExpectedErr: branch_control.ErrIncorrectPermissions, 209 }, 210 { 211 Name: "RENAME TABLE", 212 Query: "RENAME TABLE test TO test_new;", 213 ExpectedErr: branch_control.ErrIncorrectPermissions, 214 }, 215 { 216 Name: "ALTER TABLE ADD COLUMN", 217 Query: "ALTER TABLE test ADD COLUMN v2 BIGINT;", 218 ExpectedErr: branch_control.ErrIncorrectPermissions, 219 }, 220 { 221 Name: "ALTER TABLE DROP COLUMN", 222 Query: "ALTER TABLE test DROP COLUMN v1;", 223 ExpectedErr: branch_control.ErrIncorrectPermissions, 224 }, 225 { 226 Name: "ALTER TABLE CHANGE COLUMN", 227 Query: "ALTER TABLE test CHANGE COLUMN v1 v1_new BIGINT;", 228 ExpectedErr: branch_control.ErrIncorrectPermissions, 229 }, 230 { 231 Name: "ALTER TABLE MODIFY COLUMN", 232 Query: "ALTER TABLE test MODIFY COLUMN v1 TINYINT;", 233 ExpectedErr: branch_control.ErrIncorrectPermissions, 234 }, 235 { 236 Name: "ALTER TABLE RENAME COLUMN", 237 Query: "ALTER TABLE test RENAME COLUMN v1 TO v1_new;", 238 ExpectedErr: branch_control.ErrIncorrectPermissions, 239 }, 240 { 241 Name: "CREATE INDEX", 242 Query: "CREATE INDEX idx_v1 ON test (v1);", 243 ExpectedErr: branch_control.ErrIncorrectPermissions, 244 }, 245 { 246 Name: "DROP INDEX", 247 SetUpScript: []string{ 248 "CREATE INDEX idx_v1 ON test (v1);", 249 }, 250 Query: "DROP INDEX idx_v1 ON test;", 251 ExpectedErr: branch_control.ErrIncorrectPermissions, 252 }, 253 { 254 Name: "CREATE VIEW", 255 Query: "CREATE VIEW view_1 AS SELECT * FROM TEST;", 256 ExpectedErr: branch_control.ErrIncorrectPermissions, 257 }, 258 { 259 Name: "DROP VIEW", 260 SetUpScript: []string{ 261 "CREATE VIEW view_1 AS SELECT * FROM TEST;", 262 }, 263 Query: "DROP VIEW view_1;", 264 ExpectedErr: branch_control.ErrIncorrectPermissions, 265 }, 266 { 267 Name: "CREATE TRIGGER", 268 Query: "CREATE TRIGGER trigger_1 BEFORE INSERT ON test FOR EACH ROW SET NEW.v1 = 4;", 269 ExpectedErr: branch_control.ErrIncorrectPermissions, 270 }, 271 { 272 Name: "DROP TRIGGER", 273 SetUpScript: []string{ 274 "CREATE TRIGGER trigger_1 BEFORE INSERT ON test FOR EACH ROW SET NEW.v1 = 4;", 275 }, 276 Query: "DROP TRIGGER trigger_1;", 277 ExpectedErr: branch_control.ErrIncorrectPermissions, 278 }, 279 { 280 Name: "CREATE TABLE", 281 Query: "CREATE TABLE test2 (pk BIGINT PRIMARY KEY, v1 BIGINT);", 282 ExpectedErr: branch_control.ErrIncorrectPermissions, 283 }, 284 { 285 Name: "CREATE TABLE LIKE", 286 Query: "CREATE TABLE test2 LIKE test;", 287 ExpectedErr: branch_control.ErrIncorrectPermissions, 288 }, 289 { 290 Name: "CREATE TABLE AS SELECT", 291 Query: "CREATE TABLE test2 AS SELECT * FROM test;", 292 ExpectedErr: branch_control.ErrIncorrectPermissions, 293 }, 294 { 295 Name: "DROP TABLE", 296 Query: "DROP TABLE test;", 297 ExpectedErr: branch_control.ErrIncorrectPermissions, 298 }, 299 { 300 Name: "CREATE PROCEDURE", 301 Query: "CREATE PROCEDURE testabc(x DOUBLE, y DOUBLE) SELECT x*y;", 302 ExpectedErr: branch_control.ErrIncorrectPermissions, 303 }, 304 { 305 Name: "DROP PROCEDURE", 306 SetUpScript: []string{ 307 "CREATE PROCEDURE testabc(x DOUBLE, y DOUBLE) SELECT x*y;", 308 }, 309 Query: "DROP PROCEDURE testabc;", 310 ExpectedErr: branch_control.ErrIncorrectPermissions, 311 }, 312 // Dolt Procedures 313 { 314 Name: "DOLT_ADD", 315 SetUpScript: []string{ 316 "INSERT INTO test VALUES (2, 2);", 317 }, 318 Query: "CALL DOLT_ADD('-A');", 319 ExpectedErr: branch_control.ErrIncorrectPermissions, 320 }, 321 { // Normal DOLT_BRANCH is tested in BranchControlTests 322 Name: "DOLT_BRANCH Force Copy", 323 Query: "CALL DOLT_BRANCH('-f', '-c', 'main', 'other');", 324 ExpectedErr: branch_control.ErrCannotDeleteBranch, 325 }, 326 { 327 Name: "DOLT_BRANCH Force Move", 328 SetUpScript: []string{ 329 "INSERT INTO dolt_branch_control VALUES ('%', 'newother', 'testuser', 'localhost', 'write');", 330 }, 331 Query: "CALL DOLT_BRANCH('-f', '-m', 'other', 'newother');", 332 ExpectedErr: branch_control.ErrCannotDeleteBranch, 333 }, 334 { 335 Name: "DOLT_BRANCH Delete", 336 Query: "CALL DOLT_BRANCH('-d', 'other');", 337 ExpectedErr: branch_control.ErrCannotDeleteBranch, 338 }, 339 { 340 Name: "DOLT_CLEAN", 341 Query: "CALL DOLT_CLEAN();", 342 ExpectedErr: branch_control.ErrIncorrectPermissions, 343 }, 344 { 345 Name: "DOLT_COMMIT", 346 SetUpScript: []string{ 347 "INSERT INTO test VALUES (2, 2);", 348 "CALL DOLT_ADD('-A');", 349 }, 350 Query: "CALL DOLT_COMMIT('-m', 'message');", 351 ExpectedErr: branch_control.ErrIncorrectPermissions, 352 }, 353 { 354 Name: "DOLT_CONFLICTS_RESOLVE", 355 Query: "CALL DOLT_CONFLICTS_RESOLVE('--ours', '.');", 356 ExpectedErr: branch_control.ErrIncorrectPermissions, 357 }, 358 { 359 Name: "DOLT_MERGE", 360 SetUpScript: []string{ 361 "INSERT INTO test VALUES (2, 2);", 362 "CALL DOLT_ADD('-A');", 363 "CALL DOLT_COMMIT('-m', 'message');", 364 "CALL DOLT_CHECKOUT('other');", 365 }, 366 Query: "CALL DOLT_MERGE('main');", 367 ExpectedErr: branch_control.ErrIncorrectPermissions, 368 }, 369 { 370 Name: "DOLT_RESET", 371 Query: "CALL DOLT_RESET();", 372 ExpectedErr: branch_control.ErrIncorrectPermissions, 373 }, 374 { 375 Name: "DOLT_REVERT", 376 Query: "CALL DOLT_REVERT();", 377 ExpectedErr: branch_control.ErrIncorrectPermissions, 378 }, 379 { 380 Name: "DOLT_VERIFY_CONSTRAINTS", 381 Query: "CALL DOLT_VERIFY_CONSTRAINTS('-a');", 382 ExpectedErr: branch_control.ErrIncorrectPermissions, 383 }, 384 } 385 386 var BranchControlOtherDbBlockTests = []BranchControlBlockTest{ 387 { 388 Name: "INSERT", 389 Query: "INSERT INTO `mydb/other`.test VALUES (2, 2);", 390 ExpectedErr: branch_control.ErrIncorrectPermissions, 391 }, 392 { 393 Name: "REPLACE", 394 Query: "REPLACE INTO `mydb/other`.test VALUES (2, 2);", 395 ExpectedErr: branch_control.ErrIncorrectPermissions, 396 }, 397 { 398 Name: "UPDATE", 399 Query: "UPDATE `mydb/other`.test SET pk = 2;", 400 ExpectedErr: branch_control.ErrIncorrectPermissions, 401 }, 402 { 403 Name: "DELETE", 404 Query: "DELETE FROM `mydb/other`.test WHERE pk >= 0;", 405 ExpectedErr: branch_control.ErrIncorrectPermissions, 406 }, 407 { 408 Name: "TRUNCATE", 409 Query: "TRUNCATE TABLE `mydb/other`.test;", 410 ExpectedErr: branch_control.ErrIncorrectPermissions, 411 }, 412 { 413 Name: "ALTER TABLE AUTO_INCREMENT", 414 SetUpScript: []string{ 415 "CREATE TABLE `mydb/other`.test2(pk BIGINT PRIMARY KEY AUTO_INCREMENT);", 416 }, 417 Query: "ALTER TABLE `mydb/other`.test2 AUTO_INCREMENT = 20;", 418 ExpectedErr: branch_control.ErrIncorrectPermissions, 419 }, 420 { 421 Name: "ALTER TABLE ADD CHECK", 422 Query: "ALTER TABLE `mydb/other`.test ADD CONSTRAINT check_1 CHECK (pk > 0);", 423 ExpectedErr: branch_control.ErrIncorrectPermissions, 424 }, 425 { 426 Name: "ALTER TABLE DROP CHECK", 427 SetUpScript: []string{ 428 "ALTER TABLE `mydb/other`.test ADD CONSTRAINT check_1 CHECK (pk > 0);", 429 }, 430 Query: "ALTER TABLE `mydb/other`.test DROP CHECK check_1;", 431 ExpectedErr: branch_control.ErrIncorrectPermissions, 432 }, 433 { 434 Name: "ALTER TABLE ALTER COLUMN SET DEFAULT", 435 Query: "ALTER TABLE `mydb/other`.test ALTER COLUMN v1 SET DEFAULT (5);", 436 ExpectedErr: branch_control.ErrIncorrectPermissions, 437 }, 438 { 439 Name: "ALTER TABLE ALTER COLUMN DROP DEFAULT", 440 SetUpScript: []string{ 441 "ALTER TABLE `mydb/other`.test ALTER COLUMN v1 SET DEFAULT (5);", 442 }, 443 Query: "ALTER TABLE `mydb/other`.test ALTER COLUMN v1 DROP DEFAULT;", 444 ExpectedErr: branch_control.ErrIncorrectPermissions, 445 }, 446 { 447 Name: "ALTER TABLE ADD FOREIGN KEY", 448 SetUpScript: []string{ 449 "ALTER TABLE `mydb/other`.test ADD INDEX idx_v1 (v1);", 450 "CREATE TABLE `mydb/other`.test2 (pk BIGINT PRIMARY KEY, v1 BIGINT UNIQUE);", 451 }, 452 Query: "ALTER TABLE `mydb/other`.test2 ADD CONSTRAINT fk_1 FOREIGN KEY (v1) REFERENCES `mydb/other`.test (v1);", 453 ExpectedErr: branch_control.ErrIncorrectPermissions, 454 }, 455 { 456 Name: "ALTER TABLE DROP FOREIGN KEY", 457 SetUpScript: []string{ 458 "ALTER TABLE `mydb/other`.test ADD INDEX idx_v1 (v1);", 459 "CREATE TABLE `mydb/other`.test2 (pk BIGINT PRIMARY KEY, v1 BIGINT UNIQUE, CONSTRAINT fk_1 FOREIGN KEY (v1) REFERENCES `mydb/other`.test (v1));", 460 }, 461 Query: "ALTER TABLE `mydb/other`.test2 DROP FOREIGN KEY fk_1;", 462 ExpectedErr: branch_control.ErrIncorrectPermissions, 463 }, 464 { 465 Name: "ALTER TABLE ADD INDEX", 466 Query: "ALTER TABLE `mydb/other`.test ADD INDEX idx_v1 (v1);", 467 ExpectedErr: branch_control.ErrIncorrectPermissions, 468 }, 469 { 470 Name: "ALTER TABLE DROP INDEX", 471 SetUpScript: []string{ 472 "ALTER TABLE `mydb/other`.test ADD INDEX idx_v1 (v1);", 473 }, 474 Query: "ALTER TABLE `mydb/other`.test DROP INDEX idx_v1;", 475 ExpectedErr: branch_control.ErrIncorrectPermissions, 476 }, 477 { 478 Name: "ALTER TABLE RENAME INDEX", 479 SetUpScript: []string{ 480 "ALTER TABLE `mydb/other`.test ADD INDEX idx_v1 (v1);", 481 }, 482 Query: "ALTER TABLE `mydb/other`.test RENAME INDEX idx_v1 TO idx_v1_new;", 483 ExpectedErr: branch_control.ErrIncorrectPermissions, 484 }, 485 { 486 Name: "ALTER TABLE ADD PRIMARY KEY", 487 SetUpScript: []string{ 488 "CREATE TABLE `mydb/other`.test2 (v1 BIGINT, v2 BIGINT);", 489 }, 490 Query: "ALTER TABLE `mydb/other`.test2 ADD PRIMARY KEY (v1, v2);", 491 ExpectedErr: branch_control.ErrIncorrectPermissions, 492 }, 493 { 494 Name: "ALTER TABLE DROP PRIMARY KEY", 495 Query: "ALTER TABLE `mydb/other`.test DROP PRIMARY KEY;", 496 ExpectedErr: branch_control.ErrIncorrectPermissions, 497 }, 498 { 499 Name: "ALTER TABLE RENAME", 500 Query: "ALTER TABLE `mydb/other`.test RENAME TO test_new;", 501 ExpectedErr: branch_control.ErrIncorrectPermissions, 502 SkipMessage: "https://github.com/dolthub/dolt/issues/6078", 503 }, 504 { 505 Name: "RENAME TABLE", 506 Query: "RENAME TABLE `mydb/other`.test TO test_new;", 507 ExpectedErr: branch_control.ErrIncorrectPermissions, 508 SkipMessage: "https://github.com/dolthub/dolt/issues/6078", 509 }, 510 { 511 Name: "ALTER TABLE ADD COLUMN", 512 Query: "ALTER TABLE `mydb/other`.test ADD COLUMN v2 BIGINT;", 513 ExpectedErr: branch_control.ErrIncorrectPermissions, 514 }, 515 { 516 Name: "ALTER TABLE DROP COLUMN", 517 Query: "ALTER TABLE `mydb/other`.test DROP COLUMN v1;", 518 ExpectedErr: branch_control.ErrIncorrectPermissions, 519 }, 520 { 521 Name: "ALTER TABLE CHANGE COLUMN", 522 Query: "ALTER TABLE `mydb/other`.test CHANGE COLUMN v1 v1_new BIGINT;", 523 ExpectedErr: branch_control.ErrIncorrectPermissions, 524 }, 525 { 526 Name: "ALTER TABLE MODIFY COLUMN", 527 Query: "ALTER TABLE `mydb/other`.test MODIFY COLUMN v1 TINYINT;", 528 ExpectedErr: branch_control.ErrIncorrectPermissions, 529 }, 530 { 531 Name: "ALTER TABLE RENAME COLUMN", 532 Query: "ALTER TABLE `mydb/other`.test RENAME COLUMN v1 TO v1_new;", 533 ExpectedErr: branch_control.ErrIncorrectPermissions, 534 }, 535 { 536 Name: "CREATE INDEX", 537 Query: "CREATE INDEX idx_v1 ON `mydb/other`.test (v1);", 538 ExpectedErr: branch_control.ErrIncorrectPermissions, 539 }, 540 { 541 Name: "DROP INDEX", 542 SetUpScript: []string{ 543 "CREATE INDEX idx_v1 ON `mydb/other`.test (v1);", 544 }, 545 Query: "DROP INDEX idx_v1 ON `mydb/other`.test;", 546 ExpectedErr: branch_control.ErrIncorrectPermissions, 547 }, 548 { 549 Name: "CREATE VIEW", 550 Query: "CREATE VIEW view_1 AS SELECT * FROM `mydb/other`.test;", 551 ExpectedErr: branch_control.ErrIncorrectPermissions, 552 SkipMessage: "https://github.com/dolthub/dolt/issues/6078", 553 }, 554 { 555 Name: "DROP VIEW", 556 SetUpScript: []string{ 557 "CREATE VIEW view_1 AS SELECT * FROM `mydb/other`.test;", 558 }, 559 Query: "DROP VIEW view_1;", 560 ExpectedErr: branch_control.ErrIncorrectPermissions, 561 SkipMessage: "https://github.com/dolthub/dolt/issues/6078", 562 }, 563 { 564 Name: "CREATE TRIGGER", 565 Query: "CREATE TRIGGER trigger_1 BEFORE INSERT ON `mydb/other`.test FOR EACH ROW SET NEW.v1 = 4;", 566 ExpectedErr: branch_control.ErrIncorrectPermissions, 567 SkipMessage: "https://github.com/dolthub/dolt/issues/6078", 568 }, 569 { 570 Name: "DROP TRIGGER", 571 SetUpScript: []string{ 572 "CREATE TRIGGER trigger_1 BEFORE INSERT ON `mydb/other`.test FOR EACH ROW SET NEW.v1 = 4;", 573 }, 574 Query: "DROP TRIGGER `mydb/other`.trigger_1;", 575 ExpectedErr: branch_control.ErrIncorrectPermissions, 576 SkipMessage: "https://github.com/dolthub/dolt/issues/6078", 577 }, 578 { 579 Name: "CREATE TABLE", 580 Query: "CREATE TABLE `mydb/other`.test2 (pk BIGINT PRIMARY KEY, v1 BIGINT);", 581 ExpectedErr: branch_control.ErrIncorrectPermissions, 582 }, 583 { 584 Name: "CREATE TABLE LIKE", 585 Query: "CREATE TABLE `mydb/other`.test2 LIKE `mydb/other`.test;", 586 ExpectedErr: branch_control.ErrIncorrectPermissions, 587 SkipMessage: "https://github.com/dolthub/dolt/issues/6078", 588 }, 589 { 590 Name: "CREATE TABLE AS SELECT", 591 Query: "CREATE TABLE `mydb/other`.test2 AS SELECT * FROM `mydb/other`.test;", 592 ExpectedErr: branch_control.ErrIncorrectPermissions, 593 }, 594 { 595 Name: "DROP TABLE", 596 Query: "DROP TABLE `mydb/other`.test;", 597 ExpectedErr: branch_control.ErrIncorrectPermissions, 598 }, 599 } 600 601 var BranchControlTests = []BranchControlTest{ 602 { 603 Name: "Namespace entries block", 604 SetUpScript: []string{ 605 "DELETE FROM dolt_branch_control WHERE user = '%';", 606 "INSERT INTO dolt_branch_control VALUES ('%', '%', 'root', 'localhost', 'admin');", 607 "CREATE USER testuser@localhost;", 608 "GRANT ALL ON *.* TO testuser@localhost;", 609 }, 610 Assertions: []BranchControlTestAssertion{ 611 { // Empty table, all branches are allowed 612 User: "testuser", 613 Host: "localhost", 614 Query: "CALL DOLT_BRANCH('otherbranch1');", 615 Expected: []sql.Row{{0}}, 616 }, 617 { // Prefix "other" is now locked by root 618 User: "root", 619 Host: "localhost", 620 Query: "INSERT INTO dolt_branch_namespace_control VALUES ('%', 'other%', 'root', 'localhost');", 621 Expected: []sql.Row{ 622 {types.NewOkResult(1)}, 623 }, 624 }, 625 { 626 User: "testuser", 627 Host: "localhost", 628 Query: "CALL DOLT_BRANCH('otherbranch2');", 629 ExpectedErr: branch_control.ErrCannotCreateBranch, 630 }, 631 { // Allow testuser to use the "other" prefix 632 User: "root", 633 Host: "localhost", 634 Query: "INSERT INTO dolt_branch_namespace_control VALUES ('%', 'other%', 'testuser', 'localhost');", 635 Expected: []sql.Row{ 636 {types.NewOkResult(1)}, 637 }, 638 }, 639 { 640 User: "testuser", 641 Host: "localhost", 642 Query: "CALL DOLT_BRANCH('otherbranch2');", 643 Expected: []sql.Row{{0}}, 644 }, 645 { // Create a longer match, which takes precedence over shorter matches 646 User: "root", 647 Host: "localhost", 648 Query: "INSERT INTO dolt_branch_namespace_control VALUES ('%', 'otherbranch%', 'root', 'localhost');", 649 Expected: []sql.Row{ 650 {types.NewOkResult(1)}, 651 }, 652 }, 653 { // Matches both "other%" and "otherbranch%", but "otherbranch%" wins by being the longer match 654 User: "testuser", 655 Host: "localhost", 656 Query: "CALL DOLT_BRANCH('otherbranch3');", 657 ExpectedErr: branch_control.ErrCannotCreateBranch, 658 }, 659 { // This doesn't match the longer rule, so testuser has access the namespace 660 User: "testuser", 661 Host: "localhost", 662 Query: "CALL DOLT_BRANCH('other3');", 663 Expected: []sql.Row{{0}}, 664 }, 665 { 666 User: "root", 667 Host: "localhost", 668 Query: "INSERT INTO dolt_branch_namespace_control VALUES ('%', 'otherbranch%', 'testuser', 'localhost');", 669 Expected: []sql.Row{ 670 {types.NewOkResult(1)}, 671 }, 672 }, 673 { 674 User: "testuser", 675 Host: "localhost", 676 Query: "CALL DOLT_BRANCH('otherbranch3');", 677 Expected: []sql.Row{{0}}, 678 }, 679 }, 680 }, 681 { 682 Name: "Require admin to modify tables", 683 SetUpScript: []string{ 684 "DELETE FROM dolt_branch_control WHERE user = '%';", 685 "INSERT INTO dolt_branch_control VALUES ('%', '%', 'root', 'localhost', 'admin');", 686 "CREATE USER a@localhost;", 687 "CREATE USER b@localhost;", 688 "GRANT ALL ON *.* TO a@localhost;", 689 "REVOKE SUPER ON *.* FROM a@localhost;", 690 "GRANT ALL ON *.* TO b@localhost;", 691 "REVOKE SUPER ON *.* FROM b@localhost;", 692 "INSERT INTO dolt_branch_control VALUES ('%', 'other', 'a', 'localhost', 'write'), ('%', 'prefix%', 'a', 'localhost', 'admin')", 693 }, 694 Assertions: []BranchControlTestAssertion{ 695 { 696 User: "a", 697 Host: "localhost", 698 Query: "DELETE FROM dolt_branch_control WHERE branch = 'other';", 699 ExpectedErr: branch_control.ErrDeletingRow, 700 }, 701 { 702 User: "b", 703 Host: "localhost", 704 Query: "DELETE FROM dolt_branch_control WHERE branch = 'other';", 705 ExpectedErr: branch_control.ErrDeletingRow, 706 }, 707 { 708 User: "b", 709 Host: "localhost", 710 Query: "DELETE FROM dolt_branch_control WHERE branch = 'prefix%';", 711 ExpectedErr: branch_control.ErrDeletingRow, 712 }, 713 { 714 User: "a", 715 Host: "localhost", 716 Query: "INSERT INTO dolt_branch_control VALUES ('%', 'prefix1%', 'b', 'localhost', 'write');", 717 Expected: []sql.Row{ 718 {types.NewOkResult(1)}, 719 }, 720 }, 721 { 722 User: "b", 723 Host: "localhost", 724 Query: "DELETE FROM dolt_branch_control WHERE branch = 'prefix1%';", 725 ExpectedErr: branch_control.ErrDeletingRow, 726 }, 727 { // Must have permission on the new name as well 728 User: "a", 729 Host: "localhost", 730 Query: "UPDATE dolt_branch_control SET branch = 'other1' WHERE branch = 'prefix1%';", 731 ExpectedErr: branch_control.ErrUpdatingToRow, 732 }, 733 { 734 User: "b", 735 Host: "localhost", 736 Query: "UPDATE dolt_branch_control SET permissions = 'admin' WHERE branch = 'prefix1%';", 737 ExpectedErr: branch_control.ErrUpdatingRow, 738 }, 739 { 740 User: "a", 741 Host: "localhost", 742 Query: "UPDATE dolt_branch_control SET permissions = 'admin' WHERE branch = 'prefix1%';", 743 Expected: []sql.Row{ 744 {types.OkResult{RowsAffected: 1, Info: plan.UpdateInfo{Matched: 1, Updated: 1}}}, 745 }, 746 }, 747 { 748 User: "b", 749 Host: "localhost", 750 Query: "DELETE FROM dolt_branch_control WHERE branch = 'prefix1%';", 751 Expected: []sql.Row{ 752 {types.NewOkResult(1)}, 753 }, 754 }, 755 { 756 User: "b", 757 Host: "localhost", 758 Query: "INSERT INTO dolt_branch_control VALUES ('%', 'prefix1%', 'b', 'localhost', 'admin');", 759 ExpectedErr: branch_control.ErrInsertingAccessRow, 760 }, 761 { // Since "a" has admin on "prefix%", they can also insert into the namespace table 762 User: "a", 763 Host: "localhost", 764 Query: "INSERT INTO dolt_branch_namespace_control VALUES ('%', 'prefix___', 'a', 'localhost');", 765 Expected: []sql.Row{ 766 {types.NewOkResult(1)}, 767 }, 768 }, 769 { 770 User: "b", 771 Host: "localhost", 772 Query: "INSERT INTO dolt_branch_namespace_control VALUES ('%', 'prefix', 'b', 'localhost');", 773 ExpectedErr: branch_control.ErrInsertingNamespaceRow, 774 }, 775 { 776 User: "a", 777 Host: "localhost", 778 Query: "UPDATE dolt_branch_namespace_control SET branch = 'prefix%';", 779 Expected: []sql.Row{ 780 {types.OkResult{RowsAffected: 1, Info: plan.UpdateInfo{Matched: 1, Updated: 1}}}, 781 }, 782 }, 783 { 784 User: "a", 785 Host: "localhost", 786 Query: "UPDATE dolt_branch_namespace_control SET branch = 'other';", 787 ExpectedErr: branch_control.ErrUpdatingToRow, 788 }, 789 { 790 User: "b", 791 Host: "localhost", 792 Query: "DELETE FROM dolt_branch_namespace_control WHERE branch = 'prefix%';", 793 ExpectedErr: branch_control.ErrDeletingRow, 794 }, 795 { 796 User: "b", 797 Host: "localhost", 798 Query: "UPDATE dolt_branch_namespace_control SET branch = 'anything';", 799 ExpectedErr: branch_control.ErrUpdatingRow, 800 }, 801 }, 802 }, 803 { 804 Name: "Deleting entries works", 805 SetUpScript: []string{ 806 "DELETE FROM dolt_branch_control WHERE user = '%';", 807 "INSERT INTO dolt_branch_control VALUES ('%', '%', 'root', 'localhost', 'admin');", 808 "CREATE TABLE test (pk BIGINT PRIMARY KEY);", 809 "CREATE USER testuser@localhost;", 810 "GRANT ALL ON *.* TO testuser@localhost;", 811 "INSERT INTO dolt_branch_control VALUES ('%', '%', 'testuser', 'localhost_1', 'write');", 812 "INSERT INTO dolt_branch_control VALUES ('%', '%', 'testuser', 'localhost_2', 'write');", 813 "INSERT INTO dolt_branch_control VALUES ('%', '%', 'testuser', 'localhost', 'write');", 814 "INSERT INTO dolt_branch_control VALUES ('%', '%', 'testuser', 'localhost_3', 'write');", 815 "INSERT INTO dolt_branch_control VALUES ('%', '%', 'testuser', 'localhost_4', 'write');", 816 "INSERT INTO dolt_branch_control VALUES ('%', '%', 'testuser', 'localhost_5', 'write');", 817 "DELETE FROM dolt_branch_control WHERE host IN ('localhost_2', 'localhost_3');", 818 }, 819 Assertions: []BranchControlTestAssertion{ 820 { 821 User: "testuser", 822 Host: "localhost", 823 Query: "SELECT * FROM dolt_branch_control WHERE user = 'testuser';", 824 Expected: []sql.Row{ 825 {"%", "%", "testuser", "localhost_1", "write"}, 826 {"%", "%", "testuser", "localhost", "write"}, 827 {"%", "%", "testuser", "localhost_4", "write"}, 828 {"%", "%", "testuser", "localhost_5", "write"}, 829 }, 830 }, 831 { 832 User: "testuser", 833 Host: "localhost", 834 Query: "INSERT INTO test VALUES (1);", 835 Expected: []sql.Row{ 836 {types.NewOkResult(1)}, 837 }, 838 }, 839 { 840 User: "root", 841 Host: "localhost", 842 Query: "DELETE FROM dolt_branch_control WHERE host = 'localhost_5';", 843 Expected: []sql.Row{ 844 {types.NewOkResult(1)}, 845 }, 846 }, 847 { 848 User: "testuser", 849 Host: "localhost", 850 Query: "SELECT * FROM dolt_branch_control WHERE user = 'testuser';", 851 Expected: []sql.Row{ 852 {"%", "%", "testuser", "localhost_1", "write"}, 853 {"%", "%", "testuser", "localhost", "write"}, 854 {"%", "%", "testuser", "localhost_4", "write"}, 855 }, 856 }, 857 { 858 User: "testuser", 859 Host: "localhost", 860 Query: "INSERT INTO test VALUES (2);", 861 Expected: []sql.Row{ 862 {types.NewOkResult(1)}, 863 }, 864 }, 865 { 866 User: "root", 867 Host: "localhost", 868 Query: "DELETE FROM dolt_branch_control WHERE host = 'localhost_1';", 869 Expected: []sql.Row{ 870 {types.NewOkResult(1)}, 871 }, 872 }, 873 { 874 User: "testuser", 875 Host: "localhost", 876 Query: "SELECT * FROM dolt_branch_control WHERE user = 'testuser';", 877 Expected: []sql.Row{ 878 {"%", "%", "testuser", "localhost", "write"}, 879 {"%", "%", "testuser", "localhost_4", "write"}, 880 }, 881 }, 882 { 883 User: "testuser", 884 Host: "localhost", 885 Query: "INSERT INTO test VALUES (3);", 886 Expected: []sql.Row{ 887 {types.NewOkResult(1)}, 888 }, 889 }, 890 { 891 User: "root", 892 Host: "localhost", 893 Query: "DELETE FROM dolt_branch_control WHERE host = 'localhost_4';", 894 Expected: []sql.Row{ 895 {types.NewOkResult(1)}, 896 }, 897 }, 898 { 899 User: "testuser", 900 Host: "localhost", 901 Query: "SELECT * FROM dolt_branch_control WHERE user = 'testuser';", 902 Expected: []sql.Row{ 903 {"%", "%", "testuser", "localhost", "write"}, 904 }, 905 }, 906 { 907 User: "testuser", 908 Host: "localhost", 909 Query: "INSERT INTO test VALUES (4);", 910 Expected: []sql.Row{ 911 {types.NewOkResult(1)}, 912 }, 913 }, 914 { 915 User: "root", 916 Host: "localhost", 917 Query: "DELETE FROM dolt_branch_control WHERE user = 'testuser' AND host = 'localhost';", 918 Expected: []sql.Row{ 919 {types.NewOkResult(1)}, 920 }, 921 }, 922 { 923 User: "testuser", 924 Host: "localhost", 925 Query: "SELECT * FROM dolt_branch_control WHERE user = 'testuser';", 926 Expected: []sql.Row{}, 927 }, 928 { 929 User: "testuser", 930 Host: "localhost", 931 Query: "INSERT INTO test VALUES (5);", 932 ExpectedErr: branch_control.ErrIncorrectPermissions, 933 }, 934 { 935 User: "root", 936 Host: "localhost", 937 Query: "DELETE FROM dolt_branch_control;", 938 Expected: []sql.Row{ 939 {types.NewOkResult(1)}, 940 }, 941 }, 942 { 943 User: "root", 944 Host: "localhost", 945 Query: "SELECT * FROM dolt_branch_control;", 946 Expected: []sql.Row{}, 947 }, 948 { 949 User: "root", 950 Host: "localhost", 951 Query: "INSERT INTO dolt_branch_control VALUES ('%', '%', 'root', '%', 'admin');", 952 Expected: []sql.Row{ 953 {types.NewOkResult(1)}, 954 }, 955 }, 956 { 957 User: "root", 958 Host: "localhost", 959 Query: "SELECT * FROM dolt_branch_control;", 960 Expected: []sql.Row{ 961 {"%", "%", "root", "%", "admin"}, 962 }, 963 }, 964 }, 965 }, 966 { 967 Name: "Subset entries count as duplicates", 968 SetUpScript: []string{ 969 "DELETE FROM dolt_branch_control WHERE user = '%';", 970 "INSERT INTO dolt_branch_control VALUES ('%', '%', 'root', 'localhost', 'admin');", 971 "CREATE USER testuser@localhost;", 972 "GRANT ALL ON *.* TO testuser@localhost;", 973 "INSERT INTO dolt_branch_control VALUES ('%', 'prefix', 'testuser', 'localhost', 'admin');", 974 "INSERT INTO dolt_branch_control VALUES ('%', 'prefix1%', 'testuser', 'localhost', 'admin');", 975 "INSERT INTO dolt_branch_control VALUES ('%', 'prefix2_', 'testuser', 'localhost', 'admin');", 976 "INSERT INTO dolt_branch_control VALUES ('%', 'prefix3_', 'testuser', 'localhost', 'admin');", 977 }, 978 Assertions: []BranchControlTestAssertion{ 979 { // The pre-existing "prefix1%" entry will cover ALL possible matches of "prefix1sub%", so we treat it as a duplicate 980 User: "testuser", 981 Host: "localhost", 982 Query: "INSERT INTO dolt_branch_control VALUES ('%', 'prefix1sub%', 'testuser', 'localhost', 'admin');", 983 ExpectedErr: sql.ErrPrimaryKeyViolation, 984 }, 985 { // The ending "%" fully covers "_", so we also treat it as a duplicate 986 User: "testuser", 987 Host: "localhost", 988 Query: "INSERT INTO dolt_branch_control VALUES ('%', 'prefix1_', 'testuser', 'localhost', 'admin');", 989 ExpectedErr: sql.ErrPrimaryKeyViolation, 990 }, 991 { // This is the reverse of the above case, so this is NOT a duplicate (although the original is now a subset) 992 User: "root", 993 Host: "localhost", 994 Query: "INSERT INTO dolt_branch_control VALUES ('%', 'prefix2%', 'testuser', 'localhost', 'admin');", 995 Expected: []sql.Row{ 996 {types.NewOkResult(1)}, 997 }, 998 }, 999 { 1000 User: "testuser", 1001 Host: "localhost", 1002 Query: "SELECT * FROM dolt_branch_control WHERE user = 'testuser';", 1003 Expected: []sql.Row{ 1004 {"%", "prefix", "testuser", "localhost", "admin"}, 1005 {"%", "prefix1%", "testuser", "localhost", "admin"}, 1006 {"%", "prefix2_", "testuser", "localhost", "admin"}, 1007 {"%", "prefix2%", "testuser", "localhost", "admin"}, 1008 {"%", "prefix3_", "testuser", "localhost", "admin"}, 1009 }, 1010 }, 1011 { // Sanity checks to ensure that straight-up duplicates are also caught 1012 User: "testuser", 1013 Host: "localhost", 1014 Query: "INSERT INTO dolt_branch_control VALUES ('%', 'prefix', 'testuser', 'localhost', 'admin');", 1015 ExpectedErr: sql.ErrPrimaryKeyViolation, 1016 }, 1017 { 1018 User: "testuser", 1019 Host: "localhost", 1020 Query: "INSERT INTO dolt_branch_control VALUES ('%', 'prefix1%', 'testuser', 'localhost', 'admin');", 1021 ExpectedErr: sql.ErrPrimaryKeyViolation, 1022 }, 1023 { 1024 User: "testuser", 1025 Host: "localhost", 1026 Query: "INSERT INTO dolt_branch_control VALUES ('%', 'prefix3_', 'testuser', 'localhost', 'admin');", 1027 ExpectedErr: sql.ErrPrimaryKeyViolation, 1028 }, 1029 { // Verify that creating branches also skips adding an entry if it would be a subset 1030 User: "root", 1031 Host: "localhost", 1032 Query: "SELECT * FROM dolt_branch_control WHERE user = 'root';", 1033 Expected: []sql.Row{ 1034 {"%", "%", "root", "localhost", "admin"}, 1035 }, 1036 }, 1037 { 1038 User: "root", 1039 Host: "localhost", 1040 Query: "CALL DOLT_BRANCH('new_root_branch');", 1041 Expected: []sql.Row{{0}}, 1042 }, 1043 { 1044 User: "root", 1045 Host: "localhost", 1046 Query: "SELECT * FROM dolt_branch_control WHERE user = 'root';", 1047 Expected: []sql.Row{ 1048 {"%", "%", "root", "localhost", "admin"}, 1049 }, 1050 }, 1051 }, 1052 }, 1053 { 1054 Name: "Creating branch creates new entry", 1055 SetUpScript: []string{ 1056 "DELETE FROM dolt_branch_control WHERE user = '%';", 1057 "INSERT INTO dolt_branch_control VALUES ('%', '%', 'root', 'localhost', 'admin');", 1058 "CREATE USER testuser@localhost;", 1059 "GRANT ALL ON *.* TO testuser@localhost;", 1060 }, 1061 Assertions: []BranchControlTestAssertion{ 1062 { 1063 User: "testuser", 1064 Host: "localhost", 1065 Query: "SELECT * FROM dolt_branch_control WHERE user = 'testuser';", 1066 Expected: []sql.Row{}, 1067 }, 1068 { 1069 User: "testuser", 1070 Host: "localhost", 1071 Query: "CALL DOLT_BRANCH('otherbranch');", 1072 Expected: []sql.Row{{0}}, 1073 }, 1074 { 1075 User: "testuser", 1076 Host: "localhost", 1077 Query: "SELECT * FROM dolt_branch_control WHERE user = 'testuser';", 1078 Expected: []sql.Row{ 1079 {"mydb", "otherbranch", "testuser", "localhost", "admin"}, 1080 }, 1081 }, 1082 }, 1083 }, 1084 { 1085 Name: "Renaming branch creates new entry", 1086 SetUpScript: []string{ 1087 "DELETE FROM dolt_branch_control WHERE user = '%';", 1088 "INSERT INTO dolt_branch_control VALUES ('%', '%', 'root', 'localhost', 'admin');", 1089 "CREATE USER testuser@localhost;", 1090 "GRANT ALL ON *.* TO testuser@localhost;", 1091 "CALL DOLT_BRANCH('otherbranch');", 1092 "INSERT INTO dolt_branch_control VALUES ('%', 'otherbranch', 'testuser', 'localhost', 'write');", 1093 }, 1094 Assertions: []BranchControlTestAssertion{ 1095 { 1096 User: "testuser", 1097 Host: "localhost", 1098 Query: "SELECT * FROM dolt_branch_control WHERE user = 'testuser';", 1099 Expected: []sql.Row{ 1100 {"%", "otherbranch", "testuser", "localhost", "write"}, 1101 }, 1102 }, 1103 { 1104 User: "testuser", 1105 Host: "localhost", 1106 Query: "CALL DOLT_BRANCH('-f', '-m', 'otherbranch', 'newbranch');", 1107 ExpectedErr: branch_control.ErrCannotDeleteBranch, 1108 }, 1109 { 1110 User: "testuser", 1111 Host: "localhost", 1112 Query: "CALL DOLT_BRANCH('-m', 'otherbranch', 'newbranch');", 1113 Expected: []sql.Row{{0}}, 1114 }, 1115 { 1116 User: "testuser", 1117 Host: "localhost", 1118 Query: "SELECT * FROM dolt_branch_control WHERE user = 'testuser';", 1119 Expected: []sql.Row{ 1120 {"%", "otherbranch", "testuser", "localhost", "write"}, // Original entry remains 1121 {"mydb", "newbranch", "testuser", "localhost", "admin"}, // New entry is scoped specifically to db 1122 }, 1123 }, 1124 }, 1125 }, 1126 { 1127 Name: "Copying branch creates new entry", 1128 SetUpScript: []string{ 1129 "DELETE FROM dolt_branch_control WHERE user = '%';", 1130 "INSERT INTO dolt_branch_control VALUES ('%', '%', 'root', 'localhost', 'admin');", 1131 "CREATE USER testuser@localhost;", 1132 "GRANT ALL ON *.* TO testuser@localhost;", 1133 "CALL DOLT_BRANCH('otherbranch');", 1134 }, 1135 Assertions: []BranchControlTestAssertion{ 1136 { 1137 User: "testuser", 1138 Host: "localhost", 1139 Query: "SELECT * FROM dolt_branch_control WHERE user = 'testuser';", 1140 Expected: []sql.Row{}, 1141 }, 1142 { 1143 User: "testuser", 1144 Host: "localhost", 1145 Query: "CALL DOLT_BRANCH('-f', '-c', 'otherbranch', 'newbranch');", 1146 ExpectedErr: branch_control.ErrCannotDeleteBranch, 1147 }, 1148 { 1149 User: "testuser", 1150 Host: "localhost", 1151 Query: "CALL DOLT_BRANCH('-c', 'otherbranch', 'newbranch');", 1152 Expected: []sql.Row{{0}}, 1153 }, 1154 { 1155 User: "testuser", 1156 Host: "localhost", 1157 Query: "SELECT * FROM dolt_branch_control WHERE user = 'testuser';", 1158 Expected: []sql.Row{ 1159 {"mydb", "newbranch", "testuser", "localhost", "admin"}, 1160 }, 1161 }, 1162 }, 1163 }, 1164 { 1165 Name: "Proper database scoping", 1166 SetUpScript: []string{ 1167 "DELETE FROM dolt_branch_control WHERE user = '%';", 1168 "INSERT INTO dolt_branch_control VALUES ('%', '%', 'root', 'localhost', 'admin')," + 1169 "('dba', 'main', 'testuser', 'localhost', 'write'), ('dbb', 'other', 'testuser', 'localhost', 'write');", 1170 "CREATE DATABASE dba;", // Implicitly creates "main" branch 1171 "CREATE DATABASE dbb;", // Implicitly creates "main" branch 1172 "CREATE USER testuser@localhost;", 1173 "GRANT ALL ON *.* TO testuser@localhost;", 1174 "USE dba;", 1175 "CALL DOLT_BRANCH('other');", 1176 "USE dbb;", 1177 "CALL DOLT_BRANCH('other');", 1178 }, 1179 Assertions: []BranchControlTestAssertion{ 1180 { 1181 User: "testuser", 1182 Host: "localhost", 1183 Query: "USE dba;", 1184 Expected: []sql.Row{}, 1185 }, 1186 { // On "dba"."main", which we have permissions for 1187 User: "testuser", 1188 Host: "localhost", 1189 Query: "CREATE TABLE test (pk BIGINT PRIMARY KEY);", 1190 Expected: []sql.Row{ 1191 {types.NewOkResult(0)}, 1192 }, 1193 }, 1194 { 1195 User: "testuser", 1196 Host: "localhost", 1197 Query: "DROP TABLE test;", 1198 Expected: []sql.Row{ 1199 {types.NewOkResult(0)}, 1200 }, 1201 }, 1202 { 1203 User: "testuser", 1204 Host: "localhost", 1205 Query: "CALL DOLT_CHECKOUT('other');", 1206 Expected: []sql.Row{{0, "Switched to branch 'other'"}}, 1207 }, 1208 { // On "dba"."other", which we do not have permissions for 1209 User: "testuser", 1210 Host: "localhost", 1211 Query: "CREATE TABLE test (pk BIGINT PRIMARY KEY);", 1212 ExpectedErr: branch_control.ErrIncorrectPermissions, 1213 }, 1214 { 1215 User: "testuser", 1216 Host: "localhost", 1217 Query: "USE dbb;", 1218 Expected: []sql.Row{}, 1219 }, 1220 { // On "dbb"."main", which we do not have permissions for 1221 User: "testuser", 1222 Host: "localhost", 1223 Query: "CREATE TABLE test (pk BIGINT PRIMARY KEY);", 1224 ExpectedErr: branch_control.ErrIncorrectPermissions, 1225 }, 1226 { 1227 User: "testuser", 1228 Host: "localhost", 1229 Query: "CALL DOLT_CHECKOUT('other');", 1230 Expected: []sql.Row{{0, "Switched to branch 'other'"}}, 1231 }, 1232 { // On "dbb"."other", which we do not have permissions for 1233 User: "testuser", 1234 Host: "localhost", 1235 Query: "CREATE TABLE test (pk BIGINT PRIMARY KEY);", 1236 Expected: []sql.Row{ 1237 {types.NewOkResult(0)}, 1238 }, 1239 }, 1240 }, 1241 }, 1242 { 1243 Name: "Admin privileges do not give implicit branch permissions", 1244 SetUpScript: []string{ 1245 "DELETE FROM dolt_branch_control WHERE user = '%';", 1246 // Even though root already has all privileges, this makes the test logic a bit more explicit 1247 "CREATE USER testuser@localhost;", 1248 "GRANT ALL ON *.* TO testuser@localhost WITH GRANT OPTION;", 1249 }, 1250 Assertions: []BranchControlTestAssertion{ 1251 { 1252 User: "testuser", 1253 Host: "localhost", 1254 Query: "CREATE TABLE test (pk BIGINT PRIMARY KEY);", 1255 ExpectedErr: branch_control.ErrIncorrectPermissions, 1256 }, 1257 { 1258 User: "testuser", 1259 Host: "localhost", 1260 Query: "CALL DOLT_BRANCH('-m', 'main', 'newbranch');", 1261 ExpectedErr: branch_control.ErrCannotDeleteBranch, 1262 }, 1263 { // Anyone can create a branch as long as it's not blocked by dolt_branch_namespace_control 1264 User: "testuser", 1265 Host: "localhost", 1266 Query: "CALL DOLT_BRANCH('newbranch');", 1267 Expected: []sql.Row{{0}}, 1268 }, 1269 { 1270 User: "testuser", 1271 Host: "localhost", 1272 Query: "SELECT * FROM dolt_branch_control WHERE user = 'testuser';", 1273 Expected: []sql.Row{ 1274 {"mydb", "newbranch", "testuser", "localhost", "admin"}, 1275 }, 1276 }, 1277 }, 1278 }, 1279 { 1280 Name: "Database-level admin privileges allow scoped table modifications", 1281 SetUpScript: []string{ 1282 "DELETE FROM dolt_branch_control WHERE user = '%';", 1283 "INSERT INTO dolt_branch_control VALUES ('%', '%', 'root', 'localhost', 'admin');", 1284 "CREATE DATABASE dba;", 1285 "CREATE DATABASE dbb;", 1286 "CREATE USER a@localhost;", 1287 "GRANT ALL ON dba.* TO a@localhost WITH GRANT OPTION;", 1288 "CREATE USER b@localhost;", 1289 "GRANT ALL ON dbb.* TO b@localhost WITH GRANT OPTION;", 1290 // Currently, dolt system tables are scoped to the current database, so this is a workaround for that 1291 "GRANT ALL ON mydb.* TO a@localhost;", 1292 "GRANT ALL ON mydb.* TO b@localhost;", 1293 }, 1294 Assertions: []BranchControlTestAssertion{ 1295 { 1296 User: "a", 1297 Host: "localhost", 1298 Query: "INSERT INTO dolt_branch_control VALUES ('dba', 'dummy1', '%', '%', 'write');", 1299 Expected: []sql.Row{ 1300 {types.NewOkResult(1)}, 1301 }, 1302 }, 1303 { 1304 User: "a", 1305 Host: "localhost", 1306 Query: "INSERT INTO dolt_branch_control VALUES ('db_', 'dummy2', '%', '%', 'write');", 1307 ExpectedErr: branch_control.ErrInsertingAccessRow, 1308 }, 1309 { 1310 User: "a", 1311 Host: "localhost", 1312 Query: "INSERT INTO dolt_branch_control VALUES ('dbb', 'dummy3', '%', '%', 'write');", 1313 ExpectedErr: branch_control.ErrInsertingAccessRow, 1314 }, 1315 { 1316 User: "b", 1317 Host: "localhost", 1318 Query: "INSERT INTO dolt_branch_control VALUES ('dba', 'dummy4', '%', '%', 'write');", 1319 ExpectedErr: branch_control.ErrInsertingAccessRow, 1320 }, 1321 { 1322 User: "b", 1323 Host: "localhost", 1324 Query: "INSERT INTO dolt_branch_control VALUES ('db_', 'dummy5', '%', '%', 'write');", 1325 ExpectedErr: branch_control.ErrInsertingAccessRow, 1326 }, 1327 { 1328 User: "b", 1329 Host: "localhost", 1330 Query: "INSERT INTO dolt_branch_control VALUES ('dbb', 'dummy6', '%', '%', 'write');", 1331 Expected: []sql.Row{ 1332 {types.NewOkResult(1)}, 1333 }, 1334 }, 1335 { 1336 User: "root", 1337 Host: "localhost", 1338 Query: "GRANT SUPER ON *.* TO a@localhost WITH GRANT OPTION;", 1339 Expected: []sql.Row{ 1340 {types.NewOkResult(0)}, 1341 }, 1342 }, 1343 { 1344 User: "a", 1345 Host: "localhost", 1346 Query: "INSERT INTO dolt_branch_control VALUES ('db_', 'dummy7', '%', '%', 'write');", 1347 Expected: []sql.Row{ 1348 {types.NewOkResult(1)}, 1349 }, 1350 }, 1351 { 1352 User: "root", 1353 Host: "localhost", 1354 Query: "SELECT * FROM dolt_branch_control;", 1355 Expected: []sql.Row{ 1356 {"%", "%", "root", "localhost", "admin"}, 1357 {"dba", "dummy1", "%", "%", "write"}, 1358 {"dbb", "dummy6", "%", "%", "write"}, 1359 {"db_", "dummy7", "%", "%", "write"}, 1360 }, 1361 }, 1362 }, 1363 }, 1364 } 1365 1366 func TestBranchControl(t *testing.T) { 1367 for _, test := range BranchControlTests { 1368 harness := newDoltHarness(t) 1369 defer harness.Close() 1370 t.Run(test.Name, func(t *testing.T) { 1371 engine, err := harness.NewEngine(t) 1372 require.NoError(t, err) 1373 defer engine.Close() 1374 1375 ctx := enginetest.NewContext(harness) 1376 ctx.NewCtxWithClient(sql.Client{ 1377 User: "root", 1378 Address: "localhost", 1379 }) 1380 engine.EngineAnalyzer().Catalog.MySQLDb.AddRootAccount() 1381 engine.EngineAnalyzer().Catalog.MySQLDb.SetPersister(&mysql_db.NoopPersister{}) 1382 1383 for _, statement := range test.SetUpScript { 1384 enginetest.RunQueryWithContext(t, engine, harness, ctx, statement) 1385 } 1386 1387 for _, assertion := range test.Assertions { 1388 user := assertion.User 1389 host := assertion.Host 1390 if user == "" { 1391 user = "root" 1392 } 1393 if host == "" { 1394 host = "localhost" 1395 } 1396 ctx = ctx.NewCtxWithClient(sql.Client{ 1397 User: user, 1398 Address: host, 1399 }) 1400 1401 if assertion.ExpectedErr != nil { 1402 t.Run(assertion.Query, func(t *testing.T) { 1403 enginetest.AssertErrWithCtx(t, engine, harness, ctx, assertion.Query, assertion.ExpectedErr) 1404 }) 1405 } else if assertion.ExpectedErrStr != "" { 1406 t.Run(assertion.Query, func(t *testing.T) { 1407 enginetest.AssertErrWithCtx(t, engine, harness, ctx, assertion.Query, nil, assertion.ExpectedErrStr) 1408 }) 1409 } else { 1410 t.Run(assertion.Query, func(t *testing.T) { 1411 enginetest.TestQueryWithContext(t, ctx, engine, harness, assertion.Query, assertion.Expected, nil, nil) 1412 }) 1413 } 1414 } 1415 }) 1416 } 1417 } 1418 1419 func TestBranchControlBlocks(t *testing.T) { 1420 for _, test := range BranchControlBlockTests { 1421 t.Run(test.Name, func(t *testing.T) { 1422 if test.SkipMessage != "" { 1423 t.Skip(test.SkipMessage) 1424 } 1425 1426 harness := newDoltHarness(t) 1427 defer harness.Close() 1428 1429 engine, err := harness.NewEngine(t) 1430 require.NoError(t, err) 1431 defer engine.Close() 1432 1433 rootCtx := enginetest.NewContext(harness) 1434 rootCtx.NewCtxWithClient(sql.Client{ 1435 User: "root", 1436 Address: "localhost", 1437 }) 1438 engine.EngineAnalyzer().Catalog.MySQLDb.AddRootAccount() 1439 engine.EngineAnalyzer().Catalog.MySQLDb.SetPersister(&mysql_db.NoopPersister{}) 1440 1441 for _, statement := range append(TestUserSetUpScripts, test.SetUpScript...) { 1442 enginetest.RunQueryWithContext(t, engine, harness, rootCtx, statement) 1443 } 1444 1445 userCtx := enginetest.NewContextWithClient(harness, sql.Client{ 1446 User: "testuser", 1447 Address: "localhost", 1448 }) 1449 enginetest.AssertErrWithCtx(t, engine, harness, userCtx, test.Query, test.ExpectedErr) 1450 1451 addUserQuery := "INSERT INTO dolt_branch_control VALUES ('%', 'main', 'testuser', 'localhost', 'write'), ('%', 'other', 'testuser', 'localhost', 'write');" 1452 addUserQueryResults := []sql.Row{{types.NewOkResult(2)}} 1453 enginetest.TestQueryWithContext(t, rootCtx, engine, harness, addUserQuery, addUserQueryResults, nil, nil) 1454 1455 _, iter, err := engine.Query(userCtx, test.Query) 1456 if err == nil { 1457 _, err = sql.RowIterToRows(userCtx, iter) 1458 } 1459 assert.NoError(t, err) 1460 }) 1461 } 1462 1463 // These tests are run with permission on main but not other 1464 for _, test := range BranchControlOtherDbBlockTests { 1465 t.Run("OtherDB_"+test.Name, func(t *testing.T) { 1466 if test.SkipMessage != "" { 1467 t.Skip(test.SkipMessage) 1468 } 1469 1470 harness := newDoltHarness(t) 1471 defer harness.Close() 1472 1473 engine, err := harness.NewEngine(t) 1474 require.NoError(t, err) 1475 defer engine.Close() 1476 1477 rootCtx := enginetest.NewContext(harness) 1478 rootCtx.NewCtxWithClient(sql.Client{ 1479 User: "root", 1480 Address: "localhost", 1481 }) 1482 engine.EngineAnalyzer().Catalog.MySQLDb.AddRootAccount() 1483 engine.EngineAnalyzer().Catalog.MySQLDb.SetPersister(&mysql_db.NoopPersister{}) 1484 1485 for _, statement := range append(TestUserSetUpScripts, test.SetUpScript...) { 1486 enginetest.RunQueryWithContext(t, engine, harness, rootCtx, statement) 1487 } 1488 1489 addUserQuery := "INSERT INTO dolt_branch_control VALUES ('%', 'main', 'testuser', 'localhost', 'write');" 1490 addUserQueryResults := []sql.Row{{types.NewOkResult(1)}} 1491 enginetest.TestQueryWithContext(t, rootCtx, engine, harness, addUserQuery, addUserQueryResults, nil, nil) 1492 1493 userCtx := enginetest.NewContextWithClient(harness, sql.Client{ 1494 User: "testuser", 1495 Address: "localhost", 1496 }) 1497 enginetest.AssertErrWithCtx(t, engine, harness, userCtx, test.Query, test.ExpectedErr) 1498 1499 addUserQuery = "INSERT INTO dolt_branch_control VALUES ('%', 'other', 'testuser', 'localhost', 'write');" 1500 addUserQueryResults = []sql.Row{{types.NewOkResult(1)}} 1501 enginetest.TestQueryWithContext(t, rootCtx, engine, harness, addUserQuery, addUserQueryResults, nil, nil) 1502 1503 _, iter, err := engine.Query(userCtx, test.Query) 1504 if err == nil { 1505 _, err = sql.RowIterToRows(userCtx, iter) 1506 } 1507 assert.NoError(t, err) 1508 }) 1509 } 1510 }