Implement ACL for channel owners (Issue #42)
This commit is contained in:
parent
d7de1fc69e
commit
bb019deeb7
18
auth.js
18
auth.js
|
@ -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;
|
||||
}
|
||||
|
|
55
channel.js
55
channel.js
|
@ -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) {
|
|||
}
|
||||
}
|
||||
|
||||
if(receiver) {
|
||||
if(actor.rank > receiver.rank + 1) {
|
||||
var rank = receiver ? receiver.rank : this.getRank(data.name);
|
||||
|
||||
if(actor.rank > rank + 1) {
|
||||
rank++;
|
||||
if(receiver) {
|
||||
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) {
|
|||
}
|
||||
}
|
||||
|
||||
if(receiver) {
|
||||
if(actor.rank > receiver.rank) {
|
||||
var rank = receiver ? receiver.rank : this.getRank(data.name);
|
||||
|
||||
if(actor.rank > rank) {
|
||||
rank--;
|
||||
if(receiver) {
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
20
database.js
20
database.js
|
@ -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 [];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
},
|
||||
|
|
1
rank.js
1
rank.js
|
@ -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,
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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+")");
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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%">
|
||||
|
|
Loading…
Reference in a new issue