mirror of
https://github.com/meteor/meteor.git
synced 2026-05-02 03:01:46 -04:00
Merge remote-tracking branch 'upstream/release-2.3' into unix_socket_group
This commit is contained in:
92
History.md
92
History.md
@@ -2,21 +2,19 @@
|
||||
|
||||
#### Highlights
|
||||
|
||||
* Node.js update to 14.17.0 from 12.22.1 :tada:
|
||||
* Node.js update to 14.17.0 from 12.22.1 🎉
|
||||
|
||||
* Typescript update to 4.2.4
|
||||
* Typescript update to [4.3.2](https://devblogs.microsoft.com/typescript/announcing-typescript-4-3/)
|
||||
|
||||
* New env variable `METEOR_TOOL_ENABLE_REIFY_RUNTIME_CACHE` to improve runtime performance on restarts.
|
||||
* Packages had their backward compatibility to before Meteor 1.0 removed. See bellow for more details.
|
||||
|
||||
* 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
|
||||
|
||||
### Breaking changes
|
||||
### 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.
|
||||
|
||||
### Migration steps
|
||||
|
||||
@@ -26,12 +24,37 @@
|
||||
#### Meteor Version Release
|
||||
|
||||
* `meteor-tool@2.3`
|
||||
- Node.js update to 14.17.0 from 12.22.1 :tada:
|
||||
- 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.
|
||||
- `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.13.17.
|
||||
- `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.
|
||||
- New env variable `METEOR_TOOL_ENABLE_REIFY_RUNTIME_CACHE` that improves restarts by caching reify data. This new cache should help with runtime performance when restarting server, but it is not yet ready for general use. By default it is disabled but you can enable it setting `true` in this env var. Learn more in the [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.
|
||||
@@ -46,6 +69,49 @@
|
||||
* `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
|
||||
|
||||
* `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
|
||||
|
||||
* `socket-stream-client@0.4.0`
|
||||
- Remove IE8 checks
|
||||
|
||||
#### Independent Releases
|
||||
|
||||
* `ddp-server@2.3.3`
|
||||
@@ -77,6 +143,12 @@
|
||||
|
||||
* `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.
|
||||
|
||||
## v2.2, 2021-04-15
|
||||
|
||||
|
||||
2
meteor
2
meteor
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
BUNDLE_VERSION=14.17.0.0
|
||||
BUNDLE_VERSION=14.17.0.3
|
||||
|
||||
# OS Check. Put here because here is where we download the precompiled
|
||||
# bundles that are arch specific.
|
||||
|
||||
@@ -168,7 +168,7 @@ export class AccountsCommon {
|
||||
* @param {Number} options.passwordEnrollTokenExpirationInDays The number of days from when a link to set initial password is sent until token expires and user can't set password with the link anymore. Defaults to 30.
|
||||
* @param {Number} options.passwordEnrollTokenExpiration The number of milliseconds from when a link to set initial password is sent until token expires and user can't set password with the link anymore. If `passwordEnrollTokenExpirationInDays` is set, it takes precedent.
|
||||
* @param {Boolean} options.ambiguousErrorMessages Return ambiguous error messages from login failures to prevent user enumeration. Defaults to false.
|
||||
* @param {MongoFieldSpecifier} options.defaultFieldSelector To exclude by default large custom fields from `Meteor.user()` and `Meteor.findUserBy...()` functions when called without a field selector, and all `onLogin`, `onLoginFailure` and `onLogout` callbacks. Example: `Accounts.config({ defaultFieldSelector: { myBigArray: 0 }})`.
|
||||
* @param {MongoFieldSpecifier} options.defaultFieldSelector To exclude by default large custom fields from `Meteor.user()` and `Meteor.findUserBy...()` functions when called without a field selector, and all `onLogin`, `onLoginFailure` and `onLogout` callbacks. Example: `Accounts.config({ defaultFieldSelector: { myBigArray: 0 }})`. Beware when using this. If, for instance, you do not include `email` when excluding the fields, you can have problems with functions like `forgotPassword` that will break because they won't have the required data available. It's recommend that you always keep the fields `_id`, `username`, and `email`.
|
||||
*/
|
||||
config(options) {
|
||||
// We don't want users to accidentally only call Accounts.config on the
|
||||
|
||||
@@ -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);
|
||||
@@ -1462,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 => {
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
Package.describe({
|
||||
summary: "A user account system",
|
||||
version: "1.9.0",
|
||||
version: "2.0.0-beta230.3",
|
||||
});
|
||||
|
||||
Package.onUse(api => {
|
||||
|
||||
@@ -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 => {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
Package.describe({
|
||||
summary: 'Login service for Github accounts',
|
||||
version: '1.4.3',
|
||||
version: '1.5.0-beta230.3',
|
||||
});
|
||||
|
||||
Package.onUse(api => {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
Package.describe({
|
||||
summary: "Login service for Google accounts",
|
||||
version: "1.3.3",
|
||||
version: "1.4.0-beta230.3",
|
||||
});
|
||||
|
||||
Package.onUse(api => {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
Package.describe({
|
||||
summary: 'Login service for Meetup accounts',
|
||||
version: '1.4.2',
|
||||
version: '1.5.0-beta230.3',
|
||||
});
|
||||
|
||||
Package.onUse(api => {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
Package.describe({
|
||||
summary: 'Login service for Meteor developer accounts',
|
||||
version: '1.4.2',
|
||||
version: '1.5.0-beta230.3',
|
||||
});
|
||||
|
||||
Package.onUse(api => {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
Package.describe({
|
||||
summary: "Common code for OAuth-based login services",
|
||||
version: "1.2.0",
|
||||
version: "1.3.0-beta230.3",
|
||||
});
|
||||
|
||||
Package.onUse(api => {
|
||||
|
||||
@@ -5,7 +5,7 @@ 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.3"
|
||||
});
|
||||
|
||||
Package.onUse(api => {
|
||||
@@ -13,7 +13,6 @@ Package.onUse(api => {
|
||||
|
||||
api.use([
|
||||
'accounts-base',
|
||||
'srp',
|
||||
'sha',
|
||||
'ejson',
|
||||
'ddp'
|
||||
@@ -33,7 +32,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']);
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -8,9 +8,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
|
||||
@@ -276,12 +274,10 @@ const userQueryValidator = Match.Where(user => {
|
||||
return true;
|
||||
});
|
||||
|
||||
const passwordValidator = Match.OneOf(
|
||||
Match.Where(str => Match.test(str, String) && str.length <= Meteor.settings?.packages?.accounts?.passwordMaxLength || 256), {
|
||||
digest: Match.Where(str => Match.test(str, String) && str.length === 64),
|
||||
algorithm: Match.OneOf('sha-256')
|
||||
}
|
||||
);
|
||||
const passwordValidator = {
|
||||
digest: Match.Where(str => Match.test(str, String) && str.length === 64),
|
||||
algorithm: Match.OneOf('sha-256')
|
||||
};
|
||||
|
||||
// Handler to login with a password.
|
||||
//
|
||||
@@ -298,7 +294,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 +312,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 +367,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 +383,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 +426,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 +438,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)}
|
||||
@@ -646,15 +524,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 +713,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 +758,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 +772,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 +1160,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 });
|
||||
|
||||
@@ -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,14 +1343,14 @@ 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/);
|
||||
});
|
||||
@@ -1562,7 +1359,7 @@ if (Meteor.isServer) (() => {
|
||||
'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 +1372,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 +1412,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 +1447,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 +1484,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 +1719,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);
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
Package.describe({
|
||||
summary: "Login service for Twitter accounts",
|
||||
version: "1.4.2",
|
||||
version: "1.5.0-beta230.3",
|
||||
});
|
||||
|
||||
Package.onUse(api => {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
Package.describe({
|
||||
summary: "Unstyled version of login widgets",
|
||||
version: "1.4.3"
|
||||
version: "1.5.0-beta230.3"
|
||||
});
|
||||
|
||||
Package.onUse(function (api) {
|
||||
|
||||
@@ -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.3",
|
||||
});
|
||||
|
||||
Package.onUse(api => {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
Package.describe({
|
||||
summary: "Login service for Sina Weibo accounts",
|
||||
version: "1.3.2",
|
||||
version: "1.4.0-beta230.3",
|
||||
});
|
||||
|
||||
Package.onUse(api => {
|
||||
|
||||
@@ -54,9 +54,9 @@
|
||||
"integrity": "sha512-JIB2+XJrb7v3zceV2XzDhGIB902CmKGSpSl4q2C6agU9SNLG/2V1RtFRGPG1Ajh9STj3+q6zJMOC+N/pp2P9DA=="
|
||||
},
|
||||
"@babel/helper-define-polyfill-provider": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.2.0.tgz",
|
||||
"integrity": "sha512-JT8tHuFjKBo8NnaUbblz7mIu1nnvUDiHVjXXkulZULyidvo/7P6TY7+YqpV37IfF+KUFxmlK04elKtGKXaiVgw=="
|
||||
"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",
|
||||
@@ -389,9 +389,9 @@
|
||||
"integrity": "sha512-SdjAG/3DikRHpUOjxZgnkbR11xUlyDMUFJdvnIgZEE16mqmY0BINMmc4//JMJglEmn6i7sq6p+mGrFWyZ98EEw=="
|
||||
},
|
||||
"@meteorjs/babel": {
|
||||
"version": "7.11.0",
|
||||
"resolved": "https://registry.npmjs.org/@meteorjs/babel/-/babel-7.11.0.tgz",
|
||||
"integrity": "sha512-/6qog7HOFSCs42/5Svw4VbchZ4B83E7hRwjP1mDPahHqDYer3rFAipYpI6ViM/RwZSeo4MHspHUJYkENYz+JLw=="
|
||||
"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",
|
||||
@@ -504,19 +504,19 @@
|
||||
"integrity": "sha1-G8bxW4f3qxCF1CszC3F2V6IVZQA="
|
||||
},
|
||||
"babel-plugin-polyfill-corejs2": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.2.0.tgz",
|
||||
"integrity": "sha512-9bNwiR0dS881c5SHnzCmmGlMkJLl0OUZvxrxHo9w/iNoRuqaPjqlvBf4HrovXtQs/au5yKkpcdgfT1cC5PAZwg=="
|
||||
"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.2.0",
|
||||
"resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.2.0.tgz",
|
||||
"integrity": "sha512-zZyi7p3BCUyzNxLx8KV61zTINkkV65zVkDAFNZmrTCRVhjo1jAS+YLvDJ9Jgd/w2tsAviCwFHReYfxO3Iql8Yg=="
|
||||
"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.2.0",
|
||||
"resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.2.0.tgz",
|
||||
"integrity": "sha512-J7vKbCuD2Xi/eEHxquHN14bXAW9CXtecwuLrOIDJtcZzTaPzV1VdEfoUf9AzcRBMolKUQKM9/GVojeh0hFiqMg=="
|
||||
"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",
|
||||
@@ -594,9 +594,9 @@
|
||||
"integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA=="
|
||||
},
|
||||
"caniuse-lite": {
|
||||
"version": "1.0.30001228",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001228.tgz",
|
||||
"integrity": "sha512-QQmLOGJ3DEgokHbMSA8cj2a+geXqmnpyOFT0lhQV6P3/YOJvGDEwoedcwxEQ30gJIwIIunHIicunJ2rzK5gB2A=="
|
||||
"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",
|
||||
@@ -624,9 +624,9 @@
|
||||
"integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA=="
|
||||
},
|
||||
"core-js-compat": {
|
||||
"version": "3.12.1",
|
||||
"resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.12.1.tgz",
|
||||
"integrity": "sha512-i6h5qODpw6EsHAoIdQhKoZdWn+dGBF3dSS8m5tif36RlWvW3A6+yu2S16QHUo3CrkzrnEskMAt9f8FxmY9fhWQ==",
|
||||
"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",
|
||||
@@ -646,9 +646,9 @@
|
||||
"integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ=="
|
||||
},
|
||||
"electron-to-chromium": {
|
||||
"version": "1.3.734",
|
||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.734.tgz",
|
||||
"integrity": "sha512-iQF2mjPZ6zNNq45kbJ6MYZYCBNdv2JpGiJC/lVx4tGJWi9MNg73KkL9sWGN4X4I/CP2SBLWsT8nPADZZpAHIyw=="
|
||||
"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",
|
||||
@@ -766,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",
|
||||
@@ -860,9 +860,9 @@
|
||||
"integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4="
|
||||
},
|
||||
"typescript": {
|
||||
"version": "4.2.4",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.2.4.tgz",
|
||||
"integrity": "sha512-V+evlYHZnQkaz8TRBuxTA92yZBPotr5H+WhQ7bD3hZUndx5tGOa1fuCgeSjxAzM1RiN5IzvadIXTVefuuwZCRg=="
|
||||
"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",
|
||||
|
||||
@@ -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.2-beta230.0'
|
||||
version: '7.6.2-beta230.3'
|
||||
});
|
||||
|
||||
Npm.depends({
|
||||
'@meteorjs/babel': '7.11.0',
|
||||
'@meteorjs/babel': '7.11.1',
|
||||
'json5': '2.1.1'
|
||||
});
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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';
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
Package.describe({
|
||||
summary: "Meteor's latency-compensated distributed data client",
|
||||
version: '2.4.1',
|
||||
version: '2.5.0-beta230.3',
|
||||
documentation: null
|
||||
});
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
Package.describe({
|
||||
name: 'ddp-rate-limiter',
|
||||
version: '1.0.9',
|
||||
version: '1.1.0-beta230.3',
|
||||
// Brief, one-line summary of the package.
|
||||
summary: 'The DDPRateLimiter allows users to add rate limits to DDP' +
|
||||
' methods and subscriptions.',
|
||||
|
||||
@@ -119,7 +119,7 @@ var SessionCollectionView = function (collectionName, sessionCallbacks) {
|
||||
DDPServer._SessionCollectionView = SessionCollectionView;
|
||||
|
||||
|
||||
_.extend(SessionCollectionView.prototype, {
|
||||
Object.assign(SessionCollectionView.prototype, {
|
||||
|
||||
isEmpty: function () {
|
||||
var self = this;
|
||||
@@ -324,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;
|
||||
@@ -1045,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.
|
||||
@@ -1438,7 +1438,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.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
Package.describe({
|
||||
summary: "Meteor's latency-compensated distributed data server",
|
||||
version: '2.4.0-beta230.0',
|
||||
version: '2.4.0-beta230.3',
|
||||
documentation: null
|
||||
});
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
3
packages/deprecated/d3/package.js
vendored
3
packages/deprecated/d3/package.js
vendored
@@ -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) {
|
||||
|
||||
@@ -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) {
|
||||
@@ -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) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
Package.describe({
|
||||
summary: "Deprecated",
|
||||
version: '1.0.7'
|
||||
version: '1.0.7',
|
||||
deprecated: true
|
||||
});
|
||||
|
||||
Package.onUse(function (api) {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
Package.describe({
|
||||
summary: "Make HTTP calls to remote servers",
|
||||
version: '1.4.4',
|
||||
deprecated: 'Please use fetch'
|
||||
deprecated: 'Migrate to fetch when possible'
|
||||
});
|
||||
|
||||
Npm.depends({
|
||||
|
||||
@@ -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) {
|
||||
|
||||
3
packages/deprecated/jquery-layout/package.js
vendored
3
packages/deprecated/jquery-layout/package.js
vendored
@@ -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) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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) {
|
||||
@@ -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)
|
||||
|
||||
@@ -2,15 +2,14 @@
|
||||
|
||||
Package.describe({
|
||||
summary: "Markdown-to-HTML processor",
|
||||
version: "1.0.14"
|
||||
version: "2.0.0-beta230.3",
|
||||
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) {
|
||||
|
||||
@@ -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');
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { Showdown } from './showdown';
|
||||
|
||||
if (Package.templating) {
|
||||
var Template = Package.templating.Template;
|
||||
var Blaze = Package.blaze.Blaze; // implied by `templating`
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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) {
|
||||
@@ -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) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
Package.describe({
|
||||
summary: 'Expressive, dynamic, robust CSS',
|
||||
version: "2.513.15"
|
||||
version: "2.513.15",
|
||||
deprecated: true
|
||||
});
|
||||
|
||||
Package.registerBuildPlugin({
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
Package.describe({
|
||||
name: "dynamic-import",
|
||||
version: "0.7.0-beta230.0",
|
||||
version: "0.7.0-beta230.3",
|
||||
summary: "Runtime support for Meteor 1.5 dynamic import(...) syntax",
|
||||
documentation: "README.md"
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
Package.describe({
|
||||
name: 'ecmascript',
|
||||
version: '0.15.1',
|
||||
version: '0.15.2-beta230.3',
|
||||
summary: 'Compiler plugin that supports ES2015+ in all .js files',
|
||||
documentation: 'README.md'
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
Package.describe({
|
||||
summary: "Send email messages",
|
||||
version: "2.1.0-beta230.0"
|
||||
version: "2.1.0-beta230.3"
|
||||
});
|
||||
|
||||
Npm.depends({
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
Package.describe({
|
||||
summary: "Facebook OAuth flow",
|
||||
version: "1.8.0"
|
||||
version: "1.9.0-beta230.3"
|
||||
});
|
||||
|
||||
Package.onUse(api => {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
Package.describe({
|
||||
name: 'hot-module-replacement',
|
||||
version: '0.3.0-beta230.0',
|
||||
version: '0.3.0-beta230.3',
|
||||
summary: 'Update code in development without reloading the page',
|
||||
documentation: 'README.md',
|
||||
debugOnly: true
|
||||
|
||||
@@ -6,7 +6,7 @@ Package.describe({
|
||||
// between such packages and the build tool.
|
||||
name: 'launch-screen',
|
||||
summary: 'Default and customizable launch screen on mobile.',
|
||||
version: '1.3.0-beta230.0'
|
||||
version: '1.3.0-beta230.3'
|
||||
});
|
||||
|
||||
Cordova.depends({
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
Package.describe({
|
||||
summary: "General satisfiability solver for logic problems",
|
||||
version: '2.0.7'
|
||||
version: '2.0.8-beta230.3'
|
||||
});
|
||||
|
||||
Package.on_use(function (api) {
|
||||
Package.onUse(function (api) {
|
||||
api.export('Logic');
|
||||
api.use('underscore');
|
||||
api.add_files(['minisat.js',
|
||||
api.addFiles(['minisat.js',
|
||||
'minisat_wrapper.js',
|
||||
'types.js',
|
||||
'logic.js',
|
||||
'optimize.js']);
|
||||
});
|
||||
|
||||
Package.on_test(function (api) {
|
||||
Package.onTest(function (api) {
|
||||
api.use(['tinytest', 'check', 'underscore']);
|
||||
api.use('logic-solver');
|
||||
|
||||
@@ -21,5 +21,5 @@ Package.on_test(function (api) {
|
||||
// ones like IE 8, so we have to exclude it from our automated
|
||||
// testing. It needs a browser released in the last year (say) so
|
||||
// that Emscripten-compiled code runs reasonably.
|
||||
api.add_files('logic_tests.js', 'server');
|
||||
api.addFiles('logic_tests.js', 'server');
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
Package.describe({
|
||||
name: 'meteor-base',
|
||||
version: '1.4.0',
|
||||
version: '1.5.0-beta230.3',
|
||||
// Brief, one-line summary of the package.
|
||||
summary: 'Packages that every Meteor app needs',
|
||||
// By default, Meteor will default to using README.md for documentation.
|
||||
@@ -20,7 +20,6 @@ Package.onUse(function(api) {
|
||||
|
||||
// The protocol and client/server libraries that Meteor uses to send data
|
||||
'ddp',
|
||||
'livedata', // XXX COMPAT WITH PACKAGES BUILT FOR 0.9.0.
|
||||
|
||||
// This package uses the user agent of each incoming HTTP request to
|
||||
// decide whether to inject <script> tags into the <head> of the
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
Package.describe({
|
||||
summary: "The Meteor command-line tool",
|
||||
version: '2.3.0-beta.0'
|
||||
version: '2.3.0-beta.3'
|
||||
});
|
||||
|
||||
Package.includeTool();
|
||||
|
||||
@@ -345,12 +345,6 @@ export default class Cursor {
|
||||
return handle;
|
||||
}
|
||||
|
||||
// Since we don't actually have a "nextObject" interface, there's really no
|
||||
// reason to have a "rewind" interface. All it did was make multiple calls
|
||||
// to fetch/map/forEach return nothing the second time.
|
||||
// XXX COMPAT WITH 0.8.1
|
||||
rewind() {}
|
||||
|
||||
// XXX Maybe we need a version of observe that just calls a callback if
|
||||
// anything changed.
|
||||
_depend(changers, _allow_unordered) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
Package.describe({
|
||||
summary: "Meteor's client-side datastore: a port of MongoDB to Javascript",
|
||||
version: '1.6.2'
|
||||
version: '1.7.0-beta230.3'
|
||||
});
|
||||
|
||||
Package.onUse(api => {
|
||||
|
||||
@@ -922,13 +922,6 @@ _.each(['forEach', 'map', 'fetch', 'count', Symbol.iterator], function (method)
|
||||
};
|
||||
});
|
||||
|
||||
// Since we don't actually have a "nextObject" interface, there's really no
|
||||
// reason to have a "rewind" interface. All it did was make multiple calls
|
||||
// to fetch/map/forEach return nothing the second time.
|
||||
// XXX COMPAT WITH 0.8.1
|
||||
Cursor.prototype.rewind = function () {
|
||||
};
|
||||
|
||||
Cursor.prototype.getTransform = function () {
|
||||
return this._cursorDescription.options.transform;
|
||||
};
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
Package.describe({
|
||||
summary: "Adaptor for using MongoDB and Minimongo over DDP",
|
||||
version: '1.11.1'
|
||||
version: '1.12.0-beta230.3'
|
||||
});
|
||||
|
||||
Npm.depends({
|
||||
|
||||
Submodule packages/non-core/blaze updated: 5910ff535c...a055a060d5
@@ -1,5 +1,9 @@
|
||||
## Changelog
|
||||
|
||||
## 2.0.0
|
||||
### Breaking changes
|
||||
- Removed compatibility code for before Meteor v1
|
||||
|
||||
## 1.3.2 - 2020-09-30
|
||||
### Breaking changes
|
||||
- N/A
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
// XXX COMPAT WITH 0.8.0
|
||||
|
||||
Oauth = OAuth;
|
||||
@@ -126,16 +126,6 @@ OAuth.launchLogin = options => {
|
||||
}
|
||||
};
|
||||
|
||||
// XXX COMPAT WITH 0.7.0.1
|
||||
// Private interface but probably used by many oauth clients in atmosphere.
|
||||
OAuth.initiateLogin = (credentialToken, url, callback, dimensions) => {
|
||||
OAuth.showPopup(
|
||||
url,
|
||||
callback.bind(null, credentialToken),
|
||||
dimensions
|
||||
);
|
||||
};
|
||||
|
||||
// Called by the popup when the OAuth flow is completed, right before
|
||||
// the popup closes.
|
||||
OAuth._handleCredentialSecret = (credentialToken, secret) => {
|
||||
|
||||
@@ -1,15 +1,6 @@
|
||||
OAuth._storageTokenPrefix = "Meteor.oauth.credentialSecret-";
|
||||
|
||||
OAuth._redirectUri = (serviceName, config, params, absoluteUrlOptions) => {
|
||||
// XXX COMPAT WITH 0.9.0
|
||||
// The redirect URI used to have a "?close" query argument. We
|
||||
// detect whether we need to be backwards compatible by checking for
|
||||
// the absence of the `loginStyle` field, which wasn't used in the
|
||||
// code which had the "?close" argument.
|
||||
// This logic is duplicated in the tool so that the tool can do OAuth
|
||||
// flow with <= 0.9.0 servers (tools/auth.js).
|
||||
const query = config.loginStyle ? null : "close";
|
||||
|
||||
// Clone because we're going to mutate 'params'. The 'cordova' and
|
||||
// 'android' parameters are only used for picking the host of the
|
||||
// redirect URL, and not actually included in the redirect URL itself.
|
||||
@@ -55,6 +46,6 @@ OAuth._redirectUri = (serviceName, config, params, absoluteUrlOptions) => {
|
||||
|
||||
return URL._constructUrl(
|
||||
Meteor.absoluteUrl(`_oauth/${serviceName}`, absoluteUrlOptions),
|
||||
query,
|
||||
null,
|
||||
params);
|
||||
};
|
||||
|
||||
@@ -1,25 +1,17 @@
|
||||
Package.describe({
|
||||
summary: "Common code for OAuth-based services",
|
||||
version: "1.3.2"
|
||||
version: "2.0.0-beta230.3"
|
||||
});
|
||||
|
||||
Package.onUse(api => {
|
||||
api.use('check');
|
||||
api.use('ecmascript');
|
||||
api.use(['check', 'ecmascript', 'localstorage', 'url']);
|
||||
|
||||
api.use('routepolicy', 'server');
|
||||
api.use('webapp', 'server');
|
||||
api.use('mongo', 'server');
|
||||
api.use(['routepolicy', 'webapp', 'mongo', 'service-configuration', 'logging'], 'server');
|
||||
|
||||
api.use('reload', 'client');
|
||||
api.use('base64', 'client');
|
||||
|
||||
api.use(['service-configuration', 'logging'], 'server');
|
||||
api.use(['reload', 'base64'], 'client');
|
||||
|
||||
api.use('oauth-encryption', 'server', {weak: true});
|
||||
|
||||
api.use('localstorage');
|
||||
api.use('url');
|
||||
|
||||
api.export('OAuth');
|
||||
api.export('OAuthTest', 'server', {testOnly: true});
|
||||
@@ -41,10 +33,6 @@ Package.onUse(api => {
|
||||
], 'client');
|
||||
|
||||
api.addFiles('oauth_common.js');
|
||||
|
||||
// XXX COMPAT WITH 0.8.0
|
||||
api.export('Oauth');
|
||||
api.addFiles('deprecated.js', ['client', 'server']);
|
||||
});
|
||||
|
||||
Npm.depends({
|
||||
|
||||
@@ -40,7 +40,7 @@ const testPendingCredential = (test, method) => {
|
||||
}));
|
||||
|
||||
// simulate logging in using twitterfoo
|
||||
Oauth._storeRequestToken(credentialToken, twitterfooAccessToken);
|
||||
OAuth._storeRequestToken(credentialToken, twitterfooAccessToken);
|
||||
|
||||
const req = {
|
||||
method,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
Package.describe({
|
||||
name: "promise",
|
||||
version: "0.12.0-beta230.0",
|
||||
version: "0.12.0-beta230.3",
|
||||
summary: "ECMAScript 2015 Promise polyfill with Fiber support",
|
||||
git: "https://github.com/meteor/promise",
|
||||
documentation: "README.md"
|
||||
|
||||
@@ -17,9 +17,9 @@
|
||||
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="
|
||||
},
|
||||
"magic-string": {
|
||||
"version": "0.21.3",
|
||||
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.21.3.tgz",
|
||||
"integrity": "sha1-h+IBAJ6/3m9G3FdXMFpwr3HjFiQ="
|
||||
"version": "0.25.7",
|
||||
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.7.tgz",
|
||||
"integrity": "sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA=="
|
||||
},
|
||||
"ms": {
|
||||
"version": "2.0.0",
|
||||
@@ -27,29 +27,29 @@
|
||||
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
|
||||
},
|
||||
"parse5": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/parse5/-/parse5-3.0.2.tgz",
|
||||
"integrity": "sha1-Be/1fw70V3+xRKefi5qWemzERRA="
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/parse5/-/parse5-4.0.0.tgz",
|
||||
"integrity": "sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA=="
|
||||
},
|
||||
"promise-polyfill": {
|
||||
"version": "1.1.6",
|
||||
"resolved": "https://registry.npmjs.org/promise-polyfill/-/promise-polyfill-1.1.6.tgz",
|
||||
"integrity": "sha1-zQTv9G9clcOn0EVZHXm14+AfEtc="
|
||||
},
|
||||
"sourcemap-codec": {
|
||||
"version": "1.4.8",
|
||||
"resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz",
|
||||
"integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA=="
|
||||
},
|
||||
"stream-length": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/stream-length/-/stream-length-1.0.2.tgz",
|
||||
"integrity": "sha1-gnfzy+5JpNqrz9tOL0qbXp8snwA="
|
||||
},
|
||||
"stream-to-string": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/stream-to-string/-/stream-to-string-1.1.0.tgz",
|
||||
"integrity": "sha1-OSELATF+ars16FRTjgEwN7ajWUA="
|
||||
},
|
||||
"vlq": {
|
||||
"version": "0.2.3",
|
||||
"resolved": "https://registry.npmjs.org/vlq/-/vlq-0.2.3.tgz",
|
||||
"integrity": "sha512-DRibZL6DsNhIgYQ+wNdWDL2SL3bKPlVrRiBqV5yuMm++op8W4kGFtaQfCs4KEJn0wBZcHVHJ3eoywX8983k1ow=="
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/stream-to-string/-/stream-to-string-1.2.0.tgz",
|
||||
"integrity": "sha512-8drZlFIKBHSMdX9GCWv8V9AAWnQcTqw0iAI6/GC7UJ0H0SwKeFKjOoZfGY1tOU00GGU7FYZQoJ/ZCUEoXhD7yQ=="
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
Package.describe({
|
||||
name: "server-render",
|
||||
version: "0.3.1",
|
||||
version: "0.4.0-beta230.3",
|
||||
summary: "Generic support for server-side rendering in Meteor apps",
|
||||
documentation: "README.md"
|
||||
});
|
||||
|
||||
Npm.depends({
|
||||
"combined-stream2": "1.1.2",
|
||||
"magic-string": "0.21.3",
|
||||
"stream-to-string": "1.1.0",
|
||||
"parse5": "3.0.2"
|
||||
"magic-string": "0.25.7",
|
||||
"stream-to-string": "1.2.0",
|
||||
"parse5": "4.0.0"
|
||||
});
|
||||
|
||||
Package.onUse(function(api) {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user