parse-server 9.3.0-alpha.2 → 9.3.0-alpha.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +28 -0
- package/lib/Adapters/Auth/BaseCodeAuthAdapter.js +24 -4
- package/lib/Adapters/Storage/Postgres/PostgresStorageAdapter.js +15 -7
- package/lib/Auth.js +16 -3
- package/lib/Config.js +12 -1
- package/lib/Controllers/DatabaseController.js +17 -1
- package/lib/Deprecator/Deprecations.js +6 -2
- package/lib/FileUrlValidator.js +69 -0
- package/lib/GraphQL/transformers/mutation.js +7 -1
- package/lib/Options/Definitions.js +7 -1
- package/lib/Options/docs.js +2 -1
- package/lib/Options/index.js +1 -1
- package/lib/ParseServer.js +2 -2
- package/lib/RestWrite.js +9 -2
- package/lib/Routers/FunctionsRouter.js +7 -1
- package/package.json +7 -7
- package/types/Options/index.d.ts +1 -0
package/README.md
CHANGED
|
@@ -68,6 +68,7 @@ A big _thank you_ 🙏 to our [sponsors](#sponsors) and [backers](#backers) who
|
|
|
68
68
|
- [Using Environment Variables](#using-environment-variables)
|
|
69
69
|
- [Available Adapters](#available-adapters)
|
|
70
70
|
- [Configuring File Adapters](#configuring-file-adapters)
|
|
71
|
+
- [Restricting File URL Domains](#restricting-file-url-domains)
|
|
71
72
|
- [Idempotency Enforcement](#idempotency-enforcement)
|
|
72
73
|
- [Localization](#localization)
|
|
73
74
|
- [Pages](#pages)
|
|
@@ -491,6 +492,33 @@ Parse Server allows developers to choose from several options when hosting files
|
|
|
491
492
|
|
|
492
493
|
`GridFSBucketAdapter` is used by default and requires no setup, but if you're interested in using Amazon S3, Google Cloud Storage, or local file storage, additional configuration information is available in the [Parse Server guide](http://docs.parseplatform.org/parse-server/guide/#configuring-file-adapters).
|
|
493
494
|
|
|
495
|
+
### Restricting File URL Domains
|
|
496
|
+
|
|
497
|
+
Parse objects can reference files by URL. To prevent [SSRF attacks](https://owasp.org/www-community/attacks/Server_Side_Request_Forgery) via crafted file URLs, you can restrict the allowed URL domains using the `fileUpload.allowedFileUrlDomains` option.
|
|
498
|
+
|
|
499
|
+
This protects against scenarios where an attacker provides a `Parse.File` with an arbitrary URL, for example as a Cloud Function parameter or in a field of type `Object` or `Array`. If Cloud Code or a client calls `getData()` on such a file, the Parse SDK makes an HTTP request to that URL, potentially leaking the server or client IP address and accessing internal services.
|
|
500
|
+
|
|
501
|
+
> [!NOTE]
|
|
502
|
+
> Fields of type `Parse.File` in the Parse schema are not affected by this attack, because Parse Server discards the URL on write and dynamically generates it on read based on the file adapter configuration.
|
|
503
|
+
|
|
504
|
+
```javascript
|
|
505
|
+
const parseServer = new ParseServer({
|
|
506
|
+
...otherOptions,
|
|
507
|
+
fileUpload: {
|
|
508
|
+
allowedFileUrlDomains: ['cdn.example.com', '*.example.com'],
|
|
509
|
+
},
|
|
510
|
+
});
|
|
511
|
+
```
|
|
512
|
+
|
|
513
|
+
| Parameter | Optional | Type | Default | Environment Variable |
|
|
514
|
+
|---|---|---|---|---|
|
|
515
|
+
| `fileUpload.allowedFileUrlDomains` | yes | `String[]` | `['*']` | `PARSE_SERVER_FILE_UPLOAD_ALLOWED_FILE_URL_DOMAINS` |
|
|
516
|
+
|
|
517
|
+
- `['*']` (default) allows file URLs with any domain.
|
|
518
|
+
- `['cdn.example.com']` allows only exact hostname matches.
|
|
519
|
+
- `['*.example.com']` allows any subdomain of `example.com`.
|
|
520
|
+
- `[]` blocks all file URLs; only files referenced by name are allowed.
|
|
521
|
+
|
|
494
522
|
## Idempotency Enforcement
|
|
495
523
|
|
|
496
524
|
**Caution, this is an experimental feature that may not be appropriate for production.**
|
|
@@ -62,25 +62,45 @@ class BaseAuthCodeAdapter extends _AuthAdapter.default {
|
|
|
62
62
|
// abstract method
|
|
63
63
|
throw new Error('getAccessTokenFromCode is not implemented');
|
|
64
64
|
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Validates auth data on login. In the standard auth flows (login, signup,
|
|
68
|
+
* update), `beforeFind` runs first and validates credentials, so no
|
|
69
|
+
* additional credential check is needed here.
|
|
70
|
+
*/
|
|
65
71
|
validateLogin(authData) {
|
|
66
|
-
// User validation is already done in beforeFind
|
|
67
72
|
return {
|
|
68
73
|
id: authData.id
|
|
69
74
|
};
|
|
70
75
|
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Validates auth data on first setup or when linking a new provider.
|
|
79
|
+
* In the standard auth flows, `beforeFind` runs first and validates
|
|
80
|
+
* credentials, so no additional credential check is needed here.
|
|
81
|
+
*/
|
|
71
82
|
validateSetUp(authData) {
|
|
72
|
-
// User validation is already done in beforeFind
|
|
73
83
|
return {
|
|
74
84
|
id: authData.id
|
|
75
85
|
};
|
|
76
86
|
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Returns the auth data to expose to the client after a query.
|
|
90
|
+
*/
|
|
77
91
|
afterFind(authData) {
|
|
78
92
|
return {
|
|
79
93
|
id: authData.id
|
|
80
94
|
};
|
|
81
95
|
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Validates auth data on update. In the standard auth flows, `beforeFind`
|
|
99
|
+
* runs first for any changed auth data and validates credentials, so no
|
|
100
|
+
* additional credential check is needed here. Unchanged (echoed-back) data
|
|
101
|
+
* skips both `beforeFind` and validation entirely.
|
|
102
|
+
*/
|
|
82
103
|
validateUpdate(authData) {
|
|
83
|
-
// User validation is already done in beforeFind
|
|
84
104
|
return {
|
|
85
105
|
id: authData.id
|
|
86
106
|
};
|
|
@@ -96,4 +116,4 @@ class BaseAuthCodeAdapter extends _AuthAdapter.default {
|
|
|
96
116
|
}
|
|
97
117
|
}
|
|
98
118
|
exports.default = BaseAuthCodeAdapter;
|
|
99
|
-
//# sourceMappingURL=data:application/json;charset=utf-8;base64,
|
|
119
|
+
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfQXV0aEFkYXB0ZXIiLCJfaW50ZXJvcFJlcXVpcmVEZWZhdWx0IiwicmVxdWlyZSIsImUiLCJfX2VzTW9kdWxlIiwiZGVmYXVsdCIsIkJhc2VBdXRoQ29kZUFkYXB0ZXIiLCJBdXRoQWRhcHRlciIsImNvbnN0cnVjdG9yIiwiYWRhcHRlck5hbWUiLCJ2YWxpZGF0ZU9wdGlvbnMiLCJvcHRpb25zIiwiRXJyb3IiLCJlbmFibGVJbnNlY3VyZUF1dGgiLCJjbGllbnRJZCIsImNsaWVudFNlY3JldCIsImJlZm9yZUZpbmQiLCJhdXRoRGF0YSIsImNvZGUiLCJhY2Nlc3NfdG9rZW4iLCJQYXJzZSIsIk9CSkVDVF9OT1RfRk9VTkQiLCJ1c2VyIiwiZ2V0VXNlckZyb21BY2Nlc3NUb2tlbiIsImlkIiwiVkFMSURBVElPTl9FUlJPUiIsImdldEFjY2Vzc1Rva2VuRnJvbUNvZGUiLCJyZWRpcmVjdF91cmkiLCJ2YWxpZGF0ZUxvZ2luIiwidmFsaWRhdGVTZXRVcCIsImFmdGVyRmluZCIsInZhbGlkYXRlVXBkYXRlIiwicGFyc2VSZXNwb25zZURhdGEiLCJkYXRhIiwic3RhcnRQb3MiLCJpbmRleE9mIiwiZW5kUG9zIiwianNvbkRhdGEiLCJzdWJzdHJpbmciLCJKU09OIiwicGFyc2UiLCJleHBvcnRzIl0sInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL0FkYXB0ZXJzL0F1dGgvQmFzZUNvZGVBdXRoQWRhcHRlci5qcyJdLCJzb3VyY2VzQ29udGVudCI6WyIvLyBhYnN0cmFjdCBjbGFzcyBmb3IgYXV0aCBjb2RlIGFkYXB0ZXJzXG5pbXBvcnQgQXV0aEFkYXB0ZXIgZnJvbSAnLi9BdXRoQWRhcHRlcic7XG5leHBvcnQgZGVmYXVsdCBjbGFzcyBCYXNlQXV0aENvZGVBZGFwdGVyIGV4dGVuZHMgQXV0aEFkYXB0ZXIge1xuICBjb25zdHJ1Y3RvcihhZGFwdGVyTmFtZSkge1xuICAgIHN1cGVyKCk7XG4gICAgdGhpcy5hZGFwdGVyTmFtZSA9IGFkYXB0ZXJOYW1lO1xuICB9XG4gIHZhbGlkYXRlT3B0aW9ucyhvcHRpb25zKSB7XG5cbiAgICBpZiAoIW9wdGlvbnMpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgJHt0aGlzLmFkYXB0ZXJOYW1lfSBvcHRpb25zIGFyZSByZXF1aXJlZC5gKTtcbiAgICB9XG5cbiAgICB0aGlzLmVuYWJsZUluc2VjdXJlQXV0aCA9IG9wdGlvbnMuZW5hYmxlSW5zZWN1cmVBdXRoO1xuICAgIGlmICh0aGlzLmVuYWJsZUluc2VjdXJlQXV0aCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHRoaXMuY2xpZW50SWQgPSBvcHRpb25zLmNsaWVudElkO1xuICAgIHRoaXMuY2xpZW50U2VjcmV0ID0gb3B0aW9ucy5jbGllbnRTZWNyZXQ7XG5cbiAgICBpZiAoIXRoaXMuY2xpZW50SWQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgJHt0aGlzLmFkYXB0ZXJOYW1lfSBjbGllbnRJZCBpcyByZXF1aXJlZC5gKTtcbiAgICB9XG5cbiAgICBpZiAoIXRoaXMuY2xpZW50U2VjcmV0KSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYCR7dGhpcy5hZGFwdGVyTmFtZX0gY2xpZW50U2VjcmV0IGlzIHJlcXVpcmVkLmApO1xuICAgIH1cbiAgfVxuXG4gIGFzeW5jIGJlZm9yZUZpbmQoYXV0aERhdGEpIHtcbiAgICBpZiAodGhpcy5lbmFibGVJbnNlY3VyZUF1dGggJiYgIWF1dGhEYXRhPy5jb2RlKSB7XG4gICAgICBpZiAoIWF1dGhEYXRhPy5hY2Nlc3NfdG9rZW4pIHtcbiAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLk9CSkVDVF9OT1RfRk9VTkQsIGAke3RoaXMuYWRhcHRlck5hbWV9IGF1dGggaXMgaW52YWxpZCBmb3IgdGhpcyB1c2VyLmApO1xuICAgICAgfVxuXG4gICAgICBjb25zdCB1c2VyID0gYXdhaXQgdGhpcy5nZXRVc2VyRnJvbUFjY2Vzc1Rva2VuKGF1dGhEYXRhLmFjY2Vzc190b2tlbiwgYXV0aERhdGEpO1xuXG4gICAgICBpZiAodXNlci5pZCAhPT0gYXV0aERhdGEuaWQpIHtcbiAgICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLk9CSkVDVF9OT1RfRk9VTkQsIGAke3RoaXMuYWRhcHRlck5hbWV9IGF1dGggaXMgaW52YWxpZCBmb3IgdGhpcyB1c2VyLmApO1xuICAgICAgfVxuXG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKCFhdXRoRGF0YT8uY29kZSkge1xuICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLlZBTElEQVRJT05fRVJST1IsIGAke3RoaXMuYWRhcHRlck5hbWV9IGNvZGUgaXMgcmVxdWlyZWQuYCk7XG4gICAgfVxuXG4gICAgY29uc3QgYWNjZXNzX3Rva2VuID0gYXdhaXQgdGhpcy5nZXRBY2Nlc3NUb2tlbkZyb21Db2RlKGF1dGhEYXRhKTtcbiAgICBjb25zdCB1c2VyID0gYXdhaXQgdGhpcy5nZXRVc2VyRnJvbUFjY2Vzc1Rva2VuKGFjY2Vzc190b2tlbiwgYXV0aERhdGEpO1xuXG4gICAgaWYgKGF1dGhEYXRhLmlkICYmIHVzZXIuaWQgIT09IGF1dGhEYXRhLmlkKSB7XG4gICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuT0JKRUNUX05PVF9GT1VORCwgYCR7dGhpcy5hZGFwdGVyTmFtZX0gYXV0aCBpcyBpbnZhbGlkIGZvciB0aGlzIHVzZXIuYCk7XG4gICAgfVxuXG4gICAgYXV0aERhdGEuYWNjZXNzX3Rva2VuID0gYWNjZXNzX3Rva2VuO1xuICAgIGF1dGhEYXRhLmlkID0gdXNlci5pZDtcblxuICAgIGRlbGV0ZSBhdXRoRGF0YS5jb2RlO1xuICAgIGRlbGV0ZSBhdXRoRGF0YS5yZWRpcmVjdF91cmk7XG5cbiAgfVxuXG4gIGFzeW5jIGdldFVzZXJGcm9tQWNjZXNzVG9rZW4oKSB7XG4gICAgLy8gYWJzdHJhY3QgbWV0aG9kXG4gICAgdGhyb3cgbmV3IEVycm9yKCdnZXRVc2VyRnJvbUFjY2Vzc1Rva2VuIGlzIG5vdCBpbXBsZW1lbnRlZCcpO1xuICB9XG5cbiAgYXN5bmMgZ2V0QWNjZXNzVG9rZW5Gcm9tQ29kZSgpIHtcbiAgICAvLyBhYnN0cmFjdCBtZXRob2RcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ2dldEFjY2Vzc1Rva2VuRnJvbUNvZGUgaXMgbm90IGltcGxlbWVudGVkJyk7XG4gIH1cblxuICAvKipcbiAgICogVmFsaWRhdGVzIGF1dGggZGF0YSBvbiBsb2dpbi4gSW4gdGhlIHN0YW5kYXJkIGF1dGggZmxvd3MgKGxvZ2luLCBzaWdudXAsXG4gICAqIHVwZGF0ZSksIGBiZWZvcmVGaW5kYCBydW5zIGZpcnN0IGFuZCB2YWxpZGF0ZXMgY3JlZGVudGlhbHMsIHNvIG5vXG4gICAqIGFkZGl0aW9uYWwgY3JlZGVudGlhbCBjaGVjayBpcyBuZWVkZWQgaGVyZS5cbiAgICovXG4gIHZhbGlkYXRlTG9naW4oYXV0aERhdGEpIHtcbiAgICByZXR1cm4ge1xuICAgICAgaWQ6IGF1dGhEYXRhLmlkLFxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBWYWxpZGF0ZXMgYXV0aCBkYXRhIG9uIGZpcnN0IHNldHVwIG9yIHdoZW4gbGlua2luZyBhIG5ldyBwcm92aWRlci5cbiAgICogSW4gdGhlIHN0YW5kYXJkIGF1dGggZmxvd3MsIGBiZWZvcmVGaW5kYCBydW5zIGZpcnN0IGFuZCB2YWxpZGF0ZXNcbiAgICogY3JlZGVudGlhbHMsIHNvIG5vIGFkZGl0aW9uYWwgY3JlZGVudGlhbCBjaGVjayBpcyBuZWVkZWQgaGVyZS5cbiAgICovXG4gIHZhbGlkYXRlU2V0VXAoYXV0aERhdGEpIHtcbiAgICByZXR1cm4ge1xuICAgICAgaWQ6IGF1dGhEYXRhLmlkLFxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSBhdXRoIGRhdGEgdG8gZXhwb3NlIHRvIHRoZSBjbGllbnQgYWZ0ZXIgYSBxdWVyeS5cbiAgICovXG4gIGFmdGVyRmluZChhdXRoRGF0YSkge1xuICAgIHJldHVybiB7XG4gICAgICBpZDogYXV0aERhdGEuaWQsXG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFZhbGlkYXRlcyBhdXRoIGRhdGEgb24gdXBkYXRlLiBJbiB0aGUgc3RhbmRhcmQgYXV0aCBmbG93cywgYGJlZm9yZUZpbmRgXG4gICAqIHJ1bnMgZmlyc3QgZm9yIGFueSBjaGFuZ2VkIGF1dGggZGF0YSBhbmQgdmFsaWRhdGVzIGNyZWRlbnRpYWxzLCBzbyBub1xuICAgKiBhZGRpdGlvbmFsIGNyZWRlbnRpYWwgY2hlY2sgaXMgbmVlZGVkIGhlcmUuIFVuY2hhbmdlZCAoZWNob2VkLWJhY2spIGRhdGFcbiAgICogc2tpcHMgYm90aCBgYmVmb3JlRmluZGAgYW5kIHZhbGlkYXRpb24gZW50aXJlbHkuXG4gICAqL1xuICB2YWxpZGF0ZVVwZGF0ZShhdXRoRGF0YSkge1xuICAgIHJldHVybiB7XG4gICAgICBpZDogYXV0aERhdGEuaWQsXG4gICAgfVxuICB9XG5cbiAgcGFyc2VSZXNwb25zZURhdGEoZGF0YSkge1xuICAgIGNvbnN0IHN0YXJ0UG9zID0gZGF0YS5pbmRleE9mKCcoJyk7XG4gICAgY29uc3QgZW5kUG9zID0gZGF0YS5pbmRleE9mKCcpJyk7XG4gICAgaWYgKHN0YXJ0UG9zID09PSAtMSB8fCBlbmRQb3MgPT09IC0xKSB7XG4gICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuT0JKRUNUX05PVF9GT1VORCwgYCR7dGhpcy5hZGFwdGVyTmFtZX0gYXV0aCBpcyBpbnZhbGlkIGZvciB0aGlzIHVzZXIuYCk7XG4gICAgfVxuICAgIGNvbnN0IGpzb25EYXRhID0gZGF0YS5zdWJzdHJpbmcoc3RhcnRQb3MgKyAxLCBlbmRQb3MpO1xuICAgIHJldHVybiBKU09OLnBhcnNlKGpzb25EYXRhKTtcbiAgfVxufVxuIl0sIm1hcHBpbmdzIjoiOzs7Ozs7QUFDQSxJQUFBQSxZQUFBLEdBQUFDLHNCQUFBLENBQUFDLE9BQUE7QUFBd0MsU0FBQUQsdUJBQUFFLENBQUEsV0FBQUEsQ0FBQSxJQUFBQSxDQUFBLENBQUFD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TUosc0JBQXNCQSxDQUFBLEVBQUc7SUFDN0I7SUFDQSxNQUFNLElBQUlYLEtBQUssQ0FBQywyQ0FBMkMsQ0FBQztFQUM5RDtFQUVBLE1BQU1jLHNCQUFzQkEsQ0FBQSxFQUFHO0lBQzdCO0lBQ0EsTUFBTSxJQUFJZCxLQUFLLENBQUMsMkNBQTJDLENBQUM7RUFDOUQ7O0VBRUE7QUFDRjtBQUNBO0FBQ0E7QUFDQTtFQUNFZ0IsYUFBYUEsQ0FBQ1gsUUFBUSxFQUFFO0lBQ3RCLE9BQU87TUFDTE8sRUFBRSxFQUFFUCxRQUFRLENBQUNPO0lBQ2YsQ0FBQztFQUNIOztFQUVBO0FBQ0Y7QUFDQTtBQUNBO0FBQ0E7RUFDRUssYUFBYUEsQ0FBQ1osUUFBUSxFQUFFO0lBQ3RCLE9BQU87TUFDTE8sRUFBRSxFQUFFUCxRQUFRLENBQUNPO0lBQ2YsQ0FBQztFQUNIOztFQUVBO0FBQ0Y7QUFDQTtFQUNFTSxTQUFTQSxDQUFDYixRQUFRLEVBQUU7SUFDbEIsT0FBTztNQUNMTyxFQUFFLEVBQUVQLFFBQVEsQ0FBQ087SUFDZixDQUFDO0VBQ0g7O0VBRUE7QUFDRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0VBQ0VPLGNBQWNBLENBQUNkLFFBQVEsRUFBRTtJQUN2QixPQUFPO01BQ0xPLEVBQUUsRUFBRVAsUUFBUSxDQUFDTztJQUNmLENBQUM7RUFDSDtFQUVBUSxpQkFBaUJBLENBQUNDLElBQUksRUFBRTtJQUN0QixNQUFNQyxRQUFRLEdBQUdELElBQUksQ0FBQ0UsT0FBTyxDQUFDLEdBQUcsQ0FBQztJQUNsQyxNQUFNQyxNQUFNLEdBQUdILElBQUksQ0FBQ0UsT0FBTyxDQUFDLEdBQUcsQ0FBQztJQUNoQyxJQUFJRCxRQUFRLEtBQUssQ0FBQyxDQUFDLElBQUlFLE1BQU0sS0FBSyxDQUFDLENBQUMsRUFBRTtNQUNwQyxNQUFNLElBQUloQixLQUFLLENBQUNSLEtBQUssQ0FBQ1EsS0FBSyxDQUFDUixLQUFLLENBQUNTLGdCQUFnQixFQUFFLEdBQUcsSUFBSSxDQUFDWixXQUFXLGlDQUFpQyxDQUFDO0lBQzNHO0lBQ0EsTUFBTTRCLFFBQVEsR0FBR0osSUFBSSxDQUFDSyxTQUFTLENBQUNKLFFBQVEsR0FBRyxDQUFDLEVBQUVFLE1BQU0sQ0FBQztJQUNyRCxPQUFPRyxJQUFJLENBQUNDLEtBQUssQ0FBQ0gsUUFBUSxDQUFDO0VBQzdCO0FBQ0Y7QUFBQ0ksT0FBQSxDQUFBcEMsT0FBQSxHQUFBQyxtQkFBQSIsImlnbm9yZUxpc3QiOltdfQ==
|