Remove deprecated code from before v1.0

Remove deprecated code from before Meteor 1.0 that  was documented via XXX COMPAT in comments. Move deprecated packages into the deprecated folder (deps, livedata, srp).
This commit is contained in:
Jan Dvorak
2020-10-28 20:14:17 +01:00
parent 5761e73394
commit b5b7306bed
34 changed files with 20 additions and 407 deletions

View File

@@ -569,62 +569,6 @@ export class AccountsServer extends AccountsCommon {
this.setUserId(null);
};
// Delete all the current user's tokens and close all open connections logged
// in as this user. Returns a fresh new login token that this client can
// use. Tests set Accounts._noConnectionCloseDelayForTest to delete tokens
// immediately instead of using a delay.
//
// XXX COMPAT WITH 0.7.2
// This single `logoutOtherClients` method has been replaced with two
// methods, one that you call to get a new token, and another that you
// call to remove all tokens except your own. The new design allows
// clients to know when other clients have actually been logged
// out. (The `logoutOtherClients` method guarantees the caller that
// the other clients will be logged out at some point, but makes no
// guarantees about when.) This method is left in for backwards
// compatibility, especially since application code might be calling
// this method directly.
//
// @returns {Object} Object with token and tokenExpires keys.
methods.logoutOtherClients = function () {
const user = accounts.users.findOne(this.userId, {
fields: {
"services.resume.loginTokens": true
}
});
if (user) {
// Save the current tokens in the database to be deleted in
// CONNECTION_CLOSE_DELAY_MS ms. This gives other connections in the
// caller's browser time to find the fresh token in localStorage. We save
// the tokens in the database in case we crash before actually deleting
// them.
const tokens = user.services.resume.loginTokens;
const newToken = accounts._generateStampedLoginToken();
accounts.users.update(this.userId, {
$set: {
"services.resume.loginTokensToDelete": tokens,
"services.resume.haveLoginTokensToDelete": true
},
$push: { "services.resume.loginTokens": accounts._hashStampedToken(newToken) }
});
Meteor.setTimeout(() => {
// The observe on Meteor.users will take care of closing the connections
// associated with `tokens`.
accounts._deleteSavedTokensForUser(this.userId, tokens);
}, accounts._noConnectionCloseDelayForTest ? 0 :
CONNECTION_CLOSE_DELAY_MS);
// We do not set the login token on this connection, but instead the
// observe closes the connection and the client will reconnect with the
// new token.
return {
token: newToken.token,
tokenExpires: accounts._tokenExpiration(newToken.when)
};
} else {
throw new Meteor.Error("You are not logged in.");
}
};
// Generates a new login token with the same expiration as the
// connection's current token and saves it to the database. Associates
// the connection with this new token and returns it. Throws an error

View File

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

View File

@@ -351,79 +351,6 @@ Accounts.registerLoginHandler("password", options => {
);
});
// 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
///
@@ -470,12 +397,6 @@ Accounts.setUsername = (userId, newUsername) => {
// 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
@@ -497,18 +418,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;
@@ -557,7 +470,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)}

View File

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

View File

@@ -1621,15 +1621,6 @@ export class Connection {
this._heartbeat.messageReceived();
}
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))
Meteor._debug('discarding invalid livedata message', msg);
return;
}
if (msg.msg === 'connected') {
this._version = this._versionSuggestion;
this._livedata_connected(msg);

View File

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

View File

@@ -119,16 +119,9 @@ 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"}));
// call all our callbacks when we get a new socket. they will do the
// work of setting up handlers and such for specific messages.
_.each(self.registration_callbacks, function (callback) {
self.registration_callbacks.forEach((callback) => {
callback(socket);
});
});

View File

@@ -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

View File

@@ -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) {

View File

@@ -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;
};

View File

@@ -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

View File

@@ -1,3 +0,0 @@
// XXX COMPAT WITH 0.8.0
Oauth = OAuth;

View File

@@ -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) => {

View File

@@ -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);
};

View File

@@ -1,25 +1,17 @@
Package.describe({
summary: "Common code for OAuth-based services",
version: "1.3.2"
version: "2.0.0"
});
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({

View File

@@ -70,8 +70,7 @@ var showInvalidArchMsg = function (arch) {
export function parseServerOptionsForRunCommand(options, runTargets) {
const parsedServerUrl = parsePortOption(options.port);
// XXX COMPAT WITH 0.9.2.2 -- the 'mobile-port' option is deprecated
const mobileServerOption = options['mobile-server'] || options['mobile-port'];
const mobileServerOption = options['mobile-server'];
let parsedMobileServerUrl;
if (mobileServerOption) {
parsedMobileServerUrl = parseMobileServerOption(mobileServerOption);
@@ -308,8 +307,6 @@ var runCommandOptions = {
port: { type: String, short: "p", default: DEFAULT_PORT },
'mobile-server': { type: String },
'cordova-server-port': { type: String },
// XXX COMPAT WITH 0.9.2.2
'mobile-port': { type: String },
'app-port': { type: String },
'debug-port': { type: String },
...inspectOptions,
@@ -927,8 +924,6 @@ var buildCommands = {
'mobile-settings': { type: String },
server: { type: String },
"cordova-server-port": { type: String },
// XXX COMPAT WITH 0.9.2.2
"mobile-port": { type: String },
// Indicates whether these build is running headless, e.g. in a
// continuous integration building environment, where visual niceties
// like progress bars and spinners are unimportant.
@@ -949,32 +944,6 @@ main.registerCommand({
);
});
// Deprecated -- identical functionality to 'build' with one exception: it
// doesn't output a directory with all builds but rather only one tarball with
// server/client programs.
// XXX COMPAT WITH 0.9.1.1
main.registerCommand({
name: "bundle",
hidden: true,
...buildCommands,
}, async function (options) {
Console.error(
"This command has been deprecated in favor of " +
Console.command("'meteor build'") + ", which allows you to " +
"build for multiple platforms and outputs a directory instead of " +
"a single tarball. See " + Console.command("'meteor help build'") + " " +
"for more information.");
Console.error();
return Profile.run(
"meteor bundle",
() => Promise.await(buildCommand({
...options,
_bundleOnly: true,
}))
);
});
var buildCommand = function (options) {
Console.setVerbose(!!options.verbose);
if (options.headless) {
@@ -1036,8 +1005,7 @@ on an OS X system.");
}
if (!_.isEmpty(cordovaPlatforms)) {
// XXX COMPAT WITH 0.9.2.2 -- the --mobile-port option is deprecated
const mobileServerOption = options.server || options["mobile-port"];
const mobileServerOption = options.server;
if (!mobileServerOption) {
// For Cordova builds, require '--server'.
// XXX better error message?
@@ -1605,8 +1573,6 @@ testCommandOptions = {
port: { type: String, short: "p", default: DEFAULT_PORT },
'mobile-server': { type: String },
'cordova-server-port': { type: String },
// XXX COMPAT WITH 0.9.2.2
'mobile-port': { type: String },
'debug-port': { type: String },
...inspectOptions,
'no-release-check': { type: Boolean },

View File

@@ -215,16 +215,6 @@ export function getToolsVersion() {
parsed = JSON.parse(readFile(isopackJsonPath))["isopack-1"];
return parsed.name + '@' + parsed.version;
}
// XXX COMPAT WITH 0.9.3
const unipackageJsonPath = pathJoin(
getCurrentToolsDir(),
'..', // get out of tool, back to package
'unipackage.json'
);
parsed = JSON.parse(readFile(unipackageJsonPath));
return parsed.name + '@' + parsed.version;
} else {
throw new Error("Unexpected. Git checkouts don't have tools versions.");
}

View File

@@ -700,12 +700,7 @@ class ResourceSlot {
}
_isBare(options) {
return !! (
this._getOption("bare", options) ||
// XXX eventually get rid of backwards-compatible "raw" name
// XXX COMPAT WITH 0.6.4
this._getOption("raw", options)
);
return !! this._getOption("bare", options);
}
hmrAvailable() {

View File

@@ -124,7 +124,7 @@ var Isopack = function () {
self.lintingMessages = null;
};
Isopack.knownFormats = ["unipackage-pre2", "isopack-1", "isopack-2"];
Isopack.knownFormats = ["isopack-1", "isopack-2"];
// These functions are designed to convert isopack metadata between
// versions. They were designed to convert between unipackage-pre2 and
@@ -137,12 +137,6 @@ Isopack.knownFormats = ["unipackage-pre2", "isopack-1", "isopack-2"];
// they were before.
Isopack.convertOneStepForward = function (data, fromFormat) {
var convertedData = _.clone(data);
// XXX COMPAT WITH 0.9.3
if (fromFormat === "unipackage-pre2") {
convertedData.builds = convertedData.unibuilds;
delete convertedData.unibuilds;
return convertedData;
}
if (fromFormat === "isopack-1") {
// For now, there's no difference in this direction at the isopack level.
return convertedData;
@@ -215,27 +209,6 @@ Isopack.readMetadataFromDirectory =
throw new Error("Could not find isopack data supported any supported format (isopack-1 or isopack-2).\n" +
"This isopack was likely built with a much newer version of Meteor.");
}
} else if (files.exists(unipackageJsonPath)) {
// super old version with different file name
// XXX COMPAT WITH 0.9.3
if (files.exists(unipackageJsonPath)) {
metadata = JSON.parse(files.readFile(unipackageJsonPath));
metadata = Isopack.convertIsopackFormat(metadata,
"unipackage-pre2", "isopack-2");
originalVersion = 'unipackage-pre2';
}
if (metadata.format !== "unipackage-pre2") {
// We don't support pre-0.9.0 isopacks, but we do know enough to delete
// them if we find them in an isopack cache somehow (rather than crash).
if (metadata.format === "unipackage-pre1") {
throw new exports.OldIsopackFormatError();
}
throw new Error("Unsupported isopack format: " +
JSON.stringify(metadata.format));
}
}
return {metadata, originalVersion};
@@ -1060,9 +1033,6 @@ _.extend(Isopack.prototype, {
};
}
// XXX COMPAT WITH 0.9.3
builder.reserve("unipackage.json");
builder.reserve("isopack.json");
// Reserve this even if includeIsopackBuildInfo is not set, to ensure
// nothing else writes it somehow.
@@ -1347,16 +1317,6 @@ _.extend(Isopack.prototype, {
delete unibuildJson.declaredExports;
builder.writeJson(legacyFilename, unibuildJson);
});
// old unipackage.json format/filename. no point to save this if
// we can't even support isopack-1.
// XXX COMPAT WITH 0.9.3
builder.writeJson(
"unipackage.json",
Isopack.convertIsopackFormat(
// Note that mainLegacyJson is isopack-1 (has no "source" resources)
// rather than isopack-2.
mainLegacyJson, "isopack-1", "unipackage-pre2"));
}
var isopackJson = {};

View File

@@ -622,6 +622,3 @@ export class PackageAPI {
});
}
}
// XXX COMPAT WITH 0.8.x
PackageAPI.prototype.add_files = PackageAPI.prototype.addFiles;

View File

@@ -81,11 +81,4 @@ selftest.define("cordova builds with server options", ["cordova"], function () {
run.expectExit(0);
checkMobileServer(s, "https://example.com/");
cleanUpBuild(s);
// XXX COMPAT WITH 0.9.2.2
run = s.run("build", relBuildDir, "--mobile-port", "example.com:5000");
run.waitSecs(90);
run.expectExit(0);
checkMobileServer(s, "http://example.com:5000/");
cleanUpBuild(s);
});