diff --git a/client/Caddyfile b/client/Caddyfile index ba30628..a4cf994 100644 --- a/client/Caddyfile +++ b/client/Caddyfile @@ -25,7 +25,7 @@ Strict-Transport-Security "max-age=31536000" Content-Security-Policy " base-uri 'self'; - connect-src 'self'; + connect-src 'self' {$VITE_BACKEND_SERVER}; default-src 'self'; font-src https://cdn.jsdelivr.net/npm/ 'self'; frame-src 'self'; @@ -42,7 +42,7 @@ handle /env.js { header Content-Type "text/javascript" - respond `window.config = {"BUILD":"{$BUILD}"};` + respond `window.config = {"VITE_BUILD":"{$VITE_BUILD}","VITE_BACKEND_SERVER":"{$VITE_BACKEND_SERVER}"};` } file_server diff --git a/client/src/api-service/apiConfig.ts b/client/src/api-service/apiConfig.ts index fd448ab..7da8b86 100644 --- a/client/src/api-service/apiConfig.ts +++ b/client/src/api-service/apiConfig.ts @@ -4,9 +4,9 @@ const server = env.VITE_BACKEND_SERVER; const ApiConfig = { - signInUrl: `${server}/auth/signin`, + signInUrl: `${server}/auth/sign-in`, - registerUrl: `${server}/auth/signup`, + registerUrl: `${server}/auth/sign-up`, refreshTokenUrl: `${server}/rest/user-sessions/refresh`, diff --git a/client/src/api-service/authService.ts b/client/src/api-service/authService.ts index c62612e..25edb8b 100644 --- a/client/src/api-service/authService.ts +++ b/client/src/api-service/authService.ts @@ -35,6 +35,8 @@ async function registerUser(email: string, password: string): Promise = ({ children }: Pro return bearerToken; } catch (e) { if (e instanceof Error) { - if (e.message !== 'No saved token!') { + if (e.message !== 'No saved token!' && e.message !== 'Forbidden! Access denied') { console.warn(e.message); } } else if (e) { @@ -82,7 +82,10 @@ const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ children }: Pro updateUserSession(currentUser, registerResponse.token); return Promise.resolve('OK'); } catch (e) { - return Promise.reject(e); + if (e instanceof Error) { + return Promise.reject(new Error(e.message)); + } + return Promise.reject(new Error('Unknown error!')); } }; diff --git a/java-api/src/main/java/br/com/tasknoteapp/java_api/config/SecurityConfig.java b/java-api/src/main/java/br/com/tasknoteapp/java_api/config/SecurityConfig.java index 1b410e5..ff20a36 100644 --- a/java-api/src/main/java/br/com/tasknoteapp/java_api/config/SecurityConfig.java +++ b/java-api/src/main/java/br/com/tasknoteapp/java_api/config/SecurityConfig.java @@ -40,7 +40,7 @@ public class SecurityConfig { @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http.cors(Customizer.withDefaults()) - .csrf(Customizer.withDefaults()) + .csrf(custom -> custom.ignoringRequestMatchers("/auth/**")) .authorizeHttpRequests( request -> request diff --git a/java-api/src/main/java/br/com/tasknoteapp/java_api/service/impl/JwtServiceImpl.java b/java-api/src/main/java/br/com/tasknoteapp/java_api/service/impl/JwtServiceImpl.java index f85c8bb..62d9d95 100644 --- a/java-api/src/main/java/br/com/tasknoteapp/java_api/service/impl/JwtServiceImpl.java +++ b/java-api/src/main/java/br/com/tasknoteapp/java_api/service/impl/JwtServiceImpl.java @@ -3,10 +3,13 @@ package br.com.tasknoteapp.java_api.service.impl; import br.com.tasknoteapp.java_api.service.JwtService; import io.jsonwebtoken.Claims; import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.MalformedJwtException; import java.time.LocalDateTime; import java.util.Date; import java.util.HashMap; import java.util.Map; +import java.util.Objects; +import java.util.Optional; import java.util.function.Function; import javax.crypto.SecretKey; import org.springframework.security.core.userdetails.UserDetails; @@ -29,7 +32,10 @@ class JwtServiceImpl implements JwtService { @Override public LocalDateTime extractExpiration(String token) { Date date = extractClaim(token, Claims::getExpiration); - return date.toInstant().atZone(java.time.ZoneId.systemDefault()).toLocalDateTime(); + if (!Objects.isNull(date)) { + return date.toInstant().atZone(java.time.ZoneId.systemDefault()).toLocalDateTime(); + } + return null; } @Override @@ -51,21 +57,33 @@ class JwtServiceImpl implements JwtService { @Override public boolean isTokenExpired(String token) { - return extractExpiration(token).isBefore(LocalDateTime.now()); + LocalDateTime expiration = extractExpiration(token); + if (expiration != null) { + return expiration.isBefore(LocalDateTime.now()); + } + return true; } @Override public boolean validateTokenAndUser(String token, UserDetails user) { final String email = user.getUsername(); - return !isTokenExpired(token) && getEmailFromToken(token).equals(email); + return !isTokenExpired(token) && email.equals(getEmailFromToken(token)); } private T extractClaim(String token, Function claimsResolver) { - final Claims claims = extractAllClaims(token); - return claimsResolver.apply(claims); + final Optional claims = extractAllClaims(token); + if (claims.isPresent()) { + return claimsResolver.apply(claims.get()); + } + return null; } - private Claims extractAllClaims(String token) { - return Jwts.parser().verifyWith(KEY).build().parseSignedClaims(token).getPayload(); + private Optional extractAllClaims(String token) { + try { + return Optional.of( + Jwts.parser().verifyWith(KEY).build().parseSignedClaims(token).getPayload()); + } catch (MalformedJwtException me) { + return Optional.empty(); + } } } diff --git a/tools.md b/tools.md index cb0a68e..c7c4d4a 100644 --- a/tools.md +++ b/tools.md @@ -40,6 +40,7 @@ docker pull ghcr.io/ricardo-campos-org/react-typescript-todolist/client:50 Run it: +- Client ```sh docker run -d --rm \ -p 80:5000 \ @@ -48,3 +49,42 @@ docker run -d --rm \ --name tasknote \ ghcr.io/ricardo-campos-org/react-typescript-todolist/client:50 ``` + +- Java API +```sh +docker run -d --rm \ + -p 8585:8585 \ + -e CORS_ALLOWED_ORIGINS="http://localhost:5000" \ + -e POSTGRES_DB=tasknote \ + -e POSTGRES_HOST=localhost \ + -e POSTGRES_USER=tasknoteuser \ + -e POSTGRES_PASSWORD=default \ + -e POSTGRES_PORT=5435 \ + --name java-api \ + ghcr.io/ricardo-campos-org/react-typescript-todolist/java-api:50 +``` +or +```sh +docker compose --file docker-compose.prod.yml up -d server +``` + +- DB +```sh +docker run -d --rm \ + -p 5435:5432 \ + -e POSTGRES_DB="tasknote" \ + -e POSTGRES_USER="tasknoteuser" \ + -e POSTGRES_PASSWORD="default" \ + -e POSTGRES_PORT=5435 \ + -e PGDATA=/tmp \ + -v "./data:/tmp" \ + --name db \ + postgres:15.8-bookworm +``` +or +```sh +docker compose --file docker-compose.prod.yml up -d db +``` + +- Get container IP +docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' db \ No newline at end of file