Implement ACL for channel owners (Issue #42)

This commit is contained in:
Calvin Montgomery 2013-04-22 22:28:40 +04:00
parent d7de1fc69e
commit bb019deeb7
10 changed files with 173 additions and 26 deletions

18
auth.js
View File

@ -109,3 +109,21 @@ exports.login = function(name, pw) {
}
return false;
}
exports.getGlobalRank = function(name) {
var db = mysql.createConnectionSync();
db.connectSync(Config.MYSQL_SERVER, Config.MYSQL_USER,
Config.MYSQL_PASSWORD, Config.MYSQL_DB);
if(!db.connectedSync()) {
Logger.errlog.log("Auth.getGlobalRank: DB connection failed");
return false;
}
var query = "SELECT * FROM registrations WHERE uname='{1}'"
.replace(/\{1\}/, name)
var results = db.querySync(query);
var rows = results.fetchAllSync();
if(rows.length > 0) {
return rows[0].global_rank;
}
return 0;
}

View File

@ -18,6 +18,7 @@ var Logger = require("./logger.js");
var InfoGetter = require("./get-info.js");
var io = require("./server.js").io;
var Rank = require("./rank.js");
var Auth = require("./auth.js");
var ChatCommand = require("./chatcommand.js");
var Channel = function(name) {
@ -181,10 +182,12 @@ Channel.prototype.tryRegister = function(user) {
}
Channel.prototype.getRank = function(name) {
var global = Auth.getGlobalRank(name);
if(!this.registered) {
return Rank.Guest;
return global;
}
return Database.lookupChannelRank(this.name, name);
var local = Database.lookupChannelRank(this.name, name);
return local > global ? local : global;
}
Channel.prototype.saveRank = function(user) {
@ -385,6 +388,9 @@ Channel.prototype.sendRankStuff = function(user) {
}
user.socket.emit("chatFilters", {filters: filts});
}
if(Rank.hasPermission(user, "acl")) {
user.socket.emit("acl", Database.getChannelRanks(this.name));
}
}
Channel.prototype.sendPlaylist = function(user) {
@ -445,6 +451,10 @@ Channel.prototype.broadcastNewUser = function(user) {
meta: user.meta
});
this.sendRankStuff(user);
if(user.rank > Rank.Guest) {
this.saveRank(user);
this.broadcastRankTable();
}
}
Channel.prototype.broadcastRankUpdate = function(user) {
@ -491,6 +501,15 @@ Channel.prototype.broadcastBanlist = function() {
}
}
Channel.prototype.broadcastRankTable = function() {
var ranks = Database.getChannelRanks(this.name);
for(var i = 0; i < this.users.length; i++) {
if(Rank.hasPermission(this.users[i], "acl")) {
this.users[i].socket.emit("acl", ranks);
}
}
}
Channel.prototype.broadcastChatFilters = function() {
var filts = new Array(this.filters.length);
for(var i = 0; i < this.filters.length; i++) {
@ -1079,15 +1098,25 @@ Channel.prototype.tryPromoteUser = function(actor, data) {
}
}
var rank = receiver ? receiver.rank : this.getRank(data.name);
if(actor.rank > rank + 1) {
rank++;
if(receiver) {
if(actor.rank > receiver.rank + 1) {
receiver.rank++;
if(receiver.loggedIn) {
this.saveRank(receiver);
}
this.logger.log("*** " + actor.name + " promoted " + receiver.name + " from " + (receiver.rank - 1) + " to " + receiver.rank);
this.broadcastRankUpdate(receiver);
}
else {
Database.saveChannelRank(this.name, {
name: data.name,
rank: rank
});
}
this.logger.log("*** " + actor.name + " promoted " + data.name + " from " + (rank - 1) + " to " + rank);
this.broadcastRankTable();
}
}
@ -1109,15 +1138,25 @@ Channel.prototype.tryDemoteUser = function(actor, data) {
}
}
var rank = receiver ? receiver.rank : this.getRank(data.name);
if(actor.rank > rank) {
rank--;
if(receiver) {
if(actor.rank > receiver.rank) {
receiver.rank--;
if(receiver.loggedIn) {
this.saveRank(receiver);
}
this.logger.log("*** " + actor.name + " demoted " + receiver.name + " from " + (receiver.rank + 1) + " to " + receiver.rank);
this.broadcastRankUpdate(receiver);
}
else {
Database.saveChannelRank(this.name, {
name: data.name,
rank: rank
});
}
this.logger.log("*** " + actor.name + " demoted " + data.name + " from " + (rank + 1) + " to " + rank);
this.broadcastRankTable();
}
}

View File

@ -264,3 +264,23 @@ exports.removeChannelBan = function(channame, ip) {
db.closeSync();
return results;
}
exports.getChannelRanks = function(channame) {
var db = exports.getConnection();
if(!db) {
return false;
}
var query = "SELECT * FROM chan_{}_ranks WHERE 1"
.replace("{}", channame);
var results = db.querySync(query);
if(results) {
var rows = results.fetchAllSync();
db.closeSync();
return rows;
}
else {
return [];
}
}

View File

@ -2,7 +2,7 @@
"author": "Calvin Montgomery",
"name": "CyTube",
"description": "Online media synchronizer and chat",
"version": "1.2.2",
"version": "1.2.3",
"repository": {
"url": "http://github.com/calzoneman/sync"
},

View File

@ -19,6 +19,7 @@ var permissions = {
acp : exports.Siteadmin,
announce : exports.Siteadmin,
registerChannel : exports.Owner,
acl : exports.Owner,
queue : exports.Moderator,
assignLeader : exports.Moderator,
kick : exports.Moderator,

View File

@ -9,7 +9,7 @@ The above copyright notice and this permission notice shall be included in all c
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
const VERSION = "1.2.2";
const VERSION = "1.2.3";
var fs = require("fs");
var Logger = require("./logger.js");

View File

@ -101,6 +101,8 @@ function initCallbacks() {
updateBanlist(data.entries);
});
socket.on("acl", updateACL);
socket.on("voteskip", function(data) {
if(data.count > 0) {
$("#voteskip").text("Voteskip ("+data.count+"/"+data.need+")");

View File

@ -382,41 +382,50 @@ $("#updatemotd").click(function() {
});
$("#show_chancontrols").click(function() {
$("#show_banlist").parent().removeClass("active");
$("#show_motdeditor").parent().removeClass("active");
$("#show_filtereditor").parent().removeClass("active");
$("#show_chancontrols").parent().addClass("active");
$("#modnav li").each(function() {
$(this).removeClass("active");
});
$(".modonly").hide();
$("#show_chancontrols").parent().addClass("active");
$("#chancontrols").show();
});
$("#show_banlist").click(function() {
$("#show_chancontrols").parent().removeClass("active");
$("#show_motdeditor").parent().removeClass("active");
$("#show_filtereditor").parent().removeClass("active");
$("#show_banlist").parent().addClass("active");
$("#modnav li").each(function() {
$(this).removeClass("active");
});
$(".modonly").hide();
$("#show_banlist").parent().addClass("active");
$("#banlist").show();
});
$("#show_motdeditor").click(function() {
$("#show_chancontrols").parent().removeClass("active");
$("#show_banlist").parent().removeClass("active");
$("#show_filtereditor").parent().removeClass("active");
$("#show_motdeditor").parent().addClass("active");
$("#modnav li").each(function() {
$(this).removeClass("active");
});
$(".modonly").hide();
$("#show_motdeditor").parent().addClass("active");
$("#motdeditor").show();
});
$("#show_filtereditor").click(function() {
$("#show_chancontrols").parent().removeClass("active");
$("#show_banlist").parent().removeClass("active");
$("#show_motdeditor").parent().removeClass("active");
$("#show_filtereditor").parent().addClass("active");
$("#modnav li").each(function() {
$(this).removeClass("active");
});
$(".modonly").hide();
$("#show_filtereditor").parent().addClass("active");
$("#filtereditor").show();
});
$("#show_acl").click(function() {
$("#modnav li").each(function() {
$(this).removeClass("active");
});
$(".modonly").hide();
$("#show_acl").parent().addClass("active");
$("#channelranks").show();
});
function searchLibrary() {
socket.emit("searchLibrary", {
query: $("#library_query").val()

View File

@ -672,6 +672,50 @@ function updateChatFilters(entries) {
add.click(cback);
}
function updateACL(entries) {
entries.sort(function(a, b) {
var x = a.name.toLowerCase();
var y = b.name.toLowerCase();
return y == x ? 0 : (x < y ? -1 : 1);
});
var tbl = $("#channelranks table");
if(tbl.children().length > 1) {
$(tbl.children()[1]).remove();
}
for(var i = 0; i < entries.length; i++) {
var tr = $("<tr/>").appendTo(tbl);
var name = $("<td/>").text(entries[i].name).appendTo(tr);
name.addClass(getNameColor(entries[i].rank));
var rank = $("<td/>").text(entries[i].rank).appendTo(tr);
var control = $("<td/>").appendTo(tr);
var up = $("<button/>").addClass("btn btn-mini btn-success")
.appendTo(control);
$("<i/>").addClass("icon-plus").appendTo(up);
var down = $("<button/>").addClass("btn btn-mini btn-danger")
.appendTo(control);
$("<i/>").addClass("icon-minus").appendTo(down);
if(entries[i].rank + 1 >= RANK) {
up.attr("disabled", true);
}
else {
up.click(function(name) { return function() {
socket.emit("promote", {
name: name
});
}}(entries[i].name));
}
if(entries[i].rank >= RANK) {
down.attr("disabled", true);
}
else {
down.click(function(name) { return function() {
socket.emit("demote", {
name: name
});
}}(entries[i].name));
}
}
}
function handleRankChange() {
rebuildPlaylist();
if(RANK >= Rank.Moderator || LEADER) {

View File

@ -113,6 +113,9 @@
<li>
<a href="javascript:void(0)" id="show_filtereditor">Chat Filters</a>
</li>
<li>
<a href="javascript:void(0)" id="show_acl">Channel Ranks</a>
</li>
</ul>
</div>
</div>
@ -199,6 +202,17 @@
</table>
</div>
</div>
<div class="row modonly" id="channelranks" style="display: none;">
<div class="span10 offset1">
<table class="table table-striped">
<thead>
<th>Name</th>
<th>Rank</th>
<th>Control</th>
</thead>
</table>
</div>
</div>
<div class="row" id="layout_buttons">
<div class="span4 offset3">
<div class="btn-group" style="width: 100%">