aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ufund-api/src/main/java/com/ufund/api/ufundapi/controller/CupboardController.java33
-rw-r--r--ufund-api/src/main/java/com/ufund/api/ufundapi/controller/UserController.java12
-rw-r--r--ufund-api/src/main/java/com/ufund/api/ufundapi/model/Need.java2
-rw-r--r--ufund-api/src/main/java/com/ufund/api/ufundapi/persistence/UserAuthFIleDAO.java2
-rw-r--r--ufund-api/src/main/java/com/ufund/api/ufundapi/persistence/UserFileDAO.java12
-rw-r--r--ufund-api/src/main/java/com/ufund/api/ufundapi/service/AuthService.java30
-rw-r--r--ufund-api/src/main/java/com/ufund/api/ufundapi/service/CupboardService.java3
-rw-r--r--ufund-api/src/test/java/com/ufund/api/ufundapi/controller/CupboardControllerTest.java29
-rw-r--r--ufund-api/src/test/java/com/ufund/api/ufundapi/controller/UserControllerTest.java6
-rw-r--r--ufund-api/src/test/java/com/ufund/api/ufundapi/persistence/UserAuthFileDAOTest.java2
-rw-r--r--ufund-api/src/test/java/com/ufund/api/ufundapi/service/AuthServiceTest.java12
-rw-r--r--ufund-ui/src/app/app.component.ts8
-rw-r--r--ufund-ui/src/app/components/cupboard/cupboard.component.ts58
-rw-r--r--ufund-ui/src/app/components/dashboard/dashboard.component.ts20
-rw-r--r--ufund-ui/src/app/components/funding-basket/funding-basket.component.ts122
-rw-r--r--ufund-ui/src/app/components/home-page/home-page.component.ts10
-rw-r--r--ufund-ui/src/app/components/login/login.component.ts14
-rw-r--r--ufund-ui/src/app/components/need-list/need-list.component.ts212
-rw-r--r--ufund-ui/src/app/components/need-page/need-page.component.ts38
-rw-r--r--ufund-ui/src/app/models/Need.ts16
-rw-r--r--ufund-ui/src/app/models/User.ts2
-rw-r--r--ufund-ui/src/app/services/auth.service.ts57
-rw-r--r--ufund-ui/src/app/services/cupboard.service.ts30
-rw-r--r--ufund-ui/src/app/services/users.service.ts52
24 files changed, 412 insertions, 370 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);
}
}
diff --git a/ufund-api/src/test/java/com/ufund/api/ufundapi/controller/CupboardControllerTest.java b/ufund-api/src/test/java/com/ufund/api/ufundapi/controller/CupboardControllerTest.java
index 6ef6710..89697bf 100644
--- a/ufund-api/src/test/java/com/ufund/api/ufundapi/controller/CupboardControllerTest.java
+++ b/ufund-api/src/test/java/com/ufund/api/ufundapi/controller/CupboardControllerTest.java
@@ -7,10 +7,11 @@ import static java.util.Map.entry;
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.mockito.Mockito.*;
+
+import com.ufund.api.ufundapi.service.AuthService;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
import org.springframework.http.HttpStatus;
import com.ufund.api.ufundapi.DuplicateKeyException;
@@ -21,11 +22,17 @@ import com.ufund.api.ufundapi.service.CupboardService;
public class CupboardControllerTest {
private CupboardController cupboardController;
private CupboardService mockCupboardService;
+ private final String key = "dummyKey";
@BeforeEach
public void setupCupboardDAO() {
+ AuthService mockAuthService = mock(AuthService.class);
mockCupboardService = mock(CupboardService.class);
- cupboardController = new CupboardController(mockCupboardService);
+ cupboardController = new CupboardController(mockCupboardService, mockAuthService);
+
+ try {
+ doThrow().when(mockAuthService).keyHasAccessToCupboard(key);
+ } catch (Exception ignored) {}
}
@Test
@@ -43,7 +50,7 @@ public class CupboardControllerTest {
entry("type", "MONETARY")
);
- var res = cupboardController.createNeed(needMap);
+ var res = cupboardController.createNeed(needMap, key);
assertEquals(HttpStatus.OK, res.getStatusCode());
assertEquals(need, res.getBody());
@@ -58,7 +65,7 @@ public class CupboardControllerTest {
entry("maxGoal", -100.0),
entry("type", "MONETARY"));
- var res = cupboardController.createNeed(needMap);
+ var res = cupboardController.createNeed(needMap, key);
assertEquals(HttpStatus.BAD_REQUEST, res.getStatusCode());
}
@@ -72,7 +79,7 @@ public class CupboardControllerTest {
entry("maxGoal", 100.0),
entry("type", "MONETARY"));
- var res = cupboardController.createNeed(needMap);
+ var res = cupboardController.createNeed(needMap, key);
assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, res.getStatusCode());
}
@@ -174,7 +181,7 @@ public class CupboardControllerTest {
var need = new Need("Name", 1, 100, Need.GoalType.MONETARY);
when(mockCupboardService.updateNeed(need, 1)).thenReturn(need);
- var res = cupboardController.updateNeed(need, 1);
+ var res = cupboardController.updateNeed(need, 1, key);
assertEquals(HttpStatus.OK, res.getStatusCode());
assertEquals(need, res.getBody());
@@ -185,7 +192,7 @@ public class CupboardControllerTest {
var need = new Need("Name", 1, 100, Need.GoalType.MONETARY);
when(mockCupboardService.updateNeed(need, 1)).thenThrow(new IOException());
- var res = cupboardController.updateNeed(need, 1);
+ var res = cupboardController.updateNeed(need, 1, key);
assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, res.getStatusCode());
}
@@ -196,7 +203,7 @@ public class CupboardControllerTest {
when(mockCupboardService.getNeed(1)).thenReturn(need);
when(mockCupboardService.deleteNeed(1)).thenReturn(true);
- var res = cupboardController.deleteNeed(1);
+ var res = cupboardController.deleteNeed(1, key);
assertEquals(HttpStatus.OK, res.getStatusCode());
}
@@ -206,7 +213,7 @@ public class CupboardControllerTest {
when(mockCupboardService.getNeed(1)).thenReturn(null);
when(mockCupboardService.deleteNeed(1)).thenReturn(false);
- var res = cupboardController.deleteNeed(1);
+ var res = cupboardController.deleteNeed(1, key);
assertEquals(HttpStatus.NOT_FOUND, res.getStatusCode());
}
@@ -217,7 +224,7 @@ public class CupboardControllerTest {
when(mockCupboardService.getNeed(1)).thenReturn(need);
when(mockCupboardService.deleteNeed(1)).thenThrow(new IOException());
- var res = cupboardController.deleteNeed(1);
+ var res = cupboardController.deleteNeed(1, key);
assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, res.getStatusCode());
}
diff --git a/ufund-api/src/test/java/com/ufund/api/ufundapi/controller/UserControllerTest.java b/ufund-api/src/test/java/com/ufund/api/ufundapi/controller/UserControllerTest.java
index cc7df40..06fb6cd 100644
--- a/ufund-api/src/test/java/com/ufund/api/ufundapi/controller/UserControllerTest.java
+++ b/ufund-api/src/test/java/com/ufund/api/ufundapi/controller/UserControllerTest.java
@@ -82,7 +82,7 @@ public class UserControllerTest {
String key = UserAuth.generate(username).getKey();
// When getUser is called on the Mock User service, throw an IOException
// doThrow(new IllegalAccessException()).when(mockUserService).getUser(username);
- doThrow(new IllegalAccessException()).when(mockAuthService).authenticate(username, key);
+ doThrow(new IllegalAccessException()).when(mockAuthService).keyHasAccessToUser(username, key);
// Invoke
ResponseEntity<User> response = userController.getUser(username, key);
@@ -237,7 +237,7 @@ public class UserControllerTest {
String key = UserAuth.generate(username).getKey();
// When updateUser is called on the Mock User service, throw a Invalid Parameter exception
// exception
- doThrow(new IllegalAccessException()).when(mockAuthService).authenticate(username, key);
+ doThrow(new IllegalAccessException()).when(mockAuthService).keyHasAccessToUser(username, key);
// Invoke
@@ -298,7 +298,7 @@ public class UserControllerTest {
String username = "Test";
String key = UserAuth.generate(username).getKey();
// When deleteUser is called on the Mock User service, throw an IOException
- doThrow(new IllegalAccessException()).when(mockAuthService).authenticate(username, key);
+ doThrow(new IllegalAccessException()).when(mockAuthService).keyHasAccessToUser(username, key);
// Invoke
ResponseEntity<Boolean> response = userController.deleteUser(username, key);
diff --git a/ufund-api/src/test/java/com/ufund/api/ufundapi/persistence/UserAuthFileDAOTest.java b/ufund-api/src/test/java/com/ufund/api/ufundapi/persistence/UserAuthFileDAOTest.java
index 5e92deb..a4842c5 100644
--- a/ufund-api/src/test/java/com/ufund/api/ufundapi/persistence/UserAuthFileDAOTest.java
+++ b/ufund-api/src/test/java/com/ufund/api/ufundapi/persistence/UserAuthFileDAOTest.java
@@ -43,7 +43,7 @@ public class UserAuthFileDAOTest {
String key = "123";
UserAuth auth = userAuthFIleDAO.getUserAuth(key);
- assertEquals(auth, userAuths[0]);
+ assertEquals(userAuths[0], auth);
}
@Test
diff --git a/ufund-api/src/test/java/com/ufund/api/ufundapi/service/AuthServiceTest.java b/ufund-api/src/test/java/com/ufund/api/ufundapi/service/AuthServiceTest.java
index d3085e5..4f58b12 100644
--- a/ufund-api/src/test/java/com/ufund/api/ufundapi/service/AuthServiceTest.java
+++ b/ufund-api/src/test/java/com/ufund/api/ufundapi/service/AuthServiceTest.java
@@ -40,34 +40,34 @@ public class AuthServiceTest {
}
@Test
- public void testAuthenticate() throws IOException {
+ public void testKeyIsValid() throws IOException {
// Mock
when(mockAuthDAO.getUserAuth(key)).thenReturn(new UserAuth(key, username, null));
when(mockUserService.getUser(username)).thenReturn(user);
// Analyze
- assertDoesNotThrow(() -> authService.authenticate(username, key));
+ assertDoesNotThrow(() -> authService.keyHasAccessToUser(username, key));
}
@Test
- public void testAuthenticateMismatchName() throws IOException {
+ public void testKeyIsValidMismatchName() throws IOException {
// Mock
when(mockAuthDAO.getUserAuth(key)).thenReturn(new UserAuth(key, "EvilFish", null));
when(mockUserService.getUser("EvilFish")).thenReturn(user);
// Analyze
- assertThrows(IllegalAccessException.class, () -> authService.authenticate(username, key));
+ assertThrows(IllegalAccessException.class, () -> authService.keyHasAccessToUser(username, key));
}
@Test
- public void testAuthenticateMissingUserAuth() throws IOException {
+ public void testKeyIsValidMissingUserAuth() throws IOException {
// Mock
when(mockAuthDAO.getUserAuth(key)).thenReturn(null);
// Analyze
- assertThrows(IllegalAccessException.class, () -> authService.authenticate(username, key));
+ assertThrows(IllegalAccessException.class, () -> authService.keyHasAccessToUser(username, key));
}
diff --git a/ufund-ui/src/app/app.component.ts b/ufund-ui/src/app/app.component.ts
index 7dc8ffb..86717c4 100644
--- a/ufund-ui/src/app/app.component.ts
+++ b/ufund-ui/src/app/app.component.ts
@@ -1,7 +1,7 @@
import {Component, OnInit, Inject} from '@angular/core';
-import {UsersService} from './services/users.service';
import {BehaviorSubject} from 'rxjs';
import { DOCUMENT } from '@angular/common';
+import {AuthService} from './services/auth.service';
@Component({
selector: 'app-root',
@@ -14,16 +14,16 @@ export class AppComponent implements OnInit {
currentUser$: BehaviorSubject<string> = new BehaviorSubject<string>("Logged out.");
constructor(
- private userService: UsersService,
+ private authService: AuthService,
@Inject(DOCUMENT) private document: Document
) {}
reloadPage() {
this.document.defaultView?.location.reload();
- }
+ }
ngOnInit() {
- this.userService.getCurrentUserSubject().subscribe(r => {
+ this.authService.getCurrentUserSubject().subscribe(r => {
this.currentUser$?.next(r
? "Logged in as " + r.username
: "Logged out."
diff --git a/ufund-ui/src/app/components/cupboard/cupboard.component.ts b/ufund-ui/src/app/components/cupboard/cupboard.component.ts
index 24b3e2d..a812baf 100644
--- a/ufund-ui/src/app/components/cupboard/cupboard.component.ts
+++ b/ufund-ui/src/app/components/cupboard/cupboard.component.ts
@@ -1,10 +1,10 @@
import { Component, OnInit, ViewChild } from '@angular/core';
import { CupboardService } from '../../services/cupboard.service';
-import { UsersService } from '../../services/users.service';
import { Need, GoalType } from '../../models/Need';
import { userType } from '../../models/User';
import { BehaviorSubject, catchError, of } from 'rxjs';
import { NeedListComponent } from '../need-list/need-list.component';
+import {AuthService} from '../../services/auth.service';
@Component({
selector: 'app-cupboard',
@@ -20,7 +20,10 @@ export class CupboardComponent implements OnInit {
needs: any;
@ViewChild("needList") needList?: NeedListComponent
- constructor(private cupboardService: CupboardService, private usersService: UsersService) { }
+ constructor(
+ private cupboardService: CupboardService,
+ private authService: AuthService
+ ) {}
ngOnInit(): void {
this.cupboardService.getNeeds().subscribe(n => this.needs = n);
@@ -88,7 +91,7 @@ export class CupboardComponent implements OnInit {
}
isManager() {
- const type = this.usersService.getCurrentUser()?.type;
+ const type = this.authService.getCurrentUser()?.type;
return type === ("MANAGER" as unknown as userType);
}
@@ -105,7 +108,7 @@ export class CupboardComponent implements OnInit {
console.log("need:", need);
console.log(need.id, need, "need updated");
this.cupboardService.updateNeed(need.id, need)
- .pipe(catchError((ex, r) => {
+ .pipe(catchError((ex, _) => {
if (ex.status == 500) {
this.statusText.next("Fields cannot be blank");
} else if (ex.status == 400) {
@@ -140,7 +143,7 @@ export class CupboardComponent implements OnInit {
console.log("need:", need);
console.log("form submitted. creating need: ", need);
this.cupboardService.createNeed(need)
- .pipe(catchError((ex, r) => {
+ .pipe(catchError((ex, _) => {
if (ex.status == 500) {
this.statusText.next("Fields cannot be blank");
} else if (ex.status == 400) {
@@ -167,48 +170,3 @@ export class CupboardComponent implements OnInit {
}
}
-
-let friendlyHttpStatus: { [key: number]: string } = {
- 200: 'OK',
- 201: 'Created',
- 202: 'Accepted',
- 203: 'Non-Authoritative Information',
- 204: 'No Content',
- 205: 'Reset Content',
- 206: 'Partial Content',
- 300: 'Multiple Choices',
- 301: 'Moved Permanently',
- 302: 'Found',
- 303: 'See Other',
- 304: 'Not Modified',
- 305: 'Use Proxy',
- 306: 'Unused',
- 307: 'Temporary Redirect',
- 400: 'Bad Request',
- 401: 'Unauthorized',
- 402: 'Payment Required',
- 403: 'Forbidden',
- 404: 'Not Found',
- 405: 'Method Not Allowed',
- 406: 'Not Acceptable',
- 407: 'Proxy Authentication Required',
- 408: 'Request Timeout',
- 409: 'Conflict',
- 410: 'Gone',
- 411: 'Length Required',
- 412: 'Precondition Required',
- 413: 'Request Entry Too Large',
- 414: 'Request-URI Too Long',
- 415: 'Unsupported Media Type',
- 416: 'Requested Range Not Satisfiable',
- 417: 'Expectation Failed',
- 418: 'I\'m a teapot',
- 422: 'Unprocessable Entity',
- 429: 'Too Many Requests',
- 500: 'Internal Server Error',
- 501: 'Not Implemented',
- 502: 'Bad Gateway',
- 503: 'Service Unavailable',
- 504: 'Gateway Timeout',
- 505: 'HTTP Version Not Supported',
-};
diff --git a/ufund-ui/src/app/components/dashboard/dashboard.component.ts b/ufund-ui/src/app/components/dashboard/dashboard.component.ts
index b9faefa..a0ad566 100644
--- a/ufund-ui/src/app/components/dashboard/dashboard.component.ts
+++ b/ufund-ui/src/app/components/dashboard/dashboard.component.ts
@@ -1,21 +1,21 @@
-import { Component } from '@angular/core';
-import { UsersService } from '../../services/users.service';
-import { userType } from '../../models/User';
+import {Component} from '@angular/core';
+import {userType} from '../../models/User';
+import {AuthService} from '../../services/auth.service';
@Component({
- selector: 'app-dashboard',
- standalone: false,
- templateUrl: './dashboard.component.html',
- styleUrl: './dashboard.component.css'
+ selector: 'app-dashboard',
+ standalone: false,
+ templateUrl: './dashboard.component.html',
+ styleUrl: './dashboard.component.css'
})
export class DashboardComponent {
constructor(
- protected usersService: UsersService,
+ protected authService: AuthService,
) {}
isManager() {
- const type = this.usersService.getCurrentUser()?.type;
+ const type = this.authService.getCurrentUser()?.type;
return type === ("MANAGER" as unknown as userType);
- }
+ }
}
diff --git a/ufund-ui/src/app/components/funding-basket/funding-basket.component.ts b/ufund-ui/src/app/components/funding-basket/funding-basket.component.ts
index e654711..faa7e0b 100644
--- a/ufund-ui/src/app/components/funding-basket/funding-basket.component.ts
+++ b/ufund-ui/src/app/components/funding-basket/funding-basket.component.ts
@@ -1,11 +1,9 @@
import {Component, Input, OnInit, ViewChild} from '@angular/core';
-import {User} from '../../models/User';
-import { UsersService } from '../../services/users.service';
-import { Need } from '../../models/Need';
-import { NeedListComponent } from '../need-list/need-list.component';
-import { Router } from '@angular/router';
-import { CupboardService } from '../../services/cupboard.service';
-import { BehaviorSubject, catchError, firstValueFrom, Observable } from 'rxjs';
+import {UsersService} from '../../services/users.service';
+import {Router} from '@angular/router';
+import {CupboardService} from '../../services/cupboard.service';
+import {catchError, firstValueFrom, Observable} from 'rxjs';
+import {AuthService} from '../../services/auth.service';
@Component({
selector: 'app-funding-basket',
@@ -14,67 +12,67 @@ import { BehaviorSubject, catchError, firstValueFrom, Observable } from 'rxjs';
styleUrl: './funding-basket.component.css'
})
export class FundingBasketComponent implements OnInit {
- statusText: any;
+ statusText: any;
- constructor(
- private router: Router,
- protected cupboardService: CupboardService,
- protected usersService: UsersService
- ) {}
+ constructor(
+ private router: Router,
+ protected cupboardService: CupboardService,
+ protected usersService: UsersService,
+ private authService: AuthService
+ ) {}
- @ViewChild("contribution") contribution?: Input;
- @Input() isValid: boolean = true;
+ @ViewChild("contribution") contribution?: Input;
+ @Input() isValid: boolean = true;
- // this is for login rerouting
- ngOnInit(): void {
- if (!this.usersService.getCurrentUser()) {
- this.router.navigate(['/login'], {queryParams: {redir: this.router.url}});
- return;
- }
-
- this.usersService.refreshBasket();
- // this.usersService.removeNeed(); <- call this to remove
- }
+ // this is for login rerouting
+ ngOnInit(): void {
+ if (!this.authService.getCurrentUser()) {
+ this.router.navigate(['/login'], {queryParams: {redir: this.router.url}});
+ return;
+ }
- async checkout() {
- this.isValid = true;
- for (let c of document.getElementById("funding-basket")?.querySelectorAll('.contribution')!) {
- let contribution = c as HTMLInputElement;
- contribution.setAttribute("style","");
- if ( contribution.value == '' || contribution.valueAsNumber <= 0) {
- this.isValid = false;
- contribution.setAttribute("style","color: #ff0000");
- }
+ this.usersService.refreshBasket();
+ // this.usersService.removeNeed(); <- call this to remove
}
- if (this.isValid) {
- for (let c of document.getElementById("funding-basket")?.querySelectorAll('.contribution')!) {
- let contribution = c as HTMLInputElement;
- let need = await firstValueFrom(this.cupboardService.getNeed(+contribution.id));
- need.current +=+ contribution.value;
- this.usersService.removeNeed(+need.id);
- this.cupboardService.updateNeed(need.id, need)
- .pipe(catchError((ex, r) => {
- if (ex.status == 500) {
- this.statusText.next('Fields cannot be blank');
- } else if (ex.status == 400) {
- this.statusText.next('Goal must be greater than 0');
- } else {
- this.statusText.next('Error on creating need');
- }
- return new Observable<string>();
- }))
- .subscribe((result) => {
- if (result) {
- console.log('need updated successfully');
- //this.needList?.refresh()
- } else {
- console.log('need update failed');
- }
- });
- }
- }
- }
+ async checkout() {
+ this.isValid = true;
+ for (let c of document.getElementById("funding-basket")?.querySelectorAll('.contribution')!) {
+ let contribution = c as HTMLInputElement;
+ contribution.setAttribute("style", "");
+ if (contribution.value == '' || contribution.valueAsNumber <= 0) {
+ this.isValid = false;
+ contribution.setAttribute("style", "color: #ff0000");
+ }
+ }
+ if (this.isValid) {
+ for (let c of document.getElementById("funding-basket")?.querySelectorAll('.contribution')!) {
+ let contribution = c as HTMLInputElement;
+ let need = await firstValueFrom(this.cupboardService.getNeed(+contribution.id));
+ need.current += +contribution.value;
+ this.usersService.removeNeed(+need.id);
+ this.cupboardService.checkoutNeed(need.id, +contribution.value)
+ .pipe(catchError((ex, _) => {
+ if (ex.status == 500) {
+ this.statusText.next('Fields cannot be blank');
+ } else if (ex.status == 400) {
+ this.statusText.next('Goal must be greater than 0');
+ } else {
+ this.statusText.next('Error on creating need');
+ }
+ return new Observable<string>();
+ }))
+ .subscribe((result) => {
+ if (result) {
+ console.log('need updated successfully');
+ //this.needList?.refresh()
+ } else {
+ console.log('need update failed');
+ }
+ });
+ }
+ }
+ }
}
diff --git a/ufund-ui/src/app/components/home-page/home-page.component.ts b/ufund-ui/src/app/components/home-page/home-page.component.ts
index 5b2277c..95e8962 100644
--- a/ufund-ui/src/app/components/home-page/home-page.component.ts
+++ b/ufund-ui/src/app/components/home-page/home-page.component.ts
@@ -1,10 +1,10 @@
-import { Component } from '@angular/core';
+import {Component} from '@angular/core';
@Component({
- selector: 'app-home-page',
- standalone: false,
- templateUrl: './home-page.component.html',
- styleUrl: './home-page.component.css'
+ selector: 'app-home-page',
+ standalone: false,
+ templateUrl: './home-page.component.html',
+ styleUrl: './home-page.component.css'
})
export class HomePageComponent {
diff --git a/ufund-ui/src/app/components/login/login.component.ts b/ufund-ui/src/app/components/login/login.component.ts
index 9d806f5..f6a2996 100644
--- a/ufund-ui/src/app/components/login/login.component.ts
+++ b/ufund-ui/src/app/components/login/login.component.ts
@@ -2,12 +2,13 @@ import {Component, OnInit} from '@angular/core'
import {UsersService} from '../../services/users.service';
import {ActivatedRoute, Router} from '@angular/router';
import {BehaviorSubject} from 'rxjs';
+import {AuthService} from '../../services/auth.service';
@Component({
- selector: 'app-login',
- standalone: false,
- templateUrl: './login.component.html',
- styleUrl: './login.component.css'
+ selector: 'app-login',
+ standalone: false,
+ templateUrl: './login.component.html',
+ styleUrl: './login.component.css'
})
export class LoginComponent implements OnInit {
@@ -17,7 +18,8 @@ export class LoginComponent implements OnInit {
constructor(
protected usersService: UsersService,
protected router: Router,
- private route: ActivatedRoute
+ private route: ActivatedRoute,
+ private authService: AuthService
) {}
ngOnInit() {
@@ -31,7 +33,7 @@ export class LoginComponent implements OnInit {
return;
}
- this.usersService.login(username, password).then(() => {
+ this.authService.login(username, password).then(() => {
this.router.navigate([next]);
}).catch(ex => {
this.statusText.next("Unable to login: " + friendlyHttpStatus[ex.status])
diff --git a/ufund-ui/src/app/components/need-list/need-list.component.ts b/ufund-ui/src/app/components/need-list/need-list.component.ts
index 25f05d6..3a89a20 100644
--- a/ufund-ui/src/app/components/need-list/need-list.component.ts
+++ b/ufund-ui/src/app/components/need-list/need-list.component.ts
@@ -1,132 +1,138 @@
-import { Component } from '@angular/core';
+import {Component} from '@angular/core';
import {Need} from '../../models/Need';
import {CupboardService} from '../../services/cupboard.service';
-import { UsersService } from '../../services/users.service';
-import { userType } from '../../models/User';
+import {UsersService} from '../../services/users.service';
+import {userType} from '../../models/User';
+import {catchError, of} from 'rxjs';
+import {AuthService} from '../../services/auth.service';
+
@Component({
- selector: 'app-need-list',
- standalone: false,
- templateUrl: './need-list.component.html',
- styleUrl: './need-list.component.css'
+ selector: 'app-need-list',
+ standalone: false,
+ templateUrl: './need-list.component.html',
+ styleUrl: './need-list.component.css'
})
export class NeedListComponent {
- needs: Need[] = [];
- searchResults: Need[] = [];
+ needs: Need[] = [];
+ searchResults: Need[] = [];
- constructor(
- private cupboardService: CupboardService,
- private usersService: UsersService
- ) {}
+ constructor(
+ private cupboardService: CupboardService,
+ private usersService: UsersService,
+ private authService: AuthService
+ ) {}
refresh() {
this.cupboardService.getNeeds().subscribe(n => this.needs = n)
}
- ngOnInit(): void {
- this.refresh()
-
- this.close();
- }
+ ngOnInit(): void {
+ this.refresh()
- private showElement(element: any) {
- if (element){
- element.style.visibility = 'visible';
- element.style.position = 'relative';
+ this.close();
}
- }
- private hideElement(element: any) {
- if (element){
- element.style.visibility = 'hidden';
- element.style.position = 'absolute';
+ private showElement(element: any) {
+ if (element) {
+ element.style.visibility = 'visible';
+ element.style.position = 'relative';
+ }
}
- }
- private updateSearchStatus(text: string) {
- let element = document.getElementById('search-status');
- if (element) {
- element.innerHTML = text;
+ private hideElement(element: any) {
+ if (element) {
+ element.style.visibility = 'hidden';
+ element.style.position = 'absolute';
+ }
}
- }
- open() {
- this.hideElement(document.getElementById('search-button'));
- this.showElement(document.getElementById('search-form'));
- }
+ private updateSearchStatus(text: string) {
+ let element = document.getElementById('search-status');
+ if (element) {
+ element.innerHTML = text;
+ }
+ }
- close() {
- this.hideElement(document.getElementById('search-form'));
- this.showElement(document.getElementById('search-button'));
- this.hideElement(document.getElementById('search-status'));
- }
+ open() {
+ this.hideElement(document.getElementById('search-button'));
+ this.showElement(document.getElementById('search-form'));
+ }
- private searchDelay: any;
+ close() {
+ this.hideElement(document.getElementById('search-form'));
+ this.showElement(document.getElementById('search-button'));
+ this.hideElement(document.getElementById('search-status'));
+ }
- async search(form: any) {
- //wait .25 seconds before searching but cancel if another search is made during the wait to prevent too many api calls
+ private searchDelay: any;
- //remove previous search if it exists
- if (this.searchDelay) {
- clearTimeout(this.searchDelay);
- }
+ async search(form: any) {
+ //wait .25 seconds before searching but cancel if another search is made during the wait to prevent too many api calls
- this.searchDelay = setTimeout(() => {
- const currentSearchValue = form.search; //latest value of the search
- this.cupboardService.searchNeeds(currentSearchValue).subscribe((n) => {
- this.searchResults = n;
- console.log(currentSearchValue, this.searchResults);
- this.showElement(document.getElementById('search-results'));
- this.showElement(document.getElementById('search-status'));
- if (this.searchResults.length === this.needs.length) {
- this.updateSearchStatus("Please refine your search");
- this.searchResults = [];
- } else if (this.searchResults.length === 0) {
- this.updateSearchStatus("No results found");
- } else {
- this.updateSearchStatus("Search results:");
+ //remove previous search if it exists
+ if (this.searchDelay) {
+ clearTimeout(this.searchDelay);
}
- });
- }, 250);
- }
-
- delete(id : number) {
- this.cupboardService.deleteNeed(id).subscribe(() => {
- this.needs = this.needs.filter(n => n.id !== id)
- })
- }
-
- isManager() {
- const type = this.usersService.getCurrentUser()?.type;
- return type === ("MANAGER" as unknown as userType);
- }
-
- isHelper() {
- const type = this.usersService.getCurrentUser()?.type;
- return type === ("HELPER" as unknown as userType);
- }
-
- add(need: Need) {
- const currentUser = this.usersService.getCurrentUser();
- //console.log("get current user in angular:", currentUser)
- if (currentUser) {
- if (!currentUser.basket.includes(need.id)) {
- currentUser.basket.push(need.id);
- this.usersService.updateUser(currentUser).subscribe(() => {
- this.usersService.refreshBasket();
- error: (err: any) => {
- console.error(err);
- }
- });
- } else {
- window.alert("This need is already in your basket!")
- }
-
+ this.searchDelay = setTimeout(() => {
+ const currentSearchValue = form.search; //latest value of the search
+ this.cupboardService.searchNeeds(currentSearchValue).subscribe((n) => {
+ this.searchResults = n;
+ console.log(currentSearchValue, this.searchResults);
+ this.showElement(document.getElementById('search-results'));
+ this.showElement(document.getElementById('search-status'));
+ if (this.searchResults.length === this.needs.length) {
+ this.updateSearchStatus("Please refine your search");
+ this.searchResults = [];
+ } else if (this.searchResults.length === 0) {
+ this.updateSearchStatus("No results found");
+ } else {
+ this.updateSearchStatus("Search results:");
+ }
+ });
+ }, 250);
+ }
+
+ delete(id: number) {
+ this.cupboardService.deleteNeed(id).subscribe(() => {
+ this.needs = this.needs.filter(n => n.id !== id)
+ })
}
- }
+ isManager() {
+ const type = this.authService.getCurrentUser()?.type;
+ return type === ("MANAGER" as unknown as userType);
+ }
+
+ isHelper() {
+ const type = this.authService.getCurrentUser()?.type;
+ return type === ("HELPER" as unknown as userType);
+ }
+
+ add(need: Need) {
+ const currentUser = this.authService.getCurrentUser();
+ //console.log("get current user in angular:", currentUser)
+ if (currentUser) {
+ if (!currentUser.basket.includes(need.id)) {
+ currentUser.basket.push(need.id);
+ this.usersService.updateUser(currentUser)
+ .pipe(catchError((err: any, _) => {
+ console.error(err);
+ return of();
+ }))
+ .subscribe(() => {
+ this.usersService.refreshBasket();
+ });
+ } else {
+ window.alert("This need is already in your basket!")
+ }
+
- back() {
- this.searchResults = [];
- }
+ }
+
+ }
+
+ back() {
+ this.searchResults = [];
+ }
}
diff --git a/ufund-ui/src/app/components/need-page/need-page.component.ts b/ufund-ui/src/app/components/need-page/need-page.component.ts
index 597d0e0..e38554c 100644
--- a/ufund-ui/src/app/components/need-page/need-page.component.ts
+++ b/ufund-ui/src/app/components/need-page/need-page.component.ts
@@ -2,30 +2,30 @@ import {Component, Input} from '@angular/core';
import {GoalType, Need} from '../../models/Need';
import {ActivatedRoute} from "@angular/router";
import {CupboardService} from "../../services/cupboard.service";
-import { NgFor } from '@angular/common';
+import {NgFor} from '@angular/common';
@Component({
- selector: 'app-need-page',
- standalone: false,
- templateUrl: './need-page.component.html',
- styleUrl: './need-page.component.css'
+ selector: 'app-need-page',
+ standalone: false,
+ templateUrl: './need-page.component.html',
+ styleUrl: './need-page.component.css'
})
export class NeedPageComponent {
- constructor(
- private route: ActivatedRoute,
- private cupboardService: CupboardService,
- ) {}
+ constructor(
+ private route: ActivatedRoute,
+ private cupboardService: CupboardService,
+ ) {}
- public GoalType = GoalType;
+ public GoalType = GoalType;
- @Input() need?: Need;
+ @Input() need?: Need;
- ngOnInit(): void {
- const id = Number(this.route.snapshot.paramMap.get('id'));
- this.cupboardService.getNeed(id).subscribe(n => this.need = n);
- }
+ ngOnInit(): void {
+ const id = Number(this.route.snapshot.paramMap.get('id'));
+ this.cupboardService.getNeed(id).subscribe(n => this.need = n);
+ }
- back() {
- window.history.back();
- }
-} \ No newline at end of file
+ back() {
+ window.history.back();
+ }
+}
diff --git a/ufund-ui/src/app/models/Need.ts b/ufund-ui/src/app/models/Need.ts
index 9e97fd4..5cd4e39 100644
--- a/ufund-ui/src/app/models/Need.ts
+++ b/ufund-ui/src/app/models/Need.ts
@@ -1,13 +1,13 @@
export interface Need {
- name: string,
- id: number,
- filterAttributes: string[],
- type: GoalType;
- maxGoal: number;
- current: number;
+ name: string,
+ id: number,
+ filterAttributes: string[],
+ type: GoalType;
+ maxGoal: number;
+ current: number;
}
export enum GoalType {
- MONETARY,
- PHYSICAL
+ MONETARY,
+ PHYSICAL
}
diff --git a/ufund-ui/src/app/models/User.ts b/ufund-ui/src/app/models/User.ts
index f4396f6..e6848fa 100644
--- a/ufund-ui/src/app/models/User.ts
+++ b/ufund-ui/src/app/models/User.ts
@@ -1,5 +1,3 @@
-import {Need} from './Need';
-
export enum userType {
HELPER,
MANAGER
diff --git a/ufund-ui/src/app/services/auth.service.ts b/ufund-ui/src/app/services/auth.service.ts
new file mode 100644
index 0000000..6bc7145
--- /dev/null
+++ b/ufund-ui/src/app/services/auth.service.ts
@@ -0,0 +1,57 @@
+import {Injectable} from '@angular/core';
+import {BehaviorSubject, firstValueFrom} from 'rxjs';
+import {User} from '../models/User';
+import {HttpClient, HttpHeaders} from '@angular/common/http';
+
+@Injectable({
+ providedIn: 'root'
+})
+export class AuthService {
+
+ private authUrl = "http://localhost:8080/auth"
+ private userUrl = "http://localhost:8080/users"
+
+ private currentUser : BehaviorSubject<User | null> = new BehaviorSubject<User | null>(null);
+ private apiKey: string = "";
+
+ httpOptions2 = () => ({
+ headers: new HttpHeaders({
+ 'Content-Type': 'application/json',
+ "jelly-api-key": this.apiKey
+ }),
+ responseType: "text" as "json" // don't ask me how or why this works, bc i have no clue...
+ // see the relevant angular bug report https://github.com/angular/angular/issues/18586
+ });
+
+ constructor(
+ private http: HttpClient
+ ) {}
+
+ async login(username: string, password: string) {
+ let res = this.http.post<string>(this.authUrl, {username: username, password: password}, this.httpOptions2());
+ this.apiKey = await firstValueFrom(res);
+ console.log("apikey: "+this.apiKey)
+ let res2 = this.http.get<User>(`${this.userUrl}/${username}`, {
+ headers: new HttpHeaders({
+ 'Content-Type': 'application/json',
+ "jelly-api-key": this.apiKey
+ })
+ })
+ let currentU = await firstValueFrom(res2);
+ this.currentUser.next(currentU);
+ // this.currentUser.subscribe(r => console.log("currentUser: "+r.username))
+ }
+
+ getCurrentUserSubject() {
+ return this.currentUser;
+ }
+
+ getCurrentUser() {
+ return this.currentUser.getValue()
+ }
+
+ getApiKey() {
+ return this.apiKey;
+ }
+
+}
diff --git a/ufund-ui/src/app/services/cupboard.service.ts b/ufund-ui/src/app/services/cupboard.service.ts
index 9e14106..9232c0c 100644
--- a/ufund-ui/src/app/services/cupboard.service.ts
+++ b/ufund-ui/src/app/services/cupboard.service.ts
@@ -2,6 +2,7 @@ import {Injectable} from '@angular/core';
import {HttpClient, HttpHeaders} from '@angular/common/http';
import {Need} from '../models/Need';
import {Observable} from 'rxjs';
+import {AuthService} from './auth.service';
@Injectable({
providedIn: 'root'
@@ -9,35 +10,44 @@ import {Observable} from 'rxjs';
export class CupboardService {
private url = "http://localhost:8080/cupboard"
- private httpOptions = {
- headers: new HttpHeaders({'Content-Type': 'application/json'})
- };
+
+ httpOptions = () => ({
+ headers: new HttpHeaders({
+ 'Content-Type': 'application/json',
+ "jelly-api-key": this.authService.getApiKey()
+ })
+ });
constructor(
- private http: HttpClient
+ private http: HttpClient,
+ private authService: AuthService
) {}
createNeed(need: Need): Observable<boolean> {
- return this.http.post<boolean>(this.url, need, this.httpOptions)
+ return this.http.post<boolean>(this.url, need, this.httpOptions())
}
getNeeds(): Observable<Need[]> {
- return this.http.get<Need[]>(this.url, this.httpOptions)
+ return this.http.get<Need[]>(this.url, this.httpOptions())
}
searchNeeds(name: String): Observable<Need[]> {
- return this.http.get<Need[]>(`${this.url}/?name=${name}`, this.httpOptions)
+ return this.http.get<Need[]>(`${this.url}/?name=${name}`, this.httpOptions())
}
getNeed(id: number): Observable<Need> {
- return this.http.get<Need>(`${this.url}/${id}`, this.httpOptions)
+ return this.http.get<Need>(`${this.url}/${id}`, this.httpOptions())
}
updateNeed(id: number, data: Need): Observable<boolean> {
- return this.http.put<boolean>(`${this.url}/${id}`, data, this.httpOptions)
+ return this.http.put<boolean>(`${this.url}/${id}`, data, this.httpOptions())
}
deleteNeed(id: number): Observable<boolean> {
- return this.http.delete<boolean>(`${this.url}/${id}`, this.httpOptions)
+ return this.http.delete<boolean>(`${this.url}/${id}`, this.httpOptions())
+ }
+
+ checkoutNeed(id: number, quantity: number) {
+ return this.http.put(`${this.url}/checkout`, {needID: id, amount: quantity}, this.httpOptions())
}
}
diff --git a/ufund-ui/src/app/services/users.service.ts b/ufund-ui/src/app/services/users.service.ts
index 6671440..4080ebf 100644
--- a/ufund-ui/src/app/services/users.service.ts
+++ b/ufund-ui/src/app/services/users.service.ts
@@ -4,36 +4,27 @@ import {BehaviorSubject, catchError, firstValueFrom, Observable, of} from 'rxjs'
import {User} from '../models/User';
import { Need } from '../models/Need';
import { CupboardService } from './cupboard.service';
+import {AuthService} from './auth.service';
@Injectable({
providedIn: 'root'
})
export class UsersService {
- private currentUser : BehaviorSubject<User | null> = new BehaviorSubject<User | null>(null);
- private apiKey: string = "";
private basket = new BehaviorSubject<Need[]>([]);
-
private url = "http://localhost:8080/users"
- private authUrl = "http://localhost:8080/auth"
- private httpOptions = () => ({
+
+ httpOptions = () => ({
headers: new HttpHeaders({
'Content-Type': 'application/json',
- "jelly-api-key": this.apiKey
+ "jelly-api-key": this.authService.getApiKey()
})
});
- private httpOptions2 = () => ({
- headers: new HttpHeaders({
- 'Content-Type': 'application/json',
- "jelly-api-key": this.apiKey
- }),
- responseType: "text" as "json" // don't ask me how or why this works, bc i have no clue...
- // see the relevant angular bug report https://github.com/angular/angular/issues/18586
- });
constructor(
private http: HttpClient,
private cupboardService: CupboardService,
+ private authService: AuthService
) {}
async createUser(username:string, password:string) {
@@ -46,38 +37,15 @@ export class UsersService {
updateUser(user: User): Observable<User> {
console.log(`${this.url}/${user.username}`, user, this.httpOptions)
- return this.http.put<User>(`${this.url}/${user.username}`, user, this.httpOptions2()) // This line is causing issues as the key is not properly being passed
+ return this.http.put<User>(`${this.url}/${user.username}`, user, this.httpOptions())
}
deleteUser(id: number): Observable<boolean> {
return this.http.delete<boolean>(`${this.url}/${id}`, this.httpOptions())
}
- getCurrentUserSubject() {
- return this.currentUser;
- }
-
- getCurrentUser() {
- return this.currentUser.getValue()
- }
-
- async login(username: string, password: string) {
- let res = this.http.post<string>(this.authUrl, {username: username, password: password}, this.httpOptions2());
- this.apiKey = await firstValueFrom(res);
- console.log("apikey: "+this.apiKey)
- let res2 = this.http.get<User>(`${this.url}/${username}`, {
- headers: new HttpHeaders({
- 'Content-Type': 'application/json',
- "jelly-api-key": this.apiKey
- })
- })
- let currentU = await firstValueFrom(res2);
- this.currentUser.next(currentU);
- // this.currentUser.subscribe(r => console.log("currentUser: "+r.username))
- }
-
refreshBasket() {
- let promiseArr = this.getCurrentUser()!.basket.map(async needID => {
+ let promiseArr = this.authService.getCurrentUser()!.basket.map(async needID => {
return await firstValueFrom(this.cupboardService.getNeed(needID));
})
Promise.all(promiseArr).then(r => this.basket.next(r));
@@ -86,10 +54,10 @@ export class UsersService {
removeNeed(id: number) {
let newArr = this.basket.getValue().filter(v => v.id != id);
this.basket.next(newArr);
- this.getCurrentUser()!.basket = newArr.map(need => need.id);
- this.updateUser(this.getCurrentUser()!)
+ this.authService.getCurrentUser()!.basket = newArr.map(need => need.id);
+ this.updateUser(this.authService.getCurrentUser()!)
.pipe(
- catchError((err: any, ob) => {
+ catchError((err: any, _) => {
console.error(err);
return of();
})