Merge branch 'release-2.3' into hot-code-push-skelet-minimal

This commit is contained in:
Jan Dvorak
2021-06-11 22:11:46 +02:00
233 changed files with 2406 additions and 2557 deletions

View File

@@ -111,8 +111,8 @@ jobs:
command: (git submodule sync && git submodule update --init --recursive) || (rm -fr .git/config .git/modules && git submodule deinit -f . && git submodule update --init --recursive)
- restore_cache:
keys:
- v1-dev-bundle-cache-{{ checksum "meteor" }}
- v1-dev-bundle-cache-
- v3-dev-bundle-cache-{{ checksum "meteor" }}
- v3-dev-bundle-cache-
- run:
name: Combine NPM Shrinkwrap Files
command: |
@@ -120,21 +120,21 @@ jobs:
for d in packages/*/.npm/plugin/*; do cat $d/npm-shrinkwrap.json >> shrinkwraps.txt; done
- restore_cache:
keys:
- package-npm-deps-cache-group1-v1-{{ checksum "shrinkwraps.txt" }}
- package-npm-deps-cache-group1-v1-
- package-npm-deps-cache-group1-v3-{{ checksum "shrinkwraps.txt" }}
- package-npm-deps-cache-group1-v3-
- restore_cache:
keys:
- package-npm-deps-cache-group2-v3-{{ checksum "shrinkwraps.txt" }}
- package-npm-deps-cache-group2-v3-
- package-npm-deps-cache-group2-v5-{{ checksum "shrinkwraps.txt" }}
- package-npm-deps-cache-group2-v5-
- restore_cache:
keys:
- v5-other-deps-cache-{{ .Branch }}-{{ checksum "meteor" }}-{{ .Revision }}
- v5-other-deps-cache-{{ .Branch }}-{{ checksum "meteor" }}-
- v5-other-deps-cache-{{ .Branch }}-
- v7-other-deps-cache-{{ .Branch }}-{{ checksum "meteor" }}-{{ .Revision }}
- v7-other-deps-cache-{{ .Branch }}-{{ checksum "meteor" }}-
- v7-other-deps-cache-{{ .Branch }}-
- restore_cache:
keys:
- v1-test-groups-{{ .Branch }}
- v1-test-groups-
- v4-test-groups-{{ .Branch }}
- v4-test-groups-
- run:
name: Create Test Results Directory
command: |
@@ -149,8 +149,9 @@ jobs:
command: |
eval $PRE_TEST_COMMANDS;
pushd tools
npm install @types/node --save-dev
# Ensure that meteor/tools has no TypeScript errors.
../meteor npx tsc --noEmit
../meteor npx tsc --noEmit --skipLibCheck
popd
./meteor --get-ready
# shouldn't take longer than 60 minutes
@@ -706,14 +707,14 @@ jobs:
- ./tmp/test-groups
when: on_success
- save_cache:
key: v1-dev-bundle-cache-{{ checksum "meteor" }}
key: v3-dev-bundle-cache-{{ checksum "meteor" }}
paths:
- "dev_bundle"
# The package npm dependencies are split into two caches to avoid an AWS
# `MetadataTooLarge` error that consistently appears if we put all of
# these folders in the same cache
- save_cache:
key: package-npm-deps-cache-group1-v1-{{ checksum "shrinkwraps.txt" }}
key: package-npm-deps-cache-group1-v3-{{ checksum "shrinkwraps.txt" }}
paths:
- packages/meteor/.npm/package/node_modules
- packages/modules-runtime/.npm/package/node_modules
@@ -729,7 +730,7 @@ jobs:
- packages/package-version-parser/.npm/package/node_modules
- packages/boilerplate-generator/.npm/package/node_modules
- save_cache:
key: package-npm-deps-cache-group2-v3-{{ checksum "shrinkwraps.txt" }}
key: package-npm-deps-cache-group2-v5-{{ checksum "shrinkwraps.txt" }}
paths:
- packages/xmlbuilder/.npm/package/node_modules
- packages/logging/.npm/package/node_modules
@@ -756,7 +757,7 @@ jobs:
- packages/fetch/.npm/package/node_modules
- packages/non-core/mongo-decimal/.npm/package/node_modules
- save_cache:
key: v5-other-deps-cache-{{ .Branch }}-{{ checksum "meteor" }}-{{ .Revision }}
key: v7-other-deps-cache-{{ .Branch }}-{{ checksum "meteor" }}-{{ .Revision }}
paths:
- ".babel-cache"
- ".meteor"

1
.gitignore vendored
View File

@@ -24,6 +24,7 @@ TAGS
npm-debug.log
universe
.babel-cache
.reify-cache
mongo-test-output
# core packages shouldn't have .versions files

View File

@@ -24,7 +24,7 @@ can run Meteor directly from a Git checkout using these steps:
>
> $ git submodule update --init --recursive
0. **Run a Meteor command to install dependencies**
2. **Run a Meteor command to install dependencies**
> If you did not compile dependencies above, this will also download the binaries.
@@ -33,7 +33,7 @@ can run Meteor directly from a Git checkout using these steps:
$ ./meteor --help
```
0. **Ready to Go!**
3. **Ready to Go!**
Your local Meteor checkout is now ready to use! You can use this `./meteor`
anywhere you would normally call the system `meteor`. For example,:

View File

@@ -1,24 +1,167 @@
## v2.3.0, UNRELEASED
## v2.3, UNRELEASED
#### Highlights
* Node.js update to 14.17.0 from 12.22.1 🎉
* Typescript update to [4.3.2](https://devblogs.microsoft.com/typescript/announcing-typescript-4-3/)
* Packages had their backward compatibility to before Meteor 1.0 removed. See bellow for more details.
### Summary of breaking changes
- As Node.js version was upgraded to a new major version we recommend that you review if your npm dependencies are compatible with Node.js 14.
- If we receive reports from breaking changes we are going to list them here but so far we are not aware of any.
- We recommend that you read Node.js [release notes](https://nodejs.org/en/blog/release/v14.0.0/) though.
- Accounts have undergone some major changes. See bellow for more details.
- All official packages that have been deprecated have now the deprecated flag and will inform you about that if you install or update them.
### Migration steps
- As Node.js version was upgraded we recommend that you remove your `node_modules` folder (`rm -rf node_modules`) and run `meteor reset` to be sure you compile all the binary dependencies again using the new Node.js version.
- Maybe you also want to recreate your lock file.
#### Meteor Version Release
* `meteor-tool@2.3`
- Node.js update to 14.17.0 from 12.22.1 🎉
- This is a major upgrade in Node.js. See the [release notes](https://nodejs.org/en/blog/release/v14.0.0/) for more details.
- `npm` update to 6.14.13.
- `fibers` has been updated to v5.0.0.
- `promise` has been updated to v8.1.0.
- `underscore` has been updated to v1.11.0.
- `node-gyp` has been updated to v8.0.0.
- `node-pre-gyp` has been updated to v0.15.0.
- `@babel/runtime` has been updated to v7.14.0.
- `request` has been updated to v2.88.2.
- `uuid` has been updated to v3.4.0.
- `graceful-fs` has been updated to v4.2.6.
- `tar` has been updated to v2.2.2.
- `sqlite3` has been updated to v5.0.2.
- `http-proxy` has been updated to v1.18.1.
- `wordwrap` has been updated to v1.0.0.
- `moment` has been updated to v2.29.1.
- `glob` has been updated to v7.1.6.
- `split2` has been updated to v3.2.2.
- `optimism` has been updated to v0.12.2.
- `@wry/context` has been updated to v0.5.2.
- `lru-cache` has been updated to v4.1.5.
- `anser` has been updated to v2.0.1.
- `xmlbuilder2` has been updated to v1.8.1.
- `ws` has been updated to v7.4.5.
- `underscore` has been updated to v1.13.1
- Reduced time spent by server (re)start in development by adding a cache for Reify. This optimization can be enabled in production by setting the `METEOR_REIFY_CACHE_DIR` environment variable [PR](https://github.com/meteor/meteor/pull/11400).
- New flag `--platforms` has been added to the `build` command to specify the platform you want to build for. `meteor build . --platforms=android`. This is useful for example when you are not using a MacOS and you want to build your app only for Android. Also to save time on CI not building all the platforms all the time. See [PR](https://github.com/meteor/meteor/pull/11437) for details.
- The undocumented environment variable `DDP_DEFAULT_CONNECTION_URL` behavior has changed. Setting `DDP_DEFAULT_CONNECTION_URL` when running the server (development: `meteor run` or production: `node main.js`) sets the default DDP server value for meteor. But this did not work for `cordova` apps. Now you can define the `cordova` app default DDP server value by setting `DDP_DEFAULT_CONNECTION_URL` when building (`meteor build`).
- New env variable `METEOR_TOOL_ENABLE_REIFY_RUNTIME_CACHE` to improve runtime performance on restarts.
- New flag `--platforms` has been added to the `build` command to specify the platform you want to build for. `meteor build . --platforms=android`.
- Skeletons dependencies updated to latest version
* `launch-screen@1.3.0`
- Removes LaunchScreen from web clients.
* `meteor-babel@7.11.0 (@meteorjs/babel)`
- Fixes for Samsung Internet v6.2+ to be considered modern browser and addition of [logical assingment operators](https://github.com/tc39/proposal-logical-assignment) via `babel-presets-meteor`.
- This package was renamed to `@meteorjs/babel`.
* `hot-module-replacement@0.3.0`
- Fixes various HMR bugs and edge cases see [PR for more](https://github.com/meteor/meteor/pull/11405).
* `email@2.1.0`
- Updates `nodemailer` to `6.6.0` and it now adds `charset=utf-8` to `text/plain` messages by default.
* `server-render@0.4.0`
- Updated npm dependencies
### Breaking changes
* Removed deprecated `mobile-port` flag
* Removed deprecated `raw` name from `isobuild`
* Removed deprecated package API method names `Package.on_use`, `Package.on_test`, `Package._transitional_registerBuildPlugin` and `api.add_files`, if you haven't till now, please use the current camel case versions
* `accounts-base@2.0.0`
- Deprecated backward compatibility function `logoutOtherClients` has been removed
* `accounts-password@2.0.0`
- Deprecated backward compatibility functionality for `SRP` passwords from pre-Meteor 1.0 days
- Enroll account workflow has been separated from reset password workflow (the enrollment token records are now stored in a separate db field `services.password.enroll`).
* `ddp-client@2.5.0`
- Removed backward compatibility method names for Meteor before 1.0
* `ddp-server@2.4.0`
- Removed backward compatibility method names for Meteor before 1.0
- Added support for this.unblock() in Meteor.publish() context
- Add support in `Meteor.publish()` for async functions
* `meteor-base@2.0.0`
- Removed `livedata` dependency which was there for packages build for 0.9.0
* `minimongo@1.7.0`
- Removed the `rewind` method that was noop for compatibility with Meteor 0.8.1
* `mongo@1.12.0`
- Removed the `rewind` method that was noop for compatibility with Meteor 0.8.1
* `oauth@2.0.0`
- Removed `OAuth.initiateLogin` and other functionality like the addition of `?close` in return URI for deprecated OAuth flow pre Meteor 1.0
* `markdown@2.0.0`
- Use lazy imports to prevent it from being added to the initial bundle
- Added deprecation flag
* `http@2.0.0`
- Internally http has been replaced by [fetch](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API), should still work as previous version, but edge cases might be different. This is to aid you in transition to fetch.
* `socket-stream-client@0.4.0`
- Remove IE8 checks
#### Independent Releases
* Updated `ddp-server@2.3.3` and `socket-stream-client@0.3.2` dependencies which removes Node's HTTP deprecation warning.
* `ddp-server@2.3.3`
- Updates dependencies which removes Node's HTTP deprecation warning.
* `socket-stream-client@0.3.2`
- Updates dependencies which removes Node's HTTP deprecation warning.
* Released `ddp-client@2.4.1` re-ordering fields in DDP message for better client readability.
* `ddp-client@2.4.1`
- Re-ordering fields in DDP message for better client readability.
* Released `mongo@1.11.1` fixing a `Timestamp.ONE is undefined` bug.
* `mongo@1.11.1`
- Fixes a `Timestamp.ONE is undefined` bug.
* Released `mongo-id@1.0.8` removing unused dependency `id-map`.
* `mongo-id@1.0.8`
- Removes unused dependency `id-map`.
* Released `dev-error-overlay@0.1.1` fixing sometimes page content being on top of error overlay
* `accounts-server@1.7.1`
- To better test password format & limit password to 256 characters, you can change this limit by setting `Meteor.settings.packages.accounts.passwordMaxLength`.
* Released `id-map@1.1.1` removing unused dependencies and modernizing the code
* `static-html@1.3.1`
- Removes `underscore` dependency.
* `dev-error-overlay@0.1.1`
- Fixes sometimes page content being on top of error overlay.
* `id-map@1.1.1`
- Removes unused dependencies and modernizing the code.
* `http@1.4.4`
- Used the new deprecation package flag instead of loud console warning.
* `logic-solver@2.0.8`
- Fixed `package.js` to use current `api` method calls.
* `socket-stream-client@0.3.3`
- Update `faye-websocket` dependency to v0.11.4.
* `jshint@1.1.8`
- The package has been deprecated.
* `npm-bcrypt@0.9.4`
- The package has been deprecated.
## v2.2, 2021-04-15
@@ -112,7 +255,7 @@
* `meteor-tool@2.1`
- Node.js security [update](https://nodejs.org/en/blog/vulnerability/february-2021-security-releases/) to 12.21.0
- `meteor create my-app --plan professional` new flag `plan` to enable you to choose a plan from the deploy command.
### Breaking changes
* N/A
@@ -128,10 +271,10 @@
#### Highlights
- Free deploy on [Cloud](https://www.meteor.com/cloud): Deploy for free to Cloud with one command: `meteor deploy myapp.meteorapp.com --free`. ([docs](https://docs.meteor.com/commandline.html#meteordeploy))
- Deploy including MongoDB on [Cloud](https://www.meteor.com/cloud): Deploy including MongoDB in a shared instance for free to Cloud with one command: `meteor deploy myapp.meteorapp.com --free --mongo`. ([docs](https://docs.meteor.com/commandline.html#meteordeploy))
- Hot Module Replacement (HMR): Updates the javascript modules in a running app that were modified during a rebuild. Reduces the feedback cycle while developing so you can view and test changes quicker (it even updates the app before the build has finished). Enabled by adding the `hot-module-replacement` package to an app. React components are automatically updated by default using React Fast Refresh. Integrations with other libraries and view layers can be provided by third party packages. Support for Blaze is coming soon. This first version supports app code in the modern web architecture. ([docs](https://guide.meteor.com/build-tool.html#hot-module-replacement)) [#11117](https://github.com/meteor/meteor/pull/11117)
@@ -150,12 +293,12 @@
* `hot-module-replacement@1.0.0`
- New package that enables Hot Module Replacement for the Meteor app and provides an API to configure how updates are applied. HMR reduces the feedback cycle while developing by updating modified javascript modules within the running application. ([docs](https://docs.meteor.com/packages/hot-module-replacement.html)) [#11117](https://github.com/meteor/meteor/pull/11117)
- These packages have been updated to support HMR: `autoupdate@1.7.0`, `babel-compiler@7.6.0`, `ddp-client@2.4.0`, `dynamic-import@0.6.0`, `ecmascript@0.15.0`, `modules@0.16.0`, `modules-runtime-hot@0.13.0`, `standard-minifier-css@1.7.2`, `webapp@1.10.0`, `webapp-hashing@1.1.0`
- These packages have been updated to support HMR: `autoupdate@1.7.0`, `babel-compiler@7.6.0`, `ddp-client@2.4.0`, `dynamic-import@0.6.0`, `ecmascript@0.15.0`, `modules@0.16.0`, `modules-runtime-hot@0.13.0`, `standard-minifier-css@1.7.2`, `webapp@1.10.0`, `webapp-hashing@1.1.0`
* `react-fast-refresh@0.1.0`
- New package that updates React components using HMR. This is enabled by default in apps that have HMR enabled and use a supported React version. ([docs](https://atmospherejs.com/meteor/react-fast-refresh)) [#11117](https://github.com/meteor/meteor/pull/11117)
* `dev-error-overlay@0.1.0`
- New package that allows you to see build errors and server crashes in your browser during development. Requires the app to have HMR enabled. [#11117](https://github.com/meteor/meteor/pull/11117)
@@ -163,7 +306,7 @@
* `accounts-base@1.8.0` and `accounts-password@1.7.0`
- Extra parameters can now be added to reset password, verify e-mail and enroll account links that are generated for account e-mails. By default, these are added as search parameters to the generated url. You can pass them as an object in the appropriate functions. E.g. `Accounts.sendEnrollmentEmail(userId, email, null, extraParams);`. [#11288](https://github.com/meteor/meteor/pull/11288)
* `logging@1.2.0`
- Updates dependencies and make debug available for use in non production environments. [#11068](https://github.com/meteor/meteor/pull/11068)
@@ -172,7 +315,7 @@
* `react-meteor-data@2.2.0`
- Fix issue with useTracker and Subscriptions when using deps. [#306](https://github.com/meteor/react-packages/pull/306)
- Remove version constraint on core TypeScript package [#308](https://github.com/meteor/react-packages/pull/308)
* `http`
- It has been deprecated. [#11068](https://github.com/meteor/meteor/pull/11068)
@@ -208,10 +351,10 @@ N/A
* `dynamic-import@0.5.5`
- Fixes problem on IE because of modern syntax (arrow function).
* `meteor-babel@7.10.6`
- Allows to disable sourceMap generation [#36](https://github.com/meteor/babel/pull/36)
* `babel-compiler@7.5.5`
- Allows to disable sourceMap generation [#36](https://github.com/meteor/babel/pull/36)
@@ -247,7 +390,7 @@ N/A
- adds new options for `meteor list` command (TODO pending link to updated doc). [#11165](https://github.com/meteor/meteor/pull/11165)
- supports Cordova add plugin command working again with plugin id or plugin name in the git URL as it was before Meteor 1.11. [#11202](https://github.com/meteor/meteor/pull/11202)
- avoids MiTM by downloading through https. [#11188](https://github.com/meteor/meteor/pull/11188)
* `meteor-babel@7.10.5`
- updates TypeScript to 4.1.2 and enables decorators and metadata reflection. [#11225](https://github.com/meteor/meteor/pull/11225) and [#11255](https://github.com/meteor/meteor/pull/11255)

2
meteor
View File

@@ -1,6 +1,6 @@
#!/usr/bin/env bash
BUNDLE_VERSION=12.22.1.2
BUNDLE_VERSION=14.17.0.6
# OS Check. Put here because here is where we download the precompiled
# bundles that are arch specific.

View File

@@ -569,62 +569,6 @@ export class AccountsServer extends AccountsCommon {
this.setUserId(null);
};
// Delete all the current user's tokens and close all open connections logged
// in as this user. Returns a fresh new login token that this client can
// use. Tests set Accounts._noConnectionCloseDelayForTest to delete tokens
// immediately instead of using a delay.
//
// XXX COMPAT WITH 0.7.2
// This single `logoutOtherClients` method has been replaced with two
// methods, one that you call to get a new token, and another that you
// call to remove all tokens except your own. The new design allows
// clients to know when other clients have actually been logged
// out. (The `logoutOtherClients` method guarantees the caller that
// the other clients will be logged out at some point, but makes no
// guarantees about when.) This method is left in for backwards
// compatibility, especially since application code might be calling
// this method directly.
//
// @returns {Object} Object with token and tokenExpires keys.
methods.logoutOtherClients = function () {
const user = accounts.users.findOne(this.userId, {
fields: {
"services.resume.loginTokens": true
}
});
if (user) {
// Save the current tokens in the database to be deleted in
// CONNECTION_CLOSE_DELAY_MS ms. This gives other connections in the
// caller's browser time to find the fresh token in localStorage. We save
// the tokens in the database in case we crash before actually deleting
// them.
const tokens = user.services.resume.loginTokens;
const newToken = accounts._generateStampedLoginToken();
accounts.users.update(this.userId, {
$set: {
"services.resume.loginTokensToDelete": tokens,
"services.resume.haveLoginTokensToDelete": true
},
$push: { "services.resume.loginTokens": accounts._hashStampedToken(newToken) }
});
Meteor.setTimeout(() => {
// The observe on Meteor.users will take care of closing the connections
// associated with `tokens`.
accounts._deleteSavedTokensForUser(this.userId, tokens);
}, accounts._noConnectionCloseDelayForTest ? 0 :
CONNECTION_CLOSE_DELAY_MS);
// We do not set the login token on this connection, but instead the
// observe closes the connection and the client will reconnect with the
// new token.
return {
token: newToken.token,
tokenExpires: accounts._tokenExpiration(newToken.when)
};
} else {
throw new Meteor.Error("You are not logged in.");
}
};
// Generates a new login token with the same expiration as the
// connection's current token and saves it to the database. Associates
// the connection with this new token and returns it. Throws an error
@@ -1029,7 +973,7 @@ export class AccountsServer extends AccountsCommon {
(new Date(new Date() - tokenLifetimeMs));
const tokenFilter = {
"services.password.reset.reason": "enroll"
"services.password.enroll.reason": "enroll"
};
expirePasswordToken(this, oldestValidDate, tokenFilter, userId);
@@ -1143,6 +1087,7 @@ export class AccountsServer extends AccountsCommon {
} catch (e) {
// XXX string parsing sucks, maybe
// https://jira.mongodb.org/browse/SERVER-3069 will get fixed one day
// https://jira.mongodb.org/browse/SERVER-4637
if (!e.errmsg) throw e;
if (e.errmsg.includes('emails.address'))
throw new Meteor.Error(403, "Email already exists.");
@@ -1461,20 +1406,42 @@ const expirePasswordToken = (
tokenFilter,
userId
) => {
// boolean value used to determine if this method was called from enroll account workflow
let isEnroll = false;
const userFilter = userId ? {_id: userId} : {};
const resetRangeOr = {
// check if this method was called from enroll account workflow
if(tokenFilter['services.password.enroll.reason']) {
isEnroll = true;
}
let resetRangeOr = {
$or: [
{ "services.password.reset.when": { $lt: oldestValidDate } },
{ "services.password.reset.when": { $lt: +oldestValidDate } }
]
};
if(isEnroll) {
resetRangeOr = {
$or: [
{ "services.password.enroll.when": { $lt: oldestValidDate } },
{ "services.password.enroll.when": { $lt: +oldestValidDate } }
]
};
}
const expireFilter = { $and: [tokenFilter, resetRangeOr] };
if(isEnroll) {
accounts.users.update({...userFilter, ...expireFilter}, {
$unset: {
"services.password.enroll": ""
}
}, { multi: true });
} else {
accounts.users.update({...userFilter, ...expireFilter}, {
$unset: {
"services.password.reset": ""
}
}, { multi: true });
}
accounts.users.update({...userFilter, ...expireFilter}, {
$unset: {
"services.password.reset": ""
}
}, { multi: true });
};
const setExpireTokensInterval = accounts => {

View File

@@ -1,6 +1,7 @@
import { URL } from 'meteor/url';
import { Meteor } from 'meteor/meteor';
import { Accounts } from 'meteor/accounts-base';
import { Random } from 'meteor/random';
Meteor.methods({
getCurrentLoginToken: function () {
@@ -111,6 +112,32 @@ Tinytest.add('accounts - updateOrCreateUserFromExternalService - Facebook', test
Meteor.users.remove(uid1);
});
Tinytest.add('accounts - updateOrCreateUserFromExternalService - Meteor Developer', test => {
const developerId = Random.id();
const uid1 = Accounts.updateOrCreateUserFromExternalService(
'meteor-developer',
{ id: developerId, username: 'meteor-developer' },
{ profile: { name: 'meteor-developer' } }
).id;
const users1 = Meteor.users.find({ 'services.meteor-developer.id': developerId }).fetch();
test.length(users1, 1);
test.equal(users1[0].profile.name, 'meteor-developer');
const uid2 = Accounts.updateOrCreateUserFromExternalService(
'meteor-developer',
{ id: developerId, username: 'meteor-developer' },
{ profile: { name: 'meteor-developer', username: 'developer' } }
).id;
test.equal(uid1, uid2);
const users2 = Meteor.users.find({ 'services.meteor-developer.id': developerId }).fetch();
test.length(users2, 1);
test.equal(users1[0].profile.name, 'meteor-developer');
test.equal(users1[0].profile.username, undefined);
// cleanup
Meteor.users.remove(uid1);
});
Tinytest.add('accounts - updateOrCreateUserFromExternalService - Weibo', test => {
const weiboId1 = Random.id();
const weiboId2 = Random.id();

View File

@@ -1,6 +1,6 @@
Package.describe({
summary: "A user account system",
version: "1.9.0",
version: "2.0.0-beta230.6",
});
Package.onUse(api => {

View File

@@ -1,6 +1,6 @@
Package.describe({
summary: "Login service for Facebook accounts",
version: "1.3.2",
version: "1.3.0-beta.2",
});
Package.onUse(api => {

View File

@@ -1,6 +1,6 @@
Package.describe({
summary: 'Login service for Github accounts',
version: '1.4.3',
version: '1.5.0-beta230.6',
});
Package.onUse(api => {

View File

@@ -1,6 +1,6 @@
Package.describe({
summary: "Login service for Google accounts",
version: "1.3.3",
version: "1.4.0-beta230.6",
});
Package.onUse(api => {

View File

@@ -1,6 +1,6 @@
Package.describe({
summary: 'Login service for Meetup accounts',
version: '1.4.2',
version: '1.5.0-beta230.6',
});
Package.onUse(api => {

View File

@@ -1,6 +1,6 @@
Package.describe({
summary: 'Login service for Meteor developer accounts',
version: '1.4.2',
version: '1.5.0-beta230.6',
});
Package.onUse(api => {

View File

@@ -1,6 +1,6 @@
Package.describe({
summary: "Common code for OAuth-based login services",
version: "1.2.0",
version: "1.3.0-beta230.6",
});
Package.onUse(api => {

View File

@@ -5,15 +5,17 @@ Package.describe({
// 2.2.x in the future. The version was also bumped to 2.0.0 temporarily
// during the Meteor 1.5.1 release process, so versions 2.0.0-beta.2
// through -beta.5 and -rc.0 have already been published.
version: "1.7.1"
version: "2.0.0-beta230.6"
});
Npm.depends({
'bcrypt': '5.0.1'
})
Package.onUse(api => {
api.use('npm-bcrypt', 'server');
api.use([
'accounts-base',
'srp',
'sha',
'ejson',
'ddp'
@@ -33,7 +35,7 @@ Package.onUse(api => {
});
Package.onTest(api => {
api.use(['accounts-password', 'tinytest', 'test-helpers', 'tracker',
api.use(['accounts-password', 'sha', 'tinytest', 'test-helpers', 'tracker',
'accounts-base', 'random', 'email', 'check', 'ddp', 'ecmascript']);
api.addFiles('password_tests_setup.js', 'server');
api.addFiles('password_tests.js', ['client', 'server']);

View File

@@ -43,27 +43,7 @@ Meteor.loginWithPassword = (selector, password, callback) => {
password: Accounts._hashPassword(password)
}],
userCallback: (error, result) => {
if (error && error.error === 400 &&
error.reason === 'old password format') {
// The "reason" string should match the error thrown in the
// password login handler in password_server.js.
// XXX COMPAT WITH 0.8.1.3
// If this user's last login was with a previous version of
// Meteor that used SRP, then the server throws this error to
// indicate that we should try again. The error includes the
// user's SRP identity. We provide a value derived from the
// identity and the password to prove to the server that we know
// the password without requiring a full SRP flow, as well as
// SHA256(password), which the server bcrypts and stores in
// place of the old SRP information for this user.
srpUpgradePath({
upgradeError: error,
userSelector: selector,
plaintextPassword: password
}, callback);
}
else if (error) {
if (error) {
reportError(error, callback);
} else {
callback && callback();
@@ -77,35 +57,6 @@ Accounts._hashPassword = password => ({
algorithm: "sha-256"
});
// XXX COMPAT WITH 0.8.1.3
// The server requested an upgrade from the old SRP password format,
// so supply the needed SRP identity to login. Options:
// - upgradeError: the error object that the server returned to tell
// us to upgrade from SRP to bcrypt.
// - userSelector: selector to retrieve the user object
// - plaintextPassword: the password as a string
const srpUpgradePath = (options, callback) => {
let details;
try {
details = EJSON.parse(options.upgradeError.details);
} catch (e) {}
if (!(details && details.format === 'srp')) {
reportError(
new Meteor.Error(400, "Password is old. Please reset your " +
"password."), callback);
} else {
Accounts.callLoginMethod({
methodArguments: [{
user: options.userSelector,
srp: SHA256(`${details.identity}:${options.plaintextPassword}`),
password: Accounts._hashPassword(options.plaintextPassword)
}],
userCallback: callback
});
}
};
// Attempt to log in as a new user.
/**
@@ -172,30 +123,10 @@ Accounts.changePassword = (oldPassword, newPassword, callback) => {
[oldPassword ? Accounts._hashPassword(oldPassword) : null,
Accounts._hashPassword(newPassword)],
(error, result) => {
if (error || !result) {
if (error && error.error === 400 &&
error.reason === 'old password format') {
// XXX COMPAT WITH 0.8.1.3
// The server is telling us to upgrade from SRP to bcrypt, as
// in Meteor.loginWithPassword.
srpUpgradePath({
upgradeError: error,
userSelector: { id: Meteor.userId() },
plaintextPassword: oldPassword
}, err => {
if (err) {
reportError(err, callback);
} else {
// Now that we've successfully migrated from srp to
// bcrypt, try changing the password again.
Accounts.changePassword(oldPassword, newPassword, callback);
}
});
} else {
// A normal error, not an error telling us to upgrade to bcrypt
reportError(
error || new Error("No result from changePassword."), callback);
}
if (error || !result) {
// A normal error, not an error telling us to upgrade to bcrypt
reportError(
error || new Error("No result from changePassword."), callback);
} else {
callback && callback();
}

View File

@@ -1,6 +1,5 @@
/// BCRYPT
import bcrypt from 'bcrypt'
const bcrypt = NpmModuleBcrypt;
const bcryptHash = Meteor.wrapAsync(bcrypt.hash);
const bcryptCompare = Meteor.wrapAsync(bcrypt.compare);
@@ -8,9 +7,7 @@ const bcryptCompare = Meteor.wrapAsync(bcrypt.compare);
const getUserById = (id, options) => Meteor.users.findOne(id, Accounts._addDefaultFieldSelector(options));
// User records have a 'services.password.bcrypt' field on them to hold
// their hashed passwords (unless they have a 'services.password.srp'
// field, in which case they will be upgraded to bcrypt the next time
// they log in).
// their hashed passwords.
//
// When the client sends a password to the server, it can either be a
// string (the plaintext password) or an object with keys 'digest' and
@@ -298,7 +295,7 @@ const passwordValidator = Match.OneOf(
// Note that neither password option is secure without SSL.
//
Accounts.registerLoginHandler("password", options => {
if (! options.password || options.srp)
if (!options.password)
return undefined; // don't handle
check(options, {
@@ -316,116 +313,16 @@ Accounts.registerLoginHandler("password", options => {
}
if (!user.services || !user.services.password ||
!(user.services.password.bcrypt || user.services.password.srp)) {
!user.services.password.bcrypt) {
handleError("User has no password set");
}
if (!user.services.password.bcrypt) {
if (typeof options.password === "string") {
// The client has presented a plaintext password, and the user is
// not upgraded to bcrypt yet. We don't attempt to tell the client
// to upgrade to bcrypt, because it might be a standalone DDP
// client doesn't know how to do such a thing.
const verifier = user.services.password.srp;
const newVerifier = SRP.generateVerifier(options.password, {
identity: verifier.identity, salt: verifier.salt});
if (verifier.verifier !== newVerifier.verifier) {
return {
userId: Accounts._options.ambiguousErrorMessages ? null : user._id,
error: handleError("Incorrect password", false)
};
}
return {userId: user._id};
} else {
// Tell the client to use the SRP upgrade process.
throw new Meteor.Error(400, "old password format", EJSON.stringify({
format: 'srp',
identity: user.services.password.srp.identity
}));
}
}
return checkPassword(
user,
options.password
);
});
// Handler to login using the SRP upgrade path. To use this login
// handler, the client must provide:
// - srp: H(identity + ":" + password)
// - password: a string or an object with properties 'digest' and 'algorithm'
//
// We use `options.srp` to verify that the client knows the correct
// password without doing a full SRP flow. Once we've checked that, we
// upgrade the user to bcrypt and remove the SRP information from the
// user document.
//
// The client ends up using this login handler after trying the normal
// login handler (above), which throws an error telling the client to
// try the SRP upgrade path.
//
// XXX COMPAT WITH 0.8.1.3
Accounts.registerLoginHandler("password", options => {
if (!options.srp || !options.password) {
return undefined; // don't handle
}
check(options, {
user: userQueryValidator,
srp: String,
password: passwordValidator
});
const user = Accounts._findUserByQuery(options.user, {fields: {
services: 1,
...Accounts._checkPasswordUserFields,
}});
if (!user) {
handleError("User not found");
}
// Check to see if another simultaneous login has already upgraded
// the user record to bcrypt.
if (user.services && user.services.password && user.services.password.bcrypt) {
return checkPassword(user, options.password);
}
if (!(user.services && user.services.password && user.services.password.srp)) {
handleError("User has no password set");
}
const v1 = user.services.password.srp.verifier;
const v2 = SRP.generateVerifier(
null,
{
hashedIdentityAndPassword: options.srp,
salt: user.services.password.srp.salt
}
).verifier;
if (v1 !== v2) {
return {
userId: Accounts._options.ambiguousErrorMessages ? null : user._id,
error: handleError("Incorrect password", false)
};
}
// Upgrade to bcrypt on successful login.
const salted = hashPassword(options.password);
Meteor.users.update(
user._id,
{
$unset: { 'services.password.srp': 1 },
$set: { 'services.password.bcrypt': salted }
}
);
return {userId: user._id};
});
///
/// CHANGING
///
@@ -471,18 +368,6 @@ Accounts.setUsername = (userId, newUsername) => {
// Let the user change their own password if they know the old
// password. `oldPassword` and `newPassword` should be objects with keys
// `digest` and `algorithm` (representing the SHA256 of the password).
//
// XXX COMPAT WITH 0.8.1.3
// Like the login method, if the user hasn't been upgraded from SRP to
// bcrypt yet, then this method will throw an 'old password format'
// error. The client should call the SRP upgrade login handler and then
// retry this method again.
//
// UNLIKE the login method, there is no way to avoid getting SRP upgrade
// errors thrown. The reasoning for this is that clients using this
// method directly will need to be updated anyway because we no longer
// support the SRP flow that they would have been doing to use this
// method previously.
Meteor.methods({changePassword: function (oldPassword, newPassword) {
check(oldPassword, passwordValidator);
check(newPassword, passwordValidator);
@@ -499,18 +384,10 @@ Meteor.methods({changePassword: function (oldPassword, newPassword) {
handleError("User not found");
}
if (!user.services || !user.services.password ||
(!user.services.password.bcrypt && !user.services.password.srp)) {
if (!user.services || !user.services.password || !user.services.password.bcrypt) {
handleError("User has no password set");
}
if (! user.services.password.bcrypt) {
throw new Meteor.Error(400, "old password format", EJSON.stringify({
format: 'srp',
identity: user.services.password.srp.identity
}));
}
const result = checkPassword(user, oldPassword);
if (result.error) {
throw result.error;
@@ -550,6 +427,9 @@ Meteor.methods({changePassword: function (oldPassword, newPassword) {
* @importFromPackage accounts-base
*/
Accounts.setPassword = (userId, newPlaintextPassword, options) => {
check(userId, String)
check(newPlaintextPassword, Match.Where(str => Match.test(str, String) && str.length <= Meteor.settings?.packages?.accounts?.passwordMaxLength || 256))
check(options, Match.Maybe({ logout: Boolean }))
options = { logout: true , ...options };
const user = getUserById(userId, {fields: {_id: 1}});
@@ -559,7 +439,6 @@ Accounts.setPassword = (userId, newPlaintextPassword, options) => {
const update = {
$unset: {
'services.password.srp': 1, // XXX COMPAT WITH 0.8.1.3
'services.password.reset': 1
},
$set: {'services.password.bcrypt': hashPassword(newPlaintextPassword)}
@@ -583,9 +462,10 @@ const pluckAddresses = (emails = []) => emails.map(email => email.address);
// Method called by a user to request a password reset email. This is
// the start of the reset process.
Meteor.methods({forgotPassword: options => {
check(options, {email: String});
check(options, {email: String})
const user = Accounts.findUserByEmail(options.email, { fields: { emails: 1 } });
const user = Accounts.findUserByEmail(options.email, {fields: {emails: 1}});
if (!user) {
handleError("User not found");
}
@@ -646,15 +526,27 @@ Accounts.generateResetToken = (userId, email, reason, extraTokenData) => {
if (extraTokenData) {
Object.assign(tokenRecord, extraTokenData);
}
// if this method is called from the enroll account work-flow then
// store the token record in 'services.password.enroll' db field
// else store the token record in in 'services.password.reset' db field
if(reason === 'enrollAccount') {
Meteor.users.update({_id: user._id}, {
$set : {
'services.password.enroll': tokenRecord
}
});
} else {
Meteor.users.update({_id: user._id}, {
$set : {
'services.password.reset': tokenRecord
}
});
}
Meteor.users.update({_id: user._id}, {$set: {
'services.password.reset': tokenRecord
}});
// before passing to template, update user object with new token
Meteor._ensure(user, 'services', 'password').reset = tokenRecord;
Meteor._ensure(user, 'services', 'password').enroll = tokenRecord;
return {email, user, token};
};
@@ -823,17 +715,38 @@ Meteor.methods({resetPassword: function (...args) {
check(token, String);
check(newPassword, passwordValidator);
const user = Meteor.users.findOne(
let user = Meteor.users.findOne(
{"services.password.reset.token": token},
{fields: {
services: 1,
emails: 1,
}}
);
let isEnroll = false;
// if token is in services.password.reset db field implies
// this method is was not called from enroll account workflow
// else this method is called from enroll account workflow
if(!user) {
user = Meteor.users.findOne(
{"services.password.enroll.token": token},
{fields: {
services: 1,
emails: 1,
}}
);
isEnroll = true;
}
if (!user) {
throw new Meteor.Error(403, "Token expired");
}
const { when, reason, email } = user.services.password.reset;
let tokenRecord = {};
if(isEnroll) {
tokenRecord = user.services.password.enroll;
} else {
tokenRecord = user.services.password.reset;
}
const { when, reason, email } = tokenRecord;
let tokenLifetimeMs = Accounts._getPasswordResetTokenLifetimeMs();
if (reason === "enroll") {
tokenLifetimeMs = Accounts._getPasswordEnrollTokenLifetimeMs();
@@ -847,7 +760,7 @@ Meteor.methods({resetPassword: function (...args) {
error: new Meteor.Error(403, "Token has invalid email address")
};
const hashed = hashPassword(newPassword);
const hashed = hashPassword(newPassword);
// NOTE: We're about to invalidate tokens on the user, who we might be
// logged in as. Make sure to avoid logging ourselves out if this
@@ -861,18 +774,31 @@ Meteor.methods({resetPassword: function (...args) {
try {
// Update the user record by:
// - Changing the password to the new one
// - Forgetting about the reset token that was just used
// - Forgetting about the reset token or enroll token that was just used
// - Verifying their email, since they got the password reset via email.
const affectedRecords = Meteor.users.update(
{
_id: user._id,
'emails.address': email,
'services.password.reset.token': token
},
{$set: {'services.password.bcrypt': hashed,
'emails.$.verified': true},
$unset: {'services.password.reset': 1,
'services.password.srp': 1}});
let affectedRecords = {};
// if reason is enroll then check services.password.enroll.token field for affected records
if(reason === 'enroll') {
affectedRecords = Meteor.users.update(
{
_id: user._id,
'emails.address': email,
'services.password.enroll.token': token
},
{$set: {'services.password.bcrypt': hashed,
'emails.$.verified': true},
$unset: {'services.password.enroll': 1 }});
} else {
affectedRecords = Meteor.users.update(
{
_id: user._id,
'emails.address': email,
'services.password.reset.token': token
},
{$set: {'services.password.bcrypt': hashed,
'emails.$.verified': true},
$unset: {'services.password.reset': 1 }});
}
if (affectedRecords !== 1)
return {
userId: user._id,
@@ -1236,3 +1162,5 @@ Meteor.users._ensureIndex('services.email.verificationTokens.token',
{ unique: true, sparse: true });
Meteor.users._ensureIndex('services.password.reset.token',
{ unique: true, sparse: true });
Meteor.users._ensureIndex('services.password.enroll.token',
{ unique: true, sparse: true });

View File

@@ -1,5 +1,12 @@
Accounts._connectionCloseDelayMsForTests = 1000;
function hashPassword(password) {
return {
digest: SHA256(password),
algorithm: "sha-256"
};
}
if (Meteor.isServer) {
Accounts.removeDefaultRateLimit();
@@ -63,7 +70,7 @@ if (Meteor.isClient) (() => {
}
const user = Meteor.user();
test.isTrue(user && user.emails.reduce(
(prev, email) => prev || email.address === someEmail,
(prev, email) => prev || email.address === someEmail,
false
));
});
@@ -72,15 +79,15 @@ if (Meteor.isClient) (() => {
test.equal(actualError && actualError.error, expectedError.error);
test.equal(actualError && actualError.reason, expectedError.reason);
});
const expectUserNotFound = (test, expect) =>
const expectUserNotFound = (test, expect) =>
expectError(new Meteor.Error(403, "User not found"), test, expect);
const waitForLoggedOutStep = (test, expect) => pollUntil(
expect,
() => Meteor.userId() === null,
10 * 1000,
expect,
() => Meteor.userId() === null,
10 * 1000,
100
);
const invalidateLoginsStep = (test, expect) =>
const invalidateLoginsStep = (test, expect) =>
Meteor.call("testInvalidateLogins", 'fail', expect(error => {
if (error) {
test.fail(error.message);
@@ -160,51 +167,6 @@ if (Meteor.isClient) (() => {
logoutStep
]);
testAsyncMulti("passwords - plain text passwords", [
function (test, expect) {
// setup
this.username = Random.id();
this.email = `${Random.id()}-intercept@example.com`;
this.password = 'password';
// create user with raw password (no API, need to invoke callLoginMethod
// directly)
Accounts.callLoginMethod({
methodName: 'createUser',
methodArguments: [{username: this.username, password: this.password}],
userCallback: loggedInAs(this.username, test, expect)
});
},
logoutStep,
// check can login normally with this password.
function(test, expect) {
Meteor.loginWithPassword({username: this.username}, this.password,
loggedInAs(this.username, test, expect));
},
logoutStep,
// plain text password. no API for this, have to invoke callLoginMethod
// directly.
function (test, expect) {
Accounts.callLoginMethod({
// wrong password
methodArguments: [{user: {username: this.username}, password: 'wrong'}],
userCallback: expect(function (error) {
test.isTrue(error);
test.isFalse(Meteor.user());
})});
},
function (test, expect) {
Accounts.callLoginMethod({
// right password
methodArguments: [{user: {username: this.username},
password: this.password}],
userCallback: loggedInAs(this.username, test, expect)
});
},
logoutStep
]);
testAsyncMulti("passwords - logging in with case insensitive username", [
createUserStep,
logoutStep,
@@ -467,7 +429,7 @@ if (Meteor.isClient) (() => {
// change password with blank new password
function (test, expect) {
test.throws(
() => Accounts.changePassword(this.password, ''),
() => Accounts.changePassword(this.password, ''),
/Password may not be empty/
);
},
@@ -513,13 +475,13 @@ if (Meteor.isClient) (() => {
function (test, expect) {
this.secondConn = DDP.connect(Meteor.absoluteUrl());
this.secondConn.call('login',
{ user: { username: this.username }, password: this.password },
{ user: { username: this.username }, password: hashPassword(this.password) },
expect((err, result) => {
test.isFalse(err);
this.secondConn.setUserId(result.id);
test.isTrue(this.secondConn.userId());
this.secondConn.onReconnect = () =>
this.secondConn.onReconnect = () =>
this.secondConn.apply(
'login',
[{ resume: result.token }],
@@ -531,8 +493,8 @@ if (Meteor.isClient) (() => {
},
function (test, expect) {
Accounts.changePassword(
this.password,
this.password2,
this.password,
this.password2,
expect(err => test.isFalse(err))
);
},
@@ -540,9 +502,9 @@ if (Meteor.isClient) (() => {
// connection gets logged out.
function (test, expect) {
pollUntil(
expect,
() => this.secondConn.userId() === null,
10 * 1000,
expect,
() => this.secondConn.userId() === null,
10 * 1000,
100
);
}
@@ -557,14 +519,14 @@ if (Meteor.isClient) (() => {
// forgotPassword called on client with blank email
function (test, expect) {
Accounts.forgotPassword(
{ email: this.email },
{ email: this.email },
expect(error => test.isTrue(error))
);
},
// forgotPassword called on client with blank email and no callback.
function (test, expect) {
test.throws(
() => Accounts.forgotPassword({ email: this.email }),
() => Accounts.forgotPassword({ email: this.email }),
/Must pass options\.email/
);
},
@@ -607,14 +569,14 @@ if (Meteor.isClient) (() => {
// verifyEmail called on client with blank token
function (test, expect) {
Accounts.verifyEmail(
this.token,
this.token,
expect(error => test.isTrue(error))
);
},
// verifyEmail called on client with blank token and no callback.
function (test, expect) {
test.throws(
() => Accounts.verifyEmail(this.token),
() => Accounts.verifyEmail(this.token),
/Need to pass token/
);
},
@@ -629,8 +591,8 @@ if (Meteor.isClient) (() => {
// resetPassword called on client with blank token
function (test, expect) {
Accounts.resetPassword(
this.token,
this.newPassword,
this.token,
this.newPassword,
expect(error => test.isTrue(error))
);
},
@@ -642,8 +604,8 @@ if (Meteor.isClient) (() => {
// resetPassword called on client with blank password
function (test, expect) {
Accounts.resetPassword(
this.token,
this.newPassword,
this.token,
this.newPassword,
expect(error => test.isTrue(error))
);
},
@@ -882,10 +844,10 @@ if (Meteor.isClient) (() => {
const secondConn = DDP.connect(Meteor.absoluteUrl());
let token;
const expectSecondConnLoggedOut =
const expectSecondConnLoggedOut =
expect((err, result) => test.isTrue(err));
const expectAccountsConnLoggedIn =
const expectAccountsConnLoggedIn =
expect((err, result) => test.isFalse(err));
const expectSecondConnLoggedIn = expect((err, result) => {
@@ -914,78 +876,6 @@ if (Meteor.isClient) (() => {
);
},
logoutStep,
// The tests below this point are for the deprecated
// `logoutOtherClients` method.
function (test, expect) {
// Test that Meteor.logoutOtherClients logs out a second authenticated
// connection while leaving Accounts.connection logged in.
let token;
this.secondConn = DDP.connect(Meteor.absoluteUrl());
const expectLoginError = expect(err => test.isTrue(err));
const expectValidToken = expect((err, result) => {
test.isFalse(err);
test.isTrue(result);
this.tokenFromLogoutOthers = result.token;
});
const expectSecondConnLoggedIn = expect((err, result) => {
test.equal(result.token, token);
test.isFalse(err);
// This test will fail if an unrelated reconnect triggers before the
// connection is logged out. In general our tests aren't resilient to
// mid-test reconnects.
this.secondConn.onReconnect = () => {
this.secondConn.call("login", { resume: token }, expectLoginError);
};
Accounts.connection.call("logoutOtherClients", expectValidToken);
});
Meteor.loginWithPassword(this.username, this.password, expect(err => {
test.isFalse(err);
token = Accounts._storedLoginToken();
this.beforeLogoutOthersToken = token;
test.isTrue(token);
this.secondConn.call("login", { resume: token },
expectSecondConnLoggedIn);
}));
},
// Test that logoutOtherClients logged out Accounts.connection and that the
// previous token is no longer valid.
waitForLoggedOutStep,
function (test, expect) {
const token = Accounts._storedLoginToken();
test.isFalse(token);
this.secondConn.close();
Meteor.loginWithToken(
this.beforeLogoutOthersToken,
expect(err => {
test.isTrue(err);
test.isFalse(Meteor.userId());
})
);
},
// Test that logoutOtherClients returned a new token that we can use to
// log in.
function (test, expect) {
Meteor.loginWithToken(
this.tokenFromLogoutOthers,
expect(err => {
test.isFalse(err);
test.isTrue(Meteor.userId());
})
);
},
logoutStep,
function (test, expect) {
// Test that deleting a user logs out that user's connections.
Meteor.loginWithPassword(this.username, this.password, expect(err => {
test.isFalse(err);
Accounts.connection.call("removeUser", this.username);
}));
},
waitForLoggedOutStep
]);
testAsyncMulti("passwords - validateLoginAttempt", [
@@ -1208,99 +1098,6 @@ if (Meteor.isClient) (() => {
expect(() => ({}))();
}
]);
testAsyncMulti("passwords - srp to bcrypt upgrade", [
logoutStep,
// Create user with old SRP credentials in the database.
function (test, expect) {
Meteor.call("testCreateSRPUser", expect((error, result) => {
test.isFalse(error);
this.username = result;
}));
},
// We are able to login with the old style credentials in the database.
function (test, expect) {
Meteor.loginWithPassword(
this.username,
'abcdef',
expect(error => test.isFalse(error))
);
},
function (test, expect) {
Meteor.call(
"testSRPUpgrade",
this.username,
expect(error => test.isFalse(error))
);
},
logoutStep,
// After the upgrade to bcrypt we're still able to login.
function (test, expect) {
Meteor.loginWithPassword(
this.username,
'abcdef',
expect(error => test.isFalse(error))
);
},
logoutStep,
function (test, expect) {
Meteor.call(
"removeUser",
this.username,
expect(error => test.isFalse(error))
);
}
]);
testAsyncMulti("passwords - srp to bcrypt upgrade via password change", [
logoutStep,
// Create user with old SRP credentials in the database.
function (test, expect) {
Meteor.call("testCreateSRPUser", expect((error, result) => {
test.isFalse(error);
this.username = result;
}));
},
// Log in with the plaintext password handler, which should NOT upgrade us to bcrypt.
function (test, expect) {
Accounts.callLoginMethod({
methodName: "login",
methodArguments: [ { user: { username: this.username }, password: "abcdef" } ],
userCallback: expect(err => test.isFalse(err))
});
},
function (test, expect) {
Meteor.call(
"testNoSRPUpgrade",
this.username,
expect((error) => test.isFalse(error))
);
},
// Changing our password should upgrade us to bcrypt.
function (test, expect) {
Accounts.changePassword(
"abcdef",
"abcdefg",
expect(error => test.isFalse(error))
);
},
function (test, expect) {
Meteor.call(
"testSRPUpgrade",
this.username,
expect(error => test.isFalse(error))
);
},
// And after the upgrade we should be able to change our password again.
function (test, expect) {
Accounts.changePassword(
"abcdefg",
"abcdef",
expect(error => test.isFalse(error))
);
},
logoutStep
]);
}) ();
@@ -1395,7 +1192,7 @@ if (Meteor.isServer) (() => {
const username = Random.id();
Accounts.createUser({
username: username,
password: 'password'
password: hashPassword('password')
});
makeTestConnection(
@@ -1407,7 +1204,7 @@ if (Meteor.isServer) (() => {
});
const result = clientConn.call('login', {
user: {username: username},
password: 'password'
password: hashPassword('password')
});
test.isTrue(result);
const token = Accounts._getAccountData(serverConn.id, 'loginToken');
@@ -1445,7 +1242,7 @@ if (Meteor.isServer) (() => {
const userId = Accounts.createUser({
username: username,
email: email,
password: "old-password"
password: hashPassword("old-password")
});
const user = Meteor.users.findOne(userId);
@@ -1464,15 +1261,15 @@ if (Meteor.isServer) (() => {
Meteor.users.update(userId, {$set: {"emails.0.address": newEmail}});
test.throws(
() => Meteor.call("resetPassword", resetPasswordToken, "new-password"),
() => Meteor.call("resetPassword", resetPasswordToken, hashPassword("new-password")),
/Token has invalid email address/
);
test.throws(
() => Meteor.call(
"login",
{user: {username: username},
password: "new-password"}
),
"login",
{user: {username: username},
password: hashPassword("new-password")}
),
/Incorrect password/);
});
@@ -1485,7 +1282,7 @@ if (Meteor.isServer) (() => {
const userId = Accounts.createUser({
username: username,
email: email,
password: "old-password"
password: hashPassword("old-password")
});
const user = Meteor.users.findOne(userId);
@@ -1506,12 +1303,12 @@ if (Meteor.isServer) (() => {
test.isTrue(clientConn.call(
"resetPassword",
resetPasswordToken,
"new-password"
hashPassword("new-password")
));
test.isTrue(clientConn.call("login", {
user: { username },
password: "new-password"
password: hashPassword("new-password")
}));
onComplete();
@@ -1528,7 +1325,7 @@ if (Meteor.isServer) (() => {
const userId = Accounts.createUser({
username: username,
email: email,
password: "old-password"
password: hashPassword("old-password")
});
const user = Meteor.users.findOne(userId);
@@ -1546,23 +1343,52 @@ if (Meteor.isServer) (() => {
Meteor.users.update(userId, {$set: {"services.password.reset.when": new Date(Date.now() + -5 * 24 * 3600 * 1000) }});
test.throws(
() => Meteor.call("resetPassword", resetPasswordToken, "new-password"),
() => Meteor.call("resetPassword", resetPasswordToken, hashPassword("new-password")),
/Token expired/
);
test.throws(
() => Meteor.call(
"login",
{user: {username: username},
password: "new-password"}
password: hashPassword("new-password")}
),
/Incorrect password/);
});
Tinytest.add('forgotPassword - different error messages returned depending' +
' on whether ambiguousErrorMessages flag is passed in Account.config',
test =>{
const username = Random.id();
const email = `${Random.id()}-intercept@example.com`;
const randomEmail = `${Random.id()}-Ada_intercept@some.com`;
const wrongOptions = {email: randomEmail}
const password = 'password';
const options = Accounts._options
Accounts.createUser(
{ username: username, email: email, password: hashPassword(password) },
);
Accounts._options.ambiguousErrorMessages = true
test.throws(
()=> Meteor.call('forgotPassword', wrongOptions),
'Something went wrong. Please check your credentials'
)
Accounts._options.ambiguousErrorMessages = false
test.throws(
()=> Meteor.call('forgotPassword', wrongOptions),
'User not found'
)
// return accounts as it were
Accounts._options = options
});
Tinytest.add(
'passwords - reset tokens with reasons get cleaned up',
test => {
const email = `${test.id}-intercept@example.com`;
const userId = Accounts.createUser({email: email, password: 'password'});
const userId = Accounts.createUser({email: email, password: hashPassword('password')});
Accounts.sendResetPasswordEmail(userId, email);
test.isTrue(!!Meteor.users.findOne(userId).services.password.reset);
@@ -1575,7 +1401,7 @@ if (Meteor.isServer) (() => {
'passwords - reset tokens without reasons get cleaned up',
test => {
const email = `${test.id}-intercept@example.com`;
const userId = Accounts.createUser({email: email, password: 'password'});
const userId = Accounts.createUser({email: email, password: hashPassword('password')});
Accounts.sendResetPasswordEmail(userId, email);
Meteor.users.update({_id: userId}, {$unset: {"services.password.reset.reason": 1}});
test.isTrue(!!Meteor.users.findOne(userId).services.password.reset);
@@ -1615,12 +1441,12 @@ if (Meteor.isServer) (() => {
test.isTrue(clientConn.call(
"resetPassword",
enrollPasswordToken,
"new-password"
hashPassword("new-password")
));
test.isTrue(clientConn.call("login", {
user: { username },
password: "new-password"
password: hashPassword("new-password")
}));
onComplete();
@@ -1650,37 +1476,36 @@ if (Meteor.isServer) (() => {
test.isTrue(match);
const enrollPasswordToken = match[1];
Meteor.users.update(userId, {$set: {"services.password.reset.when": new Date(Date.now() + -35 * 24 * 3600 * 1000) }});
Meteor.users.update(userId, {$set: {"services.password.enroll.when": new Date(Date.now() + -35 * 24 * 3600 * 1000) }});
test.throws(
() => Meteor.call("resetPassword", enrollPasswordToken, "new-password"),
() => Meteor.call("resetPassword", enrollPasswordToken, hashPassword("new-password")),
/Token expired/
);
});
Tinytest.add('passwords - enroll tokens get cleaned up', test => {
const email = `${test.id}-intercept@example.com`;
const userId = Accounts.createUser({email: email, password: 'password'});
const userId = Accounts.createUser({email: email, password: hashPassword('password')});
Accounts.sendEnrollmentEmail(userId, email);
test.isTrue(!!Meteor.users.findOne(userId).services.password.reset);
test.isTrue(!!Meteor.users.findOne(userId).services.password.enroll);
Accounts._expirePasswordEnrollTokens(new Date(), userId);
test.isUndefined(Meteor.users.findOne(userId).services.password.reset);
test.isUndefined(Meteor.users.findOne(userId).services.password.enroll);
});
Tinytest.add(
"passwords - enroll tokens don't get cleaned up when reset tokens are cleaned up",
test => {
const email = `${test.id}-intercept@example.com`;
const userId = Accounts.createUser({email: email, password: 'password'});
const userId = Accounts.createUser({email: email, password: hashPassword('password')});
Accounts.sendEnrollmentEmail(userId, email);
const enrollToken = Meteor.users.findOne(userId).services.password.reset;
const enrollToken = Meteor.users.findOne(userId).services.password.enroll;
test.isTrue(enrollToken);
Accounts._expirePasswordResetTokens(new Date(), userId);
test.equal(enrollToken, Meteor.users.findOne(userId).services.password.reset);
test.equal(enrollToken, Meteor.users.findOne(userId).services.password.enroll);
}
)
@@ -1688,7 +1513,7 @@ if (Meteor.isServer) (() => {
"passwords - reset tokens don't get cleaned up when enroll tokens are cleaned up",
test => {
const email = `${test.id}-intercept@example.com`;
const userId = Accounts.createUser({email: email, password: 'password'});
const userId = Accounts.createUser({email: email, password: hashPassword('password')});
Accounts.sendResetPasswordEmail(userId, email);
const resetToken = Meteor.users.findOne(userId).services.password.reset;
@@ -1923,14 +1748,14 @@ if (Meteor.isServer) (() => {
Tinytest.addAsync(
'passwords - allow custom bcrypt rounds',
(test, done) => {
const getUserHashRounds = user =>
const getUserHashRounds = user =>
Number(user.services.password.bcrypt.substring(4, 6));
// Verify that a bcrypt hash generated for a new account uses the
// default number of rounds.
let username = Random.id();
const password = 'abc123';
const password = hashPassword('abc123');
const userId1 = Accounts.createUser({ username, password });
let user1 = Meteor.users.findOne(userId1);
let rounds = getUserHashRounds(user1);

View File

@@ -132,39 +132,3 @@ Meteor.methods({
},
removeUser: username => Meteor.users.remove({ "username": username }),
});
// Create a user that had previously logged in with SRP.
Meteor.methods({
testCreateSRPUser: () => {
const username = Random.id();
Meteor.users.remove({username: username});
const userId = Accounts.createUser({username: username});
Meteor.users.update(
userId,
{ '$set': { 'services.password.srp': {
"identity" : "iPNrshUEcpOSO5fRDu7o4RRDc9OJBCGGljYpcXCuyg9",
"salt" : "Dk3lFggdEtcHU3aKm6Odx7sdcaIrMskQxBbqtBtFzt6",
"verifier" : "2e8bce266b1357edf6952cc56d979db19f699ced97edfb2854b95972f820b0c7006c1a18e98aad40edf3fe111b87c52ef7dd06b320ce452d01376df2d560fdc4d8e74f7a97bca1f67b3cfaef34dee34dd6c76571c247d762624dc166dab5499da06bc9358528efa75bf74e2e7f5a80d09e60acf8856069ae5cfb080f2239ee76"
} } }
);
return username;
},
testSRPUpgrade: username => {
const user = Meteor.users.findOne({username: username});
if (user.services && user.services.password && user.services.password.srp)
throw new Error("srp wasn't removed");
if (!(user.services && user.services.password && user.services.password.bcrypt))
throw new Error("bcrypt wasn't added");
},
testNoSRPUpgrade: username => {
const user = Meteor.users.findOne({username: username});
if (user.services && user.services.password && user.services.password.bcrypt)
throw new Error("bcrypt was added");
if (user.services && user.services.password && ! user.services.password.srp)
throw new Error("srp was removed");
}
});

View File

@@ -1,6 +1,6 @@
Package.describe({
summary: "Login service for Twitter accounts",
version: "1.4.2",
version: "1.5.0-beta230.6",
});
Package.onUse(api => {

View File

@@ -1,6 +1,6 @@
Package.describe({
summary: "Unstyled version of login widgets",
version: "1.4.3"
version: "1.5.0-beta230.6"
});
Package.onUse(function (api) {
@@ -9,7 +9,7 @@ Package.onUse(function (api) {
'service-configuration',
'accounts-base',
'ecmascript',
'templating@1.2.13',
'templating@1.4.0',
'session',
], 'client');

View File

@@ -1,6 +1,6 @@
Package.describe({
summary: "Simple templates to add login widgets to an app",
version: "1.3.2",
version: "1.4.0-beta230.6",
});
Package.onUse(api => {

View File

@@ -1,6 +1,6 @@
Package.describe({
summary: "Login service for Sina Weibo accounts",
version: "1.3.2",
version: "1.4.0-beta230.6",
});
Package.onUse(api => {

View File

@@ -7,14 +7,14 @@
"integrity": "sha512-HV1Cm0Q3ZrpCR93tkWOYiuYIgLxZXZFVG2VgK+MBWjUqZTundupbfx2aXarXuw5Ko5aMcjtJgbSs4vUGBS5v6g=="
},
"@babel/compat-data": {
"version": "7.13.12",
"resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.13.12.tgz",
"integrity": "sha512-3eJJ841uKxeV8dcN/2yGEUy+RfgQspPEgQat85umsE1rotuquQ2AbIub4S6j7c50a2d+4myc+zSlnXeIHrOnhQ=="
"version": "7.14.0",
"resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.14.0.tgz",
"integrity": "sha512-vu9V3uMM/1o5Hl5OekMUowo3FqXLJSw+s+66nt0fSWVWTtmosdzn45JHOB3cPtZoe6CTBDzvSw0RdOY85Q37+Q=="
},
"@babel/core": {
"version": "7.13.14",
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.13.14.tgz",
"integrity": "sha512-wZso/vyF4ki0l0znlgM4inxbdrUvCb+cVz8grxDq+6C9k6qbqoIJteQOKicaKjCipU3ISV+XedCqpL2RJJVehA==",
"version": "7.14.3",
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.14.3.tgz",
"integrity": "sha512-jB5AmTKOCSJIZ72sd78ECEhuPiDMKlQdDI/4QRI6lzYATx5SSogS1oQA2AoPecRCknm30gHi2l+QVvNUu3wZAg==",
"dependencies": {
"json5": {
"version": "2.2.0",
@@ -24,9 +24,9 @@
}
},
"@babel/generator": {
"version": "7.13.9",
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.13.9.tgz",
"integrity": "sha512-mHOOmY0Axl/JCTkxTU6Lf5sWOg/v8nUa+Xkt4zMTftX0wqmb6Sh7J8gvcehBw7q0AhrhAR+FDacKjCZ2X8K+Sw=="
"version": "7.14.3",
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.14.3.tgz",
"integrity": "sha512-bn0S6flG/j0xtQdz3hsjJ624h3W0r3llttBMfyHX3YrZ/KtLYr15bjA0FXkgW7FpvrDuTuElXeVjiKlYRpnOFA=="
},
"@babel/helper-annotate-as-pure": {
"version": "7.12.13",
@@ -39,24 +39,24 @@
"integrity": "sha512-CZOv9tGphhDRlVjVkAgm8Nhklm9RzSmWpX2my+t7Ua/KT616pEzXsQCjinzvkRvHWJ9itO4f296efroX23XCMA=="
},
"@babel/helper-compilation-targets": {
"version": "7.13.13",
"resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.13.13.tgz",
"integrity": "sha512-q1kcdHNZehBwD9jYPh3WyXcsFERi39X4I59I3NadciWtNDyZ6x+GboOxncFK0kXlKIv6BJm5acncehXWUjWQMQ=="
"version": "7.13.16",
"resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.13.16.tgz",
"integrity": "sha512-3gmkYIrpqsLlieFwjkGgLaSHmhnvlAYzZLlYVjlW+QwI+1zE17kGxuJGmIqDQdYp56XdmGeD+Bswx0UTyG18xA=="
},
"@babel/helper-create-class-features-plugin": {
"version": "7.13.11",
"resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.13.11.tgz",
"integrity": "sha512-ays0I7XYq9xbjCSvT+EvysLgfc3tOkwCULHjrnscGT3A9qD4sk3wXnJ3of0MAWsWGjdinFvajHU2smYuqXKMrw=="
"version": "7.14.3",
"resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.14.3.tgz",
"integrity": "sha512-BnEfi5+6J2Lte9LeiL6TxLWdIlEv9Woacc1qXzXBgbikcOzMRM2Oya5XGg/f/ngotv1ej2A/b+3iJH8wbS1+lQ=="
},
"@babel/helper-create-regexp-features-plugin": {
"version": "7.12.17",
"resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.12.17.tgz",
"integrity": "sha512-p2VGmBu9oefLZ2nQpgnEnG0ZlRPvL8gAGvPUMQwUdaE8k49rOMuZpOwdQoy5qJf6K8jL3bcAMhVUlHAjIgJHUg=="
"version": "7.14.3",
"resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.14.3.tgz",
"integrity": "sha512-JIB2+XJrb7v3zceV2XzDhGIB902CmKGSpSl4q2C6agU9SNLG/2V1RtFRGPG1Ajh9STj3+q6zJMOC+N/pp2P9DA=="
},
"@babel/helper-define-polyfill-provider": {
"version": "0.1.5",
"resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.1.5.tgz",
"integrity": "sha512-nXuzCSwlJ/WKr8qxzW816gwyT6VZgiJG17zR40fou70yfAcqjoNyTLl/DQ+FExw5Hx5KNqshmN8Ldl/r2N7cTg=="
"version": "0.2.3",
"resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.2.3.tgz",
"integrity": "sha512-RH3QDAfRMzj7+0Nqu5oqgO5q9mFtQEVvCRsi8qCEfzLR9p2BHfn5FzhSB2oj1fF7I2+DcTORkYaQ6aTR9Cofew=="
},
"@babel/helper-explode-assignable-expression": {
"version": "7.13.0",
@@ -64,9 +64,9 @@
"integrity": "sha512-qS0peLTDP8kOisG1blKbaoBg/o9OSa1qoumMjTK5pM+KDTtpxpsiubnCGP34vK8BXGcb2M9eigwgvoJryrzwWA=="
},
"@babel/helper-function-name": {
"version": "7.12.13",
"resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.12.13.tgz",
"integrity": "sha512-TZvmPn0UOqmvi5G4vvw0qZTpVptGkB1GL61R6lKvrSdIxGm5Pky7Q3fpKiIkQCAtRCBUwB0PaThlx9vebCDSwA=="
"version": "7.14.2",
"resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.14.2.tgz",
"integrity": "sha512-NYZlkZRydxw+YT56IlhIcS8PAhb+FEUiOzuhFTfqDyPmzAhRge6ua0dQYT/Uh0t/EDHq05/i+e5M2d4XvjgarQ=="
},
"@babel/helper-get-function-arity": {
"version": "7.12.13",
@@ -84,9 +84,9 @@
"integrity": "sha512-4cVvR2/1B693IuOvSI20xqqa/+bl7lqAMR59R4iu39R9aOX8/JoYY1sFaNvUMyMBGnHdwvJgUrzNLoUZxXypxA=="
},
"@babel/helper-module-transforms": {
"version": "7.13.14",
"resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.13.14.tgz",
"integrity": "sha512-QuU/OJ0iAOSIatyVZmfqB0lbkVP0kDRiKj34xy+QNsnVZi/PA6BoSoreeqnxxa9EHFAIL0R9XOaAR/G9WlIy5g=="
"version": "7.14.2",
"resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.14.2.tgz",
"integrity": "sha512-OznJUda/soKXv0XhpvzGWDnml4Qnwp16GN+D/kZIdLsWoHj05kyu8Rm5kXmMef+rVJZ0+4pSGLkeixdqNUATDA=="
},
"@babel/helper-optimise-call-expression": {
"version": "7.12.13",
@@ -104,9 +104,9 @@
"integrity": "sha512-pUQpFBE9JvC9lrQbpX0TmeNIy5s7GnZjna2lhhcHC7DzgBs6fWn722Y5cfwgrtrqc7NAJwMvOa0mKhq6XaE4jg=="
},
"@babel/helper-replace-supers": {
"version": "7.13.12",
"resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.13.12.tgz",
"integrity": "sha512-Gz1eiX+4yDO8mT+heB94aLVNCL+rbuT2xy4YfyNqu8F+OI6vMvJK891qGBTqL9Uc8wxEvRW92Id6G7sDen3fFw=="
"version": "7.14.3",
"resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.14.3.tgz",
"integrity": "sha512-Rlh8qEWZSTfdz+tgNV/N4gz1a0TMNwCUcENhMjHTHKp3LseYH5Jha0NSlyTQWMnjbYcwFt+bqAMqSLHVXkQ6UA=="
},
"@babel/helper-simple-access": {
"version": "7.13.12",
@@ -124,9 +124,9 @@
"integrity": "sha512-tCJDltF83htUtXx5NLcaDqRmknv652ZWCHyoTETf1CXYJdPC7nohZohjUgieXhv0hTJdRf2FjDueFehdNucpzg=="
},
"@babel/helper-validator-identifier": {
"version": "7.12.11",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz",
"integrity": "sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw=="
"version": "7.14.0",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.0.tgz",
"integrity": "sha512-V3ts7zMSu5lfiwWDVWzRDGIN+lnCEUdaXgtVHJgLb1rGaA6jMrtB9EmE7L18foXJIE8Un/A/h6NJfGQp/e1J4A=="
},
"@babel/helper-validator-option": {
"version": "7.12.17",
@@ -139,49 +139,54 @@
"integrity": "sha512-1UX9F7K3BS42fI6qd2A4BjKzgGjToscyZTdp1DjknHLCIvpgne6918io+aL5LXFcER/8QWiwpoY902pVEqgTXA=="
},
"@babel/helpers": {
"version": "7.13.10",
"resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.13.10.tgz",
"integrity": "sha512-4VO883+MWPDUVRF3PhiLBUFHoX/bsLTGFpFK/HqvvfBZz2D57u9XzPVNFVBTc0PW/CWR9BXTOKt8NF4DInUHcQ=="
"version": "7.14.0",
"resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.14.0.tgz",
"integrity": "sha512-+ufuXprtQ1D1iZTO/K9+EBRn+qPWMJjZSw/S0KlFrxCw4tkrzv9grgpDHkY9MeQTjTY8i2sp7Jep8DfU6tN9Mg=="
},
"@babel/highlight": {
"version": "7.13.10",
"resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.13.10.tgz",
"integrity": "sha512-5aPpe5XQPzflQrFwL1/QoeHkP2MsA4JCntcXHRhEsdsfPVkvPi2w7Qix4iV7t5S/oC9OodGrggd8aco1g3SZFg=="
"version": "7.14.0",
"resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.0.tgz",
"integrity": "sha512-YSCOwxvTYEIMSGaBQb5kDDsCopDdiUGsqpatp3fOlI4+2HQSkTmEVWnVuySdAC5EWCqSWWTv0ib63RjR7dTBdg=="
},
"@babel/parser": {
"version": "7.13.13",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.13.13.tgz",
"integrity": "sha512-OhsyMrqygfk5v8HmWwOzlYjJrtLaFhF34MrfG/Z73DgYCI6ojNUTUp2TYbtnjo8PegeJp12eamsNettCQjKjVw=="
"version": "7.14.3",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.14.3.tgz",
"integrity": "sha512-7MpZDIfI7sUC5zWo2+foJ50CSI5lcqDehZ0lVgIhSi4bFEk94fLAKlF3Q0nzSQQ+ca0lm+O6G9ztKVBeu8PMRQ=="
},
"@babel/plugin-proposal-async-generator-functions": {
"version": "7.13.8",
"resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.13.8.tgz",
"integrity": "sha512-rPBnhj+WgoSmgq+4gQUtXx/vOcU+UYtjy1AA/aeD61Hwj410fwYyqfUcRP3lR8ucgliVJL/G7sXcNUecC75IXA=="
"version": "7.14.2",
"resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.14.2.tgz",
"integrity": "sha512-b1AM4F6fwck4N8ItZ/AtC4FP/cqZqmKRQ4FaTDutwSYyjuhtvsGEMLK4N/ztV/ImP40BjIDyMgBQAeAMsQYVFQ=="
},
"@babel/plugin-proposal-class-properties": {
"version": "7.13.0",
"resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.13.0.tgz",
"integrity": "sha512-KnTDjFNC1g+45ka0myZNvSBFLhNCLN+GeGYLDEA8Oq7MZ6yMgfLoIRh86GRT0FjtJhZw8JyUskP9uvj5pHM9Zg=="
},
"@babel/plugin-proposal-logical-assignment-operators": {
"version": "7.14.2",
"resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.14.2.tgz",
"integrity": "sha512-1JAZtUrqYyGsS7IDmFeaem+/LJqujfLZ2weLR9ugB0ufUPjzf8cguyVT1g5im7f7RXxuLq1xUxEzvm68uYRtGg=="
},
"@babel/plugin-proposal-nullish-coalescing-operator": {
"version": "7.13.8",
"resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.13.8.tgz",
"integrity": "sha512-iePlDPBn//UhxExyS9KyeYU7RM9WScAG+D3Hhno0PLJebAEpDZMocbDe64eqynhNAnwz/vZoL/q/QB2T1OH39A=="
"version": "7.14.2",
"resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.14.2.tgz",
"integrity": "sha512-ebR0zU9OvI2N4qiAC38KIAK75KItpIPTpAtd2r4OZmMFeKbKJpUFLYP2EuDut82+BmYi8sz42B+TfTptJ9iG5Q=="
},
"@babel/plugin-proposal-object-rest-spread": {
"version": "7.13.8",
"resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.13.8.tgz",
"integrity": "sha512-DhB2EuB1Ih7S3/IRX5AFVgZ16k3EzfRbq97CxAVI1KSYcW+lexV8VZb7G7L8zuPVSdQMRn0kiBpf/Yzu9ZKH0g=="
"version": "7.14.2",
"resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.14.2.tgz",
"integrity": "sha512-hBIQFxwZi8GIp934+nj5uV31mqclC1aYDhctDu5khTi9PCCUOczyy0b34W0oE9U/eJXiqQaKyVsmjeagOaSlbw=="
},
"@babel/plugin-proposal-optional-catch-binding": {
"version": "7.13.8",
"resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.13.8.tgz",
"integrity": "sha512-0wS/4DUF1CuTmGo+NiaHfHcVSeSLj5S3e6RivPTg/2k3wOv3jO35tZ6/ZWsQhQMvdgI7CwphjQa/ccarLymHVA=="
"version": "7.14.2",
"resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.14.2.tgz",
"integrity": "sha512-XtkJsmJtBaUbOxZsNk0Fvrv8eiqgneug0A6aqLFZ4TSkar2L5dSXWcnUKHgmjJt49pyB/6ZHvkr3dPgl9MOWRQ=="
},
"@babel/plugin-proposal-optional-chaining": {
"version": "7.13.12",
"resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.13.12.tgz",
"integrity": "sha512-fcEdKOkIB7Tf4IxrgEVeFC4zeJSTr78no9wTdBuZZbqF64kzllU0ybo2zrzm7gUQfxGhBgq4E39oRs8Zx/RMYQ=="
"version": "7.14.2",
"resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.14.2.tgz",
"integrity": "sha512-qQByMRPwMZJainfig10BoaDldx/+VDtNcrA7qdNaEOAj6VXud+gfrkA8j4CRAU5HjnWREXqIpSpH30qZX1xivA=="
},
"@babel/plugin-syntax-async-generators": {
"version": "7.8.4",
@@ -203,6 +208,11 @@
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.12.13.tgz",
"integrity": "sha512-d4HM23Q1K7oq/SLNmG6mRt85l2csmQ0cHRaxRXjKW0YFdEXqlZ5kzFQKH5Uc3rDJECgu+yCRgPkG04Mm98R/1g=="
},
"@babel/plugin-syntax-logical-assignment-operators": {
"version": "7.10.4",
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz",
"integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig=="
},
"@babel/plugin-syntax-nullish-coalescing-operator": {
"version": "7.8.3",
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz",
@@ -239,14 +249,14 @@
"integrity": "sha512-zNyFqbc3kI/fVpqwfqkg6RvBgFpC4J18aKKMmv7KdQ/1GgREapSJAykLMVNwfRGO3BtHj3YQZl8kxCXPcVMVeg=="
},
"@babel/plugin-transform-block-scoping": {
"version": "7.12.13",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.12.13.tgz",
"integrity": "sha512-Pxwe0iqWJX4fOOM2kEZeUuAxHMWb9nK+9oh5d11bsLoB0xMg+mkDpt0eYuDZB7ETrY9bbcVlKUGTOGWy7BHsMQ=="
"version": "7.14.2",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.14.2.tgz",
"integrity": "sha512-neZZcP19NugZZqNwMTH+KoBjx5WyvESPSIOQb4JHpfd+zPfqcH65RMu5xJju5+6q/Y2VzYrleQTr+b6METyyxg=="
},
"@babel/plugin-transform-classes": {
"version": "7.13.0",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.13.0.tgz",
"integrity": "sha512-9BtHCPUARyVH1oXGcSJD3YpsqRLROJx5ZNP6tN5vnk17N0SVf9WCtf8Nuh1CFmgByKKAIMstitKduoCmsaDK5g=="
"version": "7.14.2",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.14.2.tgz",
"integrity": "sha512-7oafAVcucHquA/VZCsXv/gmuiHeYd64UJyyTYU+MPfNu0KeNlxw06IeENBO8bJjXVbolu+j1MM5aKQtH1OMCNg=="
},
"@babel/plugin-transform-computed-properties": {
"version": "7.13.0",
@@ -254,9 +264,9 @@
"integrity": "sha512-RRqTYTeZkZAz8WbieLTvKUEUxZlUTdmL5KGMyZj7FnMfLNKV4+r5549aORG/mgojRmFlQMJDUupwAMiF2Q7OUg=="
},
"@babel/plugin-transform-destructuring": {
"version": "7.13.0",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.13.0.tgz",
"integrity": "sha512-zym5em7tePoNT9s964c0/KU3JPPnuq7VhIxPRefJ4/s82cD+q1mgKfuGRDMCPL0HTyKz4dISuQlCusfgCJ86HA=="
"version": "7.13.17",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.13.17.tgz",
"integrity": "sha512-UAUqiLv+uRLO+xuBKKMEpC+t7YRNVRqBsWWq1yKXbBZBje/t3IXCiSinZhjn/DC3qzBfICeYd2EFGEbHsh5RLA=="
},
"@babel/plugin-transform-exponentiation-operator": {
"version": "7.12.13",
@@ -274,9 +284,9 @@
"integrity": "sha512-FW+WPjSR7hiUxMcKqyNjP05tQ2kmBCdpEpZHY1ARm96tGQCCBvXKnpjILtDplUnJ/eHZ0lALLM+d2lMFSpYJrQ=="
},
"@babel/plugin-transform-modules-commonjs": {
"version": "7.13.8",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.13.8.tgz",
"integrity": "sha512-9QiOx4MEGglfYZ4XOnU79OHr6vIWUakIj9b4mioN8eQIoEh+pf5p/zEB36JpDFWA12nNMiRf7bfoRvl9Rn79Bw=="
"version": "7.14.0",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.14.0.tgz",
"integrity": "sha512-EX4QePlsTaRZQmw9BsoPeyh5OCtRGIhwfLquhxGp5e32w+dyL8htOcDwamlitmNFK6xBZYlygjdye9dbd9rUlQ=="
},
"@babel/plugin-transform-object-super": {
"version": "7.12.13",
@@ -284,9 +294,9 @@
"integrity": "sha512-JzYIcj3XtYspZDV8j9ulnoMPZZnF/Cj0LUxPOjR89BdBVx+zYJI9MdMIlUZjbXDX+6YVeS6I3e8op+qQ3BYBoQ=="
},
"@babel/plugin-transform-parameters": {
"version": "7.13.0",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.13.0.tgz",
"integrity": "sha512-Jt8k/h/mIwE2JFEOb3lURoY5C85ETcYPnbuAJ96zRBzh1XHtQZfs62ChZ6EP22QlC8c7Xqr9q+e1SU5qttwwjw=="
"version": "7.14.2",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.14.2.tgz",
"integrity": "sha512-NxoVmA3APNCC1JdMXkdYXuQS+EMdqy0vIwyDHeKHiJKRxmp1qGSdb0JLEIoPRhkx6H/8Qi3RJ3uqOCYw8giy9A=="
},
"@babel/plugin-transform-property-literals": {
"version": "7.12.13",
@@ -294,14 +304,14 @@
"integrity": "sha512-nqVigwVan+lR+g8Fj8Exl0UQX2kymtjcWfMOYM1vTYEKujeyv2SkMgazf2qNcK7l4SDiKyTA/nHCPqL4e2zo1A=="
},
"@babel/plugin-transform-react-display-name": {
"version": "7.12.13",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.12.13.tgz",
"integrity": "sha512-MprESJzI9O5VnJZrL7gg1MpdqmiFcUv41Jc7SahxYsNP2kDkFqClxxTZq+1Qv4AFCamm+GXMRDQINNn+qrxmiA=="
"version": "7.14.2",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.14.2.tgz",
"integrity": "sha512-zCubvP+jjahpnFJvPaHPiGVfuVUjXHhFvJKQdNnsmSsiU9kR/rCZ41jHc++tERD2zV+p7Hr6is+t5b6iWTCqSw=="
},
"@babel/plugin-transform-react-jsx": {
"version": "7.13.12",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.13.12.tgz",
"integrity": "sha512-jcEI2UqIcpCqB5U5DRxIl0tQEProI2gcu+g8VTIqxLO5Iidojb4d77q+fwGseCvd8af/lJ9masp4QWzBXFE2xA=="
"version": "7.14.3",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.14.3.tgz",
"integrity": "sha512-uuxuoUNVhdgYzERiHHFkE4dWoJx+UFVyuAl0aqN8P2/AKFHwqgUC5w2+4/PjpKXJsFgBlYAFXlUmDQ3k3DUkXw=="
},
"@babel/plugin-transform-react-jsx-development": {
"version": "7.12.17",
@@ -314,14 +324,14 @@
"integrity": "sha512-RqeaHiwZtphSIUZ5I85PEH19LOSzxfuEazoY7/pWASCAIBuATQzpSVD+eT6MebeeZT2F4eSL0u4vw6n4Nm0Mjg=="
},
"@babel/plugin-transform-regenerator": {
"version": "7.12.13",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.12.13.tgz",
"integrity": "sha512-lxb2ZAvSLyJ2PEe47hoGWPmW22v7CtSl9jW8mingV4H2sEX/JOcrAj2nPuGWi56ERUm2bUpjKzONAuT6HCn2EA=="
"version": "7.13.15",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.13.15.tgz",
"integrity": "sha512-Bk9cOLSz8DiurcMETZ8E2YtIVJbFCPGW28DJWUakmyVWtQSm6Wsf0p4B4BfEr/eL2Nkhe/CICiUiMOCi1TPhuQ=="
},
"@babel/plugin-transform-runtime": {
"version": "7.13.10",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.13.10.tgz",
"integrity": "sha512-Y5k8ipgfvz5d/76tx7JYbKQTcgFSU6VgJ3kKQv4zGTKr+a9T/KBvfRvGtSFgKDQGt/DBykQixV0vNWKIdzWErA=="
"version": "7.14.3",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.14.3.tgz",
"integrity": "sha512-t960xbi8wpTFE623ef7sd+UpEC5T6EEguQlTBJDEO05+XwnIWVfuqLw/vdLWY6IdFmtZE+65CZAfByT39zRpkg=="
},
"@babel/plugin-transform-shorthand-properties": {
"version": "7.12.13",
@@ -359,9 +369,9 @@
"integrity": "sha512-gx+tDLIE06sRjKJkVtpZ/t3mzCDOnPG+ggHZG9lffUbX8+wC739x20YQc9V35Do6ZAxaUc/HhVHIiOzz5MvDmA=="
},
"@babel/runtime": {
"version": "7.13.10",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.13.10.tgz",
"integrity": "sha512-4QPkjJq6Ns3V/RgpEahRk+AGfL0eO6RHHtTWoNNr5mO49G6B5+X6d6THgWEAvTrznU5xYpbAlVKRYcsCgh/Akw=="
"version": "7.14.0",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.14.0.tgz",
"integrity": "sha512-JELkvo/DlpNdJ7dlyw/eY7E0suy5i5GQH+Vlxaq1nsNJ+H7f4Vtv3jMeCEgRhZZQFXTjldYfQgv2qmM6M1v5wA=="
},
"@babel/template": {
"version": "7.12.13",
@@ -369,14 +379,19 @@
"integrity": "sha512-/7xxiGA57xMo/P2GVvdEumr8ONhFOhfgq2ihK3h1e6THqzTAkHbkXgB0xI9yeTfIUoH3+oAeHhqm/I43OTbbjA=="
},
"@babel/traverse": {
"version": "7.13.13",
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.13.13.tgz",
"integrity": "sha512-CblEcwmXKR6eP43oQGG++0QMTtCjAsa3frUuzHoiIJWpaIIi8dwMyEFUJoXRLxagGqCK+jALRwIO+o3R9p/uUg=="
"version": "7.14.2",
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.14.2.tgz",
"integrity": "sha512-TsdRgvBFHMyHOOzcP9S6QU0QQtjxlRpEYOy3mcCO5RgmC305ki42aSAmfZEMSSYBla2oZ9BMqYlncBaKmD/7iA=="
},
"@babel/types": {
"version": "7.13.14",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.13.14.tgz",
"integrity": "sha512-A2aa3QTkWoyqsZZFl56MLUsfmh7O0gN41IPvXAE/++8ojpbz12SszD7JEGYVdn4f9Kt4amIei07swF1h4AqmmQ=="
"version": "7.14.2",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.14.2.tgz",
"integrity": "sha512-SdjAG/3DikRHpUOjxZgnkbR11xUlyDMUFJdvnIgZEE16mqmY0BINMmc4//JMJglEmn6i7sq6p+mGrFWyZ98EEw=="
},
"@meteorjs/babel": {
"version": "7.11.1",
"resolved": "https://registry.npmjs.org/@meteorjs/babel/-/babel-7.11.1.tgz",
"integrity": "sha512-5WZZ3v7F2B5KpKBSOYe3kh83ijrj6o7oenCadqH59Lp9ONorZGJePQQg1OotepKzwNflBiw60cy9eFgi+/qhsw=="
},
"acorn": {
"version": "6.4.2",
@@ -489,19 +504,19 @@
"integrity": "sha1-G8bxW4f3qxCF1CszC3F2V6IVZQA="
},
"babel-plugin-polyfill-corejs2": {
"version": "0.1.10",
"resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.1.10.tgz",
"integrity": "sha512-DO95wD4g0A8KRaHKi0D51NdGXzvpqVLnLu5BTvDlpqUEpTmeEtypgC1xqesORaWmiUOQI14UHKlzNd9iZ2G3ZA=="
"version": "0.2.2",
"resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.2.2.tgz",
"integrity": "sha512-kISrENsJ0z5dNPq5eRvcctITNHYXWOA4DUZRFYCz3jYCcvTb/A546LIddmoGNMVYg2U38OyFeNosQwI9ENTqIQ=="
},
"babel-plugin-polyfill-corejs3": {
"version": "0.1.7",
"resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.1.7.tgz",
"integrity": "sha512-u+gbS9bbPhZWEeyy1oR/YaaSpod/KDT07arZHb80aTpl8H5ZBq+uN1nN9/xtX7jQyfLdPfoqI4Rue/MQSWJquw=="
"version": "0.2.2",
"resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.2.2.tgz",
"integrity": "sha512-l1Cf8PKk12eEk5QP/NQ6TH8A1pee6wWDJ96WjxrMXFLHLOBFzYM4moG80HFgduVhTqAFez4alnZKEhP/bYHg0A=="
},
"babel-plugin-polyfill-regenerator": {
"version": "0.1.6",
"resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.1.6.tgz",
"integrity": "sha512-OUrYG9iKPKz8NxswXbRAdSwF0GhRdIEMTloQATJi4bDuFqrXaXcCUT/VGNrr8pBcjMh1RxZ7Xt9cytVJTJfvMg=="
"version": "0.2.2",
"resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.2.2.tgz",
"integrity": "sha512-Goy5ghsc21HgPDFtzRkSirpZVW35meGoTmTOb2bxqdl60ghub4xOidgNTHaZfQ2FaxQsKmwvXtOAkcIS4SMBWg=="
},
"babel-plugin-transform-inline-consecutive-adds": {
"version": "0.4.3",
@@ -559,9 +574,9 @@
"integrity": "sha1-viQcqBQEAwZ4t0hxcyK4nQyP4oA="
},
"babel-preset-meteor": {
"version": "7.9.0",
"resolved": "https://registry.npmjs.org/babel-preset-meteor/-/babel-preset-meteor-7.9.0.tgz",
"integrity": "sha512-SB2hGHZ2wKFiqaovO5DlgoYEUjNGP9FytZlLXppDKKP+TGpoGSQUyNhQ/ACSPFbTEBhKSuyV1LCEmHS+yK7FyQ=="
"version": "7.10.0",
"resolved": "https://registry.npmjs.org/babel-preset-meteor/-/babel-preset-meteor-7.10.0.tgz",
"integrity": "sha512-bcdNfRCQAjTV42cUcmaG5/ltLZZQLpZajUcP+o0Lr+aLTY/XLNkGfASM5383wdXiAkEFl0sDOXeknnLlQtrmdg=="
},
"babel-preset-minify": {
"version": "0.5.1",
@@ -569,9 +584,9 @@
"integrity": "sha512-1IajDumYOAPYImkHbrKeiN5AKKP9iOmRoO2IPbIuVp0j2iuCcj0n7P260z38siKMZZ+85d3mJZdtW8IgOv+Tzg=="
},
"browserslist": {
"version": "4.16.3",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.3.tgz",
"integrity": "sha512-vIyhWmIkULaq04Gt93txdh+j02yX/JzlyhLYbV3YQCn/zvES3JnY7TifHHvvr1w5hTDluNKMkV05cs4vy8Q7sw=="
"version": "4.16.6",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.6.tgz",
"integrity": "sha512-Wspk/PqO+4W9qp5iUTJsa1B/QrYn1keNCcEP5OvP7WBwT4KaDly0uONYmC6Xa3Z5IqnUgS0KcgLYu1l74x0ZXQ=="
},
"call-bind": {
"version": "1.0.2",
@@ -579,9 +594,9 @@
"integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA=="
},
"caniuse-lite": {
"version": "1.0.30001205",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001205.tgz",
"integrity": "sha512-TL1GrS5V6LElbitPazidkBMD9sa448bQDDLrumDqaggmKFcuU2JW1wTOHJPukAcOMtEmLcmDJEzfRrf+GjM0Og=="
"version": "1.0.30001230",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001230.tgz",
"integrity": "sha512-5yBd5nWCBS+jWKTcHOzXwo5xzcj4ePE/yjtkZyUV1BTUmrBaA9MRGC+e7mxnqXSA90CmCA8L3eKLaSUkt099IQ=="
},
"chalk": {
"version": "2.4.2",
@@ -609,9 +624,9 @@
"integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA=="
},
"core-js-compat": {
"version": "3.10.0",
"resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.10.0.tgz",
"integrity": "sha512-9yVewub2MXNYyGvuLnMHcN1k9RkvB7/ofktpeKTIaASyB88YYqGzUnu0ywMMhJrDHOMiTjSHWGzR+i7Wb9Z1kQ==",
"version": "3.13.0",
"resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.13.0.tgz",
"integrity": "sha512-jhbI2zpVskgfDC9mGRaDo1gagd0E0i/kYW0+WvibL/rafEHKAHO653hEXIxJHqRlRLITluXtRH3AGTL5qJmifQ==",
"dependencies": {
"semver": {
"version": "7.0.0",
@@ -631,9 +646,9 @@
"integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ=="
},
"electron-to-chromium": {
"version": "1.3.703",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.703.tgz",
"integrity": "sha512-SVBVhNB+4zPL+rvtWLw7PZQkw/Eqj1HQZs22xtcqW36+xoifzEOEEDEpkxSMfB6RFeSIOcG00w6z5mSqLr1Y6w=="
"version": "1.3.741",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.741.tgz",
"integrity": "sha512-4i3T0cwnHo1O4Mnp9JniEco8bZiXoqbm3PhW5hv7uu8YLg35iajYrRnNyKFaN8/8SSTskU2hYqVTeYVPceSpUA=="
},
"escalade": {
"version": "3.1.1",
@@ -686,9 +701,9 @@
"integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw=="
},
"is-core-module": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.2.0.tgz",
"integrity": "sha512-XRAfAdyyY5F5cOXn7hYQDqh2Xmii+DEfIcQGxK/uNwMHhIkPWO0g8msXcbzLe+MpGoR951MlqM/2iIlU4vKDdQ=="
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.4.0.tgz",
"integrity": "sha512-6A2fkfq1rfeQZjxrZJGerpLCTHRNEBiSgnu0+obeJpEPZRUooHgsizvzv0ZjJwOz3iWIHdJtVWJ/tmPr3D21/A=="
},
"js-tokens": {
"version": "4.0.0",
@@ -720,11 +735,6 @@
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.7.tgz",
"integrity": "sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA=="
},
"meteor-babel": {
"version": "7.10.7",
"resolved": "https://registry.npmjs.org/meteor-babel/-/meteor-babel-7.10.7.tgz",
"integrity": "sha512-Ed9ckTjKjItwWA15AANvGpLKP1LwW8xiyt1kAEOGVVRjtBraLbt7U0dm1meT5jSRF53A5bk+aQtlReninIDf8A=="
},
"meteor-babel-helpers": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/meteor-babel-helpers/-/meteor-babel-helpers-0.0.3.tgz",
@@ -741,9 +751,9 @@
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
},
"node-releases": {
"version": "1.1.71",
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.71.tgz",
"integrity": "sha512-zR6HoT6LrLCRBwukmrVbHv0EpEQjksO6GmFcZQQuCAy139BEsoVKPYnf3jongYW83fAa1torLGYwxxky/p28sg=="
"version": "1.1.72",
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.72.tgz",
"integrity": "sha512-LLUo+PpH3dU6XizX3iVoubUNheF/owjXCZZ5yACDxNnPtgFuludV1ZL3ayK1kVep42Rmm0+R9/Y60NQbZ2bifw=="
},
"object-keys": {
"version": "1.1.1",
@@ -756,9 +766,9 @@
"integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ=="
},
"path-parse": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz",
"integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw=="
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
"integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="
},
"regenerate": {
"version": "1.4.2",
@@ -850,9 +860,9 @@
"integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4="
},
"typescript": {
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.2.3.tgz",
"integrity": "sha512-qOcYwxaByStAWrBf4x0fibwZvMRG+r4cQoTjbPtUlrWjBHbmCAww1i448U0GJ+3cNNEtebDteo/cHOR3xJ4wEw=="
"version": "4.3.2",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.3.2.tgz",
"integrity": "sha512-zZ4hShnmnoVnAHpVHWpTcxdv7dWP60S2FsydQLV8V5PbS3FifjWFFRiHSWpDJahly88PRyV5teTSLoq4eG7mKw=="
},
"unicode-canonical-property-names-ecmascript": {
"version": "1.0.4",

View File

@@ -20,8 +20,8 @@ Meteor's Babel support consists of the following core packages:
The `babel-compiler` package exports the `Babel` symbol, which exposes
functionality provided by the
[`meteor-babel`](https://www.npmjs.com/package/meteor-babel) NPM package,
which is in turn implemented using the
[`@meteorjs/babel`](https://www.npmjs.com/package/@meteorjs/babel) NPM package,
which is in turn implmented using the
[`babel-core`](https://www.npmjs.com/package/babel-core) NPM package.
Note that you can only use the `babel-compiler` package on the server.

View File

@@ -1,6 +1,6 @@
var meteorBabel = null;
function getMeteorBabel() {
return meteorBabel || (meteorBabel = Npm.require("meteor-babel"));
return meteorBabel || (meteorBabel = Npm.require("@meteorjs/babel"));
}
/**
@@ -46,6 +46,6 @@ Babel = {
},
getMinimumModernBrowserVersions: function () {
return Npm.require("meteor-babel/modern-versions.js").get();
return Npm.require("@meteorjs/babel/modern-versions.js").get();
}
};

View File

@@ -6,11 +6,11 @@ Package.describe({
// isn't possible because you can't publish a non-recommended
// release with package versions that don't have a pre-release
// identifier at the end (eg, -dev)
version: '7.6.1'
version: '7.6.2-beta230.6'
});
Npm.depends({
'meteor-babel': '7.10.7',
'@meteorjs/babel': '7.11.1',
'json5': '2.1.1'
});

View File

@@ -55,13 +55,3 @@ Meteor.connection = DDP.connect(ddpUrl, {
].forEach(name => {
Meteor[name] = Meteor.connection[name].bind(Meteor.connection);
});
// Meteor.connection used to be called
// Meteor.default_connection. Provide backcompat as a courtesy even
// though it was never documented.
// XXX COMPAT WITH 0.6.4
Meteor.default_connection = Meteor.connection;
// We should transition from Meteor.connect to DDP.connect.
// XXX COMPAT WITH 0.6.4
Meteor.connect = DDP.connect;

View File

@@ -160,7 +160,7 @@ export class Connection {
// documents written by a given method's stub. keys are associated with
// methods whose stub wrote at least one document, and whose data-done message
// has not yet been received.
self._documentsWrittenByStub = Object.create(null);
self._documentsWrittenByStub = {};
// collection -> IdMap of "server document" object. A "server document" has:
// - "document": the version of the document according the
// server (ie, the snapshot before a stub wrote it, amended by any changes
@@ -168,7 +168,7 @@ export class Connection {
// It is undefined if we think the document does not exist
// - "writtenByStubs": a set of method IDs whose stubs wrote to the document
// whose "data done" messages have not yet been processed
self._serverDocuments = Object.create(null);
self._serverDocuments = {};
// Array of callbacks to be called after the next update of the local
// cache. Used for:
@@ -197,16 +197,16 @@ export class Connection {
// Map from method ID -> true. Methods are removed from this when their
// "data done" message is received, and we will not quiesce until it is
// empty.
self._methodsBlockingQuiescence = Object.create(null);
self._methodsBlockingQuiescence = {};
// map from sub ID -> true for subs that were ready (ie, called the sub
// ready callback) before reconnect but haven't become ready again yet
self._subsBeingRevived = Object.create(null); // map from sub._id -> true
self._subsBeingRevived = {}; // map from sub._id -> true
// if true, the next data update should reset all stores. (set during
// reconnect.)
self._resetStores = false;
// name -> array of updates for (yet to be created) collections
self._updatesForUnknownStores = Object.create(null);
self._updatesForUnknownStores = {};
// if we're blocking a migration, the retry func
self._retryMigrate = null;
@@ -216,7 +216,7 @@ export class Connection {
self
);
// Collection name -> array of messages.
self._bufferedWrites = Object.create(null);
self._bufferedWrites = {};
// When current buffer of updates must be flushed at, in ms timestamp.
self._bufferedWritesFlushAt = null;
// Timeout handle for the next processing of all pending writes
@@ -236,7 +236,7 @@ export class Connection {
// an error, XXX COMPAT WITH 1.0.3.1)
// - stopCallback (an optional callback to call when the sub terminates
// for any reason, with an error argument if an error triggered the stop)
self._subscriptions = Object.create(null);
self._subscriptions = {};
// Reactive userId.
self._userId = null;
@@ -1622,11 +1622,10 @@ export class Connection {
}
if (msg === null || !msg.msg) {
// XXX COMPAT WITH 0.6.6. ignore the old welcome message for back
// compat. Remove this 'if' once the server stops sending welcome
// messages (stream_server.js).
if (!(msg && msg.server_id))
if(!msg || !msg.testMessageOnConnect) {
if (Object.keys(msg).length === 1 && msg.server_id) return;
Meteor._debug('discarding invalid livedata message', msg);
}
return;
}

View File

@@ -1,6 +1,5 @@
import { DDPCommon } from 'meteor/ddp-common';
import { Meteor } from 'meteor/meteor';
import { keys } from "meteor/ddp-common/utils.js";
import { Connection } from './livedata_connection.js';

View File

@@ -1,6 +1,6 @@
Package.describe({
summary: "Meteor's latency-compensated distributed data client",
version: '2.4.1',
version: '2.5.0-beta230.6',
documentation: null
});

View File

@@ -1,6 +1,6 @@
Package.describe({
name: 'ddp-rate-limiter',
version: '1.0.9',
version: '1.1.0-beta230.6',
// Brief, one-line summary of the package.
summary: 'The DDPRateLimiter allows users to add rate limits to DDP' +
' methods and subscriptions.',

View File

@@ -119,7 +119,7 @@ var SessionCollectionView = function (collectionName, sessionCallbacks) {
DDPServer._SessionCollectionView = SessionCollectionView;
_.extend(SessionCollectionView.prototype, {
Object.assign(SessionCollectionView.prototype, {
isEmpty: function () {
var self = this;
@@ -241,6 +241,8 @@ var Session = function (server, version, socket, options) {
self.blocked = false;
self.workerRunning = false;
self.cachedUnblock = null;
// Sub objects for active subscriptions
self._namedSubs = new Map();
self._universalSubs = [];
@@ -322,7 +324,7 @@ var Session = function (server, version, socket, options) {
"livedata", "sessions", 1);
};
_.extend(Session.prototype, {
Object.assign(Session.prototype, {
sendReady: function (subscriptionIds) {
var self = this;
@@ -567,9 +569,13 @@ _.extend(Session.prototype, {
},
protocol_handlers: {
sub: function (msg) {
sub: function (msg, unblock) {
var self = this;
// cacheUnblock temporarly, so we can capture it later
// we will use unblock in current eventLoop, so this is safe
self.cachedUnblock = unblock;
// reject malformed messages
if (typeof (msg.id) !== "string" ||
typeof (msg.name) !== "string" ||
@@ -624,6 +630,8 @@ _.extend(Session.prototype, {
self._startSubscription(handler, msg.id, msg.params, msg.name);
// cleaning cached unblock
self.cachedUnblock = null;
},
unsub: function (msg) {
@@ -852,6 +860,13 @@ _.extend(Session.prototype, {
var sub = new Subscription(
self, handler, subId, params, name);
let unblockHander = self.cachedUnblock;
// _startSubscription may call from a lot places
// so cachedUnblock might be null in somecases
// assign the cachedUnblock
sub.unblock = unblockHander || (() => {});
if (subId)
self._namedSubs.set(subId, sub);
else
@@ -1030,7 +1045,7 @@ var Subscription = function (
"livedata", "subscriptions", 1);
};
_.extend(Subscription.prototype, {
Object.assign(Subscription.prototype, {
_runHandler: function () {
// XXX should we unblock() here? Either before running the publish
// function, or before running _publishCursor.
@@ -1039,9 +1054,13 @@ _.extend(Subscription.prototype, {
// methods waiting on data from Mongo (or whatever else the function
// blocks on). This probably slows page load in common cases.
if (!this.unblock) {
this.unblock = () => {};
}
var self = this;
try {
var res = DDP._CurrentPublicationInvocation.withValue(
var resMaybePromise = DDP._CurrentPublicationInvocation.withValue(
self,
() => maybeAuditArgumentChecks(
self._handler, self, EJSON.clone(self._params),
@@ -1060,7 +1079,14 @@ _.extend(Subscription.prototype, {
if (self._isDeactivated())
return;
self._publishHandlerResult(res);
//Both conventional and async publish handler functions are supported.
//If an object is returned with a then() function, it is either a promise or thenable
//and will be resolved asynchronously.
if (resMaybePromise && typeof resMaybePromise.then === "function") {
Promise.resolve(resMaybePromise).then(self._publishHandlerResult, e => self.error(e));
} else {
self._publishHandlerResult(resMaybePromise);
}
},
_publishHandlerResult: function (res) {
@@ -1419,7 +1445,7 @@ Server = function (options) {
});
};
_.extend(Server.prototype, {
Object.assign(Server.prototype, {
/**
* @summary Register a callback to be called when a new DDP connection is made to the server.

View File

@@ -1,6 +1,6 @@
Package.describe({
summary: "Meteor's latency-compensated distributed data server",
version: '2.3.3',
version: '2.4.0-beta230.6',
documentation: null
});

View File

@@ -15,8 +15,3 @@ _.each(['publish', 'methods', 'call', 'apply', 'onConnection', 'onMessage'],
function (name) {
Meteor[name] = _.bind(Meteor.server[name], Meteor.server);
});
// Meteor.server used to be called Meteor.default_server. Provide
// backcompat as a courtesy even though it was never documented.
// XXX COMPAT WITH 0.6.4
Meteor.default_server = Meteor.server;

View File

@@ -1,5 +1,3 @@
var url = Npm.require('url');
// By default, we use the permessage-deflate extension with default
// configuration. If $SERVER_WEBSOCKET_COMPRESSION is set, then it must be valid
// JSON. If it represents a falsey value, then we do not use permessage-deflate
@@ -119,12 +117,11 @@ StreamServer = function () {
});
self.open_sockets.push(socket);
// XXX COMPAT WITH 0.6.6. Send the old style welcome message, which
// will force old clients to reload. Remove this once we're not
// concerned about people upgrading from a pre-0.7.0 release. Also,
// remove the clause in the client that ignores the welcome message
// (livedata_connection.js)
socket.send(JSON.stringify({server_id: "0"}));
// only to send a message after connection on tests, useful for
// socket-stream-client/server-tests.js
if (process.env.TEST_METADATA) {
socket.send(JSON.stringify({ testMessageOnConnect: true }));
}
// call all our callbacks when we get a new socket. they will do the
// work of setting up handlers and such for specific messages.
@@ -135,7 +132,7 @@ StreamServer = function () {
};
_.extend(StreamServer.prototype, {
Object.assign(StreamServer.prototype, {
// call my callback when a new socket connects.
// also call it for all current connections.
register: function (callback) {
@@ -161,7 +158,7 @@ _.extend(StreamServer.prototype, {
// (meaning prior to any connect middlewares) so we need to take
// an approach similar to overshadowListeners in
// https://github.com/sockjs/sockjs-node/blob/cf820c55af6a9953e16558555a31decea554f70e/src/utils.coffee
_.each(['request', 'upgrade'], function(event) {
['request', 'upgrade'].forEach((event) => {
var httpServer = WebApp.httpServer;
var oldHttpServerListeners = httpServer.listeners(event).slice(0);
httpServer.removeAllListeners(event);
@@ -172,6 +169,9 @@ _.extend(StreamServer.prototype, {
// Store arguments for use within the closure below
var args = arguments;
// TODO replace with url package
var url = Npm.require('url');
// Rewrite /websocket and /websocket/ urls to /sockjs/websocket while
// preserving query string.
var parsedUrl = url.parse(request.url);

View File

@@ -1,6 +1,7 @@
Package.describe({
summary: "API for Persistent Storage, PubSub and Request",
version: "1.0.0"
version: "1.0.0",
deprecated: true
});
Package.onUse(function (api) {

View File

@@ -1,6 +1,7 @@
Package.describe({
summary: "A minimalist client-side MVC framework",
version: "1.0.0"
version: "1.0.0",
deprecated: true
});
Package.onUse(function (api) {

View File

@@ -1,6 +1,7 @@
Package.describe({
summary: "Front-end framework from Twitter",
version: "1.0.1"
version: "1.0.1",
deprecated: true
});
Package.onUse(function (api) {

View File

@@ -1,6 +1,7 @@
Package.describe({
summary: '(Deprecated) Syntax highlighting of code, from Google',
version: '2.0.0'
version: '2.0.0',
deprecated: true
});
Package.onUse(function (api) {

View File

@@ -1,6 +1,7 @@
Package.describe({
summary: "Library for manipulating documents based on data",
version: "1.0.0"
version: "1.0.0",
deprecated: true
});
Package.onUse(function (api) {

View File

@@ -2,7 +2,8 @@
Package.describe({
summary: "Deprecated: Use the 'tracker' package instead.",
version: '1.0.12'
version: '1.0.12',
deprecated: 'Use the \'tracker\' package instead.'
});
Package.onUse(function (api) {

View File

@@ -1,6 +1,7 @@
Package.describe({
summary: "DEPRECATED - Use facebook-oauth instead - Facebook OAuth flow",
version: "1.3.0"
version: "1.3.0",
deprecated: 'Use facebook-oauth instead'
});
Package.onUse(function(api) {

View File

@@ -1,6 +1,7 @@
Package.describe({
summary: "Publish internal app statistics",
version: '1.0.9'
version: '1.0.9',
deprecated: true
});
Package.onUse(function (api) {

View File

@@ -1,6 +1,7 @@
Package.describe({
summary: "Faster touch events on mobile",
version: '1.0.13'
version: '1.0.13',
deprecated: true
});
Package.onUse(function (api) {

View File

@@ -1,6 +1,7 @@
Package.describe({
summary: 'DEPRECATED - Use github-oauth instead - GitHub OAuth flow',
version: '1.2.0'
version: '1.2.0',
deprecated: 'Use github-oauth instead'
});
Package.onUse(function (api) {

View File

@@ -1,6 +1,7 @@
Package.describe({
summary: "DEPRECATED - Use google-oauth instead - Google OAuth flow",
version: "1.2.0"
version: "1.2.0",
deprecated: 'Use google-oauth instead'
});
Package.onUse(function(api) {

View File

@@ -1,6 +1,7 @@
Package.describe({
summary: "Deprecated",
version: '1.0.7'
version: '1.0.7',
deprecated: true
});
Package.onUse(function (api) {

View File

@@ -1 +0,0 @@
node_modules

View File

@@ -1,7 +0,0 @@
This directory and the files immediately inside it are automatically generated
when you change this package's NPM dependencies. Commit the files in this
directory (npm-shrinkwrap.json, .gitignore, and this README) to source control
so that others run the same versions of sub-dependencies.
You should NOT check in the node_modules directory that Meteor automatically
creates; if you are using git, the .gitignore file tells git to ignore it.

View File

@@ -1,240 +0,0 @@
{
"lockfileVersion": 1,
"dependencies": {
"ajv": {
"version": "5.5.2",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz",
"integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU="
},
"asn1": {
"version": "0.2.4",
"resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz",
"integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg=="
},
"assert-plus": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
"integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU="
},
"asynckit": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
"integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k="
},
"aws-sign2": {
"version": "0.7.0",
"resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
"integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg="
},
"aws4": {
"version": "1.8.0",
"resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz",
"integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ=="
},
"bcrypt-pbkdf": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz",
"integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4="
},
"caseless": {
"version": "0.12.0",
"resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
"integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw="
},
"co": {
"version": "4.6.0",
"resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
"integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ="
},
"combined-stream": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz",
"integrity": "sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w=="
},
"core-util-is": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
},
"dashdash": {
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
"integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA="
},
"delayed-stream": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
"integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk="
},
"ecc-jsbn": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
"integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk="
},
"extend": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
"integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="
},
"extsprintf": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
"integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU="
},
"fast-deep-equal": {
"version": "1.1.0",
"resolved": "http://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz",
"integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ="
},
"fast-json-stable-stringify": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz",
"integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I="
},
"forever-agent": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
"integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE="
},
"form-data": {
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz",
"integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ=="
},
"getpass": {
"version": "0.1.7",
"resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
"integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo="
},
"har-schema": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
"integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI="
},
"har-validator": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.0.tgz",
"integrity": "sha512-+qnmNjI4OfH2ipQ9VQOw23bBd/ibtfbVdK2fYbY4acTDqKTW/YDp9McimZdDbG8iV9fZizUqQMD5xvriB146TA=="
},
"http-signature": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
"integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE="
},
"is-typedarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
"integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo="
},
"isstream": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
"integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo="
},
"jsbn": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
"integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM="
},
"json-schema": {
"version": "0.2.3",
"resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz",
"integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM="
},
"json-schema-traverse": {
"version": "0.3.1",
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz",
"integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A="
},
"json-stringify-safe": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
"integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus="
},
"jsprim": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz",
"integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI="
},
"mime-db": {
"version": "1.37.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.37.0.tgz",
"integrity": "sha512-R3C4db6bgQhlIhPU48fUtdVmKnflq+hRdad7IyKhtFj06VPNVdk2RhiYL3UjQIlso8L+YxAtFkobT0VK+S/ybg=="
},
"mime-types": {
"version": "2.1.21",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.21.tgz",
"integrity": "sha512-3iL6DbwpyLzjR3xHSFNFeb9Nz/M8WDkX33t1GFQnFOllWk8pOrh/LSrB5OXlnlW5P9LH73X6loW/eogc+F5lJg=="
},
"oauth-sign": {
"version": "0.9.0",
"resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz",
"integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ=="
},
"performance-now": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
"integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns="
},
"psl": {
"version": "1.1.29",
"resolved": "https://registry.npmjs.org/psl/-/psl-1.1.29.tgz",
"integrity": "sha512-AeUmQ0oLN02flVHXWh9sSJF7mcdFq0ppid/JkErufc3hGIV/AMa8Fo9VgDo/cT2jFdOWoFvHp90qqBH54W+gjQ=="
},
"punycode": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
"integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4="
},
"qs": {
"version": "6.5.2",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz",
"integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA=="
},
"request": {
"version": "2.88.0",
"resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz",
"integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg=="
},
"safe-buffer": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
},
"safer-buffer": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
},
"sshpk": {
"version": "1.15.2",
"resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.15.2.tgz",
"integrity": "sha512-Ra/OXQtuh0/enyl4ETZAfTaeksa6BXks5ZcjpSUNrjBr0DvrJKX+1fsKDPpT9TBXgHAFsa4510aNVgI8g/+SzA=="
},
"tough-cookie": {
"version": "2.4.3",
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz",
"integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ=="
},
"tunnel-agent": {
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
"integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0="
},
"tweetnacl": {
"version": "0.14.5",
"resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
"integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q="
},
"uuid": {
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz",
"integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA=="
},
"verror": {
"version": "1.10.0",
"resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
"integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA="
}
}
}

View File

@@ -1,28 +0,0 @@
# http
[Source code of released version](https://github.com/meteor/meteor/tree/master/packages/http) | [Source code of development version](https://github.com/meteor/meteor/tree/devel/packages/http)
***
## Deprecated
This package has been deprecated in favor of the [fetch](https://atmospherejs.com/meteor/fetch) package and new web standards.
## Docs
`HTTP` provides an HTTP request API on the client and server. To use
these functions, add the HTTP package to your project with `$ meteor add http`.
See the [HTTP section in the Meteor docs](http://docs.meteor.com/#http) for more details.
## Direct access to npm request API
On the server, the `http` package is implemented using the
[npm `request` module](https://www.npmjs.com/package/request). If you'd like
direct access to this module, you can find it at
`HTTPInternals.NpmModules.request.module`. Its version can be read at
`HTTPInternals.NpmModules.request.version`.
Additionally, you can override any `request` option when using `HTTP.call` (or
`HTTP.get`, etc) by including a `npmRequestOptions` option.
The version of `request` used may change incompatibly from version to version of
Meteor (or we may even replace it with an entirely different implementation);
use at your own risk.

View File

@@ -1,131 +0,0 @@
var path = require('path');
var request = require('request');
var url_util = require('url');
var URL = require("meteor/url").URL;
var common = require("./httpcall_common.js");
var HTTP = exports.HTTP = common.HTTP;
var hasOwn = Object.prototype.hasOwnProperty;
exports.HTTPInternals = {
NpmModules: {
request: {
version: Npm.require('request/package.json').version,
module: request
}
}
};
// _call always runs asynchronously; HTTP.call, defined below,
// wraps _call and runs synchronously when no callback is provided.
function _call(method, url, options, callback) {
////////// Process arguments //////////
if (! callback && typeof options === "function") {
// support (method, url, callback) argument list
callback = options;
options = null;
}
options = options || {};
if (hasOwn.call(options, 'beforeSend')) {
throw new Error("Option beforeSend not supported on server.");
}
method = (method || "").toUpperCase();
if (! /^https?:\/\//.test(url))
throw new Error("url must be absolute and start with http:// or https://");
var headers = {};
var content = options.content;
if (options.data) {
content = JSON.stringify(options.data);
headers['Content-Type'] = 'application/json';
}
var paramsForUrl, paramsForBody;
if (content || method === "GET" || method === "HEAD")
paramsForUrl = options.params;
else
paramsForBody = options.params;
var newUrl = URL._constructUrl(url, options.query, paramsForUrl);
if (options.auth) {
if (options.auth.indexOf(':') < 0)
throw new Error('auth option should be of the form "username:password"');
headers['Authorization'] = "Basic "+
Buffer.from(options.auth, "ascii").toString("base64");
}
if (paramsForBody) {
content = URL._encodeParams(paramsForBody);
headers['Content-Type'] = "application/x-www-form-urlencoded";
}
if (options.headers) {
Object.keys(options.headers).forEach(function (key) {
headers[key] = options.headers[key];
});
}
// wrap callback to add a 'response' property on an error, in case
// we have both (http 4xx/5xx error, which has a response payload)
callback = (function(callback) {
var called = false;
return function(error, response) {
if (! called) {
called = true;
if (error && response) {
error.response = response;
}
callback(error, response);
}
};
})(callback);
////////// Kickoff! //////////
// Allow users to override any request option with the npmRequestOptions
// option.
var reqOptions = Object.assign({
url: newUrl,
method: method,
encoding: "utf8",
jar: false,
timeout: options.timeout,
body: content,
followRedirect: options.followRedirects,
// Follow redirects on non-GET requests
// also. (https://github.com/meteor/meteor/issues/2808)
followAllRedirects: options.followRedirects,
headers: headers
}, options.npmRequestOptions || null);
request(reqOptions, function(error, res, body) {
var response = null;
if (! error) {
response = {};
response.statusCode = res.statusCode;
response.content = body;
response.headers = res.headers;
common.populateData(response);
if (response.statusCode >= 400) {
error = common.makeErrorByStatus(
response.statusCode,
response.content
);
}
}
callback(error, response);
});
}
HTTP.call = Meteor.wrapAsync(_call);

View File

@@ -1,542 +0,0 @@
// URL prefix for tests to talk to
var _XHR_URL_PREFIX = "/http_test_responder";
var url_base = function () {
if (Meteor.isServer) {
var address = WebApp.httpServer.address();
return "http://127.0.0.1:" + address.port;
} else {
return "";
}
};
var url_prefix = function () {
if (Meteor.isServer && _XHR_URL_PREFIX.indexOf("http") !== 0) {
_XHR_URL_PREFIX = url_base() + _XHR_URL_PREFIX;
}
return _XHR_URL_PREFIX;
};
testAsyncMulti("httpcall - basic", [
function(test, expect) {
var basic_get = function(url, options, expected_url) {
var callback = function(error, result) {
test.isFalse(error);
if (! error) {
test.equal(typeof result, "object");
test.equal(result.statusCode, 200);
var data = result.data;
// allow dropping of final ? (which mobile browsers seem to do)
var allowed = [expected_url];
if (expected_url.slice(-1) === '?')
allowed.push(expected_url.slice(0, -1));
test.include(allowed, expected_url);
test.equal(data.method, "GET");
}
};
HTTP.call("GET", url_prefix()+url, options, expect(callback));
if (Meteor.isServer) {
// test sync version
try {
var result = HTTP.call("GET", url_prefix()+url, options);
callback(undefined, result);
} catch (e) {
callback(e, e.response);
}
}
};
basic_get("/foo", null, "/foo");
basic_get("/foo?", null, "/foo?");
basic_get("/foo?a=b", null, "/foo?a=b");
basic_get("/foo", {params: {fruit: "apple"}},
"/foo?fruit=apple");
basic_get("/foo", {params: {fruit: "apple", dog: "Spot the dog"}},
"/foo?fruit=apple&dog=Spot+the+dog");
basic_get("/foo?", {params: {fruit: "apple", dog: "Spot the dog"}},
"/foo?fruit=apple&dog=Spot+the+dog");
basic_get("/foo?bar", {params: {fruit: "apple", dog: "Spot the dog"}},
"/foo?bar&fruit=apple&dog=Spot+the+dog");
basic_get("/foo?bar", {params: {fruit: "apple", dog: "Spot the dog"},
query: "baz"},
"/foo?baz&fruit=apple&dog=Spot+the+dog");
basic_get("/foo", {params: {fruit: "apple", dog: "Spot the dog"},
query: "baz"},
"/foo?baz&fruit=apple&dog=Spot+the+dog");
basic_get("/foo?", {params: {fruit: "apple", dog: "Spot the dog"},
query: "baz"},
"/foo?baz&fruit=apple&dog=Spot+the+dog");
basic_get("/foo?bar", {query: ""}, "/foo?");
basic_get("/foo?bar", {params: {fruit: "apple", dog: "Spot the dog"},
query: ""},
"/foo?fruit=apple&dog=Spot+the+dog");
}]);
testAsyncMulti("httpcall - errors", [
function(test, expect) {
// Accessing unknown server (should fail to make any connection)
var unknownServerCallback = function(error, result) {
test.isTrue(error);
test.isFalse(result);
test.isFalse(error.response);
};
const invalidIp = "0.0.0.199";
// This is an invalid destination IP address, and thus should always give an error.
// If your ISP is intercepting DNS misses and serving ads, an obviously
// invalid URL (http://asdf.asdf) might produce an HTTP response.
HTTP.call("GET", `http://${invalidIp}/`, expect(unknownServerCallback));
if (Meteor.isServer) {
// test sync version
try {
var unknownServerResult = HTTP.call("GET", `http://${invalidIp}/`);
unknownServerCallback(undefined, unknownServerResult);
} catch (e) {
unknownServerCallback(e, e.response);
}
}
// Server serves 500
var error500Callback = function(error, result) {
test.isTrue(error);
test.isTrue(error.message.indexOf("500") !== -1); // message has statusCode
test.isTrue(error.message.indexOf(
error.response.content.substring(0, 10)) !== -1); // message has part of content
test.isTrue(result);
test.isTrue(error.response);
test.equal(result, error.response);
test.equal(error.response.statusCode, 500);
// in test_responder.js we make a very long response body, to make sure
// that we truncate messages. first of all, make sure we didn't make that
// message too short, so that we can be sure we're verifying that we truncate.
test.isTrue(error.response.content.length > 520);
test.isTrue(error.message.length < 520); // make sure we truncate.
};
HTTP.call("GET", url_prefix()+"/fail", expect(error500Callback));
if (Meteor.isServer) {
// test sync version
try {
var error500Result = HTTP.call("GET", url_prefix()+"/fail");
error500Callback(undefined, error500Result);
} catch (e) {
error500Callback(e, e.response);
}
}
}
]);
testAsyncMulti("httpcall - timeout", [
function(test, expect) {
// Should time out
var timeoutCallback = function(error, result) {
test.isTrue(error);
test.isFalse(result);
test.isFalse(error.response);
};
var timeoutUrl = url_prefix()+"/slow-"+Random.id();
HTTP.call(
"GET", timeoutUrl,
{ timeout: 500 },
expect(timeoutCallback));
if (Meteor.isServer) {
// test sync version
try {
var timeoutResult = HTTP.call("GET", timeoutUrl, { timeout: 500 });
timeoutCallback(undefined, timeoutResult);
} catch (e) {
timeoutCallback(e, e.response);
}
}
// Should not time out
var noTimeoutCallback = function(error, result) {
test.isFalse(error);
test.isTrue(result);
test.equal(result.statusCode, 200);
var data = result.data;
test.equal(data.url.substring(0, 4), "/foo");
test.equal(data.method, "GET");
};
var noTimeoutUrl = url_prefix()+"/foo-"+Random.id();
HTTP.call(
"GET", noTimeoutUrl,
{ timeout: 2000 },
expect(noTimeoutCallback));
if (Meteor.isServer) {
// test sync version
try {
var noTimeoutResult = HTTP.call("GET", noTimeoutUrl, { timeout: 2000 });
noTimeoutCallback(undefined, noTimeoutResult);
} catch (e) {
noTimeoutCallback(e, e.response);
}
}
}
]);
testAsyncMulti("httpcall - redirect", [
function(test, expect) {
// Test that we follow redirects by default
HTTP.call("GET", url_prefix()+"/redirect", expect(
function(error, result) {
test.isFalse(error);
test.isTrue(result);
// should be redirected transparently to /foo
test.equal(result.statusCode, 200);
var data = result.data;
test.equal(data.url, "/foo");
test.equal(data.method, "GET");
}));
// followRedirect option; can't be false on client
_.each([false, true], function(followRedirects) {
var do_it = function(should_work) {
var maybe_expect = should_work ? expect : _.identity;
_.each(["GET", "POST"], function (method) {
HTTP.call(
method, url_prefix()+"/redirect",
{followRedirects: followRedirects},
maybe_expect(function(error, result) {
test.isFalse(error);
test.isTrue(result);
if (followRedirects) {
// should be redirected transparently to /foo
test.equal(result.statusCode, 200);
var data = result.data;
test.equal(data.url, "/foo");
// This is "GET" even when the initial request was a
// POST because browsers follow redirects with a GET
// even when the initial request was a different method.
test.equal(data.method, "GET");
} else {
// should see redirect
test.equal(result.statusCode, 301);
}
}));
});
};
if (Meteor.isClient && ! followRedirects) {
// not supported, should fail
test.throws(do_it);
} else {
do_it(true);
}
});
}
]);
testAsyncMulti("httpcall - methods", [
function(test, expect) {
// non-get methods
var test_method = function(meth, func_name) {
func_name = func_name || meth.toLowerCase();
HTTP[func_name](
url_prefix()+"/foo",
expect(function(error, result) {
test.isFalse(error);
test.isTrue(result);
test.equal(result.statusCode, 200);
var data = result.data;
test.equal(data.url, "/foo");
test.equal(data.method, meth);
}));
};
test_method("GET");
test_method("POST");
test_method("PUT");
test_method("DELETE", 'del');
test_method("PATCH");
},
function(test, expect) {
// contents and data
HTTP.call(
"POST", url_prefix()+"/foo",
{ content: "Hello World!" },
expect(function(error, result) {
test.isFalse(error);
test.isTrue(result);
test.equal(result.statusCode, 200);
var data = result.data;
test.equal(data.body, "Hello World!");
}));
HTTP.call(
"POST", url_prefix()+"/data-test",
{ data: {greeting: "Hello World!"} },
expect(function(error, result) {
test.isFalse(error);
test.isTrue(result);
test.equal(result.statusCode, 200);
var data = result.data;
test.equal(data.body, {greeting: "Hello World!"});
// nb: some browsers include a charset here too.
test.matches(data.headers['content-type'], /^application\/json\b/);
}));
HTTP.call(
"POST", url_prefix()+"/data-test-explicit",
{ data: {greeting: "Hello World!"},
headers: {'Content-Type': 'text/stupid'} },
expect(function(error, result) {
test.isFalse(error);
test.isTrue(result);
test.equal(result.statusCode, 200);
var data = result.data;
test.equal(data.body, {greeting: "Hello World!"});
// nb: some browsers include a charset here too.
test.matches(data.headers['content-type'], /^text\/stupid\b/);
}));
}
]);
testAsyncMulti("httpcall - http auth", [
function(test, expect) {
// Test basic auth
// Unfortunately, any failed auth will result in a browser
// password prompt. So we don't test auth failure, only
// success.
// Random password breaks in Firefox, because Firefox incorrectly
// uses cached credentials even if we supply different ones:
// https://bugzilla.mozilla.org/show_bug.cgi?id=654348
var password = 'rocks';
//var password = Random.id().replace(/[^0-9a-zA-Z]/g, '');
HTTP.call(
"GET", url_prefix()+"/login?"+password,
{ auth: "meteor:"+password },
expect(function(error, result) {
// should succeed
test.isFalse(error);
test.isTrue(result);
test.equal(result.statusCode, 200);
var data = result.data;
test.equal(data.url, "/login?"+password);
}));
// test fail on malformed username:password
test.throws(function() {
HTTP.call(
"GET", url_prefix()+"/login?"+password,
{ auth: "fooooo" },
function() { throw new Error("can't get here"); });
});
}
]);
testAsyncMulti("httpcall - headers", [
function(test, expect) {
HTTP.call(
"GET", url_prefix()+"/foo-with-headers",
{headers: { "Test-header": "Value",
"another": "Value2" } },
expect(function(error, result) {
test.isFalse(error);
test.isTrue(result);
test.equal(result.statusCode, 200);
var data = result.data;
test.equal(data.url, "/foo-with-headers");
test.equal(data.method, "GET");
test.equal(data.headers['test-header'], "Value");
test.equal(data.headers['another'], "Value2");
}));
HTTP.call(
"GET", url_prefix()+"/headers",
expect(function(error, result) {
test.isFalse(error);
test.isTrue(result);
test.equal(result.statusCode, 201);
test.equal(result.headers['a-silly-header'], "Tis a");
test.equal(result.headers['another-silly-header'], "Silly place.");
}));
}
]);
testAsyncMulti("httpcall - params", [
function(test, expect) {
var do_test = function(method, url, params, opt_opts, expect_url, expect_body) {
var opts = {};
if (typeof opt_opts === "string") {
// opt_opts omitted
expect_body = expect_url;
expect_url = opt_opts;
} else {
opts = opt_opts;
}
HTTP.call(
method, url_prefix()+url,
_.extend({ params: params }, opts),
expect(function(error, result) {
test.isFalse(error);
test.isTrue(result);
test.equal(result.statusCode, 200);
if (method !== "HEAD") {
var data = result.data;
test.equal(data.method, method);
test.equal(data.url, expect_url);
test.equal(data.body, expect_body);
}
}));
};
do_test("GET", "/blah", {foo:"bar"}, "/blah?foo=bar", "");
do_test("GET", "/", {foo:"bar", fruit:"apple"}, "/?foo=bar&fruit=apple", "");
do_test("POST", "/", {foo:"bar", fruit:"apple"}, "/", "foo=bar&fruit=apple");
do_test("POST", "/", {foo:"bar", fruit:"apple"}, "/", "foo=bar&fruit=apple");
do_test("GET", "/", {'foo?':"bang?"}, {}, "/?foo%3F=bang%3F", "");
do_test("POST", "/", {'foo?':"bang?"}, {}, "/", "foo%3F=bang%3F");
do_test("POST", "/", {foo:"bar", fruit:"apple"}, {
content: "stuff!"}, "/?foo=bar&fruit=apple", "stuff!");
do_test("POST", "/", {foo:"bar", greeting:"Hello World"}, {
content: "stuff!"}, "/?foo=bar&greeting=Hello+World", "stuff!");
do_test("POST", "/foo", {foo:"bar", greeting:"Hello World"},
"/foo", "foo=bar&greeting=Hello+World");
do_test("HEAD", "/head", {foo:"bar"}, "/head?foo=bar", "");
do_test("PUT", "/put", {foo:"bar"}, "/put", "foo=bar");
}
]);
testAsyncMulti("httpcall - npmRequestOptions", [
function (test, expect) {
if (Meteor.isClient) {
test.throws(function () {
HTTP.get(url_prefix() + "/",
{ npmRequestOptions: { encoding: null } },
function () {});
});
return;
}
HTTP.get(
url_prefix() + "/",
{ npmRequestOptions: { encoding: null } },
expect(function (error, result) {
test.isFalse(error);
test.isTrue(result);
test.equal(result.statusCode, 200);
test.instanceOf(result.content, Buffer);
})
);
}
]);
Meteor.isClient && testAsyncMulti("httpcall - beforeSend", [
function (test, expect) {
var fired = false;
var bSend = function(xhr){
test.isFalse(fired);
fired = true;
test.isTrue(xhr instanceof XMLHttpRequest);
};
HTTP.get(url_prefix() + "/", {beforeSend: bSend}, expect(function () {
test.isTrue(fired);
}));
}
]);
if (Meteor.isServer) {
// This is testing the server's static file sending code, not the http
// package. It's here because it is very similar to the other tests
// here, even though it is testing something else.
//
// client http library mangles paths before they are requested. only
// run this test on the server.
testAsyncMulti("httpcall - static file serving", [
function(test, expect) {
// Suppress error printing for this test (and for any other code that sets
// the x-suppress-error header).
WebApp.suppressConnectErrors();
function do_test(path, code, match) {
const prefix = Meteor.isModern
? "" // No prefix for web.browser (modern).
: "/__browser.legacy";
HTTP.get(url_base() + prefix + path, {
headers: {
"x-suppress-error": "true"
}
}, expect(function(error, result) {
test.equal(result.statusCode, code);
if (match) {
test.matches(result.content, match);
}
}));
}
// existing static file
do_test("/packages/local-test_http/test_static.serveme", 200, /static file serving/);
// no such file, so return the default app HTML.
var getsAppHtml = [
// This file doesn't exist.
"/nosuchfile",
// Our static file serving doesn't process .. or its encoded version, so
// any of these return the app HTML.
"/../nosuchfile",
"/%2e%2e/nosuchfile",
"/%2E%2E/nosuchfile",
"/%2d%2d/nosuchfile",
"/packages/http/../http/test_static.serveme",
"/packages/http/%2e%2e/http/test_static.serveme",
"/packages/http/%2E%2E/http/test_static.serveme",
"/packages/http/../../packages/http/test_static.serveme",
"/packages/http/%2e%2e/%2e%2e/packages/http/test_static.serveme",
"/packages/http/%2E%2E/%2E%2E/packages/http/test_static.serveme",
// ... and they *definitely* shouldn't be able to escape the app bundle.
"/packages/http/../../../../../../packages/http/test_static.serveme",
"/../../../../../../../../../../../bin/ls",
"/%2e%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e/bin/ls",
"/%2E%2E/%2E%2E/%2E%2E/%2E%2E/%2E%2E/%2E%2E/%2E%2E/%2E%2E/%2E%2E/%2E%2E/%2E%2E/bin/ls"
];
_.each(getsAppHtml, function (x) {
do_test(x, 200, /__meteor_runtime_config__ = JSON/);
});
}
]);
}
Meteor.isServer && Tinytest.add("httpcall - npm modules", function (test) {
// Make sure the version number looks like a version number. (All published
// request version numbers end in ".0".)
test.matches(HTTPInternals.NpmModules.request.version, /^2\.(\d+)\.0/);
test.equal(typeof(HTTPInternals.NpmModules.request.module), 'function');
test.isTrue(HTTPInternals.NpmModules.request.module.get);
});
// TO TEST/ADD:
// - https
// - cookies?
// - human-readable error reason/cause?
// - data parse error

View File

@@ -1,7 +1,8 @@
Package.describe({
name: "jquery-history",
summary: "Deprecated package for HTML5 pushState",
version: "1.0.2"
version: "1.0.2",
deprecated: true
});
Package.onUse(function (api) {

View File

@@ -4,7 +4,8 @@
Package.describe({
name: "jquery-layout",
summary: "Deprecated package for JS layout",
version: "1.0.3"
version: "1.0.3",
deprecated: true
});
Package.onUse(function (api) {

View File

@@ -1,6 +1,7 @@
Package.describe({
summary: "Run a function when the user scrolls past an element",
version: "1.0.9"
version: "1.0.9",
deprecated: true
});
Package.onUse(function (api) {

View File

@@ -0,0 +1,49 @@
allow-deny@1.1.0
babel-compiler@7.6.1
babel-runtime@1.5.0
base64@1.0.12
binary-heap@1.0.11
boilerplate-generator@1.7.1
callback-hook@1.3.0
check@1.3.1
ddp@1.4.0
ddp-client@2.4.1
ddp-common@1.4.0
ddp-server@2.3.3
diff-sequence@1.1.1
dynamic-import@0.6.0
ecmascript@0.15.1
ecmascript-runtime@0.7.0
ecmascript-runtime-client@0.11.1
ecmascript-runtime-server@0.10.1
ejson@1.1.1
fetch@0.1.1
geojson-utils@1.0.10
id-map@1.1.1
inter-process-messaging@0.1.1
jshint@1.1.8
local-test:jshint@1.1.8
logging@1.2.0
meteor@1.9.3
minimongo@1.6.2
modern-browsers@0.1.5
modules@0.16.0
modules-runtime@0.12.0
mongo@1.11.1
mongo-decimal@0.1.2
mongo-dev-server@1.1.0
mongo-id@1.0.8
npm-mongo@3.9.0
ordered-dict@1.1.0
promise@0.11.2
random@1.2.0
react-fast-refresh@0.1.1
reload@1.3.1
retry@1.1.0
routepolicy@1.1.0
socket-stream-client@0.3.3
tinytest@1.1.0
tracker@1.2.0
underscore@1.0.10
webapp@1.10.1
webapp-hashing@1.1.0

View File

@@ -1,8 +1,9 @@
Package.describe({
name: 'jshint',
version: '1.1.7',
version: '1.1.8',
summary: 'Lint all your JavaScript files with JSHint.',
documentation: 'README.md'
documentation: 'README.md',
deprecated: true
});
Package.registerBuildPlugin({

View File

@@ -1,6 +1,7 @@
Package.describe({
summary: "(Deprecated) Full-featured JavaScript parser",
version: "2.0.0"
version: "2.0.0",
deprecated: true
});
Package.onUse(function (api) {

View File

@@ -1,6 +1,7 @@
Package.describe({
summary: "Moved to the 'ddp' package",
version: '1.0.18'
version: '1.0.18',
deprecated: true
});
Package.onUse(function (api) {

View File

@@ -1,5 +1,7 @@
# markdown
[Source code of released version](https://github.com/meteor/meteor/tree/master/packages/markdown) | [Source code of development version](https://github.com/meteor/meteor/tree/devel/packages/markdown)
[Source code of released version](https://github.com/meteor/meteor/tree/master/packages/deprecated/markdown) | [Source code of development version](https://github.com/meteor/meteor/tree/devel/packages/deprecated/markdown)
***
This is an internal Meteor package.
This is an internal Meteor package.
[How to use it at Meteor Docs](https://docs.meteor.com/packages/markdown.html)

View File

@@ -2,15 +2,14 @@
Package.describe({
summary: "Markdown-to-HTML processor",
version: "1.0.14"
version: "2.0.0-beta230.6",
deprecated: true
});
Package.onUse(function (api) {
api.addFiles("showdown.js");
api.export('Showdown');
api.use("templating@1.3.1", "client", {weak: true});
api.addFiles('template-integration.js', 'client');
api.use('ecmascript');
api.use("templating@1.4.0", "client", {weak: true});
api.mainModule('template-integration.js', 'client', { lazy: true });
});
Package.onTest(function (api) {

View File

@@ -65,7 +65,7 @@
// Showdown namespace
//
// METEOR CHANGE: remove "var" so that this isn't file-local.
Showdown = { extensions: {} };
export const Showdown = { extensions: {} };
//
// forEach
@@ -121,7 +121,7 @@ var g_output_modifiers = [];
if (typeof module !== 'undefined' && typeof exports !== 'undefined' && typeof require !== 'undefined') {
var fs = require('fs');
if (fs) {
if (fs && fs.readdirSync) {
// Search extensions folder
var extensions = fs.readdirSync((__dirname || '.')+'/extensions').filter(function(file){
return ~file.indexOf('.js');

View File

@@ -1,3 +1,5 @@
import { Showdown } from './showdown';
if (Package.templating) {
var Template = Package.templating.Template;
var Blaze = Package.blaze.Blaze; // implied by `templating`

View File

@@ -1,6 +1,7 @@
Package.describe({
summary: 'DEPRECATED - Use meetup-oauth instead - Meetup OAuth flow',
version: '1.7.0'
version: '1.7.0',
deprecated: 'Use meetup-oauth instead'
});
Package.onUse(function (api) {

View File

@@ -1,6 +1,7 @@
Package.describe({
summary: 'DEPRECATED - Use meteor-developer-oauth instead - Meteor developer accounts OAuth flow',
version: '1.2.0'
version: '1.2.0',
deprecated: 'Use meteor-developer-oauth instead'
});
Package.onUse(function (api) {

View File

@@ -1,6 +1,7 @@
Package.describe({
summary: "(Deprecated) Include a standard set of Meteor packages in your app",
version: '1.2.6'
version: '1.2.6',
deprecated: true
});
Package.onUse(function(api) {

View File

@@ -3,7 +3,8 @@
// encourage this pattern. Maybe another solution would be better.
Package.describe({
summary: "(Deprecated) reset.css v2.0 from http://meyerweb.com/eric/tools/css/reset/",
version: "2.0.0"
version: "2.0.0",
deprecated: true
});
Package.onUse(function (api) {

View File

@@ -0,0 +1,4 @@
meteor@1.9.3
modules@0.16.0
modules-runtime@0.12.0
npm-bcrypt@0.9.4

View File

@@ -1,7 +1,8 @@
Package.describe({
summary: "Wrapper around the bcrypt npm package",
version: "0.9.3",
documentation: null
version: "0.9.4",
documentation: null,
deprecated: true
});
Npm.depends({

View File

@@ -1,6 +1,7 @@
Package.describe({
summary: "Deprecated package (now empty)",
version: "1.0.11"
version: "1.0.11",
deprecated: true
});
Package.onUse(function (api) {

View File

@@ -1,6 +1,7 @@
Package.describe({
summary: "Moved to the 'markdown' package",
version: '1.0.8'
version: '1.0.8',
deprecated: true
});
Package.onUse(function (api) {

View File

@@ -1,6 +1,7 @@
Package.describe({
summary: "Makes the application crawlable to web spiders",
version: "1.0.14-release-testing.0"
version: "1.0.14",
deprecated: true
});
Package.onUse(function (api) {

View File

@@ -5,7 +5,8 @@
Package.describe({
summary: "Library for Secure Remote Password (SRP) exchanges",
version: "1.1.0"
version: "1.1.0",
deprecated: true
});
Package.onUse(function (api) {

View File

@@ -1,6 +1,7 @@
Package.describe({
summary: "Moved to meteor-platform",
version: '1.0.9'
version: '1.0.9',
deprecated: true
});
Package.onUse(function (api) {

View File

@@ -1,6 +1,7 @@
Package.describe({
summary: "Deprecated package (now empty)",
version: "1.0.7"
version: "1.0.7",
deprecated: true
});
Package.onUse(function (api) {

View File

@@ -1,6 +1,7 @@
Package.describe({
summary: 'Expressive, dynamic, robust CSS',
version: "2.513.15"
version: "2.513.15",
deprecated: true
});
Package.registerBuildPlugin({

View File

@@ -1,6 +1,7 @@
Package.describe({
summary: "DEPRECATED - Use twitter-oauth instead - Twitter OAuth flow",
version: '1.2.0'
version: '1.2.0',
deprecated: 'Use twitter-oauth instead'
});
Package.onUse(function(api) {

View File

@@ -1,6 +1,7 @@
Package.describe({
summary: "DEPRECATED - Use weibo-oauth instead - Weibo OAuth flow",
version: '1.2.0'
version: '1.2.0',
deprecated: 'Use weibo-oauth instead'
});
Package.onUse(function(api) {

View File

@@ -1,6 +1,6 @@
Package.describe({
name: "dynamic-import",
version: "0.6.0",
version: "0.7.0-beta230.6",
summary: "Runtime support for Meteor 1.5 dynamic import(...) syntax",
documentation: "README.md"
});

View File

@@ -67,6 +67,8 @@ function middleware(request, response) {
if (request.method === "OPTIONS") {
const acrh = request.headers["access-control-request-headers"];
response.setHeader('Allow', 'OPTIONS, POST');
response.setHeader('Content-Length', '0');
response.setHeader(
"Access-Control-Allow-Headers",
typeof acrh === "string" ? acrh : "*"
@@ -102,11 +104,13 @@ function middleware(request, response) {
});
} else {
const body = `method ${request.method} not allowed`;
response.writeHead(405, {
Allow: "OPTIONS, POST",
'Content-Length': Buffer.byteLength(body),
"Cache-Control": "no-cache"
});
response.end(`method ${request.method} not allowed`);
response.end(body);
}
}

View File

@@ -1,6 +1,6 @@
Package.describe({
name: 'ecmascript',
version: '0.15.1',
version: '0.15.2-beta230.6',
summary: 'Compiler plugin that supports ES2015+ in all .js files',
documentation: 'README.md'
});

View File

@@ -2,9 +2,9 @@
"lockfileVersion": 1,
"dependencies": {
"nodemailer": {
"version": "6.4.6",
"resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.4.6.tgz",
"integrity": "sha512-/kJ+FYVEm2HuUlw87hjSqTss+GU35D4giOpdSfGp7DO+5h6RlJj7R94YaYHOkoxu1CSaM0d3WRBtCzwXrY6MKA=="
"version": "6.6.0",
"resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.6.0.tgz",
"integrity": "sha512-ikSMDU1nZqpo2WUPE0wTTw/NGGImTkwpJKDIFPZT+YvvR9Sj+ze5wzu95JHkBMglQLoG2ITxU21WukCC/XsFkg=="
},
"stream-buffers": {
"version": "3.0.2",

View File

@@ -42,7 +42,7 @@ Tinytest.add("email - fully customizable", function (test) {
test.equal(canonicalize(stream.getContentsAsString("utf8")),
"====== BEGIN MAIL #0 ======\n" +
devWarningBanner +
"Content-Type: text/plain\r\n" +
"Content-Type: text/plain; charset=utf-8\r\n" +
"X-Meteor-Test: a custom header\r\n" +
"Date: dummy\r\n" +
"From: foo@example.com\r\n" +
@@ -116,7 +116,7 @@ Tinytest.add("email - using mail composer", function (test) {
test.equal(canonicalize(stream.getContentsAsString("utf8")),
"====== BEGIN MAIL #0 ======\n" +
devWarningBanner +
"Content-Type: text/plain\r\n" +
"Content-Type: text/plain; charset=utf-8\r\n" +
"From: a@b.com\r\n" +
"Message-ID: <...>\r\n" +
"Content-Transfer-Encoding: 7bit\r\n" +
@@ -160,7 +160,7 @@ Tinytest.add("email - long lines", function (test) {
test.equal(canonicalize(stream.getContentsAsString("utf8")),
"====== BEGIN MAIL #0 ======\n" +
devWarningBanner +
"Content-Type: text/plain\r\n" +
"Content-Type: text/plain; charset=utf-8\r\n" +
"From: foo@example.com\r\n" +
"To: bar@example.com\r\n" +
"Subject: This is a very very very very very very very very " +
@@ -225,12 +225,12 @@ Tinytest.add("email - text and html", function (test) {
"MIME-Version: 1.0\r\n" +
"\r\n" +
"----...-Part_1\r\n" +
"Content-Type: text/plain\r\n" +
"Content-Type: text/plain; charset=utf-8\r\n" +
"Content-Transfer-Encoding: 7bit\r\n" +
"\r\n" +
"*Cool*, man\r\n" +
"----...-Part_1\r\n" +
"Content-Type: text/html\r\n" +
"Content-Type: text/html; charset=utf-8\r\n" +
"Content-Transfer-Encoding: 7bit\r\n" +
"\r\n" +
"<i>Cool</i>, man\r\n" +

Some files were not shown because too many files have changed in this diff Show More