New view-only mode for client

This commit is contained in:
Carlos 2020-06-22 19:24:46 +02:00
parent d8c71045d2
commit 209244bd22
7 changed files with 128 additions and 66 deletions

View File

@ -111,9 +111,19 @@
</div> </div>
</div> </div>
<div class="col-sm-3 mb-2"> <div class="col-sm-3 mb-2">
<button type="button" class="btn btn-danger" id="deleteServerButton">Delete server</button> <div class="card">
<div class="card-body">
<p class="card-text">
<span id="user_title">Logged as</span>
<span id="loggedUsernameLabel"></span>
(<span id="loggedUserTypeLabel"></span>)
</p>
<button type="button" class="btn btn-danger btn-sm" id="deleteServerButton">Delete server</button>
</div>
</div>
</div> </div>
</div> </div>
<div class="card mb-2"> <div class="card mb-2">
<div class="card-body overflow-auto text-light bg-dark console" id="consoleTextArea"></div> <div class="card-body overflow-auto text-light bg-dark console" id="consoleTextArea"></div>
</div> </div>

View File

@ -55,8 +55,20 @@ function onWebSocketsMessage(message){
writeToWebConsole(message.message, message.time); writeToWebConsole(message.message, message.time);
break; break;
case 200: case 200:
//Processed //LoggedIn
writeToWebConsole(message.message); writeToWebConsole(message.message);
//Show user and permissions
$("#loggedUsernameLabel").text(message.username);
$("#loggedUserTypeLabel").text(message.as);
//Disable command bar if user is viewer
if(message.as.toLowerCase() == "viewer"){
$("#commandInput").prop("disabled", true);
$("#sendCommandButton").prop("disabled", true);
}
//Read log file if enabled
if(connectionManager.activeConnection.isLogged === false){ if(connectionManager.activeConnection.isLogged === false){
connectionManager.activeConnection.isLogged = true; connectionManager.activeConnection.isLogged = true;
if(persistenceManager.getSetting("retrieveLogFile") === true) if(persistenceManager.getSetting("retrieveLogFile") === true)

View File

@ -2,11 +2,6 @@ package es.mesacarlos.webconsole.auth;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Map;
import org.bukkit.Bukkit;
import es.mesacarlos.webconsole.WebConsole;
public class LoginManager { public class LoginManager {
private ArrayList<User> loggedInUsers = new ArrayList<User>(); private ArrayList<User> loggedInUsers = new ArrayList<User>();
@ -38,6 +33,11 @@ public class LoginManager {
loggedInUsers.remove(user); loggedInUsers.remove(user);
} }
/**
* Get user object by socket
* @param address socket of the user
* @return User object, null if no user logged in from that address
*/
public User getUser(InetSocketAddress address) { public User getUser(InetSocketAddress address) {
for(User user : loggedInUsers) for(User user : loggedInUsers)
if(user.getSocketAddress().equals(address)) if(user.getSocketAddress().equals(address))
@ -65,52 +65,4 @@ public class LoginManager {
return loggedInUsers; return loggedInUsers;
} }
/**
* Check if the provided password corresponds to any admin
* @param password Provided password
* @return Name of the user if password corresponds to a valid admin, null if is a viewer or an invalid password
*/
public String isValidAdminPassword(String password) {
WebConsole plugin = (WebConsole)Bukkit.getPluginManager().getPlugin("WebConsole");
Map<String, Object> passwords = plugin.getConfig().getConfigurationSection("passwords").getConfigurationSection("admin").getValues(false);
for(Map.Entry<String, Object> entry : passwords.entrySet()) {
String pwd = (String)entry.getValue();
if(pwd.equals(password))
return entry.getKey();
}
return null;
}
/**
* Check if the provided password corresponds to any viewer
* @param password Provided password
* @return Name of the user if password corresponds to a valid viewer, null if is a admin or invalid password
*/
public String isValidViewerPassword(String password) {
WebConsole plugin = (WebConsole)Bukkit.getPluginManager().getPlugin("WebConsole");
Map<String, Object> passwords = plugin.getConfig().getConfigurationSection("passwords").getConfigurationSection("viewer").getValues(false);
for(Map.Entry<String, Object> entry : passwords.entrySet()) {
String pwd = (String)entry.getValue();
if(pwd.equals(password))
return entry.getKey();
}
return null;
}
public UserType isValidUser(String password) {
//Check if is an admin
String username = isValidAdminPassword(password);
if(username != null)
return UserType.ADMIN;
//Check if is a viewer
username = isValidViewerPassword(password);
if(username != null)
return UserType.VIEWER;
//He is nothing
return UserType.UNKNOWN;
}
} }

View File

@ -0,0 +1,65 @@
package es.mesacarlos.webconsole.auth;
import java.util.Map;
import org.bukkit.Bukkit;
import es.mesacarlos.webconsole.WebConsole;
public class PasswordManager {
/**
* Get the user type of a given password
* @param password Password to check
* @return ADMIN if password correspond to a admin user, VIEWER if viewer or UNKNOWN if invalid password
*/
public static UserType isValidUser(String password) {
//Check if is an admin
String username = isValidAdminPassword(password);
if(username != null)
return UserType.ADMIN;
//Check if is a viewer
username = isValidViewerPassword(password);
if(username != null)
return UserType.VIEWER;
//He is nothing
return UserType.UNKNOWN;
}
/**
* Check if the provided password corresponds to any admin
* @param password Provided password
* @return Name of the user if password corresponds to a valid admin, null if is a viewer or an invalid password
*/
public static String isValidAdminPassword(String password) {
WebConsole plugin = (WebConsole)Bukkit.getPluginManager().getPlugin("WebConsole");
Map<String, Object> passwords = plugin.getConfig().getConfigurationSection("passwords").getConfigurationSection("admin").getValues(false);
for(Map.Entry<String, Object> entry : passwords.entrySet()) {
String pwd = (String)entry.getValue();
if(pwd.equals(password))
return entry.getKey();
}
return null;
}
/**
* Check if the provided password corresponds to any viewer
* @param password Provided password
* @return Name of the user if password corresponds to a valid viewer, null if is a admin or invalid password
*/
public static String isValidViewerPassword(String password) {
WebConsole plugin = (WebConsole)Bukkit.getPluginManager().getPlugin("WebConsole");
Map<String, Object> passwords = plugin.getConfig().getConfigurationSection("passwords").getConfigurationSection("viewer").getValues(false);
for(Map.Entry<String, Object> entry : passwords.entrySet()) {
String pwd = (String)entry.getValue();
if(pwd.equals(password))
return entry.getKey();
}
return null;
}
}

View File

@ -19,7 +19,7 @@ import es.mesacarlos.webconsole.websocket.command.WSCommand;
import es.mesacarlos.webconsole.websocket.response.ConsoleOutput; import es.mesacarlos.webconsole.websocket.response.ConsoleOutput;
import es.mesacarlos.webconsole.websocket.response.JSONOutput; import es.mesacarlos.webconsole.websocket.response.JSONOutput;
import es.mesacarlos.webconsole.websocket.response.LoginRequired; import es.mesacarlos.webconsole.websocket.response.LoginRequired;
import es.mesacarlos.webconsole.websocket.response.Processed; import es.mesacarlos.webconsole.websocket.response.LoggedIn;
import es.mesacarlos.webconsole.websocket.response.UnknownCommand; import es.mesacarlos.webconsole.websocket.response.UnknownCommand;
public class WSServer extends WebSocketServer { public class WSServer extends WebSocketServer {
@ -34,7 +34,7 @@ public class WSServer extends WebSocketServer {
@Override @Override
public void onOpen(WebSocket conn, ClientHandshake handshake) { public void onOpen(WebSocket conn, ClientHandshake handshake) {
if (LoginManager.getInstance().isLoggedIn(conn.getRemoteSocketAddress())) { if (LoginManager.getInstance().isLoggedIn(conn.getRemoteSocketAddress())) {
sendToClient(conn, new Processed(Internationalization.getPhrase("connection-resumed-message"))); sendToClient(conn, new LoggedIn(Internationalization.getPhrase("connection-resumed-message")));
Bukkit.getLogger().info(Internationalization.getPhrase("connection-resumed-console", conn.getRemoteSocketAddress())); Bukkit.getLogger().info(Internationalization.getPhrase("connection-resumed-console", conn.getRemoteSocketAddress()));
} else { } else {
sendToClient(conn, new LoginRequired(Internationalization.getPhrase("connection-login-message"))); sendToClient(conn, new LoginRequired(Internationalization.getPhrase("connection-login-message")));

View File

@ -4,12 +4,13 @@ import org.bukkit.Bukkit;
import org.java_websocket.WebSocket; import org.java_websocket.WebSocket;
import es.mesacarlos.webconsole.auth.LoginManager; import es.mesacarlos.webconsole.auth.LoginManager;
import es.mesacarlos.webconsole.auth.PasswordManager;
import es.mesacarlos.webconsole.auth.User; import es.mesacarlos.webconsole.auth.User;
import es.mesacarlos.webconsole.auth.UserType; import es.mesacarlos.webconsole.auth.UserType;
import es.mesacarlos.webconsole.util.Internationalization; import es.mesacarlos.webconsole.util.Internationalization;
import es.mesacarlos.webconsole.websocket.WSServer; import es.mesacarlos.webconsole.websocket.WSServer;
import es.mesacarlos.webconsole.websocket.response.LoginRequired; import es.mesacarlos.webconsole.websocket.response.LoginRequired;
import es.mesacarlos.webconsole.websocket.response.Processed; import es.mesacarlos.webconsole.websocket.response.LoggedIn;
public class LogInCommand implements WSCommand { public class LogInCommand implements WSCommand {
@ -20,12 +21,12 @@ public class LogInCommand implements WSCommand {
return; return;
//Check user type and login is password is valid //Check user type and login is password is valid
switch(LoginManager.getInstance().isValidUser(password)) { switch(PasswordManager.isValidUser(password)) {
case ADMIN: case ADMIN:
login(wsServer, conn, LoginManager.getInstance().isValidAdminPassword(password), UserType.ADMIN); login(wsServer, conn, PasswordManager.isValidAdminPassword(password), UserType.ADMIN);
break; break;
case VIEWER: case VIEWER:
login(wsServer, conn, LoginManager.getInstance().isValidViewerPassword(password), UserType.VIEWER); login(wsServer, conn, PasswordManager.isValidViewerPassword(password), UserType.VIEWER);
break; break;
case UNKNOWN: case UNKNOWN:
wsServer.sendToClient(conn, new LoginRequired(Internationalization.getPhrase("login-failed-message"))); wsServer.sendToClient(conn, new LoginRequired(Internationalization.getPhrase("login-failed-message")));
@ -43,7 +44,7 @@ public class LogInCommand implements WSCommand {
User user = new User(conn.getRemoteSocketAddress(), username, as); User user = new User(conn.getRemoteSocketAddress(), username, as);
LoginManager.getInstance().logIn(user); LoginManager.getInstance().logIn(user);
wsServer.sendToClient(conn, new Processed(Internationalization.getPhrase("login-sucessful-message"), "LOGIN ********")); wsServer.sendToClient(conn, new LoggedIn(Internationalization.getPhrase("login-sucessful-message"), "LOGIN ********", user.getUsername(), user.getUserType()));
Bukkit.getLogger().info(Internationalization.getPhrase("login-sucessful-console", user.toString())); Bukkit.getLogger().info(Internationalization.getPhrase("login-sucessful-console", user.toString()));
} }

View File

@ -2,17 +2,23 @@ package es.mesacarlos.webconsole.websocket.response;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
public class Processed implements JSONOutput{ import es.mesacarlos.webconsole.auth.UserType;
public class LoggedIn implements JSONOutput{
private String message; private String message;
private String respondsTo; private String respondsTo;
private String username;
private UserType as;
public Processed(String message) { public LoggedIn(String message) {
this.message = message; this.message = message;
} }
public Processed(String message, String respondsTo) { public LoggedIn(String message, String respondsTo, String username, UserType as) {
this.message = message; this.message = message;
this.respondsTo = respondsTo; this.respondsTo = respondsTo;
this.username = username;
this.as = as;
} }
@Override @Override
@ -33,12 +39,28 @@ public class Processed implements JSONOutput{
return respondsTo; return respondsTo;
} }
public String getUsername() {
return username;
}
public String getAs() {
switch(as) {
case ADMIN:
return "ADMIN";
default:
return "VIEWER"; //This is not a security hole bc its just informative...
}
}
@Override @Override
public String toJSON() { public String toJSON() {
JsonObject object = new JsonObject(); JsonObject object = new JsonObject();
object.addProperty("status", getStatusCode()); object.addProperty("status", getStatusCode());
object.addProperty("statusDescription", "Processed"); object.addProperty("statusDescription", "LoggedIn");
object.addProperty("respondsTo", getRespondsTo()); object.addProperty("respondsTo", getRespondsTo());
object.addProperty("username", getUsername());
object.addProperty("as", getAs());
object.addProperty("message", getMessage()); object.addProperty("message", getMessage());
return object.toString(); return object.toString();
} }