Purge the awful refreshAccount logic

User.prototype.refreshAccount was responsible for multiple race
condition bugs as well as inefficient duplication of DB queries in an
attempt to correct such race conditions.

It has now been replaced by a more reasonable model:

  * Global user account information and aliases are fetched in parallel
    on socket connection
  * Channel rank is fetched when the user tries to join a channel
This commit is contained in:
Calvin Montgomery 2016-10-03 23:12:22 -07:00
parent 014eb28e0d
commit 99760b6989
7 changed files with 132 additions and 232 deletions

View file

@ -30,21 +30,15 @@ AccessControlModule.prototype.onUserPreJoin = function (user, data, cb) {
} else {
user.socket.emit("needPassword", typeof data.pw !== "undefined");
/* Option 1: log in as a moderator */
user.waitFlag(Flags.U_LOGGED_IN, function () {
user.channel = chan;
user.refreshAccount(function (err, account) {
/* Already joined the channel by some other condition */
if (user.is(Flags.U_IN_CHANNEL)) {
return;
} else if (user.channel === chan) {
user.channel = null;
}
user.waitFlag(Flags.U_HAS_CHANNEL_RANK, function () {
if (user.is(Flags.U_IN_CHANNEL)) {
return;
}
if (account.effectiveRank >= 2) {
cb(null, ChannelModule.PASSTHROUGH);
user.socket.emit("cancelNeedPassword");
}
});
if (user.account.effectiveRank >= 2) {
cb(null, ChannelModule.PASSTHROUGH);
user.socket.emit("cancelNeedPassword");
}
});
/* Option 2: Enter correct password */

View file

@ -329,41 +329,33 @@ Channel.prototype.joinUser = function (user, data) {
}
user.channel = self;
if (self.is(Flags.C_REGISTERED)) {
user.refreshAccount(function (err, account) {
if (err) {
Logger.errlog.log("user.refreshAccount failed at Channel.joinUser");
Logger.errlog.log(err.stack);
self.refCounter.unref("Channel::user");
return;
user.waitFlag(Flags.U_LOGGED_IN, () => {
db.channels.getRank(self.name, user.getName(), (error, rank) => {
if (!error) {
user.setChannelRank(rank);
user.setFlag(Flags.U_HAS_CHANNEL_RANK);
}
afterAccount();
});
} else {
afterAccount();
});
if (user.socket.disconnected) {
self.refCounter.unref("Channel::user");
return;
} else if (self.dead) {
return;
}
function afterAccount() {
if (user.socket.disconnected) {
self.checkModules("onUserPreJoin", [user, data], function (err, result) {
if (result === ChannelModule.PASSTHROUGH) {
user.channel = self;
self.acceptUser(user);
} else {
user.channel = null;
user.account.channelRank = 0;
user.account.effectiveRank = user.account.globalRank;
self.refCounter.unref("Channel::user");
return;
} else if (self.dead) {
return;
}
self.checkModules("onUserPreJoin", [user, data], function (err, result) {
if (result === ChannelModule.PASSTHROUGH) {
user.channel = self;
self.acceptUser(user);
} else {
user.channel = null;
user.account.channelRank = 0;
user.account.effectiveRank = user.account.globalRank;
self.refCounter.unref("Channel::user");
}
});
}
});
});
};
@ -401,7 +393,6 @@ Channel.prototype.acceptUser = function (user) {
if (user.account.globalRank === 0) loginStr += " (guest)";
loginStr += " (aliases: " + user.account.aliases.join(",") + ")";
self.logger.log(loginStr);
self.sendUserJoin(self.users, user);
});