Merge pull request #86 from ricardo-campos-org/fix/backend-digitalocean
feat: enable security on backend for digitalocean
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
+110
@@ -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=<branch-name-and-PR-number>
|
||||
```
|
||||
|
||||
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:<PR-Number>
|
||||
```
|
||||
|
||||
**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
|
||||
Reference in New Issue
Block a user