From aad90bb989983d97f1b42679025a49e596f0eba7 Mon Sep 17 00:00:00 2001 From: "Notmoo-PC\\Notmoo" Date: Wed, 1 Nov 2017 21:22:23 +0100 Subject: [PATCH] [VRAC] Corrections de bug #1/? MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bug détectés restants : - MainFrame pas mise à jour avec le compte utilisateur connecté lorsqu'on switch dessus depuis la StartFrame - Le serveur renvoie REFUSED_QUERY lorsqu'on tente de se déconnecter --- .../src/main/java/com/pqt/client/Main.java | 5 +- .../startup_frame/StartupFrameController.java | 2 +- .../StartupProcedureHandler.java | 4 +- .../connection/senders/HttpTextSender.java | 6 +- .../client/module/network/NetworkService.java | 4 +- .../communication/GSonMessageToolFactory.java | 49 ++++++++++++++- Workspace/server/src/main/WEB-INF/web.xml | 11 ++++ .../server/module/account/FileAccountDao.java | 24 +++++-- .../server/module/account/IAccountDao.java | 12 +++- .../pqt/server/module/stock/FileStockDao.java | 5 +- .../com/pqt/server/servlets/QueryServlet.java | 12 +++- .../java/com/pqt/server/tools/FileUtil.java | 2 +- .../tools/io/SimpleSerialFileManager.java | 4 +- .../io/SimpleSerialFileManagerFactory.java | 3 +- .../server/tools/security/RandomString.java | 62 +++++++++++++++++++ 15 files changed, 183 insertions(+), 22 deletions(-) create mode 100644 Workspace/server/src/main/WEB-INF/web.xml create mode 100644 Workspace/server/src/main/java/com/pqt/server/tools/security/RandomString.java diff --git a/Workspace/client/src/main/java/com/pqt/client/Main.java b/Workspace/client/src/main/java/com/pqt/client/Main.java index 311fd517..9582e9c3 100644 --- a/Workspace/client/src/main/java/com/pqt/client/Main.java +++ b/Workspace/client/src/main/java/com/pqt/client/Main.java @@ -58,9 +58,12 @@ public class Main extends Application{ } private IStartupFrameModelListener getStartupFrameListener(Stage primaryStage, Scene sceneToDisplay){ - return () -> trySwitchScene(primaryStage, sceneToDisplay, true); + return () -> { + Platform.runLater(()->trySwitchScene(primaryStage, sceneToDisplay, true)); + }; } + private IMainFrameModelListener getMainFrameListener(Stage primaryStage, Scene sceneToDisplay){ return () -> trySwitchScene(primaryStage, sceneToDisplay, false); } diff --git a/Workspace/client/src/main/java/com/pqt/client/gui/startup_frame/StartupFrameController.java b/Workspace/client/src/main/java/com/pqt/client/gui/startup_frame/StartupFrameController.java index f9bb07d1..9789a551 100644 --- a/Workspace/client/src/main/java/com/pqt/client/gui/startup_frame/StartupFrameController.java +++ b/Workspace/client/src/main/java/com/pqt/client/gui/startup_frame/StartupFrameController.java @@ -35,7 +35,7 @@ public class StartupFrameController implements IStartupFrameModelListener { view.getAccountUsernameTextFieldContent(), view.getAccountPasswordTextFieldContent() ); - }catch(NullPointerException | IllegalArgumentException e){ + }catch(Exception e){ view.displayError(GUIStringTool.getExceptionFormatter().render(e)); } } diff --git a/Workspace/client/src/main/java/com/pqt/client/gui/startup_frame/StartupProcedureHandler.java b/Workspace/client/src/main/java/com/pqt/client/gui/startup_frame/StartupProcedureHandler.java index b79c9f22..b3a323a2 100644 --- a/Workspace/client/src/main/java/com/pqt/client/gui/startup_frame/StartupProcedureHandler.java +++ b/Workspace/client/src/main/java/com/pqt/client/gui/startup_frame/StartupProcedureHandler.java @@ -2,6 +2,7 @@ package com.pqt.client.gui.startup_frame; import com.pqt.client.gui.startup_frame.listeners.procedure.IStartupProcedureEventFirerer; import com.pqt.client.gui.startup_frame.listeners.procedure.IStartupProcedureListener; +import com.pqt.client.gui.startup_frame.listeners.procedure.SimpleStartupProcedureEventFirerer; import com.pqt.client.module.account.AccountService; import com.pqt.client.module.account.listeners.AccountListenerAdapter; import com.pqt.client.module.account.listeners.IAccountListener; @@ -22,6 +23,7 @@ class StartupProcedureHandler { StartupProcedureHandler(NetworkService networkService, AccountService accountService) { this.networkService = networkService; this.accountService = accountService; + firerer = new SimpleStartupProcedureEventFirerer(); } StartupProcedureHandler init(String host, Integer port, String username, String password){ @@ -39,13 +41,13 @@ class StartupProcedureHandler { private void testConnection(){ networkService.addListener(getPingListener()); + networkService.setActiveServer(host, port); networkService.sendPQTPing(host, port); } private void useRequestedServer(){ //Server found firerer.fireServerFoundEvent(host, port); - networkService.setActiveServer(host, port); accountService.addListener(getUpdateAccountListListener()); accountService.refreshAccounts(); } diff --git a/Workspace/client/src/main/java/com/pqt/client/module/connection/senders/HttpTextSender.java b/Workspace/client/src/main/java/com/pqt/client/module/connection/senders/HttpTextSender.java index 993d434f..95042041 100644 --- a/Workspace/client/src/main/java/com/pqt/client/module/connection/senders/HttpTextSender.java +++ b/Workspace/client/src/main/java/com/pqt/client/module/connection/senders/HttpTextSender.java @@ -1,6 +1,7 @@ package com.pqt.client.module.connection.senders; import com.pqt.client.module.connection.listeners.IConnectionListener; +import com.sun.javafx.binding.StringFormatter; import java.io.BufferedReader; import java.io.DataOutputStream; @@ -14,7 +15,10 @@ public class HttpTextSender implements ITextSender{ @Override public void send(String url, String text, IConnectionListener listener) { try { - HttpURLConnection con = (HttpURLConnection) new URL(url).openConnection(); + String trueURL = String.format("http://%s?message=%s", url, text); + + + HttpURLConnection con = (HttpURLConnection) new URL(trueURL).openConnection(); con.setRequestMethod("GET"); con.setRequestProperty("Content-Type", "application/json"); con.setConnectTimeout(5000); diff --git a/Workspace/client/src/main/java/com/pqt/client/module/network/NetworkService.java b/Workspace/client/src/main/java/com/pqt/client/module/network/NetworkService.java index 154265d6..def9bb1d 100644 --- a/Workspace/client/src/main/java/com/pqt/client/module/network/NetworkService.java +++ b/Workspace/client/src/main/java/com/pqt/client/module/network/NetworkService.java @@ -73,7 +73,9 @@ public class NetworkService { } public void setActiveServer(String host, Integer port){ - connectionService.setServerUrl(String.format("%s:%s", host, port)); + //TODO changer le nom de context de la webapp + String webAppContext = "pqt-server"; + connectionService.setServerUrl(String.format("%s:%s/%s", host, port, webAppContext)); } private void sendConfigRequest(String host, Integer port){ diff --git a/Workspace/core/src/main/java/com/pqt/core/communication/GSonMessageToolFactory.java b/Workspace/core/src/main/java/com/pqt/core/communication/GSonMessageToolFactory.java index 939c3bda..d6cfbcd7 100644 --- a/Workspace/core/src/main/java/com/pqt/core/communication/GSonMessageToolFactory.java +++ b/Workspace/core/src/main/java/com/pqt/core/communication/GSonMessageToolFactory.java @@ -4,6 +4,7 @@ import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.reflect.TypeToken; +import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.List; @@ -20,13 +21,55 @@ public class GSonMessageToolFactory implements IMessageToolFactory { return (obj)->gson.toJson(obj); } public IObjectParser getObjectParser(Class clazz){ - return (str)->gson.fromJson(str, clazz); + return (str)->gson.fromJson(str, new Element<>(clazz)); } public IObjectFormatter> getListFormatter(Class clazz){ return (obj)->gson.toJson(obj); } public IObjectParser> getListParser(Class clazz){ - Type listType = new TypeToken>(){}.getType(); - return (str)->gson.fromJson(str, listType); + //Type listType = new TypeToken>(){}.getType(); + return (str)->gson.fromJson(str, new ListWithElements<>(clazz)); + } + + private class Element implements ParameterizedType { + + private Class cl; + + public Element(Class cl) { + this.cl = cl; + } + + public Type[] getActualTypeArguments() { + return new Type[] {cl}; + } + + public Type getRawType() { + return cl; + } + + public Type getOwnerType() { + return null; + } + } + + private class ListWithElements implements ParameterizedType { + + private Class elementsClass; + + public ListWithElements(Class elementsClass) { + this.elementsClass = elementsClass; + } + + public Type[] getActualTypeArguments() { + return new Type[] {elementsClass}; + } + + public Type getRawType() { + return List.class; + } + + public Type getOwnerType() { + return null; + } } } diff --git a/Workspace/server/src/main/WEB-INF/web.xml b/Workspace/server/src/main/WEB-INF/web.xml new file mode 100644 index 00000000..0c9131ad --- /dev/null +++ b/Workspace/server/src/main/WEB-INF/web.xml @@ -0,0 +1,11 @@ + + + + + + res-file.location + G:\temp\ + + \ No newline at end of file diff --git a/Workspace/server/src/main/java/com/pqt/server/module/account/FileAccountDao.java b/Workspace/server/src/main/java/com/pqt/server/module/account/FileAccountDao.java index 24364a18..50079ce4 100644 --- a/Workspace/server/src/main/java/com/pqt/server/module/account/FileAccountDao.java +++ b/Workspace/server/src/main/java/com/pqt/server/module/account/FileAccountDao.java @@ -5,6 +5,7 @@ import com.pqt.core.entities.user_account.AccountLevel; import com.pqt.server.tools.io.ISerialFileManager; import com.pqt.server.tools.io.SimpleSerialFileManagerFactory; import com.pqt.server.tools.security.IHashTool; +import com.pqt.server.tools.security.RandomString; import com.pqt.server.tools.security.SHA256HashTool; import java.util.*; @@ -22,19 +23,22 @@ import java.util.stream.Collectors; * Cette classe manipule les mot de passe sous forme chiffrée via un système de hash (SHA-256) + salt, et ne fait pas * persister les mots de passes non-chiffrées. Les noms d'utilisateurs sont stockés sans chiffrage. */ -class FileAccountDao implements IAccountDao { +public class FileAccountDao implements IAccountDao { - private static final String ACCOUNT_FILE_NAME = "acc.pqt"; + //TODO to modify + private static final String ACCOUNT_FILE_NAME = "G:\\temp\\acc.pqt"; private Set accountEntries; private Set connectedAccount; private IHashTool hashTool; + private RandomString randomString; private ISerialFileManager fileManager; - FileAccountDao() { + public FileAccountDao() { accountEntries = new HashSet<>(); connectedAccount = new HashSet<>(); hashTool = new SHA256HashTool(); + randomString = new RandomString(10); fileManager = SimpleSerialFileManagerFactory.getFileManager(AccountEntry.class, ACCOUNT_FILE_NAME); loadFromFile(); } @@ -96,7 +100,7 @@ class FileAccountDao implements IAccountDao { } /** - * Passe un comtpe connecté dans l'état déconnecté. N'effectue le changement que si un compte connecté correspond + * Passe un compte connecté dans l'état déconnecté. N'effectue le changement que si un compte connecté correspond * aux données fournies. * @param account données à utiliser pour efffectuer la correspondance avec un compte * @return {@code true} si le changement d'état a eu lieu, {@code false sinon} @@ -134,6 +138,18 @@ class FileAccountDao implements IAccountDao { fileManager.saveSetToFile(accountEntries); } + public boolean addAccount(Account account){ + if(accountEntries.stream().filter(accountEntry -> accountEntry.getUsername().equals(account.getUsername())).count()==0) { + String salt = randomString.nextString(); + String passwordHash = hashTool.hashAndSalt(account.getPassword(), salt); + accountEntries.add(new AccountEntry(account.getUsername(), passwordHash, salt, account.getPermissionLevel())); + saveToFile(); + return true; + }else{ + return false; + } + } + /** * Charge les données des comptes depuis le fichier de sauvegarde. *

diff --git a/Workspace/server/src/main/java/com/pqt/server/module/account/IAccountDao.java b/Workspace/server/src/main/java/com/pqt/server/module/account/IAccountDao.java index 04c70f81..0d53ee58 100644 --- a/Workspace/server/src/main/java/com/pqt/server/module/account/IAccountDao.java +++ b/Workspace/server/src/main/java/com/pqt/server/module/account/IAccountDao.java @@ -16,7 +16,7 @@ import java.util.List; * * @author Guillaume "Cess" Prost */ -interface IAccountDao { +public interface IAccountDao { /** * @see AccountService#isAccountConnected(Account) @@ -59,4 +59,14 @@ interface IAccountDao { * de données. */ List getAccountList(); + + /** + * Ajoute un objet {@link Account} dans la collection de comptes utilisateurs. + *

+ * Les implémentations doivent en outre effectuer une vérification pour s'assurer que le compte à rajouter ne pas + * un nom d'utilisateur qui existe déjà. Dans ce cas de figure, l'ajout du nouveau compte doit échouer. + * @param account + * @return + */ + boolean addAccount(Account account); } diff --git a/Workspace/server/src/main/java/com/pqt/server/module/stock/FileStockDao.java b/Workspace/server/src/main/java/com/pqt/server/module/stock/FileStockDao.java index 97cbfac7..c8c6bc94 100644 --- a/Workspace/server/src/main/java/com/pqt/server/module/stock/FileStockDao.java +++ b/Workspace/server/src/main/java/com/pqt/server/module/stock/FileStockDao.java @@ -19,14 +19,15 @@ import java.util.*; */ public class FileStockDao implements IStockDao { - private static final String STOCK_FILE_NAME = "stock.pqt"; + //TODO to modify + private static final String STOCK_FILE_NAME = "G:\\temp\\stock.pqt"; private ISerialFileManager fileManager; private long nextProductId; private Random random; private Map products; - FileStockDao() { + public FileStockDao() { random = new Random(); fileManager = SimpleSerialFileManagerFactory.getFileManager(Product.class, STOCK_FILE_NAME); loadFromFile(); diff --git a/Workspace/server/src/main/java/com/pqt/server/servlets/QueryServlet.java b/Workspace/server/src/main/java/com/pqt/server/servlets/QueryServlet.java index e8626bf6..998622b3 100644 --- a/Workspace/server/src/main/java/com/pqt/server/servlets/QueryServlet.java +++ b/Workspace/server/src/main/java/com/pqt/server/servlets/QueryServlet.java @@ -28,10 +28,16 @@ public class QueryServlet extends HttpServlet { IMessageToolFactory messageToolFactory = new GSonMessageToolFactory(); IMessageHandler msgHandler = new SimpleMessageHandler(); - if (request.getParameter("message") != null) { - Message resp = msgHandler.handleMessage(messageToolFactory.getObjectParser(Message.class).parse(request.getParameter("message"))); + if (request.getQueryString() != null && !request.getQueryString().isEmpty() && request.getParameter("message")!=null) { + try { + Message resp = msgHandler.handleMessage(messageToolFactory.getObjectParser(Message.class).parse(request.getParameter("message"))); - response.getWriter().write(messageToolFactory.getObjectFormatter(Message.class).format(resp)); + response.getWriter().write(messageToolFactory.getObjectFormatter(Message.class).format(resp)); + }catch(Exception e){ + response.getWriter().write(String.format("%s : %s", e.getClass().getName(), e.getMessage())); + } + }else{ + response.getWriter().write("Query message was not correctly made : "+request.getQueryString()); } } } diff --git a/Workspace/server/src/main/java/com/pqt/server/tools/FileUtil.java b/Workspace/server/src/main/java/com/pqt/server/tools/FileUtil.java index 26cc83d0..e8292428 100644 --- a/Workspace/server/src/main/java/com/pqt/server/tools/FileUtil.java +++ b/Workspace/server/src/main/java/com/pqt/server/tools/FileUtil.java @@ -23,7 +23,7 @@ public class FileUtil { * @throws IOException if any IOException happend during this method's execution. */ public static boolean createFileIfNotExist(Path filePath) throws IOException { - if(FileUtil.exist(filePath)){ + if(!FileUtil.exist(filePath)){ Files.createFile(filePath); return true; } diff --git a/Workspace/server/src/main/java/com/pqt/server/tools/io/SimpleSerialFileManager.java b/Workspace/server/src/main/java/com/pqt/server/tools/io/SimpleSerialFileManager.java index 619532c6..5aea6ac2 100644 --- a/Workspace/server/src/main/java/com/pqt/server/tools/io/SimpleSerialFileManager.java +++ b/Workspace/server/src/main/java/com/pqt/server/tools/io/SimpleSerialFileManager.java @@ -38,7 +38,7 @@ public class SimpleSerialFileManager implements ISerialFileManager { }catch(IOException | ClassNotFoundException e){ e.printStackTrace(); } - return null; + return new ArrayList<>(); } @Override @@ -52,7 +52,7 @@ public class SimpleSerialFileManager implements ISerialFileManager { }catch(IOException | ClassNotFoundException e){ e.printStackTrace(); } - return null; + return new HashSet<>(); } private void fillCollection(Collection collection) throws IOException, ClassNotFoundException { diff --git a/Workspace/server/src/main/java/com/pqt/server/tools/io/SimpleSerialFileManagerFactory.java b/Workspace/server/src/main/java/com/pqt/server/tools/io/SimpleSerialFileManagerFactory.java index 2ebecb47..7f751db2 100644 --- a/Workspace/server/src/main/java/com/pqt/server/tools/io/SimpleSerialFileManagerFactory.java +++ b/Workspace/server/src/main/java/com/pqt/server/tools/io/SimpleSerialFileManagerFactory.java @@ -1,12 +1,13 @@ package com.pqt.server.tools.io; import java.nio.file.Path; +import java.nio.file.Paths; public class SimpleSerialFileManagerFactory { protected SimpleSerialFileManagerFactory(){} public static ISerialFileManager getFileManager(Class clazz, String filePath){ - return new SimpleSerialFileManager<>(filePath, clazz); + return SimpleSerialFileManagerFactory.getFileManager(clazz, Paths.get(filePath)); } public static ISerialFileManager getFileManager(Class clazz, Path filePath){ diff --git a/Workspace/server/src/main/java/com/pqt/server/tools/security/RandomString.java b/Workspace/server/src/main/java/com/pqt/server/tools/security/RandomString.java new file mode 100644 index 00000000..7b748016 --- /dev/null +++ b/Workspace/server/src/main/java/com/pqt/server/tools/security/RandomString.java @@ -0,0 +1,62 @@ +package com.pqt.server.tools.security; + +import java.security.SecureRandom; +import java.util.Locale; +import java.util.Objects; +import java.util.Random; + +public class RandomString { + + /** + * Generate a random string. + */ + public String nextString() { + for (int idx = 0; idx < buf.length; ++idx) + buf[idx] = symbols[random.nextInt(symbols.length)]; + return new String(buf); + } + + public static final String upper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + + public static final String lower = upper.toLowerCase(Locale.ROOT); + + public static final String digits = "0123456789"; + + public static final String alphanum = upper + lower + digits; + + private final Random random; + + private final char[] symbols; + + private final char[] buf; + + public RandomString(int length, Random random, String symbols) { + if (length < 1) throw new IllegalArgumentException(); + if (symbols.length() < 2) throw new IllegalArgumentException(); + this.random = Objects.requireNonNull(random); + this.symbols = symbols.toCharArray(); + this.buf = new char[length]; + } + + /** + * Create an alphanumeric string generator. + */ + public RandomString(int length, Random random) { + this(length, random, alphanum); + } + + /** + * Create an alphanumeric strings from a secure generator. + */ + public RandomString(int length) { + this(length, new SecureRandom()); + } + + /** + * Create session identifiers. + */ + public RandomString() { + this(21); + } + +} \ No newline at end of file