diff options
Diffstat (limited to 'ufund-api/src/main/java')
7 files changed, 66 insertions, 28 deletions
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 d2029ed..bbfd3f6 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 @@ -5,6 +5,7 @@ import java.util.Map;  import java.util.logging.Level;  import java.util.logging.Logger; +import com.ufund.api.ufundapi.service.AuthService;  import org.springframework.http.HttpStatus;  import org.springframework.http.ResponseEntity;  import org.springframework.web.bind.annotation.DeleteMapping; @@ -23,21 +24,21 @@ import com.ufund.api.ufundapi.model.Need;  import com.ufund.api.ufundapi.model.Need.GoalType;  import com.ufund.api.ufundapi.service.CupboardService; -import static java.util.List.of; -  @RestController  @RequestMapping("cupboard")  public class CupboardController {      private static final Logger LOG = Logger.getLogger(CupboardController.class.getName());      private final CupboardService cupboardService; +    private final AuthService authService;      /**       * Create a cupboard controller to receive REST signals       *       * @param cupboardService The Data Access Object       */ -    public CupboardController(CupboardService cupboardService) { +    public CupboardController(CupboardService cupboardService, AuthService authService) {          this.cupboardService = cupboardService; +        this.authService = authService;      }      /** @@ -50,14 +51,15 @@ public class CupboardController {       *         INTERNAL_SERVER_ERROR otherwise       */      @PostMapping("") -    public ResponseEntity<Need> createNeed(@RequestBody Map<String, Object> params) { +    public ResponseEntity<Need> createNeed(@RequestBody Map<String, Object> params, @RequestHeader("jelly-api-key") String key) {          LOG.log(Level.INFO, "POST /cupboard body={0}", params);          String name = (String) params.get("name"); -        double maxGoal = (double) params.get("maxGoal"); +        double maxGoal = ((Number) params.get("maxGoal")).doubleValue();          Need.GoalType goalType = GoalType.valueOf((String) params.get("type"));          try { +            authService.keyHasAccessToCupboard(key);              Need need = cupboardService.createNeed(name, maxGoal, goalType);              return new ResponseEntity<>(need, HttpStatus.OK);          } catch (DuplicateKeyException ex) { @@ -66,6 +68,9 @@ public class CupboardController {          } catch (IllegalArgumentException ex) {              LOG.log(Level.WARNING, ex.getLocalizedMessage());              return new ResponseEntity<>(HttpStatus.BAD_REQUEST); +        } catch (IllegalAccessException ex) { +            LOG.log(Level.WARNING, ex.getLocalizedMessage()); +            return new ResponseEntity<>(HttpStatus.UNAUTHORIZED);          } catch (IOException ex) {              LOG.log(Level.SEVERE, ex.getLocalizedMessage());              return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR); @@ -152,9 +157,10 @@ public class CupboardController {       * @return OK response and the need if it was successful, or INTERNAL_SERVER_ERROR if there was an issue       */      @PutMapping("/{id}") -    public ResponseEntity<Need> updateNeed(@RequestBody Need need, @PathVariable int id) { +    public ResponseEntity<Need> updateNeed(@RequestBody Need need, @PathVariable int id, @RequestHeader("jelly-api-key") String key) {          LOG.log(Level.INFO, "PUT /cupboard/{0} body={1}", of(id, need));          try { +            authService.keyHasAccessToCupboard(key);              Need updatedNeed = cupboardService.updateNeed(need, id);              if (updatedNeed != null) {                  return new ResponseEntity<>(need, HttpStatus.OK); @@ -164,6 +170,9 @@ public class CupboardController {          } catch (IllegalArgumentException ex) {              LOG.log(Level.WARNING, ex.getLocalizedMessage());              return new ResponseEntity<>(HttpStatus.BAD_REQUEST); +        } catch (IllegalAccessException ex) { +            LOG.log(Level.WARNING, ex.getLocalizedMessage()); +            return new ResponseEntity<>(HttpStatus.UNAUTHORIZED);          } catch (IOException ex) {              LOG.log(Level.SEVERE, ex.getLocalizedMessage());              return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR); @@ -204,19 +213,27 @@ public class CupboardController {       * @return OK if the need was deleted, NOT_FOUND if the need was not found, or INTERNAL_SERVER_ERROR if an error occurred      */      @DeleteMapping("/{id}") -    public ResponseEntity<Need> deleteNeed(@PathVariable int id) { +    public ResponseEntity<Need> deleteNeed(@PathVariable int id, @RequestHeader("jelly-api-key") String key) {          LOG.log(Level.INFO, "DELETE /cupboard/{0}", id);          try { +            authService.keyHasAccessToCupboard(key);              Need need = cupboardService.getNeed(id);              if (cupboardService.deleteNeed(id)) {                  return new ResponseEntity<>(need, HttpStatus.OK);              } else {                  return new ResponseEntity<>(HttpStatus.NOT_FOUND); -            }  +            } +        } catch (IllegalAccessException ex) { +            LOG.log(Level.WARNING, ex.getLocalizedMessage()); +            return new ResponseEntity<>(HttpStatus.UNAUTHORIZED);          } catch (IOException ex) {              LOG.log(Level.SEVERE, ex.getLocalizedMessage());              return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);          }      } +    private Object[] of(Object ...params) { +        return params; +    } +  } 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 c2d9e06..33d2e4f 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 @@ -22,8 +22,6 @@ import com.ufund.api.ufundapi.model.User;  import com.ufund.api.ufundapi.service.AuthService;  import com.ufund.api.ufundapi.service.UserService; -import static java.util.List.of; -  @RestController  @RequestMapping("users")  public class UserController { @@ -79,7 +77,7 @@ public class UserController {          LOG.log(Level.INFO, "GET /user/{0} key={1}", of(username, key));          try { -            authService.authenticate(username, key); +            authService.keyHasAccessToUser(username, key);              User user = userService.getUser(username);              if (user != null) {                  return new ResponseEntity<>(user.withoutPasswordHash(), HttpStatus.OK); @@ -109,7 +107,7 @@ public class UserController {      public ResponseEntity<User> updateUser(@RequestBody User user, @PathVariable String username, @RequestHeader("jelly-api-key") String key) {          LOG.log(Level.INFO,"PUT /users/{0} body={1} key={2}", of(username, user, key));          try { -            authService.authenticate(username, key); +            authService.keyHasAccessToUser(username, key);              user = userService.updateUser(user, username);              if (user != null) {                  return new ResponseEntity<>(user, HttpStatus.OK); @@ -141,7 +139,7 @@ public class UserController {          LOG.log(Level.INFO, "DELETE /users/{0} id={1}", of(username, key));          try { -            authService.authenticate(username, key); +            authService.keyHasAccessToUser(username, key);              if (userService.deleteUser(username)) {                  return new ResponseEntity<>(HttpStatus.OK);              } else { @@ -156,4 +154,8 @@ public class UserController {          }      } +    private Object[] of(Object ...params) { +        return params; +    } +  } 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 786b104..22e86e3 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 @@ -38,7 +38,7 @@ public class 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) { // TODO why is this needed +    public Need(String name, GoalType type, double maxGoal) {          this.name = name;          this.type = type;          this.maxGoal = maxGoal; 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 index 9023b42..24a426b 100644 --- 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 @@ -37,7 +37,7 @@ public class UserAuthFIleDAO implements UserAuthDAO {          UserAuth[] userAuthKeysArray = objectMapper.readValue(new File(filename), UserAuth[].class);          for (UserAuth userAuth : userAuthKeysArray) { -            if (userAuth.getExpiration().compareTo(LocalDateTime.now()) > -1) { // Someone else double check the logic is correct. Checks if auth is valid and adds if so +            if (userAuth.getExpiration().isAfter(LocalDateTime.now())) {                  userAuthMap.put(userAuth.getKey(), userAuth);              }          } 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 0d9b9e4..ec94da8 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 @@ -2,7 +2,6 @@ package com.ufund.api.ufundapi.persistence;  import java.io.File;  import java.io.IOException; -import java.util.ArrayList;  import java.util.HashMap;  import java.util.Map;  import java.util.Objects; @@ -81,15 +80,8 @@ public class UserFileDAO implements UserDAO {      public User updateUser(User user) throws IOException {          synchronized (users) {              if (users.containsKey(user.getUsername())) { -                if (user.getBasket() == null || user.getType() == null) { // TODO clean this up -                    User oldData = users.get(user.getUsername()); -                    User crutch = new User(oldData.getUsername(), 0, new ArrayList<>(), oldData.getType()); -                    crutch.copyPassword(oldData); -                    users.put(user.getUsername(), crutch); -                } else { -                    var old = users.put(user.getUsername(), user); -                    user.copyPassword(Objects.requireNonNull(old)); -                } +                var old = users.put(user.getUsername(), user); +                user.copyPassword(Objects.requireNonNull(old));                  save();                  return user;              } else { 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 index 4e5ebce..cdce80d 100644 --- 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 @@ -25,8 +25,9 @@ public class AuthService {       * @param targetUsername The targetUsername of the user trying to be accessed.       * @param key The api key obtained by the client from logging in.       * @throws IllegalAccessException Thrown if access was denied to the user. +     * @throws IOException Thrown on a file writing issue       */ -    public void authenticate(String targetUsername, String key) throws IllegalAccessException, IOException { +    public void keyHasAccessToUser(String targetUsername, String key) throws IllegalAccessException, IOException {          var userAuth = userAuthDAO.getUserAuth(key);          if (userAuth == null) {              throw new IllegalAccessException("Invalid authentication key"); @@ -39,11 +40,36 @@ public class AuthService {         }      } -    public void authenticate(String key) throws IOException, IllegalAccessException { +    /** +     * Check if the provided key is valid +     * @param key The api key obtained by the client from logging in. +     * @throws IllegalAccessException Thrown if access was denied to the user. +     * @throws IOException Thrown on a file writing issue +     */ +    public void keyIsValid(String key) throws IOException, IllegalAccessException { +        var userAuth = userAuthDAO.getUserAuth(key); +        if (userAuth == null) { +            throw new IllegalAccessException("Invalid authentication key"); +        } +    } + +    /** +     * Check if the provided key has access to edit the cupboard +     * @param key The api key obtained by the client from logging in. +     * @throws IllegalAccessException Thrown if access was denied to the user. +     * @throws IOException Thrown on a file writing issue +     */ +    public void keyHasAccessToCupboard(String key) throws IOException, IllegalAccessException {          var userAuth = userAuthDAO.getUserAuth(key);          if (userAuth == null) {              throw new IllegalAccessException("Invalid authentication key");          } + +        var username = userAuth.getUsername(); +        var userType = userService.getUser(username).getType(); +        if (userType != User.UserType.MANAGER) { +            throw new IllegalAccessException("Provided key does not grant access to perform the requested operation"); +        }      }      /** 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 index 91e3ba5..aaa8cb8 100644 --- 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 @@ -111,7 +111,7 @@ public class CupboardService {          if (checkoutAmount <= 0) {              throw new IllegalArgumentException("Amount must be greater than 0");          } -        authService.authenticate(key); +        authService.keyIsValid(key);          Need need = cupboardDAO.getNeed(id);          need.incrementCurrent(checkoutAmount);      } @@ -124,6 +124,7 @@ public class CupboardService {       * @throws IOException Thrown on any problem removing the need       */      public boolean deleteNeed(int id) throws IOException { +                  return cupboardDAO.deleteNeed(id);      }  }  | 
