mirror of
https://github.com/thelounge/thelounge
synced 2024-11-26 22:10:22 +00:00
frontend password change functionality
- refactor clientManager.js to allow configuration parsing as a serparate function. - refactor clientManager.js to add configuration writing function. - add server.js changes to allow for new password-change functionality - add password change ui to "settings" screen - refactor client.js to use new clientManager functionality for saving the configuration files
This commit is contained in:
parent
1e8ca51d47
commit
b79a918be8
6 changed files with 177 additions and 38 deletions
|
@ -1116,6 +1116,19 @@ button,
|
||||||
line-height: 1.8;
|
line-height: 1.8;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#settings #change-password .error,
|
||||||
|
#settings #change-password .success {
|
||||||
|
margin-bottom: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#settings #change-password .error {
|
||||||
|
color: #e74c3c;
|
||||||
|
}
|
||||||
|
|
||||||
|
#settings #change-password .success {
|
||||||
|
color: #2ecc40;
|
||||||
|
}
|
||||||
|
|
||||||
#form {
|
#form {
|
||||||
background: #eee;
|
background: #eee;
|
||||||
border-top: 1px solid #ddd;
|
border-top: 1px solid #ddd;
|
||||||
|
|
|
@ -265,6 +265,31 @@
|
||||||
Enable notification for all messages
|
Enable notification for all messages
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
<% if (!public) { %>
|
||||||
|
<div id="change-password">
|
||||||
|
<form action="" method="post">
|
||||||
|
<div class="col-sm-12">
|
||||||
|
<h2>Change password</h2>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-12">
|
||||||
|
<label for="old_password" class="sr-only">Enter current password</label>
|
||||||
|
<input type="password" name="old_password" class="input" placeholder="Enter current password">
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-12">
|
||||||
|
<label for="new_password" class="sr-only">Enter desired new password</label>
|
||||||
|
<input type="password" name="new_password" class="input" placeholder="Enter desired new password">
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-12">
|
||||||
|
<label for="verify_password" class="sr-only">Repeat new password</label>
|
||||||
|
<input type="password" name="verify_password" class="input" placeholder="Repeat new password">
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-12 feedback"></div>
|
||||||
|
<div class="col-sm-12">
|
||||||
|
<button type="submit" class="btn">Change password</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<% } %>
|
||||||
<div class="col-sm-12">
|
<div class="col-sm-12">
|
||||||
<h2>About The Lounge</h2>
|
<h2>About The Lounge</h2>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -112,6 +112,31 @@ $(function() {
|
||||||
.show();
|
.show();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
socket.on("change-password", function(data) {
|
||||||
|
var passwordForm = $("#change-password");
|
||||||
|
if (data.error || data.success) {
|
||||||
|
var message = data.success ? data.success : data.error;
|
||||||
|
var feedback = passwordForm.find(".feedback");
|
||||||
|
|
||||||
|
if (data.success) {
|
||||||
|
feedback.addClass("success").removeClass("error");
|
||||||
|
} else {
|
||||||
|
feedback.addClass("error").removeClass("success");
|
||||||
|
}
|
||||||
|
|
||||||
|
feedback.text(message).show();
|
||||||
|
feedback.closest("form").one("submit", function() {
|
||||||
|
feedback.hide();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
passwordForm
|
||||||
|
.find("input")
|
||||||
|
.val("")
|
||||||
|
.end()
|
||||||
|
.find(".btn")
|
||||||
|
.prop("disabled", false);
|
||||||
|
});
|
||||||
|
|
||||||
socket.on("init", function(data) {
|
socket.on("init", function(data) {
|
||||||
if (data.networks.length === 0) {
|
if (data.networks.length === 0) {
|
||||||
$("#footer").find(".connect").trigger("click");
|
$("#footer").find(".connect").trigger("click");
|
||||||
|
@ -734,7 +759,7 @@ $(function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
var windows = $("#windows");
|
var windows = $("#windows");
|
||||||
var forms = $("#sign-in, #connect");
|
var forms = $("#sign-in, #connect, #change-password");
|
||||||
|
|
||||||
windows.on("show", "#sign-in", function() {
|
windows.on("show", "#sign-in", function() {
|
||||||
var self = $(this);
|
var self = $(this);
|
||||||
|
@ -761,6 +786,8 @@ $(function() {
|
||||||
.end();
|
.end();
|
||||||
if (form.closest(".window").attr("id") === "connect") {
|
if (form.closest(".window").attr("id") === "connect") {
|
||||||
event = "conn";
|
event = "conn";
|
||||||
|
} else if (form.closest("div").attr("id") === "change-password") {
|
||||||
|
event = "change-password";
|
||||||
}
|
}
|
||||||
var values = {};
|
var values = {};
|
||||||
$.each(form.serializeArray(), function(i, obj) {
|
$.each(form.serializeArray(), function(i, obj) {
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
var _ = require("lodash");
|
var _ = require("lodash");
|
||||||
var Chan = require("./models/chan");
|
var Chan = require("./models/chan");
|
||||||
var crypto = require("crypto");
|
var crypto = require("crypto");
|
||||||
var fs = require("fs");
|
|
||||||
var identd = require("./identd");
|
var identd = require("./identd");
|
||||||
var log = require("./log");
|
var log = require("./log");
|
||||||
var net = require("net");
|
var net = require("net");
|
||||||
|
@ -51,14 +50,15 @@ var inputs = [
|
||||||
"whois"
|
"whois"
|
||||||
];
|
];
|
||||||
|
|
||||||
function Client(sockets, name, config) {
|
function Client(manager, name, config) {
|
||||||
_.merge(this, {
|
_.merge(this, {
|
||||||
activeChannel: -1,
|
activeChannel: -1,
|
||||||
config: config,
|
config: config,
|
||||||
id: id++,
|
id: id++,
|
||||||
name: name,
|
name: name,
|
||||||
networks: [],
|
networks: [],
|
||||||
sockets: sockets
|
sockets: manager.sockets,
|
||||||
|
manager: manager
|
||||||
});
|
});
|
||||||
var client = this;
|
var client = this;
|
||||||
crypto.randomBytes(48, function(err, buf) {
|
crypto.randomBytes(48, function(err, buf) {
|
||||||
|
@ -221,6 +221,21 @@ Client.prototype.connect = function(args) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Client.prototype.setPassword = function(hash) {
|
||||||
|
var client = this;
|
||||||
|
client.manager.updateUser(client.name, {password:hash});
|
||||||
|
// re-read the hash off disk to ensure we use whatever is saved. this will
|
||||||
|
// prevent situations where the password failed to save properly and so
|
||||||
|
// a restart of the server would forget the change and use the old
|
||||||
|
// password again.
|
||||||
|
var user = client.manager.readUserConfig(client.name);
|
||||||
|
if (user.password === hash) {
|
||||||
|
client.config.password = hash;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
Client.prototype.input = function(data) {
|
Client.prototype.input = function(data) {
|
||||||
var client = this;
|
var client = this;
|
||||||
var text = data.text.trim();
|
var text = data.text.trim();
|
||||||
|
@ -353,9 +368,6 @@ Client.prototype.save = function(force) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var name = this.name;
|
|
||||||
var path = Helper.HOME + "/users/" + name + ".json";
|
|
||||||
|
|
||||||
var networks = _.map(
|
var networks = _.map(
|
||||||
this.networks,
|
this.networks,
|
||||||
function(n) {
|
function(n) {
|
||||||
|
@ -364,29 +376,6 @@ Client.prototype.save = function(force) {
|
||||||
);
|
);
|
||||||
|
|
||||||
var json = {};
|
var json = {};
|
||||||
fs.readFile(path, "utf-8", function(err, data) {
|
|
||||||
if (err) {
|
|
||||||
console.log(err);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
json = JSON.parse(data);
|
|
||||||
json.networks = networks;
|
json.networks = networks;
|
||||||
} catch (e) {
|
client.manager.updateUser(client.name, json);
|
||||||
console.log(e);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
fs.writeFile(
|
|
||||||
path,
|
|
||||||
JSON.stringify(json, null, " "),
|
|
||||||
{mode: "0777"},
|
|
||||||
function(err) {
|
|
||||||
if (err) {
|
|
||||||
console.log(err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -29,18 +29,14 @@ ClientManager.prototype.loadUsers = function() {
|
||||||
|
|
||||||
ClientManager.prototype.loadUser = function(name) {
|
ClientManager.prototype.loadUser = function(name) {
|
||||||
try {
|
try {
|
||||||
var json = fs.readFileSync(
|
var json = this.readUserConfig(name);
|
||||||
Helper.HOME + "/users/" + name + ".json",
|
|
||||||
"utf-8"
|
|
||||||
);
|
|
||||||
json = JSON.parse(json);
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log(e);
|
console.log(e);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!this.findClient(name)) {
|
if (!this.findClient(name)) {
|
||||||
this.clients.push(new Client(
|
this.clients.push(new Client(
|
||||||
this.sockets,
|
this,
|
||||||
name,
|
name,
|
||||||
json
|
json
|
||||||
));
|
));
|
||||||
|
@ -93,6 +89,50 @@ ClientManager.prototype.addUser = function(name, password) {
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
ClientManager.prototype.updateUser = function(name, opts) {
|
||||||
|
var users = this.getUsers();
|
||||||
|
if (users.indexOf(name) === -1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (typeof opts === "undefined") {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
var path = Helper.HOME + "/users/" + name + ".json";
|
||||||
|
var user = {};
|
||||||
|
|
||||||
|
try {
|
||||||
|
user = this.readUserConfig(name);
|
||||||
|
_.merge(user, opts);
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fs.writeFileSync(
|
||||||
|
path,
|
||||||
|
JSON.stringify(user, null, " "),
|
||||||
|
{mode: "0777"},
|
||||||
|
function(err) {
|
||||||
|
if (err) {
|
||||||
|
console.log(err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
ClientManager.prototype.readUserConfig = function(name) {
|
||||||
|
var users = this.getUsers();
|
||||||
|
if (users.indexOf(name) === -1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
var path = Helper.HOME + "/users/" + name + ".json";
|
||||||
|
var user = {};
|
||||||
|
var data = fs.readFileSync(path, "utf-8");
|
||||||
|
user = JSON.parse(data);
|
||||||
|
return user;
|
||||||
|
};
|
||||||
|
|
||||||
ClientManager.prototype.removeUser = function(name) {
|
ClientManager.prototype.removeUser = function(name) {
|
||||||
var users = this.getUsers();
|
var users = this.getUsers();
|
||||||
if (users.indexOf(name) === -1) {
|
if (users.indexOf(name) === -1) {
|
||||||
|
|
|
@ -107,6 +107,51 @@ function init(socket, client, token) {
|
||||||
client.connect(data);
|
client.connect(data);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
if (!config.public) {
|
||||||
|
socket.on(
|
||||||
|
"change-password",
|
||||||
|
function(data) {
|
||||||
|
var old = data.old_password;
|
||||||
|
var p1 = data.new_password;
|
||||||
|
var p2 = data.verify_password;
|
||||||
|
if (typeof old === "undefined" || old === "") {
|
||||||
|
socket.emit("change-password", {
|
||||||
|
error: "Please enter your current password"
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (typeof p1 === "undefined" || p1 === "") {
|
||||||
|
socket.emit("change-password", {
|
||||||
|
error: "Please enter a new password"
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (p1 !== p2) {
|
||||||
|
socket.emit("change-password", {
|
||||||
|
error: "Both new password fields must match"
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!bcrypt.compareSync(old || "", client.config.password)) {
|
||||||
|
socket.emit("change-password", {
|
||||||
|
error: "The current password field does not match your account password"
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var salt = bcrypt.genSaltSync(8);
|
||||||
|
var hash = bcrypt.hashSync(p1, salt);
|
||||||
|
if (client.setPassword(hash)) {
|
||||||
|
socket.emit("change-password", {
|
||||||
|
success: "Successfully updated your password"
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
socket.emit("change-password", {
|
||||||
|
error: "Failed to update your password"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
socket.on(
|
socket.on(
|
||||||
"open",
|
"open",
|
||||||
function(data) {
|
function(data) {
|
||||||
|
|
Loading…
Reference in a new issue