diff options
Diffstat (limited to 'ufund-api/src/main')
5 files changed, 423 insertions, 1 deletions
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  | 
