{"action":"created","issue":{"url":"https://api.github.com/repos/firebase/bolt/issues/110","labels_url":"https://api.github.com/repos/firebase/bolt/issues/110/labels{/name}","comments_url":"https://api.github.com/repos/firebase/bolt/issues/110/comments","events_url":"https://api.github.com/repos/firebase/bolt/issues/110/events","html_url":"https://github.com/firebase/bolt/issues/110","id":126013193,"number":110,"title":"Defining two paths, one parent one child, with wildcard and type","user":{"login":"mm-gmbd","id":3329824,"avatar_url":"https://avatars.githubusercontent.com/u/3329824?v=3","gravatar_id":"","url":"https://api.github.com/users/mm-gmbd","html_url":"https://github.com/mm-gmbd","followers_url":"https://api.github.com/users/mm-gmbd/followers","following_url":"https://api.github.com/users/mm-gmbd/following{/other_user}","gists_url":"https://api.github.com/users/mm-gmbd/gists{/gist_id}","starred_url":"https://api.github.com/users/mm-gmbd/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mm-gmbd/subscriptions","organizations_url":"https://api.github.com/users/mm-gmbd/orgs","repos_url":"https://api.github.com/users/mm-gmbd/repos","events_url":"https://api.github.com/users/mm-gmbd/events{/privacy}","received_events_url":"https://api.github.com/users/mm-gmbd/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":1,"created_at":"2016-01-11T19:04:19Z","updated_at":"2016-01-11T19:09:53Z","closed_at":null,"body":"I want to allow reads of a collection of `Elements`, but I want enforce pushing (with [Firebase.push()](https://www.firebase.com/docs/web/api/firebase/push.html) once at a time in a create-but-not-modify fashion.\r\n\r\nTo accomplish this, I've got the following rules:\r\n\r\n```\r\ntype Element {\r\n  num: Number,\r\n  str: String\r\n}\r\n\r\npath /path/of/elements is Element[] {\r\n  read()  = true;\r\n  write() = false;\r\n}\r\n\r\npath /path/of/elements/$idElement is Element {\r\n  read() = true;\r\n  write() = createOnly(this);\r\n}\r\n\r\nfunction createOnly(value) {\r\n  return prior(value) == null && value != null;\r\n}\r\n```\r\n\r\nThe problem is, because the parent location uses `Element[]` notation, it uses the wildcard `$key1`, but then the next path (which is the direct child), uses the wildcard `$idElement` which generates the following rules and causes a conflict:\r\n\r\n```\r\n{\r\n  \"rules\": {\r\n    \"path\": {\r\n      \"of\": {\r\n        \"elements\": {\r\n          \"$key1\": {\r\n            \".validate\": \"newData.hasChildren(['num', 'str'])\",\r\n            \"num\": {\r\n              \".validate\": \"newData.isNumber()\"\r\n            },\r\n            \"str\": {\r\n              \".validate\": \"newData.isString()\"\r\n            },\r\n            \"$other\": {\r\n              \".validate\": \"false\"\r\n            }\r\n          },\r\n          \".read\": \"true\",\r\n          \"$idElement\": {\r\n            \".validate\": \"newData.hasChildren(['num', 'str'])\",\r\n            \"num\": {\r\n              \".validate\": \"newData.isNumber()\"\r\n            },\r\n            \"str\": {\r\n              \".validate\": \"newData.isString()\"\r\n            },\r\n            \"$other\": {\r\n              \".validate\": \"false\"\r\n            },\r\n            \".read\": \"true\",\r\n            \".write\": \"data.val() == null && newData.val() != null\"\r\n          }\r\n        }\r\n      }\r\n    }\r\n  }\r\n}\r\n```\r\n\r\nI get around this by removing `is Element[]` from the parent path, but should Bolt be able to detect this and handle elegantly?"},"comment":{"url":"https://api.github.com/repos/firebase/bolt/issues/comments/170655759","html_url":"https://github.com/firebase/bolt/issues/110#issuecomment-170655759","issue_url":"https://api.github.com/repos/firebase/bolt/issues/110","id":170655759,"user":{"login":"mm-gmbd","id":3329824,"avatar_url":"https://avatars.githubusercontent.com/u/3329824?v=3","gravatar_id":"","url":"https://api.github.com/users/mm-gmbd","html_url":"https://github.com/mm-gmbd","followers_url":"https://api.github.com/users/mm-gmbd/followers","following_url":"https://api.github.com/users/mm-gmbd/following{/other_user}","gists_url":"https://api.github.com/users/mm-gmbd/gists{/gist_id}","starred_url":"https://api.github.com/users/mm-gmbd/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mm-gmbd/subscriptions","organizations_url":"https://api.github.com/users/mm-gmbd/orgs","repos_url":"https://api.github.com/users/mm-gmbd/repos","events_url":"https://api.github.com/users/mm-gmbd/events{/privacy}","received_events_url":"https://api.github.com/users/mm-gmbd/received_events","type":"User","site_admin":false},"created_at":"2016-01-11T19:09:53Z","updated_at":"2016-01-11T19:09:53Z","body":"Also, in the use case above, I guess it doesn't matter to remove the `is Element[]` from the parent path because that is used for *validation*, and the `write()` rule is set to false.\r\n\r\n*But*, say the write at the parent location is not simply false, how can this be enforced?\r\n\r\nThe new use case could be the following:\r\n\r\n```\r\ntype Element {\r\n  num: Number,\r\n  str: String\r\n}\r\n\r\npath /path/of/elements is Element[] {\r\n  read()  = true;\r\n  write() = isAuthAdmin();\r\n}\r\n\r\npath /path/of/elements/$idElement is Element {\r\n  read() = true;\r\n  write() = isAuthStandard() && createOnly(this);\r\n}\r\n\r\nfunction createOnly(value) {\r\n  return prior(value) == null && value != null;\r\n}\r\n\r\nfunction isAuthAdmin() {\r\n  return root.users[auth.uid].admin == true;\r\n}\r\n\r\nfunction isAuthStandard() {\r\n  return root.users[auth.uid].admin == false || root.users[auth.uid].admin == null;\r\n}\r\n```\r\n\r\nNow, an admin user can create as many records at `path/of/elements/` as desired, but we ensure that a standard user can still only create a record at a time.\r\n\r\nThe conflict still exists. Thoughts?"}}