diff --git a/.gitignore b/.gitignore index 6612da59..c28ec7eb 100644 --- a/.gitignore +++ b/.gitignore @@ -3,7 +3,6 @@ vendor #temp files cache/* -test.php newssync.db* # Windows image file caches diff --git a/lib/Database.php b/lib/Database.php index 268614d0..6ff36c50 100644 --- a/lib/Database.php +++ b/lib/Database.php @@ -341,12 +341,19 @@ class Database { } else { // if a parent is specified, make sure it exists and belongs to the user; get its root (first-level) folder if it's a nested folder $p = $this->db->prepare("SELECT id,root from newssync_folders where owner is ? and id is ?", "str", "int")->run($user, $parent)->getRow(); - if($p===null) { + if(!$p) { throw new Db\ExceptionInput("idMissing", ["action" => __FUNCTION__, "field" => "parent", 'id' => $parent]); } else { // if the parent does not have a root specified (because it is a first-level folder) use the parent ID as the root ID $root = $p['root']===null ? $parent : $p['root']; } } + // check if a folder by the same name already exists, because nulls are wonky in SQL + // FIXME: How should folder name be compared? Should a Unicode normalization be applied before comparison and insertion? + if($this->db->prepare("SELECT count(*) from newssync_folders where owner is ? and parent is ? and name is ?", "str", "int", "str")->run($user, $parent, $data['name'])->getValue() > 0) { + throw new Db\ExceptionInput("constraintViolation"); // FIXME: There needs to be a practical message here + } + // actually perform the insert (!) + return $this->db->prepare("INSERT INTO newssync_folders(owner,parent,root,name) values(?,?,?,?)", "str", "int", "int", "str")->run($user, $parent, $root, $data['name'])->lastId(); } } \ No newline at end of file diff --git a/sql/SQLite3/0.sql b/sql/SQLite3/0.sql index aaf8e820..eefcb9a3 100644 --- a/sql/SQLite3/0.sql +++ b/sql/SQLite3/0.sql @@ -53,8 +53,8 @@ create table newssync_subscriptions( create table newssync_folders( id integer primary key not null, -- sequence number owner TEXT not null references newssync_users(id) on delete cascade on update cascade, -- owner of folder - parent integer not null default 0, -- parent folder id - root integer not null default 0, -- first-level folder (ownCloud folder) + parent integer default null, -- parent folder id + root integer default null, -- first-level folder (ownCloud folder) name TEXT not null, -- folder name modified datetime not null default CURRENT_TIMESTAMP, -- unique(owner,name,parent) -- cannot have multiple folders with the same name under the same parent for the same owner diff --git a/tests/test.php b/tests/test.php new file mode 100644 index 00000000..9531bfab --- /dev/null +++ b/tests/test.php @@ -0,0 +1,24 @@ +dbSQLite3File = ":memory:"; +$conf->userAuthPreferHTTP = true; +$data = new RuntimeData($conf); +$data->db->schemaUpdate(); + + +$data->user->add($user, $pass); +$data->user->auth(); +$data->user->authorizationEnabled(false); +$data->user->rightsSet($user, User\Driver::RIGHTS_GLOBAL_ADMIN); +$data->user->authorizationEnabled(true); +$data->db->folderAdd($user, ['name' => 'ook']); +$data->db->subscriptionAdd($user, "http://www.tbray.org/ongoing/ongoing.atom"); \ No newline at end of file