461 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
			
		
		
	
	
			461 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
| package com.bib.essensbestellungsverwaltung;
 | |
| 
 | |
| import javax.crypto.SecretKeyFactory;
 | |
| import javax.crypto.spec.PBEKeySpec;
 | |
| import java.security.NoSuchAlgorithmException;
 | |
| import java.security.SecureRandom;
 | |
| import java.security.spec.InvalidKeySpecException;
 | |
| import java.security.spec.KeySpec;
 | |
| import java.util.ArrayList;
 | |
| import java.util.Base64;
 | |
| import java.util.List;
 | |
| 
 | |
| /**
 | |
|  * A collection of functions loosely related to account management
 | |
|  * Acts as an abstraction layer to the database
 | |
|  * 
 | |
|  * @author Malte Schulze Hobeling
 | |
|  */
 | |
| public class AccountMgr {
 | |
| 
 | |
|     static User currentUser = null;
 | |
| 
 | |
|     /**
 | |
|      * creates a user with createUser(...) and adds its id to the 'worker' table
 | |
|      * 
 | |
|      * @param worker the worker to be created
 | |
|      * @return userid or -1
 | |
|      * @author Malte Schulze Hobeling
 | |
|      */
 | |
|     protected static long createWorker(Worker worker) {
 | |
|         long id = createUser(worker);
 | |
|         String sId = String.valueOf(id);
 | |
|         Database.insert("worker", new String[] { "userid" }, new String[] { sId });
 | |
|         return id;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * creates a user with createUser(...) and adds its id to the 'parent' table
 | |
|      * 
 | |
|      * @param parent the parent to be created
 | |
|      * @return userid or -1
 | |
|      * @author Malte Schulze Hobeling
 | |
|      */
 | |
|     protected static long createParent(Parent parent) {
 | |
|         long id = createUser(parent);
 | |
|         String sId = String.valueOf(id);
 | |
|         Database.insert("parent", new String[] { "userid" }, new String[] { sId });
 | |
|         return id;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * adds a user to the database
 | |
|      * 
 | |
|      * @param user the user to be created
 | |
|      * @return userid or -1
 | |
|      * @author Malte Schulze Hobeling
 | |
|      */
 | |
|     protected static long createUser(User user) {
 | |
|         String[] userH = { "name", "firstname", "addressid", "password", "email" };
 | |
|         String name = user.getName();
 | |
|         String firstname = user.getFirstname();
 | |
|         String pw = hashAndSalt(user.getPassword(), getSalt());
 | |
|         String email = user.getEmail();
 | |
|         long addressId = user.getAddress().getId();
 | |
|         if (addressId < 1) {
 | |
|             addressId = createAddress(user.getAddress());
 | |
|         }
 | |
|         String[] userD = { name, firstname, String.valueOf(addressId), pw, email };
 | |
|         return Database.insert("user", userH, userD);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * adds an address to the database
 | |
|      * 
 | |
|      * @param address the address to be created
 | |
|      * @return id or -1
 | |
|      * @author Malte Schulze Hobeling
 | |
|      */
 | |
|     protected static long createAddress(Address address) {
 | |
|         String[] addressH = { "street", "number", "plz", "city" };
 | |
|         String[] addressD = { address.getStreet(), address.getNumber(), address.getPlz(), address.getCity() };
 | |
|         return Database.insert("address", addressH, addressD);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * adds a child and allergies to the database
 | |
|      * 
 | |
|      * @param child the child to be created
 | |
|      * @return id of child or -1
 | |
|      * @author Malte Schulze Hobeling
 | |
|      */
 | |
|     protected static long createChild(Child child) {
 | |
|         String[] childH = { "name", "firstname", "addressid" };
 | |
|         String[] childD = { child.getName(), child.getFirstname(), String.valueOf(child.getAddress().getId()) };
 | |
|         long id = Database.insert("child", childH, childD);
 | |
|         String[] child_allergyH = { "childid", "allergyid", "severityid" };
 | |
|         for (AllergySeverity allergy : child.getAllergies()) {
 | |
|             String sId = String.valueOf(id);
 | |
|             String sAllergyId = String.valueOf(allergy.getAllergy().getId());
 | |
|             String sSeverityId = String.valueOf(allergy.getSeverityId());
 | |
|             String[] child_allergyD = { sId, sAllergyId, sSeverityId };
 | |
|             Database.insert("child_allergy", child_allergyH, child_allergyD);
 | |
|         }
 | |
|         return id;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * update Child
 | |
|      *
 | |
|      * @param child the child to be updated
 | |
|      * @return id of child
 | |
|      * @author Johannes Kantz
 | |
|      */
 | |
|     protected static long updateChild(Child child) {
 | |
|         String[] childH = { "id", "name", "firstname", "addressid" };
 | |
|         String[] childD = { String.valueOf(child.getId()), child.getName(), child.getFirstname(),
 | |
|                 String.valueOf(child.getAddress().getId()) };
 | |
|         long updates = Database.update("child", childH, childD);
 | |
|         String[] child_allergyH = { "childid", "allergyid", "severityid" };
 | |
|         Database.select("child_allergy", new String[] { "childid" }, new String[] { String.valueOf(child.getId()) })
 | |
|                 .stream().forEach(row -> {
 | |
|                     String allergyId = row.split(":")[0];
 | |
|                     Database.delete("child_allergy", Integer.parseInt(allergyId));
 | |
|                 });
 | |
|         for (AllergySeverity allergy : child.getAllergies()) {
 | |
|             String sId = String.valueOf(child.getId());
 | |
|             String sAllergyId = String.valueOf(allergy.getAllergy().getId());
 | |
|             String sSeverityId = String.valueOf(allergy.getSeverityId());
 | |
|             String[] child_allergyD = { sId, sAllergyId, sSeverityId };
 | |
|             Database.insert("child_allergy", child_allergyH, child_allergyD);
 | |
|         }
 | |
|         return updates;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * delete Child
 | |
|      * 
 | |
|      * @author Johannes Kantz
 | |
|      */
 | |
|     protected static void deleteChildWithId(long id) {
 | |
|         Database.delete("child", id);
 | |
|         Database.select("child_allergy", new String[] { "childid" }, new String[] { String.valueOf(id) }).stream()
 | |
|                 .forEach(row -> {
 | |
|                     String allergyId = row.split(":")[0];
 | |
|                     Database.delete("child_allergy", Integer.parseInt(allergyId));
 | |
|                 });
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * returns a User(Worker | Parent) for a given id or null if no unique id was
 | |
|      * found
 | |
|      * 
 | |
|      * @param id id of the User
 | |
|      * @return User(Worker | Parent) or null
 | |
|      * @author Malte Schulze Hobeling
 | |
|      */
 | |
|     protected static User getUserById(long id) {
 | |
|         List<String> entry = Database.getEntryById("user", id);
 | |
|         if (entry.size() != 1) {
 | |
|             return null;
 | |
|         }
 | |
|         String[] parts = entry.get(0).split(":");
 | |
|         Address address = getAddressById(id);
 | |
|         if (isWorker(String.valueOf(id))) {
 | |
|             return new Worker(id, parts[1], parts[2], parts[4], parts[5], address);
 | |
|         } else {
 | |
|             String[] parent_childH = { "parentuserid" };
 | |
|             String[] parent_childD = { String.valueOf(id) };
 | |
|             List<Child> children = new ArrayList<>();
 | |
|             List<String> parent_childEntries = Database.select("parent_child", parent_childH, parent_childD);
 | |
|             for (String parent_childEntry : parent_childEntries) {
 | |
|                 String[] parent_childParts = parent_childEntry.split(":");
 | |
|                 children.add(getChildById(Long.parseLong(parent_childParts[2])));
 | |
|             }
 | |
|             return new Parent(id, parts[1], parts[2], parts[4], parts[5], address, children);
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * returns a Child for a given id or null if no unique id was found
 | |
|      * 
 | |
|      * @param id id of child
 | |
|      * @return Child or null
 | |
|      * @author Malte Schulze Hobeling
 | |
|      */
 | |
|     protected static Child getChildById(long id) {
 | |
|         List<String> entry = Database.getEntryById("child", id);
 | |
|         if (entry.size() != 1) {
 | |
|             return null;
 | |
|         }
 | |
|         String[] parts = entry.get(0).split(":");
 | |
|         String[] child_allergyH = { "childid" };
 | |
|         String[] child_allergyD = { String.valueOf(id) };
 | |
|         List<String> entriesAllergy = Database.select("child_allergy", child_allergyH, child_allergyD);
 | |
|         List<AllergySeverity> allergySeverities = new ArrayList<>();
 | |
|         for (String entryAllergy : entriesAllergy) {
 | |
|             String[] allergyParts = entryAllergy.split(":");
 | |
|             List<String> severity = Database.getEntryById("severity", Long.parseLong(allergyParts[3]));
 | |
|             String sSeverity = severity.get(0).split(":")[1];
 | |
|             long lSeverity = Long.parseLong(severity.get(0).split(":")[0]);
 | |
|             allergySeverities.add(
 | |
|                     new AllergySeverity(FoodMgr.getAllergyById(Long.parseLong(allergyParts[2])), lSeverity, sSeverity));
 | |
|         }
 | |
|         return new Child(id, parts[1], parts[2], getAddressById(Long.parseLong(parts[3])), allergySeverities);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * returns all Children
 | |
|      * 
 | |
|      * @return {List<Child} List with Childen or empty List
 | |
|      * @author Johannes Kantz
 | |
|      */
 | |
|     protected static List<Child> getAllChildren() {
 | |
|         List<String> entry = Database.getTable("child");
 | |
|         if (entry.size() < 1) {
 | |
|             return new ArrayList<>();
 | |
|         }
 | |
|         List<Child> children = new ArrayList<>();
 | |
|         for (String s : entry) {
 | |
|             String[] parts = s.split(":");
 | |
|             String[] child_allergyH = { "childid" };
 | |
|             String[] child_allergyD = { String.valueOf(parts[0]) };
 | |
|             List<String> entriesAllergy = Database.select("child_allergy", child_allergyH, child_allergyD);
 | |
|             List<AllergySeverity> allergySeverities = new ArrayList<>();
 | |
|             for (String entryAllergy : entriesAllergy) {
 | |
|                 String[] allergyParts = entryAllergy.split(":");
 | |
|                 List<String> severity = Database.getEntryById("severity", Long.parseLong(allergyParts[3]));
 | |
|                 String sSeverity = severity.get(0).split(":")[1];
 | |
|                 long lSeverity = Long.parseLong(severity.get(0).split(":")[0]);
 | |
|                 allergySeverities.add(new AllergySeverity(FoodMgr.getAllergyById(Long.parseLong(allergyParts[2])),
 | |
|                         lSeverity, sSeverity));
 | |
|             }
 | |
|             children.add(new Child(Long.parseLong(parts[0]), parts[1], parts[2],
 | |
|                     getAddressById(Long.parseLong(parts[3])), allergySeverities));
 | |
|         }
 | |
|         return children;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * returns all Children from parent
 | |
|      * @param id parentid
 | |
|      * @return {List<Child} List with Childen or empty List
 | |
|      * @author Johannes Kantz
 | |
|      */
 | |
|     protected static List<Child> getAllChildrenFromParentWithId(long id) {
 | |
|         List<String> entry = Database.select("parent_child", new String[] { "parentuserid" },
 | |
|                 new String[] { String.valueOf(id) });
 | |
|         if (entry.size() < 1) {
 | |
|             return new ArrayList<>();
 | |
|         }
 | |
|         List<String> childIds = new ArrayList<>();
 | |
|         for (String s : entry) {
 | |
|             String[] parts = s.split(":");
 | |
|             childIds.add(parts[2]);
 | |
|         }
 | |
|         List<Child> children = new ArrayList<>();
 | |
|         for (String s : childIds) {
 | |
|             List<String> child = Database.getEntryById("child", Long.parseLong(s));
 | |
|             String[] parts = child.get(0).split(":");
 | |
|             String[] child_allergyH = { "childid" };
 | |
|             String[] child_allergyD = { String.valueOf(parts[0]) };
 | |
|             List<String> entriesAllergy = Database.select("child_allergy", child_allergyH, child_allergyD);
 | |
|             List<AllergySeverity> allergySeverities = new ArrayList<>();
 | |
|             for (String entryAllergy : entriesAllergy) {
 | |
|                 String[] allergyParts = entryAllergy.split(":");
 | |
|                 List<String> severity = Database.getEntryById("severity", Long.parseLong(allergyParts[3]));
 | |
|                 String sSeverity = severity.get(0).split(":")[1];
 | |
|                 long lSeverity = Long.parseLong(severity.get(0).split(":")[0]);
 | |
|                 allergySeverities.add(new AllergySeverity(FoodMgr.getAllergyById(Long.parseLong(allergyParts[2])),
 | |
|                         lSeverity, sSeverity));
 | |
|             }
 | |
|             children.add(new Child(Long.parseLong(parts[0]), parts[1], parts[2],
 | |
|                     getAddressById(Long.parseLong(parts[3])), allergySeverities));
 | |
|         }
 | |
|         return children;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * returns an Address for a given id or null if no unique id was found
 | |
|      * 
 | |
|      * @param id id of the address
 | |
|      * @return Address or null
 | |
|      * @author Malte Schulze Hobeling
 | |
|      */
 | |
|     protected static Address getAddressById(long id) {
 | |
|         List<String> entry = Database.getEntryById("address", id);
 | |
|         if (entry.size() != 1) {
 | |
|             return null;
 | |
|         }
 | |
|         String[] parts = entry.get(0).split(":");
 | |
|         return new Address(Long.parseLong(parts[0]), parts[1], parts[2], parts[3], parts[4]);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * creates entries in the database to match parent to child
 | |
|      * 
 | |
|      * @param parentId id of parent
 | |
|      * @param childId  id of child
 | |
|      * @return id of parent_child or -1
 | |
|      * @author Malte Schulze Hobeling
 | |
|      */
 | |
|     protected static long matchParentChild(String parentId, String childId) {
 | |
|         String[] parent_childH = { "parentuserid", "childid" };
 | |
|         String[] parent_childD = { parentId, childId };
 | |
|         return Database.insert("parent_child", parent_childH, parent_childD);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * a simple login to check if a given email matches a password
 | |
|      * 
 | |
|      * @param email email
 | |
|      * @param pw    password
 | |
|      * @return id or -1
 | |
|      * @author Malte Schulze Hobeling
 | |
|      */
 | |
|     protected static long login(String email, String pw) {
 | |
|         String[] pwH = { "email" };
 | |
|         String[] pwD = { email };
 | |
|         List<String> foundEmail = Database.select("user", pwH, pwD);
 | |
|         String salt;
 | |
|         if (foundEmail.size() == 1) {
 | |
|             String[] userParts = foundEmail.get(0).split(":");
 | |
|             String[] pwParts = userParts[4].split("\\.");
 | |
|             salt = pwParts[1];
 | |
|         } else {
 | |
|             // no unique user found; still calculating a hash for security reasons
 | |
|             salt = getSalt();
 | |
|         }
 | |
|         String[] userH = { "email", "password" };
 | |
|         String[] userD = { email, hashAndSalt(pw, salt) };
 | |
|         return Database.getSingleId("user", userH, userD);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * checks if id is in worker table
 | |
|      * 
 | |
|      * @param id userid
 | |
|      * @return true if id is in worker table
 | |
|      * @author Malte Schulze Hobeling
 | |
|      */
 | |
|     protected static boolean isWorker(String id) {
 | |
|         String[] workerH = { "userid" };
 | |
|         String[] workerD = { id };
 | |
|         long workerId = Database.getSingleId("worker", workerH, workerD);
 | |
|         return workerId > 0;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * checks if id is in parent table
 | |
|      * 
 | |
|      * @param id userid
 | |
|      * @return true if id is in parent table
 | |
|      * @author Malte Schulze Hobeling
 | |
|      */
 | |
|     protected static boolean isParent(String id) {
 | |
|         String[] parentH = { "userid" };
 | |
|         String[] parentD = { id };
 | |
|         long parentId = Database.getSingleId("parent", parentH, parentD);
 | |
|         return parentId > 0;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * returns a hashed and salted password
 | |
|      * 
 | |
|      * @param pw the password to hash
 | |
|      * @return hashed and salted password
 | |
|      * @author Malte Schulze Hobeling
 | |
|      */
 | |
|     private static String hashAndSalt(String pw, String salt) {
 | |
|         Base64.Decoder dec = Base64.getDecoder();
 | |
|         byte[] bySalt = dec.decode(salt);
 | |
|         KeySpec spec = new PBEKeySpec(pw.toCharArray(), bySalt, 310001, 256);
 | |
|         String hashedPw;
 | |
|         try {
 | |
|             SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
 | |
|             byte[] hash = factory.generateSecret(spec).getEncoded();
 | |
|             Base64.Encoder enc = Base64.getEncoder();
 | |
|             hashedPw = enc.encodeToString(hash);
 | |
|         } catch (InvalidKeySpecException | NoSuchAlgorithmException e) {
 | |
|             throw new RuntimeException(e);
 | |
|         }
 | |
|         hashedPw += "." + salt;
 | |
|         return hashedPw;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * generates a secure random salt, Base64 encoded
 | |
|      * 
 | |
|      * @return String Base64 encoded
 | |
|      * @author Malte Schulze Hobeling
 | |
|      */
 | |
|     private static String getSalt() {
 | |
|         SecureRandom sec = new SecureRandom();
 | |
|         byte[] salt = new byte[16];
 | |
|         sec.nextBytes(salt);
 | |
|         Base64.Encoder enc = Base64.getEncoder();
 | |
|         return enc.encodeToString(salt);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * gives the invoice for one month and one child
 | |
|      * 
 | |
|      * @param date    YYYY-MM the month
 | |
|      * @param childId id of child
 | |
|      * @return the invoice as a List
 | |
|      * @author Malte Schulze Hobeling
 | |
|      */
 | |
|     protected static List<String> getInvoice(String date, String childId) {
 | |
|         List<String> invoice = new ArrayList<>();
 | |
|         List<String> child = Database.getEntryById("child", Long.parseLong(childId));
 | |
|         if (child.size() != 1) {
 | |
|             return invoice;
 | |
|         }
 | |
|         invoice.add("Monatsabrechnung " + date);
 | |
|         String[] childParts = child.get(0).split(":");
 | |
|         invoice.add(childParts[1] + ", " + childParts[2]);
 | |
|         String[] food_planH = { "date" };
 | |
|         String[] food_planD = { date + "%" };
 | |
|         List<String> food_plan = Database.select("food_plan", food_planH, food_planD);
 | |
|         for (String day : food_plan) {
 | |
|             String[] food_planParts = day.split(":");
 | |
|             String[] food_selectionH = { "childid", "food_planid" };
 | |
|             String[] food_selectionD = { childId, food_planParts[0] };
 | |
|             List<String> food_selection = Database.select("food_selection", food_selectionH, food_selectionD);
 | |
|             for (String food_select : food_selection) {
 | |
|                 String[] food_selectParts = food_select.split(":");
 | |
|                 List<String> food = Database.getEntryById("food", Long.parseLong(food_selectParts[3]));
 | |
|                 String[] foodParts = food.get(0).split(":");
 | |
|                 String line = food_planParts[1] + ": " + foodParts[1];
 | |
|                 invoice.add(line);
 | |
|             }
 | |
|         }
 | |
|         double price = getPrice();
 | |
|         invoice.add("Total: " + (invoice.size() - 2) + " X " + price + "€ = " + ((invoice.size() - 2) * price) + "€");
 | |
|         return invoice;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * gets the price per meal from the database and converts it to double
 | |
|      * 
 | |
|      * @return double price
 | |
|      * @author Malte Schulze Hobeling
 | |
|      */
 | |
|     protected static double getPrice() {
 | |
|         List<String> priceEntry = Database.getEntryById("price", 1);
 | |
|         return Double.parseDouble(priceEntry.get(0).split(":")[1]) / 100.0;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * converts the price per meal to integer and updates it in the database
 | |
|      * 
 | |
|      * @param price double
 | |
|      * @author Malte Schulze Hobeling
 | |
|      */
 | |
|     protected static void setPrice(double price) {
 | |
|         String[] priceH = { "id", "price" };
 | |
|         String[] priceD = { "1", String.valueOf((int) (price * 100)) };
 | |
|         Database.update("price", priceH, priceD);
 | |
|     }
 | |
| }
 | 
