diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 49c1c2b..42ec23b 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -8,7 +8,31 @@ concurrency: cancel-in-progress: true jobs: + # JOB to run change detection + changes: + name: Check changes + runs-on: ubuntu-latest + # Required permissions + permissions: + pull-requests: read + # Set job outputs to values from filter step + outputs: + server: ${{ steps.filter.outputs.server }} + client: ${{ steps.filter.outputs.client }} + steps: + # For pull requests it's not necessary to checkout the code + - uses: dorny/paths-filter@v3 + id: filter + with: + filters: | + server: + - 'server/**' + client: + - 'client/**' + client-code-checks: + needs: changes + if: ${{ needs.changes.outputs.client == 'true' }} name: Client Code Checks runs-on: ubuntu-latest steps: @@ -45,8 +69,7 @@ jobs: client-docker-build: name: Build Client Docker image runs-on: ubuntu-latest - needs: - - client-code-checks + needs: client-code-checks steps: - uses: actions/checkout@v4 - uses: docker/setup-buildx-action@v3 @@ -70,6 +93,8 @@ jobs: cache-to: type=gha,mode=max java-code-checks: + needs: changes + if: ${{ needs.changes.outputs.server == 'true' }} name: Server Code Checks runs-on: ubuntu-latest steps: @@ -105,8 +130,7 @@ jobs: java-docker-build: name: Build Java Docker image runs-on: ubuntu-latest - needs: - - java-code-checks + needs: java-code-checks steps: - uses: actions/checkout@v4 - uses: docker/setup-buildx-action@v3 diff --git a/server/src/main/java/br/com/tasknoteapp/server/config/CorsConfig.java b/server/src/main/java/br/com/tasknoteapp/server/config/CorsConfig.java index e100fae..56012b1 100644 --- a/server/src/main/java/br/com/tasknoteapp/server/config/CorsConfig.java +++ b/server/src/main/java/br/com/tasknoteapp/server/config/CorsConfig.java @@ -18,7 +18,7 @@ public class CorsConfig implements WebMvcConfigurer { /** * Add CORS mappings configuration. - * + * * @param registry CorsRegistry instance. */ public void addCorsMappings(@NonNull CorsRegistry registry) { @@ -29,7 +29,14 @@ public class CorsConfig implements WebMvcConfigurer { .addMapping("/**") .allowedOrigins(allowedOrigins) .allowCredentials(true) - .allowedHeaders("X-XSRF-TOKEN", "Content-Type", "Accept", "Authorization", "X-Frame-Options", "X-XSS-Protection", "Content-Security-Policy") + .allowedHeaders( + "X-XSRF-TOKEN", + "Content-Type", + "Accept", + "Authorization", + "X-Frame-Options", + "X-XSS-Protection", + "Content-Security-Policy") .allowedMethods("GET", "PUT", "POST", "DELETE", "OPTIONS", "HEAD", "PATCH"); } } diff --git a/server/src/main/java/br/com/tasknoteapp/server/config/SecurityConfig.java b/server/src/main/java/br/com/tasknoteapp/server/config/SecurityConfig.java index aec11c1..a5a62a9 100644 --- a/server/src/main/java/br/com/tasknoteapp/server/config/SecurityConfig.java +++ b/server/src/main/java/br/com/tasknoteapp/server/config/SecurityConfig.java @@ -18,8 +18,6 @@ import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; -import org.springframework.security.web.csrf.CookieCsrfTokenRepository; -import org.springframework.security.web.csrf.CsrfTokenRequestAttributeHandler; /** This class contains security configurations. */ @Configuration @@ -41,12 +39,7 @@ public class SecurityConfig { @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http.cors(Customizer.withDefaults()) - .csrf( - custom -> - custom - .ignoringRequestMatchers("/auth/**") - .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()) - .csrfTokenRequestHandler(new CsrfTokenRequestAttributeHandler())) + .csrf(AbstractHttpConfigurer::disable) .authorizeHttpRequests( request -> request diff --git a/server/src/main/resources/application.properties b/server/src/main/resources/application.properties index 235d942..a7fc5b1 100644 --- a/server/src/main/resources/application.properties +++ b/server/src/main/resources/application.properties @@ -1,6 +1,7 @@ spring.application.name=tasknote-api server.port = 8585 server.error.include-message=always +server.servlet.context-path=${SERVER_SERVLET_CONTEXT_PATH:/server} logging.level.br.com.tasknoteapp.server = DEBUG logging.level.org.springframework.security = DEBUG diff --git a/tools.md b/tools.md deleted file mode 100644 index eebd080..0000000 --- a/tools.md +++ /dev/null @@ -1,90 +0,0 @@ -# Tools - -- **TaskNote:** https://tasknote.local -- **GitHub Container Registry:** https://ghcr.io/ -- **Time tracking:** https://track.toggl.com/timer - -# Building locally - -Build with Docker: - -```sh -docker build --build-arg BUILD=nightly -t tasknote:nightly . -``` - -Run with Docker: -```sh -docker run -it --rm \ - --name tasknote \ - tasknote:nightly -``` -Build and run with Docker Compose: -```sh -docker compose --profile caddy up --build -``` - -# Interact with GitHub Package - -Login in: - -``` -export CR_PAT=YOUR_TOKEN -echo $CR_PAT | docker login ghcr.io -u RMCampos --password-stdin -``` - -Pull image: - -```sh -docker pull ghcr.io/ricardo-campos-org/react-typescript-todolist/client:50 -``` - -Run it: - -- Client -```sh -docker run -d --rm \ - -p 80:5000 \ - -e VITE_BUILD="client:50" \ - -e VITE_BACKEND_SERVER="http://localhost:8585" \ - --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 server \ - ghcr.io/ricardo-campos-org/react-typescript-todolist/server: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 diff --git a/tools/tools.md b/tools/tools.md new file mode 100644 index 0000000..edeb185 --- /dev/null +++ b/tools/tools.md @@ -0,0 +1,110 @@ +# Tools + +All kind of tools and useful links and commands can be found here! + +## Links + +- **GitHub Container Registry:** https://ghcr.io/ +- **Time tracking:** https://track.toggl.com/timer + +## Building locally + +**Client - Frontend Web App:** + +Before building, you need define some env vars: + +```bash +export VERSION= +``` + +Then you can call the install and build scripts (from the `client` folder): + +```bash +npm ci --ignore-scripts --no-update-notifier --omit=dev \ + && npm run build \ + && rm -rf node_modules +``` + +That's it! + +**Server - Backend REST API:** + +For the backend there's a Dockerfile ready, just run (from the project root): + +```bash +docker build -t server ./server +``` + +That's it! + +## Deploying manually + +1. Connect into the server via SSH +2. Run deploy scripts + +Here are a few steps: + +```bash +export SERVER_IP= +export SERVER_ADDRRESS= + +npm ci --ignore-scripts --no-update-notifier --omit=dev +export VITE_BACKEND_SERVER=$SERVER_ADDRRESS/server +npm run build +zip -r "client_$VERSION.zip" dist/ +scp "client_$VERSION.zip" root@$SERVER_IP:/root/ +``` + +## Runing with Docker + +**DB:** + +```bash +docker run -d --rm \ + --name db \ + --network=host \ + -e POSTGRES_DB=$POSTGRES_DB \ + -e POSTGRES_USER=$POSTGRES_USER \ + -e POSTGRES_PASSWORD=$POSTGRES_PASSWORD \ + -e PGDATA=/tmp \ + -v ./data:/tmp \ + postgres:15.8-bookworm +``` + +**Server:** + +```bash +docker run -d --rm \ + --name server \ + --network=host \ + -e POSTGRES_DB=$POSTGRES_DB \ + -e POSTGRES_USER=$POSTGRES_USER \ + -e POSTGRES_PASSWORD=$POSTGRES_PASSWORD \ + -e POSTGRES_PORT=$POSTGRES_PORT \ + -e POSTGRES_HOST=$POSTGRES_HOST \ + -e CORS_ALLOWED_ORIGINS=$CORS_ALLOWED_ORIGINS \ + ghcr.io/ricardo-campos-org/react-typescript-todolist/server: +``` + +**Client:** + +The frontend app will run on Nginx. + +## Interacting with GitHub Package and Container Registry + +**Login in:** + +``` +export CR_PAT=YOUR_TOKEN +echo $CR_PAT | docker login ghcr.io -u RMCampos --password-stdin +``` + +**Pulling images:** + +```sh +docker pull ghcr.io/ricardo-campos-org/react-typescript-todolist/client:50 +docker pull ghcr.io/ricardo-campos-org/react-typescript-todolist/server:50 +``` + +- Get container IP +docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' db