diff options
Diffstat (limited to 'ufund-api/src/main/java/com/ufund/api/ufundapi')
15 files changed, 406 insertions, 123 deletions
diff --git a/ufund-api/src/main/java/com/ufund/api/ufundapi/controller/AuthController.java b/ufund-api/src/main/java/com/ufund/api/ufundapi/controller/AuthController.java new file mode 100644 index 0000000..aa27e3f --- /dev/null +++ b/ufund-api/src/main/java/com/ufund/api/ufundapi/controller/AuthController.java @@ -0,0 +1,54 @@ +package com.ufund.api.ufundapi.controller; + +import com.ufund.api.ufundapi.model.UserAuth; +import com.ufund.api.ufundapi.persistence.UserAuthDAO; +import com.ufund.api.ufundapi.persistence.UserDAO; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.io.IOException; +import java.util.Map; + +@RestController +@RequestMapping("auth") +public class AuthController { + private final UserDAO userDAO; + private final UserAuthDAO userAuthDAO; + + public AuthController(UserDAO userDAO, UserAuthDAO userAuthDAO) { + this.userDAO = userDAO; + this.userAuthDAO = userAuthDAO; + } + + /** + * Attempts to log in as a user + * @param params A map/json object in the format {username: string, password: string} + * @return An api key if the auth was successful, null otherwise + */ + @PostMapping("") + public ResponseEntity<String> login(@RequestBody Map<String, String> params) { + String username = params.get("username"); + String password = params.get("password"); + try { + var usr = userDAO.getUser(username); + if (usr == null || !usr.verifyPassword(password)) { + return new ResponseEntity<>(HttpStatus.UNAUTHORIZED); + } + var userAuth = UserAuth.generate(username); + userAuthDAO.addUserAuth(userAuth); + return new ResponseEntity<>(userAuth.getKey(), HttpStatus.OK); + } catch (IOException ex) { + return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR); + } + } + + /** + * TODO + * @return + */ + @DeleteMapping("") + public ResponseEntity<Object> logout() { + return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED); + } +} diff --git a/ufund-api/src/main/java/com/ufund/api/ufundapi/controller/CupboardController.java b/ufund-api/src/main/java/com/ufund/api/ufundapi/controller/CupboardController.java index 4b2a04d..6b0bb71 100644 --- a/ufund-api/src/main/java/com/ufund/api/ufundapi/controller/CupboardController.java +++ b/ufund-api/src/main/java/com/ufund/api/ufundapi/controller/CupboardController.java @@ -1,6 +1,7 @@ package com.ufund.api.ufundapi.controller; import java.io.IOException; +import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; @@ -17,21 +18,23 @@ import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import com.ufund.api.ufundapi.model.Need; -import com.ufund.api.ufundapi.persistence.CupboardDAO; +import com.ufund.api.ufundapi.model.Need.GoalType; +import com.ufund.api.ufundapi.service.CupboardService; +import com.ufund.api.ufundapi.service.CupboardService.DuplicateKeyException; @RestController @RequestMapping("cupboard") public class CupboardController { private static final Logger LOG = Logger.getLogger(CupboardController.class.getName()); - private final CupboardDAO cupboardDAO; + private final CupboardService cupboardService; /** * Create a cupboard controller to receive REST signals * - * @param cupboardDAO The Data Access Object + * @param cupboardService The Data Access Object */ - public CupboardController(CupboardDAO cupboardDAO) { - this.cupboardDAO = cupboardDAO; + public CupboardController(CupboardService cupboardService) { + this.cupboardService = cupboardService; } /** @@ -41,16 +44,20 @@ public class CupboardController { * @return OK response and the need if it was successful, INTERNAL_SERVER_ERROR otherwise */ @PostMapping("") - public ResponseEntity<Need> createNeed(@RequestBody Need need) { + public ResponseEntity<Need> createNeed(@RequestBody Map<String, String> params) { + String name = params.get("name"); + int maxGoal = Integer.parseInt(params.get("maxGoal")); + Need.GoalType goalType = GoalType.valueOf(params.get("maxGoal")); + try { - if (need.getMaxGoal() <= 0) { - return new ResponseEntity<>(HttpStatus.BAD_REQUEST); - } - if (need.getMaxGoal() < need.getCurrent()) { - return new ResponseEntity<>(HttpStatus.BAD_REQUEST); - } - cupboardDAO.createNeed(need); + + Need need = cupboardService.createNeed(name, maxGoal, goalType); return new ResponseEntity<>(need, HttpStatus.OK); + + } catch (DuplicateKeyException ex) { + return new ResponseEntity<>(HttpStatus.CONFLICT); + } catch (IllegalArgumentException ex) { + return new ResponseEntity<>(HttpStatus.UNPROCESSABLE_ENTITY); } catch (IOException ex) { return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR); } @@ -69,7 +76,7 @@ public class CupboardController { LOG.info("GET /needs"); try { - Need[] needs = cupboardDAO.getNeeds(); + Need[] needs = cupboardService.getNeeds(); return new ResponseEntity<>(needs, HttpStatus.OK); } catch (IOException e) { LOG.log(Level.SEVERE, e.getLocalizedMessage()); @@ -93,8 +100,8 @@ public class CupboardController { LOG.info("GET /need/?name="+name); try { - Need[] needArray = cupboardDAO.findNeeds(name); - return new ResponseEntity<>(needArray, HttpStatus.OK); + Need[] needs = cupboardService.searchNeeds(name); + return new ResponseEntity<>(needs, HttpStatus.OK); } catch (IOException e) { LOG.log(Level.SEVERE,e.getLocalizedMessage()); return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR); @@ -116,7 +123,7 @@ public class CupboardController { LOG.log(Level.INFO, "GET /need/{0}", id); try { - Need need = cupboardDAO.getNeed(id); + Need need = cupboardService.getNeed(id); if (need != null) { return new ResponseEntity<>(need, HttpStatus.OK); } else { @@ -140,8 +147,12 @@ public class CupboardController { @PutMapping("") public ResponseEntity<Need> updateNeed(@RequestBody Need need) { try { - need = cupboardDAO.updateNeed(need); - return new ResponseEntity<>(need, HttpStatus.OK); + Need updatedNeed = cupboardService.updateNeed(need); + if (updatedNeed != null) { + return new ResponseEntity<>(need, HttpStatus.OK); + } else { + return new ResponseEntity<>(HttpStatus.NOT_FOUND); + } } catch (IOException e) { return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR); } @@ -156,9 +167,9 @@ public class CupboardController { @DeleteMapping("/{id}") public ResponseEntity<Need> deleteNeed(@PathVariable int id) { try { - if (cupboardDAO.getNeed(id) != null) { - cupboardDAO.deleteNeed(id); - return new ResponseEntity<>(HttpStatus.OK); + Need need = cupboardService.getNeed(id); + if (cupboardService.deleteNeed(id)) { + return new ResponseEntity<>(need, HttpStatus.OK); } else { return new ResponseEntity<>(HttpStatus.NOT_FOUND); } diff --git a/ufund-api/src/main/java/com/ufund/api/ufundapi/controller/UserController.java b/ufund-api/src/main/java/com/ufund/api/ufundapi/controller/UserController.java index 4e5f156..aa9598d 100644 --- a/ufund-api/src/main/java/com/ufund/api/ufundapi/controller/UserController.java +++ b/ufund-api/src/main/java/com/ufund/api/ufundapi/controller/UserController.java @@ -1,19 +1,14 @@ package com.ufund.api.ufundapi.controller; import java.io.IOException; +import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; +import com.ufund.api.ufundapi.persistence.UserAuthDAO; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.PutMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; import com.ufund.api.ufundapi.model.User; import com.ufund.api.ufundapi.persistence.UserDAO; @@ -21,30 +16,34 @@ import com.ufund.api.ufundapi.persistence.UserDAO; @RestController @RequestMapping("users") public class UserController { - private static final Logger LOG = Logger.getLogger(CupboardController.class.getName()); + private static final Logger LOG = Logger.getLogger(UserController.class.getName()); private final UserDAO UserDAO; + private final UserAuthDAO userAuthDAO; /** * Create a user controller to receive REST signals * * @param userDAO The Data Access Object */ - public UserController(UserDAO userDAO) { + public UserController(UserDAO userDAO, UserAuthDAO userAuthDAO) { this.UserDAO = userDAO; + this.userAuthDAO = userAuthDAO; } /** * Creates a User with the provided object * - * @param user The user to create * @return OK response and the user if it was successful, INTERNAL_SERVER_ERROR * otherwise */ @PostMapping("") - public ResponseEntity<User> createUser(@RequestBody User user) { + public ResponseEntity<Boolean> createUser(@RequestBody Map<String, String> params) { + String username = params.get("username"); + String password = params.get("password"); + try { - if (UserDAO.createUser(user) != null) { - return new ResponseEntity<>(user, HttpStatus.CREATED); + if (UserDAO.addUser(User.create(username, password)) != null) { + return new ResponseEntity<>(true, HttpStatus.CREATED); } else { return new ResponseEntity<>(HttpStatus.CONFLICT); } @@ -62,14 +61,19 @@ public class UserController { * ResponseEntity with HTTP status of NOT_FOUND if not found<br> * ResponseEntity with HTTP status of INTERNAL_SERVER_ERROR otherwise */ - @GetMapping("/{name}") - public ResponseEntity<User> getUser(@PathVariable String name) { - LOG.log(Level.INFO, "GET /user/{0}", name); + @GetMapping("/{username}") + public ResponseEntity<User> getUser(@PathVariable String username, @RequestHeader("jelly-api-key") String key) { + LOG.log(Level.INFO, "GET /user/{0}", username); + + var userAuth = userAuthDAO.getUserAuth(key); + if (userAuth == null || !userAuth.getUsername().equals(username)) { + return new ResponseEntity<>(HttpStatus.UNAUTHORIZED); + } try { - User user = UserDAO.getUser(name); + User user = UserDAO.getUser(username); if (user != null) { - return new ResponseEntity<>(user, HttpStatus.OK); + return new ResponseEntity<>(user.withoutPasswordHash(), HttpStatus.OK); } else { return new ResponseEntity<>(HttpStatus.NOT_FOUND); } @@ -89,7 +93,13 @@ public class UserController { * INTERNAL_SERVER_ERROR if there was an issue */ @PutMapping("/{name}") - public ResponseEntity<User> updateUser(@RequestBody User user, @PathVariable String name) { + public ResponseEntity<User> updateUser(@RequestBody User user, @PathVariable String name, @RequestHeader("jelly-api-key") String key) { + + var userAuth = userAuthDAO.getUserAuth(key); + if (userAuth == null || !userAuth.getUsername().equals(user.getUsername())) { + return new ResponseEntity<>(HttpStatus.UNAUTHORIZED); + } + try { user = UserDAO.updateUser(user, name); if (user != null) { @@ -106,14 +116,20 @@ public class UserController { /** * Deletes a user with the desired name * - * @param name The name of the user + * @param username The name of the user * @return OK if the user was deleted, NOT_FOUND if the user was not found, or * INTERNAL_SERVER_ERROR if an error occurred */ - @DeleteMapping("/{name}") - public ResponseEntity<User> deleteUser(@PathVariable String name) { + @DeleteMapping("/{username}") + public ResponseEntity<User> deleteUser(@PathVariable String username, @RequestHeader("jelly-api-key") String key) { + + var userAuth = userAuthDAO.getUserAuth(key); + if (userAuth == null || !userAuth.getUsername().equals(username)) { + return new ResponseEntity<>(HttpStatus.UNAUTHORIZED); + } + try { - if (UserDAO.deleteUser(name)) { + if (UserDAO.deleteUser(username)) { return new ResponseEntity<>(HttpStatus.OK); } else { return new ResponseEntity<>(HttpStatus.NOT_FOUND); diff --git a/ufund-api/src/main/java/com/ufund/api/ufundapi/model/Need.java b/ufund-api/src/main/java/com/ufund/api/ufundapi/model/Need.java index 2611357..9ca097a 100644 --- a/ufund-api/src/main/java/com/ufund/api/ufundapi/model/Need.java +++ b/ufund-api/src/main/java/com/ufund/api/ufundapi/model/Need.java @@ -32,6 +32,19 @@ public class Need { } /** + * Create a new need + * + * @param name The name of the need + * @param maxGoal The maximum goal for this need + * @param type The type of need (monetary, physical) + */ + public Need(String name, GoalType type, double maxGoal) { + this.name = name; + this.type = type; + this.maxGoal = maxGoal; + } + + /** * Create a deep copy of another need * * @param other The need to copy from diff --git a/ufund-api/src/main/java/com/ufund/api/ufundapi/model/User.java b/ufund-api/src/main/java/com/ufund/api/ufundapi/model/User.java index 59f4c46..1e182a6 100644 --- a/ufund-api/src/main/java/com/ufund/api/ufundapi/model/User.java +++ b/ufund-api/src/main/java/com/ufund/api/ufundapi/model/User.java @@ -7,8 +7,8 @@ import com.fasterxml.jackson.annotation.JsonProperty; public class User { - @JsonProperty("name") - private final String name; + @JsonProperty("username") + private final String username; @JsonProperty("passwordHash") private int passwordHash; @JsonProperty("basket") @@ -17,36 +17,35 @@ public class User { /** * Create a new user * - * @param name The name of the user + * @param username The name of the user */ - public User(String name) { - this.name = name; + public User(String username) { + this.username = username; basket = new ArrayList<>(); } /** * Create a new user * - * @param name The name of the user + * @param username The name of the user * @param basket A basket to copy from */ - public User(@JsonProperty("name") String name, @JsonProperty("basket") List<Need> basket) { - this.name = name; + public User(@JsonProperty("username") String username, @JsonProperty("passwordHash") int passwordHash, @JsonProperty("basket") List<Need> basket) { + this.username = username; this.basket = basket; + this.passwordHash = passwordHash; } - /** - * Create a deep copy of another user - * - * @param other The user to copy from - */ - public User(User other) { - this.name = other.name; - this.basket = other.basket; + public static User create(String username, String password) { + return new User( + username, + password.hashCode(), + new ArrayList<>() + ); } - public String getName() { - return name; + public String getUsername() { + return username; } public boolean verifyPassword(String password) { @@ -65,4 +64,8 @@ public class User { basket.remove(need); } + public User withoutPasswordHash() { + return new User(this.username, 0, this.basket); + } + } diff --git a/ufund-api/src/main/java/com/ufund/api/ufundapi/model/UserAuth.java b/ufund-api/src/main/java/com/ufund/api/ufundapi/model/UserAuth.java new file mode 100644 index 0000000..1c11a28 --- /dev/null +++ b/ufund-api/src/main/java/com/ufund/api/ufundapi/model/UserAuth.java @@ -0,0 +1,43 @@ +package com.ufund.api.ufundapi.model; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.time.LocalDateTime; +import java.util.UUID; + +public class UserAuth { + @JsonProperty("key") String key; + @JsonProperty("username") String username; + @JsonProperty("expiration") LocalDateTime expiration; + + public UserAuth(@JsonProperty("key") String key, @JsonProperty("username") String username, @JsonProperty("expiration") LocalDateTime expiration) { + this.key = key; + this.expiration = expiration; + this.username = username; + } + + /** + * Generate a new user authentication profile + * @param username the username the key will belong to + * @return The new user authentication profile + */ + public static UserAuth generate(String username) { + return new UserAuth( + UUID.randomUUID().toString(), + username, + LocalDateTime.now().plusDays(30) + ); + } + + public String getKey() { + return key; + } + + public String getUsername() { + return username; + } + + public LocalDateTime getExpiration() { + return expiration; + } +} diff --git a/ufund-api/src/main/java/com/ufund/api/ufundapi/persistence/CupboardDAO.java b/ufund-api/src/main/java/com/ufund/api/ufundapi/persistence/CupboardDAO.java index 1435410..6baf3e4 100644 --- a/ufund-api/src/main/java/com/ufund/api/ufundapi/persistence/CupboardDAO.java +++ b/ufund-api/src/main/java/com/ufund/api/ufundapi/persistence/CupboardDAO.java @@ -1,9 +1,9 @@ package com.ufund.api.ufundapi.persistence; -import com.ufund.api.ufundapi.model.Need; - import java.io.IOException; +import com.ufund.api.ufundapi.model.Need; + /** * Defines the interface for Need object persistence * @@ -20,17 +20,6 @@ public interface CupboardDAO { Need[] getNeeds() throws IOException; /** - * Finds all {@linkplain Need needs} whose name contains the given text - * - * @param targetName The text to match against - * - * @return An array of {@link Need needs} whose names contains the given text, may be empty - * - * @throws IOException if an issue with underlying storage - */ - Need[] findNeeds(String targetName) throws IOException; - - /** * Retrieves a {@linkplain Need need} with the given name * * @param id The ID of the {@link Need need} to get @@ -54,7 +43,7 @@ public interface CupboardDAO { * * @throws IOException if an issue with underlying storage */ - Need createNeed(Need need) throws IOException; + Need addNeed(Need need) throws IOException; /** * Updates and saves a {@linkplain Need need} diff --git a/ufund-api/src/main/java/com/ufund/api/ufundapi/persistence/CupboardFileDao.java b/ufund-api/src/main/java/com/ufund/api/ufundapi/persistence/CupboardFileDao.java index 81ee7c0..84ea693 100644 --- a/ufund-api/src/main/java/com/ufund/api/ufundapi/persistence/CupboardFileDao.java +++ b/ufund-api/src/main/java/com/ufund/api/ufundapi/persistence/CupboardFileDao.java @@ -61,18 +61,6 @@ public class CupboardFileDao implements CupboardDAO { } /** - * Returns an array of needs filtered by a search - * - * @param search The search substring - * @return The requested array - */ - private Need[] getNeedsArray(String search) { - return needs.values().stream() - .filter(i -> i.getName().toLowerCase().contains(search.toLowerCase())) - .toArray(Need[]::new); - } - - /** * Saves the needs to json * * @return True if the save was successful, false otherwise @@ -93,13 +81,6 @@ public class CupboardFileDao implements CupboardDAO { } @Override - public Need[] findNeeds(String targetName) { - synchronized (needs) { - return getNeedsArray(targetName); - } - } - - @Override public Need getNeed(int id) { synchronized (needs) { return needs.getOrDefault(id, null); @@ -107,7 +88,7 @@ public class CupboardFileDao implements CupboardDAO { } @Override - public Need createNeed(Need need) throws IOException { + public Need addNeed(Need need) throws IOException { synchronized (needs) { Need newNeed = new Need(need); newNeed.setID(nextId()); diff --git a/ufund-api/src/main/java/com/ufund/api/ufundapi/persistence/UserAuthDAO.java b/ufund-api/src/main/java/com/ufund/api/ufundapi/persistence/UserAuthDAO.java new file mode 100644 index 0000000..45515b8 --- /dev/null +++ b/ufund-api/src/main/java/com/ufund/api/ufundapi/persistence/UserAuthDAO.java @@ -0,0 +1,23 @@ +package com.ufund.api.ufundapi.persistence; + +import com.ufund.api.ufundapi.model.UserAuth; + +import java.io.IOException; + +public interface UserAuthDAO { + + /** + * Get a user authentication profile + * @param key The auth key + * @return The authentication profile or null if there was none + */ + UserAuth getUserAuth(String key); + + /** + * Add a user authentication profile + * @param userAuth The user auth profile to add + * @return True if it was successful + * @throws IOException On any file writing error + */ + boolean addUserAuth(UserAuth userAuth) throws IOException; +} diff --git a/ufund-api/src/main/java/com/ufund/api/ufundapi/persistence/UserAuthFIleDAO.java b/ufund-api/src/main/java/com/ufund/api/ufundapi/persistence/UserAuthFIleDAO.java new file mode 100644 index 0000000..67918cc --- /dev/null +++ b/ufund-api/src/main/java/com/ufund/api/ufundapi/persistence/UserAuthFIleDAO.java @@ -0,0 +1,62 @@ +package com.ufund.api.ufundapi.persistence; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.ufund.api.ufundapi.model.UserAuth; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +import java.io.File; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +@Component +public class UserAuthFIleDAO implements UserAuthDAO { + + private final Map<String, UserAuth> userAuthMap; + private final ObjectMapper objectMapper; + private final String filename; + + public UserAuthFIleDAO(ObjectMapper objectMapper, @Value("${authKeys.file}") String filename) throws IOException { + this.userAuthMap = new HashMap<>(); + this.objectMapper = objectMapper; + this.filename = filename; + load(); + } + + private void load() throws IOException { + userAuthMap.clear(); + + UserAuth[] userAuthKeysArray = objectMapper.readValue(new File(filename), UserAuth[].class); + + for (UserAuth userAuth : userAuthKeysArray) { + userAuthMap.put(userAuth.getKey(), userAuth); + } + } + + private void save() throws IOException { + objectMapper.writeValue(new File(filename), userAuthMap.values()); + } + + public UserAuth[] getAuthKeys() { + synchronized (userAuthMap) { + return userAuthMap.values().toArray(UserAuth[]::new); + } + } + + @Override + public UserAuth getUserAuth(String key) { + synchronized (userAuthMap) { + return userAuthMap.get(key); + } + } + + @Override + public boolean addUserAuth(UserAuth userAuth) throws IOException { + synchronized (userAuthMap) { + userAuthMap.put(userAuth.getKey(), userAuth); + save(); + return true; + } + } +} diff --git a/ufund-api/src/main/java/com/ufund/api/ufundapi/persistence/UserDAO.java b/ufund-api/src/main/java/com/ufund/api/ufundapi/persistence/UserDAO.java index d456abc..6558ce2 100644 --- a/ufund-api/src/main/java/com/ufund/api/ufundapi/persistence/UserDAO.java +++ b/ufund-api/src/main/java/com/ufund/api/ufundapi/persistence/UserDAO.java @@ -21,17 +21,17 @@ public interface UserDAO { User[] getUsers() throws IOException; /** - * Retrieves a {@linkplain User user} with the given name + * Retrieves a {@linkplain User user} with the given username * - * @param id The ID of the {@link User user} to get + * @param username The ID of the {@link User user} to get * - * @return a {@link User user} object with the matching name + * @return a {@link User user} object with the matching username * <br> - * null if no {@link User user} with a matching name is found + * null if no {@link User user} with a matching username is found * * @throws IOException if an issue with underlying storage */ - User getUser(String name) throws IOException; + User getUser(String username) throws IOException; /** * Creates and saves a {@linkplain User user} @@ -44,7 +44,7 @@ public interface UserDAO { * * @throws IOException if an issue with underlying storage */ - User createUser(User user) throws IOException; + User addUser(User user) throws IOException; /** * Updates and saves a {@linkplain User user} @@ -62,7 +62,7 @@ public interface UserDAO { /** * Deletes a {@linkplain User user} with the given id * - * @param id The id of the {@link User user} + * @param username The id of the {@link User user} * * @return true if the {@link User user} was deleted * <br> @@ -70,5 +70,5 @@ public interface UserDAO { * * @throws IOException if underlying storage cannot be accessed */ - boolean deleteUser(String name) throws IOException; + boolean deleteUser(String username) throws IOException; } diff --git a/ufund-api/src/main/java/com/ufund/api/ufundapi/persistence/UserFileDAO.java b/ufund-api/src/main/java/com/ufund/api/ufundapi/persistence/UserFileDAO.java index 18eec18..54ce74a 100644 --- a/ufund-api/src/main/java/com/ufund/api/ufundapi/persistence/UserFileDAO.java +++ b/ufund-api/src/main/java/com/ufund/api/ufundapi/persistence/UserFileDAO.java @@ -36,7 +36,7 @@ public class UserFileDAO implements UserDAO { User[] usersArray = objectMapper.readValue(new File(filename), User[].class); for (User user : usersArray) { - users.put(user.getName(), user); + users.put(user.getUsername(), user); } } @@ -72,15 +72,15 @@ public class UserFileDAO implements UserDAO { /** * Return the user with the String name name or null otherwise * - * @param name Name of desired user + * @param username Name of desired user * * @return Desired user, null otherwise * @throws IOException If there was an IO issue saving the file */ @Override - public User getUser(String name) throws IOException { + public User getUser(String username) throws IOException { synchronized (users) { - return users.getOrDefault(name, null); + return users.getOrDefault(username, null); } } @@ -93,16 +93,11 @@ public class UserFileDAO implements UserDAO { * @throws IOException If there was an IO issue saving the file */ @Override - public User createUser(User user) throws IOException { + public User addUser(User user) throws IOException { synchronized (users) { - if (getUser(user.getName()) == null) { - User newUser = new User(user); - users.put(newUser.getName(), newUser); - save(); - return newUser; - } else { - return null; - } + var res = users.putIfAbsent(user.getUsername(), user); + save(); + return res; } } @@ -131,16 +126,16 @@ public class UserFileDAO implements UserDAO { /** * Delete a user matching the name * - * @param name The name of the user + * @param username The name of the user * * @return True if deleted, false otherwise * @throws IOException If there was an IO issue saving the file */ @Override - public boolean deleteUser(String name) throws IOException { + public boolean deleteUser(String username) throws IOException { synchronized (users) { - if (users.containsKey(name)) { - users.remove(name); + if (users.containsKey(username)) { + users.remove(username); return save(); } else { return false; diff --git a/ufund-api/src/main/java/com/ufund/api/ufundapi/service/AuthService.java b/ufund-api/src/main/java/com/ufund/api/ufundapi/service/AuthService.java new file mode 100644 index 0000000..caf1edd --- /dev/null +++ b/ufund-api/src/main/java/com/ufund/api/ufundapi/service/AuthService.java @@ -0,0 +1,5 @@ +package com.ufund.api.ufundapi.service; + +public class AuthService { + +} diff --git a/ufund-api/src/main/java/com/ufund/api/ufundapi/service/CupboardService.java b/ufund-api/src/main/java/com/ufund/api/ufundapi/service/CupboardService.java new file mode 100644 index 0000000..860a2a8 --- /dev/null +++ b/ufund-api/src/main/java/com/ufund/api/ufundapi/service/CupboardService.java @@ -0,0 +1,83 @@ +package com.ufund.api.ufundapi.service; + +import java.io.IOException; +import java.util.Arrays; + +import com.ufund.api.ufundapi.model.Need; +import com.ufund.api.ufundapi.persistence.CupboardDAO; + +public class CupboardService { + + private final CupboardDAO cupboardDAO; + + public class DuplicateKeyException extends Exception { + + public DuplicateKeyException(String message) { + super(message); + } + + } + + public CupboardService(CupboardDAO cupboardDAO) { + this.cupboardDAO = cupboardDAO; + } + + public Need createNeed(String name, int maxGoal, Need.GoalType goalType) throws IOException, DuplicateKeyException { + + Need need = new Need(name, goalType, maxGoal); + + if (need.getMaxGoal() <= 0) { + throw new IllegalArgumentException("Max Goal must be greater than zero"); + } else { + for (Need searchNeed : cupboardDAO.getNeeds()) { + if (need.getName().equalsIgnoreCase(searchNeed.getName())) { + throw new DuplicateKeyException("Duplicate names are not allowed"); + } + } + return cupboardDAO.addNeed(need); + } + + } + + public Need[] getNeeds() throws IOException { + return cupboardDAO.getNeeds(); + } + + /** + * Returns an array of needs filtered by a search + * + * @param search The search substring + * @return The requested array + * @throws IOException + */ + public Need[] searchNeeds(String search) throws IOException { + return Arrays.stream(cupboardDAO.getNeeds()) + .filter(i -> i.getName().toLowerCase().contains(search.toLowerCase())) + .toArray(Need[]::new); + } + + /** + * @param id + * @return + * @throws IOException + */ + public Need getNeed(int id) throws IOException { + return cupboardDAO.getNeed(id); + } + + /** + * + * @param need + * @return + * @throws IOException + */ + public Need updateNeed(Need need) throws IOException { + return cupboardDAO.updateNeed(need); + } + + public boolean deleteNeed(int id) throws IOException { + return cupboardDAO.deleteNeed(id); + } + + +} diff --git a/ufund-api/src/main/java/com/ufund/api/ufundapi/service/UserService.java b/ufund-api/src/main/java/com/ufund/api/ufundapi/service/UserService.java new file mode 100644 index 0000000..994512d --- /dev/null +++ b/ufund-api/src/main/java/com/ufund/api/ufundapi/service/UserService.java @@ -0,0 +1,5 @@ +package com.ufund.api.ufundapi.service; + +public class UserService { + +} |