3 Commits

19 changed files with 516 additions and 115 deletions

35
.dockerignore Normal file
View File

@@ -0,0 +1,35 @@
# Exclude build output and IDE files to reduce Docker build context size
target
**/target
# Git and local metadata
.git
.gitignore
.DS_Store
# Local editor / IDE
.idea
.vscode
*.iml
*.sublime-*
# Build artifacts and temporary files
*.class
*.log
tmp/
build/
# Swap / editor backups
*.swp
# Internal Docker
.dockerignore
docker/
# Project specific ignores
README.md
LICENSE
# CI Files
.github/
.k8s/

165
.github/workflows/deploy.yml vendored Normal file
View File

@@ -0,0 +1,165 @@
name: ci
on:
push:
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up JDK 17
uses: actions/setup-java@v3
with:
java-version: '17'
distribution: 'temurin'
cache: maven
- name: Build with Maven
run: ./mvnw clean package -DskipTests
run-tests:
runs-on: ubuntu-latest
needs: [ build ]
steps:
- uses: actions/checkout@v3
- name: Set up JDK 17
uses: actions/setup-java@v3
with:
java-version: '17'
distribution: 'temurin'
cache: maven
- name: Running Tests with Maven
run: ./mvnw test
docker:
needs: [ build, run-tests ]
if: github.ref_name == 'main' || github.ref_name == 'develop'
runs-on: ubuntu-latest
permissions:
contents: read
packages: write # required to push to ghcr.io
id-token: write # optional for OIDC if you use it
steps:
- uses: actions/checkout@v3
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to GHCR
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Prepare image tags
run: |
OWNER=$(echo "${GITHUB_REPOSITORY_OWNER}" | tr '[:upper:]' '[:lower:]')
REPO=$(echo "${GITHUB_REPOSITORY#*/}" | tr '[:upper:]' '[:lower:]')
# Determine tag
if [ "${GITHUB_REF_NAME}" = "main" ]; then
TAG="latest"
else
TAG="dev"
fi
SHORT_SHA=$(echo "${GITHUB_SHA}" | cut -c1-7)
IMAGE_BASE="ghcr.io/${OWNER}/${REPO}"
echo "IMAGE_LATEST=${IMAGE_BASE}:${TAG}" >> $GITHUB_ENV
echo "IMAGE_SHA=${IMAGE_BASE}:sha-${SHORT_SHA}" >> $GITHUB_ENV
- name: Build and push Docker image (with registry cache)
uses: docker/build-push-action@v5
with:
context: .
push: true
platforms: linux/amd64,linux/arm64
tags: |
${{ env.IMAGE_LATEST }}
${{ env.IMAGE_SHA }}
cache-from: type=gha
cache-to: type=gha,mode=max
deploy:
needs: [docker]
runs-on: ubuntu-latest
if: github.event_name == 'workflow_dispatch' || (github.event_name == 'push' && github.ref_name == 'main')
environment:
name: ${{ github.ref_name == 'main' && 'production' || 'dev' }}
url: https://${{ vars.KUBE_DOMAIN }}
env:
# Kubernetes Specific
KUBE_NAMESPACE: ${{ vars.KUBE_NAMESPACE }}
KUBE_API_DOMAIN: ${{ vars.KUBE_API_DOMAIN }}
WORKER_NODE_LABEL: ${{ vars.WORKER_NODE_LABEL }}
# Application Specific
FRONTEND_PATH: ${{ vars.FRONTEND_PATH }}
steps:
- uses: actions/checkout@v4
- uses: azure/setup-kubectl@v4
- name: Set Up Kubeconfig
uses: azure/k8s-set-context@v4
with:
kubeconfig: ${{ secrets.PORTFOLIO_KUBECONFIG }}
- name: Prepare Image Tag
run: |
OWNER=$(echo "${GITHUB_REPOSITORY_OWNER}" | tr '[:upper:]' '[:lower:]')
REPO=$(echo "${GITHUB_REPOSITORY#*/}" | tr '[:upper:]' '[:lower:]')
SHORT_SHA=$(echo "${GITHUB_SHA}" | cut -c1-7)
IMAGE_BASE="ghcr.io/${OWNER}/${REPO}"
IMAGE_TAG="sha-${SHORT_SHA}"
echo "IMAGE_BASE=${IMAGE_BASE}" >> $GITHUB_ENV
echo "IMAGE_TAG=${IMAGE_TAG}" >> $GITHUB_ENV
- name: Import SOPS GPG Key
run: |
echo "${{ secrets.PORTFOLIO_GPG_PRIVATE_KEY }}" | gpg --import
- name: Install SOPS
run: |
curl -L https://github.com/mozilla/sops/releases/download/v3.9.1/sops-v3.9.1.linux.amd64 -o /usr/local/bin/sops
chmod +x /usr/local/bin/sops
- name: Decrypt SOPS Secrets Test
run: |
cd .k8s
sops -d secrets.enc.yml secrets.yml
- name: Apply Kubernetes Manifests - Configuration
run: cat .k8s/config.template.yml | envsubst | kubectl apply -f -
- name: Apply Kubernetes Manifests - Secrets
run: cat .k8s/secrets.yml | envsubst | kubectl apply -f -
- name: Apply Kubernetes Manifests - Postgres Cluster
run: cat .k8s/postgres-cluster.template.yml | envsubst | kubectl apply -f -
- name: Apply Kubernetes Manifests - Redis Cluster
run: cat .k8s/redis.template.yml | envsubst | kubectl apply -f -
- name: Apply Kubernetes Manifests - Deployment
run: |
cat .k8s/deployment.template.yml | envsubst | kubectl apply -f -
cat .k8s/deployment.yaml | envsubst | kubectl rollout status deployment/frontend-deployment -n ${KUBE_NAMESPACE} --timeout=120s
- name: Apply Kubernetes Manifests - Service
run: cat .k8s/service.template.yml | envsubst | kubectl apply -f -
- name: Apply Kubernetes Manifests - Ingress
run: cat .k8s/ingress.template.yml | envsubst | kubectl apply -f -

View File

@@ -1,43 +0,0 @@
name: ci
on:
push:
branches:
- 'main'
jobs:
docker:
runs-on: ubuntu-latest
steps:
- name: Set up QEMU
uses: docker/setup-qemu-action@v1
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
- name: Login to DockerHub
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build and push
uses: docker/build-push-action@v2
with:
platforms: linux/amd64,linux/arm64
push: true
tags: yoshiunfriendly/backend-hideyoshi.com:latest
run-dispatcher:
needs: docker
runs-on: ubuntu-latest
steps:
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
- name: Runs Infra-Hideyoshi.com Deployment Dispatcher
run: |
curl -X POST https://api.github.com/repos/HideyoshiSolutions/infra-hideyoshi.com/dispatches \
-H 'Accept: application/vnd.github.everest-preview+json' \
-u ${{ secrets.ACTIONS_KEY }} \
--data '{"event_type": "refresh-deployments", "client_payload": { "deployments": "backend-deployment" }}'

View File

@@ -1,20 +0,0 @@
name: ci
on:
push
jobs:
run-tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up JDK 17
uses: actions/setup-java@v3
with:
java-version: '17'
distribution: 'temurin'
cache: maven
- name: Running Tests with Maven
run: ./mvnw test

15
.gitignore vendored
View File

@@ -32,7 +32,9 @@ build/
### VS Code ###
.vscode/
src/main/resources/*-devel.yml
src/main/resources/application*.yml
!src/main/resources/application.yml
!src/main/resources/application-no-oauth.yml
### Maven ###
target/
@@ -46,3 +48,14 @@ buildNumber.properties
.mvn/timing.properties
# https://github.com/takari/maven-wrapper#usage-without-binary-jar
.mvn/wrapper/maven-wrapper.jar
### Certs ###
*.pem
### Secrets and Envs ###
.env*
*.secret
.k8s/*.yml
!.k8s/*.template.yml
!.k8s/*.enc.yml

5
.k8s/.sops.yaml Normal file
View File

@@ -0,0 +1,5 @@
creation_rules:
- path_regex: ^secrets(\.enc)?\.yml$
encrypted_regex: '^(data|stringData)$'
pgp: >-
8C8D94A7639C87559B0F2F64B7E1F62F69798EB6

9
.k8s/config.template.yml Normal file
View File

@@ -0,0 +1,9 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: backend-config
namespace: ${KUBE_NAMESPACE}
data:
FRONTEND_PATH: ${FRONTEND_PATH}
STORAGE_SERVICE_INTERNAL_URL: storage-service
STORAGE_SERVICE_PORT: "8000"

View File

@@ -0,0 +1,99 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: backend-deployment
namespace: ${KUBE_NAMESPACE}
spec:
replicas: 1
selector:
matchLabels:
app: backend
template:
metadata:
labels:
app: backend
spec:
nodeSelector:
${WORKER_NODE_LABEL}
imagePullSecrets:
- name: ghcr-secret
containers:
- name: backend
image: ${IMAGE_BASE}:${IMAGE_TAG}
imagePullPolicy: Always
resources:
requests:
memory: "256Mi"
cpu: "250m"
limits:
memory: "256Mi"
cpu: "1000m"
ports:
- containerPort: 8070
readinessProbe:
httpGet:
path: /health
port: 8070
initialDelaySeconds: 60
livenessProbe:
httpGet:
path: /health
port: 8070
initialDelaySeconds: 60
envFrom:
- configMapRef:
name: backend-config
- secretRef:
name: backend-secret
env:
- name: PORT
value: "8070"
- name: REDIS_URL
value: backend-redis-service
- name: REDIS_PORT
value: "6379"
- name: POSTGRES_URL
valueFrom:
secretKeyRef:
name: backend-postgres-cluster-app
key: host
- name: POSTGRES_DB
valueFrom:
secretKeyRef:
name: backend-postgres-cluster-app
key: dbname
- name: DATABASE_URL
value: "postgresql://$(POSTGRES_URL):5432/$(POSTGRES_DB)"
- name: DATABASE_USERNAME
valueFrom:
secretKeyRef:
name: backend-postgres-cluster-app
key: user
- name: DATABASE_PASSWORD
valueFrom:
secretKeyRef:
name: backend-postgres-cluster-app
key: password
- name: STORAGE_SERVICE_URL
valueFrom:
configMapKeyRef:
name: backend-config
key: STORAGE_SERVICE_INTERNAL_URL
- name: STORAGE_SERVICE_PORT
valueFrom:
configMapKeyRef:
name: backend-config
key: STORAGE_SERVICE_PORT
- name: STORAGE_SERVICE_PATH
value: "http://$(STORAGE_SERVICE_URL):$(STORAGE_SERVICE_PORT)"

25
.k8s/ingress.template.yml Normal file
View File

@@ -0,0 +1,25 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: backend-ingress
namespace: ${KUBE_NAMESPACE}
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/use-regex: "true"
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
tls:
- hosts:
- ${KUBE_API_DOMAIN}
secretName: letsencrypt-cluster-certificate-tls
rules:
- host: ${KUBE_API_DOMAIN}
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: backend-service
port:
number: 8070

View File

@@ -0,0 +1,22 @@
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
name: backend-postgres-cluster
namespace: ${KUBE_NAMESPACE}
spec:
instances: 3
primaryUpdateStrategy: unsupervised
imageName: ghcr.io/cloudnative-pg/postgresql:14.10-18
storage:
size: 5Gi
resources:
requests:
memory: "256Mi"
cpu: "200m"
limits:
memory: "512Mi"
cpu: "500m"
affinity: {}

47
.k8s/redis.template.yml Normal file
View File

@@ -0,0 +1,47 @@
apiVersion: apps/v1
kind: Deployment
metadata:
namespace: ${KUBE_NAMESPACE}
name: backend-redis-deployment
spec:
replicas: 1
selector:
matchLabels:
app: backend-redis
template:
metadata:
labels:
app: backend-redis
spec:
containers:
- name: redis
image: valkey/valkey:8.0.6-alpine
imagePullPolicy: "IfNotPresent"
resources:
requests:
memory: "256Mi"
cpu: "75m"
limits:
memory: "256Mi"
cpu: "256m"
ports:
- containerPort: 6379
env:
- name: VALKEY_PASSWORD
valueFrom:
secretKeyRef:
name: backend-secret
key: REDIS_PASSWORD
---
apiVersion: v1
kind: Service
metadata:
namespace: ${KUBE_NAMESPACE}
name: backend-redis-service
spec:
selector:
app: backend-redis
ports:
- port: 6379
type: ClusterIP

46
.k8s/secrets.enc.yml Normal file
View File

@@ -0,0 +1,46 @@
apiVersion: v1
kind: Secret
metadata:
name: backend-secret
namespace: ${KUBE_NAMESPACE}
data:
ACCESS_TOKEN_DURATION: ENC[AES256_GCM,data:UID13ASjuH9hrFfx,iv:D9cTYN60Q8KL1ZdEMPAQ/RP+uqsMbA95cOqngMtxyF8=,tag:Q4cCzqzzRiuf2wyTW86kXg==,type:str]
DEFAULT_USER_EMAIL: ENC[AES256_GCM,data:DJ/3gHT47OidWhevnCHBdzwrFhmCDQeYzjL3siAi+e/Op3Ge,iv:AqUg21UnGl5tJP6TIewcL9wdpAJBGS7Af6olHRm+auU=,tag:+PX5bjMslR0FVqd9fSXnBg==,type:str]
DEFAULT_USER_FULLNAME: ENC[AES256_GCM,data:WGQEQ1/5NhDYudrW8nBnQUXmcC0=,iv:BvysE7IGiXzFUqse0AtzrW1eO4Y52TgD1RX1hxXjqnQ=,tag:nqHCPt7Aa53OTBOTkQGSDA==,type:str]
DEFAULT_USER_PASSWORD: ENC[AES256_GCM,data:N+q5z+cYXPPf7peJdGKx+A6ou5A=,iv:kmOdcNStwIJOnO1RQ+KOcpW3wxrzR13xtdBwSTvC834=,tag:esM/CE+Y4oCFKs7w573qLw==,type:str]
DEFAULT_USER_USERNAME: ENC[AES256_GCM,data:IXWTfhIKBgs+/zUCRBN5SHcn3Ig=,iv:0RegOxvd7WzoSW8u6sjJLdn6kPoSJzstj+OyStS5zNA=,tag:Lv5XR//V9FD0Aa1kLEmOUA==,type:str]
GITHUB_CLIENT_ID: ENC[AES256_GCM,data:Wg8YoSkLie3HgAMUi2Y25GV/0Di+gs0i6KznVg==,iv:4tsj0GvTa21O/CUZ/54B0VnX9Ebi0pX8Y0cBlwQ9uGQ=,tag:uS9WRW9SEeP+PXERUAUDqg==,type:str]
GITHUB_CLIENT_SECRET: ENC[AES256_GCM,data:xA1jb1YcQzLYOtWQWnY1t6DP701Q4P7JXKVCA9m2t9npettwy4FR2Gt1WqrYkyuMrp8CYYdVnlY=,iv:ThCZid05MBY/6W4/H9Xi85bsT6AzOpdhGVWBEc4zNYE=,tag:hP3CO+ElBug0n3f4P708BA==,type:str]
GITHUB_REDIRECT_URL: ENC[AES256_GCM,data:YI1CWaPAtTilqq7ZAmKKGtn9fQs4/urH874s2Nc51Rnqc5/xjYbTpbd/2MMg0vmyrFK8Twcg2RtnfLFa,iv:viH3P9FPCUsd9KoEwVdNTYNl+v24gcGCnVMJzB4AvxM=,tag:b7oSX1Vn5SiFiMhWBsLEDQ==,type:str]
GOOGLE_CLIENT_ID: ENC[AES256_GCM,data:GaKQG4al/kl1PyVGLyQ3gKI0y93IvyPWoxlWd1Iu8YUkcP6vQ80S4fQ1LCGGS8BA0f83SnwTZT37vrFz7h6V3+po6a7CjXE/gSRsu/HIuOG+O4gyAw07KWHorLpcD8pL,iv:RGskspn8CEq3rwinaOe4T/KajAUMHVBJLnGOgBT8L78=,tag:YuSQgDuowd8LLhf5Rdcj2w==,type:str]
GOOGLE_CLIENT_SECRET: ENC[AES256_GCM,data:6sQAluZFxc6mEOZffPJV5Al64APVHJyHHZzneofu17nflE6eslzH0SfL1Uo/ngu6,iv:Za9MHjCSWsGCik9OgJXYmLfFLmcVPQ7V4bLeeflVVOw=,tag:cZfo/pdl42n+eiKPrwFGMg==,type:str]
GOOGLE_REDIRECT_URL: ENC[AES256_GCM,data:3smhd+Hp3/q2uRVHoASTnm7j1F90TAaauCVuWsCUG1aKb++eXkdLEqP5j77szzFmWmBpgeW3hjP7dipL,iv:CPUxKja1YLSnKQpVeEHGkxxmQg1qJnQxRJ48Mw/k75Q=,tag:YJ/c5N1QLLRbCXsi2D2X4g==,type:str]
REDIS_PASSWORD: ENC[AES256_GCM,data:9kexm1c0M7A=,iv:MUSnfOdUbbsJReQtuzyVrJcsc3NqptE96w3Kh1jbqjo=,tag:SvSHTW8Sm3UMIKismYubng==,type:str]
REFRESH_TOKEN_DURATION: ENC[AES256_GCM,data:MCz6j6RI9hKcD8Zzqvt1Iw==,iv:nsw3cTtVJo+/1foTp/M78ByF5p8K6uw720GY8sAJypU=,tag:Usq/7VvLn7MGpoYbZgXAtg==,type:str]
TOKEN_SECRET: ENC[AES256_GCM,data:ESHASgGJZYspUVua,iv:52aZ1Ds984u8rZR48lNjPhBM07vnWGTpEOE6c7cItUU=,tag:Xc/6w/PqDDspl3r/krgdTg==,type:str]
sops:
lastmodified: "2025-11-07T23:43:53Z"
mac: ENC[AES256_GCM,data:38dHNBEQuExxNeouXp7LotuV5aYTUcrhovYEB0v9SPK8q5ViwXSiU730BTyqF3iya6AuugT3xuFZZG0BFxAOv57FXpiX32pVOb9OQEf/vo1I6+lKjYCg0NiP6qvtpH59z4m35SG6zUXICf5zJucOr+n+UeRMsLO4tbjg9s5A+DU=,iv:vlXW79iMy1qBY+hzqkX2McB3746oJZI/6vqeSi9HNNw=,tag:kGhNHSh/aAXDv3Qz3k3gOg==,type:str]
pgp:
- created_at: "2025-11-07T23:43:53Z"
enc: |-
-----BEGIN PGP MESSAGE-----
hQIMAwzdivR1H/BQAQ//ffQ2BHDvlwBU7Ck4BfM3sN5XYFCMVY1Nd1WxNB+Mso7+
Rx4WD1UfNufJhzXIDwGICyNghrfy16UEZZxq2uM/vE/PeQjOwTmkBAB+izzOP8cM
219UV0RG+qh5/n8v5szcaOvpwI2rU5OvRJs/M7N2563rTy+GtXxM3F8zdMFX6ilQ
PNwo0Ah2ag45PEuu/RH9BQ7egdPx4niKESbBX8Ixp95BndcIUqqDmg7mq7oIeg5K
5nu6D0AAf41D5vqTDNpT5P+KiY5adStW22vwTehfBklVXK65scDbEp7BQjMlfWMX
a2DVv0axxOvqPuXaABoVtbHFH9UMnUCe3rcq1An4id/DHU7WrRt0SkHcvHPYxbsO
IWxtl8Au9NH7hjpYO5uTP1HfUYw/MkZ0kC27ZoIg/QxCM1HkYQJU85J9VrK+GhJT
/HbXGb9PE6XIH/Nh0PNJ7cHdpM0tXSE/AyTjdyN5DSnub6sT28vORbsHQkV4oykq
k03gDtT50qT5t0x9oYydJPBCcTd8vhNfNqxYA0ppuGJo3iv+81LDPRSTvGRSU8UJ
bbX56ryJMO/942oBp4u5dsL2q7u0/5cPBJ7UN8v9dJkSAuSHTVNYhhFzKnLsGbr1
ZpBzfg1Mp0zySv2CZpY5xDu1SFs+kaDVPRrOlPz8jFsyt1WNjRNun0521Gfc/CbS
XgEpMev76yzSjkbNSwRS/2U13w7fh76F2MO6ftOwcWS89Do+drdyWJq15ou0LJZE
cqV6ojX5hhtFsH2YTS/+kGDTGf0mNEHtglSzwUT4M0bHBO2vld7p7SNkzMKrwkE=
=vkjm
-----END PGP MESSAGE-----
fp: 8C8D94A7639C87559B0F2F64B7E1F62F69798EB6
encrypted_regex: ^(data|stringData)$
version: 3.11.0

13
.k8s/service.template.yml Normal file
View File

@@ -0,0 +1,13 @@
apiVersion: v1
kind: Service
metadata:
namespace: ${KUBE_NAMESPACE}
name: backend-service
spec:
selector:
app: backend
ports:
- port: 8070
protocol: TCP
targetPort: 8070
type: ClusterIP

View File

@@ -1,17 +1,24 @@
#
# Build stage
#
FROM maven:3.9.3-ibm-semeru-17-focal AS build
COPY src /home/app/src
COPY pom.xml /home/app
RUN mvn -Dmaven.test.skip -f /home/app/pom.xml clean package
WORKDIR /home/app
COPY pom.xml mvnw ./
COPY .mvn/ .mvn/
# Download dependencies into /root/.m2 (use BuildKit cache if available).
# If BuildKit isn't enabled this still works as a normal mvn dependency:go-offline.
RUN --mount=type=cache,target=/root/.m2 mvn -B -Dmaven.test.skip=true dependency:go-offline
COPY src ./src
RUN --mount=type=cache,target=/root/.m2 mvn -B -Dmaven.test.skip=true package
#
# Package stage
#
FROM ibm-semeru-runtimes:open-17-jdk-focal
WORKDIR /app
COPY --from=build /home/app/target/*.jar app.jar
COPY src/main/resources/* credentials/
# Copy final artifact
COPY --from=build /home/app/target/*.jar ./app.jar
ENTRYPOINT ["java","-XX:TieredStopAtLevel=1","-Xverify:none","-jar","/app.jar"]
ENTRYPOINT ["java","-XX:TieredStopAtLevel=1","-Xverify:none","-jar","/app/app.jar"]

View File

@@ -1,18 +0,0 @@
package br.com.hideyoshi.auth.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.repository.configuration.EnableRedisRepositories;
@Configuration
@EnableRedisRepositories
public class RedisConfig {
@Bean
public RedisTemplate<?, ?> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<byte[], byte[]> template = new RedisTemplate<byte[], byte[]>();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
}

View File

@@ -8,7 +8,6 @@ import br.com.hideyoshi.auth.model.microservice.StorageServiceUploadResponse;
import br.com.hideyoshi.auth.security.service.AuthService;
import br.com.hideyoshi.auth.service.UserService;
import br.com.hideyoshi.auth.service.microservice.StorageService;
import br.com.hideyoshi.auth.util.exception.AuthenticationInvalidException;
import br.com.hideyoshi.auth.util.exception.BadRequestException;
import br.com.hideyoshi.auth.util.guard.UserResourceGuard;
import br.com.hideyoshi.auth.util.guard.UserResourceGuardEnum;
@@ -21,9 +20,7 @@ import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.support.ServletUriComponentsBuilder;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.net.URI;
import java.util.List;

View File

@@ -1,8 +1,6 @@
package br.com.hideyoshi.auth.security.oauth2.repository;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.oauth2.client.web.AuthorizationRequestRepository;
import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest;
import org.springframework.stereotype.Repository;
@@ -13,13 +11,11 @@ import java.util.Objects;
@Log4j2
@Repository
@RequiredArgsConstructor
public class OAuthRequestRepository implements AuthorizationRequestRepository<OAuth2AuthorizationRequest> {
private final RedisTemplate<String, OAuth2AuthorizationRequest> template;
@Override
public OAuth2AuthorizationRequest loadAuthorizationRequest(HttpServletRequest request) {
String state = request.getParameter("state");
if (Objects.nonNull(state)) {
return removeAuthorizationRequest(request);
@@ -29,7 +25,14 @@ public class OAuthRequestRepository implements AuthorizationRequestRepository<OA
@Override
public void saveAuthorizationRequest(OAuth2AuthorizationRequest authorizationRequest, HttpServletRequest request, HttpServletResponse response) {
this.saveAuthorizationRequest(authorizationRequest);
String state = authorizationRequest.getState();
request.getSession().setAttribute(
String.format("state_%s", state),
authorizationRequest
);
}
@Override
@@ -39,29 +42,26 @@ public class OAuthRequestRepository implements AuthorizationRequestRepository<OA
OAuth2AuthorizationRequest authorizationRequest = null;
if (Objects.nonNull(state)) {
authorizationRequest = this.getAuthorizationRequestFromSession(state);
authorizationRequest = this.getAuthorizationRequestFromSession(request, state);
}
if (Objects.nonNull(authorizationRequest)) {
removeAuthorizationRequestFromSession(state);
removeAuthorizationRequestFromSession(request, state);
return authorizationRequest;
}
return null;
}
private void saveAuthorizationRequest(OAuth2AuthorizationRequest authorizationRequest) {
this.template.opsForValue().set(
String.format("state_%s", authorizationRequest.getState()),
authorizationRequest
private OAuth2AuthorizationRequest getAuthorizationRequestFromSession(HttpServletRequest request, String state) {
return (OAuth2AuthorizationRequest) request.getSession().getAttribute(
String.format("state_%s", state)
);
}
private OAuth2AuthorizationRequest getAuthorizationRequestFromSession(String state) {
return this.template.opsForValue().get(String.format("state_%s", state));
}
private void removeAuthorizationRequestFromSession(String state) {
this.template.delete(String.format("state_%s", state));
private void removeAuthorizationRequestFromSession(HttpServletRequest request, String state) {
request.getSession().removeAttribute(
String.format("state_%s", state)
);
}
}

View File

@@ -19,7 +19,7 @@ public class EmailUnique implements ConstraintValidator<UniqueEmail, String> {
@Override
public boolean isValid(String email, ConstraintValidatorContext constraintValidatorContext) {
AtomicReference<Boolean> emailValid = new AtomicReference();
AtomicReference<Boolean> emailValid = new AtomicReference<>();
this.userRepository.findByEmail(email).ifPresentOrElse(
(value) -> {
emailValid.set(false);

View File

@@ -20,7 +20,6 @@ server:
session:
cookie:
same-site: none
secure: true
port: ${PORT}
spring: