aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTyler Ferrari <69283684+Sowgro@users.noreply.github.com>2025-02-26 17:20:11 -0500
committerGitHub <noreply@github.com>2025-02-26 17:20:11 -0500
commit9d832c1e96ca061b80b32abda472269bf7e0bbb7 (patch)
tree67ccc4c1f33b64d75c9cc7d57d05da3bc541bd26
parent4c452d39214c42e2b0dc2a557b0c2ef1e3bcd9c0 (diff)
parentda74d5c7e67b873dc8fdbfc672891eb63c0b8ea2 (diff)
downloadJellySolutions-9d832c1e96ca061b80b32abda472269bf7e0bbb7.tar.gz
JellySolutions-9d832c1e96ca061b80b32abda472269bf7e0bbb7.tar.bz2
JellySolutions-9d832c1e96ca061b80b32abda472269bf7e0bbb7.zip
Merge pull request #7 from RIT-SWEN-261-02/user-functionality
Merge user-functionality into main
-rw-r--r--ufund-api/data/cupboard.json4
-rw-r--r--ufund-api/data/users.json1
-rw-r--r--ufund-api/src/main/java/com/ufund/api/ufundapi/controller/UserController.java128
-rw-r--r--ufund-api/src/main/java/com/ufund/api/ufundapi/model/User.java68
-rw-r--r--ufund-api/src/main/java/com/ufund/api/ufundapi/persistence/UserDAO.java74
-rw-r--r--ufund-api/src/main/java/com/ufund/api/ufundapi/persistence/UserFileDAO.java151
-rw-r--r--ufund-api/src/main/resources/application.properties3
7 files changed, 427 insertions, 2 deletions
diff --git a/ufund-api/data/cupboard.json b/ufund-api/data/cupboard.json
index a30bf2e..bb7ec03 100644
--- a/ufund-api/data/cupboard.json
+++ b/ufund-api/data/cupboard.json
@@ -1 +1,3 @@
-[{"name":"Money for coral","id":1,"maxGoal":100.0,"type":"MONETARY","filterAttributes":null,"Current":0.0}] \ No newline at end of file
+[
+ {"name":"Money for coral","id":1,"maxGoal":100.0,"type":"MONETARY","filterAttributes":null,"Current":0.0}
+] \ No newline at end of file
diff --git a/ufund-api/data/users.json b/ufund-api/data/users.json
new file mode 100644
index 0000000..4e98a14
--- /dev/null
+++ b/ufund-api/data/users.json
@@ -0,0 +1 @@
+[{"name":"steve","password":null}] \ No newline at end of file
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
new file mode 100644
index 0000000..a40c46f
--- /dev/null
+++ b/ufund-api/src/main/java/com/ufund/api/ufundapi/controller/UserController.java
@@ -0,0 +1,128 @@
+package com.ufund.api.ufundapi.controller;
+
+import java.io.IOException;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+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 com.ufund.api.ufundapi.model.User;
+import com.ufund.api.ufundapi.persistence.UserDAO;
+
+@RestController
+@RequestMapping("users")
+public class UserController {
+ private static final Logger LOG = Logger.getLogger(CupboardController.class.getName());
+ private final UserDAO UserDAO;
+
+ /**
+ * Create a user controller to receive REST signals
+ *
+ * @param UserDAO The Data Access Object
+ */
+ public UserController(UserDAO userDAO) {
+ this.UserDAO = userDAO;
+ }
+
+ /**
+ * 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) {
+ try {
+ if (UserDAO.createUser(user) != null) {
+ return new ResponseEntity<>(user, HttpStatus.OK);
+ } else {
+ return new ResponseEntity<>(HttpStatus.CONFLICT);
+ }
+
+ } catch (IOException ex) {
+ return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
+ }
+ }
+
+ /**
+ * Responds to the GET request for a {@linkplain User user} for the given id
+ *
+ * @param id The id used to locate the {@link User user}
+ *
+ * @return ResponseEntity with {@link User user} object and HTTP status of OK if
+ * found<br>
+ * 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);
+
+ try {
+ User user = UserDAO.getUser(name);
+ if (user != null) {
+ return new ResponseEntity<>(user, HttpStatus.OK);
+ } else {
+ return new ResponseEntity<>(HttpStatus.NOT_FOUND);
+ }
+
+ } catch (IOException e) {
+ LOG.log(Level.SEVERE, e.getLocalizedMessage());
+ return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
+ }
+
+ }
+
+ /**
+ * Updates a User with the provided one
+ *
+ * @param user The user to update
+ * @return OK response and the user if it was successful, or
+ * INTERNAL_SERVER_ERROR if there was an issue
+ */
+ @PutMapping("/{name}")
+ public ResponseEntity<User> updateUser(@RequestBody User user, @PathVariable String name) {
+ try {
+ user = UserDAO.updateUser(user, name);
+ if (user != null) {
+ return new ResponseEntity<>(user, HttpStatus.OK);
+ } else {
+ return new ResponseEntity<>(HttpStatus.NOT_FOUND);
+ }
+
+ } catch (IOException e) {
+ return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
+ }
+ }
+
+ /**
+ * Deletes a user with the desired name
+ *
+ * @param name 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) {
+ try {
+ if (UserDAO.deleteUser(name)) {
+ return new ResponseEntity<>(HttpStatus.OK);
+ } else {
+ return new ResponseEntity<>(HttpStatus.NOT_FOUND);
+ }
+ } catch (IOException e) {
+ return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
+ }
+ }
+
+}
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
new file mode 100644
index 0000000..0a61714
--- /dev/null
+++ b/ufund-api/src/main/java/com/ufund/api/ufundapi/model/User.java
@@ -0,0 +1,68 @@
+package com.ufund.api.ufundapi.model;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public class User {
+
+ @JsonProperty("name")
+ private final String name;
+ @JsonProperty("passwordHash")
+ private int passwordHash;
+ @JsonProperty("basket")
+ private final List<Need> basket;
+
+ /**
+ * Create a new user
+ *
+ * @param name The name of the user
+ */
+ public User(@JsonProperty("name") String name) {
+ this.name = name;
+ basket = new ArrayList<>();
+ }
+
+ /**
+ * Create a new user
+ *
+ * @param name 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;
+ this.basket = basket;
+ }
+
+ /**
+ * 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 String getName() {
+ return name;
+ }
+
+ public boolean verifyPassword(String password) {
+ return password.hashCode() == passwordHash;
+ }
+
+ public void addToBasket(Need need) {
+ basket.add(need);
+ }
+
+ public Need[] getBasketNeeds() {
+ return basket.toArray(Need[]::new);
+ }
+
+ public void removeBasketNeed(Need need) {
+ basket.remove(need);
+ }
+
+}
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
new file mode 100644
index 0000000..d456abc
--- /dev/null
+++ b/ufund-api/src/main/java/com/ufund/api/ufundapi/persistence/UserDAO.java
@@ -0,0 +1,74 @@
+package com.ufund.api.ufundapi.persistence;
+
+import java.io.IOException;
+
+import com.ufund.api.ufundapi.model.User;
+
+
+/**
+ * Defines the interface for User object persistence
+ *
+ * @author Team 2B Jelly Solutions
+ */
+public interface UserDAO {
+ /**
+ * Retrieves all {@linkplain User users}
+ *
+ * @return An array of {@link User user} objects, may be empty
+ *
+ * @throws IOException if an issue with underlying storage
+ */
+ User[] getUsers() throws IOException;
+
+ /**
+ * Retrieves a {@linkplain User user} with the given name
+ *
+ * @param id The ID of the {@link User user} to get
+ *
+ * @return a {@link User user} object with the matching name
+ * <br>
+ * null if no {@link User user} with a matching name is found
+ *
+ * @throws IOException if an issue with underlying storage
+ */
+ User getUser(String name) throws IOException;
+
+ /**
+ * Creates and saves a {@linkplain User user}
+ *
+ * @param user {@linkplain User user} object to be created and saved
+ * <br>
+ * The id of the user object is automatically incremented.
+ *
+ * @return new {@link User user} if successful, null otherwise
+ *
+ * @throws IOException if an issue with underlying storage
+ */
+ User createUser(User user) throws IOException;
+
+ /**
+ * Updates and saves a {@linkplain User user}
+ *
+ * @param newUser {@link User user} object to be updated and saved
+ * @param name {@link String name} name of object to be updated
+ *
+ * @return updated {@link User user} if successful, null if
+ * {@link User user} could not be found
+ *
+ * @throws IOException if underlying storage cannot be accessed
+ */
+ User updateUser(User newUser, String name) throws IOException;
+
+ /**
+ * Deletes a {@linkplain User user} with the given id
+ *
+ * @param id The id of the {@link User user}
+ *
+ * @return true if the {@link User user} was deleted
+ * <br>
+ * false if the user with the given id does not exist
+ *
+ * @throws IOException if underlying storage cannot be accessed
+ */
+ boolean deleteUser(String name) 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
new file mode 100644
index 0000000..18eec18
--- /dev/null
+++ b/ufund-api/src/main/java/com/ufund/api/ufundapi/persistence/UserFileDAO.java
@@ -0,0 +1,151 @@
+package com.ufund.api.ufundapi.persistence;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Map;
+import java.util.TreeMap;
+
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.ufund.api.ufundapi.model.User;
+
+@Component
+public class UserFileDAO implements UserDAO {
+
+ private final Map<String, User> users; // cache
+ private final ObjectMapper objectMapper;
+ private final String filename;
+
+ public UserFileDAO(@Value("${users.file}") String filename, ObjectMapper objectMapper) throws IOException {
+ this.filename = filename;
+ this.objectMapper = objectMapper;
+ users = new TreeMap<>();
+ load(); // load the users from the file
+ }
+
+ /**
+ * Load changes from the json file
+ *
+ * @throws IOException Any IO issue with the file
+ */
+ private void load() throws IOException {
+ users.clear();
+
+ User[] usersArray = objectMapper.readValue(new File(filename), User[].class);
+
+ for (User user : usersArray) {
+ users.put(user.getName(), user);
+ }
+ }
+
+ /**
+ * Saves the needs to json
+ *
+ * @return True if the save was successful, false otherwise
+ * @throws IOException If there was an IO issue saving the file
+ */
+ private boolean save() throws IOException {
+ User[] userArray = getUserArray();
+
+ objectMapper.writeValue(new File(filename), userArray);
+ return true;
+ }
+
+ /**
+ * Return an array of the needs
+ *
+ * @return An array of all the needs
+ */
+ private User[] getUserArray() {
+ return users.values().toArray(User[]::new);
+ }
+
+ @Override
+ public User[] getUsers() throws IOException {
+ synchronized (users) {
+ return getUserArray();
+ }
+ }
+
+ /**
+ * Return the user with the String name name or null otherwise
+ *
+ * @param name 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 {
+ synchronized (users) {
+ return users.getOrDefault(name, null);
+ }
+ }
+
+ /**
+ * Create a User user
+ *
+ * @param user User to create
+ *
+ * @return Desired created user
+ * @throws IOException If there was an IO issue saving the file
+ */
+ @Override
+ public User createUser(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;
+ }
+ }
+ }
+
+ /**
+ * Update a user that matches the supplied name
+ *
+ * @param name The name of the user
+ * @param newUser New user data
+ *
+ * @return Desired user, null otherwise
+ * @throws IOException If there was an IO issue saving the file
+ */
+ @Override
+ public User updateUser(User newUser, String name) throws IOException {
+ synchronized (users) {
+ if (users.containsKey(name)) {
+ users.put(name, newUser);
+ save();
+ return newUser;
+ } else {
+ return null;
+ }
+ }
+ }
+
+ /**
+ * Delete a user matching the name
+ *
+ * @param name 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 {
+ synchronized (users) {
+ if (users.containsKey(name)) {
+ users.remove(name);
+ return save();
+ } else {
+ return false;
+ }
+ }
+ }
+
+} \ No newline at end of file
diff --git a/ufund-api/src/main/resources/application.properties b/ufund-api/src/main/resources/application.properties
index 22e8184..254ac64 100644
--- a/ufund-api/src/main/resources/application.properties
+++ b/ufund-api/src/main/resources/application.properties
@@ -1,4 +1,5 @@
# rename to application.properties
server.error.include-message=always
-cupboard.file=ufund-api/data/cupboard.json \ No newline at end of file
+cupboard.file=ufund-api/data/cupboard.json
+users.file=ufund-api/data/users.json \ No newline at end of file