diff options
| author | Gunther6070 <haydenhartman10@yahoo.com> | 2025-03-24 21:17:33 -0400 | 
|---|---|---|
| committer | Gunther6070 <haydenhartman10@yahoo.com> | 2025-03-24 21:17:33 -0400 | 
| commit | cb3b7710b9e32df408b3a38383aca049fa98214e (patch) | |
| tree | 38bbfe093fe6b397dd5f378c77e56f581058753b | |
| parent | 35d7c971ed47718d4dc5738edb09d62cd780dac4 (diff) | |
| download | JellySolutions-cb3b7710b9e32df408b3a38383aca049fa98214e.tar.gz JellySolutions-cb3b7710b9e32df408b3a38383aca049fa98214e.tar.bz2 JellySolutions-cb3b7710b9e32df408b3a38383aca049fa98214e.zip  | |
Fixed various bugs and began fixing auth system. Also started implementing checkout method in cupboardService
Diffstat (limited to '')
14 files changed, 191 insertions, 61 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 36ae341..664b53b 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 @@ -13,6 +13,7 @@ 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.RequestHeader;  import org.springframework.web.bind.annotation.RequestMapping;  import org.springframework.web.bind.annotation.RequestParam;  import org.springframework.web.bind.annotation.RestController; @@ -162,6 +163,34 @@ public class CupboardController {      }      /** +     * Checks out a need by checkoutAmount +     *  +     * @param data JSON object with paramters needID and amount +     * @param key  Key used to authenticate user +     * @return OK if successful, other statuses if failure +     * @throws IllegalAccessException +     */ +    @PutMapping("/checkout") +    public ResponseEntity<Object> checkoutNeeds(@RequestBody Map<String, Integer> data, @RequestHeader("jelly-api-key") String key) throws IllegalAccessException { +        int needID = data.get("needID"); +        int checkoutAmount = data.get("amount"); +        LOG.log(Level.INFO, "Checking out need with ID: " + needID + " by " + checkoutAmount); +        try { +            cupboardService.checkoutNeed(needID, checkoutAmount, key); +            return new ResponseEntity<>(HttpStatus.OK); +        } catch (IllegalArgumentException ex) { +            ex.printStackTrace(); +            return new ResponseEntity<>(HttpStatus.BAD_REQUEST); +        } catch (IllegalAccessException ex) { +            ex.printStackTrace(); +            return new ResponseEntity<>(HttpStatus.UNAUTHORIZED); +        } catch (IOException ex) { +            ex.printStackTrace(); +            return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR); +        } +    } + +    /**       * Deletes a single need from the cupboard using the Need's id       *        * @param id The need's ID 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 dfaad3a..b0dbd1d 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 @@ -99,12 +99,13 @@ public class UserController {       * @param key      The authentication key of the user       * @return OK response and the user if it was successful, or       *         INTERNAL_SERVER_ERROR if there was an issue +     * @throws IllegalAccessException        */      @PutMapping("/{username}") -    public ResponseEntity<User> updateUser(@RequestBody User user, @PathVariable String username, @RequestHeader("jelly-api-key") String key) { -        LOG.log(Level.INFO,"PUT: " + user + " " + username + " " + key.toString()); +    public ResponseEntity<User> updateUser(@RequestHeader("jelly-api-key") String key, @RequestBody User user, @PathVariable String username) throws IllegalAccessException { +        LOG.log(Level.INFO,"PUT: " + user + " " + username + " " + key);          try { -            //authService.authenticate(username, key); +            authService.authenticate(username, key);              user = userService.updateUser(user, username);              if (user != null) {                  return new ResponseEntity<>(user, HttpStatus.OK); 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 c0e9214..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 @@ -17,14 +17,14 @@ public class Need {      @JsonProperty("current") private double current;      /** -     * Create a new need +     * Create a new need, used by the controller       *       * @param name The name of the need       * @param id The unique ID of the need       * @param maxGoal The maximum goal for this need       * @param type The type of need (monetary, physical)       */ -    public Need(@JsonProperty("name") String name, @JsonProperty("id") int id, @JsonProperty("maxGoal") double maxGoal, GoalType type) { +    public Need(@JsonProperty("name") String name, @JsonProperty("id") int id, @JsonProperty("maxGoal") double maxGoal, @JsonProperty("type") GoalType type) {          this.id = id;          this.name = name;          this.maxGoal = maxGoal; @@ -86,6 +86,10 @@ public class Need {          this.current = current;      } +    public void incrementCurrent(double incrementAmount) { +        this.current += incrementAmount; +    } +      public void setFilterAttributes(String[] filterAttributes) {          this.filterAttributes = filterAttributes;      } 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 6de1a8a..2871916 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 @@ -43,10 +43,21 @@ public class User {          return username;      } +    /** +     * Verifies if the provided password's hash is the same as the user's actual hash +     *  +     * @param password The password to check if valid +     * @return True or false depending on if it's equal +     */      public boolean verifyPassword(String password) {          return password.hashCode() == passwordHash;      } +    /** +     * Adds a need's ID to a user's basket +     *  +     * @param need The need to add +     */      public void addToBasket(Need need) {          basket.add(need.getId());      } @@ -59,6 +70,11 @@ public class User {          return basket.remove(needID);      } +    /** +     * Returns a user without a password hash for security purposes +     *  +     * @return new User with empty password hash +     */      public User withoutPasswordHash() {          return new User(this.username, 0, this.basket, this.type);      } @@ -71,6 +87,7 @@ public class User {          this.passwordHash = other.passwordHash;      } +    @Override      public String toString() {          return this.username + "; basket: " + this.basket + "; type:" + this.type + "; hash: " + this.passwordHash;      } 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 index 1c11a28..78dccec 100644 --- 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 @@ -1,10 +1,10 @@  package com.ufund.api.ufundapi.model; -import com.fasterxml.jackson.annotation.JsonProperty; -  import java.time.LocalDateTime;  import java.util.UUID; +import com.fasterxml.jackson.annotation.JsonProperty; +  public class UserAuth {      @JsonProperty("key") String key;      @JsonProperty("username") String username; @@ -12,12 +12,13 @@ public class UserAuth {      public UserAuth(@JsonProperty("key") String key, @JsonProperty("username") String username, @JsonProperty("expiration") LocalDateTime expiration) {          this.key = key; -        this.expiration = expiration;          this.username = username; +        this.expiration = expiration;      }      /**       * Generate a new user authentication profile +     *        * @param username the username the key will belong to       * @return The new user authentication profile       */ 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 521acae..4d11554 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 @@ -1,15 +1,16 @@  package com.ufund.api.ufundapi.persistence; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.ufund.api.ufundapi.model.Need; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.stereotype.Component; -  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.Need; +  @Component  public class CupboardFileDAO implements CupboardDAO { 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 1fc1e92..9023b42 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 @@ -1,15 +1,17 @@  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.time.LocalDateTime;  import java.util.HashMap;  import java.util.Map; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.ufund.api.ufundapi.model.UserAuth; +  @Component  public class UserAuthFIleDAO implements UserAuthDAO { @@ -35,7 +37,9 @@ public class UserAuthFIleDAO implements UserAuthDAO {          UserAuth[] userAuthKeysArray = objectMapper.readValue(new File(filename), UserAuth[].class);          for (UserAuth userAuth : userAuthKeysArray) { -            userAuthMap.put(userAuth.getKey(), userAuth); +            if (userAuth.getExpiration().compareTo(LocalDateTime.now()) > -1) { // Someone else double check the logic is correct. Checks if auth is valid and adds if so +                userAuthMap.put(userAuth.getKey(), userAuth); +            }          }      } 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 87a16a6..71b8f41 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 @@ -1,11 +1,12 @@  package com.ufund.api.ufundapi.service; +import java.io.IOException; + +import org.springframework.stereotype.Component; +  import com.ufund.api.ufundapi.model.User;  import com.ufund.api.ufundapi.model.UserAuth;  import com.ufund.api.ufundapi.persistence.UserAuthDAO; -import org.springframework.stereotype.Component; - -import java.io.IOException;  @Component  public class AuthService { @@ -30,12 +31,19 @@ public class AuthService {          if (userAuth == null) {              throw new IllegalAccessException("Unauthenticated");          } -// -//        var username = userAuth.getUsername(); -//        var userType = userService.getUser(username).getType(); -//        if (!username.equals(targetUsername) && userType != User.UserType.MANAGER) { -//            throw new IllegalAccessException("Unauthorized"); -//        } + +       var username = userAuth.getUsername(); +       var userType = userService.getUser(username).getType(); +       if (!username.equals(targetUsername) && userType != User.UserType.MANAGER) { +           throw new IllegalAccessException("Unauthorized"); +       } +    } + +    public void authenticate(String key) throws IOException, IllegalAccessException { +        var userAuth = userAuthDAO.getUserAuth(key); +        if (userAuth == null) { +            throw new IllegalAccessException("Unauthenticated"); +        }      }      /** 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 2398745..8713882 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 @@ -3,6 +3,7 @@ package com.ufund.api.ufundapi.service;  import java.io.IOException;  import java.util.Arrays; +import org.springframework.context.annotation.Lazy;  import org.springframework.stereotype.Component;  import com.ufund.api.ufundapi.DuplicateKeyException; @@ -13,8 +14,10 @@ import com.ufund.api.ufundapi.persistence.CupboardDAO;  public class CupboardService {      private final CupboardDAO cupboardDAO; +    final AuthService authService; -    public CupboardService(CupboardDAO cupboardDAO) { +    public CupboardService(@Lazy AuthService authService, CupboardDAO cupboardDAO) { +        this.authService = authService;          this.cupboardDAO = cupboardDAO;      } @@ -97,6 +100,23 @@ public class CupboardService {      }      /** +     * Checks out a need with the desired amount +     *  +     * @param id The ID of the need to update +     * @param checkoutAmount The amount to update the need by +     * @throws IOException  +     * @throws IllegalAccessException  +    */ +    public void checkoutNeed(int id, double checkoutAmount, String key) throws IOException, IllegalAccessException { +        if (checkoutAmount <= 0) { +            throw new IllegalArgumentException("Amount must be greather than 0"); +        } +        authService.authenticate(key); +        Need need = cupboardDAO.getNeed(id); +        need.incrementCurrent(checkoutAmount); +    } + +    /**       * Delete a need from the cupboard       *       * @param id the ID of the need 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 index caf9f4c..aaa2f06 100644 --- 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 @@ -2,6 +2,7 @@ package com.ufund.api.ufundapi.service;  import java.io.IOException; +import org.springframework.context.annotation.Lazy;  import org.springframework.stereotype.Component;  import com.ufund.api.ufundapi.DuplicateKeyException; @@ -12,7 +13,7 @@ import com.ufund.api.ufundapi.persistence.UserDAO;  public class UserService {      private final UserDAO userDAO; -    private final CupboardService cupboardService; +    final CupboardService cupboardService;      public UserService(UserDAO userDao, CupboardService cupboardService) {          this.userDAO = userDao; @@ -44,6 +45,9 @@ public class UserService {       */      public User getUser(String username) throws IOException {          User user = userDAO.getUser(username); +        if (user == null) { +            return null; +        }          for (int needId : user.getNeeds()) {              if (cupboardService.getNeed(needId) == null) {                  user.removeBasketNeed(needId); diff --git a/ufund-api/src/test/java/com/ufund/api/ufundapi/persistence/CupboardFileDAOTest.java b/ufund-api/src/test/java/com/ufund/api/ufundapi/persistence/CupboardFileDAOTest.java index f786a8c..0ebbeca 100644 --- a/ufund-api/src/test/java/com/ufund/api/ufundapi/persistence/CupboardFileDAOTest.java +++ b/ufund-api/src/test/java/com/ufund/api/ufundapi/persistence/CupboardFileDAOTest.java @@ -4,6 +4,7 @@ import java.io.File;  import java.io.IOException;  import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse;  import static org.junit.jupiter.api.Assertions.assertNotEquals;  import static org.junit.jupiter.api.Assertions.assertNotNull;  import static org.junit.jupiter.api.Assertions.assertNull; @@ -20,44 +21,43 @@ import com.ufund.api.ufundapi.model.Need.GoalType;  @Tag("Persistence-tier")  public class CupboardFileDAOTest { -    private CupboardFileDAO cupboardFileDao; -    private Need[] testNeeds; -    private ObjectMapper mockObjectMapper; - -    @BeforeEach -    public void setupCupboardFileDao() throws IOException { -        mockObjectMapper = mock(ObjectMapper.class); -        testNeeds = new Need[]{ -        	new Need("one", 0, 100, Need.GoalType.MONETARY), -			new Need("two", 1, 100, Need.GoalType.MONETARY), -			new Need("three", 2, 100, Need.GoalType.MONETARY) +	private CupboardFileDAO cupboardFileDao; +	private Need[] testNeeds; +	private ObjectMapper mockObjectMapper; + +	@BeforeEach +	public void setupCupboardFileDao() throws IOException { +		mockObjectMapper = mock(ObjectMapper.class); +		testNeeds = new Need[] { +				new Need("one", 0, 100, Need.GoalType.MONETARY), +				new Need("two", 1, 100, Need.GoalType.MONETARY), +				new Need("three", 2, 100, Need.GoalType.MONETARY)  		}; -        // When the object mapper is supposed to read from the file -        // the mock object mapper will return the hero array above -        when(mockObjectMapper -            .readValue(new File("doesnt_matter.txt"),Need[].class)) -                .thenReturn(testNeeds); -        cupboardFileDao = new CupboardFileDAO("doesnt_matter.txt",mockObjectMapper); -    } - -    @Test -    public void getNeedsTest() { -        Need[] needs = cupboardFileDao.getNeeds(); -        assertEquals(needs.length,testNeeds.length); +		// When the object mapper is supposed to read from the file +		// the mock object mapper will return the hero array above +		when(mockObjectMapper +				.readValue(new File("doesnt_matter.txt"), Need[].class)) +				.thenReturn(testNeeds); +		cupboardFileDao = new CupboardFileDAO("doesnt_matter.txt", mockObjectMapper); +	} + +	@Test +	public void getNeedsTest() { +		Need[] needs = cupboardFileDao.getNeeds(); +		assertEquals(needs.length, testNeeds.length);  		assertEquals(needs[0].getName(), testNeeds[0].getName()); -    } +	} -    @Test -    public void getNeedTest() { +	@Test +	public void getNeedTest() {  		Need need1 = cupboardFileDao.getNeed(0); -	 +  		assertEquals(testNeeds[0], need1); -    } +	}  	@Test  	public void createNeedTest() throws IOException {  		Need newNeed = new Need("sea urchin hats", 3, 100, GoalType.PHYSICAL); -		  		Need actualNeed = cupboardFileDao.addNeed(newNeed); @@ -79,6 +79,15 @@ public class CupboardFileDAOTest {  	}  	@Test +	public void deleteNeedTestFail() throws IOException { +		Need undeletedNeed = cupboardFileDao.getNeed(0); +		assertNotNull(undeletedNeed); + +		boolean nullNeed = cupboardFileDao.deleteNeed(20); +		assertFalse(nullNeed); +	} + +	@Test  	public void updateNeedTest() throws IOException {  		Need[] needs = cupboardFileDao.getNeeds();  		Need unupdatedNeed = needs[needs.length - 1]; @@ -91,4 +100,16 @@ public class CupboardFileDAOTest {  		assertNotEquals(actualNeed, unupdatedNeed);  	} +	@Test +	public void updateNeedTestFail() throws IOException { +		Need[] needs = cupboardFileDao.getNeeds(); +		Need unupdatedNeed = needs[needs.length - 1]; +		assertNotNull(unupdatedNeed); + +		Need updatedNeed = new Need("sequin sea urchin hats", 20, 100, GoalType.PHYSICAL); + +		Need actualNeed = cupboardFileDao.updateNeed(updatedNeed); +		assertNull(actualNeed); +	} +  } diff --git a/ufund-api/src/test/java/com/ufund/api/ufundapi/persistence/UserFileDAOTest.java b/ufund-api/src/test/java/com/ufund/api/ufundapi/persistence/UserFileDAOTest.java index 9361188..2ee0fc0 100644 --- a/ufund-api/src/test/java/com/ufund/api/ufundapi/persistence/UserFileDAOTest.java +++ b/ufund-api/src/test/java/com/ufund/api/ufundapi/persistence/UserFileDAOTest.java @@ -39,6 +39,24 @@ public class UserFileDAOTest {          userFileDAO = new UserFileDAO("doesnt_matter.txt",mockObjectMapper);      } +	@Test +	public void addUsersTest() throws IOException { +		User user = User.create("Name", "Pass"); + +		User addedUser = userFileDAO.addUser(user); + +		assertEquals(addedUser, user); +	} + +	@Test +	public void addUsersTestFail() throws IOException { +		User user = User.create("bob", "test"); + +		User existingUser = userFileDAO.addUser(user); + +		assertEquals(existingUser, testUsers[0]); +	} +      @Test      public void getUsersTest() {          User[] users = userFileDAO.getUsers(); diff --git a/ufund-api/src/test/java/com/ufund/api/ufundapi/service/CupboardServiceTest.java b/ufund-api/src/test/java/com/ufund/api/ufundapi/service/CupboardServiceTest.java index 99ca23c..59f5b1b 100644 --- a/ufund-api/src/test/java/com/ufund/api/ufundapi/service/CupboardServiceTest.java +++ b/ufund-api/src/test/java/com/ufund/api/ufundapi/service/CupboardServiceTest.java @@ -23,11 +23,13 @@ public class CupboardServiceTest {      private CupboardDAO mockCupboardDAO;      private CupboardService cupboardService; +    private AuthService mockAuthService;      @BeforeEach      public void setupCupboardService() {          mockCupboardDAO = mock(CupboardDAO.class); -        cupboardService = new CupboardService(mockCupboardDAO); +        mockAuthService = mock(AuthService.class); +        cupboardService = new CupboardService(mockAuthService, mockCupboardDAO);      } diff --git a/ufund-ui/src/app/services/users.service.ts b/ufund-ui/src/app/services/users.service.ts index dba8185..6709192 100644 --- a/ufund-ui/src/app/services/users.service.ts +++ b/ufund-ui/src/app/services/users.service.ts @@ -45,7 +45,7 @@ export class UsersService {      }      updateUser(user: User): Observable<User> { -        return this.http.put<User>(`${this.url}/${user.username}`,user, this.httpOptions2) +        return this.http.put<User>(`${this.url}/${user.username}`, user, this.httpOptions2)      }      deleteUser(id: number): Observable<boolean> {  | 
