aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--build/server.js121
-rw-r--r--default-config.json7
-rw-r--r--src/Types.hx23
-rw-r--r--src/server/Main.hx66
4 files changed, 190 insertions, 27 deletions
diff --git a/build/server.js b/build/server.js
index c7b1101..33397b4 100644
--- a/build/server.js
+++ b/build/server.js
@@ -979,8 +979,8 @@ var server_Main = function(port,wsPort) {
this.port = port;
server_Utils.getGlobalIp(function(ip) {
_gthis.globalIp = ip;
- haxe_Log.trace("Local: http://" + _gthis.localIp + ":" + port,{ fileName : "src/server/Main.hx", lineNumber : 78, className : "server.Main", methodName : "new"});
- haxe_Log.trace("Global: http://" + _gthis.globalIp + ":" + port,{ fileName : "src/server/Main.hx", lineNumber : 79, className : "server.Main", methodName : "new"});
+ haxe_Log.trace("Local: http://" + _gthis.localIp + ":" + port,{ fileName : "src/server/Main.hx", lineNumber : 79, className : "server.Main", methodName : "new"});
+ haxe_Log.trace("Global: http://" + _gthis.globalIp + ":" + port,{ fileName : "src/server/Main.hx", lineNumber : 80, className : "server.Main", methodName : "new"});
return;
});
var dir = "" + this.rootDir + "/res";
@@ -1011,6 +1011,32 @@ server_Main.prototype = {
return this.userList.salt;
}
,loadUserConfig: function() {
+ var config = this.getUserConfig();
+ var groups = ["guest","user","leader","admin"];
+ var _g = 0;
+ while(_g < groups.length) {
+ var field = groups[_g];
+ ++_g;
+ var group = Reflect.field(config.permissions,field);
+ var _g1 = 0;
+ while(_g1 < groups.length) {
+ var type = groups[_g1];
+ ++_g1;
+ if(type == field) {
+ continue;
+ }
+ if(group.indexOf(type) == -1) {
+ continue;
+ }
+ HxOverrides.remove(group,type);
+ var _g2 = 0;
+ var _g11 = Reflect.field(config.permissions,type);
+ while(_g2 < _g11.length) group.push(_g11[_g2++]);
+ }
+ }
+ return config;
+ }
+ ,getUserConfig: function() {
var config = JSON.parse(js_node_Fs.readFileSync("" + this.rootDir + "/default-config.json",{ encoding : "utf8"}));
var customPath = "" + this.rootDir + "/user/config.json";
if(!sys_FileSystem.exists(customPath)) {
@@ -1023,7 +1049,7 @@ server_Main.prototype = {
var field = _g1[_g];
++_g;
if(Reflect.field(config,field) == null) {
- haxe_Log.trace("Warning: config field \"" + field + "\" is unknown",{ fileName : "src/server/Main.hx", lineNumber : 111, className : "server.Main", methodName : "loadUserConfig"});
+ haxe_Log.trace("Warning: config field \"" + field + "\" is unknown",{ fileName : "src/server/Main.hx", lineNumber : 130, className : "server.Main", methodName : "getUserConfig"});
}
config[field] = Reflect.field(customConfig,field);
}
@@ -1044,7 +1070,7 @@ server_Main.prototype = {
js_node_Fs.writeFileSync("" + folder + "/users.json",JSON.stringify(users,null,"\t"));
}
,saveState: function() {
- haxe_Log.trace("Saving state...",{ fileName : "src/server/Main.hx", lineNumber : 135, className : "server.Main", methodName : "saveState"});
+ haxe_Log.trace("Saving state...",{ fileName : "src/server/Main.hx", lineNumber : 154, className : "server.Main", methodName : "saveState"});
var json = JSON.stringify({ videoList : this.videoList, isPlaylistOpen : this.isPlaylistOpen, itemPos : this.itemPos, messages : this.messages, timer : { time : this.videoTimer.getTime(), paused : this.videoTimer.isPaused()}},null,"\t");
js_node_Fs.writeFileSync(this.statePath,json);
}
@@ -1052,7 +1078,7 @@ server_Main.prototype = {
if(!sys_FileSystem.exists(this.statePath)) {
return;
}
- haxe_Log.trace("Loading state...",{ fileName : "src/server/Main.hx", lineNumber : 152, className : "server.Main", methodName : "loadState"});
+ haxe_Log.trace("Loading state...",{ fileName : "src/server/Main.hx", lineNumber : 171, className : "server.Main", methodName : "loadState"});
var data = JSON.parse(js_node_Fs.readFileSync(this.statePath,{ encoding : "utf8"}));
this.videoList.length = 0;
this.messages.length = 0;
@@ -1069,7 +1095,7 @@ server_Main.prototype = {
this.videoTimer.pause();
}
,logError: function(type,data) {
- haxe_Log.trace(type,{ fileName : "src/server/Main.hx", lineNumber : 166, className : "server.Main", methodName : "logError", customParams : [data]});
+ haxe_Log.trace(type,{ fileName : "src/server/Main.hx", lineNumber : 185, className : "server.Main", methodName : "logError", customParams : [data]});
var crashesFolder = "" + this.rootDir + "/user/crashes";
var name = new Date().toISOString() + "-" + type;
if(!sys_FileSystem.exists(crashesFolder)) {
@@ -1085,7 +1111,7 @@ server_Main.prototype = {
return;
}
var url = "http://" + process.env["APP_URL"];
- haxe_Log.trace("Ping " + url,{ fileName : "src/server/Main.hx", lineNumber : 180, className : "server.Main", methodName : "initIntergationHandlers"});
+ haxe_Log.trace("Ping " + url,{ fileName : "src/server/Main.hx", lineNumber : 199, className : "server.Main", methodName : "initIntergationHandlers"});
js_node_Http.get(url,function(r) {
return;
});
@@ -1100,14 +1126,14 @@ server_Main.prototype = {
}
this.userList.admins.push({ name : name, hash : hash});
this.writeUsers(this.userList);
- haxe_Log.trace("Admin " + name + " added.",{ fileName : "src/server/Main.hx", lineNumber : 195, className : "server.Main", methodName : "addAdmin"});
+ haxe_Log.trace("Admin " + name + " added.",{ fileName : "src/server/Main.hx", lineNumber : 214, className : "server.Main", methodName : "addAdmin"});
}
,onConnect: function(ws,req) {
var _gthis = this;
var ip = req.connection.remoteAddress;
var id = this.freeIds.length > 0 ? this.freeIds.shift() : this.clients.length;
var name = "Guest " + (id + 1);
- haxe_Log.trace("" + name + " connected (" + ip + ")",{ fileName : "src/server/Main.hx", lineNumber : 202, className : "server.Main", methodName : "onConnect"});
+ haxe_Log.trace("" + name + " connected (" + ip + ")",{ fileName : "src/server/Main.hx", lineNumber : 221, className : "server.Main", methodName : "onConnect"});
var client = new Client(ws,req,id,name,0);
client.setGroupFlag(ClientGroup.Admin,req.connection.localAddress == ip);
this.clients.push(client);
@@ -1131,7 +1157,7 @@ server_Main.prototype = {
return;
});
ws.on("close",function(err) {
- haxe_Log.trace("Client " + client.name + " disconnected",{ fileName : "src/server/Main.hx", lineNumber : 232, className : "server.Main", methodName : "onConnect"});
+ haxe_Log.trace("Client " + client.name + " disconnected",{ fileName : "src/server/Main.hx", lineNumber : 251, className : "server.Main", methodName : "onConnect"});
server_Utils.sortedPush(_gthis.freeIds,client.id);
HxOverrides.remove(_gthis.clients,client);
_gthis.sendClientList();
@@ -1152,10 +1178,14 @@ server_Main.prototype = {
,onMessage: function(client,data) {
switch(data.type) {
case "AddVideo":
- if((client.group & 4) == 0 && !this.isPlaylistOpen) {
- this.serverMessage(client,"accessError");
+ if(!this.checkPermission(client,"addVideo")) {
return;
}
+ if(!this.isPlaylistOpen) {
+ if(!this.checkPermission(client,"lockPlaylist")) {
+ return;
+ }
+ }
if(this.config.totalVideoLimit != 0 && this.videoList.length >= this.config.totalVideoLimit) {
this.serverMessage(client,"totalVideoLimitError");
return;
@@ -1183,12 +1213,16 @@ server_Main.prototype = {
}
break;
case "ClearChat":
- this.messages.length = 0;
- if((client.group & 4) != 0) {
- this.broadcast(data);
+ if(!this.checkPermission(client,"clearChat")) {
+ return;
}
+ this.messages.length = 0;
+ this.broadcast(data);
break;
case "ClearPlaylist":
+ if(!this.checkPermission(client,"removeVideo")) {
+ return;
+ }
this.videoTimer.stop();
this.videoList.length = 0;
this.itemPos = 0;
@@ -1250,6 +1284,9 @@ server_Main.prototype = {
this.sendClientList();
break;
case "Message":
+ if(!this.checkPermission(client,"writeChat")) {
+ return;
+ }
var text = data.message.text;
if(text.length == 0) {
return;
@@ -1291,11 +1328,17 @@ server_Main.prototype = {
this.broadcast(data);
break;
case "PlayItem":
+ if(!this.checkPermission(client,"changeOrder")) {
+ return;
+ }
this.itemPos = data.playItem.pos;
this.restartWaitTimer();
this.broadcast(data);
break;
case "RemoveVideo":
+ if(!this.checkPermission(client,"removeVideo")) {
+ return;
+ }
if(this.videoList.length == 0) {
return;
}
@@ -1314,6 +1357,9 @@ server_Main.prototype = {
this.broadcast(data);
break;
case "Rewind":
+ if(!this.checkPermission(client,"rewind")) {
+ return;
+ }
if(this.videoList.length == 0) {
return;
}
@@ -1327,8 +1373,18 @@ server_Main.prototype = {
case "ServerMessage":
break;
case "SetLeader":
- ClientTools.setLeader(this.clients,data.setLeader.clientName);
- this.broadcast({ type : "SetLeader", setLeader : { clientName : data.setLeader.clientName}});
+ var clientName = data.setLeader.clientName;
+ if(client.name == clientName) {
+ if(!this.checkPermission(client,"requestLeader")) {
+ return;
+ }
+ } else if((client.group & 2) == 0 && clientName != "") {
+ if(!this.checkPermission(client,"setLeader")) {
+ return;
+ }
+ }
+ ClientTools.setLeader(this.clients,clientName);
+ this.broadcast({ type : "SetLeader", setLeader : { clientName : clientName}});
if(this.videoList.length == 0) {
return;
}
@@ -1340,6 +1396,9 @@ server_Main.prototype = {
}
break;
case "SetNextItem":
+ if(!this.checkPermission(client,"changeOrder")) {
+ return;
+ }
var pos = data.setNextItem.pos;
if(pos == this.itemPos || pos == this.itemPos + 1) {
return;
@@ -1358,6 +1417,9 @@ server_Main.prototype = {
this.broadcastExcept(client,data);
break;
case "ShufflePlaylist":
+ if(!this.checkPermission(client,"changeOrder")) {
+ return;
+ }
if(this.videoList.length == 0) {
return;
}
@@ -1368,6 +1430,9 @@ server_Main.prototype = {
this.broadcast({ type : "UpdatePlaylist", updatePlaylist : { videoList : this.videoList}});
break;
case "SkipVideo":
+ if(!this.checkPermission(client,"removeVideo")) {
+ return;
+ }
if(this.videoList.length == 0) {
return;
}
@@ -1385,7 +1450,7 @@ server_Main.prototype = {
this.broadcast(data);
break;
case "TogglePlaylistLock":
- if((client.group & 4) == 0) {
+ if(!this.checkPermission(client,"lockPlaylist")) {
return;
}
this.isPlaylistOpen = !this.isPlaylistOpen;
@@ -1437,6 +1502,26 @@ server_Main.prototype = {
client.ws.send(json,null);
}
}
+ ,checkPermission: function(client,perm) {
+ var state = this.hasPermission(client,perm);
+ if(!state) {
+ this.send(client,{ type : "ServerMessage", serverMessage : { textId : "accessError"}});
+ }
+ return state;
+ }
+ ,hasPermission: function(client,perm) {
+ var p = this.config.permissions;
+ if((client.group & 4) != 0) {
+ return p.admin.indexOf(perm) != -1;
+ }
+ if((client.group & 2) != 0) {
+ return p.leader.indexOf(perm) != -1;
+ }
+ if((client.group & 1) != 0) {
+ return p.user.indexOf(perm) != -1;
+ }
+ return p.guest.indexOf(perm) != -1;
+ }
,badNickName: function(name) {
if(name.length == 0) {
return true;
diff --git a/default-config.json b/default-config.json
index f569962..488532f 100644
--- a/default-config.json
+++ b/default-config.json
@@ -6,7 +6,12 @@
"totalVideoLimit": 0,
"userVideoLimit": 0,
"templateUrl": "https://youtube.com/watch?v=iY1QHpp6iEE",
- "leaderRequest": "everyone",
+ "permissions": {
+ "guest": ["writeChat", "addVideo", "removeVideo", "changeOrder", "requestLeader", "rewind"],
+ "user": ["guest"],
+ "leader": ["user"],
+ "admin": ["user", "clearChat", "setLeader", "lockPlaylist"]
+ },
"emotes": [
{"name": ":adorable:", "image": "https://i.imgur.com/5GxNwDY.png"},
{"name": ":angry:", "image": "https://i.imgur.com/Mx9lhMZ.png"},
diff --git a/src/Types.hx b/src/Types.hx
index 06c85ea..41d5340 100644
--- a/src/Types.hx
+++ b/src/Types.hx
@@ -15,12 +15,33 @@ typedef Config = {
totalVideoLimit:Int,
userVideoLimit:Int,
templateUrl:String,
- leaderRequest:String,
+ permissions:{
+ guest:Array<Permission>,
+ user:Array<Permission>,
+ leader:Array<Permission>,
+ admin:Array<Permission>
+ },
emotes:Array<Emote>,
filters:Array<Filter>,
?salt:String
};
+enum abstract Permission(String) {
+ var GuestPerm = "guest";
+ var UserPerm = "user";
+ var LeaderPerm = "leader";
+ var AdminPerm = "admin";
+ var WriteChatPerm = "writeChat";
+ var AddVideoPerm = "addVideo";
+ var RemoveVideoPerm = "removeVideo";
+ var RequestLeaderPerm = "requestLeader";
+ var RewindPerm = "rewind";
+ var ClearChatPerm = "clearChat";
+ var SetLeaderPerm = "setLeader";
+ var ChangeOrderPerm = "changeOrder";
+ var LockPlaylistPerm = "lockPlaylist";
+}
+
typedef UserList = {
admins:Array<UserField>,
?salt:String
diff --git a/src/server/Main.hx b/src/server/Main.hx
index 8f71bd2..033e2a0 100644
--- a/src/server/Main.hx
+++ b/src/server/Main.hx
@@ -14,6 +14,7 @@ import js.npm.ws.WebSocket;
import js.node.http.IncomingMessage;
import js.node.Http;
import Types.Config;
+import Types.Permission;
import Types.UserList;
import Types.Message;
import Types.WsEvent;
@@ -103,6 +104,24 @@ class Main {
}
function loadUserConfig():Config {
+ final config = getUserConfig();
+ inline function getPermissions(type:Permission):Array<Permission> {
+ return Reflect.field(config.permissions, cast type);
+ }
+ final groups = [GuestPerm, UserPerm, LeaderPerm, AdminPerm];
+ for (field in groups) {
+ final group = getPermissions(field);
+ for (type in groups) {
+ if (type == field) continue;
+ if (group.indexOf(type) == -1) continue;
+ group.remove(type);
+ for (item in getPermissions(type)) group.push(item);
+ }
+ }
+ return config;
+ }
+
+ function getUserConfig():Config {
final config:Config = Json.parse(File.getContent('$rootDir/default-config.json'));
final customPath = '$rootDir/user/config.json';
if (!FileSystem.exists(customPath)) return config;
@@ -302,6 +321,7 @@ class Main {
sendClientList();
case Message:
+ if (!checkPermission(client, WriteChatPerm)) return;
var text = data.message.text;
if (text.length == 0) return;
if (text.length > config.maxMessageLength) {
@@ -316,9 +336,9 @@ class Main {
case ServerMessage:
case AddVideo:
- if (!client.isAdmin && !isPlaylistOpen) {
- serverMessage(client, "accessError");
- return;
+ if (!checkPermission(client, AddVideoPerm)) return;
+ if (!isPlaylistOpen) {
+ if (!checkPermission(client, LockPlaylistPerm)) return;
}
if (config.totalVideoLimit != 0
&& videoList.length >= config.totalVideoLimit) {
@@ -350,6 +370,7 @@ class Main {
prepareVideoPlayback();
case RemoveVideo:
+ if (!checkPermission(client, RemoveVideoPerm)) return;
if (videoList.length == 0) return;
final url = data.removeVideo.url;
var index = videoList.findIndex(item -> item.url == url);
@@ -363,6 +384,7 @@ class Main {
broadcast(data);
case SkipVideo:
+ if (!checkPermission(client, RemoveVideoPerm)) return;
if (videoList.length == 0) return;
final item = videoList[itemPos];
if (item.url != data.skipVideo.url) return;
@@ -408,6 +430,7 @@ class Main {
broadcastExcept(client, data);
case Rewind:
+ if (!checkPermission(client, RewindPerm)) return;
if (videoList.length == 0) return;
// TODO permission
data.rewind.time += videoTimer.getTime();
@@ -416,10 +439,16 @@ class Main {
broadcast(data);
case SetLeader:
- clients.setLeader(data.setLeader.clientName);
+ final clientName = data.setLeader.clientName;
+ if (client.name == clientName) {
+ if (!checkPermission(client, RequestLeaderPerm)) return;
+ } else if (!client.isLeader && clientName != "") {
+ if (!checkPermission(client, SetLeaderPerm)) return;
+ }
+ clients.setLeader(clientName);
broadcast({
type: SetLeader, setLeader: {
- clientName: data.setLeader.clientName
+ clientName: clientName
}
});
if (videoList.length == 0) return;
@@ -433,11 +462,13 @@ class Main {
}
case PlayItem:
+ if (!checkPermission(client, ChangeOrderPerm)) return;
itemPos = data.playItem.pos;
restartWaitTimer();
broadcast(data);
case SetNextItem:
+ if (!checkPermission(client, ChangeOrderPerm)) return;
final pos = data.setNextItem.pos;
if (pos == itemPos || pos == itemPos + 1) return;
videoList.setNextItem(pos, itemPos);
@@ -449,16 +480,19 @@ class Main {
broadcast(data);
case ClearChat:
+ if (!checkPermission(client, ClearChatPerm)) return;
messages.resize(0);
- if (client.isAdmin) broadcast(data);
+ broadcast(data);
case ClearPlaylist:
+ if (!checkPermission(client, RemoveVideoPerm)) return;
videoTimer.stop();
videoList.resize(0);
itemPos = 0;
broadcast(data);
case ShufflePlaylist:
+ if (!checkPermission(client, ChangeOrderPerm)) return;
if (videoList.length == 0) return;
final current = videoList[itemPos];
videoList.remove(current);
@@ -478,7 +512,7 @@ class Main {
}});
case TogglePlaylistLock:
- if (!client.isAdmin) return;
+ if (!checkPermission(client, LockPlaylistPerm)) return;
isPlaylistOpen = !isPlaylistOpen;
broadcast({
type: TogglePlaylistLock,
@@ -529,6 +563,24 @@ class Main {
}
}
+ function checkPermission(client:Client, perm:Permission):Bool {
+ final state = hasPermission(client, perm);
+ if (!state) send(client, {
+ type: ServerMessage, serverMessage: {
+ textId: "accessError"
+ }
+ });
+ return state;
+ }
+
+ function hasPermission(client:Client, perm:Permission):Bool {
+ final p = config.permissions;
+ if (client.isAdmin) return p.admin.indexOf(cast perm) != -1;
+ if (client.isLeader) return p.leader.indexOf(cast perm) != -1;
+ if (client.isUser) return p.user.indexOf(cast perm) != -1;
+ return p.guest.indexOf(cast perm) != -1;
+ }
+
final htmlChars = ~/[&^<>'"]/;
public function badNickName(name:String):Bool {
send patches to the email below
yukais@pinapelz.com
include the subject [PATCH repo_name]
pinapelz.com
homepage