diff --git a/client/src/App.tsx b/client/src/App.tsx index f1b35da..65890b9 100644 --- a/client/src/App.tsx +++ b/client/src/App.tsx @@ -13,6 +13,7 @@ import { Home } from "./Home"; import { loginAction, signupAction } from "./actions"; import { homeLoader } from "./loaders"; import { isError } from "./api/dto"; +import { Feed } from "./Feed"; const router = createBrowserRouter([ { @@ -39,6 +40,7 @@ const router = createBrowserRouter([ return ret; }, element: , + children: [{ path: "feed", element: }], }, { path: "/login", diff --git a/client/src/Feed.tsx b/client/src/Feed.tsx new file mode 100644 index 0000000..8f78735 --- /dev/null +++ b/client/src/Feed.tsx @@ -0,0 +1,3 @@ +export function Feed() { + return feed; +} diff --git a/client/src/Login.tsx b/client/src/Login.tsx index 89dae46..3288bc8 100644 --- a/client/src/Login.tsx +++ b/client/src/Login.tsx @@ -9,7 +9,7 @@ export function Login() { | undefined; if (data && !isError(data)) { - return
Success, now log in!;
; + return
Login success
; } let errors: JSX.Element[] = []; diff --git a/client/src/Signup.tsx b/client/src/Signup.tsx index b88497b..6e1a2df 100644 --- a/client/src/Signup.tsx +++ b/client/src/Signup.tsx @@ -9,7 +9,7 @@ export function Signup() { | undefined; if (data && !isError(data)) { - return
Success, now log in!;
; + return
Signup success
; } let errors: JSX.Element[] = []; diff --git a/client/src/actions.ts b/client/src/actions.ts index ece4b3c..8181c97 100644 --- a/client/src/actions.ts +++ b/client/src/actions.ts @@ -11,7 +11,7 @@ export async function loginAction({ request }: ActionFunctionArgs) { formData.get("password")!.toString(), ); - if (!isError(ret)) { + if (ret && !isError(ret)) { setToken(ret.token); return redirect("/home"); } @@ -21,9 +21,26 @@ export async function loginAction({ request }: ActionFunctionArgs) { export async function signupAction({ request }: ActionFunctionArgs) { const formData = await request.formData(); - return await signup( + const s = await signup( formData.get("username")!.toString(), formData.get("fullName")!.toString(), formData.get("password")!.toString(), ); + + if (!s || isError(s)) { + return s; + } + + // Login if everything's OK + const ret = await login( + formData.get("username")!.toString(), + formData.get("password")!.toString(), + ); + + if (ret && !isError(ret)) { + setToken(ret.token); + return redirect("/home"); + } + + return ret; } diff --git a/server/src/main/java/com/usatiuk/tjv/y/server/controller/ApiExceptionHandler.java b/server/src/main/java/com/usatiuk/tjv/y/server/controller/ApiExceptionHandler.java index 0669041..69b68f7 100644 --- a/server/src/main/java/com/usatiuk/tjv/y/server/controller/ApiExceptionHandler.java +++ b/server/src/main/java/com/usatiuk/tjv/y/server/controller/ApiExceptionHandler.java @@ -6,11 +6,16 @@ import jakarta.validation.ConstraintViolationException; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; +import org.springframework.security.core.AuthenticationException; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.context.request.WebRequest; +import org.springframework.web.server.ResponseStatusException; import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler; +import java.util.List; +import java.util.Objects; + @ControllerAdvice public class ApiExceptionHandler extends ResponseEntityExceptionHandler { @ExceptionHandler(value = {ConstraintViolationException.class}) @@ -19,4 +24,25 @@ public class ApiExceptionHandler extends ResponseEntityExceptionHandler { new ErrorTo(ex.getConstraintViolations().stream().map(ConstraintViolation::getMessage), HttpStatus.BAD_REQUEST.value()), new HttpHeaders(), HttpStatus.BAD_REQUEST, request); } + + @ExceptionHandler(value = {AuthenticationException.class}) + protected ResponseEntity handleAuthenticationException(AuthenticationException ex, WebRequest request) { + return handleExceptionInternal(ex, + new ErrorTo(List.of(ex.getMessage()), HttpStatus.UNAUTHORIZED.value()), + new HttpHeaders(), HttpStatus.UNAUTHORIZED, request); + } + + @ExceptionHandler(value = {ResponseStatusException.class}) + protected ResponseEntity handleResponseStatusException(ResponseStatusException ex, WebRequest request) { + return handleExceptionInternal(ex, + new ErrorTo(List.of(Objects.requireNonNullElse(ex.getReason(), ex.getStatusCode().toString())), ex.getStatusCode().value()), + new HttpHeaders(), ex.getStatusCode(), request); + } + + @ExceptionHandler(value = {Exception.class}) + protected ResponseEntity handleGenericException(Exception ex, WebRequest request) { + return handleExceptionInternal(ex, + new ErrorTo(List.of("Error"), HttpStatus.INTERNAL_SERVER_ERROR.value()), + new HttpHeaders(), HttpStatus.INTERNAL_SERVER_ERROR, request); + } } diff --git a/server/src/main/java/com/usatiuk/tjv/y/server/controller/TokenController.java b/server/src/main/java/com/usatiuk/tjv/y/server/controller/TokenController.java index 309ba9c..69e677e 100644 --- a/server/src/main/java/com/usatiuk/tjv/y/server/controller/TokenController.java +++ b/server/src/main/java/com/usatiuk/tjv/y/server/controller/TokenController.java @@ -28,7 +28,7 @@ public class TokenController { public TokenResponseTo request(@RequestBody TokenRequestTo tokenRequestTo) throws UserNotFoundException { Optional found = personService.login(tokenRequestTo.username(), tokenRequestTo.password()); - if (found.isEmpty()) throw new ResponseStatusException(HttpStatus.NOT_FOUND); + if (found.isEmpty()) throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Couldn't find user"); return new TokenResponseTo(tokenService.generateToken(found.get().getId())); }