Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,7 @@ data.ref(someVar + '.members.id')
- Can override `view`, `update`, and `create`
- Cannot override `delete`
- The `create` rule runs during auth signup flows (not via `transact`). Use it to restrict signups or validate `extraFields`.
- `extraFields` require an explicit `create` rule. Without one, signup is blocked to prevent unvalidated writes.

## $files Permissions

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@ data.ref(someVar + '.members.id')
- Can override `view`, `update`, and `create`
- Cannot override `delete`
- The `create` rule runs during auth signup flows (not via `transact`). Use it to restrict signups or validate `extraFields`.
- `extraFields` require an explicit `create` rule. Without one, signup is blocked to prevent unvalidated writes.

## $files Permissions

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@ data.ref(someVar + '.members.id')
- Can override `view`, `update`, and `create`
- Cannot override `delete`
- The `create` rule runs during auth signup flows (not via `transact`). Use it to restrict signups or validate `extraFields`.
- `extraFields` require an explicit `create` rule. Without one, signup is blocked to prevent unvalidated writes.

## $files Permissions

Expand Down
1 change: 1 addition & 0 deletions client/www/lib/intern/instant-rules.md
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,7 @@ data.ref(someVar + '.members.id')
- Can override `view`, `update`, and `create`
- Cannot override `delete`
- The `create` rule runs during auth signup flows (not via `transact`). Use it to restrict signups or validate `extraFields`.
- `extraFields` require an explicit `create` rule. Without one, signup is blocked to prevent unvalidated writes.

## $files Permissions

Expand Down
2 changes: 2 additions & 0 deletions client/www/pages/docs/users.md
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,8 @@ if (created) {
}
```

When using `extraFields`, a `create` rule on `$users` is required. Signup will fail if no rule is defined. This ensures you explicitly opt in to accepting custom fields. A rule of `"true"` allows any values through. See [Signup rules](#signup-rules) for more examples.

## Signup rules

You can write a `create` rule on `$users` to control who can sign up and what fields they can set. This rule runs during the auth signup flow (magic codes, OAuth, guest sign-in) but does not apply to `transact`.
Expand Down
20 changes: 15 additions & 5 deletions server/src/instant/model/app_user.clj
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,14 @@
extra-fields))))

(defn- assert-create-permission!
[app-id user-data]
[app-id user-data has-extra-fields?]
(let [rules (rule-model/get-by-app-id {:app-id app-id})
program (rule-model/get-program! rules "$users" "create")]
(when program
program (rule-model/get-program! rules
{:etype "$users"
:action "create"
:paths [["$users" "allow" "create"]]})]
(cond
program
(let [ctx {:db {:conn-pool (aurora/conn-pool :read)}
:app-id app-id
:attrs (attr-model/get-by-app-id app-id)
Expand All @@ -56,7 +60,13 @@
:perms-pass?
["$users" "create"]
(cel/eval-program! ctx program {:data user-data
:new-data user-data}))))))
:new-data user-data})))

has-extra-fields?
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if we really need this distinction.

I get that it could be a surprise to users, but I also feel it's surprising that the presence or absence of extraFields changes the create rule.

cc @dwwoelfel for thoughts too

(ex/assert-permitted!
:perms-pass?
["$users" "create"]
false))))

(defn assert-signup!
"Validates extra-fields and checks the $users create permission rule.
Expand All @@ -66,7 +76,7 @@
(when-not skip-perm-check?
(let [id (or (:id params) (random-uuid))
user-data (build-user-data (assoc params :id id))]
(assert-create-permission! app-id user-data))))
(assert-create-permission! app-id user-data (seq extra-fields)))))

(defn create!
([params]
Expand Down
20 changes: 20 additions & 0 deletions server/test/instant/runtime/routes_test.clj
Original file line number Diff line number Diff line change
Expand Up @@ -409,6 +409,8 @@
(test-util/make-attrs app-id
[[:$users/username :unique? :index?]
[:$users/displayName]])
(rule-model/put! {:app-id app-id
:code {"$users" {"allow" {"create" "true"}}}})

(testing "new user with extra-fields"
(let [code (send-code app {:email "new@test.com"})
Expand Down Expand Up @@ -478,6 +480,8 @@
(fn [{app-id :id :as app}]
(test-util/make-attrs app-id
[[:$users/username]])
(rule-model/put! {:app-id app-id
:code {"$users" {"allow" {"create" "true"}}}})

(let [guest (sign-in-guest app)
_ (is (= "guest" (:type guest)))
Expand All @@ -498,6 +502,8 @@
(test-util/make-attrs app-id
[[:$users/username]
[:$users/displayName]])
(rule-model/put! {:app-id app-id
:code {"$users" {"allow" {"create" "true"}}}})

(let [provider (provider-model/create! {:app-id app-id
:provider-name "clerk"})]
Expand Down Expand Up @@ -632,6 +638,14 @@
:code code})]
(is (true? (:created body)))))

(testing "extra-fields without create rule blocks signup"
(let [code (send-code app {:email "norule@test.com"})]
(is (thrown-with-msg?
ExceptionInfo #"status 400"
(verify-body app {:email "norule@test.com"
:code code
:extra-fields {"username" "sneaky"}})))))

(testing "create rule does not run for existing users"
(rule-model/put! {:app-id app-id
:code {"$users" {"allow" {"create" "false"}}}})
Expand Down Expand Up @@ -693,6 +707,12 @@
(testing "create rule allows guest signup when passing"
(rule-model/put! {:app-id app-id
:code {"$users" {"allow" {"create" "true"}}}})
(let [guest (sign-in-guest-runtime app)]
(is (= "guest" (:type guest)))))

(testing "$default rules do not affect guest signup"
(rule-model/put! {:app-id app-id
:code {"$default" {"allow" {"$default" "false"}}}})
(let [guest (sign-in-guest-runtime app)]
(is (= "guest" (:type guest))))))))

Expand Down
Loading