package at.reisinger.server.objects; import at.reisinger.obj.*; import at.reisinger.obj.Package; import at.reisinger.server.DBConnection; import at.reisinger.server.helper.JsonHelper; import at.reisinger.server.helper.ResponseHelper; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; import java.io.PrintStream; import java.util.*; /** * Erstellt und sendet eine Response anhand des Requests * @author Georg Reisinger */ public class Response { private final PrintStream out; private final String url; private final String payload; private final String authString; /** * Nimmt die Daten des requests und generiert eine Response * @param url Request Url * @param cmd Request CMD * @param out out Print Stream * @param authString Der MsgHandler * @param payload Payload des Requests */ public Response(String url, String cmd, PrintStream out, String authString, String payload){ this.authString = authString; this.url = url; this.out = out; this.payload = payload; if (this.url != null) { switch (cmd) { case "GET": if (login()) { getMethodes(); } else { sendResponse("Login Error", "401"); } break; case "POST": try { postMethodes(); } catch (JsonProcessingException e) { e.printStackTrace(); } break; case "PUT": if (login()) { putMethodes(); } else { sendResponse("Login Error", "401"); } break; case "DELETE": if (login()) { deleteMethodes(); } else { sendResponse("Login Error", "401"); } break; default: sendResponse("", "405"); break; } } } /** * Alle Get Methoden * Nur für angemeldete user erreichbar */ private void getMethodes(){ if (this.url.startsWith("/users")) { String username = this.url.substring(this.url.lastIndexOf('/') + 1); User user; user = new DBConnection().getUser(username); if (user != null){ String userJson = JsonHelper.userToJson(user); if(userJson != null && !userJson.isEmpty()){ sendResponse(userJson, "200"); } }else{ sendResponse("", "500"); } } else if (this.url.startsWith("/cards")) { String username = basicAuthGetUsername(this.authString); Cards allCards = new DBConnection().getCards(username); String jsonCards = JsonHelper.objToJson(allCards); if (jsonCards != null && !jsonCards.isEmpty()){ sendResponse(jsonCards, "200"); }else{ sendResponse("", "500"); } }else if(this.url.startsWith("/deck")) { String format = this.url.substring(this.url.lastIndexOf('?') + 1); String username = basicAuthGetUsername(this.authString); ArrayList allCards = new DBConnection().getDeck(username); Cards deck; Object tmp; if(format.startsWith("format=plain")){ tmp = allCards; }else{ deck = new DBConnection().getCardsFromIDList(allCards); tmp = deck; } String jsonCards = JsonHelper.objToJson(tmp); if (jsonCards != null && !jsonCards.isEmpty()) { sendResponse(jsonCards, "200"); } else { sendResponse("", "500"); } }else if(this.url.startsWith("/tradings")) { ArrayList allDeals = new DBConnection().getAllTradingDeals(); if(allDeals != null && !allDeals.isEmpty()){ String json = JsonHelper.objToJson(allDeals); if(json != null && !json.equals("")){ sendResponse(json, "200"); }else{ sendResponse("", "500"); } }else{ sendResponse("", "500"); } }else if(this.url.startsWith("/score")) { String username = basicAuthGetUsername(this.authString); if (username != null && !username.isEmpty()){ int lastBallteId = new DBConnection().getLastBattleIdUser(username); if (lastBallteId > -1){ Map map = new DBConnection().getBattleLog(lastBallteId + ""); if(map != null && !map.isEmpty()){ sendResponse("BATTLE #" + map.get("id") + "\nSCORE\n" + map.get("playerone") + "(#Player1) |vs| " + map.get("playertwo") + "(#Player2) \n" + map.get("playeronescore") + "(#Player1) |vs| " + map.get("playertwoscore") + "(#Player2) \nGame LOG:\n" + ResponseHelper.logLineBreak(map.get("log")), "200"); }else { sendResponse("Konnte Battle log nicht holen", "500"); } }else { sendResponse("Last Battle ID error", "500"); } }else{ sendResponse("Login Error", "401"); } }else if(this.url.startsWith("/stats")) { String username = basicAuthGetUsername(this.authString); if (username != null && !username.isEmpty()) { ArrayList battleIds = new DBConnection().getAllBattleIdUser(username); if (battleIds != null && !battleIds.isEmpty()){ StringBuilder resString = new StringBuilder(); for(String i : battleIds){ Map map = new DBConnection().getBattleLog(i + ""); if(map != null && !map.isEmpty()){ resString = new StringBuilder("BATTLE #" + map.get("id") + "\nSCORE\n" + map.get("playerone") + "(#Player1) |vs| " + map.get("playertwo") + "(#Player2) \n" + map.get("playeronescore") + "(#Player1) |vs| " + map.get("playertwoscore") + "(#Player2) \nGame LOG:\n"); resString.append(ResponseHelper.logLineBreak(map.get("log"))); }else { sendResponse("Konnte Battle log nicht holen", "500"); } } sendResponse(resString.toString(), "200"); }else { sendResponse("Konnte Battle ids ned holen", "500"); } }else{ sendResponse("Login Error", "401"); } }else{ sendResponse("", "204"); } } /** * Vergleicht das angegebene PW mit dem gespeicherten PW, True wenn richtig * @param username User aus DB * @param password PW zu User aus DB * @param compareTo Base64 String von Basic Auth * @return True if Login is correct, false if incorrect */ private boolean basicAuth(String username, String password, String compareTo){ String authStringEnc = basicAuthBase64(username, password); return compareTo.equals(authStringEnc); } /** * Erstellt den basicAuth Base64 Token aus Username und Passwort * @param username Username für den Token * @param password Passwort für den Token * @return Der Base64 BasicAtuth String */ private String basicAuthBase64(String username, String password){ String authString = username + ":" + password; byte[] authEncBytes = Base64.getEncoder().encode(authString.getBytes()); return new String(authEncBytes); } /** * Aus dem Base64 BasicAuth String wird der Username extrahiert * @param authString Base64 BasicAuth String aus dem der Username ausgelesen werden soll * @return Der Username der in dem Base64 BasicAuth String ist */ private String basicAuthGetUsername(String authString) { String[] values; if (authString != null) { byte[] credDecoded = Base64.getDecoder().decode(authString); String credentials = new String(credDecoded); values = credentials.split(":", 2); }else{ values = null; } return Objects.requireNonNull(values)[0]; } /** * Alle Post Methoden, siehe API beschreibung für genauere details * * Kann auch von nicht angemeldeten usern erreicht werden. * login() wird hier verwendet * @throws JsonProcessingException Fehler beim de-/serialisieren */ private void postMethodes() throws JsonProcessingException { if (this.url.startsWith("/users")) { Map map = JsonHelper.jsonPayloadToMap(this.payload); String username = (String) Objects.requireNonNull(map).get("Username"); String password = (String) map.get("Password"); User newUser = new User(new Credentials(username, password), username, username, "not implemented", new Coins(20), "BIO", "IMAGE"); DBConnection con = new DBConnection(); if(!con.addUser(newUser.getCredentials().getUsername(), newUser.getCredentials().getPasswort(), newUser.getCredentials().getUsername(), newUser.getEmail(), newUser.getBio(), newUser.getImage())){ sendResponse("", "409"); } String userJson = JsonHelper.userToJson(newUser); if(userJson != null) { sendResponse(userJson, "201"); }else{ sendResponse("", "500"); } }else if (this.url.startsWith("/sessions")) { Map map = JsonHelper.jsonPayloadToMap(this.payload); String username = (String) Objects.requireNonNull(map).get("Username"); String password = (String) map.get("Password"); User user; DBConnection con = new DBConnection(); user = con.getUser(username); String authString = basicAuthBase64(user.getCredentials().getUsername(), user.getCredentials().getPasswort()); if(basicAuth(username, password, authString)){ sendResponse(authString, "200"); }else{ sendResponse("Login Error", "401"); } }else if (this.url.startsWith("/packages")) { if (basicAuth("admin", "istrator", this.authString)) { ObjectMapper objectMapper = new ObjectMapper(); ArrayList listCards = objectMapper.readValue(this.payload, new TypeReference<>() { }); Package packageCards = new Package(new Cards(listCards), new DBConnection().nextPackageId() + "", 5); if (!new DBConnection().addPackage(packageCards)) { sendResponse("", "500"); } else { String packageJson = JsonHelper.objToJson(packageCards); if (packageJson != null) { sendResponse(packageJson, "201"); } else { sendResponse("", "500"); } } } else { sendResponse("Login Error", "401"); } }else if (this.url.startsWith("/transactions/packages")) { if (login()) { DBConnection db = new DBConnection(); Package newPackage = db.userAcquirePackage(basicAuthGetUsername(this.authString)); if (newPackage == null) { sendResponse("", "500"); } else { String packageJson = JsonHelper.objToJson(newPackage); if (packageJson == null) { sendResponse("", "500"); } else { sendResponse(packageJson, "200"); } } }else{ sendResponse("Login Error", "401"); } }else if (this.url.startsWith("/tradings")) { if(login()) { String dotradeid = this.url.substring(this.url.lastIndexOf('/') + 1); if (!dotradeid.isEmpty() && !dotradeid.equals("tradings")) { //DO TRADE String username = basicAuthGetUsername(this.authString); if (username != null && !username.isEmpty()) { ArrayList tradingDealArrayList = new DBConnection().getAllTradingDeals(); TradingDeal tradingDeal = null; if (tradingDealArrayList != null && !tradingDealArrayList.isEmpty()) { for (TradingDeal tr : tradingDealArrayList) { if (tr.getId().equals(dotradeid)) { tradingDeal = tr; } } Card card = new DBConnection().getCardFromID(this.payload); if (card != null) { if (tradingDeal != null) { if (tradingDeal.cardOk(card)) { String json = JsonHelper.objToJson(card); if (json != null && !json.isEmpty()) { if (new DBConnection().addUserCard(username, tradingDeal.getCardToTrade().getName())) { if (new DBConnection().delUserCard(tradingDeal.getUsername(), tradingDeal.getCardToTrade().getName())) { if (new DBConnection().deleteTradingDeal(tradingDeal.getId())) { if (new DBConnection().delUserCard(username, card.getName())) { if (new DBConnection().addUserCard(tradingDeal.getUsername(), card.getName())) { sendResponse(json, "200"); } else { sendResponse("ERROR --> Add Card to: " + tradingDeal.getUsername(), "500"); } } else { sendResponse("ERROR --> Del Card from: " + username, "500"); } } else { sendResponse("Error --> Del Trading Deal", "500"); } } else { sendResponse("ERROR --> Del Card from: " + tradingDeal.getUsername(), "500"); } } else { sendResponse("ERROR --> Add Card to: " + username, "500"); } } else { sendResponse("ERROR --> JSON Empty", "500"); } } else { sendResponse("ERROR --> Trading Deal not ok", "500"); } } else { sendResponse("ERROR --> Trading Deal not exist", "500"); } } else { sendResponse("ERROR --> Card not exist", "500"); } } else { sendResponse("ERROR --> Trading Deal not exist", "500"); } } else { sendResponse("ERROR --> Username empty", "401"); } } else { //CREATE TRADING DEAL Map map = JsonHelper.jsonPayloadToMap(this.payload); String id = (String) Objects.requireNonNull(map).get("Id"); String cardtotrade = (String) map.get("CardToTrade"); String type = (String) map.get("Type"); double mindamage = Double.parseDouble(map.get("MinimumDamage") + ""); String username = basicAuthGetUsername(this.authString); if (username != null) { Card cardtoTradeC = new DBConnection().getCardFromID(cardtotrade); if (cardtoTradeC != null) { TradingDeal tradingDeal = new TradingDeal(id, cardtoTradeC, mindamage, type, username); String tradingJson = JsonHelper.objToJson(tradingDeal); ArrayList deckCards = new DBConnection().getDeck(username); if (deckCards != null) { if (deckCards.contains(cardtotrade)) { new DBConnection().delDeck(username); } if (new DBConnection().addTradingdeal(tradingDeal.getUsername(), tradingDeal.getId(), tradingDeal.getRequiredMinDamage(), tradingDeal.getRequiredCardType().name(), tradingDeal.getRequiredElementType().name(), tradingDeal.getCardToTrade().getName())) { if (new DBConnection().updateCardLock(tradingDeal.getCardToTrade().getName(), true)) { sendResponse(Objects.requireNonNull(JsonHelper.objToJson(tradingDeal)), "201"); } else { sendResponse("", "500"); } } else { sendResponse("", "500"); } } else { sendResponse("", "500"); } sendResponse(Objects.requireNonNull(tradingJson), "201"); } else { sendResponse("", "500"); } } else { sendResponse("", "500"); } } } }else if (this.url.startsWith("/battle")) { if(login()){ String username = basicAuthGetUsername(this.authString); if (username != null && !username.isEmpty()) { List deckNamen = new DBConnection().getDeck(username); if (deckNamen != null && !deckNamen.isEmpty()) { Cards deck = new DBConnection().getCardsFromIDList(deckNamen); if(deck != null && deck.getCards().size() == 4) { Battle openBattle = new DBConnection().getOpenBattle(); if (openBattle == null) { //Creator player Mode if(new DBConnection().addBattle(username)){ sendResponse("Du bist: #PLAYER 1\nBattle Einladung wurde erstellt von: " + username + "(#PLAYER1) \nSobald ein 2. Spieler dem Battle beitritt, kann das ergebnis mit /score abgefragt werden.","200"); }else { sendResponse("", "500"); } } else { //Join game player User player2 = new DBConnection().getUser(username); if(player2 != null){ openBattle.setPlayer2(player2); openBattle.setDeckPlayer2(deck); if(new DBConnection().delBattleEinladung(openBattle.getId() + "")) { if (openBattle.doFight()){ System.out.println(JsonHelper.objToJson(openBattle.getLog().size())); if (new DBConnection().addBattleLog(openBattle.getId() + "", openBattle.getPlayer1().getName(), openBattle.getPlayer2().getName(), openBattle.getScorePlayer1() + "", openBattle.getScorePlayer2() + "", openBattle.getLog().toString())) { if (new DBConnection().delDeck(openBattle.getPlayer1().getCredentials().getUsername()) && new DBConnection().delDeck(openBattle.getPlayer2().getCredentials().getUsername())) { //DEL OLD DECK CARDS ArrayList oldDeck1 = new ArrayList<>(); for (Card ca : openBattle.getDeckPlayer1Init().getCards()) { oldDeck1.add(ca.getName()); } ArrayList oldDeck2 = new ArrayList<>(); for (Card ca : openBattle.getDeckPlayer2Init().getCards()) { oldDeck2.add(ca.getName()); } //DEL NEW CARDS IF EXIST Cards player1cards = new DBConnection().getCards(openBattle.getPlayer1().getCredentials().getUsername()); for (Card ca : openBattle.getDeckPlayer1().getCards()) { oldDeck1.add(ca.getName()); } if (player1cards.getCards() != null && !player1cards.getCards().isEmpty()) { for (String ca : oldDeck1) { if (!new DBConnection().delUserCard(openBattle.getPlayer1().getCredentials().getUsername(), ca)) { sendResponse("Error Deleting user card1: " + ca, "500"); } } } Cards player2cards = new DBConnection().getCards(openBattle.getPlayer2().getCredentials().getUsername()); for (Card ca : openBattle.getDeckPlayer2().getCards()) { oldDeck2.add(ca.getName()); } if (player2cards.getCards() != null && !player2cards.getCards().isEmpty()) { for (String ca : oldDeck2) { if (!new DBConnection().delUserCard(openBattle.getPlayer2().getCredentials().getUsername(), ca)) { sendResponse("Error Deleting user card2: " + ca, "500"); } } } //ADD CARDS TO DECK for (Card ca : openBattle.getDeckPlayer1().getCards()) { if (!new DBConnection().addUserCard(openBattle.getPlayer1().getCredentials().getUsername(), ca.getName())) { sendResponse("Error adding card to user1: " + ca.getName(), "500"); } } for (Card ca : openBattle.getDeckPlayer2().getCards()) { if (!new DBConnection().addUserCard(openBattle.getPlayer2().getCredentials().getUsername(), ca.getName())) { sendResponse("Error adding card to user2: " + ca.getName(), "500"); } } sendResponse("Du bist: #PLAYER 2\nBattle --> " + openBattle.getPlayer1().getName() + "(#PLAYER1) |vs| " + openBattle.getPlayer2().getName() + "(#PLAYER2)\nErgebnisse unter /score abrufbar", "200"); } } else { sendResponse("Battle Log konnte ned geschrieben werden", "500"); //ERROR } }else { sendResponse("Battle konnte ned durchgeführt werden", "500"); } }else{ sendResponse("Battle einladung konnte ned akzeptiert werden", "500"); //ERROR } }else{ sendResponse("GET User error", "500"); //ERROR } } }else { sendResponse("Nur "+ Objects.requireNonNull(deck).getCards().size()+" von 4 Karten im Deck. \nMach zuerst POST /deck [ID, ID, ID, ID] um dein Deck korrekt zu befüllen","424"); } }else { sendResponse("Deck ist nicht gesetzt","424"); } }else { sendResponse("", "500"); } }else { sendResponse("Login Error", "401"); } } else{ sendResponse("", "405"); } } /** * Prüft den Login, anhand des BasicAuth Base64 String * @return True wenn login daten korrekt, sonst false */ private boolean login(){ if(this.authString != null && !this.authString.isEmpty()){ String username = basicAuthGetUsername(this.authString); User user; user = new DBConnection().getUser(username); return basicAuth(user.getCredentials().getUsername(), user.getCredentials().getPasswort(), this.authString); }else{ return false; } } /** * Alle Put Methoden * Nur für angemeldete user erreichbar */ private void putMethodes(){ if (this.url.startsWith("/users")) { String username = this.url.substring(this.url.lastIndexOf('/') + 1); User user; user = new DBConnection().getUser(username); if(user != null) { Map map = JsonHelper.jsonPayloadToMap(this.payload); String bio = (String) Objects.requireNonNull(map).get("Bio"); String image = (String) map.get("Image"); String name = (String) map.get("Name"); user.setBio(bio); user.setImage(image); user.setNachname(name); if (new DBConnection().updateUser(username, user.getBio(), user.getImage(), user.getNachname())) { sendResponse(JsonHelper.userToJson(user), "200"); } else { sendResponse("", "500"); } }else{ sendResponse("", "500"); } }else if(this.url.startsWith("/deck")) { List deckIds = JsonHelper.jsonPayloadToList(this.payload); if (deckIds != null && deckIds.size() == 4){ if (new DBConnection().setDeck(basicAuthGetUsername(this.authString), deckIds)){ Cards deck = new DBConnection().getCardsFromIDList(deckIds); String deckJson = JsonHelper.objToJson(deck); if (deck != null && deckJson != null){ sendResponse(deckJson, "200"); }else { sendResponse("", "500"); } }else { sendResponse("", "500"); } }else{ sendResponse(Objects.requireNonNull(deckIds).size() + " von 4 Karten sind im Deck.","500"); } } } /** * Alle Delete Methoden, siehe API beschreibung für genauere details * Nur für angemeldete user erreichbar */ private void deleteMethodes(){ if (this.url.startsWith("/tradings")) { String tradeid = this.url.substring(this.url.lastIndexOf('/') + 1); ArrayList allTradingDeals = new DBConnection().getAllTradingDeals(); TradingDeal tr = null; if (allTradingDeals != null && !allTradingDeals.isEmpty()) { for (TradingDeal i : allTradingDeals) { if (i.getId().equals(tradeid)) { tr = i; } } if (tr != null) { if (new DBConnection().deleteTradingDeal(tradeid)) { if (new DBConnection().updateCardLock(tr.getCardToTrade().getName(), false)) sendResponse("", "204"); } else { sendResponse("", "500"); } }else{ sendResponse("", "500"); } } } } /** * Sendet eine Response * @param responseText Text der zu senden ist * @param code Http code */ private void sendResponse(String responseText, String code){ out.print("HTTP/1.0 "+code+"\r\n"); out.print("Server: Apache/0.8.4\r\n"); out.print("Content-Type: text/plain\r\n"); out.print("Content-Length: "+responseText.length()+"\r\n"); out.print("\r\n"); out.print(responseText); } }