mirror of
https://github.com/parse-community/parse-server
synced 2026-08-09 13:03:18 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7a3c9cd33a | ||
|
|
193e5a4278 | ||
|
|
6ae0675010 | ||
|
|
a520ea0243 | ||
|
|
58bdeeee2d | ||
|
|
fc7f9f76f5 | ||
|
|
ef8d534679 | ||
|
|
1c9852e53f | ||
|
|
3f0de0c2ed | ||
|
|
eccdeccb59 | ||
|
|
f16f8423db | ||
|
|
bd60a5c1d1 | ||
|
|
40b9f953ca | ||
|
|
15eafd4dcc | ||
|
|
11cde12245 | ||
|
|
5861996cb0 | ||
|
|
ca70ad0141 | ||
|
|
5a22df13a5 | ||
|
|
5b7144176c | ||
|
|
4979503f63 | ||
|
|
e32a37c2ec | ||
|
|
f7f17cdb23 | ||
|
|
ecf422b2d9 | ||
|
|
49dc8df1de | ||
|
|
c3c5f06efd | ||
|
|
2a454fec35 | ||
|
|
01b4c4e0cb | ||
|
|
3714d68aaf | ||
|
|
77daa3ca18 | ||
|
|
0b574f04a9 | ||
|
|
a89a30182e | ||
|
|
96a9588a6e | ||
|
|
66cdfaed4b | ||
|
|
9262147a6f | ||
|
|
8b4e9ca637 | ||
|
|
2160d10990 | ||
|
|
e7f2995143 | ||
|
|
d5940b17b6 | ||
|
|
f864141663 | ||
|
|
711db9ccd2 | ||
|
|
6a6829ce80 | ||
|
|
d67be492f5 | ||
|
|
ea45f69af6 | ||
|
|
43c3d8e2a2 | ||
|
|
d8a1a614e8 | ||
|
|
553db0ada5 | ||
|
|
388a59d816 | ||
|
|
de4c1ee418 | ||
|
|
cb15c0b616 | ||
|
|
8dd864a033 | ||
|
|
c26db2248f | ||
|
|
b2a3479dbf | ||
|
|
deedf7b370 | ||
|
|
5f849ca662 | ||
|
|
0279b5e5f3 | ||
|
|
4cb6e7d209 | ||
|
|
56bb505df2 | ||
|
|
ceb5a1b5f0 | ||
|
|
0958b15297 | ||
|
|
5d9dbea07b | ||
|
|
f331f6644c | ||
|
|
df029b82eb | ||
|
|
edba550cf6 | ||
|
|
c7775eb0b9 | ||
|
|
0b44820a7d | ||
|
|
b7322064d8 | ||
|
|
ac3f5cd686 | ||
|
|
9fd34fd25e | ||
|
|
7ff3a3813d | ||
|
|
754f5d0505 | ||
|
|
0e8c3c2457 | ||
|
|
423a50133a | ||
|
|
a3d416de4a | ||
|
|
a2dfcc8da8 | ||
|
|
f4734a65c0 | ||
|
|
aa071e034e | ||
|
|
4f46eceacf | ||
|
|
81ebbb8954 | ||
|
|
e82395e268 | ||
|
|
0159360a5d | ||
|
|
aab10bea79 | ||
|
|
752f0e9143 | ||
|
|
025e7a3218 | ||
|
|
ca286b7108 | ||
|
|
a6c988176e | ||
|
|
e069b20ef9 | ||
|
|
ae30ec647b | ||
|
|
fc53fa9c32 | ||
|
|
c1dcaf1271 | ||
|
|
a9067260fc | ||
|
|
2e569ca7dd | ||
|
|
8111c3338e | ||
|
|
fb36dfa26f | ||
|
|
998b271994 | ||
|
|
a7821f6e57 | ||
|
|
ddb6f7bc57 | ||
|
|
8124bf4600 | ||
|
|
df74a1f8ae | ||
|
|
e0704b440c | ||
|
|
01b05b060f | ||
|
|
a270632570 | ||
|
|
b9afccd338 | ||
|
|
37daafc7b0 | ||
|
|
8359284329 | ||
|
|
2b0c39caaa | ||
|
|
11f7712651 | ||
|
|
7292fa7f11 | ||
|
|
4d17bed374 | ||
|
|
143bd11638 | ||
|
|
bd1689190f | ||
|
|
08bac9f790 | ||
|
|
f2df0303b2 | ||
|
|
fbb2b086af |
+7
-1
@@ -15,6 +15,12 @@
|
||||
},
|
||||
"rules": {
|
||||
"indent": ["error", 2],
|
||||
"linebreak-style": ["error", "unix"]
|
||||
"linebreak-style": ["error", "unix"],
|
||||
"no-trailing-spaces": 2,
|
||||
"eol-last": 2,
|
||||
"space-in-parens": ["error", "never"],
|
||||
"no-multiple-empty-lines": 1,
|
||||
"prefer-const": "error",
|
||||
"space-infix-ops": "error"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,50 +1,28 @@
|
||||
Please read the following instructions carefully.
|
||||
We use GitHub Issues for bugs.
|
||||
|
||||
Check out https://github.com/ParsePlatform/parse-server/issues/1271 for an ideal bug report.
|
||||
The closer your issue report is to that one, the more likely we are to be able to help, and the more likely we will be to fix the issue quickly!
|
||||
If you have a non-bug question, ask on Stack Overflow or Server Fault:
|
||||
- https://stackoverflow.com/questions/tagged/parse.com
|
||||
- https://serverfault.com/tags/parse
|
||||
|
||||
Many members of the community use Stack Overflow and Server Fault to ask questions.
|
||||
Read through the existing questions or ask your own!
|
||||
- Stack Overflow: http://stackoverflow.com/questions/tagged/parse.com
|
||||
- Server Fault: https://serverfault.com/tags/parse
|
||||
You may also search through existing issues before opening a new one: https://github.com/ParsePlatform/Parse-Server/issues?utf8=%E2%9C%93&q=is%3Aissue
|
||||
|
||||
For database migration help, please file a bug report at https://parse.com/help#report
|
||||
|
||||
Make sure these boxes are checked before submitting your issue -- thanks for reporting issues back to Parse Server!
|
||||
|
||||
- [ ] You've met the prerequisites: https://github.com/ParsePlatform/parse-server/wiki/Parse-Server-Guide#prerequisites.
|
||||
|
||||
- [ ] You're running the latest version of Parse Server: https://github.com/ParsePlatform/parse-server/releases
|
||||
|
||||
- [ ] You've searched through existing issues: https://github.com/ParsePlatform/Parse-Server/issues?utf8=%E2%9C%93&q=is%3Aissue Chances are that your issue has been reported or resolved before.
|
||||
|
||||
- [ ] You have filled out every section below. Issues without sufficient information are more likely to be closed.
|
||||
|
||||
--
|
||||
--- Please use this template. If you don't use this template, your issue may be closed without comment. ---
|
||||
|
||||
### Issue Description
|
||||
|
||||
[DELETE EVERYTHING ABOVE THIS LINE BEFORE SUBMITTING YOUR ISSUE]
|
||||
|
||||
Describe your issue in as much detail as possible.
|
||||
|
||||
[FILL THIS OUT]
|
||||
|
||||
### Steps to reproduce
|
||||
|
||||
Please include a detailed list of steps that reproduce the issue. Include curl commands when applicable.
|
||||
|
||||
1. [FILL THIS OUT]
|
||||
2. [FILL THIS OUT]
|
||||
3. [FILL THIS OUT]
|
||||
|
||||
#### Expected Results
|
||||
|
||||
[FILL THIS OUT]
|
||||
What you expected to happen.
|
||||
|
||||
#### Actual Outcome
|
||||
|
||||
[FILL THIS OUT]
|
||||
What is happening instead.
|
||||
|
||||
### Environment Setup
|
||||
|
||||
@@ -62,6 +40,4 @@ Please include a detailed list of steps that reproduce the issue. Include curl c
|
||||
|
||||
### Logs/Trace
|
||||
|
||||
You can turn on additional logging by configuring VERBOSE=1 in your environment.
|
||||
|
||||
[FILL THIS OUT]
|
||||
Include all relevant logs. You can turn on additional logging by configuring VERBOSE=1 in your environment.
|
||||
|
||||
@@ -44,6 +44,7 @@ lib/
|
||||
|
||||
# cache folder
|
||||
.cache
|
||||
.eslintcache
|
||||
|
||||
# Mac DS_Store files
|
||||
.DS_Store
|
||||
|
||||
+14
-15
@@ -1,8 +1,7 @@
|
||||
language: node_js
|
||||
dist: trusty
|
||||
sudo: required
|
||||
node_js:
|
||||
- '4.5'
|
||||
- '4.6'
|
||||
- '6.1'
|
||||
services:
|
||||
- postgresql
|
||||
@@ -10,12 +9,13 @@ services:
|
||||
- docker
|
||||
addons:
|
||||
postgresql: '9.5'
|
||||
apt_packages:
|
||||
- postgresql-9.5-postgis-2.3
|
||||
before_script:
|
||||
- ls -al "$HOME/.mongodb/versions"
|
||||
- psql -c 'create database parse_server_postgres_adapter_test_database;' -U postgres
|
||||
- psql -c 'CREATE EXTENSION postgis;' -U postgres -d parse_server_postgres_adapter_test_database
|
||||
- psql -c 'CREATE EXTENSION postgis_topology;' -U postgres -d parse_server_postgres_adapter_test_database
|
||||
- npm run lint
|
||||
env:
|
||||
global:
|
||||
- COVERAGE_OPTION='./node_modules/.bin/istanbul cover'
|
||||
@@ -26,8 +26,6 @@ env:
|
||||
- PARSE_SERVER_TEST_CACHE=redis
|
||||
matrix:
|
||||
fast_finish: true
|
||||
allow_failures:
|
||||
- env: PARSE_SERVER_TEST_DB=postgres
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
@@ -45,6 +43,17 @@ after_success:
|
||||
- export $(cat resources/.to_export_back)
|
||||
|
||||
deploy:
|
||||
- provider: npm
|
||||
skip_cleanup: true
|
||||
email:
|
||||
secure: T3LwSJFcu632SDfCoavcKL39NktWLEOOFzonAjeHAglmMyDp9hvU8xHwQ4JJy2CRA03c+ezAe2gH3Va+jfxvh1JtFUan+p88vaCHHKuNwPSp4WZBPt1ZTDmG+ACG6j+ZWHK+eP7hLvtlCi/M9/v4/bVojpm7v01LLiM+MRhnE9E7eLemQC4zb6RVtf2oGQ3mX51kMeya218kEm5bsQPpRJElI9jwletFa8qYK5AFgaCHpll059RRHQTTE9MTNcN58P/Kf6Qb3KGpKNoaHTXoOD4U6LcXLWvdHONVB6AzGefxg2b/dvtaO4nd5lDooMBR3u9kWpopXkyAuf+fO/8je9JTxO6CDUtDjHRcR2mCEXWX6rculIAbNXOv1ccRYCTQ8aFtYnFlMSb1+QIAdyT6HHmeT5ktk3+XJRuEv0PJJvqHTo+j7tPngjiv5sPNutgGFlOFO90omTbzEkIT/D/LsgXbWm2QKYWejbLiuSINg+FiFiZN90doCf4aCpm2y1Q/9GzvK+eXcpqzPCGxOykE7EuPZK3+S/ZU2oaWL2uSpbKPtC0qxebrneR307aVEa7C85HCkTMMBzE4tjUr8h5HhLqtWvqmDcnBo3PfQhf9cEO6jQLd3qhEVJmcwKz/yOCfgPXlCbRqiKk7j94perpNCIalXtMI9ySYjJNjHsB4600=
|
||||
api_key:
|
||||
secure: WLjhHVAdUkDy6UdNWveTpZqphw9olN0alCpyPpU0cJjlN/hk7YxPP+YHOSVnMZaRZoHM0LL11jPKLf970nymBfvJHDWxKk71c/5xyTX8pBtSxmGmGy23a5g2VrHVMd2JxsI7NEAH500tlFz+01t4E3Steo0NpAkHR3Q51kj01gQy8IumsksfhRc9uvjZ7zjm99Yk4L+cxyei79v4esfpx7Bgm0HTfAAAG/19F+r0hvvFiV517SREDU/YtcX/rIjVepEy1uiLKEohnmYtVIRSA3Hjh6VlHVhdj2WDd/dYrxi/Ioysq2zOM9pZVLamO9asB1e6JrTEipWE9jSZXxsbnfFzuNLxcOjKv1wd3OzQKF/7pGKGiWRTv5Xm19D/FrXoE/ULs6bHcC/Ke8Gs2RxPlOCdvAFehCkyf5P4HOPCQdR7o8Yiuvt+5JWKBflElNbSd4nWgwUOo3Yv8vC4Vj53fwmM+Uqfu3IgYFWktYxCm4RWIKMfB/gtmjcF6QYFfjvEMwAvRfBV81kuynCsnubXWzQeBE/b3JOhBfpGciKCjKfy+tS6bZfFjCtQV98hMMiCPre8Y7PahHDYc65wU9Ake+ZE+dDaSbeV3DZ5JeifLJHzKW2J2dWeRANkOaiSwO9VBC9/rht5ulK5qQ1pB2+sKDToAaiKy6RMlB/HgIoYqsU=
|
||||
on:
|
||||
tags: true
|
||||
all_branches: true
|
||||
condition: "$BUILD_LEADER$BUILD_AGGREGATE_STATUS = YESothers_succeeded"
|
||||
repo: ParsePlatform/parse-server
|
||||
- provider: script
|
||||
skip_cleanup: true
|
||||
script: ./resources/npm-git.sh
|
||||
@@ -58,13 +67,3 @@ deploy:
|
||||
tags: true
|
||||
all_branches: true
|
||||
condition: "$BUILD_LEADER$BUILD_AGGREGATE_STATUS = YESothers_succeeded"
|
||||
- provider: npm
|
||||
email:
|
||||
secure: T3LwSJFcu632SDfCoavcKL39NktWLEOOFzonAjeHAglmMyDp9hvU8xHwQ4JJy2CRA03c+ezAe2gH3Va+jfxvh1JtFUan+p88vaCHHKuNwPSp4WZBPt1ZTDmG+ACG6j+ZWHK+eP7hLvtlCi/M9/v4/bVojpm7v01LLiM+MRhnE9E7eLemQC4zb6RVtf2oGQ3mX51kMeya218kEm5bsQPpRJElI9jwletFa8qYK5AFgaCHpll059RRHQTTE9MTNcN58P/Kf6Qb3KGpKNoaHTXoOD4U6LcXLWvdHONVB6AzGefxg2b/dvtaO4nd5lDooMBR3u9kWpopXkyAuf+fO/8je9JTxO6CDUtDjHRcR2mCEXWX6rculIAbNXOv1ccRYCTQ8aFtYnFlMSb1+QIAdyT6HHmeT5ktk3+XJRuEv0PJJvqHTo+j7tPngjiv5sPNutgGFlOFO90omTbzEkIT/D/LsgXbWm2QKYWejbLiuSINg+FiFiZN90doCf4aCpm2y1Q/9GzvK+eXcpqzPCGxOykE7EuPZK3+S/ZU2oaWL2uSpbKPtC0qxebrneR307aVEa7C85HCkTMMBzE4tjUr8h5HhLqtWvqmDcnBo3PfQhf9cEO6jQLd3qhEVJmcwKz/yOCfgPXlCbRqiKk7j94perpNCIalXtMI9ySYjJNjHsB4600=
|
||||
api_key:
|
||||
secure: WLjhHVAdUkDy6UdNWveTpZqphw9olN0alCpyPpU0cJjlN/hk7YxPP+YHOSVnMZaRZoHM0LL11jPKLf970nymBfvJHDWxKk71c/5xyTX8pBtSxmGmGy23a5g2VrHVMd2JxsI7NEAH500tlFz+01t4E3Steo0NpAkHR3Q51kj01gQy8IumsksfhRc9uvjZ7zjm99Yk4L+cxyei79v4esfpx7Bgm0HTfAAAG/19F+r0hvvFiV517SREDU/YtcX/rIjVepEy1uiLKEohnmYtVIRSA3Hjh6VlHVhdj2WDd/dYrxi/Ioysq2zOM9pZVLamO9asB1e6JrTEipWE9jSZXxsbnfFzuNLxcOjKv1wd3OzQKF/7pGKGiWRTv5Xm19D/FrXoE/ULs6bHcC/Ke8Gs2RxPlOCdvAFehCkyf5P4HOPCQdR7o8Yiuvt+5JWKBflElNbSd4nWgwUOo3Yv8vC4Vj53fwmM+Uqfu3IgYFWktYxCm4RWIKMfB/gtmjcF6QYFfjvEMwAvRfBV81kuynCsnubXWzQeBE/b3JOhBfpGciKCjKfy+tS6bZfFjCtQV98hMMiCPre8Y7PahHDYc65wU9Ake+ZE+dDaSbeV3DZ5JeifLJHzKW2J2dWeRANkOaiSwO9VBC9/rht5ulK5qQ1pB2+sKDToAaiKy6RMlB/HgIoYqsU=
|
||||
on:
|
||||
tags: true
|
||||
all_branches: true
|
||||
condition: "$MONGODB_VERSION = '3.0.8'"
|
||||
repo: ParsePlatform/parse-server
|
||||
|
||||
+81
-2
@@ -1,5 +1,84 @@
|
||||
## Parse Server Changelog
|
||||
|
||||
### 2.3.4
|
||||
[Full Changelog](https://github.com/ParsePlatform/parse-server/compare/2.3.3...2.3.4)
|
||||
|
||||
#### Bug Fixes
|
||||
* Allow empty client key
|
||||
(#3497), thanks to [Arthur Cinader](https://github.com/acinader)
|
||||
* Fix LiveQuery unsafe user
|
||||
(#3525), thanks to [David Starke](https://github.com/dstarke)
|
||||
* Use `flushdb` instead of `flushall` in RedisCacheAdapter
|
||||
(#3523), thanks to [Jeremy Louie](https://github.com/JeremyPlease)
|
||||
* Fix saving GeoPoints and Files in `_GlobalConfig` (Make sure we don't treat
|
||||
dot notation keys as topLevel atoms)
|
||||
(#3531), thanks to [Florent Vilmart](https://github.com/flovilmart)
|
||||
|
||||
### 2.3.3
|
||||
[Full Changelog](https://github.com/ParsePlatform/parse-server/compare/2.3.2...2.3.3)
|
||||
|
||||
#### Breaking Changes
|
||||
* **Minimum Node engine bumped to 4.6** (#3480), thanks to [Florent Vilmart](https://github.com/flovilmart)
|
||||
|
||||
#### Bug Fixes
|
||||
* Add logging on failure to create file (#3424), thanks to [Arthur Cinader](https://github.com/acinader)
|
||||
* Log Parse Errors so they are intelligible (#3431), thanks to [Arthur Cinader](https://github.com/acinader)
|
||||
* MongoDB $or Queries avoid SERVER-13732 bug (#3476), thanks to [Jack Wearden](https://github.com/NotBobTheBuilder)
|
||||
* Mongo object to Parse object date serialization - avoid re-serialization of iso of type Date (#3389), thanks to [nodechefMatt](https://github.com/nodechefMatt)
|
||||
|
||||
#### Improvements
|
||||
* Ground preparations for push scalability (#3080), thanks to [Florent Vilmart](https://github.com/flovilmart)
|
||||
* Use uWS as optional dependency for ws server (#3231), thanks to [Florent Vilmart](https://github.com/flovilmart)
|
||||
|
||||
### 2.3.2
|
||||
[Full Changelog](https://github.com/ParsePlatform/parse-server/compare/2.3.1...2.3.2)
|
||||
|
||||
#### New features
|
||||
* Add parseFrameURL for masking user-facing pages (#3267), thanks to [Lenart Rudel](https://github.com/lenart)
|
||||
|
||||
#### Bug fixes
|
||||
* Fix Parse-Server to work with winston-daily-rotate-1.4.2 (#3335), thanks to [Arthur Cinader](https://github.com/acinader)
|
||||
|
||||
#### Improvements
|
||||
* Add support for regex string for password policy validatorPattern setting (#3331), thanks to [Bhaskar Reddy Yasa](https://github.com/bhaskaryasa)
|
||||
* LiveQuery should match subobjects with dot notation (#3322), thanks to [David Starke](https://github.com/dstarke)
|
||||
* Reduce time to process high number of installations for push (#3264), thanks to [jeacott1](https://github.com/jeacott1)
|
||||
* Fix trivial typo in error message (#3238), thanks to [Arthur Cinader](https://github.com/acinader)
|
||||
|
||||
### 2.3.1
|
||||
[Full Changelog](https://github.com/ParsePlatform/parse-server/compare/2.3.0...2.3.1)
|
||||
|
||||
A major issue was introduced when refactoring the authentication modules.
|
||||
This release addresses only that issue.
|
||||
|
||||
### 2.3.0
|
||||
[Full Changelog](https://github.com/ParsePlatform/parse-server/compare/2.2.25...2.3.0)
|
||||
|
||||
#### Breaking changes
|
||||
* Parse.Cloud.useMasterKey() is a no-op, please refer to (Cloud Code migration guide)[https://github.com/ParsePlatform/parse-server/wiki/Compatibility-with-Hosted-Parse#cloud-code]
|
||||
* Authentication helpers are now proper adapters, deprecates oauth option in favor of auth.
|
||||
* DEPRECATES: facebookAppIds, use `auth: { facebook: { appIds: ["AAAAAAAAA" ] } }`
|
||||
* `email` field is not returned anymore for `Parse.User` queries. (Provided only on the user itself if provided).
|
||||
|
||||
#### New Features
|
||||
* Adds ability to restrict access through Class Level Permissions to only authenticated users [see docs](http://parseplatform.github.io/docs/ios/guide/#requires-authentication-permission-requires-parse-server---230)
|
||||
* Adds ability to strip sensitive data from `_User` responses, strips emails by default, thanks to [Arthur Cinader](https://github.com/acinader)
|
||||
* Adds password history support for password policies, thanks to [Bhaskar Reddy Yasa](https://github.com/bhaskaryasa)
|
||||
|
||||
#### Improvements
|
||||
* Bump parse-server-s3-adapter to 1.0.6, thanks to [Arthur Cinader](https://github.com/acinader)
|
||||
* Using PARSE_SERVER_ENABLE_EXPERIMENTAL_DIRECT_ACCESS let you create user sessions when passing {installationId: "xxx-xxx"} on signup in cloud code, thanks to [Florent Vilmart](https://github.com/flovilmart)
|
||||
* Add CLI option to pass `host` parameter when creating parse-server from CLI, thanks to [Kulshekhar Kabra](https://github.com/kulshekhar)
|
||||
|
||||
#### Bug fixes
|
||||
* Ensure batch routes are only using posix paths, thanks to [Steven Shipton](https://github.com/steven-supersolid)
|
||||
* Ensure falsy options from CLI are properly taken into account, thanks to [Steven Shipton](https://github.com/steven-supersolid)
|
||||
* Fixes issues affecting calls to `matchesKeyInQuery` with pointers.
|
||||
* Ensure that `select` keys can be changed in triggers (beforeFind...), thanks to [Arthur Cinader](https://github.com/acinader)
|
||||
|
||||
#### Housekeeping
|
||||
* Enables and enforces linting with eslint, thanks to [Arthur Cinader](https://github.com/acinader)
|
||||
|
||||
### 2.2.25
|
||||
|
||||
Postgres support requires v9.5
|
||||
@@ -36,7 +115,7 @@ Postgres support requires v9.5
|
||||
* Better Postgres support, thanks to [Kulshekhar Kabra](https://github.com/kulshekhar)
|
||||
* Logs the function name when failing (#2963), thanks to [Michael Helvey](https://github.com/michaelhelvey)
|
||||
* CLI: forces closing the connections with SIGINT/SIGTERM (#2964), thanks to [Kulshekhar Kabra](https://github.com/kulshekhar)
|
||||
* Reduce the number of calls to the _SCHEMA table (#2912), thanks to [Steven Shipton](https://github.com/steven-supersolid)
|
||||
* Reduce the number of calls to the `_SCHEMA` table (#2912), thanks to [Steven Shipton](https://github.com/steven-supersolid)
|
||||
* LiveQuery: Support for Role ACL's, thanks to [Aaron Blondeau](https://github.com/aaron-blondeau-dose)
|
||||
|
||||
#### Bug Fixes
|
||||
@@ -83,7 +162,7 @@ Postgres support requires v9.5
|
||||
### 2.2.20
|
||||
|
||||
* New: Adds CloudCode handler for `beforeFind`, thanks to [Florent Vilmart](https://github.com/flovilmart)
|
||||
* New: RedisCacheAdapter for syncing schema, role and user caches across servers, thanks to [Florent Vilmart](https://github.com/flovilmart)
|
||||
* New: RedisCacheAdapter for syncing schema, role and user caches across servers, thanks to [Florent Vilmart](https://github.com/flovilmart)
|
||||
* New: Latest master build available at `ParsePlatform/parse-server#latest`, thanks to [Florent Vilmart](https://github.com/flovilmart)
|
||||
* Fix: Better support for upgradeToRevocableSession with missing session token, thanks to [Florent Vilmart](https://github.com/flovilmart)
|
||||
* Fix: Removes babel-polyfill runtime dependency, thanks to [Florent Vilmart](https://github.com/flovilmart)
|
||||
|
||||
@@ -122,10 +122,9 @@ We have provided a basic [Node.js application](https://github.com/ParsePlatform/
|
||||
* [Microsoft Azure](https://azure.microsoft.com/en-us/blog/azure-welcomes-parse-developers/)
|
||||
* [SashiDo](https://blog.sashido.io/tag/migration/)
|
||||
* [Digital Ocean](https://www.digitalocean.com/community/tutorials/how-to-run-parse-server-on-ubuntu-14-04)
|
||||
* [NodeChef](https://nodechef.com/blog/post/6/migrate-from-parse-to-nodechef%E2%80%99s-managed-parse-server)
|
||||
* [Pivotal Web Services](https://github.com/cf-platform-eng/pws-parse-server)
|
||||
* [Back4app](http://blog.back4app.com/2016/03/01/quick-wizard-migration/)
|
||||
* [HyperDev](https://hyperdev.com/blog/use-parse-server-apps-backend-hyperdev/)
|
||||
* [Gomix](https://gomix.com/#!/project/parse-server)
|
||||
|
||||
### Parse Server + Express
|
||||
|
||||
@@ -157,7 +156,7 @@ For a full list of available options, run `parse-server --help`.
|
||||
|
||||
## Logging
|
||||
|
||||
Parse Server will, by default, will log:
|
||||
Parse Server will, by default, log:
|
||||
* to the console
|
||||
* daily rotating files as new line delimited JSON
|
||||
|
||||
@@ -207,7 +206,7 @@ The client keys used with Parse are no longer necessary with Parse Server. If yo
|
||||
* `fileKey` - For migrated apps, this is necessary to provide access to files already hosted on Parse.
|
||||
* `allowClientClassCreation` - Set to false to disable client class creation. Defaults to true.
|
||||
* `enableAnonymousUsers` - Set to false to disable anonymous users. Defaults to true.
|
||||
* `oauth` - Used to configure support for [3rd party authentication](https://github.com/ParsePlatform/parse-server/wiki/OAuth).
|
||||
* `auth` - Used to configure support for [3rd party authentication](https://github.com/ParsePlatform/parse-server/wiki/OAuth--and-Custom-Authentication).
|
||||
* `facebookAppIds` - An array of valid Facebook application IDs that users may authenticate with.
|
||||
* `mountPath` - Mount path for the server. Defaults to `/parse`.
|
||||
* `filesAdapter` - The default behavior (GridStore) can be changed by creating an adapter class (see [`FilesAdapter.js`](https://github.com/ParsePlatform/parse-server/blob/master/src/Adapters/Files/FilesAdapter.js)).
|
||||
@@ -217,6 +216,7 @@ The client keys used with Parse are no longer necessary with Parse Server. If yo
|
||||
* `revokeSessionOnPasswordReset` - When a user changes their password, either through the reset password email or while logged in, all sessions are revoked if this is true. Set to false if you don't want to revoke sessions.
|
||||
* `accountLockout` - Lock account when a malicious user is attempting to determine an account password by trial and error.
|
||||
* `passwordPolicy` - Optional password policy rules to enforce.
|
||||
* `customPages` - A hash with urls to override email verification links, password reset links and specify frame url for masking user-facing pages. Available keys: `parseFrameURL`, `invalidLink`, `choosePassword`, `passwordResetSuccess`, `verifyEmailSuccess`.
|
||||
|
||||
##### Logging
|
||||
|
||||
@@ -282,12 +282,13 @@ var server = ParseServer({
|
||||
passwordPolicy: {
|
||||
// Two optional settings to enforce strong passwords. Either one or both can be specified.
|
||||
// If both are specified, both checks must pass to accept the password
|
||||
// 1. a RegExp representing the pattern to enforce
|
||||
// 1. a RegExp object or a regex string representing the pattern to enforce
|
||||
validatorPattern: /^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.{8,})/, // enforce password with at least 8 char with at least 1 lower case, 1 upper case and 1 digit
|
||||
// 2. a callback function to be invoked to validate the password
|
||||
validatorCallback: (password) => { return validatePassword(password) },
|
||||
doNotAllowUsername: true, // optional setting to disallow username in passwords
|
||||
maxPasswordAge: 90, // optional setting in days for password expiry. Login fails if user does not reset the password within this period after signup/last reset.
|
||||
maxPasswordHistory: 5, // optional setting to prevent reuse of previous n passwords. Maximum value that can be specified is 20. Not specifying it or specifying 0 will not enforce history.
|
||||
//optional setting to set a validity duration for password reset links (in seconds)
|
||||
resetTokenValidityDuration: 24*60*60, // expire after 24 hours
|
||||
}
|
||||
|
||||
+2
-2
@@ -95,10 +95,10 @@ confirm 'Y' 'Do you want to continue? (Y/n): '
|
||||
check_node
|
||||
check_npm
|
||||
|
||||
printf "Setting up parse-server in %s" "${INSTALL_DIR}\n"
|
||||
printf "Setting up parse-server in %s\n" "${INSTALL_DIR}"
|
||||
|
||||
if [ -d "${INSTALL_DIR}" ]; then
|
||||
echo "{CHECK} ${INSTALL_DIR} exists"
|
||||
echo "${CHECK} ${INSTALL_DIR} exists"
|
||||
else
|
||||
mkdir -p "${INSTALL_DIR}"
|
||||
echo "${CHECK} Created ${INSTALL_DIR}"
|
||||
|
||||
+31
-28
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "parse-server",
|
||||
"version": "2.2.25",
|
||||
"version": "2.3.4",
|
||||
"description": "An express module providing a Parse-compatible API server",
|
||||
"main": "lib/index.js",
|
||||
"repository": {
|
||||
@@ -18,71 +18,74 @@
|
||||
],
|
||||
"license": "BSD-3-Clause",
|
||||
"dependencies": {
|
||||
"bcryptjs": "2.3.0",
|
||||
"body-parser": "1.15.2",
|
||||
"bcryptjs": "2.4.3",
|
||||
"body-parser": "1.16.1",
|
||||
"commander": "2.9.0",
|
||||
"deepcopy": "0.6.3",
|
||||
"express": "4.14.0",
|
||||
"express": "4.14.1",
|
||||
"intersect": "1.0.1",
|
||||
"lodash": "4.17.2",
|
||||
"lodash": "4.17.4",
|
||||
"lru-cache": "4.0.2",
|
||||
"mime": "1.3.4",
|
||||
"mongodb": "2.2.10",
|
||||
"multer": "1.2.0",
|
||||
"mongodb": "2.2.24",
|
||||
"multer": "1.3.0",
|
||||
"parse": "1.9.2",
|
||||
"parse-server-fs-adapter": "1.0.1",
|
||||
"parse-server-push-adapter": "1.1.0",
|
||||
"parse-server-s3-adapter": "1.0.5",
|
||||
"parse-server-push-adapter": "1.2.0",
|
||||
"parse-server-s3-adapter": "1.0.6",
|
||||
"parse-server-simple-mailgun-adapter": "1.0.0",
|
||||
"pg-promise": "5.4.3",
|
||||
"redis": "2.6.3",
|
||||
"pg-promise": "5.5.7",
|
||||
"redis": "2.6.5",
|
||||
"request": "2.79.0",
|
||||
"semver": "5.2.0",
|
||||
"tv4": "1.2.7",
|
||||
"winston": "2.3.0",
|
||||
"winston-daily-rotate-file": "1.3.1",
|
||||
"ws": "1.1.1"
|
||||
"winston": "2.3.1",
|
||||
"winston-daily-rotate-file": "1.4.4",
|
||||
"ws": "2.0.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"babel-cli": "6.18.0",
|
||||
"babel-core": "6.18.2",
|
||||
|
||||
"babel-cli": "6.23.0",
|
||||
"babel-core": "6.23.1",
|
||||
"babel-eslint": "^7.1.1",
|
||||
"babel-plugin-syntax-flow": "6.13.0",
|
||||
"babel-plugin-transform-flow-strip-types": "6.18.0",
|
||||
"babel-preset-es2015": "6.14.0",
|
||||
"babel-preset-stage-0": "6.5.0",
|
||||
"babel-register": "6.18.0",
|
||||
"babel-plugin-transform-flow-strip-types": "6.22.0",
|
||||
"babel-preset-es2015": "6.22.0",
|
||||
"babel-preset-stage-0": "6.22.0",
|
||||
"babel-register": "6.23.0",
|
||||
"bcrypt-nodejs": "0.0.3",
|
||||
"cross-env": "3.1.3",
|
||||
"cross-env": "3.1.4",
|
||||
"deep-diff": "0.3.4",
|
||||
"eslint": "^3.10.2",
|
||||
"eslint-plugin-flowtype": "^2.25.0",
|
||||
"gaze": "1.1.1",
|
||||
"istanbul": "1.0.0-alpha.1",
|
||||
"jasmine": "2.5.2",
|
||||
"jasmine-spec-reporter": "^2.7.0",
|
||||
"jasmine": "2.5.3",
|
||||
"jasmine-spec-reporter": "^3.1.0",
|
||||
"mongodb-runner": "3.4.0",
|
||||
"nodemon": "1.11.0",
|
||||
"request-promise": "4.1.1"
|
||||
},
|
||||
"scripts": {
|
||||
"dev": "npm run build && node bin/dev",
|
||||
"lint": "eslint ./",
|
||||
"lint": "eslint --cache ./",
|
||||
"build": "babel src/ -d lib/",
|
||||
"pretest": "npm run lint",
|
||||
"test": "cross-env MONGODB_VERSION=${MONGODB_VERSION:=3.2.6} MONGODB_STORAGE_ENGINE=mmapv1 NODE_ENV=test TESTING=1 $COVERAGE_OPTION jasmine",
|
||||
"test:win": "npm run pretest && cross-env NODE_ENV=test TESTING=1 node ./node_modules/jasmine/bin/jasmine.js && npm run posttest",
|
||||
"test:win": "cross-env MONGODB_VERSION=${MONGODB_VERSION:=3.2.6} MONGODB_STORAGE_ENGINE=mmapv1 NODE_ENV=test TESTING=1 jasmine",
|
||||
"coverage": "cross-env COVERAGE_OPTION='./node_modules/.bin/istanbul cover' npm test",
|
||||
"coverage:win": "npm run pretest && cross-env NODE_ENV=test TESTING=1 node ./node_modules/babel-istanbul/lib/cli.js cover ./node_modules/jasmine/bin/jasmine.js && npm run posttest",
|
||||
"coverage:win": "cross-env MONGODB_VERSION=${MONGODB_VERSION:=3.2.6} MONGODB_STORAGE_ENGINE=mmapv1 NODE_ENV=test TESTING=1 node ./node_modules/istanbul/lib/cli.js cover ./node_modules/jasmine/bin/jasmine.js",
|
||||
"start": "node ./bin/parse-server",
|
||||
"prepublish": "npm run build"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4.5"
|
||||
"node": ">=4.6"
|
||||
},
|
||||
"bin": {
|
||||
"parse-server": "./bin/parse-server"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"bcrypt": "0.8.7"
|
||||
"bcrypt": "1.0.2",
|
||||
"uws": "^0.12.0"
|
||||
}
|
||||
}
|
||||
|
||||
Regular → Executable
+2
-6
@@ -1,8 +1,5 @@
|
||||
{
|
||||
"extends": "eslint:recommended",
|
||||
"env": {
|
||||
"node": true,
|
||||
"es6": true,
|
||||
"jasmine": true
|
||||
},
|
||||
"globals": {
|
||||
@@ -29,7 +26,6 @@
|
||||
"arrayContains": true
|
||||
},
|
||||
"rules": {
|
||||
"no-console": [0],
|
||||
"indent": ["error", 2]
|
||||
"no-console": [0]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -263,7 +263,7 @@ describe("Account Lockout Policy: ", () => {
|
||||
return isAccountLockoutError('username3', 'wrong password', 0.05, 1);
|
||||
})
|
||||
.then(() => {
|
||||
// account should still be locked even after 2 seconds.
|
||||
// account should still be locked even after 2 seconds.
|
||||
return isAccountLockoutError('username3', 'wrong password', 0.05, 2000);
|
||||
})
|
||||
.then(() => {
|
||||
@@ -297,7 +297,7 @@ describe("Account Lockout Policy: ", () => {
|
||||
return loginWithWrongCredentialsShouldFail('username4', 'wrong password');
|
||||
})
|
||||
.then(() => {
|
||||
// allow locked user to login after 3 seconds with a valid userid and password
|
||||
// allow locked user to login after 3 seconds with a valid userid and password
|
||||
return new Promise((resolve, reject) => {
|
||||
setTimeout(() => {
|
||||
Parse.User.logIn('username4', 'correct password')
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
const analyticsAdapter = {
|
||||
appOpened: function() {},
|
||||
appOpened: function() {},
|
||||
trackEvent: function() {}
|
||||
}
|
||||
|
||||
describe('AnalyticsController', () => {
|
||||
it('should track a simple event', (done) => {
|
||||
|
||||
|
||||
spyOn(analyticsAdapter, 'trackEvent').and.callThrough();
|
||||
reconfigureServer({
|
||||
analyticsAdapter
|
||||
@@ -17,7 +17,7 @@ describe('AnalyticsController', () => {
|
||||
}).then(() => {
|
||||
expect(analyticsAdapter.trackEvent).toHaveBeenCalled();
|
||||
var lastCall = analyticsAdapter.trackEvent.calls.first();
|
||||
let args = lastCall.args;
|
||||
const args = lastCall.args;
|
||||
expect(args[0]).toEqual('MyEvent');
|
||||
expect(args[1]).toEqual({
|
||||
dimensions: {
|
||||
@@ -31,9 +31,9 @@ describe('AnalyticsController', () => {
|
||||
done();
|
||||
})
|
||||
});
|
||||
|
||||
|
||||
it('should track a app opened event', (done) => {
|
||||
|
||||
|
||||
spyOn(analyticsAdapter, 'appOpened').and.callThrough();
|
||||
reconfigureServer({
|
||||
analyticsAdapter
|
||||
@@ -45,7 +45,7 @@ describe('AnalyticsController', () => {
|
||||
}).then(() => {
|
||||
expect(analyticsAdapter.appOpened).toHaveBeenCalled();
|
||||
var lastCall = analyticsAdapter.appOpened.calls.first();
|
||||
let args = lastCall.args;
|
||||
const args = lastCall.args;
|
||||
expect(args[0]).toEqual({
|
||||
dimensions: {
|
||||
key: 'value',
|
||||
@@ -58,4 +58,4 @@ describe('AnalyticsController', () => {
|
||||
done();
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1,145 +1,13 @@
|
||||
var OAuth = require("../src/authDataManager/OAuth1Client");
|
||||
var request = require('request');
|
||||
var Config = require("../src/Config");
|
||||
var defaultColumns = require('../src/Controllers/SchemaController').defaultColumns;
|
||||
var authenticationLoader = require('../src/Adapters/Auth');
|
||||
var path = require('path');
|
||||
|
||||
describe('OAuth', function() {
|
||||
it("Nonce should have right length", (done) => {
|
||||
jequal(OAuth.nonce().length, 30);
|
||||
done();
|
||||
});
|
||||
|
||||
it("Should properly build parameter string", (done) => {
|
||||
var string = OAuth.buildParameterString({c:1, a:2, b:3})
|
||||
jequal(string, "a=2&b=3&c=1");
|
||||
done();
|
||||
});
|
||||
|
||||
it("Should properly build empty parameter string", (done) => {
|
||||
var string = OAuth.buildParameterString()
|
||||
jequal(string, "");
|
||||
done();
|
||||
});
|
||||
|
||||
it("Should properly build signature string", (done) => {
|
||||
var string = OAuth.buildSignatureString("get", "http://dummy.com", "");
|
||||
jequal(string, "GET&http%3A%2F%2Fdummy.com&");
|
||||
done();
|
||||
});
|
||||
|
||||
it("Should properly generate request signature", (done) => {
|
||||
var request = {
|
||||
host: "dummy.com",
|
||||
path: "path"
|
||||
};
|
||||
|
||||
var oauth_params = {
|
||||
oauth_timestamp: 123450000,
|
||||
oauth_nonce: "AAAAAAAAAAAAAAAAA",
|
||||
oauth_consumer_key: "hello",
|
||||
oauth_token: "token"
|
||||
};
|
||||
|
||||
var consumer_secret = "world";
|
||||
var auth_token_secret = "secret";
|
||||
request = OAuth.signRequest(request, oauth_params, consumer_secret, auth_token_secret);
|
||||
jequal(request.headers['Authorization'], 'OAuth oauth_consumer_key="hello", oauth_nonce="AAAAAAAAAAAAAAAAA", oauth_signature="8K95bpQcDi9Nd2GkhumTVcw4%2BXw%3D", oauth_signature_method="HMAC-SHA1", oauth_timestamp="123450000", oauth_token="token", oauth_version="1.0"');
|
||||
done();
|
||||
});
|
||||
|
||||
it("Should properly build request", (done) => {
|
||||
var options = {
|
||||
host: "dummy.com",
|
||||
consumer_key: "hello",
|
||||
consumer_secret: "world",
|
||||
auth_token: "token",
|
||||
auth_token_secret: "secret",
|
||||
// Custom oauth params for tests
|
||||
oauth_params: {
|
||||
oauth_timestamp: 123450000,
|
||||
oauth_nonce: "AAAAAAAAAAAAAAAAA"
|
||||
}
|
||||
};
|
||||
var path = "path";
|
||||
var method = "get";
|
||||
|
||||
var oauthClient = new OAuth(options);
|
||||
var req = oauthClient.buildRequest(method, path, {"query": "param"});
|
||||
|
||||
jequal(req.host, options.host);
|
||||
jequal(req.path, "/"+path+"?query=param");
|
||||
jequal(req.method, "GET");
|
||||
jequal(req.headers['Content-Type'], 'application/x-www-form-urlencoded');
|
||||
jequal(req.headers['Authorization'], 'OAuth oauth_consumer_key="hello", oauth_nonce="AAAAAAAAAAAAAAAAA", oauth_signature="wNkyEkDE%2F0JZ2idmqyrgHdvC0rs%3D", oauth_signature_method="HMAC-SHA1", oauth_timestamp="123450000", oauth_token="token", oauth_version="1.0"')
|
||||
done();
|
||||
});
|
||||
|
||||
|
||||
function validateCannotAuthenticateError(data, done) {
|
||||
jequal(typeof data, "object");
|
||||
jequal(typeof data.errors, "object");
|
||||
var errors = data.errors;
|
||||
jequal(typeof errors[0], "object");
|
||||
// Cannot authenticate error
|
||||
jequal(errors[0].code, 32);
|
||||
done();
|
||||
}
|
||||
|
||||
it("Should fail a GET request", (done) => {
|
||||
var options = {
|
||||
host: "api.twitter.com",
|
||||
consumer_key: "XXXXXXXXXXXXXXXXXXXXXXXXX",
|
||||
consumer_secret: "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
|
||||
};
|
||||
var path = "/1.1/help/configuration.json";
|
||||
var params = {"lang": "en"};
|
||||
var oauthClient = new OAuth(options);
|
||||
oauthClient.get(path, params).then(function(data){
|
||||
validateCannotAuthenticateError(data, done);
|
||||
})
|
||||
});
|
||||
|
||||
it("Should fail a POST request", (done) => {
|
||||
var options = {
|
||||
host: "api.twitter.com",
|
||||
consumer_key: "XXXXXXXXXXXXXXXXXXXXXXXXX",
|
||||
consumer_secret: "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
|
||||
};
|
||||
var body = {
|
||||
lang: "en"
|
||||
};
|
||||
var path = "/1.1/account/settings.json";
|
||||
|
||||
var oauthClient = new OAuth(options);
|
||||
oauthClient.post(path, null, body).then(function(data){
|
||||
validateCannotAuthenticateError(data, done);
|
||||
})
|
||||
});
|
||||
|
||||
it("Should fail a request", (done) => {
|
||||
var options = {
|
||||
host: "localhost",
|
||||
consumer_key: "XXXXXXXXXXXXXXXXXXXXXXXXX",
|
||||
consumer_secret: "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
|
||||
};
|
||||
var body = {
|
||||
lang: "en"
|
||||
};
|
||||
var path = "/";
|
||||
|
||||
var oauthClient = new OAuth(options);
|
||||
oauthClient.post(path, null, body).then(function(){
|
||||
jequal(false, true);
|
||||
done();
|
||||
}).catch(function(){
|
||||
jequal(true, true);
|
||||
done();
|
||||
})
|
||||
});
|
||||
|
||||
describe('AuthenticationProviers', function() {
|
||||
["facebook", "github", "instagram", "google", "linkedin", "meetup", "twitter", "janrainengage", "janraincapture", "vkontakte"].map(function(providerName){
|
||||
it("Should validate structure of "+providerName, (done) => {
|
||||
var provider = require("../src/authDataManager/"+providerName);
|
||||
it("Should validate structure of " + providerName, (done) => {
|
||||
var provider = require("../src/Adapters/Auth/" + providerName);
|
||||
jequal(typeof provider.validateAuthData, "function");
|
||||
jequal(typeof provider.validateAppId, "function");
|
||||
jequal(provider.validateAuthData({}, {}).constructor, Promise.prototype.constructor);
|
||||
@@ -325,5 +193,123 @@ describe('OAuth', function() {
|
||||
});
|
||||
});
|
||||
|
||||
function validateValidator(validator) {
|
||||
expect(typeof validator).toBe('function');
|
||||
}
|
||||
|
||||
})
|
||||
function validateAuthenticationHandler(authenticatonHandler) {
|
||||
expect(authenticatonHandler).not.toBeUndefined();
|
||||
expect(typeof authenticatonHandler.getValidatorForProvider).toBe('function');
|
||||
expect(typeof authenticatonHandler.getValidatorForProvider).toBe('function');
|
||||
}
|
||||
|
||||
function validateAuthenticationAdapter(authAdapter) {
|
||||
expect(authAdapter).not.toBeUndefined();
|
||||
if (!authAdapter) { return; }
|
||||
expect(typeof authAdapter.validateAuthData).toBe('function');
|
||||
expect(typeof authAdapter.validateAppId).toBe('function');
|
||||
}
|
||||
|
||||
it('properly loads custom adapter', (done) => {
|
||||
var validAuthData = {
|
||||
id: 'hello',
|
||||
token: 'world'
|
||||
}
|
||||
const adapter = {
|
||||
validateAppId: function() {
|
||||
return Promise.resolve();
|
||||
},
|
||||
validateAuthData: function(authData) {
|
||||
if (authData.id == validAuthData.id && authData.token == validAuthData.token) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
return Promise.reject();
|
||||
}
|
||||
};
|
||||
|
||||
const authDataSpy = spyOn(adapter, 'validateAuthData').and.callThrough();
|
||||
const appIdSpy = spyOn(adapter, 'validateAppId').and.callThrough();
|
||||
|
||||
const authenticationHandler = authenticationLoader({
|
||||
customAuthentication: adapter
|
||||
});
|
||||
|
||||
validateAuthenticationHandler(authenticationHandler);
|
||||
const validator = authenticationHandler.getValidatorForProvider('customAuthentication');
|
||||
validateValidator(validator);
|
||||
|
||||
validator(validAuthData).then(() => {
|
||||
expect(authDataSpy).toHaveBeenCalled();
|
||||
// AppIds are not provided in the adapter, should not be called
|
||||
expect(appIdSpy).not.toHaveBeenCalled();
|
||||
done();
|
||||
}, (err) => {
|
||||
jfail(err);
|
||||
done();
|
||||
})
|
||||
});
|
||||
|
||||
it('properly loads custom adapter module object', (done) => {
|
||||
const authenticationHandler = authenticationLoader({
|
||||
customAuthentication: path.resolve('./spec/support/CustomAuth.js')
|
||||
});
|
||||
|
||||
validateAuthenticationHandler(authenticationHandler);
|
||||
const validator = authenticationHandler.getValidatorForProvider('customAuthentication');
|
||||
validateValidator(validator);
|
||||
|
||||
validator({
|
||||
token: 'my-token'
|
||||
}).then(() => {
|
||||
done();
|
||||
}, (err) => {
|
||||
jfail(err);
|
||||
done();
|
||||
})
|
||||
});
|
||||
|
||||
it('properly loads custom adapter module object', (done) => {
|
||||
const authenticationHandler = authenticationLoader({
|
||||
customAuthentication: { module: path.resolve('./spec/support/CustomAuthFunction.js'), options: { token: 'valid-token' }}
|
||||
});
|
||||
|
||||
validateAuthenticationHandler(authenticationHandler);
|
||||
const validator = authenticationHandler.getValidatorForProvider('customAuthentication');
|
||||
validateValidator(validator);
|
||||
|
||||
validator({
|
||||
token: 'valid-token'
|
||||
}).then(() => {
|
||||
done();
|
||||
}, (err) => {
|
||||
jfail(err);
|
||||
done();
|
||||
})
|
||||
});
|
||||
|
||||
it('properly loads a default adapter with options', () => {
|
||||
const options = {
|
||||
facebook: {
|
||||
appIds: ['a', 'b']
|
||||
}
|
||||
};
|
||||
const { adapter, appIds, providerOptions } = authenticationLoader.loadAuthAdapter('facebook', options);
|
||||
validateAuthenticationAdapter(adapter);
|
||||
expect(appIds).toEqual(['a', 'b']);
|
||||
expect(providerOptions).toEqual(options.facebook);
|
||||
});
|
||||
|
||||
it('properly loads a custom adapter with options', () => {
|
||||
const options = {
|
||||
custom: {
|
||||
validateAppId: () => {},
|
||||
validateAuthData: () => {},
|
||||
appIds: ['a', 'b']
|
||||
}
|
||||
};
|
||||
const { adapter, appIds, providerOptions } = authenticationLoader.loadAuthAdapter('custom', options);
|
||||
validateAuthenticationAdapter(adapter);
|
||||
expect(appIds).toEqual(['a', 'b']);
|
||||
expect(providerOptions).toEqual(options.custom);
|
||||
});
|
||||
});
|
||||
+9
-8
@@ -63,15 +63,16 @@ describe('commander additions', () => {
|
||||
|
||||
it('should load properly use args over env', (done) => {
|
||||
commander.loadDefinitions(testDefinitions);
|
||||
commander.parse(['node','./CLI.spec.js','--arg0', 'arg0Value', '--arg4', 'anotherArg4'], {
|
||||
commander.parse(['node','./CLI.spec.js','--arg0', 'arg0Value', '--arg4', ''], {
|
||||
'PROGRAM_ARG_0': 'arg0ENVValue',
|
||||
'PROGRAM_ARG_1': 'arg1ENVValue',
|
||||
'PROGRAM_ARG_2': '4',
|
||||
'PROGRAM_ARG_4': 'arg4ENVValue'
|
||||
});
|
||||
expect(commander.arg0).toEqual('arg0Value');
|
||||
expect(commander.arg1).toEqual('arg1ENVValue');
|
||||
expect(commander.arg2).toEqual(4);
|
||||
expect(commander.arg4).toEqual('anotherArg4');
|
||||
expect(commander.arg4).toEqual('');
|
||||
done();
|
||||
});
|
||||
|
||||
@@ -93,7 +94,7 @@ describe('commander additions', () => {
|
||||
'PROGRAM_ARG_0': 'arg0ENVValue',
|
||||
'PROGRAM_ARG_1': 'arg1ENVValue',
|
||||
});
|
||||
let options = commander.getOptions();
|
||||
const options = commander.getOptions();
|
||||
expect(options.arg2).toBe(8888);
|
||||
expect(options.arg3).toBe('hello'); //config value
|
||||
expect(options.arg4).toBe('/1');
|
||||
@@ -122,7 +123,7 @@ describe('commander additions', () => {
|
||||
it('should load config from apps', (done) => {
|
||||
commander.loadDefinitions(testDefinitions);
|
||||
commander.parse(['node', './CLI.spec.js', './spec/configs/CLIConfigApps.json']);
|
||||
let options = commander.getOptions();
|
||||
const options = commander.getOptions();
|
||||
expect(options.arg1).toBe('my_app');
|
||||
expect(options.arg2).toBe(8888);
|
||||
expect(options.arg3).toBe('hello'); //config value
|
||||
@@ -141,8 +142,8 @@ describe('commander additions', () => {
|
||||
|
||||
describe('definitions', () => {
|
||||
it('should have valid types', () => {
|
||||
for (let key in definitions) {
|
||||
let definition = definitions[key];
|
||||
for (const key in definitions) {
|
||||
const definition = definitions[key];
|
||||
expect(typeof definition).toBe('object');
|
||||
if (typeof definition.env !== 'undefined') {
|
||||
expect(typeof definition.env).toBe('string');
|
||||
@@ -160,8 +161,8 @@ describe('definitions', () => {
|
||||
|
||||
describe('LiveQuery definitions', () => {
|
||||
it('should have valid types', () => {
|
||||
for (let key in liveQueryDefinitions) {
|
||||
let definition = liveQueryDefinitions[key];
|
||||
for (const key in liveQueryDefinitions) {
|
||||
const definition = liveQueryDefinitions[key];
|
||||
expect(typeof definition).toBe('object');
|
||||
if (typeof definition.env !== 'undefined') {
|
||||
expect(typeof definition.env).toBe('string');
|
||||
|
||||
@@ -2,7 +2,7 @@ var ClientSDK = require('../src/ClientSDK');
|
||||
|
||||
describe('ClientSDK', () => {
|
||||
it('should properly parse the SDK versions', () => {
|
||||
let clientSDKFromVersion = ClientSDK.fromString;
|
||||
const clientSDKFromVersion = ClientSDK.fromString;
|
||||
expect(clientSDKFromVersion('i1.1.1')).toEqual({
|
||||
sdk: 'i',
|
||||
version: '1.1.1'
|
||||
@@ -20,12 +20,12 @@ describe('ClientSDK', () => {
|
||||
version: '1.9.0'
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
it('should properly sastisfy', () => {
|
||||
expect(ClientSDK.compatible({
|
||||
js: '>=1.9.0'
|
||||
})("js1.9.0")).toBe(true);
|
||||
|
||||
|
||||
expect(ClientSDK.compatible({
|
||||
js: '>=1.9.0'
|
||||
})("js2.0.0")).toBe(true);
|
||||
@@ -38,4 +38,4 @@ describe('ClientSDK', () => {
|
||||
js: '>=1.9.0'
|
||||
})(undefined)).toBe(true);
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
+102
-67
@@ -180,10 +180,10 @@ describe('Cloud Code', () => {
|
||||
|
||||
it('test afterSave ran on created object and returned a promise', function(done) {
|
||||
Parse.Cloud.afterSave('AfterSaveTest2', function(req) {
|
||||
let obj = req.object;
|
||||
const obj = req.object;
|
||||
if(!obj.existed())
|
||||
{
|
||||
let promise = new Parse.Promise();
|
||||
const promise = new Parse.Promise();
|
||||
setTimeout(function(){
|
||||
obj.set('proof', obj.id);
|
||||
obj.save().then(function(){
|
||||
@@ -195,13 +195,13 @@ describe('Cloud Code', () => {
|
||||
}
|
||||
});
|
||||
|
||||
let obj = new Parse.Object('AfterSaveTest2');
|
||||
const obj = new Parse.Object('AfterSaveTest2');
|
||||
obj.save().then(function(){
|
||||
let query = new Parse.Query('AfterSaveTest2');
|
||||
const query = new Parse.Query('AfterSaveTest2');
|
||||
query.equalTo('proof', obj.id);
|
||||
query.find().then(function(results) {
|
||||
expect(results.length).toEqual(1);
|
||||
let savedObject = results[0];
|
||||
const savedObject = results[0];
|
||||
expect(savedObject.get('proof')).toEqual(obj.id);
|
||||
done();
|
||||
},
|
||||
@@ -215,10 +215,10 @@ describe('Cloud Code', () => {
|
||||
// TODO: Fails on CI randomly as racing
|
||||
xit('test afterSave ignoring promise, object not found', function(done) {
|
||||
Parse.Cloud.afterSave('AfterSaveTest2', function(req) {
|
||||
let obj = req.object;
|
||||
const obj = req.object;
|
||||
if(!obj.existed())
|
||||
{
|
||||
let promise = new Parse.Promise();
|
||||
const promise = new Parse.Promise();
|
||||
setTimeout(function(){
|
||||
obj.set('proof', obj.id);
|
||||
obj.save().then(function(){
|
||||
@@ -230,12 +230,12 @@ describe('Cloud Code', () => {
|
||||
}
|
||||
});
|
||||
|
||||
let obj = new Parse.Object('AfterSaveTest2');
|
||||
const obj = new Parse.Object('AfterSaveTest2');
|
||||
obj.save().then(function(){
|
||||
done();
|
||||
})
|
||||
|
||||
let query = new Parse.Query('AfterSaveTest2');
|
||||
const query = new Parse.Query('AfterSaveTest2');
|
||||
query.equalTo('proof', obj.id);
|
||||
query.find().then(function(results) {
|
||||
expect(results.length).toEqual(0);
|
||||
@@ -247,7 +247,7 @@ describe('Cloud Code', () => {
|
||||
|
||||
it('test afterSave rejecting promise', function(done) {
|
||||
Parse.Cloud.afterSave('AfterSaveTest2', function() {
|
||||
let promise = new Parse.Promise();
|
||||
const promise = new Parse.Promise();
|
||||
setTimeout(function(){
|
||||
promise.reject("THIS SHOULD BE IGNORED");
|
||||
}, 1000);
|
||||
@@ -255,7 +255,7 @@ describe('Cloud Code', () => {
|
||||
return promise;
|
||||
});
|
||||
|
||||
let obj = new Parse.Object('AfterSaveTest2');
|
||||
const obj = new Parse.Object('AfterSaveTest2');
|
||||
obj.save().then(function(){
|
||||
done();
|
||||
}, function(error){
|
||||
@@ -266,10 +266,10 @@ describe('Cloud Code', () => {
|
||||
|
||||
it('test afterDelete returning promise, object is deleted when destroy resolves', function(done) {
|
||||
Parse.Cloud.afterDelete('AfterDeleteTest2', function(req) {
|
||||
let promise = new Parse.Promise();
|
||||
const promise = new Parse.Promise();
|
||||
|
||||
setTimeout(function(){
|
||||
let obj = new Parse.Object('AfterDeleteTestProof');
|
||||
const obj = new Parse.Object('AfterDeleteTestProof');
|
||||
obj.set('proof', req.object.id);
|
||||
obj.save().then(function(){
|
||||
promise.resolve();
|
||||
@@ -280,19 +280,19 @@ describe('Cloud Code', () => {
|
||||
return promise;
|
||||
});
|
||||
|
||||
let errorHandler = function(error) {
|
||||
const errorHandler = function(error) {
|
||||
fail(error);
|
||||
done();
|
||||
}
|
||||
|
||||
let obj = new Parse.Object('AfterDeleteTest2');
|
||||
const obj = new Parse.Object('AfterDeleteTest2');
|
||||
obj.save().then(function(){
|
||||
obj.destroy().then(function(){
|
||||
let query = new Parse.Query('AfterDeleteTestProof');
|
||||
const query = new Parse.Query('AfterDeleteTestProof');
|
||||
query.equalTo('proof', obj.id);
|
||||
query.find().then(function(results) {
|
||||
expect(results.length).toEqual(1);
|
||||
let deletedObject = results[0];
|
||||
const deletedObject = results[0];
|
||||
expect(deletedObject.get('proof')).toEqual(obj.id);
|
||||
done();
|
||||
}, errorHandler);
|
||||
@@ -302,10 +302,10 @@ describe('Cloud Code', () => {
|
||||
|
||||
it('test afterDelete ignoring promise, object is not yet deleted', function(done) {
|
||||
Parse.Cloud.afterDelete('AfterDeleteTest2', function(req) {
|
||||
let promise = new Parse.Promise();
|
||||
const promise = new Parse.Promise();
|
||||
|
||||
setTimeout(function(){
|
||||
let obj = new Parse.Object('AfterDeleteTestProof');
|
||||
const obj = new Parse.Object('AfterDeleteTestProof');
|
||||
obj.set('proof', req.object.id);
|
||||
obj.save().then(function(){
|
||||
promise.resolve();
|
||||
@@ -316,18 +316,18 @@ describe('Cloud Code', () => {
|
||||
return promise;
|
||||
});
|
||||
|
||||
let errorHandler = function(error) {
|
||||
const errorHandler = function(error) {
|
||||
fail(error);
|
||||
done();
|
||||
}
|
||||
|
||||
let obj = new Parse.Object('AfterDeleteTest2');
|
||||
const obj = new Parse.Object('AfterDeleteTest2');
|
||||
obj.save().then(function(){
|
||||
obj.destroy().then(function(){
|
||||
done();
|
||||
})
|
||||
|
||||
let query = new Parse.Query('AfterDeleteTestProof');
|
||||
const query = new Parse.Query('AfterDeleteTestProof');
|
||||
query.equalTo('proof', obj.id);
|
||||
query.find().then(function(results) {
|
||||
expect(results.length).toEqual(0);
|
||||
@@ -509,7 +509,7 @@ describe('Cloud Code', () => {
|
||||
return res.success({});
|
||||
});
|
||||
|
||||
let params = {
|
||||
const params = {
|
||||
'date': {
|
||||
'__type': 'Date',
|
||||
'iso': '2016-05-22T09:00:00.000Z'
|
||||
@@ -616,7 +616,7 @@ describe('Cloud Code', () => {
|
||||
res.success();
|
||||
});
|
||||
|
||||
let obj = new Parse.Object('GameScore');
|
||||
const obj = new Parse.Object('GameScore');
|
||||
obj.set('foo', 'bar');
|
||||
obj.set('fooAgain', 'barAgain');
|
||||
obj.save().then(() => {
|
||||
@@ -703,7 +703,7 @@ describe('Cloud Code', () => {
|
||||
request.object.set('foo', 'baz');
|
||||
response.success();
|
||||
});
|
||||
let obj = new Parse.Object('ChangingObject');
|
||||
const obj = new Parse.Object('ChangingObject');
|
||||
obj.save({ foo: 'bar' }).then((objAgain) => {
|
||||
expect(objAgain.get('foo')).toEqual('baz');
|
||||
done();
|
||||
@@ -712,7 +712,7 @@ describe('Cloud Code', () => {
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
it('beforeSave change propagates through the afterSave #1931', (done) => {
|
||||
Parse.Cloud.beforeSave('ChangingObject', function(request, response) {
|
||||
request.object.unset('file');
|
||||
@@ -726,9 +726,9 @@ describe('Cloud Code', () => {
|
||||
expect(request.object.get('file')).toBeUndefined();
|
||||
return Promise.resolve();
|
||||
});
|
||||
let file = new Parse.File("yolo.txt", [1,2,3], "text/plain");
|
||||
const file = new Parse.File("yolo.txt", [1,2,3], "text/plain");
|
||||
file.save().then(() => {
|
||||
let obj = new Parse.Object('ChangingObject');
|
||||
const obj = new Parse.Object('ChangingObject');
|
||||
return obj.save({ file, date: new Date() })
|
||||
}).then(() => {
|
||||
done();
|
||||
@@ -995,7 +995,7 @@ describe('Cloud Code', () => {
|
||||
});
|
||||
|
||||
let object;
|
||||
let testObject = new TestObject({key: 'value'});
|
||||
const testObject = new TestObject({key: 'value'});
|
||||
testObject.save().then(() => {
|
||||
object = new BeforeSaveObject();
|
||||
return object.save().then(() => {
|
||||
@@ -1026,7 +1026,7 @@ describe('Cloud Code', () => {
|
||||
}, res.error);
|
||||
});
|
||||
|
||||
let object = new BeforeSaveObject();
|
||||
const object = new BeforeSaveObject();
|
||||
object.save().then((objectAgain) => {
|
||||
// Originally it would throw as it would be a non-relation
|
||||
expect(() => { objectAgain.relation('testsRelation') }).not.toThrow();
|
||||
@@ -1044,7 +1044,7 @@ describe('Cloud Code', () => {
|
||||
res.success();
|
||||
});
|
||||
}).not.toThrow();
|
||||
|
||||
|
||||
rp.post({
|
||||
url: 'http://localhost:8378/1/jobs/myJob',
|
||||
headers: {
|
||||
@@ -1065,7 +1065,7 @@ describe('Cloud Code', () => {
|
||||
res.success();
|
||||
});
|
||||
}).not.toThrow();
|
||||
|
||||
|
||||
rp.post({
|
||||
url: 'http://localhost:8378/1/jobs/myJob',
|
||||
headers: {
|
||||
@@ -1094,7 +1094,7 @@ describe('Cloud Code', () => {
|
||||
done();
|
||||
});
|
||||
}).not.toThrow();
|
||||
|
||||
|
||||
rp.post({
|
||||
url: 'http://localhost:8378/1/jobs/myJob',
|
||||
headers: {
|
||||
@@ -1121,7 +1121,7 @@ describe('Cloud Code', () => {
|
||||
done();
|
||||
});
|
||||
}).not.toThrow();
|
||||
|
||||
|
||||
rp.post({
|
||||
url: `http://${Parse.applicationId}:${Parse.masterKey}@localhost:8378/1/jobs/myJob`,
|
||||
}).then(() => {
|
||||
@@ -1152,7 +1152,7 @@ describe('Cloud Code', () => {
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
rp.post({
|
||||
url: 'http://localhost:8378/1/jobs/myJob',
|
||||
headers: {
|
||||
@@ -1179,7 +1179,7 @@ describe('Cloud Code', () => {
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
rp.post({
|
||||
url: 'http://localhost:8378/1/jobs/myJob',
|
||||
headers: {
|
||||
@@ -1194,7 +1194,7 @@ describe('Cloud Code', () => {
|
||||
});
|
||||
|
||||
function getJobStatus(jobId) {
|
||||
let q = new Parse.Query('_JobStatus');
|
||||
const q = new Parse.Query('_JobStatus');
|
||||
return q.get(jobId, {useMasterKey: true});
|
||||
}
|
||||
});
|
||||
@@ -1203,9 +1203,9 @@ describe('Cloud Code', () => {
|
||||
describe('beforeFind hooks', () => {
|
||||
it('should add beforeFind trigger', (done) => {
|
||||
Parse.Cloud.beforeFind('MyObject', (req) => {
|
||||
let q = req.query;
|
||||
const q = req.query;
|
||||
expect(q instanceof Parse.Query).toBe(true);
|
||||
let jsonQuery = q.toJSON();
|
||||
const jsonQuery = q.toJSON();
|
||||
expect(jsonQuery.where.key).toEqual('value');
|
||||
expect(jsonQuery.where.some).toEqual({'$gt': 10});
|
||||
expect(jsonQuery.include).toEqual('otherKey,otherValue');
|
||||
@@ -1213,7 +1213,7 @@ describe('beforeFind hooks', () => {
|
||||
expect(jsonQuery.skip).toBe(undefined);
|
||||
});
|
||||
|
||||
let query = new Parse.Query('MyObject');
|
||||
const query = new Parse.Query('MyObject');
|
||||
query.equalTo('key', 'value');
|
||||
query.greaterThan('some', 10);
|
||||
query.include('otherKey');
|
||||
@@ -1225,21 +1225,21 @@ describe('beforeFind hooks', () => {
|
||||
|
||||
it('should use modify', (done) => {
|
||||
Parse.Cloud.beforeFind('MyObject', (req) => {
|
||||
let q = req.query;
|
||||
const q = req.query;
|
||||
q.equalTo('forced', true);
|
||||
});
|
||||
|
||||
let obj0 = new Parse.Object('MyObject');
|
||||
const obj0 = new Parse.Object('MyObject');
|
||||
obj0.set('forced', false);
|
||||
|
||||
let obj1 = new Parse.Object('MyObject');
|
||||
const obj1 = new Parse.Object('MyObject');
|
||||
obj1.set('forced', true);
|
||||
Parse.Object.saveAll([obj0, obj1]).then(() => {
|
||||
let query = new Parse.Query('MyObject');
|
||||
const query = new Parse.Query('MyObject');
|
||||
query.equalTo('forced', false);
|
||||
query.find().then((results) => {
|
||||
expect(results.length).toBe(1);
|
||||
let firstResult = results[0];
|
||||
const firstResult = results[0];
|
||||
expect(firstResult.get('forced')).toBe(true);
|
||||
done();
|
||||
});
|
||||
@@ -1248,19 +1248,19 @@ describe('beforeFind hooks', () => {
|
||||
|
||||
it('should use the modified the query', (done) => {
|
||||
Parse.Cloud.beforeFind('MyObject', (req) => {
|
||||
let q = req.query;
|
||||
let otherQuery = new Parse.Query('MyObject');
|
||||
const q = req.query;
|
||||
const otherQuery = new Parse.Query('MyObject');
|
||||
otherQuery.equalTo('forced', true);
|
||||
return Parse.Query.or(q, otherQuery);
|
||||
});
|
||||
|
||||
let obj0 = new Parse.Object('MyObject');
|
||||
const obj0 = new Parse.Object('MyObject');
|
||||
obj0.set('forced', false);
|
||||
|
||||
let obj1 = new Parse.Object('MyObject');
|
||||
const obj1 = new Parse.Object('MyObject');
|
||||
obj1.set('forced', true);
|
||||
Parse.Object.saveAll([obj0, obj1]).then(() => {
|
||||
let query = new Parse.Query('MyObject');
|
||||
const query = new Parse.Query('MyObject');
|
||||
query.equalTo('forced', false);
|
||||
query.find().then((results) => {
|
||||
expect(results.length).toBe(2);
|
||||
@@ -1274,7 +1274,7 @@ describe('beforeFind hooks', () => {
|
||||
return Promise.reject('Do not run that query');
|
||||
});
|
||||
|
||||
let query = new Parse.Query('MyObject');
|
||||
const query = new Parse.Query('MyObject');
|
||||
query.find().then(() => {
|
||||
fail('should not succeed');
|
||||
done();
|
||||
@@ -1287,7 +1287,7 @@ describe('beforeFind hooks', () => {
|
||||
|
||||
it('should handle empty where', (done) => {
|
||||
Parse.Cloud.beforeFind('MyObject', (req) => {
|
||||
let otherQuery = new Parse.Query('MyObject');
|
||||
const otherQuery = new Parse.Query('MyObject');
|
||||
otherQuery.equalTo('some', true);
|
||||
return Parse.Query.or(req.query, otherQuery);
|
||||
});
|
||||
@@ -1315,10 +1315,10 @@ describe('afterFind hooks', () => {
|
||||
}
|
||||
res.success(req.objects);
|
||||
});
|
||||
let obj = new Parse.Object('MyObject');
|
||||
const obj = new Parse.Object('MyObject');
|
||||
obj.set('secretField', 'SSID');
|
||||
obj.save().then(function() {
|
||||
let query = new Parse.Query('MyObject');
|
||||
const query = new Parse.Query('MyObject');
|
||||
query.get(obj.id).then(function(result) {
|
||||
expect(result.get('secretField')).toEqual('###');
|
||||
done();
|
||||
@@ -1339,10 +1339,10 @@ describe('afterFind hooks', () => {
|
||||
}
|
||||
res.success(req.objects);
|
||||
});
|
||||
let obj = new Parse.Object('MyObject');
|
||||
const obj = new Parse.Object('MyObject');
|
||||
obj.set('secretField', 'SSID');
|
||||
obj.save().then(function() {
|
||||
let query = new Parse.Query('MyObject');
|
||||
const query = new Parse.Query('MyObject');
|
||||
query.equalTo('objectId',obj.id);
|
||||
query.find().then(function(results) {
|
||||
expect(results[0].get('secretField')).toEqual('###');
|
||||
@@ -1359,20 +1359,20 @@ describe('afterFind hooks', () => {
|
||||
|
||||
it('should filter out results',(done) => {
|
||||
Parse.Cloud.afterFind('MyObject', (req, res) => {
|
||||
let filteredResults = [];
|
||||
const filteredResults = [];
|
||||
for(let i = 0 ; i < req.objects.length ; i++){
|
||||
if(req.objects[i].get("secretField")==="SSID1") {
|
||||
if(req.objects[i].get("secretField") === "SSID1") {
|
||||
filteredResults.push(req.objects[i]);
|
||||
}
|
||||
}
|
||||
res.success(filteredResults);
|
||||
});
|
||||
let obj0 = new Parse.Object('MyObject');
|
||||
const obj0 = new Parse.Object('MyObject');
|
||||
obj0.set('secretField', 'SSID1');
|
||||
let obj1 = new Parse.Object('MyObject');
|
||||
const obj1 = new Parse.Object('MyObject');
|
||||
obj1.set('secretField', 'SSID2');
|
||||
Parse.Object.saveAll([obj0, obj1]).then(function() {
|
||||
let query = new Parse.Query('MyObject');
|
||||
const query = new Parse.Query('MyObject');
|
||||
query.find().then(function(results) {
|
||||
expect(results[0].get('secretField')).toEqual('SSID1');
|
||||
expect(results.length).toEqual(1);
|
||||
@@ -1391,10 +1391,10 @@ describe('afterFind hooks', () => {
|
||||
Parse.Cloud.afterFind('MyObject', (req, res) => {
|
||||
res.error(Parse.Error.SCRIPT_FAILED, "It should fail");
|
||||
});
|
||||
let obj = new Parse.Object('MyObject');
|
||||
const obj = new Parse.Object('MyObject');
|
||||
obj.set('secretField', 'SSID');
|
||||
obj.save().then(function() {
|
||||
let query = new Parse.Query('MyObject');
|
||||
const query = new Parse.Query('MyObject');
|
||||
query.equalTo('objectId',obj.id);
|
||||
query.find().then(function() {
|
||||
fail("AfterFind should handle response failure correctly");
|
||||
@@ -1409,7 +1409,7 @@ describe('afterFind hooks', () => {
|
||||
|
||||
it('should also work with promise',(done) => {
|
||||
Parse.Cloud.afterFind('MyObject', (req) => {
|
||||
let promise = new Parse.Promise();
|
||||
const promise = new Parse.Promise();
|
||||
setTimeout(function(){
|
||||
for(let i = 0 ; i < req.objects.length ; i++){
|
||||
req.objects[i].set("secretField","###");
|
||||
@@ -1418,10 +1418,10 @@ describe('afterFind hooks', () => {
|
||||
}, 1000);
|
||||
return promise;
|
||||
});
|
||||
let obj = new Parse.Object('MyObject');
|
||||
const obj = new Parse.Object('MyObject');
|
||||
obj.set('secretField', 'SSID');
|
||||
obj.save().then(function() {
|
||||
let query = new Parse.Query('MyObject');
|
||||
const query = new Parse.Query('MyObject');
|
||||
query.equalTo('objectId',obj.id);
|
||||
query.find().then(function(results) {
|
||||
expect(results[0].get('secretField')).toEqual('###');
|
||||
@@ -1434,5 +1434,40 @@ describe('afterFind hooks', () => {
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
it('should alter select', (done) => {
|
||||
Parse.Cloud.beforeFind('MyObject', (req) => {
|
||||
req.query.select('white');
|
||||
return req.query;
|
||||
});
|
||||
|
||||
const obj0 = new Parse.Object('MyObject')
|
||||
.set('white', true)
|
||||
.set('black', true);
|
||||
obj0.save()
|
||||
.then(() => {
|
||||
new Parse.Query('MyObject')
|
||||
.first()
|
||||
.then(result => {
|
||||
expect(result.get('white')).toBe(true);
|
||||
expect(result.get('black')).toBe(undefined);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should not alter select', (done) => {
|
||||
const obj0 = new Parse.Object('MyObject')
|
||||
.set('white', true)
|
||||
.set('black', true);
|
||||
obj0.save()
|
||||
.then(() => {
|
||||
new Parse.Query('MyObject')
|
||||
.first()
|
||||
.then(result => {
|
||||
expect(result.get('white')).toBe(true);
|
||||
expect(result.get('black')).toBe(true);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -37,10 +37,10 @@ describe("Cloud Code Logger", () => {
|
||||
return logController.getLogs({ from: Date.now() - 500, size: 1000 });
|
||||
}).then((res) => {
|
||||
expect(res.length).not.toBe(0);
|
||||
let lastLogs = res.slice(0, 3);
|
||||
let cloudFunctionMessage = lastLogs[0];
|
||||
let errorMessage = lastLogs[1];
|
||||
let infoMessage = lastLogs[2];
|
||||
const lastLogs = res.slice(0, 3);
|
||||
const cloudFunctionMessage = lastLogs[0];
|
||||
const errorMessage = lastLogs[1];
|
||||
const infoMessage = lastLogs[2];
|
||||
expect(cloudFunctionMessage.level).toBe('info');
|
||||
expect(cloudFunctionMessage.params).toEqual({});
|
||||
expect(cloudFunctionMessage.message).toMatch(/Ran cloud function loggerTest for user [^ ]* with:\n {2}Input: {}\n {2}Result: {}/);
|
||||
@@ -82,15 +82,15 @@ describe("Cloud Code Logger", () => {
|
||||
res.success({});
|
||||
});
|
||||
|
||||
let obj = new Parse.Object('MyObject');
|
||||
const obj = new Parse.Object('MyObject');
|
||||
obj.save().then(() => {
|
||||
return logController.getLogs({ from: Date.now() - 500, size: 1000 })
|
||||
}).then((res) => {
|
||||
expect(res.length).not.toBe(0);
|
||||
let lastLogs = res.slice(0, 3);
|
||||
let cloudTriggerMessage = lastLogs[0];
|
||||
let errorMessage = lastLogs[1];
|
||||
let infoMessage = lastLogs[2];
|
||||
const lastLogs = res.slice(0, 3);
|
||||
const cloudTriggerMessage = lastLogs[0];
|
||||
const errorMessage = lastLogs[1];
|
||||
const infoMessage = lastLogs[2];
|
||||
expect(cloudTriggerMessage.level).toBe('info');
|
||||
expect(cloudTriggerMessage.triggerType).toEqual('beforeSave');
|
||||
expect(cloudTriggerMessage.message).toMatch(/beforeSave triggered for MyObject for user [^ ]*\n {2}Input: {}\n {2}Result: {}/);
|
||||
@@ -156,8 +156,9 @@ describe("Cloud Code Logger", () => {
|
||||
.save()
|
||||
.then(
|
||||
() => done.fail('this is not supposed to succeed'),
|
||||
() => logController.getLogs({ from: Date.now() - 500, size: 1000 })
|
||||
() => new Promise(resolve => setTimeout(resolve, 100))
|
||||
)
|
||||
.then(() => logController.getLogs({ from: Date.now() - 500, size: 1000 }))
|
||||
.then(logs => {
|
||||
const log = logs[1]; // 0 is the 'uh oh!' from rejection...
|
||||
expect(log.level).toEqual('error');
|
||||
@@ -194,7 +195,7 @@ describe("Cloud Code Logger", () => {
|
||||
Parse.Cloud.run('aFunction', { foo: 'bar' })
|
||||
.then(null, () => logController.getLogs({ from: Date.now() - 500, size: 1000 }))
|
||||
.then(logs => {
|
||||
const log = logs[1];
|
||||
const log = logs[2];
|
||||
expect(log.level).toEqual('error');
|
||||
expect(log.message).toMatch(
|
||||
/Failed running cloud function aFunction for user [^ ]* with:\n {2}Input: {"foo":"bar"}\n {2}Error: {"code":141,"message":"it failed!"}/);
|
||||
|
||||
@@ -241,12 +241,12 @@ describe("Email Verification Token Expiration: ", () => {
|
||||
return user.signUp();
|
||||
})
|
||||
.then(() => {
|
||||
let config = new Config('test');
|
||||
const config = new Config('test');
|
||||
return config.database.find('_User', {username: 'sets_email_verify_token_expires_at'});
|
||||
})
|
||||
.then(results => {
|
||||
expect(results.length).toBe(1);
|
||||
let user = results[0];
|
||||
const user = results[0];
|
||||
expect(typeof user).toBe('object');
|
||||
expect(user.emailVerified).toEqual(false);
|
||||
expect(typeof user._email_verify_token).toBe('string');
|
||||
@@ -288,7 +288,7 @@ describe("Email Verification Token Expiration: ", () => {
|
||||
followRedirect: false,
|
||||
}, (error, response) => {
|
||||
expect(response.statusCode).toEqual(302);
|
||||
let config = new Config('test');
|
||||
const config = new Config('test');
|
||||
return config.database.find('_User', {username: 'unsets_email_verify_token_expires_at'}).then((results) => {
|
||||
expect(results.length).toBe(1);
|
||||
return results[0];
|
||||
@@ -420,18 +420,18 @@ describe("Email Verification Token Expiration: ", () => {
|
||||
|
||||
it('setting the email on the user should set a new email verification token and new expiration date for the token when expire email verify token flag is set', done => {
|
||||
|
||||
let user = new Parse.User();
|
||||
const user = new Parse.User();
|
||||
let userBeforeEmailReset;
|
||||
|
||||
let sendEmailOptions;
|
||||
let emailAdapter = {
|
||||
const emailAdapter = {
|
||||
sendVerificationEmail: options => {
|
||||
sendEmailOptions = options;
|
||||
},
|
||||
sendPasswordResetEmail: () => Promise.resolve(),
|
||||
sendMail: () => {}
|
||||
};
|
||||
let serverConfig = {
|
||||
const serverConfig = {
|
||||
appName: 'emailVerifyToken',
|
||||
verifyUserEmails: true,
|
||||
emailAdapter: emailAdapter,
|
||||
@@ -447,7 +447,7 @@ describe("Email Verification Token Expiration: ", () => {
|
||||
return user.signUp();
|
||||
})
|
||||
.then(() => {
|
||||
let config = new Config('test');
|
||||
const config = new Config('test');
|
||||
return config.database.find('_User', {username: 'newEmailVerifyTokenOnEmailReset'}).then((results) => {
|
||||
return results[0];
|
||||
});
|
||||
@@ -460,11 +460,11 @@ describe("Email Verification Token Expiration: ", () => {
|
||||
user.set('email', 'user@parse.com');
|
||||
return new Promise((resolve) => {
|
||||
// wait for half a sec to get a new expiration time
|
||||
setTimeout( () => resolve(user.save()), 500 );
|
||||
setTimeout(() => resolve(user.save()), 500);
|
||||
});
|
||||
})
|
||||
.then(() => {
|
||||
let config = new Config('test');
|
||||
const config = new Config('test');
|
||||
return config.database.find('_User', {username: 'newEmailVerifyTokenOnEmailReset'}).then((results) => {
|
||||
return results[0];
|
||||
});
|
||||
|
||||
@@ -1,7 +1,17 @@
|
||||
var GridStoreAdapter = require("../src/Adapters/Files/GridStoreAdapter").GridStoreAdapter;
|
||||
var Config = require("../src/Config");
|
||||
var FilesController = require('../src/Controllers/FilesController').default;
|
||||
const LoggerController = require('../src/Controllers/LoggerController').LoggerController;
|
||||
const WinstonLoggerAdapter = require('../src/Adapters/Logger/WinstonLoggerAdapter').WinstonLoggerAdapter;
|
||||
const GridStoreAdapter = require("../src/Adapters/Files/GridStoreAdapter").GridStoreAdapter;
|
||||
const Config = require("../src/Config");
|
||||
const FilesController = require('../src/Controllers/FilesController').default;
|
||||
|
||||
const mockAdapter = {
|
||||
createFile: () => {
|
||||
return Parse.Promise.reject(new Error('it failed'));
|
||||
},
|
||||
deleteFile: () => { },
|
||||
getFileData: () => { },
|
||||
getFileLocation: () => 'xyz'
|
||||
}
|
||||
|
||||
// Small additional tests to improve overall coverage
|
||||
describe("FilesController",() =>{
|
||||
@@ -26,5 +36,30 @@ describe("FilesController",() =>{
|
||||
expect(anObject.aFile.url).toEqual("http://an.url");
|
||||
|
||||
done();
|
||||
})
|
||||
});
|
||||
|
||||
it('should create a server log on failure', done => {
|
||||
const logController = new LoggerController(new WinstonLoggerAdapter());
|
||||
|
||||
reconfigureServer({ filesAdapter: mockAdapter })
|
||||
.then(() => new Promise(resolve => setTimeout(resolve, 1000)))
|
||||
.then(() => new Parse.File("yolo.txt", [1,2,3], "text/plain").save())
|
||||
.then(
|
||||
() => done.fail('should not succeed'),
|
||||
() => setImmediate(() => Parse.Promise.as('done'))
|
||||
)
|
||||
.then(() => logController.getLogs({ from: Date.now() - 500, size: 1000 }))
|
||||
.then((logs) => {
|
||||
// we get two logs here: 1. the source of the failure to save the file
|
||||
// and 2 the message that will be sent back to the client.
|
||||
const log1 = logs.pop();
|
||||
expect(log1.level).toBe('error');
|
||||
expect(log1.message).toBe('it failed');
|
||||
const log2 = logs.pop();
|
||||
expect(log2.level).toBe('error');
|
||||
expect(log2.code).toBe(130);
|
||||
expect(log2.message).toBe('Could not store file.');
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
+36
-36
@@ -6,7 +6,7 @@ var httpRequest = require("../src/cloud-code/httpRequest"),
|
||||
express = require("express");
|
||||
|
||||
var port = 13371;
|
||||
var httpRequestServer = "http://localhost:"+port;
|
||||
var httpRequestServer = "http://localhost:" + port;
|
||||
|
||||
var app = express();
|
||||
app.use(bodyParser.json({ 'type': '*/*' }));
|
||||
@@ -39,7 +39,7 @@ app.listen(13371);
|
||||
describe("httpRequest", () => {
|
||||
it("should do /hello", (done) => {
|
||||
httpRequest({
|
||||
url: httpRequestServer+"/hello"
|
||||
url: httpRequestServer + "/hello"
|
||||
}).then(function(httpResponse){
|
||||
expect(httpResponse.status).toBe(200);
|
||||
expect(httpResponse.buffer).toEqual(new Buffer('{"response":"OK"}'));
|
||||
@@ -55,7 +55,7 @@ describe("httpRequest", () => {
|
||||
it("should do /hello with callback and promises", (done) => {
|
||||
var calls = 0;
|
||||
httpRequest({
|
||||
url: httpRequestServer+"/hello",
|
||||
url: httpRequestServer + "/hello",
|
||||
success: function() { calls++; },
|
||||
error: function() { calls++; }
|
||||
}).then(function(httpResponse){
|
||||
@@ -74,7 +74,7 @@ describe("httpRequest", () => {
|
||||
it("should do not follow redirects by default", (done) => {
|
||||
|
||||
httpRequest({
|
||||
url: httpRequestServer+"/301"
|
||||
url: httpRequestServer + "/301"
|
||||
}).then(function(httpResponse){
|
||||
expect(httpResponse.status).toBe(301);
|
||||
done();
|
||||
@@ -87,7 +87,7 @@ describe("httpRequest", () => {
|
||||
it("should follow redirects when set", (done) => {
|
||||
|
||||
httpRequest({
|
||||
url: httpRequestServer+"/301",
|
||||
url: httpRequestServer + "/301",
|
||||
followRedirects: true
|
||||
}).then(function(httpResponse){
|
||||
expect(httpResponse.status).toBe(200);
|
||||
@@ -104,7 +104,7 @@ describe("httpRequest", () => {
|
||||
it("should fail on 404", (done) => {
|
||||
var calls = 0;
|
||||
httpRequest({
|
||||
url: httpRequestServer+"/404",
|
||||
url: httpRequestServer + "/404",
|
||||
success: function() {
|
||||
calls++;
|
||||
fail("should not succeed");
|
||||
@@ -124,7 +124,7 @@ describe("httpRequest", () => {
|
||||
|
||||
it("should fail on 404", (done) => {
|
||||
httpRequest({
|
||||
url: httpRequestServer+"/404",
|
||||
url: httpRequestServer + "/404",
|
||||
}).then(function(){
|
||||
fail("should not succeed");
|
||||
done();
|
||||
@@ -141,7 +141,7 @@ describe("httpRequest", () => {
|
||||
var calls = 0;
|
||||
httpRequest({
|
||||
method: "POST",
|
||||
url: httpRequestServer+"/echo",
|
||||
url: httpRequestServer + "/echo",
|
||||
body: {
|
||||
foo: "bar"
|
||||
},
|
||||
@@ -162,10 +162,10 @@ describe("httpRequest", () => {
|
||||
});
|
||||
|
||||
it("should encode a query string body by default", (done) => {
|
||||
let options = {
|
||||
const options = {
|
||||
body: {"foo": "bar"},
|
||||
}
|
||||
let result = httpRequest.encodeBody(options);
|
||||
const result = httpRequest.encodeBody(options);
|
||||
expect(result.body).toEqual('foo=bar');
|
||||
expect(result.headers['Content-Type']).toEqual('application/x-www-form-urlencoded');
|
||||
done();
|
||||
@@ -173,30 +173,30 @@ describe("httpRequest", () => {
|
||||
})
|
||||
|
||||
it("should encode a JSON body", (done) => {
|
||||
let options = {
|
||||
const options = {
|
||||
body: {"foo": "bar"},
|
||||
headers: {'Content-Type': 'application/json'}
|
||||
}
|
||||
let result = httpRequest.encodeBody(options);
|
||||
const result = httpRequest.encodeBody(options);
|
||||
expect(result.body).toEqual('{"foo":"bar"}');
|
||||
done();
|
||||
|
||||
})
|
||||
it("should encode a www-form body", (done) => {
|
||||
let options = {
|
||||
const options = {
|
||||
body: {"foo": "bar", "bar": "baz"},
|
||||
headers: {'cOntent-tYpe': 'application/x-www-form-urlencoded'}
|
||||
}
|
||||
let result = httpRequest.encodeBody(options);
|
||||
const result = httpRequest.encodeBody(options);
|
||||
expect(result.body).toEqual("foo=bar&bar=baz");
|
||||
done();
|
||||
});
|
||||
it("should not encode a wrong content type", (done) => {
|
||||
let options = {
|
||||
const options = {
|
||||
body:{"foo": "bar", "bar": "baz"},
|
||||
headers: {'cOntent-tYpe': 'mime/jpeg'}
|
||||
}
|
||||
let result = httpRequest.encodeBody(options);
|
||||
const result = httpRequest.encodeBody(options);
|
||||
expect(result.body).toEqual({"foo": "bar", "bar": "baz"});
|
||||
done();
|
||||
});
|
||||
@@ -218,7 +218,7 @@ describe("httpRequest", () => {
|
||||
|
||||
it("should params object to query string", (done) => {
|
||||
httpRequest({
|
||||
url: httpRequestServer+"/qs",
|
||||
url: httpRequestServer + "/qs",
|
||||
params: {
|
||||
foo: "bar"
|
||||
}
|
||||
@@ -234,7 +234,7 @@ describe("httpRequest", () => {
|
||||
|
||||
it("should params string to query string", (done) => {
|
||||
httpRequest({
|
||||
url: httpRequestServer+"/qs",
|
||||
url: httpRequestServer + "/qs",
|
||||
params: "foo=bar&foo2=bar2"
|
||||
}).then(function(httpResponse){
|
||||
expect(httpResponse.status).toBe(200);
|
||||
@@ -247,7 +247,7 @@ describe("httpRequest", () => {
|
||||
});
|
||||
|
||||
it('should not crash with undefined body', () => {
|
||||
let httpResponse = new HTTPResponse({});
|
||||
const httpResponse = new HTTPResponse({});
|
||||
expect(httpResponse.body).toBeUndefined();
|
||||
expect(httpResponse.data).toBeUndefined();
|
||||
expect(httpResponse.text).toBeUndefined();
|
||||
@@ -255,24 +255,24 @@ describe("httpRequest", () => {
|
||||
});
|
||||
|
||||
it('serialized httpResponse correctly with body string', () => {
|
||||
let httpResponse = new HTTPResponse({}, 'hello');
|
||||
const httpResponse = new HTTPResponse({}, 'hello');
|
||||
expect(httpResponse.text).toBe('hello');
|
||||
expect(httpResponse.data).toBe(undefined);
|
||||
expect(httpResponse.body).toBe('hello');
|
||||
|
||||
let serialized = JSON.stringify(httpResponse);
|
||||
let result = JSON.parse(serialized);
|
||||
const serialized = JSON.stringify(httpResponse);
|
||||
const result = JSON.parse(serialized);
|
||||
expect(result.text).toBe('hello');
|
||||
expect(result.data).toBe(undefined);
|
||||
expect(result.body).toBe(undefined);
|
||||
});
|
||||
|
||||
it('serialized httpResponse correctly with body object', () => {
|
||||
let httpResponse = new HTTPResponse({}, {foo: "bar"});
|
||||
const httpResponse = new HTTPResponse({}, {foo: "bar"});
|
||||
Parse._encode(httpResponse);
|
||||
let serialized = JSON.stringify(httpResponse);
|
||||
let result = JSON.parse(serialized);
|
||||
|
||||
const serialized = JSON.stringify(httpResponse);
|
||||
const result = JSON.parse(serialized);
|
||||
|
||||
expect(httpResponse.text).toEqual('{"foo":"bar"}');
|
||||
expect(httpResponse.data).toEqual({foo: 'bar'});
|
||||
expect(httpResponse.body).toEqual({foo: 'bar'});
|
||||
@@ -283,29 +283,29 @@ describe("httpRequest", () => {
|
||||
});
|
||||
|
||||
it('serialized httpResponse correctly with body buffer string', () => {
|
||||
let httpResponse = new HTTPResponse({}, new Buffer('hello'));
|
||||
const httpResponse = new HTTPResponse({}, new Buffer('hello'));
|
||||
expect(httpResponse.text).toBe('hello');
|
||||
expect(httpResponse.data).toBe(undefined);
|
||||
|
||||
let serialized = JSON.stringify(httpResponse);
|
||||
let result = JSON.parse(serialized);
|
||||
const serialized = JSON.stringify(httpResponse);
|
||||
const result = JSON.parse(serialized);
|
||||
expect(result.text).toBe('hello');
|
||||
expect(result.data).toBe(undefined);
|
||||
});
|
||||
|
||||
it('serialized httpResponse correctly with body buffer JSON Object', () => {
|
||||
let json = '{"foo":"bar"}';
|
||||
let httpResponse = new HTTPResponse({}, new Buffer(json));
|
||||
let serialized = JSON.stringify(httpResponse);
|
||||
let result = JSON.parse(serialized);
|
||||
const json = '{"foo":"bar"}';
|
||||
const httpResponse = new HTTPResponse({}, new Buffer(json));
|
||||
const serialized = JSON.stringify(httpResponse);
|
||||
const result = JSON.parse(serialized);
|
||||
expect(result.text).toEqual('{"foo":"bar"}');
|
||||
expect(result.data).toEqual({foo: 'bar'});
|
||||
});
|
||||
|
||||
it('serialized httpResponse with Parse._encode should be allright', () => {
|
||||
let json = '{"foo":"bar"}';
|
||||
let httpResponse = new HTTPResponse({}, new Buffer(json));
|
||||
let encoded = Parse._encode(httpResponse);
|
||||
const json = '{"foo":"bar"}';
|
||||
const httpResponse = new HTTPResponse({}, new Buffer(json));
|
||||
const encoded = Parse._encode(httpResponse);
|
||||
let foundData, foundText, foundBody = false;
|
||||
for(var key in encoded) {
|
||||
if (key == 'data') {
|
||||
|
||||
+5
-5
@@ -23,8 +23,8 @@ describe('Logger', () => {
|
||||
|
||||
it('should have files transports', (done) => {
|
||||
reconfigureServer().then(() => {
|
||||
let transports = logging.logger.transports;
|
||||
let transportKeys = Object.keys(transports);
|
||||
const transports = logging.logger.transports;
|
||||
const transportKeys = Object.keys(transports);
|
||||
expect(transportKeys.length).toBe(3);
|
||||
done();
|
||||
});
|
||||
@@ -34,8 +34,8 @@ describe('Logger', () => {
|
||||
reconfigureServer({
|
||||
logsFolder: null
|
||||
}).then(() => {
|
||||
let transports = logging.logger.transports;
|
||||
let transportKeys = Object.keys(transports);
|
||||
const transports = logging.logger.transports;
|
||||
const transportKeys = Object.keys(transports);
|
||||
expect(transportKeys.length).toBe(1);
|
||||
done();
|
||||
});
|
||||
@@ -52,7 +52,7 @@ describe('Logger', () => {
|
||||
logging.logger.info('hi', {key: 'value'});
|
||||
expect(process.stdout.write).toHaveBeenCalled();
|
||||
var firstLog = process.stdout.write.calls.first().args[0];
|
||||
expect(firstLog).toEqual(JSON.stringify({key: 'value', level: 'info', message: 'hi' })+'\n');
|
||||
expect(firstLog).toEqual(JSON.stringify({key: 'value', level: 'info', message: 'hi' }) + '\n');
|
||||
return reconfigureServer({
|
||||
jsonLogs: false
|
||||
});
|
||||
|
||||
@@ -79,6 +79,19 @@ describe('middlewares', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('should succeed when client key supplied but empty', (done) => {
|
||||
AppCache.put(fakeReq.body._ApplicationId, {
|
||||
clientKey: '',
|
||||
masterKey: 'masterKey',
|
||||
restAPIKey: 'restAPIKey'
|
||||
});
|
||||
fakeReq.headers['x-parse-client-key'] = '';
|
||||
middlewares.handleParseHeaders(fakeReq, fakeRes, () => {
|
||||
expect(fakeRes.status).not.toHaveBeenCalled();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should succeed when no keys are configured and none supplied', (done) => {
|
||||
AppCache.put(fakeReq.body._ApplicationId, {
|
||||
masterKey: 'masterKey'
|
||||
@@ -120,4 +133,4 @@ describe('middlewares', () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -2,7 +2,7 @@ module.exports = options => {
|
||||
if (!options) {
|
||||
throw "Options were not provided"
|
||||
}
|
||||
let adapter = {
|
||||
const adapter = {
|
||||
sendVerificationEmail: () => Promise.resolve(),
|
||||
sendPasswordResetEmail: () => Promise.resolve(),
|
||||
sendMail: () => Promise.resolve()
|
||||
|
||||
@@ -48,7 +48,7 @@ describe_only_db('mongo')('MongoStorageAdapter', () => {
|
||||
});
|
||||
|
||||
it('stores objectId in _id', done => {
|
||||
let adapter = new MongoStorageAdapter({ uri: databaseURI });
|
||||
const adapter = new MongoStorageAdapter({ uri: databaseURI });
|
||||
adapter.createObject('Foo', { fields: {} }, { objectId: 'abcde' })
|
||||
.then(() => adapter._rawFind('Foo', {}))
|
||||
.then(results => {
|
||||
@@ -62,7 +62,7 @@ describe_only_db('mongo')('MongoStorageAdapter', () => {
|
||||
|
||||
it('find succeeds when query is within maxTimeMS', (done) => {
|
||||
const maxTimeMS = 250;
|
||||
let adapter = new MongoStorageAdapter({
|
||||
const adapter = new MongoStorageAdapter({
|
||||
uri: databaseURI,
|
||||
mongoOptions: { maxTimeMS },
|
||||
});
|
||||
@@ -78,7 +78,7 @@ describe_only_db('mongo')('MongoStorageAdapter', () => {
|
||||
|
||||
it('find fails when query exceeds maxTimeMS', (done) => {
|
||||
const maxTimeMS = 250;
|
||||
let adapter = new MongoStorageAdapter({
|
||||
const adapter = new MongoStorageAdapter({
|
||||
uri: databaseURI,
|
||||
mongoOptions: { maxTimeMS },
|
||||
});
|
||||
@@ -98,7 +98,7 @@ describe_only_db('mongo')('MongoStorageAdapter', () => {
|
||||
});
|
||||
|
||||
it('stores pointers with a _p_ prefix', (done) => {
|
||||
let obj = {
|
||||
const obj = {
|
||||
objectId: 'bar',
|
||||
aPointer: {
|
||||
__type: 'Pointer',
|
||||
@@ -106,7 +106,7 @@ describe_only_db('mongo')('MongoStorageAdapter', () => {
|
||||
objectId: 'qwerty'
|
||||
}
|
||||
};
|
||||
let adapter = new MongoStorageAdapter({ uri: databaseURI });
|
||||
const adapter = new MongoStorageAdapter({ uri: databaseURI });
|
||||
adapter.createObject('APointerDarkly', { fields: {
|
||||
objectId: { type: 'String' },
|
||||
aPointer: { type: 'Pointer', targetClass: 'JustThePointer' },
|
||||
@@ -114,7 +114,7 @@ describe_only_db('mongo')('MongoStorageAdapter', () => {
|
||||
.then(() => adapter._rawFind('APointerDarkly', {}))
|
||||
.then(results => {
|
||||
expect(results.length).toEqual(1);
|
||||
let output = results[0];
|
||||
const output = results[0];
|
||||
expect(typeof output._id).toEqual('string');
|
||||
expect(typeof output._p_aPointer).toEqual('string');
|
||||
expect(output._p_aPointer).toEqual('JustThePointer$qwerty');
|
||||
@@ -124,24 +124,24 @@ describe_only_db('mongo')('MongoStorageAdapter', () => {
|
||||
});
|
||||
|
||||
it('handles object and subdocument', done => {
|
||||
let adapter = new MongoStorageAdapter({ uri: databaseURI });
|
||||
let schema = { fields : { subdoc: { type: 'Object' } } };
|
||||
let obj = { subdoc: {foo: 'bar', wu: 'tan'} };
|
||||
const adapter = new MongoStorageAdapter({ uri: databaseURI });
|
||||
const schema = { fields : { subdoc: { type: 'Object' } } };
|
||||
const obj = { subdoc: {foo: 'bar', wu: 'tan'} };
|
||||
adapter.createObject('MyClass', schema, obj)
|
||||
.then(() => adapter._rawFind('MyClass', {}))
|
||||
.then(results => {
|
||||
expect(results.length).toEqual(1);
|
||||
let mob = results[0];
|
||||
const mob = results[0];
|
||||
expect(typeof mob.subdoc).toBe('object');
|
||||
expect(mob.subdoc.foo).toBe('bar');
|
||||
expect(mob.subdoc.wu).toBe('tan');
|
||||
let obj = { 'subdoc.wu': 'clan' };
|
||||
const obj = { 'subdoc.wu': 'clan' };
|
||||
return adapter.findOneAndUpdate('MyClass', schema, {}, obj);
|
||||
})
|
||||
.then(() => adapter._rawFind('MyClass', {}))
|
||||
.then(results => {
|
||||
expect(results.length).toEqual(1);
|
||||
let mob = results[0];
|
||||
const mob = results[0];
|
||||
expect(typeof mob.subdoc).toBe('object');
|
||||
expect(mob.subdoc.foo).toBe('bar');
|
||||
expect(mob.subdoc.wu).toBe('clan');
|
||||
@@ -150,8 +150,8 @@ describe_only_db('mongo')('MongoStorageAdapter', () => {
|
||||
});
|
||||
|
||||
it('handles creating an array, object, date', (done) => {
|
||||
let adapter = new MongoStorageAdapter({ uri: databaseURI });
|
||||
let obj = {
|
||||
const adapter = new MongoStorageAdapter({ uri: databaseURI });
|
||||
const obj = {
|
||||
array: [1, 2, 3],
|
||||
object: {foo: 'bar'},
|
||||
date: {
|
||||
@@ -159,7 +159,7 @@ describe_only_db('mongo')('MongoStorageAdapter', () => {
|
||||
iso: '2016-05-26T20:55:01.154Z',
|
||||
},
|
||||
};
|
||||
let schema = { fields: {
|
||||
const schema = { fields: {
|
||||
array: { type: 'Array' },
|
||||
object: { type: 'Object' },
|
||||
date: { type: 'Date' },
|
||||
@@ -168,7 +168,7 @@ describe_only_db('mongo')('MongoStorageAdapter', () => {
|
||||
.then(() => adapter._rawFind('MyClass', {}))
|
||||
.then(results => {
|
||||
expect(results.length).toEqual(1);
|
||||
let mob = results[0];
|
||||
const mob = results[0];
|
||||
expect(mob.array instanceof Array).toBe(true);
|
||||
expect(typeof mob.object).toBe('object');
|
||||
expect(mob.date instanceof Date).toBe(true);
|
||||
@@ -176,7 +176,7 @@ describe_only_db('mongo')('MongoStorageAdapter', () => {
|
||||
})
|
||||
.then(results => {
|
||||
expect(results.length).toEqual(1);
|
||||
let mob = results[0];
|
||||
const mob = results[0];
|
||||
expect(mob.array instanceof Array).toBe(true);
|
||||
expect(typeof mob.object).toBe('object');
|
||||
expect(mob.date.__type).toBe('Date');
|
||||
@@ -191,20 +191,20 @@ describe_only_db('mongo')('MongoStorageAdapter', () => {
|
||||
});
|
||||
|
||||
it("handles updating a single object with array, object date", (done) => {
|
||||
let adapter = new MongoStorageAdapter({ uri: databaseURI });
|
||||
|
||||
let schema = { fields: {
|
||||
const adapter = new MongoStorageAdapter({ uri: databaseURI });
|
||||
|
||||
const schema = { fields: {
|
||||
array: { type: 'Array' },
|
||||
object: { type: 'Object' },
|
||||
date: { type: 'Date' },
|
||||
} };
|
||||
|
||||
|
||||
|
||||
adapter.createObject('MyClass', schema, {})
|
||||
.then(() => adapter._rawFind('MyClass', {}))
|
||||
.then(results => {
|
||||
expect(results.length).toEqual(1);
|
||||
let update = {
|
||||
const update = {
|
||||
array: [1, 2, 3],
|
||||
object: {foo: 'bar'},
|
||||
date: {
|
||||
@@ -212,11 +212,11 @@ describe_only_db('mongo')('MongoStorageAdapter', () => {
|
||||
iso: '2016-05-26T20:55:01.154Z',
|
||||
},
|
||||
};
|
||||
let query = {};
|
||||
const query = {};
|
||||
return adapter.findOneAndUpdate('MyClass', schema, query, update)
|
||||
})
|
||||
.then(results => {
|
||||
let mob = results;
|
||||
const mob = results;
|
||||
expect(mob.array instanceof Array).toBe(true);
|
||||
expect(typeof mob.object).toBe('object');
|
||||
expect(mob.date.__type).toBe('Date');
|
||||
@@ -225,7 +225,7 @@ describe_only_db('mongo')('MongoStorageAdapter', () => {
|
||||
})
|
||||
.then(results => {
|
||||
expect(results.length).toEqual(1);
|
||||
let mob = results[0];
|
||||
const mob = results[0];
|
||||
expect(mob.array instanceof Array).toBe(true);
|
||||
expect(typeof mob.object).toBe('object');
|
||||
expect(mob.date instanceof Date).toBe(true);
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
// These tests are unit tests designed to only test transform.js.
|
||||
"use strict";
|
||||
|
||||
let transform = require('../src/Adapters/Storage/Mongo/MongoTransform');
|
||||
let dd = require('deep-diff');
|
||||
let mongodb = require('mongodb');
|
||||
const transform = require('../src/Adapters/Storage/Mongo/MongoTransform');
|
||||
const dd = require('deep-diff');
|
||||
const mongodb = require('mongodb');
|
||||
|
||||
describe('parseObjectToMongoObjectForCreate', () => {
|
||||
it('a basic number', (done) => {
|
||||
@@ -179,7 +179,7 @@ describe('parseObjectToMongoObjectForCreate', () => {
|
||||
});
|
||||
|
||||
it('untransforms objects containing nested special keys', done => {
|
||||
let input = {array: [{
|
||||
const input = {array: [{
|
||||
_id: "Test ID",
|
||||
_hashed_password: "I Don't know why you would name a key this, but if you do it should work",
|
||||
_tombstone: {
|
||||
@@ -190,7 +190,7 @@ describe('parseObjectToMongoObjectForCreate', () => {
|
||||
},
|
||||
regularKey: "some data",
|
||||
}]}
|
||||
let output = transform.mongoObjectToParseObject(null, input, {
|
||||
const output = transform.mongoObjectToParseObject(null, input, {
|
||||
fields: { array: { type: 'Array' }},
|
||||
});
|
||||
expect(dd(output, input)).toEqual(undefined);
|
||||
@@ -242,7 +242,7 @@ describe('parseObjectToMongoObjectForCreate', () => {
|
||||
};
|
||||
var output = transform.parseObjectToMongoObjectForCreate(null, input, {
|
||||
fields: {
|
||||
aRelation: { __type: 'Relation', className: 'Stuff' },
|
||||
aRelation: { __type: 'Relation', className: 'Stuff' },
|
||||
},
|
||||
});
|
||||
expect(output).toEqual({});
|
||||
@@ -293,6 +293,32 @@ describe('parseObjectToMongoObjectForCreate', () => {
|
||||
expect(output.double).toBe(Number.MAX_VALUE);
|
||||
done();
|
||||
});
|
||||
|
||||
it('Date object where iso attribute is of type Date', (done) => {
|
||||
var input = {
|
||||
ts : { __type: 'Date', iso: new Date('2017-01-18T00:00:00.000Z') }
|
||||
}
|
||||
var output = transform.mongoObjectToParseObject(null, input, {
|
||||
fields : {
|
||||
ts : { type : 'Date' }
|
||||
}
|
||||
});
|
||||
expect(output.ts.iso).toEqual('2017-01-18T00:00:00.000Z');
|
||||
done();
|
||||
});
|
||||
|
||||
it('Date object where iso attribute is of type String', (done) => {
|
||||
var input = {
|
||||
ts : { __type: 'Date', iso: '2017-01-18T00:00:00.000Z' }
|
||||
}
|
||||
var output = transform.mongoObjectToParseObject(null, input, {
|
||||
fields : {
|
||||
ts : { type : 'Date' }
|
||||
}
|
||||
});
|
||||
expect(output.ts.iso).toEqual('2017-01-18T00:00:00.000Z');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
describe('transformUpdate', () => {
|
||||
@@ -302,7 +328,7 @@ describe('transformUpdate', () => {
|
||||
};
|
||||
var output = transform.transformUpdate(null, input, {
|
||||
fields: {
|
||||
aRelation: { __type: 'Relation', className: 'Stuff' },
|
||||
aRelation: { __type: 'Relation', className: 'Stuff' },
|
||||
},
|
||||
});
|
||||
expect(output).toEqual({});
|
||||
|
||||
@@ -0,0 +1,136 @@
|
||||
var OAuth = require("../src/Adapters/Auth/OAuth1Client");
|
||||
|
||||
describe('OAuth', function() {
|
||||
it("Nonce should have right length", (done) => {
|
||||
jequal(OAuth.nonce().length, 30);
|
||||
done();
|
||||
});
|
||||
|
||||
it("Should properly build parameter string", (done) => {
|
||||
var string = OAuth.buildParameterString({c:1, a:2, b:3})
|
||||
jequal(string, "a=2&b=3&c=1");
|
||||
done();
|
||||
});
|
||||
|
||||
it("Should properly build empty parameter string", (done) => {
|
||||
var string = OAuth.buildParameterString()
|
||||
jequal(string, "");
|
||||
done();
|
||||
});
|
||||
|
||||
it("Should properly build signature string", (done) => {
|
||||
var string = OAuth.buildSignatureString("get", "http://dummy.com", "");
|
||||
jequal(string, "GET&http%3A%2F%2Fdummy.com&");
|
||||
done();
|
||||
});
|
||||
|
||||
it("Should properly generate request signature", (done) => {
|
||||
var request = {
|
||||
host: "dummy.com",
|
||||
path: "path"
|
||||
};
|
||||
|
||||
var oauth_params = {
|
||||
oauth_timestamp: 123450000,
|
||||
oauth_nonce: "AAAAAAAAAAAAAAAAA",
|
||||
oauth_consumer_key: "hello",
|
||||
oauth_token: "token"
|
||||
};
|
||||
|
||||
var consumer_secret = "world";
|
||||
var auth_token_secret = "secret";
|
||||
request = OAuth.signRequest(request, oauth_params, consumer_secret, auth_token_secret);
|
||||
jequal(request.headers['Authorization'], 'OAuth oauth_consumer_key="hello", oauth_nonce="AAAAAAAAAAAAAAAAA", oauth_signature="8K95bpQcDi9Nd2GkhumTVcw4%2BXw%3D", oauth_signature_method="HMAC-SHA1", oauth_timestamp="123450000", oauth_token="token", oauth_version="1.0"');
|
||||
done();
|
||||
});
|
||||
|
||||
it("Should properly build request", (done) => {
|
||||
var options = {
|
||||
host: "dummy.com",
|
||||
consumer_key: "hello",
|
||||
consumer_secret: "world",
|
||||
auth_token: "token",
|
||||
auth_token_secret: "secret",
|
||||
// Custom oauth params for tests
|
||||
oauth_params: {
|
||||
oauth_timestamp: 123450000,
|
||||
oauth_nonce: "AAAAAAAAAAAAAAAAA"
|
||||
}
|
||||
};
|
||||
var path = "path";
|
||||
var method = "get";
|
||||
|
||||
var oauthClient = new OAuth(options);
|
||||
var req = oauthClient.buildRequest(method, path, {"query": "param"});
|
||||
|
||||
jequal(req.host, options.host);
|
||||
jequal(req.path, "/" + path + "?query=param");
|
||||
jequal(req.method, "GET");
|
||||
jequal(req.headers['Content-Type'], 'application/x-www-form-urlencoded');
|
||||
jequal(req.headers['Authorization'], 'OAuth oauth_consumer_key="hello", oauth_nonce="AAAAAAAAAAAAAAAAA", oauth_signature="wNkyEkDE%2F0JZ2idmqyrgHdvC0rs%3D", oauth_signature_method="HMAC-SHA1", oauth_timestamp="123450000", oauth_token="token", oauth_version="1.0"')
|
||||
done();
|
||||
});
|
||||
|
||||
|
||||
function validateCannotAuthenticateError(data, done) {
|
||||
jequal(typeof data, "object");
|
||||
jequal(typeof data.errors, "object");
|
||||
var errors = data.errors;
|
||||
jequal(typeof errors[0], "object");
|
||||
// Cannot authenticate error
|
||||
jequal(errors[0].code, 32);
|
||||
done();
|
||||
}
|
||||
|
||||
it("Should fail a GET request", (done) => {
|
||||
var options = {
|
||||
host: "api.twitter.com",
|
||||
consumer_key: "XXXXXXXXXXXXXXXXXXXXXXXXX",
|
||||
consumer_secret: "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
|
||||
};
|
||||
var path = "/1.1/help/configuration.json";
|
||||
var params = {"lang": "en"};
|
||||
var oauthClient = new OAuth(options);
|
||||
oauthClient.get(path, params).then(function(data){
|
||||
validateCannotAuthenticateError(data, done);
|
||||
})
|
||||
});
|
||||
|
||||
it("Should fail a POST request", (done) => {
|
||||
var options = {
|
||||
host: "api.twitter.com",
|
||||
consumer_key: "XXXXXXXXXXXXXXXXXXXXXXXXX",
|
||||
consumer_secret: "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
|
||||
};
|
||||
var body = {
|
||||
lang: "en"
|
||||
};
|
||||
var path = "/1.1/account/settings.json";
|
||||
|
||||
var oauthClient = new OAuth(options);
|
||||
oauthClient.post(path, null, body).then(function(data){
|
||||
validateCannotAuthenticateError(data, done);
|
||||
})
|
||||
});
|
||||
|
||||
it("Should fail a request", (done) => {
|
||||
var options = {
|
||||
host: "localhost",
|
||||
consumer_key: "XXXXXXXXXXXXXXXXXXXXXXXXX",
|
||||
consumer_secret: "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
|
||||
};
|
||||
var body = {
|
||||
lang: "en"
|
||||
};
|
||||
var path = "/";
|
||||
|
||||
var oauthClient = new OAuth(options);
|
||||
oauthClient.post(path, null, body).then(function(){
|
||||
jequal(false, true);
|
||||
done();
|
||||
}).catch(function(){
|
||||
jequal(true, true);
|
||||
done();
|
||||
})
|
||||
});
|
||||
});
|
||||
+36
-11
@@ -1,23 +1,33 @@
|
||||
'use strict';
|
||||
|
||||
let request = require('request');
|
||||
const request = require('request');
|
||||
|
||||
const delayPromise = (delay) => {
|
||||
return new Promise((resolve) => {
|
||||
setTimeout(resolve, delay);
|
||||
});
|
||||
}
|
||||
|
||||
describe('Parse.Push', () => {
|
||||
var setup = function() {
|
||||
var sendToInstallationSpy = jasmine.createSpy();
|
||||
|
||||
var pushAdapter = {
|
||||
send: function(body, installations) {
|
||||
var badge = body.data.badge;
|
||||
let promises = installations.map((installation) => {
|
||||
const promises = installations.map((installation) => {
|
||||
sendToInstallationSpy(installation);
|
||||
|
||||
if (installation.deviceType == "ios") {
|
||||
expect(installation.badge).toEqual(badge);
|
||||
expect(installation.originalBadge+1).toEqual(installation.badge);
|
||||
expect(installation.originalBadge + 1).toEqual(installation.badge);
|
||||
} else {
|
||||
expect(installation.badge).toBeUndefined();
|
||||
}
|
||||
return Promise.resolve({
|
||||
err: null,
|
||||
deviceType: installation.deviceType,
|
||||
result: true
|
||||
device: installation,
|
||||
transmitted: true
|
||||
})
|
||||
});
|
||||
return Promise.all(promises);
|
||||
@@ -39,21 +49,29 @@ describe('Parse.Push', () => {
|
||||
var installations = [];
|
||||
while(installations.length != 10) {
|
||||
var installation = new Parse.Object("_Installation");
|
||||
installation.set("installationId", "installation_"+installations.length);
|
||||
installation.set("deviceToken","device_token_"+installations.length)
|
||||
installation.set("installationId", "installation_" + installations.length);
|
||||
installation.set("deviceToken","device_token_" + installations.length)
|
||||
installation.set("badge", installations.length);
|
||||
installation.set("originalBadge", installations.length);
|
||||
installation.set("deviceType", "ios");
|
||||
installations.push(installation);
|
||||
}
|
||||
return Parse.Object.saveAll(installations);
|
||||
}).catch((err) => {
|
||||
})
|
||||
.then(() => {
|
||||
return {
|
||||
sendToInstallationSpy,
|
||||
};
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error(err);
|
||||
|
||||
throw err;
|
||||
})
|
||||
}
|
||||
|
||||
it('should properly send push', (done) => {
|
||||
return setup().then(() => {
|
||||
return setup().then(({ sendToInstallationSpy }) => {
|
||||
return Parse.Push.send({
|
||||
where: {
|
||||
deviceType: 'ios'
|
||||
@@ -63,8 +81,13 @@ describe('Parse.Push', () => {
|
||||
alert: 'Hello world!'
|
||||
}
|
||||
}, {useMasterKey: true})
|
||||
})
|
||||
.then(() => {
|
||||
.then(() => {
|
||||
return delayPromise(500);
|
||||
})
|
||||
.then(() => {
|
||||
expect(sendToInstallationSpy.calls.count()).toEqual(10);
|
||||
})
|
||||
}).then(() => {
|
||||
done();
|
||||
}).catch((err) => {
|
||||
jfail(err);
|
||||
@@ -83,6 +106,8 @@ describe('Parse.Push', () => {
|
||||
alert: 'Hello world!'
|
||||
}
|
||||
}, {useMasterKey: true})
|
||||
}).then(() => {
|
||||
return delayPromise(500);
|
||||
}).then(() => {
|
||||
done();
|
||||
}).catch((err) => {
|
||||
|
||||
@@ -733,6 +733,40 @@ describe('Parse.ACL', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("acl making an object privately writable (#3194)", (done) => {
|
||||
// Create an object owned by Alice.
|
||||
var object;
|
||||
var user2;
|
||||
var user = new Parse.User();
|
||||
user.set("username", "alice");
|
||||
user.set("password", "wonderland");
|
||||
user.signUp().then(() => {
|
||||
object = new TestObject();
|
||||
var acl = new Parse.ACL(user);
|
||||
acl.setPublicWriteAccess(false);
|
||||
acl.setPublicReadAccess(true);
|
||||
object.setACL(acl);
|
||||
return object.save().then(() => {
|
||||
return Parse.User.logOut();
|
||||
})
|
||||
}).then(() => {
|
||||
user2 = new Parse.User();
|
||||
user2.set("username", "bob");
|
||||
user2.set("password", "burger");
|
||||
return user2.signUp();
|
||||
}).then(() => {
|
||||
console.log(user2.getSessionToken());
|
||||
return object.destroy({sessionToken: user2.getSessionToken() });
|
||||
}).then((res) => {
|
||||
console.log(res);
|
||||
fail('should not be able to destroy the object');
|
||||
done();
|
||||
}, (err) => {
|
||||
console.error(err);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it("acl sharing with another user and get", (done) => {
|
||||
// Sign in as Bob.
|
||||
Parse.User.signUp("bob", "pass", null, {
|
||||
|
||||
+92
-92
@@ -5,7 +5,7 @@
|
||||
var request = require('request');
|
||||
const rp = require('request-promise');
|
||||
const Parse = require("parse/node");
|
||||
let Config = require('../src/Config');
|
||||
const Config = require('../src/Config');
|
||||
const SchemaController = require('../src/Controllers/SchemaController');
|
||||
var TestUtils = require('../src/TestUtils');
|
||||
|
||||
@@ -23,7 +23,7 @@ describe_only_db('mongo')('miscellaneous', () => {
|
||||
obj.set('foo', 'bar');
|
||||
return obj.save();
|
||||
}).then(() => {
|
||||
let config = new Config(appId);
|
||||
const config = new Config(appId);
|
||||
return config.database.adapter.find('TestObject', { fields: {} }, {}, {});
|
||||
}).then((results) => {
|
||||
expect(results.length).toEqual(1);
|
||||
@@ -83,7 +83,7 @@ describe('miscellaneous', function() {
|
||||
it('fail to create a duplicate username', done => {
|
||||
let numCreated = 0;
|
||||
let numFailed = 0;
|
||||
let p1 = createTestUser();
|
||||
const p1 = createTestUser();
|
||||
p1.then(() => {
|
||||
numCreated++;
|
||||
expect(numCreated).toEqual(1);
|
||||
@@ -93,7 +93,7 @@ describe('miscellaneous', function() {
|
||||
expect(numFailed).toEqual(1);
|
||||
expect(error.code).toEqual(Parse.Error.USERNAME_TAKEN);
|
||||
});
|
||||
let p2 = createTestUser();
|
||||
const p2 = createTestUser();
|
||||
p2.then(() => {
|
||||
numCreated++;
|
||||
expect(numCreated).toEqual(1);
|
||||
@@ -114,11 +114,11 @@ describe('miscellaneous', function() {
|
||||
it('ensure that email is uniquely indexed', done => {
|
||||
let numFailed = 0;
|
||||
let numCreated = 0;
|
||||
let user1 = new Parse.User();
|
||||
const user1 = new Parse.User();
|
||||
user1.setPassword('asdf');
|
||||
user1.setUsername('u1');
|
||||
user1.setEmail('dupe@dupe.dupe');
|
||||
let p1 = user1.signUp();
|
||||
const p1 = user1.signUp();
|
||||
p1.then(() => {
|
||||
numCreated++;
|
||||
expect(numCreated).toEqual(1);
|
||||
@@ -128,11 +128,11 @@ describe('miscellaneous', function() {
|
||||
expect(error.code).toEqual(Parse.Error.EMAIL_TAKEN);
|
||||
});
|
||||
|
||||
let user2 = new Parse.User();
|
||||
const user2 = new Parse.User();
|
||||
user2.setPassword('asdf');
|
||||
user2.setUsername('u2');
|
||||
user2.setEmail('dupe@dupe.dupe');
|
||||
let p2 = user2.signUp();
|
||||
const p2 = user2.signUp();
|
||||
p2.then(() => {
|
||||
numCreated++;
|
||||
expect(numCreated).toEqual(1);
|
||||
@@ -151,7 +151,7 @@ describe('miscellaneous', function() {
|
||||
});
|
||||
|
||||
it('ensure that if people already have duplicate users, they can still sign up new users', done => {
|
||||
let config = new Config('test');
|
||||
const config = new Config('test');
|
||||
// Remove existing data to clear out unique index
|
||||
TestUtils.destroyAllDataPermanently()
|
||||
.then(() => config.database.adapter.createClass('_User', userSchema))
|
||||
@@ -161,13 +161,13 @@ describe('miscellaneous', function() {
|
||||
.then(reconfigureServer)
|
||||
.catch(error => {
|
||||
expect(error.code).toEqual(Parse.Error.DUPLICATE_VALUE);
|
||||
let user = new Parse.User();
|
||||
const user = new Parse.User();
|
||||
user.setPassword('asdf');
|
||||
user.setUsername('zxcv');
|
||||
return user.signUp().catch(fail);
|
||||
})
|
||||
.then(() => {
|
||||
let user = new Parse.User();
|
||||
const user = new Parse.User();
|
||||
user.setPassword('asdf');
|
||||
user.setUsername('u');
|
||||
return user.signUp()
|
||||
@@ -183,7 +183,7 @@ describe('miscellaneous', function() {
|
||||
});
|
||||
|
||||
it('ensure that if people already have duplicate emails, they can still sign up new users', done => {
|
||||
let config = new Config('test');
|
||||
const config = new Config('test');
|
||||
// Remove existing data to clear out unique index
|
||||
TestUtils.destroyAllDataPermanently()
|
||||
.then(() => config.database.adapter.createClass('_User', userSchema))
|
||||
@@ -191,14 +191,14 @@ describe('miscellaneous', function() {
|
||||
.then(() => config.database.adapter.createObject('_User', userSchema, { objectId: 'y', email: 'a@b.c' }))
|
||||
.then(reconfigureServer)
|
||||
.catch(() => {
|
||||
let user = new Parse.User();
|
||||
const user = new Parse.User();
|
||||
user.setPassword('asdf');
|
||||
user.setUsername('qqq');
|
||||
user.setEmail('unique@unique.unique');
|
||||
return user.signUp().catch(fail);
|
||||
})
|
||||
.then(() => {
|
||||
let user = new Parse.User();
|
||||
const user = new Parse.User();
|
||||
user.setPassword('asdf');
|
||||
user.setUsername('www');
|
||||
user.setEmail('a@b.c');
|
||||
@@ -211,11 +211,11 @@ describe('miscellaneous', function() {
|
||||
});
|
||||
|
||||
it('ensure that if you try to sign up a user with a unique username and email, but duplicates in some other field that has a uniqueness constraint, you get a regular duplicate value error', done => {
|
||||
let config = new Config('test');
|
||||
const config = new Config('test');
|
||||
config.database.adapter.addFieldIfNotExists('_User', 'randomField', { type: 'String' })
|
||||
.then(() => config.database.adapter.ensureUniqueness('_User', userSchema, ['randomField']))
|
||||
.then(() => {
|
||||
let user = new Parse.User();
|
||||
const user = new Parse.User();
|
||||
user.setPassword('asdf');
|
||||
user.setUsername('1');
|
||||
user.setEmail('1@b.c');
|
||||
@@ -223,7 +223,7 @@ describe('miscellaneous', function() {
|
||||
return user.signUp()
|
||||
})
|
||||
.then(() => {
|
||||
let user = new Parse.User();
|
||||
const user = new Parse.User();
|
||||
user.setPassword('asdf');
|
||||
user.setUsername('2');
|
||||
user.setEmail('2@b.c');
|
||||
@@ -374,7 +374,7 @@ describe('miscellaneous', function() {
|
||||
let triggerTime = 0;
|
||||
// Register a mock beforeSave hook
|
||||
Parse.Cloud.beforeSave('GameScore', (req, res) => {
|
||||
let object = req.object;
|
||||
const object = req.object;
|
||||
expect(object instanceof Parse.Object).toBeTruthy();
|
||||
expect(object.get('fooAgain')).toEqual('barAgain');
|
||||
if (triggerTime == 0) {
|
||||
@@ -397,7 +397,7 @@ describe('miscellaneous', function() {
|
||||
res.success();
|
||||
});
|
||||
|
||||
let obj = new Parse.Object('GameScore');
|
||||
const obj = new Parse.Object('GameScore');
|
||||
obj.set('foo', 'bar');
|
||||
obj.set('fooAgain', 'barAgain');
|
||||
obj.save().then(() => {
|
||||
@@ -417,13 +417,13 @@ describe('miscellaneous', function() {
|
||||
let triggerTime = 0;
|
||||
// Register a mock beforeSave hook
|
||||
Parse.Cloud.beforeSave('GameScore', (req, res) => {
|
||||
let object = req.object;
|
||||
const object = req.object;
|
||||
object.set('foo', 'bar');
|
||||
triggerTime++;
|
||||
res.success(object);
|
||||
});
|
||||
|
||||
let obj = new Parse.Object('GameScore');
|
||||
const obj = new Parse.Object('GameScore');
|
||||
obj.set('foo', 'baz');
|
||||
obj.save().then(() => {
|
||||
expect(triggerTime).toBe(1);
|
||||
@@ -439,10 +439,10 @@ describe('miscellaneous', function() {
|
||||
let triggerTime = 0;
|
||||
// Register a mock beforeSave hook
|
||||
Parse.Cloud.beforeSave('GameScore', (req, res) => {
|
||||
let object = req.object;
|
||||
const object = req.object;
|
||||
expect(object instanceof Parse.Object).toBeTruthy();
|
||||
expect(object.get('fooAgain')).toEqual('barAgain');
|
||||
let originalObject = req.original;
|
||||
const originalObject = req.original;
|
||||
if (triggerTime == 0) {
|
||||
// No id/createdAt/updatedAt
|
||||
expect(object.id).toBeUndefined();
|
||||
@@ -472,7 +472,7 @@ describe('miscellaneous', function() {
|
||||
res.success();
|
||||
});
|
||||
|
||||
let obj = new Parse.Object('GameScore');
|
||||
const obj = new Parse.Object('GameScore');
|
||||
obj.set('foo', 'bar');
|
||||
obj.set('fooAgain', 'barAgain');
|
||||
obj.save().then(() => {
|
||||
@@ -490,13 +490,13 @@ describe('miscellaneous', function() {
|
||||
});
|
||||
|
||||
it('pointer mutation properly saves object', done => {
|
||||
let className = 'GameScore';
|
||||
const className = 'GameScore';
|
||||
|
||||
Parse.Cloud.beforeSave(className, (req, res) => {
|
||||
let object = req.object;
|
||||
const object = req.object;
|
||||
expect(object instanceof Parse.Object).toBeTruthy();
|
||||
|
||||
let child = object.get('child');
|
||||
const child = object.get('child');
|
||||
expect(child instanceof Parse.Object).toBeTruthy();
|
||||
child.set('a', 'b');
|
||||
child.save().then(() => {
|
||||
@@ -504,20 +504,20 @@ describe('miscellaneous', function() {
|
||||
});
|
||||
});
|
||||
|
||||
let obj = new Parse.Object(className);
|
||||
const obj = new Parse.Object(className);
|
||||
obj.set('foo', 'bar');
|
||||
|
||||
let child = new Parse.Object('Child');
|
||||
const child = new Parse.Object('Child');
|
||||
child.save().then(() => {
|
||||
obj.set('child', child);
|
||||
return obj.save();
|
||||
}).then(() => {
|
||||
let query = new Parse.Query(className);
|
||||
const query = new Parse.Query(className);
|
||||
query.include('child');
|
||||
return query.get(obj.id).then(objAgain => {
|
||||
expect(objAgain.get('foo')).toEqual('bar');
|
||||
|
||||
let childAgain = objAgain.get('child');
|
||||
const childAgain = objAgain.get('child');
|
||||
expect(childAgain instanceof Parse.Object).toBeTruthy();
|
||||
expect(childAgain.get('a')).toEqual('b');
|
||||
|
||||
@@ -703,9 +703,9 @@ describe('miscellaneous', function() {
|
||||
var triggerTime = 0;
|
||||
// Register a mock beforeSave hook
|
||||
Parse.Cloud.afterSave('GameScore', function(req, res) {
|
||||
let object = req.object;
|
||||
const object = req.object;
|
||||
expect(object instanceof Parse.Object).toBeTruthy();
|
||||
let originalObject = req.original;
|
||||
const originalObject = req.original;
|
||||
if (triggerTime == 0) {
|
||||
// Create
|
||||
expect(object.get('yolo')).toEqual(1);
|
||||
@@ -740,13 +740,13 @@ describe('miscellaneous', function() {
|
||||
let triggerTime = 0;
|
||||
// Register a mock beforeSave hook
|
||||
Parse.Cloud.beforeSave('GameScore', function(req, res) {
|
||||
let object = req.object;
|
||||
const object = req.object;
|
||||
if (triggerTime == 0) {
|
||||
let acl = object.getACL();
|
||||
const acl = object.getACL();
|
||||
expect(acl.getPublicReadAccess()).toBeTruthy();
|
||||
expect(acl.getPublicWriteAccess()).toBeTruthy();
|
||||
} else if (triggerTime == 1) {
|
||||
let acl = object.getACL();
|
||||
const acl = object.getACL();
|
||||
expect(acl.getPublicReadAccess()).toBeFalsy();
|
||||
expect(acl.getPublicWriteAccess()).toBeTruthy();
|
||||
} else {
|
||||
@@ -756,8 +756,8 @@ describe('miscellaneous', function() {
|
||||
res.success();
|
||||
});
|
||||
|
||||
let obj = new Parse.Object('GameScore');
|
||||
let acl = new Parse.ACL();
|
||||
const obj = new Parse.Object('GameScore');
|
||||
const acl = new Parse.ACL();
|
||||
acl.setPublicReadAccess(true);
|
||||
acl.setPublicWriteAccess(true);
|
||||
obj.setACL(acl);
|
||||
@@ -779,13 +779,13 @@ describe('miscellaneous', function() {
|
||||
let triggerTime = 0;
|
||||
// Register a mock beforeSave hook
|
||||
Parse.Cloud.afterSave('GameScore', function(req, res) {
|
||||
let object = req.object;
|
||||
const object = req.object;
|
||||
if (triggerTime == 0) {
|
||||
let acl = object.getACL();
|
||||
const acl = object.getACL();
|
||||
expect(acl.getPublicReadAccess()).toBeTruthy();
|
||||
expect(acl.getPublicWriteAccess()).toBeTruthy();
|
||||
} else if (triggerTime == 1) {
|
||||
let acl = object.getACL();
|
||||
const acl = object.getACL();
|
||||
expect(acl.getPublicReadAccess()).toBeFalsy();
|
||||
expect(acl.getPublicWriteAccess()).toBeTruthy();
|
||||
} else {
|
||||
@@ -795,8 +795,8 @@ describe('miscellaneous', function() {
|
||||
res.success();
|
||||
});
|
||||
|
||||
let obj = new Parse.Object('GameScore');
|
||||
let acl = new Parse.ACL();
|
||||
const obj = new Parse.Object('GameScore');
|
||||
const acl = new Parse.ACL();
|
||||
acl.setPublicReadAccess(true);
|
||||
acl.setPublicWriteAccess(true);
|
||||
obj.setACL(acl);
|
||||
@@ -815,8 +815,8 @@ describe('miscellaneous', function() {
|
||||
});
|
||||
|
||||
it('should return the updated fields on PUT', done => {
|
||||
let obj = new Parse.Object('GameScore');
|
||||
obj.save({a:'hello', c: 1, d: ['1'], e:['1'], f:['1','2']}).then(( ) => {
|
||||
const obj = new Parse.Object('GameScore');
|
||||
obj.save({a:'hello', c: 1, d: ['1'], e:['1'], f:['1','2']}).then(() => {
|
||||
var headers = {
|
||||
'Content-Type': 'application/json',
|
||||
'X-Parse-Application-Id': 'test',
|
||||
@@ -825,7 +825,7 @@ describe('miscellaneous', function() {
|
||||
};
|
||||
request.put({
|
||||
headers: headers,
|
||||
url: 'http://localhost:8378/1/classes/GameScore/'+obj.id,
|
||||
url: 'http://localhost:8378/1/classes/GameScore/' + obj.id,
|
||||
body: JSON.stringify({
|
||||
a: 'b',
|
||||
c: {"__op":"Increment","amount":2},
|
||||
@@ -1037,7 +1037,7 @@ describe('miscellaneous', function() {
|
||||
});
|
||||
|
||||
it('can handle date params in cloud functions (#2214)', done => {
|
||||
let date = new Date();
|
||||
const date = new Date();
|
||||
Parse.Cloud.define('dateFunc', (request, response) => {
|
||||
expect(request.params.date.__type).toEqual('Date');
|
||||
expect(request.params.date.iso).toEqual(date.toISOString());
|
||||
@@ -1133,27 +1133,27 @@ describe('miscellaneous', function() {
|
||||
});
|
||||
|
||||
it('dedupes an installation properly and returns updatedAt', (done) => {
|
||||
let headers = {
|
||||
const headers = {
|
||||
'Content-Type': 'application/json',
|
||||
'X-Parse-Application-Id': 'test',
|
||||
'X-Parse-REST-API-Key': 'rest'
|
||||
};
|
||||
let data = {
|
||||
const data = {
|
||||
'installationId': 'lkjsahdfkjhsdfkjhsdfkjhsdf',
|
||||
'deviceType': 'embedded'
|
||||
};
|
||||
let requestOptions = {
|
||||
const requestOptions = {
|
||||
headers: headers,
|
||||
url: 'http://localhost:8378/1/installations',
|
||||
body: JSON.stringify(data)
|
||||
};
|
||||
request.post(requestOptions, (error, response, body) => {
|
||||
expect(error).toBe(null);
|
||||
let b = JSON.parse(body);
|
||||
const b = JSON.parse(body);
|
||||
expect(typeof b.objectId).toEqual('string');
|
||||
request.post(requestOptions, (error, response, body) => {
|
||||
expect(error).toBe(null);
|
||||
let b = JSON.parse(body);
|
||||
const b = JSON.parse(body);
|
||||
expect(typeof b.updatedAt).toEqual('string');
|
||||
done();
|
||||
});
|
||||
@@ -1161,17 +1161,17 @@ describe('miscellaneous', function() {
|
||||
});
|
||||
|
||||
it('android login providing empty authData block works', (done) => {
|
||||
let headers = {
|
||||
const headers = {
|
||||
'Content-Type': 'application/json',
|
||||
'X-Parse-Application-Id': 'test',
|
||||
'X-Parse-REST-API-Key': 'rest'
|
||||
};
|
||||
let data = {
|
||||
const data = {
|
||||
username: 'pulse1989',
|
||||
password: 'password1234',
|
||||
authData: {}
|
||||
};
|
||||
let requestOptions = {
|
||||
const requestOptions = {
|
||||
headers: headers,
|
||||
url: 'http://localhost:8378/1/users',
|
||||
body: JSON.stringify(data)
|
||||
@@ -1181,7 +1181,7 @@ describe('miscellaneous', function() {
|
||||
requestOptions.url = 'http://localhost:8378/1/login';
|
||||
request.get(requestOptions, (error, response, body) => {
|
||||
expect(error).toBe(null);
|
||||
let b = JSON.parse(body);
|
||||
const b = JSON.parse(body);
|
||||
expect(typeof b['sessionToken']).toEqual('string');
|
||||
done();
|
||||
});
|
||||
@@ -1189,25 +1189,25 @@ describe('miscellaneous', function() {
|
||||
});
|
||||
|
||||
it('gets relation fields', (done) => {
|
||||
let object = new Parse.Object('AnObject');
|
||||
let relatedObject = new Parse.Object('RelatedObject');
|
||||
const object = new Parse.Object('AnObject');
|
||||
const relatedObject = new Parse.Object('RelatedObject');
|
||||
Parse.Object.saveAll([object, relatedObject]).then(() => {
|
||||
object.relation('related').add(relatedObject);
|
||||
return object.save();
|
||||
}).then(() => {
|
||||
let headers = {
|
||||
const headers = {
|
||||
'Content-Type': 'application/json',
|
||||
'X-Parse-Application-Id': 'test',
|
||||
'X-Parse-REST-API-Key': 'rest'
|
||||
};
|
||||
let requestOptions = {
|
||||
const requestOptions = {
|
||||
headers: headers,
|
||||
url: 'http://localhost:8378/1/classes/AnObject',
|
||||
json: true
|
||||
};
|
||||
request.get(requestOptions, (err, res, body) => {
|
||||
expect(body.results.length).toBe(1);
|
||||
let result = body.results[0];
|
||||
const result = body.results[0];
|
||||
expect(result.related).toEqual({
|
||||
__type: "Relation",
|
||||
className: 'RelatedObject'
|
||||
@@ -1221,27 +1221,27 @@ describe('miscellaneous', function() {
|
||||
});
|
||||
|
||||
it('properly returns incremented values (#1554)', (done) => {
|
||||
let headers = {
|
||||
const headers = {
|
||||
'Content-Type': 'application/json',
|
||||
'X-Parse-Application-Id': 'test',
|
||||
'X-Parse-REST-API-Key': 'rest'
|
||||
};
|
||||
let requestOptions = {
|
||||
const requestOptions = {
|
||||
headers: headers,
|
||||
url: 'http://localhost:8378/1/classes/AnObject',
|
||||
json: true
|
||||
};
|
||||
let object = new Parse.Object('AnObject');
|
||||
const object = new Parse.Object('AnObject');
|
||||
|
||||
function runIncrement(amount) {
|
||||
let options = Object.assign({}, requestOptions, {
|
||||
const options = Object.assign({}, requestOptions, {
|
||||
body: {
|
||||
"key": {
|
||||
__op: 'Increment',
|
||||
amount: amount
|
||||
}
|
||||
},
|
||||
url: 'http://localhost:8378/1/classes/AnObject/'+object.id
|
||||
url: 'http://localhost:8378/1/classes/AnObject/' + object.id
|
||||
})
|
||||
return new Promise((resolve, reject) => {
|
||||
request.put(options, (err, res, body) => {
|
||||
@@ -1266,7 +1266,7 @@ describe('miscellaneous', function() {
|
||||
})
|
||||
|
||||
it('ignores _RevocableSession "header" send by JS SDK', (done) => {
|
||||
let object = new Parse.Object('AnObject');
|
||||
const object = new Parse.Object('AnObject');
|
||||
object.set('a', 'b');
|
||||
object.save().then(() => {
|
||||
request.post({
|
||||
@@ -1285,7 +1285,7 @@ describe('miscellaneous', function() {
|
||||
expect(body.error).toBeUndefined();
|
||||
expect(body.results).not.toBeUndefined();
|
||||
expect(body.results.length).toBe(1);
|
||||
let result = body.results[0];
|
||||
const result = body.results[0];
|
||||
expect(result.a).toBe('b');
|
||||
done();
|
||||
})
|
||||
@@ -1293,7 +1293,7 @@ describe('miscellaneous', function() {
|
||||
});
|
||||
|
||||
it('doesnt convert interior keys of objects that use special names', done => {
|
||||
let obj = new Parse.Object('Obj');
|
||||
const obj = new Parse.Object('Obj');
|
||||
obj.set('val', { createdAt: 'a', updatedAt: 1 });
|
||||
obj.save()
|
||||
.then(obj => new Parse.Query('Obj').get(obj.id))
|
||||
@@ -1361,10 +1361,10 @@ describe('miscellaneous', function() {
|
||||
});
|
||||
|
||||
it('does not change inner objects if the key has the same name as a geopoint field on the class, and the value is an array of length 2, or if the key has the same name as a file field on the class, and the value is a string', done => {
|
||||
let file = new Parse.File('myfile.txt', { base64: 'eAo=' });
|
||||
const file = new Parse.File('myfile.txt', { base64: 'eAo=' });
|
||||
file.save()
|
||||
.then(f => {
|
||||
let obj = new Parse.Object('O');
|
||||
const obj = new Parse.Object('O');
|
||||
obj.set('fileField', f);
|
||||
obj.set('geoField', new Parse.GeoPoint(0, 0));
|
||||
obj.set('innerObj', {
|
||||
@@ -1387,17 +1387,17 @@ describe('miscellaneous', function() {
|
||||
});
|
||||
|
||||
it('purge all objects in class', (done) => {
|
||||
let object = new Parse.Object('TestObject');
|
||||
const object = new Parse.Object('TestObject');
|
||||
object.set('foo', 'bar');
|
||||
let object2 = new Parse.Object('TestObject');
|
||||
const object2 = new Parse.Object('TestObject');
|
||||
object2.set('alice', 'wonderland');
|
||||
Parse.Object.saveAll([object, object2])
|
||||
.then(() => {
|
||||
let query = new Parse.Query(TestObject);
|
||||
const query = new Parse.Query(TestObject);
|
||||
return query.count()
|
||||
}).then((count) => {
|
||||
expect(count).toBe(2);
|
||||
let headers = {
|
||||
const headers = {
|
||||
'Content-Type': 'application/json',
|
||||
'X-Parse-Application-Id': 'test',
|
||||
'X-Parse-Master-Key': 'test'
|
||||
@@ -1408,7 +1408,7 @@ describe('miscellaneous', function() {
|
||||
json: true
|
||||
}, (err) => {
|
||||
expect(err).toBe(null);
|
||||
let query = new Parse.Query(TestObject);
|
||||
const query = new Parse.Query(TestObject);
|
||||
return query.count().then((count) => {
|
||||
expect(count).toBe(0);
|
||||
done();
|
||||
@@ -1418,7 +1418,7 @@ describe('miscellaneous', function() {
|
||||
});
|
||||
|
||||
it('fail on purge all objects in class without master key', (done) => {
|
||||
let headers = {
|
||||
const headers = {
|
||||
'Content-Type': 'application/json',
|
||||
'X-Parse-Application-Id': 'test',
|
||||
'X-Parse-REST-API-Key': 'rest'
|
||||
@@ -1437,7 +1437,7 @@ describe('miscellaneous', function() {
|
||||
});
|
||||
|
||||
it('purge all objects in _Role also purge cache', (done) => {
|
||||
let headers = {
|
||||
const headers = {
|
||||
'Content-Type': 'application/json',
|
||||
'X-Parse-Application-Id': 'test',
|
||||
'X-Parse-Master-Key': 'test'
|
||||
@@ -1445,26 +1445,26 @@ describe('miscellaneous', function() {
|
||||
var user, object;
|
||||
createTestUser().then((x) => {
|
||||
user = x;
|
||||
let acl = new Parse.ACL();
|
||||
const acl = new Parse.ACL();
|
||||
acl.setPublicReadAccess(true);
|
||||
acl.setPublicWriteAccess(false);
|
||||
let role = new Parse.Object('_Role');
|
||||
const role = new Parse.Object('_Role');
|
||||
role.set('name', 'TestRole');
|
||||
role.setACL(acl);
|
||||
let users = role.relation('users');
|
||||
const users = role.relation('users');
|
||||
users.add(user);
|
||||
return role.save({}, { useMasterKey: true });
|
||||
}).then(() => {
|
||||
let query = new Parse.Query('_Role');
|
||||
const query = new Parse.Query('_Role');
|
||||
return query.find({ useMasterKey: true });
|
||||
}).then((x) => {
|
||||
expect(x.length).toEqual(1);
|
||||
let relation = x[0].relation('users').query();
|
||||
const relation = x[0].relation('users').query();
|
||||
return relation.first({ useMasterKey: true });
|
||||
}).then((x) => {
|
||||
expect(x.id).toEqual(user.id);
|
||||
object = new Parse.Object('TestObject');
|
||||
let acl = new Parse.ACL();
|
||||
const acl = new Parse.ACL();
|
||||
acl.setPublicReadAccess(false);
|
||||
acl.setPublicWriteAccess(false);
|
||||
acl.setRoleReadAccess('TestRole', true);
|
||||
@@ -1472,7 +1472,7 @@ describe('miscellaneous', function() {
|
||||
object.setACL(acl);
|
||||
return object.save();
|
||||
}).then(() => {
|
||||
let query = new Parse.Query('TestObject');
|
||||
const query = new Parse.Query('TestObject');
|
||||
return query.find({ sessionToken: user.getSessionToken() });
|
||||
}).then((x) => {
|
||||
expect(x.length).toEqual(1);
|
||||
@@ -1483,7 +1483,7 @@ describe('miscellaneous', function() {
|
||||
json: true
|
||||
});
|
||||
}).then(() => {
|
||||
let query = new Parse.Query('TestObject');
|
||||
const query = new Parse.Query('TestObject');
|
||||
return query.get(object.id, { sessionToken: user.getSessionToken() });
|
||||
}).then(() => {
|
||||
fail('Should not succeed');
|
||||
@@ -1502,7 +1502,7 @@ describe('miscellaneous', function() {
|
||||
response.success();
|
||||
});
|
||||
|
||||
let object = new Parse.Object('MyObject');
|
||||
const object = new Parse.Object('MyObject');
|
||||
object.set('key', 'value');
|
||||
object.save().then(() => {
|
||||
return object.save({'secret': 'should not update schema'});
|
||||
@@ -1520,7 +1520,7 @@ describe('miscellaneous', function() {
|
||||
json: true
|
||||
});
|
||||
}).then((res) => {
|
||||
let fields = res.fields;
|
||||
const fields = res.fields;
|
||||
expect(fields.secret).toBeUndefined();
|
||||
done();
|
||||
}, (err) => {
|
||||
@@ -1532,7 +1532,7 @@ describe('miscellaneous', function() {
|
||||
|
||||
describe_only_db('mongo')('legacy _acl', () => {
|
||||
it('should have _acl when locking down (regression for #2465)', (done) => {
|
||||
let headers = {
|
||||
const headers = {
|
||||
'X-Parse-Application-Id': 'test',
|
||||
'X-Parse-REST-API-Key': 'rest'
|
||||
}
|
||||
@@ -1546,13 +1546,13 @@ describe_only_db('mongo')('legacy _acl', () => {
|
||||
},
|
||||
json: true
|
||||
}).then(() => {
|
||||
let config = new Config('test');
|
||||
let adapter = config.database.adapter;
|
||||
const config = new Config('test');
|
||||
const adapter = config.database.adapter;
|
||||
return adapter._adaptiveCollection("Report")
|
||||
.then(collection => collection.find({}))
|
||||
}).then((results) => {
|
||||
expect(results.length).toBe(1);
|
||||
let result = results[0];
|
||||
const result = results[0];
|
||||
expect(result.name).toEqual('My Report');
|
||||
expect(result._wperm).toEqual([]);
|
||||
expect(result._rperm).toEqual([]);
|
||||
|
||||
@@ -563,7 +563,7 @@ describe('Parse.File testing', () => {
|
||||
var query = new Parse.Query('FileTest');
|
||||
return query.first();
|
||||
}).then(result => {
|
||||
let fileAgain = result.get('file');
|
||||
const fileAgain = result.get('file');
|
||||
expect(fileAgain.url()).toMatch(/123.txt$/);
|
||||
done();
|
||||
}).catch((e) => {
|
||||
@@ -587,7 +587,7 @@ describe('Parse.File testing', () => {
|
||||
var query = new Parse.Query('FileTest');
|
||||
return query.first();
|
||||
}).then(result => {
|
||||
let fileAgain = result.get('file');
|
||||
const fileAgain = result.get('file');
|
||||
expect(fileAgain.url().indexOf('https://mydomain/parse')).toBe(0);
|
||||
done();
|
||||
}).catch((e) => {
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
'use strict';
|
||||
|
||||
var request = require('request');
|
||||
let Config = require('../src/Config');
|
||||
const Config = require('../src/Config');
|
||||
|
||||
describe('a GlobalConfig', () => {
|
||||
beforeEach(done => {
|
||||
let config = new Config('test');
|
||||
let query = on_db('mongo', () => {
|
||||
const config = new Config('test');
|
||||
const query = on_db('mongo', () => {
|
||||
// Legacy is with an int...
|
||||
return { objectId: 1 };
|
||||
}, () => {
|
||||
@@ -56,6 +56,49 @@ describe('a GlobalConfig', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('can add and retrive files', (done) => {
|
||||
request.put({
|
||||
url : 'http://localhost:8378/1/config',
|
||||
json : true,
|
||||
body : { params: { file: { __type: 'File', name: 'name', url: 'http://url' } } },
|
||||
headers: {
|
||||
'X-Parse-Application-Id': 'test',
|
||||
'X-Parse-Master-Key' : 'test'
|
||||
}
|
||||
}, (error, response, body) => {
|
||||
expect(response.statusCode).toEqual(200);
|
||||
expect(body.result).toEqual(true);
|
||||
Parse.Config.get().then((res) => {
|
||||
const file = res.get('file');
|
||||
expect(file.name()).toBe('name');
|
||||
expect(file.url()).toBe('http://url');
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('can add and retrive Geopoints', (done) => {
|
||||
const geopoint = new Parse.GeoPoint(10,-20);
|
||||
request.put({
|
||||
url : 'http://localhost:8378/1/config',
|
||||
json : true,
|
||||
body : { params: { point: geopoint.toJSON() } },
|
||||
headers: {
|
||||
'X-Parse-Application-Id': 'test',
|
||||
'X-Parse-Master-Key' : 'test'
|
||||
}
|
||||
}, (error, response, body) => {
|
||||
expect(response.statusCode).toEqual(200);
|
||||
expect(body.result).toEqual(true);
|
||||
Parse.Config.get().then((res) => {
|
||||
const point = res.get('point');
|
||||
expect(point.latitude).toBe(10);
|
||||
expect(point.longitude).toBe(-20);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('properly handles delete op', (done) => {
|
||||
request.put({
|
||||
url : 'http://localhost:8378/1/config',
|
||||
@@ -104,7 +147,7 @@ describe('a GlobalConfig', () => {
|
||||
});
|
||||
|
||||
it('failed getting config when it is missing', (done) => {
|
||||
let config = new Config('test');
|
||||
const config = new Config('test');
|
||||
config.database.adapter.deleteObjectsByQuery(
|
||||
'_GlobalConfig',
|
||||
{ fields: { params: { __type: 'String' } } },
|
||||
|
||||
+40
-39
@@ -7,8 +7,8 @@ var express = require("express");
|
||||
var bodyParser = require('body-parser');
|
||||
|
||||
var port = 12345;
|
||||
var hookServerURL = "http://localhost:"+port;
|
||||
let AppCache = require('../src/cache').AppCache;
|
||||
var hookServerURL = "http://localhost:" + port;
|
||||
const AppCache = require('../src/cache').AppCache;
|
||||
|
||||
var app = express();
|
||||
app.use(bodyParser.json({ 'type': '*/*' }))
|
||||
@@ -26,7 +26,7 @@ describe('Hooks', () => {
|
||||
});
|
||||
|
||||
it("should have no triggers registered", (done) => {
|
||||
Parse.Hooks.getTriggers().then( (res) => {
|
||||
Parse.Hooks.getTriggers().then((res) => {
|
||||
expect(res.constructor).toBe(Array.prototype.constructor);
|
||||
done();
|
||||
}, (err) => {
|
||||
@@ -129,7 +129,7 @@ describe('Hooks', () => {
|
||||
});
|
||||
|
||||
it("should fail to register hooks without Master Key", (done) => {
|
||||
request.post(Parse.serverURL+"/hooks/functions", {
|
||||
request.post(Parse.serverURL + "/hooks/functions", {
|
||||
headers: {
|
||||
"X-Parse-Application-Id": Parse.applicationId,
|
||||
"X-Parse-REST-API-Key": Parse.restKey,
|
||||
@@ -143,11 +143,13 @@ describe('Hooks', () => {
|
||||
});
|
||||
|
||||
it("should fail trying to create two times the same function", (done) => {
|
||||
Parse.Hooks.createFunction("my_new_function", "http://url.com").then( () => {
|
||||
Parse.Hooks.createFunction("my_new_function", "http://url.com")
|
||||
.then(() => new Promise(resolve => setTimeout(resolve, 100)))
|
||||
.then(() => {
|
||||
return Parse.Hooks.createFunction("my_new_function", "http://url.com")
|
||||
}, () => {
|
||||
fail("should create a new function");
|
||||
}).then( () => {
|
||||
}).then(() => {
|
||||
fail("should not be able to create the same function");
|
||||
}, (err) => {
|
||||
expect(err).not.toBe(undefined);
|
||||
@@ -166,11 +168,11 @@ describe('Hooks', () => {
|
||||
});
|
||||
|
||||
it("should fail trying to create two times the same trigger", (done) => {
|
||||
Parse.Hooks.createTrigger("MyClass", "beforeSave", "http://url.com").then( () => {
|
||||
Parse.Hooks.createTrigger("MyClass", "beforeSave", "http://url.com").then(() => {
|
||||
return Parse.Hooks.createTrigger("MyClass", "beforeSave", "http://url.com")
|
||||
}, () => {
|
||||
fail("should create a new trigger");
|
||||
}).then( () => {
|
||||
}).then(() => {
|
||||
fail("should not be able to create the same trigger");
|
||||
}, (err) => {
|
||||
expect(err).not.toBe(undefined);
|
||||
@@ -189,7 +191,7 @@ describe('Hooks', () => {
|
||||
});
|
||||
|
||||
it("should fail trying to update a function that don't exist", (done) => {
|
||||
Parse.Hooks.updateFunction("A_COOL_FUNCTION", "http://url.com").then( () => {
|
||||
Parse.Hooks.updateFunction("A_COOL_FUNCTION", "http://url.com").then(() => {
|
||||
fail("Should not succeed")
|
||||
}, (err) => {
|
||||
expect(err).not.toBe(undefined);
|
||||
@@ -214,7 +216,7 @@ describe('Hooks', () => {
|
||||
});
|
||||
|
||||
it("should fail trying to update a trigger that don't exist", (done) => {
|
||||
Parse.Hooks.updateTrigger("AClassName","beforeSave", "http://url.com").then( () => {
|
||||
Parse.Hooks.updateTrigger("AClassName","beforeSave", "http://url.com").then(() => {
|
||||
fail("Should not succeed")
|
||||
}, (err) => {
|
||||
expect(err).not.toBe(undefined);
|
||||
@@ -240,7 +242,7 @@ describe('Hooks', () => {
|
||||
|
||||
|
||||
it("should fail trying to create a malformed function", (done) => {
|
||||
Parse.Hooks.createFunction("MyFunction").then( (res) => {
|
||||
Parse.Hooks.createFunction("MyFunction").then((res) => {
|
||||
fail(res);
|
||||
}, (err) => {
|
||||
expect(err).not.toBe(undefined);
|
||||
@@ -254,7 +256,7 @@ describe('Hooks', () => {
|
||||
});
|
||||
|
||||
it("should fail trying to create a malformed function (REST)", (done) => {
|
||||
request.post(Parse.serverURL+"/hooks/functions", {
|
||||
request.post(Parse.serverURL + "/hooks/functions", {
|
||||
headers: {
|
||||
"X-Parse-Application-Id": Parse.applicationId,
|
||||
"X-Parse-Master-Key": Parse.masterKey,
|
||||
@@ -272,18 +274,18 @@ describe('Hooks', () => {
|
||||
it("should create hooks and properly preload them", (done) => {
|
||||
|
||||
var promises = [];
|
||||
for (var i = 0; i<5; i++) {
|
||||
promises.push(Parse.Hooks.createTrigger("MyClass"+i, "beforeSave", "http://url.com/beforeSave/"+i));
|
||||
promises.push(Parse.Hooks.createFunction("AFunction"+i, "http://url.com/function"+i));
|
||||
for (var i = 0; i < 5; i++) {
|
||||
promises.push(Parse.Hooks.createTrigger("MyClass" + i, "beforeSave", "http://url.com/beforeSave/" + i));
|
||||
promises.push(Parse.Hooks.createFunction("AFunction" + i, "http://url.com/function" + i));
|
||||
}
|
||||
|
||||
Parse.Promise.when(promises).then(function(){
|
||||
for (var i=0; i<5; i++) {
|
||||
for (var i = 0; i < 5; i++) {
|
||||
// Delete everything from memory, as the server just started
|
||||
triggers.removeTrigger("beforeSave", "MyClass"+i, Parse.applicationId);
|
||||
triggers.removeFunction("AFunction"+i, Parse.applicationId);
|
||||
expect(triggers.getTrigger("MyClass"+i, "beforeSave", Parse.applicationId)).toBeUndefined();
|
||||
expect(triggers.getFunction("AFunction"+i, Parse.applicationId)).toBeUndefined();
|
||||
triggers.removeTrigger("beforeSave", "MyClass" + i, Parse.applicationId);
|
||||
triggers.removeFunction("AFunction" + i, Parse.applicationId);
|
||||
expect(triggers.getTrigger("MyClass" + i, "beforeSave", Parse.applicationId)).toBeUndefined();
|
||||
expect(triggers.getFunction("AFunction" + i, Parse.applicationId)).toBeUndefined();
|
||||
}
|
||||
const hooksController = new HooksController(Parse.applicationId, AppCache.get('test').databaseController);
|
||||
return hooksController.load()
|
||||
@@ -292,9 +294,9 @@ describe('Hooks', () => {
|
||||
fail('Should properly create all hooks');
|
||||
done();
|
||||
}).then(function() {
|
||||
for (var i=0; i<5; i++) {
|
||||
expect(triggers.getTrigger("MyClass"+i, "beforeSave", Parse.applicationId)).not.toBeUndefined();
|
||||
expect(triggers.getFunction("AFunction"+i, Parse.applicationId)).not.toBeUndefined();
|
||||
for (var i = 0; i < 5; i++) {
|
||||
expect(triggers.getTrigger("MyClass" + i, "beforeSave", Parse.applicationId)).not.toBeUndefined();
|
||||
expect(triggers.getFunction("AFunction" + i, Parse.applicationId)).not.toBeUndefined();
|
||||
}
|
||||
done();
|
||||
}, (err) => {
|
||||
@@ -310,7 +312,7 @@ describe('Hooks', () => {
|
||||
res.json({success:"OK!"});
|
||||
});
|
||||
|
||||
Parse.Hooks.createFunction("SOME_TEST_FUNCTION", hookServerURL+"/SomeFunction").then(function(){
|
||||
Parse.Hooks.createFunction("SOME_TEST_FUNCTION", hookServerURL + "/SomeFunction").then(function(){
|
||||
return Parse.Cloud.run("SOME_TEST_FUNCTION")
|
||||
}, (err) => {
|
||||
jfail(err);
|
||||
@@ -332,7 +334,7 @@ describe('Hooks', () => {
|
||||
res.json({error: {code: 1337, error: "hacking that one!"}});
|
||||
});
|
||||
// The function is deleted as the DB is dropped between calls
|
||||
Parse.Hooks.createFunction("SOME_TEST_FUNCTION", hookServerURL+"/SomeFunctionError").then(function(){
|
||||
Parse.Hooks.createFunction("SOME_TEST_FUNCTION", hookServerURL + "/SomeFunctionError").then(function(){
|
||||
return Parse.Cloud.run("SOME_TEST_FUNCTION")
|
||||
}, (err) => {
|
||||
jfail(err);
|
||||
@@ -362,7 +364,7 @@ describe('Hooks', () => {
|
||||
}
|
||||
});
|
||||
|
||||
Parse.Hooks.createFunction("SOME_TEST_FUNCTION", hookServerURL+"/ExpectingKey").then(function(){
|
||||
Parse.Hooks.createFunction("SOME_TEST_FUNCTION", hookServerURL + "/ExpectingKey").then(function(){
|
||||
return Parse.Cloud.run("SOME_TEST_FUNCTION")
|
||||
}, (err) => {
|
||||
jfail(err);
|
||||
@@ -389,7 +391,7 @@ describe('Hooks', () => {
|
||||
}
|
||||
});
|
||||
|
||||
Parse.Hooks.createFunction("SOME_TEST_FUNCTION", hookServerURL+"/ExpectingKeyAlso").then(function(){
|
||||
Parse.Hooks.createFunction("SOME_TEST_FUNCTION", hookServerURL + "/ExpectingKeyAlso").then(function(){
|
||||
return Parse.Cloud.run("SOME_TEST_FUNCTION")
|
||||
}, (err) => {
|
||||
jfail(err);
|
||||
@@ -421,8 +423,8 @@ describe('Hooks', () => {
|
||||
// But this should override the key upon return
|
||||
res.json({success: object});
|
||||
});
|
||||
// The function is delete as the DB is dropped between calls
|
||||
Parse.Hooks.createTrigger("SomeRandomObject", "beforeSave" ,hookServerURL+"/BeforeSaveSome").then(function(){
|
||||
// The function is deleted as the DB is dropped between calls
|
||||
Parse.Hooks.createTrigger("SomeRandomObject", "beforeSave", hookServerURL + "/BeforeSaveSome").then(function () {
|
||||
const obj = new Parse.Object("SomeRandomObject");
|
||||
return obj.save();
|
||||
}).then(function(res) {
|
||||
@@ -444,7 +446,7 @@ describe('Hooks', () => {
|
||||
object.set('hello', "world");
|
||||
res.json({success: object});
|
||||
});
|
||||
Parse.Hooks.createTrigger("SomeRandomObject2", "beforeSave" ,hookServerURL+"/BeforeSaveSome2").then(function(){
|
||||
Parse.Hooks.createTrigger("SomeRandomObject2", "beforeSave", hookServerURL + "/BeforeSaveSome2").then(function(){
|
||||
const obj = new Parse.Object("SomeRandomObject2");
|
||||
return obj.save();
|
||||
}).then(function(res) {
|
||||
@@ -470,20 +472,19 @@ describe('Hooks', () => {
|
||||
res.json({success: {}});
|
||||
})
|
||||
});
|
||||
// The function is delete as the DB is dropped between calls
|
||||
Parse.Hooks.createTrigger("SomeRandomObject", "afterSave" ,hookServerURL+"/AfterSaveSome").then(function(){
|
||||
// The function is deleted as the DB is dropped between calls
|
||||
Parse.Hooks.createTrigger("SomeRandomObject", "afterSave", hookServerURL + "/AfterSaveSome").then(function(){
|
||||
const obj = new Parse.Object("SomeRandomObject");
|
||||
return obj.save();
|
||||
}).then(function() {
|
||||
var promise = new Parse.Promise();
|
||||
// Wait a bit here as it's an after save
|
||||
setTimeout(function(){
|
||||
// Wait a bit here as it's an after save
|
||||
setTimeout(() => {
|
||||
expect(triggerCount).toBe(1);
|
||||
var q = new Parse.Query("AnotherObject");
|
||||
q.get(newObjectId).then(function(r){
|
||||
promise.resolve(r);
|
||||
});
|
||||
}, 300)
|
||||
new Parse.Query("AnotherObject")
|
||||
.get(newObjectId)
|
||||
.then((r) => promise.resolve(r));
|
||||
}, 500);
|
||||
return promise;
|
||||
}).then(function(res){
|
||||
expect(res.get("foo")).toEqual("bar");
|
||||
|
||||
@@ -2,15 +2,19 @@
|
||||
// These tests check the Installations functionality of the REST API.
|
||||
// Ported from installation_collection_test.go
|
||||
|
||||
let auth = require('../src/Auth');
|
||||
let Config = require('../src/Config');
|
||||
let Parse = require('parse/node').Parse;
|
||||
let rest = require('../src/rest');
|
||||
let request = require("request");
|
||||
const auth = require('../src/Auth');
|
||||
const Config = require('../src/Config');
|
||||
const Parse = require('parse/node').Parse;
|
||||
const rest = require('../src/rest');
|
||||
const request = require("request");
|
||||
|
||||
let config;
|
||||
let database;
|
||||
let defaultColumns = require('../src/Controllers/SchemaController').defaultColumns;
|
||||
const defaultColumns = require('../src/Controllers/SchemaController').defaultColumns;
|
||||
|
||||
const delay = function delay(delay) {
|
||||
return new Promise(resolve => setTimeout(resolve, delay));
|
||||
}
|
||||
|
||||
const installationSchema = { fields: Object.assign({}, defaultColumns._Default, defaultColumns._Installation) };
|
||||
|
||||
@@ -130,7 +134,7 @@ describe('Installations', () => {
|
||||
};
|
||||
rest.create(config, auth.nobody(config), '_Installation', input)
|
||||
.then(() => {
|
||||
let query = new Parse.Query(Parse.Installation);
|
||||
const query = new Parse.Query(Parse.Installation);
|
||||
return query.find()
|
||||
}).then(() => {
|
||||
fail('Should not succeed!');
|
||||
@@ -151,7 +155,7 @@ describe('Installations', () => {
|
||||
};
|
||||
rest.create(config, auth.nobody(config), '_Installation', input)
|
||||
.then(() => {
|
||||
let query = new Parse.Query(Parse.Installation);
|
||||
const query = new Parse.Query(Parse.Installation);
|
||||
return query.find({useMasterKey: true});
|
||||
}).then((results) => {
|
||||
expect(results.length).toEqual(1);
|
||||
@@ -288,9 +292,9 @@ describe('Installations', () => {
|
||||
expect(results.length).toEqual(1);
|
||||
expect(results[0]['_id']).toEqual(secondObject._id);
|
||||
done();
|
||||
}).catch((error) => {
|
||||
jfail(error);
|
||||
done();
|
||||
}).catch((error) => {
|
||||
jfail(error);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -542,12 +546,14 @@ describe('Installations', () => {
|
||||
};
|
||||
return rest.create(config, auth.nobody(config), '_Installation', input);
|
||||
})
|
||||
.then(() => delay(100))
|
||||
.then(() => database.adapter.find('_Installation', installationSchema, {installationId: installId1}, {}))
|
||||
.then((results) => {
|
||||
expect(results.length).toEqual(1);
|
||||
firstObject = results[0];
|
||||
return database.adapter.find('_Installation', installationSchema, {installationId: installId2}, {});
|
||||
})
|
||||
.then(() => delay(100))
|
||||
.then(() => database.adapter.find('_Installation', installationSchema, {installationId: installId2}, {}))
|
||||
.then(results => {
|
||||
expect(results.length).toEqual(1);
|
||||
secondObject = results[0];
|
||||
@@ -558,6 +564,7 @@ describe('Installations', () => {
|
||||
};
|
||||
return rest.update(config, auth.nobody(config), '_Installation', secondObject.objectId, input);
|
||||
})
|
||||
.then(() => delay(100))
|
||||
.then(() => database.adapter.find('_Installation', installationSchema, {objectId: firstObject.objectId}, {}))
|
||||
.then(results => {
|
||||
// The first object should have been deleted
|
||||
@@ -842,15 +849,15 @@ describe('Installations', () => {
|
||||
});
|
||||
|
||||
it('allows you to get your own installation (regression test for #1718)', done => {
|
||||
let installId = '12345678-abcd-abcd-abcd-123456789abc';
|
||||
let device = 'android';
|
||||
let input = {
|
||||
const installId = '12345678-abcd-abcd-abcd-123456789abc';
|
||||
const device = 'android';
|
||||
const input = {
|
||||
'installationId': installId,
|
||||
'deviceType': device
|
||||
};
|
||||
rest.create(config, auth.nobody(config), '_Installation', input)
|
||||
.then(createResult => {
|
||||
let headers = {
|
||||
const headers = {
|
||||
'X-Parse-Application-Id': 'test',
|
||||
'X-Parse-REST-API-Key': 'rest',
|
||||
};
|
||||
@@ -871,15 +878,15 @@ describe('Installations', () => {
|
||||
});
|
||||
|
||||
it('allows you to update installation from header (#2090)', done => {
|
||||
let installId = '12345678-abcd-abcd-abcd-123456789abc';
|
||||
let device = 'android';
|
||||
let input = {
|
||||
const installId = '12345678-abcd-abcd-abcd-123456789abc';
|
||||
const device = 'android';
|
||||
const input = {
|
||||
'installationId': installId,
|
||||
'deviceType': device
|
||||
};
|
||||
rest.create(config, auth.nobody(config), '_Installation', input)
|
||||
.then(() => {
|
||||
let headers = {
|
||||
const headers = {
|
||||
'X-Parse-Application-Id': 'test',
|
||||
'X-Parse-REST-API-Key': 'rest',
|
||||
'X-Parse-Installation-Id': installId
|
||||
@@ -905,15 +912,15 @@ describe('Installations', () => {
|
||||
});
|
||||
|
||||
it('allows you to update installation with masterKey', done => {
|
||||
let installId = '12345678-abcd-abcd-abcd-123456789abc';
|
||||
let device = 'android';
|
||||
let input = {
|
||||
const installId = '12345678-abcd-abcd-abcd-123456789abc';
|
||||
const device = 'android';
|
||||
const input = {
|
||||
'installationId': installId,
|
||||
'deviceType': device
|
||||
};
|
||||
rest.create(config, auth.nobody(config), '_Installation', input)
|
||||
.then(createResult => {
|
||||
let installationObj = Parse.Installation.createWithoutData(createResult.response.objectId);
|
||||
const installationObj = Parse.Installation.createWithoutData(createResult.response.objectId);
|
||||
installationObj.set('customField', 'custom value');
|
||||
return installationObj.save(null, {useMasterKey: true});
|
||||
}).then(updateResult => {
|
||||
@@ -928,14 +935,14 @@ describe('Installations', () => {
|
||||
});
|
||||
|
||||
it('should properly handle installation save #2780', done => {
|
||||
let installId = '12345678-abcd-abcd-abcd-123456789abc';
|
||||
let device = 'android';
|
||||
let input = {
|
||||
const installId = '12345678-abcd-abcd-abcd-123456789abc';
|
||||
const device = 'android';
|
||||
const input = {
|
||||
'installationId': installId,
|
||||
'deviceType': device
|
||||
};
|
||||
rest.create(config, auth.nobody(config), '_Installation', input).then(() => {
|
||||
let query = new Parse.Query(Parse.Installation);
|
||||
const query = new Parse.Query(Parse.Installation);
|
||||
query.equalTo('installationId', installId);
|
||||
query.first({useMasterKey: true}).then((installation) => {
|
||||
return installation.save({
|
||||
@@ -951,14 +958,14 @@ describe('Installations', () => {
|
||||
});
|
||||
|
||||
it('should properly reject updating installationId', done => {
|
||||
let installId = '12345678-abcd-abcd-abcd-123456789abc';
|
||||
let device = 'android';
|
||||
let input = {
|
||||
const installId = '12345678-abcd-abcd-abcd-123456789abc';
|
||||
const device = 'android';
|
||||
const input = {
|
||||
'installationId': installId,
|
||||
'deviceType': device
|
||||
};
|
||||
rest.create(config, auth.nobody(config), '_Installation', input).then(() => {
|
||||
let query = new Parse.Query(Parse.Installation);
|
||||
const query = new Parse.Query(Parse.Installation);
|
||||
query.equalTo('installationId', installId);
|
||||
query.first({useMasterKey: true}).then((installation) => {
|
||||
return installation.save({
|
||||
|
||||
@@ -358,7 +358,7 @@ describe('ParseLiveQueryServer', function() {
|
||||
expect(args[0]).toBe(parseWebSocket);
|
||||
expect(JSON.stringify(args[1])).toBe(updateRequest);
|
||||
expect(parseLiveQueryServer._handleUnsubscribe).toHaveBeenCalled();
|
||||
let unsubArgs = parseLiveQueryServer._handleUnsubscribe.calls.mostRecent().args;
|
||||
const unsubArgs = parseLiveQueryServer._handleUnsubscribe.calls.mostRecent().args;
|
||||
expect(unsubArgs.length).toBe(3);
|
||||
expect(unsubArgs[2]).toBe(false);
|
||||
expect(parseLiveQueryServer._handleSubscribe).toHaveBeenCalled();
|
||||
@@ -928,7 +928,7 @@ describe('ParseLiveQueryServer', function() {
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
parseLiveQueryServer._matchesACL(acl, client, requestId).then(function(isMatched) {
|
||||
expect(isMatched).toBe(false);
|
||||
done();
|
||||
|
||||
+35
-35
@@ -596,8 +596,8 @@ describe('Parse.Object testing', () => {
|
||||
var query = new Parse.Query('X');
|
||||
return query.get(x1.id);
|
||||
}).then((x3) => {
|
||||
let stuff = x3.get('stuff');
|
||||
let expected = [1, 2, 4];
|
||||
const stuff = x3.get('stuff');
|
||||
const expected = [1, 2, 4];
|
||||
expect(stuff.length).toBe(expected.length);
|
||||
for (var i of stuff) {
|
||||
expect(expected.indexOf(i) >= 0).toBe(true);
|
||||
@@ -628,12 +628,12 @@ describe('Parse.Object testing', () => {
|
||||
var query = new Parse.Query('X');
|
||||
return query.get(x1.id);
|
||||
}).then((x3) => {
|
||||
let stuff = x3.get('stuff');
|
||||
let target = [1, {'hello': 'world'}, {'foo': 'bar'}, {'bar': 'baz'}];
|
||||
const stuff = x3.get('stuff');
|
||||
const target = [1, {'hello': 'world'}, {'foo': 'bar'}, {'bar': 'baz'}];
|
||||
expect(stuff.length).toEqual(target.length);
|
||||
let found = 0;
|
||||
for (let thing in target) {
|
||||
for (let st in stuff) {
|
||||
for (const thing in target) {
|
||||
for (const st in stuff) {
|
||||
if (st == thing) {
|
||||
found++;
|
||||
}
|
||||
@@ -1390,7 +1390,7 @@ describe('Parse.Object testing', () => {
|
||||
}
|
||||
equal(itemsAgain.length, numItems, "Should get the array back");
|
||||
itemsAgain.forEach(function(item, i) {
|
||||
var newValue = i*2;
|
||||
var newValue = i * 2;
|
||||
item.set("x", newValue);
|
||||
});
|
||||
return Parse.Object.saveAll(itemsAgain);
|
||||
@@ -1400,7 +1400,7 @@ describe('Parse.Object testing', () => {
|
||||
equal(fetchedItemsAgain.length, numItems,
|
||||
"Number of items fetched should not change");
|
||||
fetchedItemsAgain.forEach(function(item, i) {
|
||||
equal(item.get("x"), i*2);
|
||||
equal(item.get("x"), i * 2);
|
||||
});
|
||||
done();
|
||||
});
|
||||
@@ -1457,7 +1457,7 @@ describe('Parse.Object testing', () => {
|
||||
}
|
||||
equal(itemsAgain.length, numItems, "Should get the array back");
|
||||
itemsAgain.forEach(function(item, i) {
|
||||
var newValue = i*2;
|
||||
var newValue = i * 2;
|
||||
item.set("x", newValue);
|
||||
});
|
||||
return Parse.Object.saveAll(itemsAgain);
|
||||
@@ -1467,7 +1467,7 @@ describe('Parse.Object testing', () => {
|
||||
equal(fetchedItemsAgain.length, numItems,
|
||||
"Number of items fetched should not change");
|
||||
fetchedItemsAgain.forEach(function(item, i) {
|
||||
equal(item.get("x"), i*2);
|
||||
equal(item.get("x"), i * 2);
|
||||
});
|
||||
done();
|
||||
},
|
||||
@@ -1581,7 +1581,7 @@ describe('Parse.Object testing', () => {
|
||||
return;
|
||||
}
|
||||
itemsAgain.forEach(function(item, i) {
|
||||
item.set("x", i*2);
|
||||
item.set("x", i * 2);
|
||||
});
|
||||
return Parse.Object.saveAll(itemsAgain);
|
||||
}).then(function() {
|
||||
@@ -1619,7 +1619,7 @@ describe('Parse.Object testing', () => {
|
||||
return;
|
||||
}
|
||||
itemsAgain.forEach(function(item, i) {
|
||||
item.set("x", i*2);
|
||||
item.set("x", i * 2);
|
||||
});
|
||||
return Parse.Object.saveAll(itemsAgain);
|
||||
}).then(function() {
|
||||
@@ -1842,10 +1842,10 @@ describe('Parse.Object testing', () => {
|
||||
"_nested": "key"
|
||||
}
|
||||
});
|
||||
object.save().then( res => {
|
||||
object.save().then(res => {
|
||||
ok(res);
|
||||
return res.fetch();
|
||||
}).then( res => {
|
||||
}).then(res => {
|
||||
const foo = res.get("foo");
|
||||
expect(foo["_bar"]).toEqual("_");
|
||||
expect(foo["baz_bar"]).toEqual(1);
|
||||
@@ -1853,7 +1853,7 @@ describe('Parse.Object testing', () => {
|
||||
expect(foo["_0"]).toEqual("underscore_zero");
|
||||
expect(foo["_more"]["_nested"]).toEqual("key");
|
||||
done();
|
||||
}).fail( err => {
|
||||
}).fail(err => {
|
||||
jfail(err);
|
||||
fail("should not fail");
|
||||
done();
|
||||
@@ -1861,15 +1861,15 @@ describe('Parse.Object testing', () => {
|
||||
});
|
||||
|
||||
it('should have undefined includes when object is missing', (done) => {
|
||||
let obj1 = new Parse.Object("AnObject");
|
||||
let obj2 = new Parse.Object("AnObject");
|
||||
const obj1 = new Parse.Object("AnObject");
|
||||
const obj2 = new Parse.Object("AnObject");
|
||||
|
||||
Parse.Object.saveAll([obj1, obj2]).then(() => {
|
||||
obj1.set("obj", obj2);
|
||||
// Save the pointer, delete the pointee
|
||||
return obj1.save().then(() => { return obj2.destroy() });
|
||||
}).then(() => {
|
||||
let query = new Parse.Query("AnObject");
|
||||
const query = new Parse.Query("AnObject");
|
||||
query.include("obj");
|
||||
return query.find();
|
||||
}).then((res) => {
|
||||
@@ -1877,7 +1877,7 @@ describe('Parse.Object testing', () => {
|
||||
if (res[0]) {
|
||||
expect(res[0].get("obj")).toBe(undefined);
|
||||
}
|
||||
let query = new Parse.Query("AnObject");
|
||||
const query = new Parse.Query("AnObject");
|
||||
return query.find();
|
||||
}).then((res) => {
|
||||
expect(res.length).toBe(1);
|
||||
@@ -1896,16 +1896,16 @@ describe('Parse.Object testing', () => {
|
||||
});
|
||||
|
||||
it('should have undefined includes when object is missing on deeper path', (done) => {
|
||||
let obj1 = new Parse.Object("AnObject");
|
||||
let obj2 = new Parse.Object("AnObject");
|
||||
let obj3 = new Parse.Object("AnObject");
|
||||
const obj1 = new Parse.Object("AnObject");
|
||||
const obj2 = new Parse.Object("AnObject");
|
||||
const obj3 = new Parse.Object("AnObject");
|
||||
Parse.Object.saveAll([obj1, obj2, obj3]).then(() => {
|
||||
obj1.set("obj", obj2);
|
||||
obj2.set("obj", obj3);
|
||||
// Save the pointer, delete the pointee
|
||||
return Parse.Object.saveAll([obj1, obj2]).then(() => { return obj3.destroy() });
|
||||
}).then(() => {
|
||||
let query = new Parse.Query("AnObject");
|
||||
const query = new Parse.Query("AnObject");
|
||||
query.include("obj.obj");
|
||||
return query.get(obj1.id);
|
||||
}).then((res) => {
|
||||
@@ -1919,9 +1919,9 @@ describe('Parse.Object testing', () => {
|
||||
});
|
||||
|
||||
it('should handle includes on null arrays #2752', (done) => {
|
||||
let obj1 = new Parse.Object("AnObject");
|
||||
let obj2 = new Parse.Object("AnotherObject");
|
||||
let obj3 = new Parse.Object("NestedObject");
|
||||
const obj1 = new Parse.Object("AnObject");
|
||||
const obj2 = new Parse.Object("AnotherObject");
|
||||
const obj3 = new Parse.Object("NestedObject");
|
||||
obj3.set({
|
||||
"foo": "bar"
|
||||
})
|
||||
@@ -1933,13 +1933,13 @@ describe('Parse.Object testing', () => {
|
||||
obj1.set("objects", [null, null, obj2]);
|
||||
return obj1.save();
|
||||
}).then(() => {
|
||||
let query = new Parse.Query("AnObject");
|
||||
const query = new Parse.Query("AnObject");
|
||||
query.include("objects.key");
|
||||
return query.find();
|
||||
}).then((res) => {
|
||||
let obj = res[0];
|
||||
const obj = res[0];
|
||||
expect(obj.get("objects")).not.toBe(undefined);
|
||||
let array = obj.get("objects");
|
||||
const array = obj.get("objects");
|
||||
expect(Array.isArray(array)).toBe(true);
|
||||
expect(array[0]).toBe(null);
|
||||
expect(array[1]).toBe(null);
|
||||
@@ -1952,8 +1952,8 @@ describe('Parse.Object testing', () => {
|
||||
});
|
||||
|
||||
it('should handle select and include #2786', (done) => {
|
||||
let score = new Parse.Object("GameScore");
|
||||
let player = new Parse.Object("Player");
|
||||
const score = new Parse.Object("GameScore");
|
||||
const player = new Parse.Object("Player");
|
||||
score.set({
|
||||
"score": 1234
|
||||
});
|
||||
@@ -1963,14 +1963,14 @@ describe('Parse.Object testing', () => {
|
||||
player.set("other", "value");
|
||||
return player.save();
|
||||
}).then(() => {
|
||||
let query = new Parse.Query("Player");
|
||||
const query = new Parse.Query("Player");
|
||||
query.include("gameScore");
|
||||
query.select("gameScore");
|
||||
return query.find();
|
||||
}).then((res) => {
|
||||
let obj = res[0];
|
||||
let gameScore = obj.get("gameScore");
|
||||
let other = obj.get("other");
|
||||
const obj = res[0];
|
||||
const gameScore = obj.get("gameScore");
|
||||
const other = obj.get("other");
|
||||
expect(other).toBeUndefined();
|
||||
expect(gameScore).not.toBeUndefined();
|
||||
expect(gameScore.get("score")).toBe(1234);
|
||||
|
||||
@@ -59,7 +59,7 @@ describe('ParsePubSub', function() {
|
||||
});
|
||||
|
||||
it('can create publisher/sub with custom adapter', function() {
|
||||
let adapter = {
|
||||
const adapter = {
|
||||
createPublisher: jasmine.createSpy('createPublisher'),
|
||||
createSubscriber: jasmine.createSpy('createSubscriber')
|
||||
}
|
||||
@@ -82,7 +82,7 @@ describe('ParsePubSub', function() {
|
||||
});
|
||||
|
||||
it('can create publisher/sub with custom function adapter', function() {
|
||||
let adapter = {
|
||||
const adapter = {
|
||||
createPublisher: jasmine.createSpy('createPublisher'),
|
||||
createSubscriber: jasmine.createSpy('createSubscriber')
|
||||
}
|
||||
|
||||
+122
-52
@@ -114,7 +114,7 @@ describe('Parse.Query testing', () => {
|
||||
// Only cake3 is liked only by user1
|
||||
return query.find().then(function(results){
|
||||
equal(results.length, 1);
|
||||
let cake = results[0];
|
||||
const cake = results[0];
|
||||
expect(cake.id).toBe(cake3.id);
|
||||
});
|
||||
}).then(function(){
|
||||
@@ -816,7 +816,7 @@ describe('Parse.Query testing', () => {
|
||||
var makeBoxedNumber = function(i) {
|
||||
return new BoxedNumber({ number: i });
|
||||
};
|
||||
Parse.Object.saveAll([3, 1, 2].map(makeBoxedNumber)).then( function() {
|
||||
Parse.Object.saveAll([3, 1, 2].map(makeBoxedNumber)).then(function() {
|
||||
var query = new Parse.Query(BoxedNumber);
|
||||
query.descending("number");
|
||||
query.find(expectSuccess({
|
||||
@@ -864,7 +864,7 @@ describe('Parse.Query testing', () => {
|
||||
return new BoxedNumber({ number: num, string: strings[i] });
|
||||
};
|
||||
|
||||
let objects = [3, 1, 3, 2].map(makeBoxedNumber);
|
||||
const objects = [3, 1, 3, 2].map(makeBoxedNumber);
|
||||
Parse.Object.saveAll(objects)
|
||||
.then(() => {
|
||||
var query = new Parse.Query(BoxedNumber);
|
||||
@@ -1566,26 +1566,26 @@ describe('Parse.Query testing', () => {
|
||||
});
|
||||
|
||||
it('properly includes array', (done) => {
|
||||
let objects = [];
|
||||
const objects = [];
|
||||
let total = 0;
|
||||
while(objects.length != 5) {
|
||||
let object = new Parse.Object('AnObject');
|
||||
const object = new Parse.Object('AnObject');
|
||||
object.set('key', objects.length);
|
||||
total += objects.length;
|
||||
objects.push(object);
|
||||
}
|
||||
Parse.Object.saveAll(objects).then(() => {
|
||||
let object = new Parse.Object("AContainer");
|
||||
const object = new Parse.Object("AContainer");
|
||||
object.set('objects', objects);
|
||||
return object.save();
|
||||
}).then(() => {
|
||||
let query = new Parse.Query('AContainer');
|
||||
const query = new Parse.Query('AContainer');
|
||||
query.include('objects');
|
||||
return query.find()
|
||||
}).then((results) => {
|
||||
expect(results.length).toBe(1);
|
||||
let res = results[0];
|
||||
let objects = res.get('objects');
|
||||
const res = results[0];
|
||||
const objects = res.get('objects');
|
||||
expect(objects.length).toBe(5);
|
||||
objects.forEach((object) => {
|
||||
total -= object.get('key');
|
||||
@@ -1599,61 +1599,62 @@ describe('Parse.Query testing', () => {
|
||||
});
|
||||
|
||||
it('properly includes array of mixed objects', (done) => {
|
||||
let objects = [];
|
||||
const objects = [];
|
||||
let total = 0;
|
||||
while(objects.length != 5) {
|
||||
let object = new Parse.Object('AnObject');
|
||||
const object = new Parse.Object('AnObject');
|
||||
object.set('key', objects.length);
|
||||
total += objects.length;
|
||||
objects.push(object);
|
||||
}
|
||||
while(objects.length != 10) {
|
||||
let object = new Parse.Object('AnotherObject');
|
||||
const object = new Parse.Object('AnotherObject');
|
||||
object.set('key', objects.length);
|
||||
total += objects.length;
|
||||
objects.push(object);
|
||||
}
|
||||
Parse.Object.saveAll(objects).then(() => {
|
||||
let object = new Parse.Object("AContainer");
|
||||
const object = new Parse.Object("AContainer");
|
||||
object.set('objects', objects);
|
||||
return object.save();
|
||||
}).then(() => {
|
||||
let query = new Parse.Query('AContainer');
|
||||
const query = new Parse.Query('AContainer');
|
||||
query.include('objects');
|
||||
return query.find()
|
||||
}).then((results) => {
|
||||
expect(results.length).toBe(1);
|
||||
let res = results[0];
|
||||
let objects = res.get('objects');
|
||||
const res = results[0];
|
||||
const objects = res.get('objects');
|
||||
expect(objects.length).toBe(10);
|
||||
objects.forEach((object) => {
|
||||
total -= object.get('key');
|
||||
});
|
||||
expect(total).toBe(0);
|
||||
done()
|
||||
}, () => {
|
||||
}, (e) => {
|
||||
fail('should not fail');
|
||||
fail(JSON.stringify(e));
|
||||
done();
|
||||
})
|
||||
});
|
||||
|
||||
it('properly nested array of mixed objects with bad ids', (done) => {
|
||||
let objects = [];
|
||||
const objects = [];
|
||||
let total = 0;
|
||||
while(objects.length != 5) {
|
||||
let object = new Parse.Object('AnObject');
|
||||
const object = new Parse.Object('AnObject');
|
||||
object.set('key', objects.length);
|
||||
objects.push(object);
|
||||
}
|
||||
while(objects.length != 10) {
|
||||
let object = new Parse.Object('AnotherObject');
|
||||
const object = new Parse.Object('AnotherObject');
|
||||
object.set('key', objects.length);
|
||||
objects.push(object);
|
||||
}
|
||||
Parse.Object.saveAll(objects).then(() => {
|
||||
let object = new Parse.Object("AContainer");
|
||||
for (var i=0; i<objects.length; i++) {
|
||||
if (i%2 == 0) {
|
||||
const object = new Parse.Object("AContainer");
|
||||
for (var i = 0; i < objects.length; i++) {
|
||||
if (i % 2 == 0) {
|
||||
objects[i].id = 'randomThing'
|
||||
} else {
|
||||
total += objects[i].get('key');
|
||||
@@ -1662,13 +1663,13 @@ describe('Parse.Query testing', () => {
|
||||
object.set('objects', objects);
|
||||
return object.save();
|
||||
}).then(() => {
|
||||
let query = new Parse.Query('AContainer');
|
||||
const query = new Parse.Query('AContainer');
|
||||
query.include('objects');
|
||||
return query.find()
|
||||
}).then((results) => {
|
||||
expect(results.length).toBe(1);
|
||||
let res = results[0];
|
||||
let objects = res.get('objects');
|
||||
const res = results[0];
|
||||
const objects = res.get('objects');
|
||||
expect(objects.length).toBe(5);
|
||||
objects.forEach((object) => {
|
||||
total -= object.get('key');
|
||||
@@ -1683,25 +1684,25 @@ describe('Parse.Query testing', () => {
|
||||
});
|
||||
|
||||
it('properly fetches nested pointers', (done) => {
|
||||
let color = new Parse.Object('Color');
|
||||
const color = new Parse.Object('Color');
|
||||
color.set('hex','#133733');
|
||||
let circle = new Parse.Object('Circle');
|
||||
const circle = new Parse.Object('Circle');
|
||||
circle.set('radius', 1337);
|
||||
|
||||
Parse.Object.saveAll([color, circle]).then(() => {
|
||||
circle.set('color', color);
|
||||
let badCircle = new Parse.Object('Circle');
|
||||
const badCircle = new Parse.Object('Circle');
|
||||
badCircle.id = 'badId';
|
||||
let complexFigure = new Parse.Object('ComplexFigure');
|
||||
const complexFigure = new Parse.Object('ComplexFigure');
|
||||
complexFigure.set('consistsOf', [circle, badCircle]);
|
||||
return complexFigure.save();
|
||||
}).then(() => {
|
||||
let q = new Parse.Query('ComplexFigure');
|
||||
const q = new Parse.Query('ComplexFigure');
|
||||
q.include('consistsOf.color');
|
||||
return q.find()
|
||||
}).then((results) => {
|
||||
expect(results.length).toBe(1);
|
||||
let figure = results[0];
|
||||
const figure = results[0];
|
||||
expect(figure.get('consistsOf').length).toBe(1);
|
||||
expect(figure.get('consistsOf')[0].get('color').get('hex')).toBe('#133733');
|
||||
done();
|
||||
@@ -2357,15 +2358,15 @@ describe('Parse.Query testing', () => {
|
||||
});
|
||||
|
||||
it('supports include on the wrong key type (#2262)', function(done) {
|
||||
let childObject = new Parse.Object('TestChildObject');
|
||||
const childObject = new Parse.Object('TestChildObject');
|
||||
childObject.set('hello', 'world');
|
||||
childObject.save().then(() => {
|
||||
let obj = new Parse.Object('TestObject');
|
||||
const obj = new Parse.Object('TestObject');
|
||||
obj.set('foo', 'bar');
|
||||
obj.set('child', childObject);
|
||||
return obj.save();
|
||||
}).then(() => {
|
||||
let q = new Parse.Query('TestObject');
|
||||
const q = new Parse.Query('TestObject');
|
||||
q.include('child');
|
||||
q.include('child.parent');
|
||||
q.include('createdAt');
|
||||
@@ -2401,7 +2402,7 @@ describe('Parse.Query testing', () => {
|
||||
it('query match on array with multiple objects', (done) => {
|
||||
var target1 = {__type: 'Pointer', className: 'TestObject', objectId: 'abc'};
|
||||
var target2 = {__type: 'Pointer', className: 'TestObject', objectId: '123'};
|
||||
var obj= new Parse.Object('TestObject');
|
||||
var obj = new Parse.Object('TestObject');
|
||||
obj.set('someObjs', [target1, target2]);
|
||||
obj.save().then(() => {
|
||||
var query = new Parse.Query('TestObject');
|
||||
@@ -2435,7 +2436,7 @@ describe('Parse.Query testing', () => {
|
||||
var user = new Parse.User();
|
||||
user.set("username", "foo");
|
||||
user.set("password", "bar");
|
||||
return user.save().then( (user) => {
|
||||
return user.save().then((user) => {
|
||||
var objIdQuery = new Parse.Query("_User").equalTo("objectId", user.id);
|
||||
var blockedUserQuery = user.relation("blockedUsers").query();
|
||||
|
||||
@@ -2467,6 +2468,35 @@ describe('Parse.Query testing', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("should match a key in an array (#3195)", function(done) {
|
||||
var AuthorObject = Parse.Object.extend("Author");
|
||||
var GroupObject = Parse.Object.extend("Group");
|
||||
var PostObject = Parse.Object.extend("Post");
|
||||
|
||||
return new AuthorObject().save().then((user) => {
|
||||
const post = new PostObject({
|
||||
author: user
|
||||
});
|
||||
|
||||
const group = new GroupObject({
|
||||
members: [user],
|
||||
});
|
||||
|
||||
return Parse.Promise.when(post.save(), group.save());
|
||||
}).then((p) => {
|
||||
return new Parse.Query(PostObject)
|
||||
.matchesKeyInQuery("author", "members", new Parse.Query(GroupObject))
|
||||
.find()
|
||||
.then((r) => {
|
||||
expect(r.length).toEqual(1);
|
||||
if (r.length > 0) {
|
||||
expect(r[0].id).toEqual(p.id);
|
||||
}
|
||||
done();
|
||||
}, done.fail);
|
||||
});
|
||||
});
|
||||
|
||||
it('should find objects with array of pointers', (done) => {
|
||||
var objects = [];
|
||||
while(objects.length != 5) {
|
||||
@@ -2485,13 +2515,13 @@ describe('Parse.Query testing', () => {
|
||||
}
|
||||
})
|
||||
container.set('objects', pointers);
|
||||
let container2 = new Parse.Object('Container');
|
||||
const container2 = new Parse.Object('Container');
|
||||
container2.set('objects', pointers.slice(2, 3));
|
||||
return Parse.Object.saveAll([container, container2]);
|
||||
}).then(() => {
|
||||
let inQuery = new Parse.Query('ContainedObject');
|
||||
const inQuery = new Parse.Query('ContainedObject');
|
||||
inQuery.greaterThanOrEqualTo('index', 1);
|
||||
let query = new Parse.Query('Container');
|
||||
const query = new Parse.Query('Container');
|
||||
query.matchesQuery('objects', inQuery);
|
||||
return query.find();
|
||||
}).then((results) => {
|
||||
@@ -2507,16 +2537,16 @@ describe('Parse.Query testing', () => {
|
||||
})
|
||||
|
||||
it('query with two OR subqueries (regression test #1259)', done => {
|
||||
let relatedObject = new Parse.Object('Class2');
|
||||
const relatedObject = new Parse.Object('Class2');
|
||||
relatedObject.save().then(relatedObject => {
|
||||
let anObject = new Parse.Object('Class1');
|
||||
let relation = anObject.relation('relation');
|
||||
const anObject = new Parse.Object('Class1');
|
||||
const relation = anObject.relation('relation');
|
||||
relation.add(relatedObject);
|
||||
return anObject.save();
|
||||
}).then(anObject => {
|
||||
let q1 = anObject.relation('relation').query();
|
||||
const q1 = anObject.relation('relation').query();
|
||||
q1.doesNotExist('nonExistantKey1');
|
||||
let q2 = anObject.relation('relation').query();
|
||||
const q2 = anObject.relation('relation').query();
|
||||
q2.doesNotExist('nonExistantKey2');
|
||||
Parse.Query.or(q1, q2).find().then(results => {
|
||||
expect(results.length).toEqual(1);
|
||||
@@ -2529,14 +2559,14 @@ describe('Parse.Query testing', () => {
|
||||
});
|
||||
|
||||
it('objectId containedIn with multiple large array', done => {
|
||||
let obj = new Parse.Object('MyClass');
|
||||
const obj = new Parse.Object('MyClass');
|
||||
obj.save().then(obj => {
|
||||
let longListOfStrings = [];
|
||||
const longListOfStrings = [];
|
||||
for (let i = 0; i < 130; i++) {
|
||||
longListOfStrings.push(i.toString());
|
||||
}
|
||||
longListOfStrings.push(obj.id);
|
||||
let q = new Parse.Query('MyClass');
|
||||
const q = new Parse.Query('MyClass');
|
||||
q.containedIn('objectId', longListOfStrings);
|
||||
q.containedIn('objectId', longListOfStrings);
|
||||
return q.find();
|
||||
@@ -2655,6 +2685,46 @@ describe('Parse.Query testing', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('select nested keys 2 level without include (issue #3185)', function(done) {
|
||||
var Foobar = new Parse.Object('Foobar');
|
||||
var BarBaz = new Parse.Object('Barbaz');
|
||||
var Bazoo = new Parse.Object('Bazoo');
|
||||
|
||||
Bazoo.set('some', 'thing');
|
||||
Bazoo.set('otherSome', 'value');
|
||||
Bazoo.save().then(() => {
|
||||
BarBaz.set('key', 'value');
|
||||
BarBaz.set('otherKey', 'value');
|
||||
BarBaz.set('bazoo', Bazoo);
|
||||
return BarBaz.save();
|
||||
}).then(() => {
|
||||
Foobar.set('foo', 'bar');
|
||||
Foobar.set('fizz', 'buzz');
|
||||
Foobar.set('barBaz', BarBaz);
|
||||
return Foobar.save();
|
||||
}).then(function(savedFoobar){
|
||||
var foobarQuery = new Parse.Query('Foobar');
|
||||
foobarQuery.select(['fizz', 'barBaz.key', 'barBaz.bazoo.some']);
|
||||
return foobarQuery.get(savedFoobar.id);
|
||||
}).then((foobarObj) => {
|
||||
equal(foobarObj.get('fizz'), 'buzz');
|
||||
equal(foobarObj.get('foo'), undefined);
|
||||
if (foobarObj.has('barBaz')) {
|
||||
equal(foobarObj.get('barBaz').get('key'), 'value');
|
||||
equal(foobarObj.get('barBaz').get('otherKey'), undefined);
|
||||
if (foobarObj.get('barBaz').has('bazoo')) {
|
||||
equal(foobarObj.get('barBaz').get('bazoo').get('some'), 'thing');
|
||||
equal(foobarObj.get('barBaz').get('bazoo').get('otherSome'), undefined);
|
||||
} else {
|
||||
fail('bazoo should be set');
|
||||
}
|
||||
} else {
|
||||
fail('barBaz should be set');
|
||||
}
|
||||
done();
|
||||
})
|
||||
});
|
||||
|
||||
it('properly handles nested ors', function(done) {
|
||||
var objects = [];
|
||||
while(objects.length != 4) {
|
||||
@@ -2663,13 +2733,13 @@ describe('Parse.Query testing', () => {
|
||||
objects.push(obj)
|
||||
}
|
||||
Parse.Object.saveAll(objects).then(() => {
|
||||
let q0 = new Parse.Query('Object');
|
||||
const q0 = new Parse.Query('Object');
|
||||
q0.equalTo('x', 0);
|
||||
let q1 = new Parse.Query('Object');
|
||||
const q1 = new Parse.Query('Object');
|
||||
q1.equalTo('x', 1);
|
||||
let q2 = new Parse.Query('Object');
|
||||
const q2 = new Parse.Query('Object');
|
||||
q2.equalTo('x', 2);
|
||||
let or01 = Parse.Query.or(q0,q1);
|
||||
const or01 = Parse.Query.or(q0,q1);
|
||||
return Parse.Query.or(or01, q2).find();
|
||||
}).then((results) => {
|
||||
expect(results.length).toBe(3);
|
||||
|
||||
+56
-47
@@ -249,35 +249,35 @@ describe('Parse.Relation testing', () => {
|
||||
});
|
||||
|
||||
it("queries on relation fields with multiple containedIn (regression test for #1271)", (done) => {
|
||||
let ChildObject = Parse.Object.extend("ChildObject");
|
||||
let childObjects = [];
|
||||
const ChildObject = Parse.Object.extend("ChildObject");
|
||||
const childObjects = [];
|
||||
for (let i = 0; i < 10; i++) {
|
||||
childObjects.push(new ChildObject({x: i}));
|
||||
}
|
||||
|
||||
Parse.Object.saveAll(childObjects).then(() => {
|
||||
let ParentObject = Parse.Object.extend("ParentObject");
|
||||
let parent = new ParentObject();
|
||||
const ParentObject = Parse.Object.extend("ParentObject");
|
||||
const parent = new ParentObject();
|
||||
parent.set("x", 4);
|
||||
let parent1Children = parent.relation("child");
|
||||
const parent1Children = parent.relation("child");
|
||||
parent1Children.add(childObjects[0]);
|
||||
parent1Children.add(childObjects[1]);
|
||||
parent1Children.add(childObjects[2]);
|
||||
let parent2 = new ParentObject();
|
||||
const parent2 = new ParentObject();
|
||||
parent2.set("x", 3);
|
||||
let parent2Children = parent2.relation("child");
|
||||
const parent2Children = parent2.relation("child");
|
||||
parent2Children.add(childObjects[4]);
|
||||
parent2Children.add(childObjects[5]);
|
||||
parent2Children.add(childObjects[6]);
|
||||
|
||||
let parent2OtherChildren = parent2.relation("otherChild");
|
||||
const parent2OtherChildren = parent2.relation("otherChild");
|
||||
parent2OtherChildren.add(childObjects[0]);
|
||||
parent2OtherChildren.add(childObjects[1]);
|
||||
parent2OtherChildren.add(childObjects[2]);
|
||||
|
||||
return Parse.Object.saveAll([parent, parent2]);
|
||||
}).then(() => {
|
||||
let objectsWithChild0InBothChildren = new Parse.Query(ParentObject);
|
||||
const objectsWithChild0InBothChildren = new Parse.Query(ParentObject);
|
||||
objectsWithChild0InBothChildren.containedIn("child", [childObjects[0]]);
|
||||
objectsWithChild0InBothChildren.containedIn("otherChild", [childObjects[0]]);
|
||||
return objectsWithChild0InBothChildren.find();
|
||||
@@ -285,7 +285,7 @@ describe('Parse.Relation testing', () => {
|
||||
//No parent has child 0 in both it's "child" and "otherChild" field;
|
||||
expect(objectsWithChild0InBothChildren.length).toEqual(0);
|
||||
}).then(() => {
|
||||
let objectsWithChild4andOtherChild1 = new Parse.Query(ParentObject);
|
||||
const objectsWithChild4andOtherChild1 = new Parse.Query(ParentObject);
|
||||
objectsWithChild4andOtherChild1.containedIn("child", [childObjects[4]]);
|
||||
objectsWithChild4andOtherChild1.containedIn("otherChild", [childObjects[1]]);
|
||||
return objectsWithChild4andOtherChild1.find();
|
||||
@@ -510,24 +510,24 @@ describe('Parse.Relation testing', () => {
|
||||
});
|
||||
|
||||
it('should properly get related objects with unfetched queries', (done) => {
|
||||
let objects = [];
|
||||
let owners = [];
|
||||
let allObjects = [];
|
||||
const objects = [];
|
||||
const owners = [];
|
||||
const allObjects = [];
|
||||
// Build 10 Objects and 10 owners
|
||||
while (objects.length != 10) {
|
||||
let object = new Parse.Object('AnObject');
|
||||
const object = new Parse.Object('AnObject');
|
||||
object.set({
|
||||
index: objects.length,
|
||||
even: objects.length % 2 == 0
|
||||
});
|
||||
objects.push(object);
|
||||
let owner = new Parse.Object('AnOwner');
|
||||
const owner = new Parse.Object('AnOwner');
|
||||
owners.push(owner);
|
||||
allObjects.push(object);
|
||||
allObjects.push(owner);
|
||||
}
|
||||
|
||||
let anotherOwner = new Parse.Object('AnotherOwner');
|
||||
const anotherOwner = new Parse.Object('AnotherOwner');
|
||||
|
||||
return Parse.Object.saveAll(allObjects.concat([anotherOwner])).then(() => {
|
||||
// put all the AnObject into the anotherOwner relationKey
|
||||
@@ -539,13 +539,13 @@ describe('Parse.Relation testing', () => {
|
||||
return Parse.Object.saveAll(owners.concat([anotherOwner]));
|
||||
}).then(() => {
|
||||
// Query on the relation of another owner
|
||||
let object = new Parse.Object('AnotherOwner');
|
||||
const object = new Parse.Object('AnotherOwner');
|
||||
object.id = anotherOwner.id;
|
||||
let relationQuery = object.relation('relationKey').query();
|
||||
const relationQuery = object.relation('relationKey').query();
|
||||
// Just get the even ones
|
||||
relationQuery.equalTo('even', true);
|
||||
// Make the query on anOwner
|
||||
let query = new Parse.Query('AnOwner');
|
||||
const query = new Parse.Query('AnOwner');
|
||||
// where key match the relation query.
|
||||
query.matchesQuery('key', relationQuery);
|
||||
query.include('key');
|
||||
@@ -558,13 +558,13 @@ describe('Parse.Relation testing', () => {
|
||||
return Promise.resolve();
|
||||
}).then(() => {
|
||||
// Query on the relation of another owner
|
||||
let object = new Parse.Object('AnotherOwner');
|
||||
const object = new Parse.Object('AnotherOwner');
|
||||
object.id = anotherOwner.id;
|
||||
let relationQuery = object.relation('relationKey').query();
|
||||
const relationQuery = object.relation('relationKey').query();
|
||||
// Just get the even ones
|
||||
relationQuery.equalTo('even', true);
|
||||
// Make the query on anOwner
|
||||
let query = new Parse.Query('AnOwner');
|
||||
const query = new Parse.Query('AnOwner');
|
||||
// where key match the relation query.
|
||||
query.doesNotMatchQuery('key', relationQuery);
|
||||
query.include('key');
|
||||
@@ -575,6 +575,9 @@ describe('Parse.Relation testing', () => {
|
||||
expect(result.get('key').get('even')).toBe(false);
|
||||
});
|
||||
done();
|
||||
}, (e) => {
|
||||
fail(JSON.stringify(e));
|
||||
done();
|
||||
})
|
||||
});
|
||||
|
||||
@@ -586,19 +589,19 @@ describe('Parse.Relation testing', () => {
|
||||
new RestaurantObject({ ratings: 5, location: "Djibouti" }),
|
||||
new RestaurantObject({ ratings: 3, location: "Ouagadougou" }),
|
||||
];
|
||||
let persons = [
|
||||
const persons = [
|
||||
new PersonObject({ name: "Bob", hometown: "Djibouti" }),
|
||||
new PersonObject({ name: "Tom", hometown: "Ouagadougou" }),
|
||||
new PersonObject({ name: "Billy", hometown: "Detroit" }),
|
||||
];
|
||||
let owner = new OwnerObject({name: 'Joe'});
|
||||
let allObjects = [owner].concat(restaurants).concat(persons);
|
||||
const owner = new OwnerObject({name: 'Joe'});
|
||||
const allObjects = [owner].concat(restaurants).concat(persons);
|
||||
expect(allObjects.length).toEqual(6);
|
||||
Parse.Object.saveAll([owner].concat(restaurants).concat(persons)).then(function() {
|
||||
owner.relation('restaurants').add(restaurants);
|
||||
return owner.save()
|
||||
}).then(() => {
|
||||
let unfetchedOwner = new OwnerObject();
|
||||
const unfetchedOwner = new OwnerObject();
|
||||
unfetchedOwner.id = owner.id;
|
||||
var query = unfetchedOwner.relation('restaurants').query();
|
||||
query.greaterThan("ratings", 4);
|
||||
@@ -613,6 +616,9 @@ describe('Parse.Relation testing', () => {
|
||||
done();
|
||||
}
|
||||
}));
|
||||
}, (e) => {
|
||||
fail(JSON.stringify(e));
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -624,19 +630,19 @@ describe('Parse.Relation testing', () => {
|
||||
new RestaurantObject({ ratings: 5, location: "Djibouti" }),
|
||||
new RestaurantObject({ ratings: 3, location: "Ouagadougou" }),
|
||||
];
|
||||
let persons = [
|
||||
const persons = [
|
||||
new PersonObject({ name: "Bob", hometown: "Djibouti" }),
|
||||
new PersonObject({ name: "Tom", hometown: "Ouagadougou" }),
|
||||
new PersonObject({ name: "Billy", hometown: "Detroit" }),
|
||||
];
|
||||
let owner = new OwnerObject({name: 'Joe'});
|
||||
let allObjects = [owner].concat(restaurants).concat(persons);
|
||||
const owner = new OwnerObject({name: 'Joe'});
|
||||
const allObjects = [owner].concat(restaurants).concat(persons);
|
||||
expect(allObjects.length).toEqual(6);
|
||||
Parse.Object.saveAll([owner].concat(restaurants).concat(persons)).then(function() {
|
||||
owner.relation('restaurants').add(restaurants);
|
||||
return owner.save()
|
||||
}).then(() => {
|
||||
let unfetchedOwner = new OwnerObject();
|
||||
const unfetchedOwner = new OwnerObject();
|
||||
unfetchedOwner.id = owner.id;
|
||||
var query = unfetchedOwner.relation('restaurants').query();
|
||||
query.greaterThan("ratings", 4);
|
||||
@@ -653,25 +659,28 @@ describe('Parse.Relation testing', () => {
|
||||
done();
|
||||
}
|
||||
}));
|
||||
}, (e) => {
|
||||
fail(JSON.stringify(e));
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('relations are not bidirectional (regression test for #871)', done => {
|
||||
let PersonObject = Parse.Object.extend("Person");
|
||||
let p1 = new PersonObject();
|
||||
let p2 = new PersonObject();
|
||||
const PersonObject = Parse.Object.extend("Person");
|
||||
const p1 = new PersonObject();
|
||||
const p2 = new PersonObject();
|
||||
Parse.Object.saveAll([p1, p2]).then(results => {
|
||||
let p1 = results[0];
|
||||
let p2 = results[1];
|
||||
let relation = p1.relation('relation');
|
||||
const p1 = results[0];
|
||||
const p2 = results[1];
|
||||
const relation = p1.relation('relation');
|
||||
relation.add(p2);
|
||||
p1.save().then(() => {
|
||||
let query = new Parse.Query(PersonObject);
|
||||
const query = new Parse.Query(PersonObject);
|
||||
query.equalTo('relation', p1);
|
||||
query.find().then(results => {
|
||||
expect(results.length).toEqual(0);
|
||||
|
||||
let query = new Parse.Query(PersonObject);
|
||||
const query = new Parse.Query(PersonObject);
|
||||
query.equalTo('relation', p2);
|
||||
query.find().then(results => {
|
||||
expect(results.length).toEqual(1);
|
||||
@@ -685,12 +694,12 @@ describe('Parse.Relation testing', () => {
|
||||
|
||||
it('can query roles in Cloud Code (regession test #1489)', done => {
|
||||
Parse.Cloud.define('isAdmin', (request, response) => {
|
||||
let query = new Parse.Query(Parse.Role);
|
||||
const query = new Parse.Query(Parse.Role);
|
||||
query.equalTo('name', 'admin');
|
||||
query.first({ useMasterKey: true })
|
||||
.then(role => {
|
||||
let relation = new Parse.Relation(role, 'users');
|
||||
let admins = relation.query();
|
||||
const relation = new Parse.Relation(role, 'users');
|
||||
const admins = relation.query();
|
||||
admins.equalTo('username', request.user.get('username'));
|
||||
admins.first({ useMasterKey: true })
|
||||
.then(user => {
|
||||
@@ -712,16 +721,16 @@ describe('Parse.Relation testing', () => {
|
||||
});
|
||||
});
|
||||
|
||||
let adminUser = new Parse.User();
|
||||
const adminUser = new Parse.User();
|
||||
adminUser.set('username', 'name');
|
||||
adminUser.set('password', 'pass');
|
||||
adminUser.signUp()
|
||||
.then(adminUser => {
|
||||
let adminACL = new Parse.ACL();
|
||||
const adminACL = new Parse.ACL();
|
||||
adminACL.setPublicReadAccess(true);
|
||||
|
||||
// Create admin role
|
||||
let adminRole = new Parse.Role('admin', adminACL);
|
||||
const adminRole = new Parse.Role('admin', adminACL);
|
||||
adminRole.getUsers().add(adminUser);
|
||||
adminRole.save()
|
||||
.then(() => {
|
||||
@@ -739,13 +748,13 @@ describe('Parse.Relation testing', () => {
|
||||
});
|
||||
|
||||
it('can be saved without error', done => {
|
||||
let obj1 = new Parse.Object('PPAP');
|
||||
const obj1 = new Parse.Object('PPAP');
|
||||
obj1.save()
|
||||
.then(() => {
|
||||
let newRelation = obj1.relation('aRelation');
|
||||
const newRelation = obj1.relation('aRelation');
|
||||
newRelation.add(obj1);
|
||||
obj1.save().then(() => {
|
||||
let relation = obj1.get('aRelation');
|
||||
const relation = obj1.get('aRelation');
|
||||
obj1.set('aRelation', relation);
|
||||
obj1.save().then(() => {
|
||||
done();
|
||||
|
||||
+85
-22
@@ -13,7 +13,7 @@ describe('Parse Role testing', () => {
|
||||
|
||||
createTestUser().then((x) => {
|
||||
user = x;
|
||||
let acl = new Parse.ACL();
|
||||
const acl = new Parse.ACL();
|
||||
acl.setPublicReadAccess(true);
|
||||
acl.setPublicWriteAccess(false);
|
||||
role = new Parse.Object('_Role');
|
||||
@@ -98,10 +98,10 @@ describe('Parse Role testing', () => {
|
||||
var user,
|
||||
auth,
|
||||
getAllRolesSpy;
|
||||
createTestUser().then( (newUser) => {
|
||||
createTestUser().then((newUser) => {
|
||||
user = newUser;
|
||||
return createAllRoles(user);
|
||||
}).then ( (roles) => {
|
||||
}).then ((roles) => {
|
||||
var rootRoleObj = roleObjs[rootRole];
|
||||
roles.forEach(function(role, i) {
|
||||
// Add all roles to the RootRole
|
||||
@@ -115,16 +115,16 @@ describe('Parse Role testing', () => {
|
||||
});
|
||||
|
||||
return Parse.Object.saveAll(roles, { useMasterKey: true });
|
||||
}).then( () => {
|
||||
}).then(() => {
|
||||
auth = new Auth({config: new Config("test"), isMaster: true, user: user});
|
||||
getAllRolesSpy = spyOn(auth, "_getAllRolesNamesForRoleIds").and.callThrough();
|
||||
|
||||
return auth._loadRoles();
|
||||
}).then ( (roles) => {
|
||||
}).then ((roles) => {
|
||||
expect(roles.length).toEqual(4);
|
||||
|
||||
allRoles.forEach(function(name) {
|
||||
expect(roles.indexOf("role:"+name)).not.toBe(-1);
|
||||
expect(roles.indexOf("role:" + name)).not.toBe(-1);
|
||||
});
|
||||
|
||||
// 1 Query for the initial setup
|
||||
@@ -135,7 +135,7 @@ describe('Parse Role testing', () => {
|
||||
// 1 call for the 2nd layer
|
||||
expect(getAllRolesSpy.calls.count()).toEqual(2);
|
||||
done()
|
||||
}).catch( () => {
|
||||
}).catch(() => {
|
||||
fail("should succeed");
|
||||
done();
|
||||
});
|
||||
@@ -145,27 +145,27 @@ describe('Parse Role testing', () => {
|
||||
it("should recursively load roles", (done) => {
|
||||
var rolesNames = ["FooRole", "BarRole", "BazRole"];
|
||||
var roleIds = {};
|
||||
createTestUser().then( (user) => {
|
||||
createTestUser().then((user) => {
|
||||
// Put the user on the 1st role
|
||||
return createRole(rolesNames[0], null, user).then( (aRole) => {
|
||||
return createRole(rolesNames[0], null, user).then((aRole) => {
|
||||
roleIds[aRole.get("name")] = aRole.id;
|
||||
// set the 1st role as a sibling of the second
|
||||
// user will should have 2 role now
|
||||
return createRole(rolesNames[1], aRole, null);
|
||||
}).then( (anotherRole) => {
|
||||
}).then((anotherRole) => {
|
||||
roleIds[anotherRole.get("name")] = anotherRole.id;
|
||||
// set this role as a sibling of the last
|
||||
// the user should now have 3 roles
|
||||
return createRole(rolesNames[2], anotherRole, null);
|
||||
}).then( (lastRole) => {
|
||||
}).then((lastRole) => {
|
||||
roleIds[lastRole.get("name")] = lastRole.id;
|
||||
var auth = new Auth({ config: new Config("test"), isMaster: true, user: user });
|
||||
return auth._loadRoles();
|
||||
})
|
||||
}).then( (roles) => {
|
||||
}).then((roles) => {
|
||||
expect(roles.length).toEqual(3);
|
||||
rolesNames.forEach( (name) => {
|
||||
expect(roles.indexOf('role:'+name)).not.toBe(-1);
|
||||
rolesNames.forEach((name) => {
|
||||
expect(roles.indexOf('role:' + name)).not.toBe(-1);
|
||||
});
|
||||
done();
|
||||
}, function(){
|
||||
@@ -193,11 +193,11 @@ describe('Parse Role testing', () => {
|
||||
});
|
||||
|
||||
it("Should properly resolve roles", (done) => {
|
||||
let admin = new Parse.Role("Admin", new Parse.ACL());
|
||||
let moderator = new Parse.Role("Moderator", new Parse.ACL());
|
||||
let superModerator = new Parse.Role("SuperModerator", new Parse.ACL());
|
||||
let contentManager = new Parse.Role('ContentManager', new Parse.ACL());
|
||||
let superContentManager = new Parse.Role('SuperContentManager', new Parse.ACL());
|
||||
const admin = new Parse.Role("Admin", new Parse.ACL());
|
||||
const moderator = new Parse.Role("Moderator", new Parse.ACL());
|
||||
const superModerator = new Parse.Role("SuperModerator", new Parse.ACL());
|
||||
const contentManager = new Parse.Role('ContentManager', new Parse.ACL());
|
||||
const superContentManager = new Parse.Role('SuperContentManager', new Parse.ACL());
|
||||
Parse.Object.saveAll([admin, moderator, contentManager, superModerator, superContentManager], {useMasterKey: true}).then(() => {
|
||||
contentManager.getRoles().add([moderator, superContentManager]);
|
||||
moderator.getRoles().add([admin, superModerator]);
|
||||
@@ -207,7 +207,7 @@ describe('Parse Role testing', () => {
|
||||
var auth = new Auth({ config: new Config("test"), isMaster: true });
|
||||
// For each role, fetch their sibling, what they inherit
|
||||
// return with result and roleId for later comparison
|
||||
let promises = [admin, moderator, contentManager, superModerator].map((role) => {
|
||||
const promises = [admin, moderator, contentManager, superModerator].map((role) => {
|
||||
return auth._getAllRolesNamesForRoleIds([role.id]).then((result) => {
|
||||
return Parse.Promise.as({
|
||||
id: role.id,
|
||||
@@ -220,8 +220,8 @@ describe('Parse Role testing', () => {
|
||||
return Parse.Promise.when(promises);
|
||||
}).then((results) => {
|
||||
results.forEach((result) => {
|
||||
let id = result.id;
|
||||
let roleNames = result.roleNames;
|
||||
const id = result.id;
|
||||
const roleNames = result.roleNames;
|
||||
if (id == admin.id) {
|
||||
expect(roleNames.length).toBe(2);
|
||||
expect(roleNames.indexOf("Moderator")).not.toBe(-1);
|
||||
@@ -347,4 +347,67 @@ describe('Parse Role testing', () => {
|
||||
})
|
||||
});
|
||||
|
||||
it('should add multiple users to a role and remove users', (done) => {
|
||||
var user, user2, user3;
|
||||
var role;
|
||||
var obj;
|
||||
|
||||
var prACL = new Parse.ACL();
|
||||
prACL.setPublicReadAccess(true);
|
||||
prACL.setPublicWriteAccess(true);
|
||||
|
||||
createTestUser().then((x) => {
|
||||
user = x;
|
||||
user2 = new Parse.User();
|
||||
return user2.save({ username: 'user2', password: 'omgbbq' });
|
||||
}).then(() => {
|
||||
user3 = new Parse.User();
|
||||
return user3.save({ username: 'user3', password: 'omgbbq' });
|
||||
}).then(() => {
|
||||
role = new Parse.Role('sharedRole', prACL);
|
||||
var users = role.relation('users');
|
||||
users.add(user);
|
||||
users.add(user2);
|
||||
users.add(user3);
|
||||
return role.save({}, { useMasterKey: true });
|
||||
}).then(() => {
|
||||
// query for saved role and get 3 users
|
||||
var query = new Parse.Query('_Role');
|
||||
query.equalTo('name', 'sharedRole');
|
||||
return query.find({ useMasterKey: true });
|
||||
}).then((role) => {
|
||||
expect(role.length).toEqual(1);
|
||||
var users = role[0].relation('users').query();
|
||||
return users.find({ useMasterKey: true });
|
||||
}).then((users) => {
|
||||
expect(users.length).toEqual(3);
|
||||
obj = new Parse.Object('TestObjectRoles');
|
||||
obj.set('ACL', prACL);
|
||||
return obj.save(null, { useMasterKey: true });
|
||||
}).then(() => {
|
||||
// Above, the Admin role was added to the Customer role.
|
||||
// An object secured by the Customer ACL should be able to be edited by the Admin user.
|
||||
obj.set('changedByUsers', true);
|
||||
return obj.save(null, { sessionToken: user.getSessionToken() });
|
||||
}).then(() => {
|
||||
// query for saved role and get 3 users
|
||||
var query = new Parse.Query('_Role');
|
||||
query.equalTo('name', 'sharedRole');
|
||||
return query.find({ useMasterKey: true });
|
||||
}).then((role) => {
|
||||
expect(role.length).toEqual(1);
|
||||
var users = role[0].relation('users');
|
||||
users.remove(user);
|
||||
users.remove(user3);
|
||||
return role[0].save({}, { useMasterKey: true });
|
||||
}).then((role) =>{
|
||||
var users = role.relation('users').query();
|
||||
return users.find({ useMasterKey: true });
|
||||
}).then((users) => {
|
||||
expect(users.length).toEqual(1);
|
||||
expect(users[0].get('username')).toEqual('user2');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
@@ -73,7 +73,7 @@ describe('ParseServerRESTController', () => {
|
||||
let userId;
|
||||
Parse.User.signUp('user', 'pass').then((user) => {
|
||||
userId = user.id;
|
||||
let sessionToken = user.getSessionToken();
|
||||
const sessionToken = user.getSessionToken();
|
||||
return RESTController.request("GET", "/users/me", undefined, {sessionToken});
|
||||
}).then((res) => {
|
||||
// Result is in JSON format
|
||||
@@ -104,8 +104,9 @@ describe('ParseServerRESTController', () => {
|
||||
});
|
||||
|
||||
it('ensures no session token is created on creating users', (done) => {
|
||||
RESTController.request("POST", "/classes/_User", {username: "hello", password: "world"}).then(() => {
|
||||
let query = new Parse.Query('_Session');
|
||||
RESTController.request("POST", "/classes/_User", {username: "hello", password: "world"}).then((user) => {
|
||||
expect(user.sessionToken).toBeUndefined();
|
||||
const query = new Parse.Query('_Session');
|
||||
return query.find({useMasterKey: true});
|
||||
}).then(sessions => {
|
||||
expect(sessions.length).toBe(0);
|
||||
@@ -115,4 +116,19 @@ describe('ParseServerRESTController', () => {
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('ensures a session token is created when passing installationId != cloud', (done) => {
|
||||
RESTController.request("POST", "/classes/_User", {username: "hello", password: "world"}, {installationId: 'my-installation'}).then((user) => {
|
||||
expect(user.sessionToken).not.toBeUndefined();
|
||||
const query = new Parse.Query('_Session');
|
||||
return query.find({useMasterKey: true});
|
||||
}).then(sessions => {
|
||||
expect(sessions.length).toBe(1);
|
||||
expect(sessions[0].get('installationId')).toBe('my-installation');
|
||||
done();
|
||||
}, (err) => {
|
||||
jfail(err);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
+35
-35
@@ -141,8 +141,8 @@ describe('Parse.User testing', () => {
|
||||
});
|
||||
|
||||
it('should respect ACL without locking user out', (done) => {
|
||||
let user = new Parse.User();
|
||||
let ACL = new Parse.ACL();
|
||||
const user = new Parse.User();
|
||||
const ACL = new Parse.ACL();
|
||||
ACL.setPublicReadAccess(false);
|
||||
ACL.setPublicWriteAccess(false);
|
||||
user.setUsername('asdf');
|
||||
@@ -163,7 +163,7 @@ describe('Parse.User testing', () => {
|
||||
expect(perms[user.id].write).toBe(true);
|
||||
expect(perms['*']).toBeUndefined();
|
||||
// Try to lock out user
|
||||
let newACL = new Parse.ACL();
|
||||
const newACL = new Parse.ACL();
|
||||
newACL.setReadAccess(user.id, false);
|
||||
newACL.setWriteAccess(user.id, false);
|
||||
user.setACL(newACL);
|
||||
@@ -190,13 +190,13 @@ describe('Parse.User testing', () => {
|
||||
});
|
||||
|
||||
it("user login with files", (done) => {
|
||||
let file = new Parse.File("yolo.txt", [1,2,3], "text/plain");
|
||||
const file = new Parse.File("yolo.txt", [1,2,3], "text/plain");
|
||||
file.save().then((file) => {
|
||||
return Parse.User.signUp("asdf", "zxcv", { "file" : file });
|
||||
}).then(() => {
|
||||
return Parse.User.logIn("asdf", "zxcv");
|
||||
}).then((user) => {
|
||||
let fileAgain = user.get('file');
|
||||
const fileAgain = user.get('file');
|
||||
ok(fileAgain.name());
|
||||
ok(fileAgain.url());
|
||||
done();
|
||||
@@ -1153,11 +1153,11 @@ describe('Parse.User testing', () => {
|
||||
|
||||
it('returns authData when authed and logged in with provider (regression test for #1498)', done => {
|
||||
Parse.Object.enableSingleInstance();
|
||||
let provider = getMockFacebookProvider();
|
||||
const provider = getMockFacebookProvider();
|
||||
Parse.User._registerAuthenticationProvider(provider);
|
||||
Parse.User._logInWith('facebook', {
|
||||
success: user => {
|
||||
let userQuery = new Parse.Query(Parse.User);
|
||||
const userQuery = new Parse.Query(Parse.User);
|
||||
userQuery.get(user.id)
|
||||
.then(user => {
|
||||
expect(user.get('authData')).not.toBeUndefined();
|
||||
@@ -1169,18 +1169,18 @@ describe('Parse.User testing', () => {
|
||||
});
|
||||
|
||||
it('log in with provider with files', done => {
|
||||
let provider = getMockFacebookProvider();
|
||||
const provider = getMockFacebookProvider();
|
||||
Parse.User._registerAuthenticationProvider(provider);
|
||||
let file = new Parse.File("yolo.txt", [1, 2, 3], "text/plain");
|
||||
const file = new Parse.File("yolo.txt", [1, 2, 3], "text/plain");
|
||||
file.save().then(file => {
|
||||
let user = new Parse.User();
|
||||
const user = new Parse.User();
|
||||
user.set('file', file);
|
||||
return user._linkWith('facebook', {});
|
||||
}).then(user => {
|
||||
expect(user._isLinked("facebook")).toBeTruthy();
|
||||
return Parse.User._logInWith('facebook', {});
|
||||
}).then(user => {
|
||||
let fileAgain = user.get('file');
|
||||
const fileAgain = user.get('file');
|
||||
expect(fileAgain.name()).toMatch(/yolo.txt$/);
|
||||
expect(fileAgain.url()).toMatch(/yolo.txt$/);
|
||||
}).then(() => {
|
||||
@@ -1535,7 +1535,7 @@ describe('Parse.User testing', () => {
|
||||
strictEqual(provider.authData.expiration_date, provider.synchronizedExpiration);
|
||||
ok(model._isLinked("facebook"), "User should be linked to facebook");
|
||||
Parse.User._registerAuthenticationProvider(mockProvider);
|
||||
let objectId = model.id;
|
||||
const objectId = model.id;
|
||||
model._linkWith("myoauth", {
|
||||
success: function(model) {
|
||||
expect(model.id).toEqual(objectId);
|
||||
@@ -1571,7 +1571,7 @@ describe('Parse.User testing', () => {
|
||||
Parse.User._logInWith("facebook", {
|
||||
success: function(model) {
|
||||
Parse.User._registerAuthenticationProvider(mockProvider);
|
||||
let objectId = model.id;
|
||||
const objectId = model.id;
|
||||
model._linkWith("myoauth", {
|
||||
success: function() {
|
||||
Parse.User._registerAuthenticationProvider(secondProvider);
|
||||
@@ -1612,7 +1612,7 @@ describe('Parse.User testing', () => {
|
||||
strictEqual(provider.authData.expiration_date, provider.synchronizedExpiration);
|
||||
ok(model._isLinked("facebook"), "User should be linked to facebook");
|
||||
Parse.User._registerAuthenticationProvider(mockProvider);
|
||||
let objectId = model.id;
|
||||
const objectId = model.id;
|
||||
model._linkWith("myoauth", {
|
||||
success: function(model) {
|
||||
expect(model.id).toEqual(objectId);
|
||||
@@ -1650,7 +1650,7 @@ describe('Parse.User testing', () => {
|
||||
Parse.User._logInWith("facebook", {
|
||||
success: function() {
|
||||
Parse.User.logOut().then(() => {
|
||||
let user = new Parse.User();
|
||||
const user = new Parse.User();
|
||||
user.setUsername('user');
|
||||
user.setPassword('password');
|
||||
return user.signUp().then(() => {
|
||||
@@ -1675,10 +1675,10 @@ describe('Parse.User testing', () => {
|
||||
Parse.User._registerAuthenticationProvider(provider);
|
||||
Parse.User._logInWith("facebook", {
|
||||
success: function(model) {
|
||||
let userId = model.id;
|
||||
const userId = model.id;
|
||||
Parse.User.logOut().then(() => {
|
||||
request.post({
|
||||
url:Parse.serverURL+'/classes/_User',
|
||||
url:Parse.serverURL + '/classes/_User',
|
||||
headers: {
|
||||
'X-Parse-Application-Id': Parse.applicationId,
|
||||
'X-Parse-REST-API-Key': 'rest'
|
||||
@@ -1688,7 +1688,7 @@ describe('Parse.User testing', () => {
|
||||
// make sure the location header is properly set
|
||||
expect(userId).not.toBeUndefined();
|
||||
expect(body.objectId).toEqual(userId);
|
||||
expect(res.headers.location).toEqual(Parse.serverURL+'/users/'+userId);
|
||||
expect(res.headers.location).toEqual(Parse.serverURL + '/users/' + userId);
|
||||
done();
|
||||
});
|
||||
});
|
||||
@@ -1722,7 +1722,7 @@ describe('Parse.User testing', () => {
|
||||
it('should have authData in beforeSave and afterSave', (done) => {
|
||||
|
||||
Parse.Cloud.beforeSave('_User', (request, response) => {
|
||||
let authData = request.object.get('authData');
|
||||
const authData = request.object.get('authData');
|
||||
expect(authData).not.toBeUndefined();
|
||||
if (authData) {
|
||||
expect(authData.facebook.id).toEqual('8675309');
|
||||
@@ -1734,7 +1734,7 @@ describe('Parse.User testing', () => {
|
||||
});
|
||||
|
||||
Parse.Cloud.afterSave('_User', (request, response) => {
|
||||
let authData = request.object.get('authData');
|
||||
const authData = request.object.get('authData');
|
||||
expect(authData).not.toBeUndefined();
|
||||
if (authData) {
|
||||
expect(authData.facebook.id).toEqual('8675309');
|
||||
@@ -2326,7 +2326,7 @@ describe('Parse.User testing', () => {
|
||||
});
|
||||
|
||||
it_exclude_dbs(['postgres'])('should cleanup null authData keys (regression test for #935)', (done) => {
|
||||
let database = new Config(Parse.applicationId).database;
|
||||
const database = new Config(Parse.applicationId).database;
|
||||
database.create('_User', {
|
||||
username: 'user',
|
||||
_hashed_password: '$2a$10$8/wZJyEuiEaobBBqzTG.jeY.XSFJd0rzaN//ososvEI4yLqI.4aie',
|
||||
@@ -2349,7 +2349,7 @@ describe('Parse.User testing', () => {
|
||||
})
|
||||
})
|
||||
}).then((user) => {
|
||||
let authData = user.authData;
|
||||
const authData = user.authData;
|
||||
expect(user.username).toEqual('user');
|
||||
expect(authData).toBeUndefined();
|
||||
done();
|
||||
@@ -2360,7 +2360,7 @@ describe('Parse.User testing', () => {
|
||||
});
|
||||
|
||||
it_exclude_dbs(['postgres'])('should not serve null authData keys', (done) => {
|
||||
let database = new Config(Parse.applicationId).database;
|
||||
const database = new Config(Parse.applicationId).database;
|
||||
database.create('_User', {
|
||||
username: 'user',
|
||||
_hashed_password: '$2a$10$8/wZJyEuiEaobBBqzTG.jeY.XSFJd0rzaN//ososvEI4yLqI.4aie',
|
||||
@@ -2370,7 +2370,7 @@ describe('Parse.User testing', () => {
|
||||
.equalTo('username', 'user')
|
||||
.first({useMasterKey: true});
|
||||
}).then((user) => {
|
||||
let authData = user.get('authData');
|
||||
const authData = user.get('authData');
|
||||
expect(user.get('username')).toEqual('user');
|
||||
expect(authData).toBeUndefined();
|
||||
done();
|
||||
@@ -2385,7 +2385,7 @@ describe('Parse.User testing', () => {
|
||||
req.object.set('foo', 'bar');
|
||||
res.success();
|
||||
});
|
||||
|
||||
|
||||
let originalSessionToken;
|
||||
let originalUserId;
|
||||
// Simulate anonymous user save
|
||||
@@ -2463,7 +2463,7 @@ describe('Parse.User testing', () => {
|
||||
});
|
||||
|
||||
it('should send email when upgrading from anon', (done) => {
|
||||
|
||||
|
||||
let emailCalled = false;
|
||||
let emailOptions;
|
||||
var emailAdapter = {
|
||||
@@ -2570,7 +2570,7 @@ describe('Parse.User testing', () => {
|
||||
expect(req.object.get('username')).toEqual('User');
|
||||
res.success();
|
||||
});
|
||||
let user = new Parse.User()
|
||||
const user = new Parse.User()
|
||||
user.setUsername('User');
|
||||
user.setPassword('pass');
|
||||
user.signUp().then(()=> {
|
||||
@@ -2587,7 +2587,7 @@ describe('Parse.User testing', () => {
|
||||
expect(req.user.get('han')).toEqual('solo');
|
||||
res.success({});
|
||||
});
|
||||
let user = new Parse.User();
|
||||
const user = new Parse.User();
|
||||
user.setUsername('harrison');
|
||||
user.setPassword('ford');
|
||||
user.signUp().then(() => {
|
||||
@@ -2645,19 +2645,19 @@ describe('Parse.User testing', () => {
|
||||
});
|
||||
|
||||
it('should not create extraneous session tokens', (done) => {
|
||||
let config = new Config(Parse.applicationId);
|
||||
const config = new Config(Parse.applicationId);
|
||||
config.database.loadSchema().then((s) => {
|
||||
// Lock down the _User class for creation
|
||||
return s.addClassIfNotExists('_User', {}, {create: {}})
|
||||
}).then(() => {
|
||||
let user = new Parse.User();
|
||||
const user = new Parse.User();
|
||||
return user.save({'username': 'user', 'password': 'pass'});
|
||||
}).then(() => {
|
||||
fail('should not be able to save the user');
|
||||
}, () => {
|
||||
return Promise.resolve();
|
||||
}).then(() => {
|
||||
let q = new Parse.Query('_Session');
|
||||
const q = new Parse.Query('_Session');
|
||||
return q.find({useMasterKey: true})
|
||||
}).then((res) => {
|
||||
// We should have no session created
|
||||
@@ -2713,7 +2713,7 @@ describe('Parse.User testing', () => {
|
||||
}, (err, res, body) => {
|
||||
Parse.User.become(body.sessionToken)
|
||||
.then(user => {
|
||||
let obj = new Parse.Object('TestObject');
|
||||
const obj = new Parse.Object('TestObject');
|
||||
obj.setACL(new Parse.ACL(user));
|
||||
return obj.save()
|
||||
.then(() => {
|
||||
@@ -2751,7 +2751,7 @@ describe('Parse.User testing', () => {
|
||||
}, (err, res, body) => {
|
||||
Parse.User.become(body.sessionToken)
|
||||
.then(user => {
|
||||
let obj = new Parse.Object('TestObject');
|
||||
const obj = new Parse.Object('TestObject');
|
||||
obj.setACL(new Parse.ACL(user));
|
||||
return obj.save()
|
||||
.then(() => {
|
||||
@@ -2768,8 +2768,8 @@ describe('Parse.User testing', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('should not fail querying non existing relations', done => {
|
||||
let user = new Parse.User();
|
||||
it('should not fail querying non existing relations', done => {
|
||||
const user = new Parse.User();
|
||||
user.set({
|
||||
username: 'hello',
|
||||
password: 'world'
|
||||
|
||||
@@ -14,7 +14,9 @@ describe('ParseWebSocketServer', function() {
|
||||
|
||||
it('can handle connect event when ws is open', function(done) {
|
||||
var onConnectCallback = jasmine.createSpy('onConnectCallback');
|
||||
var parseWebSocketServer = new ParseWebSocketServer({}, onConnectCallback, 5).server;
|
||||
var http = require('http');
|
||||
var server = http.createServer();
|
||||
var parseWebSocketServer = new ParseWebSocketServer(server, onConnectCallback, 5).server;
|
||||
var ws = {
|
||||
readyState: 0,
|
||||
OPEN: 0,
|
||||
@@ -27,6 +29,7 @@ describe('ParseWebSocketServer', function() {
|
||||
// Make sure we ping to the client
|
||||
setTimeout(function() {
|
||||
expect(ws.ping).toHaveBeenCalled();
|
||||
server.close();
|
||||
done();
|
||||
}, 10)
|
||||
});
|
||||
|
||||
+301
-7
@@ -147,14 +147,14 @@ describe("Password Policy: ", () => {
|
||||
reconfigureServer({
|
||||
appName: 'passwordPolicy',
|
||||
passwordPolicy: {
|
||||
validatorPattern: "abc" // string is not a valid setting
|
||||
validatorPattern: 1234 // number is not a valid setting
|
||||
},
|
||||
publicServerURL: "http://localhost:8378/1"
|
||||
}).then(() => {
|
||||
fail('passwordPolicy.validatorPattern type test failed');
|
||||
done();
|
||||
}).catch(err => {
|
||||
expect(err).toEqual('passwordPolicy.validatorPattern must be a RegExp.');
|
||||
expect(err).toEqual('passwordPolicy.validatorPattern must be a regex string or RegExp object.');
|
||||
done();
|
||||
});
|
||||
});
|
||||
@@ -197,6 +197,28 @@ describe("Password Policy: ", () => {
|
||||
})
|
||||
});
|
||||
|
||||
it('signup should fail if password does not conform to the policy enforced using validatorPattern string', (done) => {
|
||||
const user = new Parse.User();
|
||||
reconfigureServer({
|
||||
appName: 'passwordPolicy',
|
||||
passwordPolicy: {
|
||||
validatorPattern: "^.{8,}" // password should contain at least 8 char
|
||||
},
|
||||
publicServerURL: "http://localhost:8378/1"
|
||||
}).then(() => {
|
||||
user.setUsername("user1");
|
||||
user.setPassword("less");
|
||||
user.set('email', 'user1@parse.com');
|
||||
user.signUp().then(() => {
|
||||
fail('Should have failed as password does not conform to the policy.');
|
||||
done();
|
||||
}).catch((error) => {
|
||||
expect(error.code).toEqual(142);
|
||||
done();
|
||||
});
|
||||
})
|
||||
});
|
||||
|
||||
it('signup should succeed if password conforms to the policy enforced using validatorPattern', (done) => {
|
||||
const user = new Parse.User();
|
||||
reconfigureServer({
|
||||
@@ -231,6 +253,40 @@ describe("Password Policy: ", () => {
|
||||
})
|
||||
});
|
||||
|
||||
it('signup should succeed if password conforms to the policy enforced using validatorPattern string', (done) => {
|
||||
const user = new Parse.User();
|
||||
reconfigureServer({
|
||||
appName: 'passwordPolicy',
|
||||
passwordPolicy: {
|
||||
validatorPattern: "[!@#$]+" // password should contain at least one special char
|
||||
},
|
||||
publicServerURL: "http://localhost:8378/1"
|
||||
}).then(() => {
|
||||
user.setUsername("user1");
|
||||
user.setPassword("p@sswrod");
|
||||
user.set('email', 'user1@parse.com');
|
||||
user.signUp().then(() => {
|
||||
Parse.User.logOut().then(() => {
|
||||
Parse.User.logIn("user1", "p@sswrod").then(function () {
|
||||
done();
|
||||
}).catch((err) => {
|
||||
jfail(err);
|
||||
fail("Should be able to login");
|
||||
done();
|
||||
});
|
||||
}).catch((error) => {
|
||||
jfail(error);
|
||||
fail('logout should have succeeded');
|
||||
done();
|
||||
});
|
||||
}).catch((error) => {
|
||||
jfail(error);
|
||||
fail('Signup should have succeeded as password conforms to the policy.');
|
||||
done();
|
||||
});
|
||||
})
|
||||
});
|
||||
|
||||
it('signup should fail if password does not conform to the policy enforced using validatorCallback', (done) => {
|
||||
const user = new Parse.User();
|
||||
reconfigureServer({
|
||||
@@ -409,12 +465,12 @@ describe("Password Policy: ", () => {
|
||||
fail("should login with new password");
|
||||
done();
|
||||
});
|
||||
}).catch((error)=> {
|
||||
}).catch((error) => {
|
||||
jfail(error);
|
||||
fail("Failed to POST request password reset");
|
||||
done();
|
||||
});
|
||||
}).catch((error)=> {
|
||||
}).catch((error) => {
|
||||
jfail(error);
|
||||
fail("Failed to get the reset link");
|
||||
done();
|
||||
@@ -839,7 +895,7 @@ describe("Password Policy: ", () => {
|
||||
reconfigureServer({
|
||||
appName: 'passwordPolicy',
|
||||
passwordPolicy: {
|
||||
maxPasswordAge: 0.5/(24*60*60) // 0.5 sec
|
||||
maxPasswordAge: 0.5 / (24 * 60 * 60) // 0.5 sec
|
||||
},
|
||||
publicServerURL: "http://localhost:8378/1"
|
||||
}).then(() => {
|
||||
@@ -880,7 +936,7 @@ describe("Password Policy: ", () => {
|
||||
reconfigureServer({
|
||||
appName: 'passwordPolicy',
|
||||
passwordPolicy: {
|
||||
maxPasswordAge: 0.5/(24*60*60) // 0.5 sec
|
||||
maxPasswordAge: 0.5 / (24 * 60 * 60) // 0.5 sec
|
||||
},
|
||||
publicServerURL: "http://localhost:8378/1"
|
||||
}).then(() => {
|
||||
@@ -979,7 +1035,7 @@ describe("Password Policy: ", () => {
|
||||
appName: 'passwordPolicy',
|
||||
emailAdapter: emailAdapter,
|
||||
passwordPolicy: {
|
||||
maxPasswordAge: 0.5/(24*60*60) // 0.5 sec
|
||||
maxPasswordAge: 0.5 / (24 * 60 * 60) // 0.5 sec
|
||||
},
|
||||
publicServerURL: "http://localhost:8378/1"
|
||||
}).then(() => {
|
||||
@@ -1010,4 +1066,242 @@ describe("Password Policy: ", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('should fail if passwordPolicy.maxPasswordHistory is not a number', done => {
|
||||
reconfigureServer({
|
||||
appName: 'passwordPolicy',
|
||||
passwordPolicy: {
|
||||
maxPasswordHistory: "not a number"
|
||||
},
|
||||
publicServerURL: "http://localhost:8378/1"
|
||||
}).then(() => {
|
||||
fail('passwordPolicy.maxPasswordHistory "not a number" test failed');
|
||||
done();
|
||||
}).catch(err => {
|
||||
expect(err).toEqual('passwordPolicy.maxPasswordHistory must be an integer ranging 0 - 20');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should fail if passwordPolicy.maxPasswordHistory is a negative number', done => {
|
||||
reconfigureServer({
|
||||
appName: 'passwordPolicy',
|
||||
passwordPolicy: {
|
||||
maxPasswordHistory: -10
|
||||
},
|
||||
publicServerURL: "http://localhost:8378/1"
|
||||
}).then(() => {
|
||||
fail('passwordPolicy.maxPasswordHistory negative number test failed');
|
||||
done();
|
||||
}).catch(err => {
|
||||
expect(err).toEqual('passwordPolicy.maxPasswordHistory must be an integer ranging 0 - 20');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should fail if passwordPolicy.maxPasswordHistory is greater than 20', done => {
|
||||
reconfigureServer({
|
||||
appName: 'passwordPolicy',
|
||||
passwordPolicy: {
|
||||
maxPasswordHistory: 21
|
||||
},
|
||||
publicServerURL: "http://localhost:8378/1"
|
||||
}).then(() => {
|
||||
fail('passwordPolicy.maxPasswordHistory negative number test failed');
|
||||
done();
|
||||
}).catch(err => {
|
||||
expect(err).toEqual('passwordPolicy.maxPasswordHistory must be an integer ranging 0 - 20');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should fail to reset if the new password is same as the last password', done => {
|
||||
const user = new Parse.User();
|
||||
const emailAdapter = {
|
||||
sendVerificationEmail: () => Promise.resolve(),
|
||||
sendPasswordResetEmail: options => {
|
||||
requestp.get({
|
||||
uri: options.link,
|
||||
followRedirect: false,
|
||||
simple: false,
|
||||
resolveWithFullResponse: true
|
||||
}).then(response => {
|
||||
expect(response.statusCode).toEqual(302);
|
||||
const re = /http:\/\/localhost:8378\/1\/apps\/choose_password\?token=([a-zA-Z0-9]+)\&id=test\&username=user1/;
|
||||
const match = response.body.match(re);
|
||||
if (!match) {
|
||||
fail("should have a token");
|
||||
return Promise.reject("Invalid password link");
|
||||
}
|
||||
return Promise.resolve(match[1]); // token
|
||||
}).then(token => {
|
||||
return new Promise((resolve, reject) => {
|
||||
requestp.post({
|
||||
uri: "http://localhost:8378/1/apps/test/request_password_reset",
|
||||
body: `new_password=user1&token=${token}&username=user1`,
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded'
|
||||
},
|
||||
followRedirect: false,
|
||||
simple: false,
|
||||
resolveWithFullResponse: true
|
||||
}).then(response => {
|
||||
resolve([response, token]);
|
||||
}).catch(error => {
|
||||
reject(error);
|
||||
});
|
||||
});
|
||||
}).then(data => {
|
||||
const response = data[0];
|
||||
const token = data[1];
|
||||
expect(response.statusCode).toEqual(302);
|
||||
expect(response.body).toEqual(`Found. Redirecting to http://localhost:8378/1/apps/choose_password?username=user1&token=${token}&id=test&error=New%20password%20should%20not%20be%20the%20same%20as%20last%201%20passwords.&app=passwordPolicy`);
|
||||
done();
|
||||
return Promise.resolve();
|
||||
}).catch(error => {
|
||||
jfail(error);
|
||||
fail("Repeat password test failed");
|
||||
done();
|
||||
});
|
||||
},
|
||||
sendMail: () => {
|
||||
}
|
||||
};
|
||||
reconfigureServer({
|
||||
appName: 'passwordPolicy',
|
||||
verifyUserEmails: false,
|
||||
emailAdapter: emailAdapter,
|
||||
passwordPolicy: {
|
||||
maxPasswordHistory: 1
|
||||
},
|
||||
publicServerURL: "http://localhost:8378/1"
|
||||
}).then(() => {
|
||||
user.setUsername("user1");
|
||||
user.setPassword("user1");
|
||||
user.set('email', 'user1@parse.com');
|
||||
user.signUp().then(() => {
|
||||
return Parse.User.logOut();
|
||||
}).then(() => {
|
||||
return Parse.User.requestPasswordReset('user1@parse.com');
|
||||
}).catch(error => {
|
||||
jfail(error);
|
||||
fail("SignUp or reset request failed");
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
it('should fail if the new password is same as the previous one', done => {
|
||||
const user = new Parse.User();
|
||||
|
||||
reconfigureServer({
|
||||
appName: 'passwordPolicy',
|
||||
verifyUserEmails: false,
|
||||
passwordPolicy: {
|
||||
maxPasswordHistory: 5
|
||||
},
|
||||
publicServerURL: "http://localhost:8378/1"
|
||||
}).then(() => {
|
||||
user.setUsername("user1");
|
||||
user.setPassword("user1");
|
||||
user.set('email', 'user1@parse.com');
|
||||
user.signUp().then(() => {
|
||||
// try to set the same password as the previous one
|
||||
user.setPassword('user1');
|
||||
return user.save();
|
||||
}).then(() => {
|
||||
fail("should have failed because the new password is same as the old");
|
||||
done();
|
||||
}).catch(error => {
|
||||
expect(error.message).toEqual('New password should not be the same as last 5 passwords.');
|
||||
expect(error.code).toEqual(Parse.Error.VALIDATION_ERROR);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should fail if the new password is same as the 5th oldest one and policy does not allow the previous 5', done => {
|
||||
const user = new Parse.User();
|
||||
|
||||
reconfigureServer({
|
||||
appName: 'passwordPolicy',
|
||||
verifyUserEmails: false,
|
||||
passwordPolicy: {
|
||||
maxPasswordHistory: 5
|
||||
},
|
||||
publicServerURL: "http://localhost:8378/1"
|
||||
}).then(() => {
|
||||
user.setUsername("user1");
|
||||
user.setPassword("user1");
|
||||
user.set('email', 'user1@parse.com');
|
||||
user.signUp().then(() => {
|
||||
// build history
|
||||
user.setPassword('user2');
|
||||
return user.save();
|
||||
}).then(() => {
|
||||
user.setPassword('user3');
|
||||
return user.save();
|
||||
}).then(() => {
|
||||
user.setPassword('user4');
|
||||
return user.save();
|
||||
}).then(() => {
|
||||
user.setPassword('user5');
|
||||
return user.save();
|
||||
}).then(() => {
|
||||
// set the same password as the initial one
|
||||
user.setPassword('user1');
|
||||
return user.save();
|
||||
}).then(() => {
|
||||
fail("should have failed because the new password is same as the old");
|
||||
done();
|
||||
}).catch(error => {
|
||||
expect(error.message).toEqual('New password should not be the same as last 5 passwords.');
|
||||
expect(error.code).toEqual(Parse.Error.VALIDATION_ERROR);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should succeed if the new password is same as the 6th oldest one and policy does not allow only previous 5', done => {
|
||||
const user = new Parse.User();
|
||||
|
||||
reconfigureServer({
|
||||
appName: 'passwordPolicy',
|
||||
verifyUserEmails: false,
|
||||
passwordPolicy: {
|
||||
maxPasswordHistory: 5
|
||||
},
|
||||
publicServerURL: "http://localhost:8378/1"
|
||||
}).then(() => {
|
||||
user.setUsername("user1");
|
||||
user.setPassword("user1");
|
||||
user.set('email', 'user1@parse.com');
|
||||
user.signUp().then(() => {
|
||||
// build history
|
||||
user.setPassword('user2');
|
||||
return user.save();
|
||||
}).then(() => {
|
||||
user.setPassword('user3');
|
||||
return user.save();
|
||||
}).then(() => {
|
||||
user.setPassword('user4');
|
||||
return user.save();
|
||||
}).then(() => {
|
||||
user.setPassword('user5');
|
||||
return user.save();
|
||||
}).then(() => {
|
||||
user.setPassword('user6'); // this pushes initial password out of history
|
||||
return user.save();
|
||||
}).then(() => {
|
||||
// set the same password as the initial one
|
||||
user.setPassword('user1');
|
||||
return user.save();
|
||||
}).then(() => {
|
||||
done();
|
||||
}).catch(() => {
|
||||
fail("should have succeeded because the new password is not in history");
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
})
|
||||
|
||||
@@ -8,9 +8,9 @@ describe('Pointer Permissions', () => {
|
||||
});
|
||||
|
||||
it('should work with find', (done) => {
|
||||
let config = new Config(Parse.applicationId);
|
||||
let user = new Parse.User();
|
||||
let user2 = new Parse.User();
|
||||
const config = new Config(Parse.applicationId);
|
||||
const user = new Parse.User();
|
||||
const user2 = new Parse.User();
|
||||
user.set({
|
||||
username: 'user1',
|
||||
password: 'password'
|
||||
@@ -19,8 +19,8 @@ describe('Pointer Permissions', () => {
|
||||
username: 'user2',
|
||||
password: 'password'
|
||||
});
|
||||
let obj = new Parse.Object('AnObject');
|
||||
let obj2 = new Parse.Object('AnObject');
|
||||
const obj = new Parse.Object('AnObject');
|
||||
const obj2 = new Parse.Object('AnObject');
|
||||
|
||||
Parse.Object.saveAll([user, user2]).then(() => {
|
||||
obj.set('owner', user);
|
||||
@@ -33,7 +33,7 @@ describe('Pointer Permissions', () => {
|
||||
}).then(() => {
|
||||
return Parse.User.logIn('user1', 'password');
|
||||
}).then(() => {
|
||||
let q = new Parse.Query('AnObject');
|
||||
const q = new Parse.Query('AnObject');
|
||||
return q.find();
|
||||
}).then((res) => {
|
||||
expect(res.length).toBe(1);
|
||||
@@ -47,9 +47,9 @@ describe('Pointer Permissions', () => {
|
||||
|
||||
|
||||
it('should work with write', (done) => {
|
||||
let config = new Config(Parse.applicationId);
|
||||
let user = new Parse.User();
|
||||
let user2 = new Parse.User();
|
||||
const config = new Config(Parse.applicationId);
|
||||
const user = new Parse.User();
|
||||
const user2 = new Parse.User();
|
||||
user.set({
|
||||
username: 'user1',
|
||||
password: 'password'
|
||||
@@ -58,8 +58,8 @@ describe('Pointer Permissions', () => {
|
||||
username: 'user2',
|
||||
password: 'password'
|
||||
});
|
||||
let obj = new Parse.Object('AnObject');
|
||||
let obj2 = new Parse.Object('AnObject');
|
||||
const obj = new Parse.Object('AnObject');
|
||||
const obj2 = new Parse.Object('AnObject');
|
||||
|
||||
Parse.Object.saveAll([user, user2]).then(() => {
|
||||
obj.set('owner', user);
|
||||
@@ -91,7 +91,7 @@ describe('Pointer Permissions', () => {
|
||||
fail('User should be able to update');
|
||||
return Promise.resolve();
|
||||
}).then(() => {
|
||||
let q = new Parse.Query('AnObject');
|
||||
const q = new Parse.Query('AnObject');
|
||||
return q.find();
|
||||
}, () => {
|
||||
fail('should login with user 2');
|
||||
@@ -112,9 +112,9 @@ describe('Pointer Permissions', () => {
|
||||
});
|
||||
|
||||
it('should let a proper user find', (done) => {
|
||||
let config = new Config(Parse.applicationId);
|
||||
let user = new Parse.User();
|
||||
let user2 = new Parse.User();
|
||||
const config = new Config(Parse.applicationId);
|
||||
const user = new Parse.User();
|
||||
const user2 = new Parse.User();
|
||||
user.set({
|
||||
username: 'user1',
|
||||
password: 'password'
|
||||
@@ -123,8 +123,8 @@ describe('Pointer Permissions', () => {
|
||||
username: 'user2',
|
||||
password: 'password'
|
||||
});
|
||||
let obj = new Parse.Object('AnObject');
|
||||
let obj2 = new Parse.Object('AnObject');
|
||||
const obj = new Parse.Object('AnObject');
|
||||
const obj2 = new Parse.Object('AnObject');
|
||||
user.signUp().then(() => {
|
||||
return user2.signUp()
|
||||
}).then(() => {
|
||||
@@ -137,18 +137,18 @@ describe('Pointer Permissions', () => {
|
||||
return schema.updateClass('AnObject', {}, {find: {}, get:{}, readUserFields: ['owner']})
|
||||
});
|
||||
}).then(() => {
|
||||
let q = new Parse.Query('AnObject');
|
||||
const q = new Parse.Query('AnObject');
|
||||
return q.find();
|
||||
}).then((res) => {
|
||||
expect(res.length).toBe(0);
|
||||
}).then(() => {
|
||||
return Parse.User.logIn('user2', 'password');
|
||||
}).then(() => {
|
||||
let q = new Parse.Query('AnObject');
|
||||
const q = new Parse.Query('AnObject');
|
||||
return q.find();
|
||||
}).then((res) => {
|
||||
expect(res.length).toBe(0);
|
||||
let q = new Parse.Query('AnObject');
|
||||
const q = new Parse.Query('AnObject');
|
||||
return q.get(obj.id);
|
||||
}).then(() => {
|
||||
fail('User 2 should not get the obj1 object');
|
||||
@@ -159,7 +159,7 @@ describe('Pointer Permissions', () => {
|
||||
}).then(() => {
|
||||
return Parse.User.logIn('user1', 'password');
|
||||
}).then(() => {
|
||||
let q = new Parse.Query('AnObject');
|
||||
const q = new Parse.Query('AnObject');
|
||||
return q.find();
|
||||
}).then((res) => {
|
||||
expect(res.length).toBe(1);
|
||||
@@ -172,13 +172,13 @@ describe('Pointer Permissions', () => {
|
||||
});
|
||||
|
||||
it('should not allow creating objects', (done) => {
|
||||
let config = new Config(Parse.applicationId);
|
||||
let user = new Parse.User();
|
||||
const config = new Config(Parse.applicationId);
|
||||
const user = new Parse.User();
|
||||
user.set({
|
||||
username: 'user1',
|
||||
password: 'password'
|
||||
});
|
||||
let obj = new Parse.Object('AnObject');
|
||||
const obj = new Parse.Object('AnObject');
|
||||
user.save().then(() => {
|
||||
return config.database.loadSchema().then((schema) => {
|
||||
return schema.addClassIfNotExists('AnObject', {owner: {type:'Pointer', targetClass: '_User'}}, {create: {}, writeUserFields: ['owner'], readUserFields: ['owner']});
|
||||
@@ -198,9 +198,9 @@ describe('Pointer Permissions', () => {
|
||||
});
|
||||
|
||||
it('should handle multiple writeUserFields', done => {
|
||||
let config = new Config(Parse.applicationId);
|
||||
let user = new Parse.User();
|
||||
let user2 = new Parse.User();
|
||||
const config = new Config(Parse.applicationId);
|
||||
const user = new Parse.User();
|
||||
const user2 = new Parse.User();
|
||||
user.set({
|
||||
username: 'user1',
|
||||
password: 'password'
|
||||
@@ -209,7 +209,7 @@ describe('Pointer Permissions', () => {
|
||||
username: 'user2',
|
||||
password: 'password'
|
||||
});
|
||||
let obj = new Parse.Object('AnObject');
|
||||
const obj = new Parse.Object('AnObject');
|
||||
Parse.Object.saveAll([user, user2])
|
||||
.then(() => {
|
||||
obj.set('owner', user);
|
||||
@@ -224,7 +224,7 @@ describe('Pointer Permissions', () => {
|
||||
.then(() => obj.save({hello: 'fromUser2'}))
|
||||
.then(() => Parse.User.logOut())
|
||||
.then(() => {
|
||||
let q = new Parse.Query('AnObject');
|
||||
const q = new Parse.Query('AnObject');
|
||||
return q.first();
|
||||
})
|
||||
.then(result => {
|
||||
@@ -237,7 +237,7 @@ describe('Pointer Permissions', () => {
|
||||
});
|
||||
|
||||
it('should prevent creating pointer permission on missing field', (done) => {
|
||||
let config = new Config(Parse.applicationId);
|
||||
const config = new Config(Parse.applicationId);
|
||||
config.database.loadSchema().then((schema) => {
|
||||
return schema.addClassIfNotExists('AnObject', {}, {create: {}, writeUserFields: ['owner'], readUserFields: ['owner']});
|
||||
}).then(() => {
|
||||
@@ -250,7 +250,7 @@ describe('Pointer Permissions', () => {
|
||||
});
|
||||
|
||||
it('should prevent creating pointer permission on bad field', (done) => {
|
||||
let config = new Config(Parse.applicationId);
|
||||
const config = new Config(Parse.applicationId);
|
||||
config.database.loadSchema().then((schema) => {
|
||||
return schema.addClassIfNotExists('AnObject', {owner: {type: 'String'}}, {create: {}, writeUserFields: ['owner'], readUserFields: ['owner']});
|
||||
}).then(() => {
|
||||
@@ -263,8 +263,8 @@ describe('Pointer Permissions', () => {
|
||||
});
|
||||
|
||||
it('should prevent creating pointer permission on bad field', (done) => {
|
||||
let config = new Config(Parse.applicationId);
|
||||
let object = new Parse.Object('AnObject');
|
||||
const config = new Config(Parse.applicationId);
|
||||
const object = new Parse.Object('AnObject');
|
||||
object.set('owner', 'value');
|
||||
object.save().then(() => {
|
||||
return config.database.loadSchema();
|
||||
@@ -288,9 +288,9 @@ describe('Pointer Permissions', () => {
|
||||
|
||||
The owner is another user than the ACL
|
||||
*/
|
||||
let config = new Config(Parse.applicationId);
|
||||
let user = new Parse.User();
|
||||
let user2 = new Parse.User();
|
||||
const config = new Config(Parse.applicationId);
|
||||
const user = new Parse.User();
|
||||
const user2 = new Parse.User();
|
||||
user.set({
|
||||
username: 'user1',
|
||||
password: 'password'
|
||||
@@ -299,9 +299,9 @@ describe('Pointer Permissions', () => {
|
||||
username: 'user2',
|
||||
password: 'password'
|
||||
});
|
||||
let obj = new Parse.Object('AnObject');
|
||||
const obj = new Parse.Object('AnObject');
|
||||
Parse.Object.saveAll([user, user2]).then(() => {
|
||||
let ACL = new Parse.ACL();
|
||||
const ACL = new Parse.ACL();
|
||||
ACL.setReadAccess(user, true);
|
||||
ACL.setWriteAccess(user, true);
|
||||
obj.setACL(ACL);
|
||||
@@ -333,9 +333,9 @@ describe('Pointer Permissions', () => {
|
||||
PointerPerm: "owner"
|
||||
ACL: logged in user has access
|
||||
*/
|
||||
let config = new Config(Parse.applicationId);
|
||||
let user = new Parse.User();
|
||||
let user2 = new Parse.User();
|
||||
const config = new Config(Parse.applicationId);
|
||||
const user = new Parse.User();
|
||||
const user2 = new Parse.User();
|
||||
user.set({
|
||||
username: 'user1',
|
||||
password: 'password'
|
||||
@@ -344,9 +344,9 @@ describe('Pointer Permissions', () => {
|
||||
username: 'user2',
|
||||
password: 'password'
|
||||
});
|
||||
let obj = new Parse.Object('AnObject');
|
||||
const obj = new Parse.Object('AnObject');
|
||||
Parse.Object.saveAll([user, user2]).then(() => {
|
||||
let ACL = new Parse.ACL();
|
||||
const ACL = new Parse.ACL();
|
||||
ACL.setReadAccess(user, true);
|
||||
ACL.setWriteAccess(user, true);
|
||||
obj.setACL(ACL);
|
||||
@@ -378,9 +378,9 @@ describe('Pointer Permissions', () => {
|
||||
PointerPerm: "owner"
|
||||
ACL: logged in user has access
|
||||
*/
|
||||
let config = new Config(Parse.applicationId);
|
||||
let user = new Parse.User();
|
||||
let user2 = new Parse.User();
|
||||
const config = new Config(Parse.applicationId);
|
||||
const user = new Parse.User();
|
||||
const user2 = new Parse.User();
|
||||
user.set({
|
||||
username: 'user1',
|
||||
password: 'password'
|
||||
@@ -389,9 +389,9 @@ describe('Pointer Permissions', () => {
|
||||
username: 'user2',
|
||||
password: 'password'
|
||||
});
|
||||
let obj = new Parse.Object('AnObject');
|
||||
const obj = new Parse.Object('AnObject');
|
||||
Parse.Object.saveAll([user, user2]).then(() => {
|
||||
let ACL = new Parse.ACL();
|
||||
const ACL = new Parse.ACL();
|
||||
ACL.setWriteAccess(user, true);
|
||||
ACL.setWriteAccess(user2, true);
|
||||
obj.setACL(ACL);
|
||||
@@ -425,9 +425,9 @@ describe('Pointer Permissions', () => {
|
||||
|
||||
The owner is another user than the ACL
|
||||
*/
|
||||
let config = new Config(Parse.applicationId);
|
||||
let user = new Parse.User();
|
||||
let user2 = new Parse.User();
|
||||
const config = new Config(Parse.applicationId);
|
||||
const user = new Parse.User();
|
||||
const user2 = new Parse.User();
|
||||
user.set({
|
||||
username: 'user1',
|
||||
password: 'password'
|
||||
@@ -436,9 +436,9 @@ describe('Pointer Permissions', () => {
|
||||
username: 'user2',
|
||||
password: 'password'
|
||||
});
|
||||
let obj = new Parse.Object('AnObject');
|
||||
const obj = new Parse.Object('AnObject');
|
||||
Parse.Object.saveAll([user, user2]).then(() => {
|
||||
let ACL = new Parse.ACL();
|
||||
const ACL = new Parse.ACL();
|
||||
ACL.setReadAccess(user, true);
|
||||
ACL.setWriteAccess(user, true);
|
||||
obj.setACL(ACL);
|
||||
@@ -470,9 +470,9 @@ describe('Pointer Permissions', () => {
|
||||
PointerPerm: "owner" : read
|
||||
ACL: logged in user has access
|
||||
*/
|
||||
let config = new Config(Parse.applicationId);
|
||||
let user = new Parse.User();
|
||||
let user2 = new Parse.User();
|
||||
const config = new Config(Parse.applicationId);
|
||||
const user = new Parse.User();
|
||||
const user2 = new Parse.User();
|
||||
user.set({
|
||||
username: 'user1',
|
||||
password: 'password'
|
||||
@@ -481,9 +481,9 @@ describe('Pointer Permissions', () => {
|
||||
username: 'user2',
|
||||
password: 'password'
|
||||
});
|
||||
let obj = new Parse.Object('AnObject');
|
||||
const obj = new Parse.Object('AnObject');
|
||||
Parse.Object.saveAll([user, user2]).then(() => {
|
||||
let ACL = new Parse.ACL();
|
||||
const ACL = new Parse.ACL();
|
||||
ACL.setReadAccess(user, true);
|
||||
ACL.setWriteAccess(user, true);
|
||||
ACL.setReadAccess(user2, true);
|
||||
@@ -517,9 +517,9 @@ describe('Pointer Permissions', () => {
|
||||
PointerPerm: "owner" : read // proper owner
|
||||
ACL: logged in user has not access
|
||||
*/
|
||||
let config = new Config(Parse.applicationId);
|
||||
let user = new Parse.User();
|
||||
let user2 = new Parse.User();
|
||||
const config = new Config(Parse.applicationId);
|
||||
const user = new Parse.User();
|
||||
const user2 = new Parse.User();
|
||||
user.set({
|
||||
username: 'user1',
|
||||
password: 'password'
|
||||
@@ -528,9 +528,9 @@ describe('Pointer Permissions', () => {
|
||||
username: 'user2',
|
||||
password: 'password'
|
||||
});
|
||||
let obj = new Parse.Object('AnObject');
|
||||
const obj = new Parse.Object('AnObject');
|
||||
Parse.Object.saveAll([user, user2]).then(() => {
|
||||
let ACL = new Parse.ACL();
|
||||
const ACL = new Parse.ACL();
|
||||
ACL.setReadAccess(user, true);
|
||||
ACL.setWriteAccess(user, true);
|
||||
obj.setACL(ACL);
|
||||
@@ -556,8 +556,8 @@ describe('Pointer Permissions', () => {
|
||||
});
|
||||
|
||||
it('should let master key find objects', (done) => {
|
||||
let config = new Config(Parse.applicationId);
|
||||
let object = new Parse.Object('AnObject');
|
||||
const config = new Config(Parse.applicationId);
|
||||
const object = new Parse.Object('AnObject');
|
||||
object.set('hello', 'world');
|
||||
return object.save().then(() => {
|
||||
return config.database.loadSchema().then((schema) => {
|
||||
@@ -565,7 +565,7 @@ describe('Pointer Permissions', () => {
|
||||
return schema.updateClass('AnObject', {owner: {type: 'Pointer', targetClass: '_User'}}, {find: {}, get: {}, readUserFields: ['owner']});
|
||||
});
|
||||
}).then(() => {
|
||||
let q = new Parse.Query('AnObject');
|
||||
const q = new Parse.Query('AnObject');
|
||||
return q.find();
|
||||
}).then(() => {
|
||||
|
||||
@@ -573,7 +573,7 @@ describe('Pointer Permissions', () => {
|
||||
expect(err.code).toBe(101);
|
||||
return Promise.resolve();
|
||||
}).then(() => {
|
||||
let q = new Parse.Query('AnObject');
|
||||
const q = new Parse.Query('AnObject');
|
||||
return q.find({useMasterKey: true});
|
||||
}).then((objects) => {
|
||||
expect(objects.length).toBe(1);
|
||||
@@ -585,8 +585,8 @@ describe('Pointer Permissions', () => {
|
||||
});
|
||||
|
||||
it('should let master key get objects', (done) => {
|
||||
let config = new Config(Parse.applicationId);
|
||||
let object = new Parse.Object('AnObject');
|
||||
const config = new Config(Parse.applicationId);
|
||||
const object = new Parse.Object('AnObject');
|
||||
object.set('hello', 'world');
|
||||
return object.save().then(() => {
|
||||
return config.database.loadSchema().then((schema) => {
|
||||
@@ -594,7 +594,7 @@ describe('Pointer Permissions', () => {
|
||||
return schema.updateClass('AnObject', {owner: {type: 'Pointer', targetClass: '_User'}}, {find: {}, get: {}, readUserFields: ['owner']});
|
||||
});
|
||||
}).then(() => {
|
||||
let q = new Parse.Query('AnObject');
|
||||
const q = new Parse.Query('AnObject');
|
||||
return q.get(object.id);
|
||||
}).then(() => {
|
||||
|
||||
@@ -602,7 +602,7 @@ describe('Pointer Permissions', () => {
|
||||
expect(err.code).toBe(101);
|
||||
return Promise.resolve();
|
||||
}).then(() => {
|
||||
let q = new Parse.Query('AnObject');
|
||||
const q = new Parse.Query('AnObject');
|
||||
return q.get(object.id, {useMasterKey: true});
|
||||
}).then((objectAgain) => {
|
||||
expect(objectAgain).not.toBeUndefined();
|
||||
@@ -616,8 +616,8 @@ describe('Pointer Permissions', () => {
|
||||
|
||||
|
||||
it('should let master key update objects', (done) => {
|
||||
let config = new Config(Parse.applicationId);
|
||||
let object = new Parse.Object('AnObject');
|
||||
const config = new Config(Parse.applicationId);
|
||||
const object = new Parse.Object('AnObject');
|
||||
object.set('hello', 'world');
|
||||
return object.save().then(() => {
|
||||
return config.database.loadSchema().then((schema) => {
|
||||
@@ -643,8 +643,8 @@ describe('Pointer Permissions', () => {
|
||||
});
|
||||
|
||||
it('should let master key delete objects', (done) => {
|
||||
let config = new Config(Parse.applicationId);
|
||||
let object = new Parse.Object('AnObject');
|
||||
const config = new Config(Parse.applicationId);
|
||||
const object = new Parse.Object('AnObject');
|
||||
object.set('hello', 'world');
|
||||
return object.save().then(() => {
|
||||
return config.database.loadSchema().then((schema) => {
|
||||
@@ -669,7 +669,7 @@ describe('Pointer Permissions', () => {
|
||||
});
|
||||
|
||||
it('should fail with invalid pointer perms', (done) => {
|
||||
let config = new Config(Parse.applicationId);
|
||||
const config = new Config(Parse.applicationId);
|
||||
config.database.loadSchema().then((schema) => {
|
||||
// Lock the update, and let only owner write
|
||||
return schema.addClassIfNotExists('AnObject', {owner: {type: 'Pointer', targetClass: '_User'}}, {delete: {}, writeUserFields: 'owner'});
|
||||
@@ -680,7 +680,7 @@ describe('Pointer Permissions', () => {
|
||||
});
|
||||
|
||||
it('should fail with invalid pointer perms', (done) => {
|
||||
let config = new Config(Parse.applicationId);
|
||||
const config = new Config(Parse.applicationId);
|
||||
config.database.loadSchema().then((schema) => {
|
||||
// Lock the update, and let only owner write
|
||||
return schema.addClassIfNotExists('AnObject', {owner: {type: 'Pointer', targetClass: '_User'}}, {delete: {}, writeUserFields: ['owner', 'invalid']});
|
||||
|
||||
@@ -20,7 +20,7 @@ function createProduct() {
|
||||
}
|
||||
|
||||
describe("test validate_receipt endpoint", () => {
|
||||
beforeEach( done => {
|
||||
beforeEach(done => {
|
||||
createProduct().then(done).fail(function(){
|
||||
done();
|
||||
});
|
||||
|
||||
+146
-118
@@ -2,10 +2,11 @@
|
||||
var PushController = require('../src/Controllers/PushController').PushController;
|
||||
var StatusHandler = require('../src/StatusHandler');
|
||||
var Config = require('../src/Config');
|
||||
var validatePushType = require('../src/Push/utils').validatePushType;
|
||||
|
||||
const successfulTransmissions = function(body, installations) {
|
||||
|
||||
let promises = installations.map((device) => {
|
||||
const promises = installations.map((device) => {
|
||||
return Promise.resolve({
|
||||
transmitted: true,
|
||||
device: device,
|
||||
@@ -17,7 +18,7 @@ const successfulTransmissions = function(body, installations) {
|
||||
|
||||
const successfulIOS = function(body, installations) {
|
||||
|
||||
let promises = installations.map((device) => {
|
||||
const promises = installations.map((device) => {
|
||||
return Promise.resolve({
|
||||
transmitted: device.deviceType == "ios",
|
||||
device: device,
|
||||
@@ -35,7 +36,7 @@ describe('PushController', () => {
|
||||
var validPushTypes = ['ios', 'android'];
|
||||
|
||||
expect(function(){
|
||||
PushController.validatePushType(where, validPushTypes);
|
||||
validatePushType(where, validPushTypes);
|
||||
}).not.toThrow();
|
||||
done();
|
||||
});
|
||||
@@ -48,7 +49,7 @@ describe('PushController', () => {
|
||||
var validPushTypes = ['ios', 'android'];
|
||||
|
||||
expect(function(){
|
||||
PushController.validatePushType(where, validPushTypes);
|
||||
validatePushType(where, validPushTypes);
|
||||
}).not.toThrow();
|
||||
done();
|
||||
});
|
||||
@@ -63,7 +64,7 @@ describe('PushController', () => {
|
||||
var validPushTypes = ['ios', 'android'];
|
||||
|
||||
expect(function(){
|
||||
PushController.validatePushType(where, validPushTypes);
|
||||
validatePushType(where, validPushTypes);
|
||||
}).not.toThrow();
|
||||
done();
|
||||
});
|
||||
@@ -76,7 +77,7 @@ describe('PushController', () => {
|
||||
var validPushTypes = ['ios', 'android'];
|
||||
|
||||
expect(function(){
|
||||
PushController.validatePushType(where, validPushTypes);
|
||||
validatePushType(where, validPushTypes);
|
||||
}).toThrow();
|
||||
done();
|
||||
});
|
||||
@@ -89,7 +90,7 @@ describe('PushController', () => {
|
||||
var validPushTypes = ['ios', 'android'];
|
||||
|
||||
expect(function(){
|
||||
PushController.validatePushType(where, validPushTypes);
|
||||
validatePushType(where, validPushTypes);
|
||||
}).toThrow();
|
||||
done();
|
||||
});
|
||||
@@ -131,37 +132,13 @@ describe('PushController', () => {
|
||||
});
|
||||
|
||||
it('properly increment badges', (done) => {
|
||||
|
||||
var payload = {data:{
|
||||
alert: "Hello World!",
|
||||
badge: "Increment",
|
||||
}}
|
||||
var installations = [];
|
||||
while(installations.length != 10) {
|
||||
let installation = new Parse.Object("_Installation");
|
||||
installation.set("installationId", "installation_"+installations.length);
|
||||
installation.set("deviceToken","device_token_"+installations.length)
|
||||
installation.set("badge", installations.length);
|
||||
installation.set("originalBadge", installations.length);
|
||||
installation.set("deviceType", "ios");
|
||||
installations.push(installation);
|
||||
}
|
||||
|
||||
while(installations.length != 15) {
|
||||
let installation = new Parse.Object("_Installation");
|
||||
installation.set("installationId", "installation_"+installations.length);
|
||||
installation.set("deviceToken","device_token_"+installations.length)
|
||||
installation.set("deviceType", "android");
|
||||
installations.push(installation);
|
||||
}
|
||||
|
||||
var pushAdapter = {
|
||||
send: function(body, installations) {
|
||||
var badge = body.data.badge;
|
||||
installations.forEach((installation) => {
|
||||
if (installation.deviceType == "ios") {
|
||||
expect(installation.badge).toEqual(badge);
|
||||
expect(installation.originalBadge+1).toEqual(installation.badge);
|
||||
expect(installation.originalBadge + 1).toEqual(installation.badge);
|
||||
} else {
|
||||
expect(installation.badge).toBeUndefined();
|
||||
}
|
||||
@@ -172,14 +149,39 @@ describe('PushController', () => {
|
||||
return ["ios", "android"];
|
||||
}
|
||||
}
|
||||
var payload = {data:{
|
||||
alert: "Hello World!",
|
||||
badge: "Increment",
|
||||
}}
|
||||
var installations = [];
|
||||
while(installations.length != 10) {
|
||||
const installation = new Parse.Object("_Installation");
|
||||
installation.set("installationId", "installation_" + installations.length);
|
||||
installation.set("deviceToken","device_token_" + installations.length)
|
||||
installation.set("badge", installations.length);
|
||||
installation.set("originalBadge", installations.length);
|
||||
installation.set("deviceType", "ios");
|
||||
installations.push(installation);
|
||||
}
|
||||
|
||||
while(installations.length != 15) {
|
||||
const installation = new Parse.Object("_Installation");
|
||||
installation.set("installationId", "installation_" + installations.length);
|
||||
installation.set("deviceToken","device_token_" + installations.length)
|
||||
installation.set("deviceType", "android");
|
||||
installations.push(installation);
|
||||
}
|
||||
var config = new Config(Parse.applicationId);
|
||||
var auth = {
|
||||
isMaster: true
|
||||
}
|
||||
|
||||
var pushController = new PushController(pushAdapter, Parse.applicationId, defaultConfiguration.push);
|
||||
Parse.Object.saveAll(installations).then(() => {
|
||||
var pushController = new PushController();
|
||||
reconfigureServer({
|
||||
push: { adapter: pushAdapter }
|
||||
}).then(() => {
|
||||
return Parse.Object.saveAll(installations)
|
||||
}).then(() => {
|
||||
return pushController.sendPush(payload, {}, config, auth);
|
||||
}).then(() => {
|
||||
done();
|
||||
@@ -187,26 +189,10 @@ describe('PushController', () => {
|
||||
jfail(err);
|
||||
done();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
it('properly set badges to 1', (done) => {
|
||||
|
||||
var payload = {data: {
|
||||
alert: "Hello World!",
|
||||
badge: 1,
|
||||
}}
|
||||
var installations = [];
|
||||
while(installations.length != 10) {
|
||||
var installation = new Parse.Object("_Installation");
|
||||
installation.set("installationId", "installation_"+installations.length);
|
||||
installation.set("deviceToken","device_token_"+installations.length)
|
||||
installation.set("badge", installations.length);
|
||||
installation.set("originalBadge", installations.length);
|
||||
installation.set("deviceType", "ios");
|
||||
installations.push(installation);
|
||||
}
|
||||
|
||||
var pushAdapter = {
|
||||
send: function(body, installations) {
|
||||
var badge = body.data.badge;
|
||||
@@ -221,13 +207,32 @@ describe('PushController', () => {
|
||||
}
|
||||
}
|
||||
|
||||
var payload = {data: {
|
||||
alert: "Hello World!",
|
||||
badge: 1,
|
||||
}}
|
||||
var installations = [];
|
||||
while(installations.length != 10) {
|
||||
var installation = new Parse.Object("_Installation");
|
||||
installation.set("installationId", "installation_" + installations.length);
|
||||
installation.set("deviceToken","device_token_" + installations.length)
|
||||
installation.set("badge", installations.length);
|
||||
installation.set("originalBadge", installations.length);
|
||||
installation.set("deviceType", "ios");
|
||||
installations.push(installation);
|
||||
}
|
||||
|
||||
var config = new Config(Parse.applicationId);
|
||||
var auth = {
|
||||
isMaster: true
|
||||
}
|
||||
|
||||
var pushController = new PushController(pushAdapter, Parse.applicationId, defaultConfiguration.push);
|
||||
Parse.Object.saveAll(installations).then(() => {
|
||||
var pushController = new PushController();
|
||||
reconfigureServer({
|
||||
push: { adapter: pushAdapter }
|
||||
}).then(() => {
|
||||
return Parse.Object.saveAll(installations)
|
||||
}).then(() => {
|
||||
return pushController.sendPush(payload, {}, config, auth);
|
||||
}).then(() => {
|
||||
done();
|
||||
@@ -235,7 +240,6 @@ describe('PushController', () => {
|
||||
fail("should not fail");
|
||||
done();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
it('properly set badges to 1 with complex query #2903 #3022', (done) => {
|
||||
@@ -249,8 +253,8 @@ describe('PushController', () => {
|
||||
var installations = [];
|
||||
while(installations.length != 10) {
|
||||
var installation = new Parse.Object("_Installation");
|
||||
installation.set("installationId", "installation_"+installations.length);
|
||||
installation.set("deviceToken","device_token_"+installations.length)
|
||||
installation.set("installationId", "installation_" + installations.length);
|
||||
installation.set("deviceToken","device_token_" + installations.length)
|
||||
installation.set("badge", installations.length);
|
||||
installation.set("originalBadge", installations.length);
|
||||
installation.set("deviceType", "ios");
|
||||
@@ -276,19 +280,28 @@ describe('PushController', () => {
|
||||
var auth = {
|
||||
isMaster: true
|
||||
}
|
||||
|
||||
var pushController = new PushController(pushAdapter, Parse.applicationId, defaultConfiguration.push);
|
||||
Parse.Object.saveAll(installations).then((installations) => {
|
||||
let objectIds = installations.map(installation => {
|
||||
var pushController = new PushController();
|
||||
reconfigureServer({
|
||||
push: {
|
||||
adapter: pushAdapter
|
||||
}
|
||||
}).then(() => {
|
||||
return Parse.Object.saveAll(installations)
|
||||
}).then((installations) => {
|
||||
const objectIds = installations.map(installation => {
|
||||
return installation.id;
|
||||
})
|
||||
let where = {
|
||||
const where = {
|
||||
objectId: {'$in': objectIds.slice(0, 5)}
|
||||
}
|
||||
return pushController.sendPush(payload, where, config, auth);
|
||||
}).then(() => {
|
||||
return new Promise((res) => {
|
||||
setTimeout(res, 300);
|
||||
});
|
||||
}).then(() => {
|
||||
expect(matchedInstallationsCount).toBe(5);
|
||||
let query = new Parse.Query(Parse.Installation);
|
||||
const query = new Parse.Query(Parse.Installation);
|
||||
query.equalTo('badge', 1);
|
||||
return query.find({useMasterKey: true});
|
||||
}).then((installations) => {
|
||||
@@ -304,9 +317,9 @@ describe('PushController', () => {
|
||||
|
||||
var installations = [];
|
||||
while(installations.length != 10) {
|
||||
let installation = new Parse.Object("_Installation");
|
||||
installation.set("installationId", "installation_"+installations.length);
|
||||
installation.set("deviceToken","device_token_"+installations.length)
|
||||
const installation = new Parse.Object("_Installation");
|
||||
installation.set("installationId", "installation_" + installations.length);
|
||||
installation.set("deviceToken","device_token_" + installations.length)
|
||||
installation.set("badge", installations.length);
|
||||
installation.set("originalBadge", installations.length);
|
||||
installation.set("deviceType", "ios");
|
||||
@@ -314,9 +327,9 @@ describe('PushController', () => {
|
||||
}
|
||||
|
||||
while(installations.length != 15) {
|
||||
let installation = new Parse.Object("_Installation");
|
||||
installation.set("installationId", "installation_"+installations.length);
|
||||
installation.set("deviceToken","device_token_"+installations.length)
|
||||
const installation = new Parse.Object("_Installation");
|
||||
installation.set("installationId", "installation_" + installations.length);
|
||||
installation.set("deviceToken","device_token_" + installations.length)
|
||||
installation.set("deviceType", "android");
|
||||
installations.push(installation);
|
||||
}
|
||||
@@ -338,46 +351,50 @@ describe('PushController', () => {
|
||||
var auth = {
|
||||
isMaster: true
|
||||
}
|
||||
|
||||
var pushController = new PushController(pushAdapter, Parse.applicationId, defaultConfiguration.push);
|
||||
Parse.Object.saveAll(installations).then(() => {
|
||||
return pushController.sendPush(payload, {}, config, auth);
|
||||
var pushController = new PushController();
|
||||
reconfigureServer({
|
||||
push: { adapter: pushAdapter }
|
||||
}).then(() => {
|
||||
return new Promise((resolve) => {
|
||||
setTimeout(() => {
|
||||
resolve();
|
||||
}, 1000);
|
||||
});
|
||||
}).then(() => {
|
||||
let query = new Parse.Query('_PushStatus');
|
||||
return query.find({useMasterKey: true});
|
||||
}).then((results) => {
|
||||
expect(results.length).toBe(1);
|
||||
let result = results[0];
|
||||
expect(result.createdAt instanceof Date).toBe(true);
|
||||
expect(result.updatedAt instanceof Date).toBe(true);
|
||||
expect(result.id.length).toBe(10);
|
||||
expect(result.get('source')).toEqual('rest');
|
||||
expect(result.get('query')).toEqual(JSON.stringify({}));
|
||||
expect(typeof result.get('payload')).toEqual("string");
|
||||
expect(JSON.parse(result.get('payload'))).toEqual(payload.data);
|
||||
expect(result.get('status')).toEqual('succeeded');
|
||||
expect(result.get('numSent')).toEqual(10);
|
||||
expect(result.get('sentPerType')).toEqual({
|
||||
'ios': 10 // 10 ios
|
||||
});
|
||||
expect(result.get('numFailed')).toEqual(5);
|
||||
expect(result.get('failedPerType')).toEqual({
|
||||
'android': 5 // android
|
||||
});
|
||||
return Parse.Object.saveAll(installations)
|
||||
})
|
||||
.then(() => {
|
||||
return pushController.sendPush(payload, {}, config, auth);
|
||||
}).then(() => {
|
||||
// it is enqueued so it can take time
|
||||
return new Promise((resolve) => {
|
||||
setTimeout(() => {
|
||||
resolve();
|
||||
}, 1000);
|
||||
});
|
||||
}).then(() => {
|
||||
const query = new Parse.Query('_PushStatus');
|
||||
return query.find({useMasterKey: true});
|
||||
}).then((results) => {
|
||||
expect(results.length).toBe(1);
|
||||
const result = results[0];
|
||||
expect(result.createdAt instanceof Date).toBe(true);
|
||||
expect(result.updatedAt instanceof Date).toBe(true);
|
||||
expect(result.id.length).toBe(10);
|
||||
expect(result.get('source')).toEqual('rest');
|
||||
expect(result.get('query')).toEqual(JSON.stringify({}));
|
||||
expect(typeof result.get('payload')).toEqual("string");
|
||||
expect(JSON.parse(result.get('payload'))).toEqual(payload.data);
|
||||
expect(result.get('status')).toEqual('succeeded');
|
||||
expect(result.get('numSent')).toEqual(10);
|
||||
expect(result.get('sentPerType')).toEqual({
|
||||
'ios': 10 // 10 ios
|
||||
});
|
||||
expect(result.get('numFailed')).toEqual(5);
|
||||
expect(result.get('failedPerType')).toEqual({
|
||||
'android': 5 // android
|
||||
});
|
||||
// Try to get it without masterKey
|
||||
let query = new Parse.Query('_PushStatus');
|
||||
return query.find();
|
||||
}).then((results) => {
|
||||
expect(results.length).toBe(0);
|
||||
done();
|
||||
});
|
||||
|
||||
const query = new Parse.Query('_PushStatus');
|
||||
return query.find();
|
||||
}).then((results) => {
|
||||
expect(results.length).toBe(0);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should properly report failures in _PushStatus', (done) => {
|
||||
@@ -393,7 +410,7 @@ describe('PushController', () => {
|
||||
return ["ios"];
|
||||
}
|
||||
}
|
||||
let where = { 'channels': {
|
||||
const where = { 'channels': {
|
||||
'$ins': ['Giants', 'Mets']
|
||||
}};
|
||||
var payload = {data: {
|
||||
@@ -404,19 +421,23 @@ describe('PushController', () => {
|
||||
var auth = {
|
||||
isMaster: true
|
||||
}
|
||||
var pushController = new PushController(pushAdapter, Parse.applicationId, defaultConfiguration.push);
|
||||
pushController.sendPush(payload, where, config, auth).then(() => {
|
||||
var pushController = new PushController();
|
||||
reconfigureServer({
|
||||
push: { adapter: pushAdapter }
|
||||
}).then(() => {
|
||||
return pushController.sendPush(payload, where, config, auth)
|
||||
}).then(() => {
|
||||
fail('should not succeed');
|
||||
done();
|
||||
}).catch(() => {
|
||||
let query = new Parse.Query('_PushStatus');
|
||||
const query = new Parse.Query('_PushStatus');
|
||||
query.find({useMasterKey: true}).then((results) => {
|
||||
expect(results.length).toBe(1);
|
||||
let pushStatus = results[0];
|
||||
const pushStatus = results[0];
|
||||
expect(pushStatus.get('status')).toBe('failed');
|
||||
done();
|
||||
});
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
it('should support full RESTQuery for increment', (done) => {
|
||||
@@ -433,13 +454,12 @@ describe('PushController', () => {
|
||||
return ["ios"];
|
||||
}
|
||||
}
|
||||
|
||||
var config = new Config(Parse.applicationId);
|
||||
var auth = {
|
||||
isMaster: true
|
||||
}
|
||||
|
||||
let where = {
|
||||
const where = {
|
||||
'deviceToken': {
|
||||
'$inQuery': {
|
||||
'where': {
|
||||
@@ -450,8 +470,12 @@ describe('PushController', () => {
|
||||
}
|
||||
}
|
||||
|
||||
var pushController = new PushController(pushAdapter, Parse.applicationId, defaultConfiguration.push);
|
||||
pushController.sendPush(payload, where, config, auth).then(() => {
|
||||
var pushController = new PushController();
|
||||
reconfigureServer({
|
||||
push: { adapter: pushAdapter }
|
||||
}).then(() => {
|
||||
return pushController.sendPush(payload, where, config, auth);
|
||||
}).then(() => {
|
||||
done();
|
||||
}).catch((err) => {
|
||||
jfail(err);
|
||||
@@ -480,7 +504,7 @@ describe('PushController', () => {
|
||||
isMaster: true
|
||||
}
|
||||
|
||||
let where = {
|
||||
const where = {
|
||||
'deviceToken': {
|
||||
'$inQuery': {
|
||||
'where': {
|
||||
@@ -491,8 +515,12 @@ describe('PushController', () => {
|
||||
}
|
||||
}
|
||||
|
||||
var pushController = new PushController(pushAdapter, Parse.applicationId, defaultConfiguration.push);
|
||||
pushController.sendPush(payload, where, config, auth).then(() => {
|
||||
var pushController = new PushController();
|
||||
reconfigureServer({
|
||||
push: { adapter: pushAdapter }
|
||||
}).then(() => {
|
||||
pushController.sendPush(payload, where, config, auth)
|
||||
}).then(() => {
|
||||
done();
|
||||
}).catch(() => {
|
||||
fail('should not fail');
|
||||
|
||||
@@ -70,7 +70,7 @@ describe('PushRouter', () => {
|
||||
|
||||
it('sends a push through REST', (done) => {
|
||||
request.post({
|
||||
url: Parse.serverURL+"/push",
|
||||
url: Parse.serverURL + "/push",
|
||||
json: true,
|
||||
body: {
|
||||
'channels': {
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
var PushWorker = require('../src').PushWorker;
|
||||
var Config = require('../src/Config');
|
||||
|
||||
describe('PushWorker', () => {
|
||||
it('should run with small batch', (done) => {
|
||||
const batchSize = 3;
|
||||
var sendCount = 0;
|
||||
reconfigureServer({
|
||||
push: {
|
||||
queueOptions: {
|
||||
disablePushWorker: true,
|
||||
batchSize
|
||||
}
|
||||
}
|
||||
}).then(() => {
|
||||
expect(new Config('test').pushWorker).toBeUndefined();
|
||||
new PushWorker({
|
||||
send: (body, installations) => {
|
||||
expect(installations.length <= batchSize).toBe(true);
|
||||
sendCount += installations.length;
|
||||
return Promise.resolve();
|
||||
},
|
||||
getValidPushTypes: function() {
|
||||
return ['ios', 'android']
|
||||
}
|
||||
});
|
||||
var installations = [];
|
||||
while(installations.length != 10) {
|
||||
var installation = new Parse.Object("_Installation");
|
||||
installation.set("installationId", "installation_" + installations.length);
|
||||
installation.set("deviceToken","device_token_" + installations.length)
|
||||
installation.set("badge", 1);
|
||||
installation.set("deviceType", "ios");
|
||||
installations.push(installation);
|
||||
}
|
||||
return Parse.Object.saveAll(installations);
|
||||
}).then(() => {
|
||||
return Parse.Push.send({
|
||||
where: {
|
||||
deviceType: 'ios'
|
||||
},
|
||||
data: {
|
||||
alert: 'Hello world!'
|
||||
}
|
||||
}, {useMasterKey: true})
|
||||
}).then(() => {
|
||||
return new Promise((resolve) => {
|
||||
setTimeout(resolve, 500);
|
||||
});
|
||||
}).then(() => {
|
||||
expect(sendCount).toBe(10);
|
||||
done();
|
||||
}).catch(err => {
|
||||
jfail(err);
|
||||
})
|
||||
});
|
||||
});
|
||||
@@ -412,4 +412,66 @@ describe('matchesQuery', function() {
|
||||
expect(matchesQuery(caltrainStation, q)).toBe(false);
|
||||
expect(matchesQuery(santaClara, q)).toBe(false);
|
||||
});
|
||||
|
||||
it('matches on subobjects with dot notation', function() {
|
||||
var message = {
|
||||
id: new Id('Message', 'O1'),
|
||||
text: "content",
|
||||
status: {x: "read", y: "delivered"}
|
||||
};
|
||||
|
||||
var q = new Parse.Query('Message');
|
||||
q.equalTo("status.x", "read");
|
||||
expect(matchesQuery(message, q)).toBe(true);
|
||||
|
||||
q = new Parse.Query('Message');
|
||||
q.equalTo("status.z", "read");
|
||||
expect(matchesQuery(message, q)).toBe(false);
|
||||
|
||||
q = new Parse.Query('Message');
|
||||
q.equalTo("status.x", "delivered");
|
||||
expect(matchesQuery(message, q)).toBe(false);
|
||||
|
||||
q = new Parse.Query('Message');
|
||||
q.notEqualTo("status.x", "read");
|
||||
expect(matchesQuery(message, q)).toBe(false);
|
||||
|
||||
q = new Parse.Query('Message');
|
||||
q.notEqualTo("status.z", "read");
|
||||
expect(matchesQuery(message, q)).toBe(true);
|
||||
|
||||
q = new Parse.Query('Message');
|
||||
q.notEqualTo("status.x", "delivered");
|
||||
expect(matchesQuery(message, q)).toBe(true);
|
||||
|
||||
q = new Parse.Query('Message');
|
||||
q.exists("status.x");
|
||||
expect(matchesQuery(message, q)).toBe(true);
|
||||
|
||||
q = new Parse.Query('Message');
|
||||
q.exists("status.z");
|
||||
expect(matchesQuery(message, q)).toBe(false);
|
||||
|
||||
q = new Parse.Query('Message');
|
||||
q.exists("nonexistent.x");
|
||||
expect(matchesQuery(message, q)).toBe(false);
|
||||
|
||||
q = new Parse.Query('Message');
|
||||
q.doesNotExist("status.x");
|
||||
expect(matchesQuery(message, q)).toBe(false);
|
||||
|
||||
q = new Parse.Query('Message');
|
||||
q.doesNotExist("status.z");
|
||||
expect(matchesQuery(message, q)).toBe(true);
|
||||
|
||||
q = new Parse.Query('Message');
|
||||
q.doesNotExist("nonexistent.z");
|
||||
expect(matchesQuery(message, q)).toBe(true);
|
||||
|
||||
q = new Parse.Query('Message');
|
||||
q.equalTo("status.x", "read");
|
||||
q.doesNotExist("status.y");
|
||||
expect(matchesQuery(message, q)).toBe(false);
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
+10
-10
@@ -172,8 +172,8 @@ describe('rest query', () => {
|
||||
'X-Parse-Application-Id': 'test',
|
||||
'X-Parse-REST-API-Key': 'rest'
|
||||
};
|
||||
|
||||
let p0 = rp.get({
|
||||
|
||||
const p0 = rp.get({
|
||||
headers: headers,
|
||||
url: 'http://localhost:8378/1/classes/TestParameterEncode?'
|
||||
+ querystring.stringify({
|
||||
@@ -181,19 +181,19 @@ describe('rest query', () => {
|
||||
limit: 1
|
||||
}).replace('=', '%3D'),
|
||||
}).then(fail, (response) => {
|
||||
let error = response.error;
|
||||
const error = response.error;
|
||||
var b = JSON.parse(error);
|
||||
expect(b.code).toEqual(Parse.Error.INVALID_QUERY);
|
||||
});
|
||||
|
||||
let p1 = rp.get({
|
||||
const p1 = rp.get({
|
||||
headers: headers,
|
||||
url: 'http://localhost:8378/1/classes/TestParameterEncode?'
|
||||
+ querystring.stringify({
|
||||
limit: 1
|
||||
}).replace('=', '%3D'),
|
||||
}).then(fail, (response) => {
|
||||
let error = response.error;
|
||||
const error = response.error;
|
||||
var b = JSON.parse(error);
|
||||
expect(b.code).toEqual(Parse.Error.INVALID_QUERY);
|
||||
});
|
||||
@@ -235,21 +235,21 @@ describe('rest query', () => {
|
||||
});
|
||||
|
||||
it('makes sure null pointers are handed correctly #2189', done => {
|
||||
let object = new Parse.Object('AnObject');
|
||||
let anotherObject = new Parse.Object('AnotherObject');
|
||||
const object = new Parse.Object('AnObject');
|
||||
const anotherObject = new Parse.Object('AnotherObject');
|
||||
anotherObject.save().then(() => {
|
||||
object.set('values', [null, null, anotherObject]);
|
||||
return object.save();
|
||||
}).then(() => {
|
||||
let query = new Parse.Query('AnObject');
|
||||
const query = new Parse.Query('AnObject');
|
||||
query.include('values');
|
||||
return query.first();
|
||||
}).then((result) => {
|
||||
let values = result.get('values');
|
||||
const values = result.get('values');
|
||||
expect(values.length).toBe(3);
|
||||
let anotherObjectFound = false;
|
||||
let nullCounts = 0;
|
||||
for(let value of values) {
|
||||
for(const value of values) {
|
||||
if (value === null) {
|
||||
nullCounts++;
|
||||
} else if (value instanceof Parse.Object) {
|
||||
|
||||
@@ -22,7 +22,7 @@ describe_only_db('mongo')('revocable sessions', () => {
|
||||
});
|
||||
|
||||
it('should upgrade legacy session token', done => {
|
||||
let user = Parse.Object.fromJSON({
|
||||
const user = Parse.Object.fromJSON({
|
||||
className: '_User',
|
||||
objectId: '1234567890',
|
||||
sessionToken: sessionToken
|
||||
@@ -49,7 +49,7 @@ describe_only_db('mongo')('revocable sessions', () => {
|
||||
});
|
||||
|
||||
it('should be able to become with revocable session token', done => {
|
||||
let user = Parse.Object.fromJSON({
|
||||
const user = Parse.Object.fromJSON({
|
||||
className: '_User',
|
||||
objectId: '1234567890',
|
||||
sessionToken: sessionToken
|
||||
@@ -71,7 +71,7 @@ describe_only_db('mongo')('revocable sessions', () => {
|
||||
|
||||
it('should not upgrade bad legacy session token', done => {
|
||||
rp.post({
|
||||
url: Parse.serverURL+'/upgradeToRevocableSession',
|
||||
url: Parse.serverURL + '/upgradeToRevocableSession',
|
||||
headers: {
|
||||
'X-Parse-Application-Id': Parse.applicationId,
|
||||
'X-Parse-Rest-API-Key': 'rest',
|
||||
@@ -92,7 +92,7 @@ describe_only_db('mongo')('revocable sessions', () => {
|
||||
|
||||
it('should not crash without session token #2720', done => {
|
||||
rp.post({
|
||||
url: Parse.serverURL+'/upgradeToRevocableSession',
|
||||
url: Parse.serverURL + '/upgradeToRevocableSession',
|
||||
headers: {
|
||||
'X-Parse-Application-Id': Parse.applicationId,
|
||||
'X-Parse-Rest-API-Key': 'rest'
|
||||
@@ -109,4 +109,4 @@ describe_only_db('mongo')('revocable sessions', () => {
|
||||
done();
|
||||
});
|
||||
});
|
||||
})
|
||||
})
|
||||
|
||||
+267
-8
@@ -708,7 +708,7 @@ describe('SchemaController', () => {
|
||||
}, () => {
|
||||
expect(exist).toEqual(false);
|
||||
});
|
||||
|
||||
|
||||
})
|
||||
.then(() => schema.deleteField('relationField', 'NewClass', config.database))
|
||||
.then(() => schema.reloadData())
|
||||
@@ -824,9 +824,9 @@ describe('SchemaController', () => {
|
||||
});
|
||||
|
||||
it('yields a proper schema mismatch error (#2661)', done => {
|
||||
let anObject = new Parse.Object('AnObject');
|
||||
let anotherObject = new Parse.Object('AnotherObject');
|
||||
let someObject = new Parse.Object('SomeObject');
|
||||
const anObject = new Parse.Object('AnObject');
|
||||
const anotherObject = new Parse.Object('AnotherObject');
|
||||
const someObject = new Parse.Object('SomeObject');
|
||||
Parse.Object.saveAll([anObject, anotherObject, someObject]).then(() => {
|
||||
anObject.set('pointer', anotherObject);
|
||||
return anObject.save();
|
||||
@@ -844,8 +844,8 @@ describe('SchemaController', () => {
|
||||
});
|
||||
|
||||
it('yields a proper schema mismatch error bis (#2661)', done => {
|
||||
let anObject = new Parse.Object('AnObject');
|
||||
let someObject = new Parse.Object('SomeObject');
|
||||
const anObject = new Parse.Object('AnObject');
|
||||
const someObject = new Parse.Object('SomeObject');
|
||||
Parse.Object.saveAll([anObject, someObject]).then(() => {
|
||||
anObject.set('number', 1);
|
||||
return anObject.save();
|
||||
@@ -863,8 +863,8 @@ describe('SchemaController', () => {
|
||||
});
|
||||
|
||||
it('yields a proper schema mismatch error ter (#2661)', done => {
|
||||
let anObject = new Parse.Object('AnObject');
|
||||
let someObject = new Parse.Object('SomeObject');
|
||||
const anObject = new Parse.Object('AnObject');
|
||||
const someObject = new Parse.Object('SomeObject');
|
||||
Parse.Object.saveAll([anObject, someObject]).then(() => {
|
||||
anObject.set('pointer', someObject);
|
||||
return anObject.save();
|
||||
@@ -880,4 +880,263 @@ describe('SchemaController', () => {
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('properly handles volatile _Schemas', done => {
|
||||
function validateSchemaStructure(schema) {
|
||||
expect(schema.hasOwnProperty('className')).toBe(true);
|
||||
expect(schema.hasOwnProperty('fields')).toBe(true);
|
||||
expect(schema.hasOwnProperty('classLevelPermissions')).toBe(true);
|
||||
}
|
||||
function validateSchemaDataStructure(schemaData) {
|
||||
Object.keys(schemaData).forEach(className => {
|
||||
const schema = schemaData[className];
|
||||
// Hooks has className...
|
||||
if (className != '_Hooks') {
|
||||
expect(schema.hasOwnProperty('className')).toBe(false);
|
||||
}
|
||||
expect(schema.hasOwnProperty('fields')).toBe(false);
|
||||
expect(schema.hasOwnProperty('classLevelPermissions')).toBe(false);
|
||||
});
|
||||
}
|
||||
let schema;
|
||||
config.database.loadSchema().then(s => {
|
||||
schema = s;
|
||||
return schema.getOneSchema('_User', false);
|
||||
}).then(userSchema => {
|
||||
validateSchemaStructure(userSchema);
|
||||
validateSchemaDataStructure(schema.data);
|
||||
return schema.getOneSchema('_PushStatus', true);
|
||||
}).then(pushStatusSchema => {
|
||||
validateSchemaStructure(pushStatusSchema);
|
||||
validateSchemaDataStructure(schema.data);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Class Level Permissions for requiredAuth', () => {
|
||||
|
||||
beforeEach(() => {
|
||||
config = new Config('test');
|
||||
});
|
||||
|
||||
function createUser() {
|
||||
const user = new Parse.User();
|
||||
user.set("username", "hello");
|
||||
user.set("password", "world");
|
||||
return user.signUp(null);
|
||||
}
|
||||
|
||||
it('required auth test find', (done) => {
|
||||
config.database.loadSchema().then((schema) => {
|
||||
// Just to create a valid class
|
||||
return schema.validateObject('Stuff', {foo: 'bar'});
|
||||
}).then((schema) => {
|
||||
return schema.setPermissions('Stuff', {
|
||||
'find': {
|
||||
'requiresAuthentication': true
|
||||
}
|
||||
});
|
||||
}).then(() => {
|
||||
var query = new Parse.Query('Stuff');
|
||||
return query.find();
|
||||
}).then(() => {
|
||||
fail('Class permissions should have rejected this query.');
|
||||
done();
|
||||
}, (e) => {
|
||||
expect(e.message).toEqual('Permission denied, user needs to be authenticated.');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('required auth test find authenticated', (done) => {
|
||||
config.database.loadSchema().then((schema) => {
|
||||
// Just to create a valid class
|
||||
return schema.validateObject('Stuff', {foo: 'bar'});
|
||||
}).then((schema) => {
|
||||
return schema.setPermissions('Stuff', {
|
||||
'find': {
|
||||
'requiresAuthentication': true
|
||||
}
|
||||
});
|
||||
}).then(() => {
|
||||
return createUser();
|
||||
}).then(() => {
|
||||
var query = new Parse.Query('Stuff');
|
||||
return query.find();
|
||||
}).then((results) => {
|
||||
expect(results.length).toEqual(0);
|
||||
done();
|
||||
}, (e) => {
|
||||
console.error(e);
|
||||
fail("Should not have failed");
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('required auth should allow create authenticated', (done) => {
|
||||
config.database.loadSchema().then((schema) => {
|
||||
// Just to create a valid class
|
||||
return schema.validateObject('Stuff', {foo: 'bar'});
|
||||
}).then((schema) => {
|
||||
return schema.setPermissions('Stuff', {
|
||||
'create': {
|
||||
'requiresAuthentication': true
|
||||
}
|
||||
});
|
||||
}).then(() => {
|
||||
return createUser();
|
||||
}).then(() => {
|
||||
const stuff = new Parse.Object('Stuff');
|
||||
stuff.set('foo', 'bar');
|
||||
return stuff.save();
|
||||
}).then(() => {
|
||||
done();
|
||||
}, (e) => {
|
||||
console.error(e);
|
||||
fail("Should not have failed");
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('required auth should reject create when not authenticated', (done) => {
|
||||
config.database.loadSchema().then((schema) => {
|
||||
// Just to create a valid class
|
||||
return schema.validateObject('Stuff', {foo: 'bar'});
|
||||
}).then((schema) => {
|
||||
return schema.setPermissions('Stuff', {
|
||||
'create': {
|
||||
'requiresAuthentication': true
|
||||
}
|
||||
});
|
||||
}).then(() => {
|
||||
const stuff = new Parse.Object('Stuff');
|
||||
stuff.set('foo', 'bar');
|
||||
return stuff.save();
|
||||
}).then(() => {
|
||||
fail('Class permissions should have rejected this query.');
|
||||
done();
|
||||
}, (e) => {
|
||||
expect(e.message).toEqual('Permission denied, user needs to be authenticated.');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('required auth test create/get/update/delete authenticated', (done) => {
|
||||
config.database.loadSchema().then((schema) => {
|
||||
// Just to create a valid class
|
||||
return schema.validateObject('Stuff', {foo: 'bar'});
|
||||
}).then((schema) => {
|
||||
return schema.setPermissions('Stuff', {
|
||||
'create': {
|
||||
'requiresAuthentication': true
|
||||
},
|
||||
'get': {
|
||||
'requiresAuthentication': true
|
||||
},
|
||||
'delete': {
|
||||
'requiresAuthentication': true
|
||||
},
|
||||
'update': {
|
||||
'requiresAuthentication': true
|
||||
}
|
||||
});
|
||||
}).then(() => {
|
||||
return createUser();
|
||||
}).then(() => {
|
||||
const stuff = new Parse.Object('Stuff');
|
||||
stuff.set('foo', 'bar');
|
||||
return stuff.save().then(() => {
|
||||
const query = new Parse.Query('Stuff');
|
||||
return query.get(stuff.id);
|
||||
});
|
||||
}).then((gotStuff) => {
|
||||
return gotStuff.save({'foo': 'baz'}).then(() => {
|
||||
return gotStuff.destroy();
|
||||
})
|
||||
}).then(() => {
|
||||
done();
|
||||
}, (e) => {
|
||||
console.error(e);
|
||||
fail("Should not have failed");
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('required auth test create/get/update/delete not authenitcated', (done) => {
|
||||
config.database.loadSchema().then((schema) => {
|
||||
// Just to create a valid class
|
||||
return schema.validateObject('Stuff', {foo: 'bar'});
|
||||
}).then((schema) => {
|
||||
return schema.setPermissions('Stuff', {
|
||||
'get': {
|
||||
'requiresAuthentication': true
|
||||
},
|
||||
'delete': {
|
||||
'requiresAuthentication': true
|
||||
},
|
||||
'update': {
|
||||
'requiresAuthentication': true
|
||||
},
|
||||
'create': {
|
||||
'*': true
|
||||
}
|
||||
});
|
||||
}).then(() => {
|
||||
const stuff = new Parse.Object('Stuff');
|
||||
stuff.set('foo', 'bar');
|
||||
return stuff.save().then(() => {
|
||||
const query = new Parse.Query('Stuff');
|
||||
return query.get(stuff.id);
|
||||
});
|
||||
}).then(() => {
|
||||
fail("Should not succeed!");
|
||||
done();
|
||||
}, (e) => {
|
||||
expect(e.message).toEqual('Permission denied, user needs to be authenticated.');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('required auth test create/get/update/delete not authenitcated', (done) => {
|
||||
config.database.loadSchema().then((schema) => {
|
||||
// Just to create a valid class
|
||||
return schema.validateObject('Stuff', {foo: 'bar'});
|
||||
}).then((schema) => {
|
||||
return schema.setPermissions('Stuff', {
|
||||
'find': {
|
||||
'requiresAuthentication': true
|
||||
},
|
||||
'delete': {
|
||||
'requiresAuthentication': true
|
||||
},
|
||||
'update': {
|
||||
'requiresAuthentication': true
|
||||
},
|
||||
'create': {
|
||||
'*': true
|
||||
},
|
||||
'get': {
|
||||
'*': true
|
||||
}
|
||||
});
|
||||
}).then(() => {
|
||||
const stuff = new Parse.Object('Stuff');
|
||||
stuff.set('foo', 'bar');
|
||||
return stuff.save().then(() => {
|
||||
const query = new Parse.Query('Stuff');
|
||||
return query.get(stuff.id);
|
||||
})
|
||||
}).then((result) => {
|
||||
expect(result.get('foo')).toEqual('bar');
|
||||
const query = new Parse.Query('Stuff');
|
||||
return query.find();
|
||||
}).then(() => {
|
||||
fail("Should not succeed!");
|
||||
done();
|
||||
}, (e) => {
|
||||
expect(e.message).toEqual('Permission denied, user needs to be authenticated.');
|
||||
done();
|
||||
});
|
||||
});
|
||||
})
|
||||
|
||||
@@ -4,13 +4,14 @@ describe('SessionTokenCache', function() {
|
||||
|
||||
beforeEach(function(done) {
|
||||
var Parse = require('parse/node');
|
||||
// Mock parse
|
||||
var mockUser = {
|
||||
become: jasmine.createSpy('become').and.returnValue(Parse.Promise.as({
|
||||
id: 'userId'
|
||||
}))
|
||||
}
|
||||
jasmine.mockLibrary('parse/node', 'User', mockUser);
|
||||
|
||||
spyOn(Parse, "Query").and.returnValue({
|
||||
first: jasmine.createSpy("first").and.returnValue(Parse.Promise.as(new Parse.Object("_Session", {
|
||||
user: new Parse.User({id:"userId"})
|
||||
}))),
|
||||
equalTo: function(){}
|
||||
})
|
||||
|
||||
done();
|
||||
});
|
||||
|
||||
@@ -46,7 +47,4 @@ describe('SessionTokenCache', function() {
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
jasmine.restoreLibrary('parse/node', 'User');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
let twitter = require('../src/authDataManager/twitter');
|
||||
const twitter = require('../src/Adapters/Auth/twitter');
|
||||
|
||||
describe('Twitter Auth', () => {
|
||||
it('should use the proper configuration', () => {
|
||||
@@ -10,9 +10,9 @@ describe('Twitter Auth', () => {
|
||||
}, {
|
||||
consumer_key: 'world'
|
||||
}]).consumer_key).toEqual('hello')
|
||||
|
||||
|
||||
// Multiple options, consumer_key not found
|
||||
expect(function(){
|
||||
expect(function(){
|
||||
twitter.handleMultipleConfigurations({
|
||||
consumer_key: 'some',
|
||||
}, [{
|
||||
@@ -23,7 +23,7 @@ describe('Twitter Auth', () => {
|
||||
}).toThrow();
|
||||
|
||||
// Multiple options, consumer_key not found
|
||||
expect(function(){
|
||||
expect(function(){
|
||||
twitter.handleMultipleConfigurations({
|
||||
auth_token: 'token',
|
||||
}, [{
|
||||
@@ -47,4 +47,4 @@ describe('Twitter Auth', () => {
|
||||
consumer_key: 'hello'
|
||||
}).consumer_key).toEqual('hello');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
+15
-15
@@ -1,19 +1,19 @@
|
||||
'use strict';
|
||||
|
||||
const Parse = require("parse/node");
|
||||
let Config = require('../src/Config');
|
||||
const Config = require('../src/Config');
|
||||
|
||||
describe('Uniqueness', function() {
|
||||
it('fail when create duplicate value in unique field', done => {
|
||||
let obj = new Parse.Object('UniqueField');
|
||||
const obj = new Parse.Object('UniqueField');
|
||||
obj.set('unique', 'value');
|
||||
obj.save().then(() => {
|
||||
expect(obj.id).not.toBeUndefined();
|
||||
let config = new Config('test');
|
||||
const config = new Config('test');
|
||||
return config.database.adapter.ensureUniqueness('UniqueField', { fields: { unique: { __type: 'String' } } }, ['unique'])
|
||||
})
|
||||
.then(() => {
|
||||
let obj = new Parse.Object('UniqueField');
|
||||
const obj = new Parse.Object('UniqueField');
|
||||
obj.set('unique', 'value');
|
||||
return obj.save()
|
||||
}).then(() => {
|
||||
@@ -26,18 +26,18 @@ describe('Uniqueness', function() {
|
||||
});
|
||||
|
||||
it('unique indexing works on pointer fields', done => {
|
||||
let obj = new Parse.Object('UniquePointer');
|
||||
const obj = new Parse.Object('UniquePointer');
|
||||
obj.save({ string: 'who cares' })
|
||||
.then(() => obj.save({ ptr: obj }))
|
||||
.then(() => {
|
||||
let config = new Config('test');
|
||||
const config = new Config('test');
|
||||
return config.database.adapter.ensureUniqueness('UniquePointer', { fields: {
|
||||
string: { __type: 'String' },
|
||||
ptr: { __type: 'Pointer', targetClass: 'UniquePointer' }
|
||||
} }, ['ptr']);
|
||||
})
|
||||
.then(() => {
|
||||
let newObj = new Parse.Object('UniquePointer')
|
||||
const newObj = new Parse.Object('UniquePointer')
|
||||
newObj.set('ptr', obj)
|
||||
return newObj.save()
|
||||
})
|
||||
@@ -52,13 +52,13 @@ describe('Uniqueness', function() {
|
||||
});
|
||||
|
||||
it('fails when attempting to ensure uniqueness of fields that are not currently unique', done => {
|
||||
let o1 = new Parse.Object('UniqueFail');
|
||||
const o1 = new Parse.Object('UniqueFail');
|
||||
o1.set('key', 'val');
|
||||
let o2 = new Parse.Object('UniqueFail');
|
||||
const o2 = new Parse.Object('UniqueFail');
|
||||
o2.set('key', 'val');
|
||||
Parse.Object.saveAll([o1, o2])
|
||||
.then(() => {
|
||||
let config = new Config('test');
|
||||
const config = new Config('test');
|
||||
return config.database.adapter.ensureUniqueness('UniqueFail', { fields: { key: { __type: 'String' } } }, ['key']);
|
||||
})
|
||||
.catch(error => {
|
||||
@@ -68,28 +68,28 @@ describe('Uniqueness', function() {
|
||||
});
|
||||
|
||||
it_exclude_dbs(['postgres'])('can do compound uniqueness', done => {
|
||||
let config = new Config('test');
|
||||
const config = new Config('test');
|
||||
config.database.adapter.ensureUniqueness('CompoundUnique', { fields: { k1: { __type: 'String' }, k2: { __type: 'String' } } }, ['k1', 'k2'])
|
||||
.then(() => {
|
||||
let o1 = new Parse.Object('CompoundUnique');
|
||||
const o1 = new Parse.Object('CompoundUnique');
|
||||
o1.set('k1', 'v1');
|
||||
o1.set('k2', 'v2');
|
||||
return o1.save();
|
||||
})
|
||||
.then(() => {
|
||||
let o2 = new Parse.Object('CompoundUnique');
|
||||
const o2 = new Parse.Object('CompoundUnique');
|
||||
o2.set('k1', 'v1');
|
||||
o2.set('k2', 'not a dupe');
|
||||
return o2.save();
|
||||
})
|
||||
.then(() => {
|
||||
let o3 = new Parse.Object('CompoundUnique');
|
||||
const o3 = new Parse.Object('CompoundUnique');
|
||||
o3.set('k1', 'not a dupe');
|
||||
o3.set('k2', 'v2');
|
||||
return o3.save();
|
||||
})
|
||||
.then(() => {
|
||||
let o4 = new Parse.Object('CompoundUnique');
|
||||
const o4 = new Parse.Object('CompoundUnique');
|
||||
o4.set('k1', 'v1');
|
||||
o4.set('k2', 'v2');
|
||||
return o4.save();
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
var UserController = require('../src/Controllers/UserController').UserController;
|
||||
var emailAdapter = require('./MockEmailAdapter')
|
||||
var AppCache = require('../src/cache').AppCache;
|
||||
|
||||
describe('UserController', () => {
|
||||
var user = {
|
||||
_email_verify_token: 'testToken',
|
||||
username: 'testUser',
|
||||
email: 'test@example.com'
|
||||
}
|
||||
|
||||
describe('sendVerificationEmail', () => {
|
||||
describe('parseFrameURL not provided', () => {
|
||||
it('uses publicServerURL', (done) => {
|
||||
|
||||
AppCache.put(defaultConfiguration.appId, Object.assign({}, defaultConfiguration, {
|
||||
publicServerURL: 'http://www.example.com',
|
||||
customPages: {
|
||||
parseFrameURL: undefined
|
||||
}
|
||||
}))
|
||||
|
||||
emailAdapter.sendVerificationEmail = (options) => {
|
||||
expect(options.link).toEqual('http://www.example.com/apps/test/verify_email?token=testToken&username=testUser')
|
||||
done()
|
||||
}
|
||||
|
||||
var userController = new UserController(emailAdapter, 'test', {
|
||||
verifyUserEmails: true
|
||||
})
|
||||
|
||||
userController.sendVerificationEmail(user)
|
||||
})
|
||||
})
|
||||
|
||||
describe('parseFrameURL provided', () => {
|
||||
it('uses parseFrameURL and includes the destination in the link parameter', (done) => {
|
||||
|
||||
AppCache.put(defaultConfiguration.appId, Object.assign({}, defaultConfiguration, {
|
||||
publicServerURL: 'http://www.example.com',
|
||||
customPages: {
|
||||
parseFrameURL: 'http://someother.example.com/handle-parse-iframe'
|
||||
}
|
||||
}))
|
||||
|
||||
emailAdapter.sendVerificationEmail = (options) => {
|
||||
expect(options.link).toEqual('http://someother.example.com/handle-parse-iframe?link=%2Fapps%2Ftest%2Fverify_email&token=testToken&username=testUser')
|
||||
done()
|
||||
}
|
||||
|
||||
var userController = new UserController(emailAdapter, 'test', {
|
||||
verifyUserEmails: true
|
||||
})
|
||||
|
||||
userController.sendVerificationEmail(user)
|
||||
})
|
||||
})
|
||||
})
|
||||
});
|
||||
@@ -0,0 +1,503 @@
|
||||
'use strict';
|
||||
|
||||
const Parse = require('parse/node');
|
||||
const request = require('request-promise');
|
||||
|
||||
// const Config = require('../src/Config');
|
||||
|
||||
const EMAIL = 'foo@bar.com';
|
||||
const ZIP = '10001';
|
||||
const SSN = '999-99-9999';
|
||||
|
||||
describe('Personally Identifiable Information', () => {
|
||||
let user;
|
||||
|
||||
beforeEach(done => {
|
||||
return Parse.User.signUp('tester', 'abc')
|
||||
.then(loggedInUser => user = loggedInUser)
|
||||
.then(() => Parse.User.logIn(user.get('username'), 'abc'))
|
||||
.then(() => user
|
||||
.set('email', EMAIL)
|
||||
.set('zip', ZIP)
|
||||
.set('ssn', SSN)
|
||||
.save())
|
||||
.then(() => done());
|
||||
});
|
||||
|
||||
it('should be able to get own PII via API with object', (done) => {
|
||||
const userObj = new (Parse.Object.extend(Parse.User));
|
||||
userObj.id = user.id;
|
||||
userObj.fetch().then(
|
||||
fetchedUser => {
|
||||
expect(fetchedUser.get('email')).toBe(EMAIL);
|
||||
}, e => console.error('error', e))
|
||||
.done(() => done());
|
||||
});
|
||||
|
||||
it('should not be able to get PII via API with object', (done) => {
|
||||
Parse.User.logOut()
|
||||
.then(() => {
|
||||
const userObj = new (Parse.Object.extend(Parse.User));
|
||||
userObj.id = user.id;
|
||||
userObj.fetch().then(
|
||||
fetchedUser => {
|
||||
expect(fetchedUser.get('email')).toBe(undefined);
|
||||
})
|
||||
.fail(e => {
|
||||
done.fail(JSON.stringify(e));
|
||||
})
|
||||
.done(() => done());
|
||||
});
|
||||
});
|
||||
|
||||
it('should be able to get PII via API with object using master key', (done) => {
|
||||
Parse.User.logOut()
|
||||
.then(() => {
|
||||
const userObj = new (Parse.Object.extend(Parse.User));
|
||||
userObj.id = user.id;
|
||||
userObj.fetch({ useMasterKey: true }).then(
|
||||
fetchedUser => {
|
||||
expect(fetchedUser.get('email')).toBe(EMAIL);
|
||||
}, e => console.error('error', e))
|
||||
.done(() => done());
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
it('should be able to get own PII via API with Find', (done) => {
|
||||
new Parse.Query(Parse.User)
|
||||
.first()
|
||||
.then(fetchedUser => {
|
||||
expect(fetchedUser.get('email')).toBe(EMAIL);
|
||||
expect(fetchedUser.get('zip')).toBe(ZIP);
|
||||
expect(fetchedUser.get('ssn')).toBe(SSN);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should not get PII via API with Find', (done) => {
|
||||
Parse.User.logOut()
|
||||
.then(() => new Parse.Query(Parse.User)
|
||||
.first()
|
||||
.then(fetchedUser => {
|
||||
expect(fetchedUser.get('email')).toBe(undefined);
|
||||
expect(fetchedUser.get('zip')).toBe(ZIP);
|
||||
expect(fetchedUser.get('ssn')).toBe(SSN);
|
||||
done();
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
it('should get PII via API with Find using master key', (done) => {
|
||||
Parse.User.logOut()
|
||||
.then(() => new Parse.Query(Parse.User)
|
||||
.first({ useMasterKey: true })
|
||||
.then(fetchedUser => {
|
||||
expect(fetchedUser.get('email')).toBe(EMAIL);
|
||||
expect(fetchedUser.get('zip')).toBe(ZIP);
|
||||
expect(fetchedUser.get('ssn')).toBe(SSN);
|
||||
done();
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
it('should be able to get own PII via API with Get', (done) => {
|
||||
new Parse.Query(Parse.User)
|
||||
.get(user.id)
|
||||
.then(fetchedUser => {
|
||||
expect(fetchedUser.get('email')).toBe(EMAIL);
|
||||
expect(fetchedUser.get('zip')).toBe(ZIP);
|
||||
expect(fetchedUser.get('ssn')).toBe(SSN);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should not get PII via API with Get', (done) => {
|
||||
Parse.User.logOut()
|
||||
.then(() => new Parse.Query(Parse.User)
|
||||
.get(user.id)
|
||||
.then(fetchedUser => {
|
||||
expect(fetchedUser.get('email')).toBe(undefined);
|
||||
expect(fetchedUser.get('zip')).toBe(ZIP);
|
||||
expect(fetchedUser.get('ssn')).toBe(SSN);
|
||||
done();
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
it('should get PII via API with Get using master key', (done) => {
|
||||
Parse.User.logOut()
|
||||
.then(() => new Parse.Query(Parse.User)
|
||||
.get(user.id, { useMasterKey: true })
|
||||
.then(fetchedUser => {
|
||||
expect(fetchedUser.get('email')).toBe(EMAIL);
|
||||
expect(fetchedUser.get('zip')).toBe(ZIP);
|
||||
expect(fetchedUser.get('ssn')).toBe(SSN);
|
||||
done();
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
it('should not get PII via REST', (done) => {
|
||||
request.get({
|
||||
url: 'http://localhost:8378/1/classes/_User',
|
||||
json: true,
|
||||
headers: {
|
||||
'X-Parse-Application-Id': 'test',
|
||||
'X-Parse-Javascript-Key': 'test'
|
||||
}
|
||||
})
|
||||
.then(
|
||||
result => {
|
||||
const fetchedUser = result.results[0];
|
||||
expect(fetchedUser.zip).toBe(ZIP);
|
||||
expect(fetchedUser.email).toBe(undefined);
|
||||
},
|
||||
e => console.error('error', e.message)
|
||||
).done(() => done());
|
||||
});
|
||||
|
||||
it('should get PII via REST with self credentials', (done) => {
|
||||
request.get({
|
||||
url: 'http://localhost:8378/1/classes/_User',
|
||||
json: true,
|
||||
headers: {
|
||||
'X-Parse-Application-Id': 'test',
|
||||
'X-Parse-Javascript-Key': 'test',
|
||||
'X-Parse-Session-Token': user.getSessionToken()
|
||||
}
|
||||
})
|
||||
.then(
|
||||
result => {
|
||||
const fetchedUser = result.results[0];
|
||||
expect(fetchedUser.zip).toBe(ZIP);
|
||||
expect(fetchedUser.email).toBe(EMAIL);
|
||||
},
|
||||
e => console.error('error', e.message)
|
||||
).done(() => done());
|
||||
});
|
||||
|
||||
it('should get PII via REST using master key', (done) => {
|
||||
request.get({
|
||||
url: 'http://localhost:8378/1/classes/_User',
|
||||
json: true,
|
||||
headers: {
|
||||
'X-Parse-Application-Id': 'test',
|
||||
'X-Parse-Master-Key': 'test'
|
||||
}
|
||||
})
|
||||
.then(
|
||||
result => {
|
||||
const fetchedUser = result.results[0];
|
||||
expect(fetchedUser.zip).toBe(ZIP);
|
||||
expect(fetchedUser.email).toBe(EMAIL);
|
||||
},
|
||||
e => console.error('error', e.message)
|
||||
).done(() => done());
|
||||
});
|
||||
|
||||
it('should not get PII via REST by ID', (done) => {
|
||||
request.get({
|
||||
url: `http://localhost:8378/1/classes/_User/${user.id}`,
|
||||
json: true,
|
||||
headers: {
|
||||
'X-Parse-Application-Id': 'test',
|
||||
'X-Parse-Javascript-Key': 'test'
|
||||
}
|
||||
})
|
||||
.then(
|
||||
result => {
|
||||
const fetchedUser = result;
|
||||
expect(fetchedUser.zip).toBe(ZIP);
|
||||
expect(fetchedUser.email).toBe(undefined);
|
||||
},
|
||||
e => console.error('error', e.message)
|
||||
).done(() => done());
|
||||
});
|
||||
|
||||
it('should get PII via REST by ID with self credentials', (done) => {
|
||||
request.get({
|
||||
url: `http://localhost:8378/1/classes/_User/${user.id}`,
|
||||
json: true,
|
||||
headers: {
|
||||
'X-Parse-Application-Id': 'test',
|
||||
'X-Parse-Javascript-Key': 'test',
|
||||
'X-Parse-Session-Token': user.getSessionToken()
|
||||
}
|
||||
})
|
||||
.then(
|
||||
result => {
|
||||
const fetchedUser = result;
|
||||
expect(fetchedUser.zip).toBe(ZIP);
|
||||
expect(fetchedUser.email).toBe(EMAIL);
|
||||
},
|
||||
e => console.error('error', e.message)
|
||||
).done(() => done());
|
||||
});
|
||||
|
||||
it('should get PII via REST by ID with master key', (done) => {
|
||||
request.get({
|
||||
url: `http://localhost:8378/1/classes/_User/${user.id}`,
|
||||
json: true,
|
||||
headers: {
|
||||
'X-Parse-Application-Id': 'test',
|
||||
'X-Parse-Javascript-Key': 'test',
|
||||
'X-Parse-Master-Key': 'test',
|
||||
}
|
||||
})
|
||||
.then(
|
||||
result => {
|
||||
const fetchedUser = result;
|
||||
expect(fetchedUser.zip).toBe(ZIP);
|
||||
expect(fetchedUser.email).toBe(EMAIL);
|
||||
},
|
||||
e => console.error('error', e.message)
|
||||
).done(() => done());
|
||||
});
|
||||
|
||||
describe('with configured sensitive fields', () => {
|
||||
beforeEach((done) => {
|
||||
reconfigureServer({ userSensitiveFields: ['ssn', 'zip'] })
|
||||
.then(() => done());
|
||||
});
|
||||
|
||||
it('should be able to get own PII via API with object', (done) => {
|
||||
const userObj = new (Parse.Object.extend(Parse.User));
|
||||
userObj.id = user.id;
|
||||
userObj.fetch().then(
|
||||
fetchedUser => {
|
||||
expect(fetchedUser.get('email')).toBe(EMAIL);
|
||||
expect(fetchedUser.get('zip')).toBe(ZIP);
|
||||
expect(fetchedUser.get('ssn')).toBe(SSN);
|
||||
done();
|
||||
}, e => done.fail(e));
|
||||
});
|
||||
|
||||
it('should not be able to get PII via API with object', (done) => {
|
||||
Parse.User.logOut()
|
||||
.then(() => {
|
||||
const userObj = new (Parse.Object.extend(Parse.User));
|
||||
userObj.id = user.id;
|
||||
userObj.fetch().then(
|
||||
fetchedUser => {
|
||||
expect(fetchedUser.get('email')).toBe(undefined);
|
||||
expect(fetchedUser.get('zip')).toBe(undefined);
|
||||
expect(fetchedUser.get('ssn')).toBe(undefined);
|
||||
}, e => console.error('error', e))
|
||||
.done(() => done());
|
||||
});
|
||||
});
|
||||
|
||||
it('should be able to get PII via API with object using master key', (done) => {
|
||||
Parse.User.logOut()
|
||||
.then(() => {
|
||||
const userObj = new (Parse.Object.extend(Parse.User));
|
||||
userObj.id = user.id;
|
||||
userObj.fetch({ useMasterKey: true }).then(
|
||||
fetchedUser => {
|
||||
expect(fetchedUser.get('email')).toBe(EMAIL);
|
||||
expect(fetchedUser.get('zip')).toBe(ZIP);
|
||||
expect(fetchedUser.get('ssn')).toBe(SSN);
|
||||
}, e => console.error('error', e))
|
||||
.done(() => done());
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
it('should be able to get own PII via API with Find', (done) => {
|
||||
new Parse.Query(Parse.User)
|
||||
.first()
|
||||
.then(fetchedUser => {
|
||||
expect(fetchedUser.get('email')).toBe(EMAIL);
|
||||
expect(fetchedUser.get('zip')).toBe(ZIP);
|
||||
expect(fetchedUser.get('ssn')).toBe(SSN);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should not get PII via API with Find', (done) => {
|
||||
Parse.User.logOut()
|
||||
.then(() => new Parse.Query(Parse.User)
|
||||
.first()
|
||||
.then(fetchedUser => {
|
||||
expect(fetchedUser.get('email')).toBe(undefined);
|
||||
expect(fetchedUser.get('zip')).toBe(undefined);
|
||||
expect(fetchedUser.get('ssn')).toBe(undefined);
|
||||
done();
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
it('should get PII via API with Find using master key', (done) => {
|
||||
Parse.User.logOut()
|
||||
.then(() => new Parse.Query(Parse.User)
|
||||
.first({ useMasterKey: true })
|
||||
.then(fetchedUser => {
|
||||
expect(fetchedUser.get('email')).toBe(EMAIL);
|
||||
expect(fetchedUser.get('zip')).toBe(ZIP);
|
||||
expect(fetchedUser.get('ssn')).toBe(SSN);
|
||||
done();
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
it('should be able to get own PII via API with Get', (done) => {
|
||||
new Parse.Query(Parse.User)
|
||||
.get(user.id)
|
||||
.then(fetchedUser => {
|
||||
expect(fetchedUser.get('email')).toBe(EMAIL);
|
||||
expect(fetchedUser.get('zip')).toBe(ZIP);
|
||||
expect(fetchedUser.get('ssn')).toBe(SSN);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should not get PII via API with Get', (done) => {
|
||||
Parse.User.logOut()
|
||||
.then(() => new Parse.Query(Parse.User)
|
||||
.get(user.id)
|
||||
.then(fetchedUser => {
|
||||
expect(fetchedUser.get('email')).toBe(undefined);
|
||||
expect(fetchedUser.get('zip')).toBe(undefined);
|
||||
expect(fetchedUser.get('ssn')).toBe(undefined);
|
||||
done();
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
it('should get PII via API with Get using master key', (done) => {
|
||||
Parse.User.logOut()
|
||||
.then(() => new Parse.Query(Parse.User)
|
||||
.get(user.id, { useMasterKey: true })
|
||||
.then(fetchedUser => {
|
||||
expect(fetchedUser.get('email')).toBe(EMAIL);
|
||||
expect(fetchedUser.get('zip')).toBe(ZIP);
|
||||
expect(fetchedUser.get('ssn')).toBe(SSN);
|
||||
done();
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
it('should not get PII via REST', (done) => {
|
||||
request.get({
|
||||
url: 'http://localhost:8378/1/classes/_User',
|
||||
json: true,
|
||||
headers: {
|
||||
'X-Parse-Application-Id': 'test',
|
||||
'X-Parse-Javascript-Key': 'test'
|
||||
}
|
||||
})
|
||||
.then(
|
||||
result => {
|
||||
const fetchedUser = result.results[0];
|
||||
expect(fetchedUser.zip).toBe(undefined);
|
||||
expect(fetchedUser.ssn).toBe(undefined);
|
||||
expect(fetchedUser.email).toBe(undefined);
|
||||
},
|
||||
e => console.error('error', e.message)
|
||||
).done(() => done());
|
||||
});
|
||||
|
||||
it('should get PII via REST with self credentials', (done) => {
|
||||
request.get({
|
||||
url: 'http://localhost:8378/1/classes/_User',
|
||||
json: true,
|
||||
headers: {
|
||||
'X-Parse-Application-Id': 'test',
|
||||
'X-Parse-Javascript-Key': 'test',
|
||||
'X-Parse-Session-Token': user.getSessionToken()
|
||||
}
|
||||
})
|
||||
.then(
|
||||
result => {
|
||||
const fetchedUser = result.results[0];
|
||||
expect(fetchedUser.zip).toBe(ZIP);
|
||||
expect(fetchedUser.email).toBe(EMAIL);
|
||||
expect(fetchedUser.ssn).toBe(SSN);
|
||||
},
|
||||
e => console.error('error', e.message)
|
||||
).done(() => done());
|
||||
});
|
||||
|
||||
it('should get PII via REST using master key', (done) => {
|
||||
request.get({
|
||||
url: 'http://localhost:8378/1/classes/_User',
|
||||
json: true,
|
||||
headers: {
|
||||
'X-Parse-Application-Id': 'test',
|
||||
'X-Parse-Master-Key': 'test'
|
||||
}
|
||||
})
|
||||
.then(
|
||||
result => {
|
||||
const fetchedUser = result.results[0];
|
||||
expect(fetchedUser.zip).toBe(ZIP);
|
||||
expect(fetchedUser.email).toBe(EMAIL);
|
||||
expect(fetchedUser.ssn).toBe(SSN);
|
||||
},
|
||||
e => console.error('error', e.message)
|
||||
).done(() => done());
|
||||
});
|
||||
|
||||
it('should not get PII via REST by ID', (done) => {
|
||||
request.get({
|
||||
url: `http://localhost:8378/1/classes/_User/${user.id}`,
|
||||
json: true,
|
||||
headers: {
|
||||
'X-Parse-Application-Id': 'test',
|
||||
'X-Parse-Javascript-Key': 'test'
|
||||
}
|
||||
})
|
||||
.then(
|
||||
result => {
|
||||
const fetchedUser = result;
|
||||
expect(fetchedUser.zip).toBe(undefined);
|
||||
expect(fetchedUser.email).toBe(undefined);
|
||||
},
|
||||
e => console.error('error', e.message)
|
||||
).done(() => done());
|
||||
});
|
||||
|
||||
it('should get PII via REST by ID with self credentials', (done) => {
|
||||
request.get({
|
||||
url: `http://localhost:8378/1/classes/_User/${user.id}`,
|
||||
json: true,
|
||||
headers: {
|
||||
'X-Parse-Application-Id': 'test',
|
||||
'X-Parse-Javascript-Key': 'test',
|
||||
'X-Parse-Session-Token': user.getSessionToken()
|
||||
}
|
||||
})
|
||||
.then(
|
||||
result => {
|
||||
const fetchedUser = result;
|
||||
expect(fetchedUser.zip).toBe(ZIP);
|
||||
expect(fetchedUser.email).toBe(EMAIL);
|
||||
},
|
||||
e => console.error('error', e.message)
|
||||
).done(() => done());
|
||||
});
|
||||
|
||||
it('should get PII via REST by ID with master key', (done) => {
|
||||
request.get({
|
||||
url: `http://localhost:8378/1/classes/_User/${user.id}`,
|
||||
json: true,
|
||||
headers: {
|
||||
'X-Parse-Application-Id': 'test',
|
||||
'X-Parse-Javascript-Key': 'test',
|
||||
'X-Parse-Master-Key': 'test',
|
||||
}
|
||||
})
|
||||
.then(
|
||||
result => {
|
||||
const fetchedUser = result;
|
||||
expect(fetchedUser.zip).toBe(ZIP);
|
||||
expect(fetchedUser.email).toBe(EMAIL);
|
||||
},
|
||||
e => console.error('error', e.message)
|
||||
).done(() => done());
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,8 +1,8 @@
|
||||
"use strict";
|
||||
|
||||
let MockEmailAdapterWithOptions = require('./MockEmailAdapterWithOptions');
|
||||
let request = require('request');
|
||||
let Config = require("../src/Config");
|
||||
const MockEmailAdapterWithOptions = require('./MockEmailAdapterWithOptions');
|
||||
const request = require('request');
|
||||
const Config = require("../src/Config");
|
||||
|
||||
describe("Custom Pages, Email Verification, Password Reset", () => {
|
||||
it("should set the custom pages", (done) => {
|
||||
@@ -12,7 +12,8 @@ describe("Custom Pages, Email Verification, Password Reset", () => {
|
||||
invalidLink: "myInvalidLink",
|
||||
verifyEmailSuccess: "myVerifyEmailSuccess",
|
||||
choosePassword: "myChoosePassword",
|
||||
passwordResetSuccess: "myPasswordResetSuccess"
|
||||
passwordResetSuccess: "myPasswordResetSuccess",
|
||||
parseFrameURL: "http://example.com/handle-parse-iframe"
|
||||
},
|
||||
publicServerURL: "https://my.public.server.com/1"
|
||||
})
|
||||
@@ -22,6 +23,7 @@ describe("Custom Pages, Email Verification, Password Reset", () => {
|
||||
expect(config.verifyEmailSuccessURL).toEqual("myVerifyEmailSuccess");
|
||||
expect(config.choosePasswordURL).toEqual("myChoosePassword");
|
||||
expect(config.passwordResetSuccessURL).toEqual("myPasswordResetSuccess");
|
||||
expect(config.parseFrameURL).toEqual("http://example.com/handle-parse-iframe");
|
||||
expect(config.verifyEmailURL).toEqual("https://my.public.server.com/1/apps/test/verify_email");
|
||||
expect(config.requestResetPasswordURL).toEqual("https://my.public.server.com/1/apps/test/request_password_reset");
|
||||
done();
|
||||
@@ -251,7 +253,7 @@ describe("Custom Pages, Email Verification, Password Reset", () => {
|
||||
}),
|
||||
})
|
||||
.then(() => {
|
||||
let user = new Parse.User();
|
||||
const user = new Parse.User();
|
||||
user.setPassword("asdf");
|
||||
user.setUsername("zxcv");
|
||||
user.set("email", "testInvalidConfig@parse.com");
|
||||
@@ -338,7 +340,7 @@ describe("Custom Pages, Email Verification, Password Reset", () => {
|
||||
}),
|
||||
})
|
||||
.then(() => {
|
||||
let user = new Parse.User();
|
||||
const user = new Parse.User();
|
||||
user.setPassword("asdf");
|
||||
user.setUsername("zxcv");
|
||||
user.set("email", "testInvalidConfig@parse.com");
|
||||
@@ -370,7 +372,7 @@ describe("Custom Pages, Email Verification, Password Reset", () => {
|
||||
}),
|
||||
})
|
||||
.then(() => {
|
||||
let user = new Parse.User();
|
||||
const user = new Parse.User();
|
||||
user.setPassword("asdf");
|
||||
user.setUsername("zxcv");
|
||||
user.set("email", "testInvalidConfig@parse.com");
|
||||
@@ -401,7 +403,7 @@ describe("Custom Pages, Email Verification, Password Reset", () => {
|
||||
}),
|
||||
})
|
||||
.then(() => {
|
||||
let user = new Parse.User();
|
||||
const user = new Parse.User();
|
||||
user.setPassword("asdf");
|
||||
user.setUsername("zxcv");
|
||||
user.set("email", "testInvalidConfig@parse.com");
|
||||
@@ -429,7 +431,7 @@ describe("Custom Pages, Email Verification, Password Reset", () => {
|
||||
emailAdapter: undefined,
|
||||
})
|
||||
.then(() => {
|
||||
let user = new Parse.User();
|
||||
const user = new Parse.User();
|
||||
user.setPassword("asdf");
|
||||
user.setUsername("zxcv");
|
||||
user.set("email", "testInvalidConfig@parse.com");
|
||||
@@ -461,7 +463,7 @@ describe("Custom Pages, Email Verification, Password Reset", () => {
|
||||
}),
|
||||
})
|
||||
.then(() => {
|
||||
let user = new Parse.User();
|
||||
const user = new Parse.User();
|
||||
user.setPassword("asdf");
|
||||
user.setUsername("zxcv");
|
||||
user.set("email", "testInvalidConfig@parse.com");
|
||||
@@ -480,7 +482,7 @@ describe("Custom Pages, Email Verification, Password Reset", () => {
|
||||
});
|
||||
|
||||
it('succeeds sending a password reset username if appName, publicServerURL, and email adapter are prodvided', done => {
|
||||
let adapter = MockEmailAdapterWithOptions({
|
||||
const adapter = MockEmailAdapterWithOptions({
|
||||
fromAddress: 'parse@example.com',
|
||||
apiKey: 'k',
|
||||
domain: 'd',
|
||||
@@ -500,7 +502,7 @@ describe("Custom Pages, Email Verification, Password Reset", () => {
|
||||
emailAdapter: adapter
|
||||
})
|
||||
.then(() => {
|
||||
let user = new Parse.User();
|
||||
const user = new Parse.User();
|
||||
user.setPassword("asdf");
|
||||
user.setUsername("testValidConfig@parse.com");
|
||||
user.signUp(null)
|
||||
@@ -819,7 +821,7 @@ describe("Custom Pages, Email Verification, Password Reset", () => {
|
||||
expect(response.body).toEqual('Found. Redirecting to http://localhost:8378/1/apps/password_reset_success.html?username=zxcv');
|
||||
|
||||
Parse.User.logIn("zxcv", "hello").then(function(){
|
||||
let config = new Config('test');
|
||||
const config = new Config('test');
|
||||
config.database.adapter.find('_User', { fields: {} }, { 'username': 'zxcv' }, { limit: 1 })
|
||||
.then(results => {
|
||||
// _perishable_token should be unset after reset password
|
||||
|
||||
@@ -60,14 +60,14 @@ describe('verbose logs', () => {
|
||||
reconfigureServer({ verbose: true })
|
||||
.then(() => createTestUser())
|
||||
.then(() => {
|
||||
let winstonLoggerAdapter = new WinstonLoggerAdapter();
|
||||
const winstonLoggerAdapter = new WinstonLoggerAdapter();
|
||||
return winstonLoggerAdapter.query({
|
||||
from: new Date(Date.now() - 500),
|
||||
size: 100,
|
||||
level: 'verbose'
|
||||
});
|
||||
}).then((results) => {
|
||||
let logString = JSON.stringify(results);
|
||||
const logString = JSON.stringify(results);
|
||||
expect(logString.match(/\*\*\*\*\*\*\*\*/g).length).not.toBe(0);
|
||||
expect(logString.match(/moon-y/g)).toBe(null);
|
||||
|
||||
@@ -79,13 +79,13 @@ describe('verbose logs', () => {
|
||||
headers: headers,
|
||||
url: 'http://localhost:8378/1/login?username=test&password=moon-y'
|
||||
}, () => {
|
||||
let winstonLoggerAdapter = new WinstonLoggerAdapter();
|
||||
const winstonLoggerAdapter = new WinstonLoggerAdapter();
|
||||
return winstonLoggerAdapter.query({
|
||||
from: new Date(Date.now() - 500),
|
||||
size: 100,
|
||||
level: 'verbose'
|
||||
}).then((results) => {
|
||||
let logString = JSON.stringify(results);
|
||||
const logString = JSON.stringify(results);
|
||||
expect(logString.match(/\*\*\*\*\*\*\*\*/g).length).not.toBe(0);
|
||||
expect(logString.match(/moon-y/g)).toBe(null);
|
||||
done();
|
||||
|
||||
+9
-9
@@ -9,35 +9,35 @@ const publicServerURLNaked = 'http://domain.com/';
|
||||
|
||||
describe('batch', () => {
|
||||
it('should return the proper url', () => {
|
||||
let internalURL = batch.makeBatchRoutingPathFunction(originalURL)('/parse/classes/Object');
|
||||
const internalURL = batch.makeBatchRoutingPathFunction(originalURL)('/parse/classes/Object');
|
||||
|
||||
expect(internalURL).toEqual('/classes/Object');
|
||||
});
|
||||
|
||||
it('should return the proper url same public/local endpoint', () => {
|
||||
let originalURL = '/parse/batch';
|
||||
let internalURL = batch.makeBatchRoutingPathFunction(originalURL, serverURL, publicServerURL)('/parse/classes/Object');
|
||||
const originalURL = '/parse/batch';
|
||||
const internalURL = batch.makeBatchRoutingPathFunction(originalURL, serverURL, publicServerURL)('/parse/classes/Object');
|
||||
|
||||
expect(internalURL).toEqual('/classes/Object');
|
||||
});
|
||||
|
||||
it('should return the proper url with different public/local mount', () => {
|
||||
let originalURL = '/parse/batch';
|
||||
let internalURL = batch.makeBatchRoutingPathFunction(originalURL, serverURL1, publicServerURL)('/parse/classes/Object');
|
||||
const originalURL = '/parse/batch';
|
||||
const internalURL = batch.makeBatchRoutingPathFunction(originalURL, serverURL1, publicServerURL)('/parse/classes/Object');
|
||||
|
||||
expect(internalURL).toEqual('/classes/Object');
|
||||
});
|
||||
|
||||
it('should return the proper url with naked public', () => {
|
||||
let originalURL = '/batch';
|
||||
let internalURL = batch.makeBatchRoutingPathFunction(originalURL, serverURL, publicServerURLNaked)('/classes/Object');
|
||||
const originalURL = '/batch';
|
||||
const internalURL = batch.makeBatchRoutingPathFunction(originalURL, serverURL, publicServerURLNaked)('/classes/Object');
|
||||
|
||||
expect(internalURL).toEqual('/classes/Object');
|
||||
});
|
||||
|
||||
it('should return the proper url with naked local', () => {
|
||||
let originalURL = '/parse/batch';
|
||||
let internalURL = batch.makeBatchRoutingPathFunction(originalURL, serverURLNaked, publicServerURL)('/parse/classes/Object');
|
||||
const originalURL = '/parse/batch';
|
||||
const internalURL = batch.makeBatchRoutingPathFunction(originalURL, serverURLNaked, publicServerURL)('/parse/classes/Object');
|
||||
|
||||
expect(internalURL).toEqual('/classes/Object');
|
||||
});
|
||||
|
||||
+9
-10
@@ -1,11 +1,11 @@
|
||||
"use strict"
|
||||
// Sets up a Parse API server for testing.
|
||||
const SpecReporter = require('jasmine-spec-reporter');
|
||||
const SpecReporter = require('jasmine-spec-reporter').SpecReporter;
|
||||
|
||||
jasmine.DEFAULT_TIMEOUT_INTERVAL = process.env.PARSE_SERVER_TEST_TIMEOUT || 5000;
|
||||
|
||||
jasmine.getEnv().clearReporters();
|
||||
jasmine.getEnv().addReporter(new SpecReporter());
|
||||
jasmine.getEnv().addReporter(new SpecReporter());
|
||||
|
||||
global.on_db = (db, callback, elseCallback) => {
|
||||
if (process.env.PARSE_SERVER_TEST_DB == db) {
|
||||
@@ -102,7 +102,7 @@ var defaultConfiguration = {
|
||||
bundleId: 'bundleId',
|
||||
}
|
||||
},
|
||||
oauth: { // Override the facebook provider
|
||||
auth: { // Override the facebook provider
|
||||
facebook: mockFacebook(),
|
||||
myoauth: {
|
||||
module: path.resolve(__dirname, "myoauth") // relative path as it's run from src
|
||||
@@ -114,7 +114,7 @@ if (process.env.PARSE_SERVER_TEST_CACHE === 'redis') {
|
||||
defaultConfiguration.cacheAdapter = new RedisCacheAdapter();
|
||||
}
|
||||
|
||||
let openConnections = {};
|
||||
const openConnections = {};
|
||||
|
||||
// Set up a default API server for testing with default configuration.
|
||||
var app = express();
|
||||
@@ -125,7 +125,7 @@ app.use('/1', () => {
|
||||
});
|
||||
var server = app.listen(port);
|
||||
server.on('connection', connection => {
|
||||
let key = `${connection.remoteAddress}:${connection.remotePort}`;
|
||||
const key = `${connection.remoteAddress}:${connection.remotePort}`;
|
||||
openConnections[key] = connection;
|
||||
connection.on('close', () => { delete openConnections[key] });
|
||||
});
|
||||
@@ -134,7 +134,7 @@ const reconfigureServer = changedConfiguration => {
|
||||
return new Promise((resolve, reject) => {
|
||||
server.close(() => {
|
||||
try {
|
||||
let newConfiguration = Object.assign({}, defaultConfiguration, changedConfiguration, {
|
||||
const newConfiguration = Object.assign({}, defaultConfiguration, changedConfiguration, {
|
||||
__indexBuildCompletionCallbackForTests: indexBuildPromise => indexBuildPromise.then(resolve, reject)
|
||||
});
|
||||
cache.clear();
|
||||
@@ -147,7 +147,7 @@ const reconfigureServer = changedConfiguration => {
|
||||
});
|
||||
server = app.listen(port);
|
||||
server.on('connection', connection => {
|
||||
let key = `${connection.remoteAddress}:${connection.remotePort}`;
|
||||
const key = `${connection.remoteAddress}:${connection.remotePort}`;
|
||||
openConnections[key] = connection;
|
||||
connection.on('close', () => { delete openConnections[key] });
|
||||
});
|
||||
@@ -167,7 +167,7 @@ Parse.serverURL = 'http://localhost:' + port + '/1';
|
||||
Parse.Promise.disableAPlusCompliant();
|
||||
|
||||
// 10 minutes timeout
|
||||
beforeAll(startDB, 10*60*1000);
|
||||
beforeAll(startDB, 10 * 60 * 1000);
|
||||
|
||||
afterAll(stopDB);
|
||||
|
||||
@@ -203,7 +203,7 @@ beforeEach(done => {
|
||||
});
|
||||
|
||||
afterEach(function(done) {
|
||||
let afterLogOut = () => {
|
||||
const afterLogOut = () => {
|
||||
if (Object.keys(openConnections).length > 0) {
|
||||
fail('There were open connections to the server left after the test finished');
|
||||
}
|
||||
@@ -370,7 +370,6 @@ function mockFacebook() {
|
||||
}
|
||||
|
||||
|
||||
|
||||
// This is polluting, but, it makes it way easier to directly port old tests.
|
||||
global.Parse = Parse;
|
||||
global.TestObject = TestObject;
|
||||
|
||||
+4
-4
@@ -207,7 +207,7 @@ describe('server', () => {
|
||||
it('can create a parse-server v2', done => {
|
||||
let objId;
|
||||
let server
|
||||
let parseServer = ParseServer.ParseServer(Object.assign({},
|
||||
const parseServer = ParseServer.ParseServer(Object.assign({},
|
||||
defaultConfiguration, {
|
||||
appId: "anOtherTestApp",
|
||||
masterKey: "anOtherTestMasterKey",
|
||||
@@ -216,16 +216,16 @@ describe('server', () => {
|
||||
promise
|
||||
.then(() => {
|
||||
expect(Parse.applicationId).toEqual("anOtherTestApp");
|
||||
let app = express();
|
||||
const app = express();
|
||||
app.use('/parse', parseServer);
|
||||
|
||||
server = app.listen(12667);
|
||||
let obj = new Parse.Object("AnObject");
|
||||
const obj = new Parse.Object("AnObject");
|
||||
return obj.save()
|
||||
})
|
||||
.then(obj => {
|
||||
objId = obj.id;
|
||||
let q = new Parse.Query("AnObject");
|
||||
const q = new Parse.Query("AnObject");
|
||||
return q.first();
|
||||
})
|
||||
.then(obj => {
|
||||
|
||||
@@ -31,4 +31,4 @@ describe('parsers', () => {
|
||||
expect(parser(1)).toEqual(true);
|
||||
expect(parser(2)).toEqual(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
+10
-10
@@ -7,10 +7,10 @@ var rest = require('../src/rest');
|
||||
var request = require('request');
|
||||
|
||||
var config = new Config('test');
|
||||
let database = config.database;
|
||||
const database = config.database;
|
||||
|
||||
describe('rest create', () => {
|
||||
|
||||
|
||||
beforeEach(() => {
|
||||
config = new Config('test');
|
||||
});
|
||||
@@ -28,7 +28,7 @@ describe('rest create', () => {
|
||||
});
|
||||
|
||||
it('handles array, object, date', (done) => {
|
||||
let now = new Date();
|
||||
const now = new Date();
|
||||
var obj = {
|
||||
array: [1, 2, 3],
|
||||
object: {foo: 'bar'},
|
||||
@@ -52,23 +52,23 @@ describe('rest create', () => {
|
||||
});
|
||||
|
||||
it('handles object and subdocument', done => {
|
||||
let obj = { subdoc: {foo: 'bar', wu: 'tan'} };
|
||||
const obj = { subdoc: {foo: 'bar', wu: 'tan'} };
|
||||
rest.create(config, auth.nobody(config), 'MyClass', obj)
|
||||
.then(() => database.adapter.find('MyClass', { fields: {} }, {}, {}))
|
||||
.then(results => {
|
||||
expect(results.length).toEqual(1);
|
||||
let mob = results[0];
|
||||
const mob = results[0];
|
||||
expect(typeof mob.subdoc).toBe('object');
|
||||
expect(mob.subdoc.foo).toBe('bar');
|
||||
expect(mob.subdoc.wu).toBe('tan');
|
||||
expect(typeof mob.objectId).toEqual('string');
|
||||
let obj = { 'subdoc.wu': 'clan' };
|
||||
const obj = { 'subdoc.wu': 'clan' };
|
||||
return rest.update(config, auth.nobody(config), 'MyClass', mob.objectId, obj)
|
||||
})
|
||||
.then(() => database.adapter.find('MyClass', { fields: {} }, {}, {}))
|
||||
.then(results => {
|
||||
expect(results.length).toEqual(1);
|
||||
let mob = results[0];
|
||||
const mob = results[0];
|
||||
expect(typeof mob.subdoc).toBe('object');
|
||||
expect(mob.subdoc.foo).toBe('bar');
|
||||
expect(mob.subdoc.wu).toBe('clan');
|
||||
@@ -267,7 +267,7 @@ describe('rest create', () => {
|
||||
});
|
||||
|
||||
it('stores pointers', done => {
|
||||
let obj = {
|
||||
const obj = {
|
||||
foo: 'bar',
|
||||
aPointer: {
|
||||
__type: 'Pointer',
|
||||
@@ -282,7 +282,7 @@ describe('rest create', () => {
|
||||
}}, {}, {}))
|
||||
.then(results => {
|
||||
expect(results.length).toEqual(1);
|
||||
let output = results[0];
|
||||
const output = results[0];
|
||||
expect(typeof output.foo).toEqual('string');
|
||||
expect(typeof output._p_aPointer).toEqual('undefined');
|
||||
expect(output._p_aPointer).toBeUndefined();
|
||||
@@ -374,7 +374,7 @@ describe('rest create', () => {
|
||||
|
||||
var session = r.results[0];
|
||||
var actual = new Date(session.expiresAt.iso);
|
||||
var expected = new Date(now.getTime() + (sessionLength*1000));
|
||||
var expected = new Date(now.getTime() + (sessionLength * 1000));
|
||||
|
||||
expect(actual.getFullYear()).toEqual(expected.getFullYear());
|
||||
expect(actual.getMonth()).toEqual(expected.getMonth());
|
||||
|
||||
+60
-60
@@ -23,7 +23,7 @@ var hasAllPODobject = () => {
|
||||
return obj;
|
||||
};
|
||||
|
||||
let defaultClassLevelPermissions = {
|
||||
const defaultClassLevelPermissions = {
|
||||
find: {
|
||||
'*': true
|
||||
},
|
||||
@@ -1008,7 +1008,7 @@ describe('schemas', () => {
|
||||
|
||||
it('should fail setting schema permissions with invalid key', done => {
|
||||
|
||||
let object = new Parse.Object('AClass');
|
||||
const object = new Parse.Object('AClass');
|
||||
object.save().then(() => {
|
||||
request.put({
|
||||
url: 'http://localhost:8378/1/schemas/AClass',
|
||||
@@ -1056,7 +1056,7 @@ describe('schemas', () => {
|
||||
}
|
||||
}, (error) => {
|
||||
expect(error).toEqual(null);
|
||||
let object = new Parse.Object('AClass');
|
||||
const object = new Parse.Object('AClass');
|
||||
object.set('hello', 'world');
|
||||
return object.save().then(() => {
|
||||
fail('should not be able to add a field');
|
||||
@@ -1085,7 +1085,7 @@ describe('schemas', () => {
|
||||
}
|
||||
}, (error) => {
|
||||
expect(error).toEqual(null);
|
||||
let object = new Parse.Object('AClass');
|
||||
const object = new Parse.Object('AClass');
|
||||
object.set('hello', 'world');
|
||||
return object.save().then(() => {
|
||||
done();
|
||||
@@ -1230,7 +1230,7 @@ describe('schemas', () => {
|
||||
}
|
||||
return new Promise((resolve, reject) => {
|
||||
op({
|
||||
url: 'http://localhost:8378/1/schemas/'+className,
|
||||
url: 'http://localhost:8378/1/schemas/' + className,
|
||||
headers: masterKeyHeaders,
|
||||
json: true,
|
||||
body: {
|
||||
@@ -1249,15 +1249,15 @@ describe('schemas', () => {
|
||||
}
|
||||
|
||||
it('validate CLP 1', done => {
|
||||
let user = new Parse.User();
|
||||
const user = new Parse.User();
|
||||
user.setUsername('user');
|
||||
user.setPassword('user');
|
||||
|
||||
let admin = new Parse.User();
|
||||
const admin = new Parse.User();
|
||||
admin.setUsername('admin');
|
||||
admin.setPassword('admin');
|
||||
|
||||
let role = new Parse.Role('admin', new Parse.ACL());
|
||||
const role = new Parse.Role('admin', new Parse.ACL());
|
||||
|
||||
setPermissionsOnClass('AClass', {
|
||||
'find': {
|
||||
@@ -1270,11 +1270,11 @@ describe('schemas', () => {
|
||||
return role.save(null, {useMasterKey: true});
|
||||
}).then(() => {
|
||||
return Parse.User.logIn('user', 'user').then(() => {
|
||||
let obj = new Parse.Object('AClass');
|
||||
const obj = new Parse.Object('AClass');
|
||||
return obj.save(null, {useMasterKey: true});
|
||||
})
|
||||
}).then(() => {
|
||||
let query = new Parse.Query('AClass');
|
||||
const query = new Parse.Query('AClass');
|
||||
return query.find().then(() => {
|
||||
fail('Use should hot be able to find!')
|
||||
}, (err) => {
|
||||
@@ -1283,28 +1283,28 @@ describe('schemas', () => {
|
||||
})
|
||||
}).then(() => {
|
||||
return Parse.User.logIn('admin', 'admin');
|
||||
}).then( () => {
|
||||
let query = new Parse.Query('AClass');
|
||||
}).then(() => {
|
||||
const query = new Parse.Query('AClass');
|
||||
return query.find();
|
||||
}).then((results) => {
|
||||
expect(results.length).toBe(1);
|
||||
done();
|
||||
}).catch( (err) => {
|
||||
}).catch((err) => {
|
||||
jfail(err);
|
||||
done();
|
||||
})
|
||||
});
|
||||
|
||||
it('validate CLP 2', done => {
|
||||
let user = new Parse.User();
|
||||
const user = new Parse.User();
|
||||
user.setUsername('user');
|
||||
user.setPassword('user');
|
||||
|
||||
let admin = new Parse.User();
|
||||
const admin = new Parse.User();
|
||||
admin.setUsername('admin');
|
||||
admin.setPassword('admin');
|
||||
|
||||
let role = new Parse.Role('admin', new Parse.ACL());
|
||||
const role = new Parse.Role('admin', new Parse.ACL());
|
||||
|
||||
setPermissionsOnClass('AClass', {
|
||||
'find': {
|
||||
@@ -1317,11 +1317,11 @@ describe('schemas', () => {
|
||||
return role.save(null, {useMasterKey: true});
|
||||
}).then(() => {
|
||||
return Parse.User.logIn('user', 'user').then(() => {
|
||||
let obj = new Parse.Object('AClass');
|
||||
const obj = new Parse.Object('AClass');
|
||||
return obj.save(null, {useMasterKey: true});
|
||||
})
|
||||
}).then(() => {
|
||||
let query = new Parse.Query('AClass');
|
||||
const query = new Parse.Query('AClass');
|
||||
return query.find().then(() => {
|
||||
fail('User should not be able to find!')
|
||||
}, (err) => {
|
||||
@@ -1337,7 +1337,7 @@ describe('schemas', () => {
|
||||
}
|
||||
}, true);
|
||||
}).then(() => {
|
||||
let query = new Parse.Query('AClass');
|
||||
const query = new Parse.Query('AClass');
|
||||
return query.find().then((result) => {
|
||||
expect(result.length).toBe(1);
|
||||
}, () => {
|
||||
@@ -1346,28 +1346,28 @@ describe('schemas', () => {
|
||||
});
|
||||
}).then(() => {
|
||||
return Parse.User.logIn('admin', 'admin');
|
||||
}).then( () => {
|
||||
let query = new Parse.Query('AClass');
|
||||
}).then(() => {
|
||||
const query = new Parse.Query('AClass');
|
||||
return query.find();
|
||||
}).then((results) => {
|
||||
expect(results.length).toBe(1);
|
||||
done();
|
||||
}).catch( (err) => {
|
||||
}).catch((err) => {
|
||||
jfail(err);
|
||||
done();
|
||||
})
|
||||
});
|
||||
|
||||
it('validate CLP 3', done => {
|
||||
let user = new Parse.User();
|
||||
const user = new Parse.User();
|
||||
user.setUsername('user');
|
||||
user.setPassword('user');
|
||||
|
||||
let admin = new Parse.User();
|
||||
const admin = new Parse.User();
|
||||
admin.setUsername('admin');
|
||||
admin.setPassword('admin');
|
||||
|
||||
let role = new Parse.Role('admin', new Parse.ACL());
|
||||
const role = new Parse.Role('admin', new Parse.ACL());
|
||||
|
||||
setPermissionsOnClass('AClass', {
|
||||
'find': {
|
||||
@@ -1380,11 +1380,11 @@ describe('schemas', () => {
|
||||
return role.save(null, {useMasterKey: true});
|
||||
}).then(() => {
|
||||
return Parse.User.logIn('user', 'user').then(() => {
|
||||
let obj = new Parse.Object('AClass');
|
||||
const obj = new Parse.Object('AClass');
|
||||
return obj.save(null, {useMasterKey: true});
|
||||
})
|
||||
}).then(() => {
|
||||
let query = new Parse.Query('AClass');
|
||||
const query = new Parse.Query('AClass');
|
||||
return query.find().then(() => {
|
||||
fail('User should not be able to find!')
|
||||
}, (err) => {
|
||||
@@ -1395,7 +1395,7 @@ describe('schemas', () => {
|
||||
// delete all CLP
|
||||
return setPermissionsOnClass('AClass', null, true);
|
||||
}).then(() => {
|
||||
let query = new Parse.Query('AClass');
|
||||
const query = new Parse.Query('AClass');
|
||||
return query.find().then((result) => {
|
||||
expect(result.length).toBe(1);
|
||||
}, () => {
|
||||
@@ -1404,8 +1404,8 @@ describe('schemas', () => {
|
||||
});
|
||||
}).then(() => {
|
||||
return Parse.User.logIn('admin', 'admin');
|
||||
}).then( () => {
|
||||
let query = new Parse.Query('AClass');
|
||||
}).then(() => {
|
||||
const query = new Parse.Query('AClass');
|
||||
return query.find();
|
||||
}).then((results) => {
|
||||
expect(results.length).toBe(1);
|
||||
@@ -1417,15 +1417,15 @@ describe('schemas', () => {
|
||||
});
|
||||
|
||||
it('validate CLP 4', done => {
|
||||
let user = new Parse.User();
|
||||
const user = new Parse.User();
|
||||
user.setUsername('user');
|
||||
user.setPassword('user');
|
||||
|
||||
let admin = new Parse.User();
|
||||
const admin = new Parse.User();
|
||||
admin.setUsername('admin');
|
||||
admin.setPassword('admin');
|
||||
|
||||
let role = new Parse.Role('admin', new Parse.ACL());
|
||||
const role = new Parse.Role('admin', new Parse.ACL());
|
||||
|
||||
setPermissionsOnClass('AClass', {
|
||||
'find': {
|
||||
@@ -1438,11 +1438,11 @@ describe('schemas', () => {
|
||||
return role.save(null, {useMasterKey: true});
|
||||
}).then(() => {
|
||||
return Parse.User.logIn('user', 'user').then(() => {
|
||||
let obj = new Parse.Object('AClass');
|
||||
const obj = new Parse.Object('AClass');
|
||||
return obj.save(null, {useMasterKey: true});
|
||||
})
|
||||
}).then(() => {
|
||||
let query = new Parse.Query('AClass');
|
||||
const query = new Parse.Query('AClass');
|
||||
return query.find().then(() => {
|
||||
fail('User should not be able to find!')
|
||||
}, (err) => {
|
||||
@@ -1461,7 +1461,7 @@ describe('schemas', () => {
|
||||
return Promise.resolve();
|
||||
})
|
||||
}).then(() => {
|
||||
let query = new Parse.Query('AClass');
|
||||
const query = new Parse.Query('AClass');
|
||||
return query.find().then(() => {
|
||||
fail('User should not be able to find!')
|
||||
}, (err) => {
|
||||
@@ -1470,38 +1470,38 @@ describe('schemas', () => {
|
||||
});
|
||||
}).then(() => {
|
||||
return Parse.User.logIn('admin', 'admin');
|
||||
}).then( () => {
|
||||
let query = new Parse.Query('AClass');
|
||||
}).then(() => {
|
||||
const query = new Parse.Query('AClass');
|
||||
return query.find();
|
||||
}).then((results) => {
|
||||
expect(results.length).toBe(1);
|
||||
done();
|
||||
}).catch( (err) => {
|
||||
}).catch((err) => {
|
||||
jfail(err);
|
||||
done();
|
||||
})
|
||||
});
|
||||
|
||||
it('validate CLP 5', done => {
|
||||
let user = new Parse.User();
|
||||
const user = new Parse.User();
|
||||
user.setUsername('user');
|
||||
user.setPassword('user');
|
||||
|
||||
let user2 = new Parse.User();
|
||||
const user2 = new Parse.User();
|
||||
user2.setUsername('user2');
|
||||
user2.setPassword('user2');
|
||||
let admin = new Parse.User();
|
||||
const admin = new Parse.User();
|
||||
admin.setUsername('admin');
|
||||
admin.setPassword('admin');
|
||||
|
||||
let role = new Parse.Role('admin', new Parse.ACL());
|
||||
const role = new Parse.Role('admin', new Parse.ACL());
|
||||
|
||||
Promise.resolve().then(() => {
|
||||
return Parse.Object.saveAll([user, user2, admin, role], {useMasterKey: true});
|
||||
}).then(()=> {
|
||||
role.relation('users').add(admin);
|
||||
return role.save(null, {useMasterKey: true}).then(() => {
|
||||
let perm = {
|
||||
const perm = {
|
||||
find: {}
|
||||
};
|
||||
// let the user find
|
||||
@@ -1510,11 +1510,11 @@ describe('schemas', () => {
|
||||
})
|
||||
}).then(() => {
|
||||
return Parse.User.logIn('user', 'user').then(() => {
|
||||
let obj = new Parse.Object('AClass');
|
||||
const obj = new Parse.Object('AClass');
|
||||
return obj.save();
|
||||
})
|
||||
}).then(() => {
|
||||
let query = new Parse.Query('AClass');
|
||||
const query = new Parse.Query('AClass');
|
||||
return query.find().then((res) => {
|
||||
expect(res.length).toEqual(1);
|
||||
}, () => {
|
||||
@@ -1523,8 +1523,8 @@ describe('schemas', () => {
|
||||
})
|
||||
}).then(() => {
|
||||
return Parse.User.logIn('admin', 'admin');
|
||||
}).then( () => {
|
||||
let query = new Parse.Query('AClass');
|
||||
}).then(() => {
|
||||
const query = new Parse.Query('AClass');
|
||||
return query.find();
|
||||
}).then(() => {
|
||||
fail("should not be able to read!");
|
||||
@@ -1534,8 +1534,8 @@ describe('schemas', () => {
|
||||
return Promise.resolve();
|
||||
}).then(() => {
|
||||
return Parse.User.logIn('user2', 'user2');
|
||||
}).then( () => {
|
||||
let query = new Parse.Query('AClass');
|
||||
}).then(() => {
|
||||
const query = new Parse.Query('AClass');
|
||||
return query.find();
|
||||
}).then(() => {
|
||||
fail("should not be able to read!");
|
||||
@@ -1557,13 +1557,13 @@ describe('schemas', () => {
|
||||
delete: {'*': true},
|
||||
addField:{'*': true}
|
||||
}).then(() => {
|
||||
let obj = new Parse.Object('AnObject');
|
||||
let anotherObject = new Parse.Object('AnotherObject');
|
||||
const obj = new Parse.Object('AnObject');
|
||||
const anotherObject = new Parse.Object('AnotherObject');
|
||||
return obj.save({
|
||||
anotherObject
|
||||
})
|
||||
}).then(() => {
|
||||
let query = new Parse.Query('AnObject');
|
||||
const query = new Parse.Query('AnObject');
|
||||
query.include('anotherObject');
|
||||
return query.find();
|
||||
}).then((res) => {
|
||||
@@ -1625,11 +1625,11 @@ describe('schemas', () => {
|
||||
});
|
||||
|
||||
it("regression test for #1991", done => {
|
||||
let user = new Parse.User();
|
||||
const user = new Parse.User();
|
||||
user.setUsername('user');
|
||||
user.setPassword('user');
|
||||
let role = new Parse.Role('admin', new Parse.ACL());
|
||||
let obj = new Parse.Object('AnObject');
|
||||
const role = new Parse.Role('admin', new Parse.ACL());
|
||||
const obj = new Parse.Object('AnObject');
|
||||
Parse.Object.saveAll([user, role]).then(() => {
|
||||
role.relation('users').add(user);
|
||||
return role.save(null, {useMasterKey: true});
|
||||
@@ -1648,7 +1648,7 @@ describe('schemas', () => {
|
||||
}).then(() => {
|
||||
return obj.destroy();
|
||||
}).then(() => {
|
||||
let query = new Parse.Query('AnObject');
|
||||
const query = new Parse.Query('AnObject');
|
||||
return query.find();
|
||||
}).then((results) => {
|
||||
expect(results.length).toBe(0);
|
||||
@@ -1661,8 +1661,8 @@ describe('schemas', () => {
|
||||
});
|
||||
|
||||
it('regression test for #2246', done => {
|
||||
let profile = new Parse.Object('UserProfile');
|
||||
let user = new Parse.User();
|
||||
const profile = new Parse.Object('UserProfile');
|
||||
const user = new Parse.User();
|
||||
function initialize() {
|
||||
return user.save({
|
||||
username: 'user',
|
||||
@@ -1684,7 +1684,7 @@ describe('schemas', () => {
|
||||
}).then(() => {
|
||||
return Parse.User.logIn('user', 'password')
|
||||
}).then(() => {
|
||||
let query = new Parse.Query('_User');
|
||||
const query = new Parse.Query('_User');
|
||||
query.include('userProfile');
|
||||
return query.get(user.id);
|
||||
}).then((user) => {
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
|
||||
module.exports = {
|
||||
validateAppId: function() {
|
||||
return Promise.resolve();
|
||||
},
|
||||
validateAuthData: function(authData) {
|
||||
if (authData.token == 'my-token') {
|
||||
return Promise.resolve();
|
||||
}
|
||||
return Promise.reject();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
|
||||
module.exports = function(validAuthData) {
|
||||
return {
|
||||
validateAppId: function() {
|
||||
return Promise.resolve();
|
||||
},
|
||||
validateAuthData: function(authData) {
|
||||
if (authData.token == validAuthData.token) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
return Promise.reject();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,7 @@ export class AccountLockout {
|
||||
* set _failed_login_count to value
|
||||
*/
|
||||
_setFailedLoginCount(value) {
|
||||
let query = {
|
||||
const query = {
|
||||
username: this._user.username
|
||||
};
|
||||
|
||||
@@ -84,8 +84,8 @@ export class AccountLockout {
|
||||
}
|
||||
|
||||
/**
|
||||
* if the failed login count is greater than the threshold
|
||||
* then sets lockout expiration to 'currenttime + accountPolicy.duration', i.e., account is locked out for the next 'accountPolicy.duration' minutes
|
||||
* if the failed login count is greater than the threshold
|
||||
* then sets lockout expiration to 'currenttime + accountPolicy.duration', i.e., account is locked out for the next 'accountPolicy.duration' minutes
|
||||
* else do nothing
|
||||
*/
|
||||
_setLockoutExpiration() {
|
||||
@@ -98,7 +98,7 @@ export class AccountLockout {
|
||||
const now = new Date();
|
||||
|
||||
const updateFields = {
|
||||
_account_lockout_expires_at: Parse._encode(new Date(now.getTime() + this._config.accountLockout.duration*60*1000))
|
||||
_account_lockout_expires_at: Parse._encode(new Date(now.getTime() + this._config.accountLockout.duration * 60 * 1000))
|
||||
};
|
||||
|
||||
this._config.database.update('_User', query, updateFields)
|
||||
@@ -147,8 +147,8 @@ export class AccountLockout {
|
||||
* set and/or increment _failed_login_count
|
||||
* if _failed_login_count > threshold
|
||||
* set the _account_lockout_expires_at to current_time + accountPolicy.duration
|
||||
* else
|
||||
* do nothing
|
||||
* else
|
||||
* do nothing
|
||||
*/
|
||||
_handleFailedLoginAttempt() {
|
||||
return new Promise((resolve, reject) => {
|
||||
@@ -175,7 +175,7 @@ export class AccountLockout {
|
||||
if (!this._config.accountLockout) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
this._notLocked()
|
||||
.then(() => {
|
||||
|
||||
@@ -17,6 +17,7 @@ export function loadAdapter(adapter, defaultAdapter, options) {
|
||||
}
|
||||
}
|
||||
} else if (typeof adapter === "string") {
|
||||
/* eslint-disable */
|
||||
adapter = require(adapter);
|
||||
// If it's define as a module, get the default
|
||||
if (adapter.default) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*eslint no-unused-vars: "off"*/
|
||||
export class AnalyticsAdapter {
|
||||
|
||||
|
||||
/*
|
||||
@param parameters: the analytics request body, analytics info will be in the dimensions property
|
||||
@param req: the original http request
|
||||
@@ -8,7 +8,7 @@ export class AnalyticsAdapter {
|
||||
appOpened(parameters, req) {
|
||||
return Promise.resolve({});
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
@param eventName: the name of the custom eventName
|
||||
@param parameters: the analytics request body, analytics info will be in the dimensions property
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
/*eslint no-unused-vars: "off"*/
|
||||
export class AuthAdapter {
|
||||
|
||||
/*
|
||||
@param appIds: the specified app ids in the configuration
|
||||
@param authData: the client provided authData
|
||||
@returns a promise that resolves if the applicationId is valid
|
||||
*/
|
||||
validateAppId(appIds, authData) {
|
||||
return Promise.resolve({});
|
||||
}
|
||||
|
||||
/*
|
||||
@param authData: the client provided authData
|
||||
@param options: additional options
|
||||
*/
|
||||
validateAuthData(authData, options) {
|
||||
return Promise.resolve({});
|
||||
}
|
||||
}
|
||||
|
||||
export default AuthAdapter;
|
||||
@@ -36,7 +36,7 @@ OAuth.prototype.send = function(method, path, params, body){
|
||||
|
||||
OAuth.prototype.buildRequest = function(method, path, params, body) {
|
||||
if (path.indexOf("/") != 0) {
|
||||
path = "/"+path;
|
||||
path = "/" + path;
|
||||
}
|
||||
if (params && Object.keys(params).length > 0) {
|
||||
path += "?" + OAuth.buildParameterString(params);
|
||||
@@ -118,7 +118,7 @@ OAuth.nonce = function(){
|
||||
var text = "";
|
||||
var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
||||
|
||||
for( var i=0; i < 30; i++ )
|
||||
for(var i = 0; i < 30; i++)
|
||||
text += possible.charAt(Math.floor(Math.random() * possible.length));
|
||||
|
||||
return text;
|
||||
@@ -162,7 +162,7 @@ OAuth.signRequest = function(request, oauth_parameters, consumer_secret, auth_to
|
||||
oauth_parameters.oauth_nonce = OAuth.nonce();
|
||||
}
|
||||
if (!oauth_parameters.oauth_timestamp) {
|
||||
oauth_parameters.oauth_timestamp = Math.floor(new Date().getTime()/1000);
|
||||
oauth_parameters.oauth_timestamp = Math.floor(new Date().getTime() / 1000);
|
||||
}
|
||||
if (!oauth_parameters.oauth_signature_method) {
|
||||
oauth_parameters.oauth_signature_method = OAuth.signatureMethod;
|
||||
@@ -172,7 +172,7 @@ OAuth.signRequest = function(request, oauth_parameters, consumer_secret, auth_to
|
||||
}
|
||||
|
||||
if(!auth_token_secret){
|
||||
auth_token_secret="";
|
||||
auth_token_secret = "";
|
||||
}
|
||||
// Force GET method if unset
|
||||
if (!request.method) {
|
||||
@@ -193,7 +193,7 @@ OAuth.signRequest = function(request, oauth_parameters, consumer_secret, auth_to
|
||||
var parameterString = OAuth.buildParameterString(signatureParams);
|
||||
|
||||
// Build the signature string
|
||||
var url = "https://"+request.host+""+request.path;
|
||||
var url = "https://" + request.host + "" + request.path;
|
||||
|
||||
var signatureString = OAuth.buildSignatureString(request.method, url, parameterString);
|
||||
// Hash the signature string
|
||||
@@ -210,7 +210,7 @@ OAuth.signRequest = function(request, oauth_parameters, consumer_secret, auth_to
|
||||
// Set the authorization header
|
||||
var authHeader = Object.keys(oauth_parameters).sort().map(function(key){
|
||||
var value = oauth_parameters[key];
|
||||
return key+'="'+value+'"';
|
||||
return key + '="' + value + '"';
|
||||
}).join(", ")
|
||||
|
||||
request.headers.Authorization = 'OAuth ' + authHeader;
|
||||
@@ -221,4 +221,4 @@ OAuth.signRequest = function(request, oauth_parameters, consumer_secret, auth_to
|
||||
|
||||
}
|
||||
|
||||
module.exports = OAuth;
|
||||
module.exports = OAuth;
|
||||
@@ -27,7 +27,7 @@ function request(path, access_token) {
|
||||
host: 'api.github.com',
|
||||
path: '/' + path,
|
||||
headers: {
|
||||
'Authorization': 'bearer '+access_token,
|
||||
'Authorization': 'bearer ' + access_token,
|
||||
'User-Agent': 'parse-server'
|
||||
}
|
||||
}, function(res) {
|
||||
@@ -3,7 +3,7 @@ var https = require('https');
|
||||
var Parse = require('parse/node').Parse;
|
||||
|
||||
function validateIdToken(id, token) {
|
||||
return request("tokeninfo?id_token="+token)
|
||||
return request("tokeninfo?id_token=" + token)
|
||||
.then((response) => {
|
||||
if (response && (response.sub == id || response.user_id == id)) {
|
||||
return;
|
||||
@@ -15,7 +15,7 @@ function validateIdToken(id, token) {
|
||||
}
|
||||
|
||||
function validateAuthToken(id, token) {
|
||||
return request("tokeninfo?access_token="+token)
|
||||
return request("tokeninfo?access_token=" + token)
|
||||
.then((response) => {
|
||||
if (response && (response.sub == id || response.user_id == id)) {
|
||||
return;
|
||||
@@ -29,7 +29,7 @@ function validateAuthToken(id, token) {
|
||||
// Returns a promise that fulfills if this user id is valid.
|
||||
function validateAuthData(authData) {
|
||||
if (authData.id_token) {
|
||||
return validateIdToken(authData.id, authData.id_token);
|
||||
return validateIdToken(authData.id, authData.id_token);
|
||||
} else {
|
||||
return validateAuthToken(authData.id, authData.access_token).then(() => {
|
||||
// Validation with auth token worked
|
||||
Executable
+115
@@ -0,0 +1,115 @@
|
||||
import loadAdapter from '../AdapterLoader';
|
||||
|
||||
const facebook = require('./facebook');
|
||||
const instagram = require("./instagram");
|
||||
const linkedin = require("./linkedin");
|
||||
const meetup = require("./meetup");
|
||||
const google = require("./google");
|
||||
const github = require("./github");
|
||||
const twitter = require("./twitter");
|
||||
const spotify = require("./spotify");
|
||||
const digits = require("./twitter"); // digits tokens are validated by twitter
|
||||
const janrainengage = require("./janrainengage");
|
||||
const janraincapture = require("./janraincapture");
|
||||
const vkontakte = require("./vkontakte");
|
||||
const qq = require("./qq");
|
||||
const wechat = require("./wechat");
|
||||
const weibo = require("./weibo");
|
||||
|
||||
const anonymous = {
|
||||
validateAuthData: () => {
|
||||
return Promise.resolve();
|
||||
},
|
||||
validateAppId: () => {
|
||||
return Promise.resolve();
|
||||
}
|
||||
}
|
||||
|
||||
const providers = {
|
||||
facebook,
|
||||
instagram,
|
||||
linkedin,
|
||||
meetup,
|
||||
google,
|
||||
github,
|
||||
twitter,
|
||||
spotify,
|
||||
anonymous,
|
||||
digits,
|
||||
janrainengage,
|
||||
janraincapture,
|
||||
vkontakte,
|
||||
qq,
|
||||
wechat,
|
||||
weibo
|
||||
}
|
||||
|
||||
function authDataValidator(adapter, appIds, options) {
|
||||
return function(authData) {
|
||||
return adapter.validateAuthData(authData, options).then(() => {
|
||||
if (appIds) {
|
||||
return adapter.validateAppId(appIds, authData, options);
|
||||
}
|
||||
return Promise.resolve();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function loadAuthAdapter(provider, authOptions) {
|
||||
const defaultAdapter = providers[provider];
|
||||
const adapter = Object.assign({}, defaultAdapter);
|
||||
const providerOptions = authOptions[provider];
|
||||
|
||||
if (!defaultAdapter && !providerOptions) {
|
||||
return;
|
||||
}
|
||||
|
||||
const appIds = providerOptions ? providerOptions.appIds : undefined;
|
||||
|
||||
// Try the configuration methods
|
||||
if (providerOptions) {
|
||||
const optionalAdapter = loadAdapter(providerOptions, undefined, providerOptions);
|
||||
if (optionalAdapter) {
|
||||
['validateAuthData', 'validateAppId'].forEach((key) => {
|
||||
if (optionalAdapter[key]) {
|
||||
adapter[key] = optionalAdapter[key];
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (!adapter.validateAuthData || !adapter.validateAppId) {
|
||||
return;
|
||||
}
|
||||
|
||||
return {adapter, appIds, providerOptions};
|
||||
}
|
||||
|
||||
module.exports = function(authOptions = {}, enableAnonymousUsers = true) {
|
||||
let _enableAnonymousUsers = enableAnonymousUsers;
|
||||
const setEnableAnonymousUsers = function(enable) {
|
||||
_enableAnonymousUsers = enable;
|
||||
}
|
||||
// To handle the test cases on configuration
|
||||
const getValidatorForProvider = function(provider) {
|
||||
|
||||
if (provider === 'anonymous' && !_enableAnonymousUsers) {
|
||||
return;
|
||||
}
|
||||
|
||||
const {
|
||||
adapter,
|
||||
appIds,
|
||||
providerOptions
|
||||
} = loadAuthAdapter(provider, authOptions);
|
||||
|
||||
return authDataValidator(adapter, appIds, providerOptions);
|
||||
}
|
||||
|
||||
return Object.freeze({
|
||||
getValidatorForProvider,
|
||||
setEnableAnonymousUsers
|
||||
})
|
||||
}
|
||||
|
||||
module.exports.loadAuthAdapter = loadAuthAdapter;
|
||||
@@ -4,7 +4,7 @@ var Parse = require('parse/node').Parse;
|
||||
|
||||
// Returns a promise that fulfills iff this user id is valid.
|
||||
function validateAuthData(authData) {
|
||||
return request("users/self/?access_token="+authData.access_token)
|
||||
return request("users/self/?access_token=" + authData.access_token)
|
||||
.then((response) => {
|
||||
if (response && response.data && response.data.id == authData.id) {
|
||||
return;
|
||||
@@ -27,7 +27,7 @@ function request(path, access_token) {
|
||||
host: 'api.meetup.com',
|
||||
path: '/2/' + path,
|
||||
headers: {
|
||||
'Authorization': 'bearer '+access_token
|
||||
'Authorization': 'bearer ' + access_token
|
||||
}
|
||||
}, function(res) {
|
||||
var data = '';
|
||||
@@ -26,12 +26,12 @@ function graphRequest(path) {
|
||||
data += chunk;
|
||||
});
|
||||
res.on('end', function () {
|
||||
var starPos=data.indexOf("(");
|
||||
var endPos=data.indexOf(")");
|
||||
if(starPos==-1||endPos==-1){
|
||||
var starPos = data.indexOf("(");
|
||||
var endPos = data.indexOf(")");
|
||||
if(starPos == -1 || endPos == -1){
|
||||
throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'qq auth is invalid for this user.');
|
||||
}
|
||||
data=data.substring(starPos+1,endPos-1);
|
||||
data = data.substring(starPos + 1,endPos - 1);
|
||||
data = JSON.parse(data);
|
||||
resolve(data);
|
||||
});
|
||||
@@ -41,7 +41,7 @@ function request(path, access_token) {
|
||||
host: 'api.spotify.com',
|
||||
path: '/v1/' + path,
|
||||
headers: {
|
||||
'Authorization': 'Bearer '+access_token
|
||||
'Authorization': 'Bearer ' + access_token
|
||||
}
|
||||
}, function(res) {
|
||||
var data = '';
|
||||
@@ -1,7 +1,7 @@
|
||||
// Helper functions for accessing the twitter API.
|
||||
var OAuth = require('./OAuth1Client');
|
||||
var Parse = require('parse/node').Parse;
|
||||
var logger = require('../logger').default;
|
||||
var logger = require('../../logger').default;
|
||||
|
||||
// Returns a promise that fulfills iff this user id is valid.
|
||||
function validateAuthData(authData, options) {
|
||||
@@ -10,9 +10,9 @@ function validateAuthData(authData, options) {
|
||||
client.host = "api.twitter.com";
|
||||
client.auth_token = authData.auth_token;
|
||||
client.auth_token_secret = authData.auth_token_secret;
|
||||
|
||||
|
||||
return client.get("/1.1/account/verify_credentials.json").then((data) => {
|
||||
if (data && data.id_str == ''+authData.id) {
|
||||
if (data && data.id_str == '' + authData.id) {
|
||||
return;
|
||||
}
|
||||
throw new Parse.Error(
|
||||
@@ -28,7 +28,7 @@ function validateAppId() {
|
||||
|
||||
function handleMultipleConfigurations(authData, options) {
|
||||
if (Array.isArray(options)) {
|
||||
let consumer_key = authData.consumer_key;
|
||||
const consumer_key = authData.consumer_key;
|
||||
if (!consumer_key) {
|
||||
logger.error('Twitter Auth', 'Multiple twitter configurations are available, by no consumer_key was sent by the client.');
|
||||
throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Twitter auth is invalid for this user.');
|
||||
@@ -4,10 +4,10 @@
|
||||
|
||||
var https = require('https');
|
||||
var Parse = require('parse/node').Parse;
|
||||
var logger = require('../logger').default;
|
||||
var logger = require('../../logger').default;
|
||||
|
||||
// Returns a promise that fulfills iff this user id is valid.
|
||||
function validateAuthData(authData, params) {
|
||||
function validateAuthData(authData, params) {
|
||||
return vkOAuth2Request(params).then(function (response) {
|
||||
if (response && response && response.access_token) {
|
||||
return request("api.vk.com", "method/secure.checkToken?token=" + authData.access_token + "&client_secret=" + params.appSecret + "&access_token=" + response.access_token).then(function (response) {
|
||||
@@ -25,7 +25,7 @@ function validateAuthData(authData, params) {
|
||||
function vkOAuth2Request(params) {
|
||||
var promise = new Parse.Promise();
|
||||
return promise.then(function(){
|
||||
if (!params || !params.appIds || !params.appIds.length || !params.appSecret || !params.appSecret.length ) {
|
||||
if (!params || !params.appIds || !params.appIds.length || !params.appSecret || !params.appSecret.length) {
|
||||
logger.error('Vk Auth', 'Vk auth is not configured. Missing appIds or appSecret.');
|
||||
throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Vk auth is not configured. Missing appIds or appSecret.');
|
||||
}
|
||||
@@ -59,4 +59,4 @@ function request(host, path) {
|
||||
module.exports = {
|
||||
validateAppId: validateAppId,
|
||||
validateAuthData: validateAuthData
|
||||
};
|
||||
};
|
||||
@@ -4,7 +4,7 @@ var Parse = require('parse/node').Parse;
|
||||
|
||||
// Returns a promise that fulfills iff this user id is valid.
|
||||
function validateAuthData(authData) {
|
||||
return graphRequest('auth?access_token=' + authData.access_token +'&openid=' +authData.id).then(function (data) {
|
||||
return graphRequest('auth?access_token=' + authData.access_token + '&openid=' + authData.id).then(function (data) {
|
||||
if (data.errcode == 0) {
|
||||
return;
|
||||
}
|
||||
@@ -10,7 +10,7 @@ export class InMemoryCache {
|
||||
}
|
||||
|
||||
get(key) {
|
||||
let record = this.cache[key];
|
||||
const record = this.cache[key];
|
||||
if (record == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ export class InMemoryCacheAdapter {
|
||||
|
||||
get(key) {
|
||||
return new Promise((resolve) => {
|
||||
let record = this.cache.get(key);
|
||||
const record = this.cache.get(key);
|
||||
if (record == null) {
|
||||
return resolve(null);
|
||||
}
|
||||
|
||||
@@ -71,7 +71,7 @@ export class RedisCacheAdapter {
|
||||
debug('clear');
|
||||
this.p = this.p.then(() => {
|
||||
return new Promise((resolve) => {
|
||||
this.client.flushall(function() {
|
||||
this.client.flushdb(function() {
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -12,7 +12,7 @@ export class MailAdapter {
|
||||
* - subject: the subject of the email
|
||||
*/
|
||||
sendMail(options) {}
|
||||
|
||||
|
||||
/* You can implement those methods if you want
|
||||
* to provide HTML templates etc...
|
||||
*/
|
||||
|
||||
@@ -30,7 +30,7 @@ export class GridStoreAdapter extends FilesAdapter {
|
||||
// Returns a promise
|
||||
createFile(filename: string, data) {
|
||||
return this._connect().then(database => {
|
||||
let gridStore = new GridStore(database, filename, 'w');
|
||||
const gridStore = new GridStore(database, filename, 'w');
|
||||
return gridStore.open();
|
||||
}).then(gridStore => {
|
||||
return gridStore.write(data);
|
||||
@@ -41,7 +41,7 @@ export class GridStoreAdapter extends FilesAdapter {
|
||||
|
||||
deleteFile(filename: string) {
|
||||
return this._connect().then(database => {
|
||||
let gridStore = new GridStore(database, filename, 'r');
|
||||
const gridStore = new GridStore(database, filename, 'r');
|
||||
return gridStore.open();
|
||||
}).then((gridStore) => {
|
||||
return gridStore.unlink();
|
||||
@@ -54,7 +54,7 @@ export class GridStoreAdapter extends FilesAdapter {
|
||||
return this._connect().then(database => {
|
||||
return GridStore.exist(database, filename)
|
||||
.then(() => {
|
||||
let gridStore = new GridStore(database, filename, 'r');
|
||||
const gridStore = new GridStore(database, filename, 'r');
|
||||
return gridStore.open();
|
||||
});
|
||||
}).then(gridStore => {
|
||||
@@ -69,7 +69,7 @@ export class GridStoreAdapter extends FilesAdapter {
|
||||
getFileStream(filename: string) {
|
||||
return this._connect().then(database => {
|
||||
return GridStore.exist(database, filename).then(() => {
|
||||
let gridStore = new GridStore(database, filename, 'r');
|
||||
const gridStore = new GridStore(database, filename, 'r');
|
||||
return gridStore.open();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -9,9 +9,9 @@ const logger = new winston.Logger();
|
||||
const additionalTransports = [];
|
||||
|
||||
function updateTransports(options) {
|
||||
let transports = Object.assign({}, logger.transports);
|
||||
const transports = Object.assign({}, logger.transports);
|
||||
if (options) {
|
||||
let silent = options.silent;
|
||||
const silent = options.silent;
|
||||
delete options.silent;
|
||||
if (_.isNull(options.dirname)) {
|
||||
delete transports['parse-server'];
|
||||
@@ -21,12 +21,12 @@ function updateTransports(options) {
|
||||
Object.assign({}, {
|
||||
filename: 'parse-server.info',
|
||||
name: 'parse-server',
|
||||
}, options));
|
||||
}, options, { timestamp: true }));
|
||||
transports['parse-server-error'] = new (DailyRotateFile)(
|
||||
Object.assign({}, {
|
||||
filename: 'parse-server.err',
|
||||
name: 'parse-server-error',
|
||||
}, options, { level: 'error'}));
|
||||
}, options, { level: 'error', timestamp: true }));
|
||||
}
|
||||
|
||||
transports.console = new (winston.transports.Console)(
|
||||
@@ -84,8 +84,8 @@ export function addTransport(transport) {
|
||||
}
|
||||
|
||||
export function removeTransport(transport) {
|
||||
let transportName = typeof transport == 'string' ? transport : transport.name;
|
||||
let transports = Object.assign({}, logger.transports);
|
||||
const transportName = typeof transport == 'string' ? transport : transport.name;
|
||||
const transports = Object.assign({}, logger.transports);
|
||||
delete transports[transportName];
|
||||
logger.configure({
|
||||
transports: _.values(transports)
|
||||
|
||||
@@ -28,11 +28,11 @@ export class WinstonLoggerAdapter extends LoggerAdapter {
|
||||
options = {};
|
||||
}
|
||||
// defaults to 7 days prior
|
||||
let from = options.from || new Date(Date.now() - (7 * MILLISECONDS_IN_A_DAY));
|
||||
let until = options.until || new Date();
|
||||
let limit = options.size || 10;
|
||||
let order = options.order || 'desc';
|
||||
let level = options.level || 'info';
|
||||
const from = options.from || new Date(Date.now() - (7 * MILLISECONDS_IN_A_DAY));
|
||||
const until = options.until || new Date();
|
||||
const limit = options.size || 10;
|
||||
const order = options.order || 'desc';
|
||||
const level = options.level || 'info';
|
||||
|
||||
const queryOptions = {
|
||||
from,
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
import events from 'events';
|
||||
|
||||
const emitter = new events.EventEmitter();
|
||||
const subscriptions = new Map();
|
||||
|
||||
function unsubscribe(channel: string) {
|
||||
if (!subscriptions.has(channel)) {
|
||||
//console.log('No channel to unsub from');
|
||||
return;
|
||||
}
|
||||
//console.log('unsub ', channel);
|
||||
emitter.removeListener(channel, subscriptions.get(channel));
|
||||
subscriptions.delete(channel);
|
||||
}
|
||||
|
||||
class Publisher {
|
||||
emitter: any;
|
||||
|
||||
constructor(emitter: any) {
|
||||
this.emitter = emitter;
|
||||
}
|
||||
|
||||
publish(channel: string, message: string): void {
|
||||
this.emitter.emit(channel, message);
|
||||
}
|
||||
}
|
||||
|
||||
class Consumer extends events.EventEmitter {
|
||||
emitter: any;
|
||||
|
||||
constructor(emitter: any) {
|
||||
super();
|
||||
this.emitter = emitter;
|
||||
}
|
||||
|
||||
subscribe(channel: string): void {
|
||||
unsubscribe(channel);
|
||||
const handler = (message) => {
|
||||
this.emit('message', channel, message);
|
||||
}
|
||||
subscriptions.set(channel, handler);
|
||||
this.emitter.on(channel, handler);
|
||||
}
|
||||
|
||||
unsubscribe(channel: string): void {
|
||||
unsubscribe(channel);
|
||||
}
|
||||
}
|
||||
|
||||
function createPublisher(): any {
|
||||
return new Publisher(emitter);
|
||||
}
|
||||
|
||||
function createSubscriber(): any {
|
||||
return new Consumer(emitter);
|
||||
}
|
||||
|
||||
const EventEmitterMQ = {
|
||||
createPublisher,
|
||||
createSubscriber
|
||||
}
|
||||
|
||||
export {
|
||||
EventEmitterMQ
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
import events from 'events';
|
||||
|
||||
let emitter = new events.EventEmitter();
|
||||
const emitter = new events.EventEmitter();
|
||||
|
||||
class Publisher {
|
||||
emitter: any;
|
||||
@@ -25,7 +25,7 @@ class Subscriber extends events.EventEmitter {
|
||||
}
|
||||
|
||||
subscribe(channel: string): void {
|
||||
let handler = (message) => {
|
||||
const handler = (message) => {
|
||||
this.emit('message', channel, message);
|
||||
}
|
||||
this.subscriptions.set(channel, handler);
|
||||
@@ -49,7 +49,7 @@ function createSubscriber(): any {
|
||||
return new Subscriber(emitter);
|
||||
}
|
||||
|
||||
let EventEmitterPubSub = {
|
||||
const EventEmitterPubSub = {
|
||||
createPublisher,
|
||||
createSubscriber
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// @flow
|
||||
/*eslint no-unused-vars: "off"*/
|
||||
// Push Adapter
|
||||
//
|
||||
@@ -11,13 +12,15 @@
|
||||
// android push and APNS for ios push.
|
||||
|
||||
export class PushAdapter {
|
||||
send(devices, installations, pushStatus) { }
|
||||
send(body: any, installations: any[], pushStatus: any): ?Promise<*> {}
|
||||
|
||||
/**
|
||||
* Get an array of valid push types.
|
||||
* @returns {Array} An array of valid push types
|
||||
*/
|
||||
getValidPushTypes() {}
|
||||
getValidPushTypes(): string[] {
|
||||
return []
|
||||
}
|
||||
}
|
||||
|
||||
export default PushAdapter;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
let mongodb = require('mongodb');
|
||||
let Collection = mongodb.Collection;
|
||||
const mongodb = require('mongodb');
|
||||
const Collection = mongodb.Collection;
|
||||
|
||||
export default class MongoCollection {
|
||||
_mongoCollection:Collection;
|
||||
@@ -21,7 +21,7 @@ export default class MongoCollection {
|
||||
throw error;
|
||||
}
|
||||
// Figure out what key needs an index
|
||||
let key = error.message.match(/field=([A-Za-z_0-9]+) /)[1];
|
||||
const key = error.message.match(/field=([A-Za-z_0-9]+) /)[1];
|
||||
if (!key) {
|
||||
throw error;
|
||||
}
|
||||
@@ -50,7 +50,7 @@ export default class MongoCollection {
|
||||
}
|
||||
|
||||
count(query, { skip, limit, sort, maxTimeMS } = {}) {
|
||||
let countOperation = this._mongoCollection.count(query, { skip, limit, sort, maxTimeMS });
|
||||
const countOperation = this._mongoCollection.count(query, { skip, limit, sort, maxTimeMS });
|
||||
|
||||
return countOperation;
|
||||
}
|
||||
|
||||
@@ -73,7 +73,7 @@ function mongoSchemaToParseSchema(mongoSchema) {
|
||||
}
|
||||
|
||||
function _mongoSchemaQueryFromNameQuery(name: string, query) {
|
||||
let object = { _id: name };
|
||||
const object = { _id: name };
|
||||
if (query) {
|
||||
Object.keys(query).forEach(key => {
|
||||
object[key] = query[key];
|
||||
@@ -83,7 +83,6 @@ function _mongoSchemaQueryFromNameQuery(name: string, query) {
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Returns a type suitable for inserting into mongo _SCHEMA collection.
|
||||
// Does no validation. That is expected to be done in Parse Server.
|
||||
function parseFieldTypeToMongoFieldType({ type, targetClass }) {
|
||||
|
||||
@@ -15,8 +15,8 @@ import Parse from 'parse/node';
|
||||
import _ from 'lodash';
|
||||
import defaults from '../../../defaults';
|
||||
|
||||
let mongodb = require('mongodb');
|
||||
let MongoClient = mongodb.MongoClient;
|
||||
const mongodb = require('mongodb');
|
||||
const MongoClient = mongodb.MongoClient;
|
||||
|
||||
const MongoSchemaCollectionName = '_SCHEMA';
|
||||
|
||||
@@ -53,14 +53,14 @@ const convertParseSchemaToMongoSchema = ({...schema}) => {
|
||||
// Returns { code, error } if invalid, or { result }, an object
|
||||
// suitable for inserting into _SCHEMA collection, otherwise.
|
||||
const mongoSchemaFromFieldsAndClassNameAndCLP = (fields, className, classLevelPermissions) => {
|
||||
let mongoObject = {
|
||||
const mongoObject = {
|
||||
_id: className,
|
||||
objectId: 'string',
|
||||
updatedAt: 'string',
|
||||
createdAt: 'string'
|
||||
};
|
||||
|
||||
for (let fieldName in fields) {
|
||||
for (const fieldName in fields) {
|
||||
mongoObject[fieldName] = MongoSchemaCollection.parseFieldTypeToMongoFieldType(fields[fieldName]);
|
||||
}
|
||||
|
||||
@@ -157,7 +157,7 @@ export class MongoStorageAdapter {
|
||||
|
||||
createClass(className, schema) {
|
||||
schema = convertParseSchemaToMongoSchema(schema);
|
||||
let mongoObject = mongoSchemaFromFieldsAndClassNameAndCLP(schema.fields, className, schema.classLevelPermissions);
|
||||
const mongoObject = mongoSchemaFromFieldsAndClassNameAndCLP(schema.fields, className, schema.classLevelPermissions);
|
||||
mongoObject._id = className;
|
||||
return this._schemaCollection()
|
||||
.then(schemaCollection => schemaCollection._collection.insertOne(mongoObject))
|
||||
@@ -282,7 +282,7 @@ export class MongoStorageAdapter {
|
||||
schema = convertParseSchemaToMongoSchema(schema);
|
||||
return this._adaptiveCollection(className)
|
||||
.then(collection => {
|
||||
let mongoWhere = transformWhere(className, query, schema);
|
||||
const mongoWhere = transformWhere(className, query, schema);
|
||||
return collection.deleteMany(mongoWhere)
|
||||
})
|
||||
.then(({ result }) => {
|
||||
@@ -327,9 +327,9 @@ export class MongoStorageAdapter {
|
||||
// Executes a find. Accepts: className, query in Parse format, and { skip, limit, sort }.
|
||||
find(className, schema, query, { skip, limit, sort, keys }) {
|
||||
schema = convertParseSchemaToMongoSchema(schema);
|
||||
let mongoWhere = transformWhere(className, query, schema);
|
||||
let mongoSort = _.mapKeys(sort, (value, fieldName) => transformKey(className, fieldName, schema));
|
||||
let mongoKeys = _.reduce(keys, (memo, key) => {
|
||||
const mongoWhere = transformWhere(className, query, schema);
|
||||
const mongoSort = _.mapKeys(sort, (value, fieldName) => transformKey(className, fieldName, schema));
|
||||
const mongoKeys = _.reduce(keys, (memo, key) => {
|
||||
memo[transformKey(className, key, schema)] = 1;
|
||||
return memo;
|
||||
}, {});
|
||||
@@ -351,8 +351,8 @@ export class MongoStorageAdapter {
|
||||
// which is why we use sparse indexes.
|
||||
ensureUniqueness(className, schema, fieldNames) {
|
||||
schema = convertParseSchemaToMongoSchema(schema);
|
||||
let indexCreationRequest = {};
|
||||
let mongoFieldNames = fieldNames.map(fieldName => transformKey(className, fieldName, schema));
|
||||
const indexCreationRequest = {};
|
||||
const mongoFieldNames = fieldNames.map(fieldName => transformKey(className, fieldName, schema));
|
||||
mongoFieldNames.forEach(fieldName => {
|
||||
indexCreationRequest[fieldName] = 1;
|
||||
});
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user