Added kick & lil refactor

This commit is contained in:
Thomas
2020-08-13 17:12:46 +02:00
parent c1b3280fff
commit 63eca90f0e
11 changed files with 239 additions and 148 deletions

View File

@@ -1,23 +1,13 @@
<template> <template>
<div> <div>
<b-button @click="broadcastStatus" icon-left="sync">Force status update</b-button>
<hr>
<b-table :data="usersList" striped hoverable> <b-table :data="usersList" striped hoverable>
<template slot-scope="props"> <template slot-scope="props">
<b-table-column field="name" label="Name"> <b-table-column field="name" label="Name">
{{props.row.name}} {{props.row}}
</b-table-column>
<b-table-column field="connection" label="Connection">
{{props.row.connection.signalingState}}
</b-table-column>
<b-table-column field="data" label="DataChannel">
{{props.row.dataChannel.readyState}}
</b-table-column> </b-table-column>
<b-table-column> <b-table-column>
<b-button @click="kickUser(props.row.name)" icon-left="karate" type="is-dark"/> <b-button v-if="isAdmin" @click="kickUser(props.row)" icon-left="karate" type="is-dark"/>
</b-table-column> </b-table-column>
</template> </template>
</b-table> </b-table>
@@ -25,20 +15,21 @@
</template> </template>
<script> <script>
import { send } from '@/store/signalPlugin'
export default { export default {
name: 'Admin', name: 'Admin',
computed: { computed: {
usersList () { usersList () {
// return this.$store.state.rtc.peers return this.$store.state.room.roomStatus.users
return [] },
isAdmin () {
return this.$store.state.room.admin
} }
}, },
methods: { methods: {
broadcastStatus () {
// this.$store.dispatch('rtc/broadcast', { message: this.$store.state.room.roomStatus, type: 'status' })
},
kickUser (target) { kickUser (target) {
// this.$store.dispatch('rtc/kick', target) send({ name: target, type: 'roomUserKick' })
} }
} }
} }

View File

@@ -18,7 +18,8 @@ const state = {
votes: 0, votes: 0,
voters: [] voters: []
}, },
playlist: [] playlist: [],
users: []
}, },
roomSettings: { roomSettings: {
userControl: false, userControl: false,
@@ -125,6 +126,7 @@ const actions = {
}, },
playlist: [] playlist: []
}) })
router.push({ name: 'Home' })
} }
} }

View File

@@ -2,18 +2,24 @@ const connection = new WebSocket('ws://localhost:8181/socket')
// const connection = new WebSocket('wss://echo.websocket.org') // const connection = new WebSocket('wss://echo.websocket.org')
// const connection = new WebSocket('wss://voozik.gltronic.ovh/socket') // const connection = new WebSocket('wss://voozik.gltronic.ovh/socket')
setTimeout(send({ type: 'alive' }), 5000) var alive = null
export default function createSignalPlugin () { export default function createSignalPlugin () {
return store => { return store => {
connection.onopen = function () { connection.onopen = function () {
console.log('[WS] connected') console.log('[WS] connected')
store.dispatch('app/signalConnected') store.dispatch('app/signalConnected')
alive = setTimeout(send({ type: 'alive' }), 5000)
}
connection.onclose = function () {
clearTimeout(alive)
} }
connection.onerror = function (error) { connection.onerror = function (error) {
console.log('[WS] error ' + error) console.log('[WS] error ' + error.type)
store.dispatch('app/signalError', error) clearTimeout(alive)
store.dispatch('app/signalError', error.type)
} }
connection.onmessage = function (message) { connection.onmessage = function (message) {
@@ -23,7 +29,6 @@ export default function createSignalPlugin () {
switch (data.type) { switch (data.type) {
case 'leave': case 'leave':
store.dispatch('rtc/leave')
break break
case 'login': case 'login':
@@ -31,7 +36,7 @@ export default function createSignalPlugin () {
break break
case 'serverInfos': case 'serverInfos':
store.dispatch('app/serverStatus', data) store.dispatch('app/serverStatus', data.message)
break break
case 'roomCreate': case 'roomCreate':
@@ -47,7 +52,7 @@ export default function createSignalPlugin () {
break break
case 'roomStatus': case 'roomStatus':
if (!store.state.room.admin) store.dispatch('room/setRoomStatus', data.message) store.dispatch('room/setRoomStatus', data.message)
break break
case 'roomSettings': case 'roomSettings':
@@ -62,6 +67,10 @@ export default function createSignalPlugin () {
if (store.state.room.roomSettings.userControl) store.dispatch('room/setUserCommand', data.message) if (store.state.room.roomSettings.userControl) store.dispatch('room/setUserCommand', data.message)
break break
case 'roomUserKick':
store.dispatch('room/leave', data.message)
break
default: default:
break break
} }

View File

@@ -14,7 +14,7 @@
<Player /> <Player />
</b-tab-item> </b-tab-item>
<b-tab-item label="Peers" icon="lan" :visible="isAdmin"> <b-tab-item label="Users" icon="account-multiple">
<Admin /> <Admin />
</b-tab-item> </b-tab-item>
@@ -51,9 +51,6 @@ export default {
roomStatus () { roomStatus () {
return this.$store.state.room.roomStatus return this.$store.state.room.roomStatus
}, },
isAdmin () {
return this.$store.state.room.admin
},
isLoggedIn () { isLoggedIn () {
return this.$store.state.app.loginSuccess return this.$store.state.app.loginSuccess
}, },

View File

@@ -18,6 +18,7 @@ public interface IRoomManager {
public void forwardRoomMessage(WebSocketSession session, TextMessage message) throws InterruptedException, IOException; public void forwardRoomMessage(WebSocketSession session, TextMessage message) throws InterruptedException, IOException;
public void sendMessage(WebSocketSession session, String type, String message) throws InterruptedException, IOException; public void kickUser(WebSocketSession session, String username) throws InterruptedException, IOException;
public void sendServerInfos(WebSocketSession session) throws InterruptedException, IOException; public void sendServerInfos(WebSocketSession session) throws InterruptedException, IOException;
} }

View File

@@ -10,6 +10,7 @@ import org.springframework.stereotype.Service;
import org.springframework.web.socket.TextMessage; import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession; import org.springframework.web.socket.WebSocketSession;
import gltronic.voozik.model.ServerStatus;
import gltronic.voozik.model.VRoom; import gltronic.voozik.model.VRoom;
import gltronic.voozik.model.VUser; import gltronic.voozik.model.VUser;
@@ -18,19 +19,20 @@ public class RoomManager implements IRoomManager {
private volatile ArrayList<VUser> users = new ArrayList<VUser>(); private volatile ArrayList<VUser> users = new ArrayList<VUser>();
private volatile ArrayList<VRoom> rooms = new ArrayList<VRoom>(); private volatile ArrayList<VRoom> rooms = new ArrayList<VRoom>();
@Override
public void login(WebSocketSession session, String name) throws InterruptedException, IOException { public void login(WebSocketSession session, String name) throws InterruptedException, IOException {
if (name == null) { if (name == null) {
sendMessage(session, "error", "bad command command"); SocketUtils.sendMessage(session, "error", "bad command command");
return; return;
} }
if (users.stream().anyMatch(user -> user.getSession().equals(session))) { if (users.stream().anyMatch(user -> user.getSession().equals(session))) {
sendMessage(session, "login", "false"); SocketUtils.sendMessage(session, "login", "false");
return; return;
} }
if (users.stream().anyMatch(user -> user.getName().equals(name))) { if (users.stream().anyMatch(user -> user.getName().equals(name))) {
sendMessage(session, "login", "false"); SocketUtils.sendMessage(session, "login", "false");
return; return;
} }
@@ -40,21 +42,16 @@ public class RoomManager implements IRoomManager {
users.add(user); users.add(user);
sendMessage(session, "login", "true"); SocketUtils.sendMessage(session, "login", "true");
sendServerInfos(session); sendServerInfos(session);
System.err.println("[ROOM] Logged " + name); System.err.println("[ROOM] Logged " + name);
} }
@Override
public void leave(WebSocketSession session) throws InterruptedException, IOException { public void leave(WebSocketSession session) throws InterruptedException, IOException {
Optional<VUser> ouser = users.stream().filter(user -> user.getSession().equals(session)).findFirst(); VUser user = UserUtils.getUser(session, users);
if (user == null) return;
if (ouser.isEmpty()) {
sendMessage(session, "error", "need login");
return;
}
VUser user = ouser.get();
users.remove(user); users.remove(user);
Optional<VRoom> oroom = rooms.stream().filter(room -> room.getUsers().contains(user)).findFirst(); Optional<VRoom> oroom = rooms.stream().filter(room -> room.getUsers().contains(user)).findFirst();
@@ -64,16 +61,13 @@ public class RoomManager implements IRoomManager {
} }
} }
@Override
public void createRoom(WebSocketSession session) throws InterruptedException, IOException { public void createRoom(WebSocketSession session) throws InterruptedException, IOException {
if (!users.stream().anyMatch(user -> user.getSession().equals(session))) { VUser user = UserUtils.getUser(session, users);
sendMessage(session, "error", "need login"); if (user == null) return;
return;
}
VUser user = users.stream().filter(suser -> suser.getSession().equals(session)).findFirst().get();
if (user.getRoom() != null) { if (user.getRoom() != null) {
sendMessage(session, "error", "no already in room"); SocketUtils.sendMessage(session, "error", "no already in room");
return; return;
} }
@@ -92,36 +86,42 @@ public class RoomManager implements IRoomManager {
rooms.add(room); rooms.add(room);
user.setRoom(room); user.setRoom(room);
sendMessage(session, "roomCreate", roomCode); SocketUtils.sendMessage(session, "roomCreate", roomCode);
System.err.println("[ROOM] Created room " + roomCode + " by " + user.getName()); System.err.println("[ROOM] Created room " + roomCode + " by " + user.getName());
} }
@Override
public void connectRoom(WebSocketSession session, String roomCode) throws InterruptedException, IOException { public void connectRoom(WebSocketSession session, String roomCode) throws InterruptedException, IOException {
if (roomCode == null) { if (roomCode == null) {
sendMessage(session, "error", "bad command command"); SocketUtils.sendMessage(session, "error", "bad command command");
return;
}
if (!users.stream().anyMatch(user -> user.getSession().equals(session))) {
sendMessage(session, "error", "need login");
return; return;
} }
Optional<VRoom> oroom = rooms.stream().filter(room -> room.getCode().equals(roomCode)).findFirst(); Optional<VRoom> oroom = rooms.stream().filter(room -> room.getCode().equals(roomCode)).findFirst();
if (oroom.isEmpty()) { if (oroom.isEmpty()) {
sendMessage(session, "error", "no room"); SocketUtils.sendMessage(session, "error", "no room");
return; return;
} }
VRoom room = oroom.get(); VRoom room = oroom.get();
VUser user = users.stream().filter(suser -> suser.getSession().equals(session)).findFirst().get(); VUser user = UserUtils.getUser(session, users);
if (user == null) return;
room.getUsers().add(user);
user.setRoom(room); user.setRoom(room);
room.getUsers().add(user);
sendMessage(session, "roomConnect", "true"); ArrayList<String> usersName = new ArrayList<String>();
forwardMessage(session, "roomStatus", room.getRoomStatus()); room.getUsers().forEach(userL -> usersName.add(userL.getName()));
forwardMessage(session, "roomSettings", room.getRoomSettings());
JSONObject roomStatus = room.getRoomStatus();
roomStatus.put("users", usersName);
room.setRoomStatus(roomStatus);
SocketUtils.sendMessage(session, "roomConnect", "true");
SocketUtils.forwardMessage(session, "roomSettings", room.getRoomSettings());
SocketUtils.broadcast(room, "roomStatus", room.getRoomStatus());
SocketUtils.forwardMessage(room.getAdmin().getSession(), "roomStatus", room.getRoomStatus());
System.err System.err
.println("[ROOM] Connection to room " + roomCode + " (" + room.getAdmin().getName() + ") by " + user.getName()); .println("[ROOM] Connection to room " + roomCode + " (" + room.getAdmin().getName() + ") by " + user.getName());
@@ -129,127 +129,124 @@ public class RoomManager implements IRoomManager {
@Override @Override
public void leaveRoom(WebSocketSession session) throws InterruptedException, IOException { public void leaveRoom(WebSocketSession session) throws InterruptedException, IOException {
Optional<VUser> ouser = users.stream().filter(user -> user.getSession().equals(session)).findFirst(); VUser user = UserUtils.getUser(session, users);
if (user == null) return;
if (ouser.isEmpty()) { VRoom room = UserUtils.getRoom(session, user);
sendMessage(session, "error", "need login"); if (room == null) return;
return;
}
VUser user = ouser.get(); room.getUsers().remove(user);
if (user.getRoom() == null) {
sendMessage(session, "error", "no room");
return;
}
user.getRoom().getUsers().remove(user);
user.setRoom(null); user.setRoom(null);
ArrayList<String> usersName = new ArrayList<String>();
room.getUsers().forEach(userL -> usersName.add(userL.getName()));
JSONObject roomStatus = room.getRoomStatus();
roomStatus.put("users", usersName);
room.setRoomStatus(roomStatus);
SocketUtils.broadcast(room, "roomStatus", room.getRoomStatus());
SocketUtils.forwardMessage(room.getAdmin().getSession(), "roomStatus", room.getRoomStatus());
} }
@Override @Override
public void setRoomStatus(WebSocketSession session, TextMessage message) throws InterruptedException, IOException { public void setRoomStatus(WebSocketSession session, TextMessage message) throws InterruptedException, IOException {
Optional<VUser> ouser = users.stream().filter(user -> user.getSession().equals(session)).findFirst(); VUser user = UserUtils.getUser(session, users);
if (user == null) return;
if (ouser.isEmpty()) { VRoom room = UserUtils.getRoom(session, user);
sendMessage(session, "error", "need login"); if (room == null) return;
return;
}
VUser user = ouser.get(); if (!UserUtils.checkIsAdmin(session, user)) return;
if (user.getRoom() == null) {
sendMessage(session, "error", "no room");
return;
}
if (!user.getRoom().getAdmin().equals(user)) {
sendMessage(session, "error", "not admin");
return;
}
String payload = message.getPayload(); String payload = message.getPayload();
JSONObject jsonObject = new JSONObject(payload); JSONObject jsonObject = new JSONObject(payload);
user.getRoom().setRoomStatus((JSONObject) jsonObject.get("message")); ArrayList<String> usersName = new ArrayList<String>();
broadcast(user.getRoom(), "roomStatus", user.getRoom().getRoomStatus()); room.getUsers().forEach(userL -> usersName.add(userL.getName()));
JSONObject roomStatus = (JSONObject) jsonObject.get("message");
roomStatus.put("users", usersName);
room.setRoomStatus(roomStatus);
SocketUtils.broadcast(room, "roomStatus", room.getRoomStatus());
SocketUtils.forwardMessage(session, "roomStatus", room.getRoomStatus());
} }
@Override @Override
public void setRoomSettings(WebSocketSession session, TextMessage message) throws InterruptedException, IOException { public void setRoomSettings(WebSocketSession session, TextMessage message) throws InterruptedException, IOException {
Optional<VUser> ouser = users.stream().filter(user -> user.getSession().equals(session)).findFirst(); VUser user = UserUtils.getUser(session, users);
if (user == null) return;
if (ouser.isEmpty()) { VRoom room = UserUtils.getRoom(session, user);
sendMessage(session, "error", "need login"); if (room == null) return;
return;
}
VUser user = ouser.get(); if (!UserUtils.checkIsAdmin(session, user)) return;
if (user.getRoom() == null) {
sendMessage(session, "error", "no room");
return;
}
if (!user.getRoom().getAdmin().equals(user)) {
sendMessage(session, "error", "not admin");
return;
}
String payload = message.getPayload(); String payload = message.getPayload();
JSONObject jsonObject = new JSONObject(payload); JSONObject jsonObject = new JSONObject(payload);
user.getRoom().setRoomSettings((JSONObject) jsonObject.get("message")); room.setRoomSettings((JSONObject) jsonObject.get("message"));
broadcast(user.getRoom(), "roomSettings", user.getRoom().getRoomSettings()); SocketUtils.broadcast(room, "roomSettings", room.getRoomSettings());
}
public void sendMessage(WebSocketSession session, String type, String message) throws InterruptedException, IOException {
session.sendMessage(new TextMessage("{\"type\":\"" + type + "\",\"message\": \"" + message.toString() + "\" }"));
}
public void forwardMessage(WebSocketSession session, String type, JSONObject message) throws InterruptedException, IOException {
session.sendMessage(new TextMessage("{\"type\":\"" + type + "\",\"message\": " + message.toString() + " }"));
}
public void broadcast(VRoom room, String type, JSONObject message) {
room.getUsers().forEach(user -> {
try {
forwardMessage(user.getSession(), type, message);
} catch (InterruptedException | IOException e) {
e.printStackTrace();
}
});
}
public void sendServerInfos(WebSocketSession session) throws InterruptedException, IOException {
session.sendMessage(new TextMessage(
"{\"type\":\"serverInfos\",\"userCount\":\"" + users.size() + "\",\"roomCount\":\"" + rooms.size() + "\"}"));
} }
@Override @Override
public void forwardRoomMessage(WebSocketSession session, TextMessage message) throws InterruptedException, IOException { public void forwardRoomMessage(WebSocketSession session, TextMessage message) throws InterruptedException, IOException {
Optional<VUser> ouser = users.stream().filter(user -> user.getSession().equals(session)).findFirst(); VUser user = UserUtils.getUser(session, users);
if (user == null) return;
if (ouser.isEmpty()) { VRoom room = UserUtils.getRoom(session, user);
sendMessage(session, "error", "need login"); if (room == null) return;
return;
}
VUser user = ouser.get();
if (user.getRoom() == null) {
sendMessage(session, "error", "no room");
return;
}
String payload = message.getPayload(); String payload = message.getPayload();
JSONObject jsonObject = new JSONObject(payload); JSONObject jsonObject = new JSONObject(payload);
String type = (String) jsonObject.get("type"); String type = (String) jsonObject.get("type");
JSONObject data = (JSONObject) jsonObject.get("message"); JSONObject data = (JSONObject) jsonObject.get("message");
if (user.getRoom().getAdmin().equals(user)) broadcast(user.getRoom(), type, data); if (room.getAdmin().equals(user)) SocketUtils.broadcast(room, type, data);
else forwardMessage(user.getRoom().getAdmin().getSession(), type, data); else SocketUtils.forwardMessage(room.getAdmin().getSession(), type, data);
} }
@Override
public void kickUser(WebSocketSession session, String username) throws InterruptedException, IOException {
VUser user = UserUtils.getUser(session, users);
if (user == null) return;
VRoom room = UserUtils.getRoom(session, user);
if (room == null) return;
if (!UserUtils.checkIsAdmin(session, user)) return;
if (username.isEmpty()) {
SocketUtils.sendMessage(session, "error", "bad command command");
return;
}
Optional<VUser> ouserToKick = room.getUsers().stream().filter(userL -> userL.getName().equals(username)).findFirst();
if (!ouserToKick.isPresent()) return;
VUser userToKick = ouserToKick.get();
room.getUsers().remove(userToKick);
SocketUtils.sendMessage(userToKick.getSession(), "roomUserKick", "true");
SocketUtils.broadcast(room, "roomStatus", room.getRoomStatus());
SocketUtils.forwardMessage(session, "roomStatus", room.getRoomStatus());
}
public void sendServerInfos(WebSocketSession session) throws InterruptedException, IOException {
ServerStatus status = new ServerStatus();
status.setRoomCount(rooms.size());
status.setUserCount(users.size());
status.setRooms(new ArrayList<String>());
rooms.forEach(room -> {
if(room.isPublic()) status.getRooms().add(room.getCode());
});
SocketUtils.forwardMessage(session, "serverInfos", new JSONObject(status));
}
} }

View File

@@ -0,0 +1,33 @@
package gltronic.voozik.business;
import java.io.IOException;
import org.json.JSONObject;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import gltronic.voozik.model.VRoom;
public class SocketUtils {
public static void sendMessage(WebSocketSession session, String type, String message) {
try {
session.sendMessage(new TextMessage("{\"type\":\"" + type + "\",\"message\": \"" + message.toString() + "\" }"));
} catch (IOException e) {
e.printStackTrace();
}
}
public static void forwardMessage(WebSocketSession session, String type, JSONObject message) {
try {
session.sendMessage(new TextMessage("{\"type\":\"" + type + "\",\"message\": " + message.toString() + " }"));
} catch (IOException e) {
e.printStackTrace();
}
}
public static void broadcast(VRoom room, String type, JSONObject message) {
room.getUsers().forEach(user -> {
forwardMessage(user.getSession(), type, message);
});
}
}

View File

@@ -0,0 +1,38 @@
package gltronic.voozik.business;
import java.util.ArrayList;
import java.util.Optional;
import org.springframework.web.socket.WebSocketSession;
import gltronic.voozik.model.VRoom;
import gltronic.voozik.model.VUser;
public class UserUtils {
public static VUser getUser (WebSocketSession session, ArrayList<VUser> users) {
Optional<VUser> ouser = users.stream().filter(user -> user.getSession().equals(session)).findFirst();
if (ouser.isEmpty()) {
SocketUtils.sendMessage(session, "error", "need login");
return null;
}
return ouser.get();
}
public static VRoom getRoom (WebSocketSession session, VUser user) {
if (user.getRoom() == null) {
SocketUtils.sendMessage(session, "error", "no room");
return null;
}
else return user.getRoom();
}
public static boolean checkIsAdmin (WebSocketSession session, VUser user) {
if (!user.getRoom().getAdmin().equals(user)) {
SocketUtils.sendMessage(session, "error", "not admin");
return false;
}
else return true;
}
}

View File

@@ -0,0 +1,18 @@
package gltronic.voozik.model;
import java.io.Serializable;
import java.util.List;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@Getter
@Setter
@NoArgsConstructor
public class ServerStatus implements Serializable{
private static final long serialVersionUID = 1L;
int userCount;
int roomCount;
List<String> rooms;
}

View File

@@ -13,6 +13,7 @@ import lombok.Setter;
@NoArgsConstructor @NoArgsConstructor
public class VRoom { public class VRoom {
private String code; private String code;
private String name;
private boolean isPublic; private boolean isPublic;
private JSONObject roomStatus; private JSONObject roomStatus;
private JSONObject roomSettings; private JSONObject roomSettings;

View File

@@ -13,6 +13,7 @@ import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler; import org.springframework.web.socket.handler.TextWebSocketHandler;
import gltronic.voozik.business.IRoomManager; import gltronic.voozik.business.IRoomManager;
import gltronic.voozik.business.SocketUtils;
@Component @Component
public class SocketHandler extends TextWebSocketHandler { public class SocketHandler extends TextWebSocketHandler {
@@ -55,6 +56,9 @@ public class SocketHandler extends TextWebSocketHandler {
case "roomSettings": case "roomSettings":
roomManager.setRoomSettings(session, message); roomManager.setRoomSettings(session, message);
break; break;
case "roomUserKick":
roomManager.kickUser(session, (String) jsonObject.get("name"));
break;
case "roomVote": case "roomVote":
case "roomUserCommand": case "roomUserCommand":
roomManager.forwardRoomMessage(session, message); roomManager.forwardRoomMessage(session, message);
@@ -64,7 +68,7 @@ public class SocketHandler extends TextWebSocketHandler {
case "alive": case "alive":
break; break;
default: default:
roomManager.sendMessage(session, "error", "unknow command"); SocketUtils.sendMessage(session, "error", "unknow command");
} }
} }