mirror of
https://github.com/thelounge/thelounge
synced 2024-11-26 14:00:21 +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;
|
||||
}
|
||||
|
||||
#settings #change-password .error,
|
||||
#settings #change-password .success {
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
#settings #change-password .error {
|
||||
color: #e74c3c;
|
||||
}
|
||||
|
||||
#settings #change-password .success {
|
||||
color: #2ecc40;
|
||||
}
|
||||
|
||||
#form {
|
||||
background: #eee;
|
||||
border-top: 1px solid #ddd;
|
||||
|
|
|
@ -265,6 +265,31 @@
|
|||
Enable notification for all messages
|
||||
</label>
|
||||
</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">
|
||||
<h2>About The Lounge</h2>
|
||||
</div>
|
||||
|
|
|
@ -112,6 +112,31 @@ $(function() {
|
|||
.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) {
|
||||
if (data.networks.length === 0) {
|
||||
$("#footer").find(".connect").trigger("click");
|
||||
|
@ -734,7 +759,7 @@ $(function() {
|
|||
});
|
||||
|
||||
var windows = $("#windows");
|
||||
var forms = $("#sign-in, #connect");
|
||||
var forms = $("#sign-in, #connect, #change-password");
|
||||
|
||||
windows.on("show", "#sign-in", function() {
|
||||
var self = $(this);
|
||||
|
@ -761,6 +786,8 @@ $(function() {
|
|||
.end();
|
||||
if (form.closest(".window").attr("id") === "connect") {
|
||||
event = "conn";
|
||||
} else if (form.closest("div").attr("id") === "change-password") {
|
||||
event = "change-password";
|
||||
}
|
||||
var values = {};
|
||||
$.each(form.serializeArray(), function(i, obj) {
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
var _ = require("lodash");
|
||||
var Chan = require("./models/chan");
|
||||
var crypto = require("crypto");
|
||||
var fs = require("fs");
|
||||
var identd = require("./identd");
|
||||
var log = require("./log");
|
||||
var net = require("net");
|
||||
|
@ -51,14 +50,15 @@ var inputs = [
|
|||
"whois"
|
||||
];
|
||||
|
||||
function Client(sockets, name, config) {
|
||||
function Client(manager, name, config) {
|
||||
_.merge(this, {
|
||||
activeChannel: -1,
|
||||
config: config,
|
||||
id: id++,
|
||||
name: name,
|
||||
networks: [],
|
||||
sockets: sockets
|
||||
sockets: manager.sockets,
|
||||
manager: manager
|
||||
});
|
||||
var client = this;
|
||||
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) {
|
||||
var client = this;
|
||||
var text = data.text.trim();
|
||||
|
@ -353,9 +368,6 @@ Client.prototype.save = function(force) {
|
|||
return;
|
||||
}
|
||||
|
||||
var name = this.name;
|
||||
var path = Helper.HOME + "/users/" + name + ".json";
|
||||
|
||||
var networks = _.map(
|
||||
this.networks,
|
||||
function(n) {
|
||||
|
@ -364,29 +376,6 @@ Client.prototype.save = function(force) {
|
|||
);
|
||||
|
||||
var json = {};
|
||||
fs.readFile(path, "utf-8", function(err, data) {
|
||||
if (err) {
|
||||
console.log(err);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
json = JSON.parse(data);
|
||||
json.networks = networks;
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
return;
|
||||
}
|
||||
|
||||
fs.writeFile(
|
||||
path,
|
||||
JSON.stringify(json, null, " "),
|
||||
{mode: "0777"},
|
||||
function(err) {
|
||||
if (err) {
|
||||
console.log(err);
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
client.manager.updateUser(client.name, json);
|
||||
};
|
||||
|
|
|
@ -29,18 +29,14 @@ ClientManager.prototype.loadUsers = function() {
|
|||
|
||||
ClientManager.prototype.loadUser = function(name) {
|
||||
try {
|
||||
var json = fs.readFileSync(
|
||||
Helper.HOME + "/users/" + name + ".json",
|
||||
"utf-8"
|
||||
);
|
||||
json = JSON.parse(json);
|
||||
var json = this.readUserConfig(name);
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
return;
|
||||
}
|
||||
if (!this.findClient(name)) {
|
||||
this.clients.push(new Client(
|
||||
this.sockets,
|
||||
this,
|
||||
name,
|
||||
json
|
||||
));
|
||||
|
@ -93,6 +89,50 @@ ClientManager.prototype.addUser = function(name, password) {
|
|||
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) {
|
||||
var users = this.getUsers();
|
||||
if (users.indexOf(name) === -1) {
|
||||
|
|
|
@ -107,6 +107,51 @@ function init(socket, client, token) {
|
|||
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(
|
||||
"open",
|
||||
function(data) {
|
||||
|
|
Loading…
Reference in a new issue