Skip to content

Commit

Permalink
🔇 silent changes: add resolve placeholders by configs for SagaAuthHea…
Browse files Browse the repository at this point in the history
…der annotation #2
  • Loading branch information
pnguyen215 committed Sep 15, 2024
1 parent 426bd45 commit 852cf97
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@
import org.aspectj.lang.reflect.MethodSignature;
import org.clarify4j.common.Clarify4j;
import org.clarify4j.common.annotation.SagaAuthHeader;
import org.clarify4j.service.Clarify4jService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.stereotype.Component;
import org.unify4j.common.Request4j;
Expand All @@ -20,6 +22,32 @@
public class SagaAuthHeaderHandler {
protected static final Logger logger = LoggerFactory.getLogger(SagaAuthHeaderHandler.class);

protected final Clarify4jService clarify4jService;

@Autowired
public SagaAuthHeaderHandler(Clarify4jService environment) {
this.clarify4jService = environment;
}

/**
* AOP advice that intercepts method calls annotated with {@link SagaAuthHeader} and performs
* authentication checks based on the presence and value of specified headers.
* <p>
* This method is executed around the annotated method. It first proceeds with the method execution
* and then checks if authentication is disabled through the annotation. If authentication is
* enabled, it resolves the header key and expected value from the annotation, retrieves the
* headers from the current request, and validates the presence and value of the specified
* authentication header. If the header is missing or its value does not match the expected value,
* an {@link AccessDeniedException} is thrown with an appropriate message.
*
* @param joinPoint The join point providing reflective access to both the state available at
* a join point and static information about it. It represents the method
* being intercepted.
* @return The result of the method execution if authentication is successful; otherwise, an
* {@link AccessDeniedException} is thrown.
* @throws Throwable If the underlying method throws an exception, it will propagate it through
* this method.
*/
@Around(value = "@annotation(org.clarify4j.common.annotation.SagaAuthHeader)")
public Object execute(ProceedingJoinPoint joinPoint) throws Throwable {
Object proceed = joinPoint.proceed();
Expand All @@ -29,12 +57,14 @@ public Object execute(ProceedingJoinPoint joinPoint) throws Throwable {
if (auth.disabled()) {
return proceed;
}
String headerKey = clarify4jService.resolveValue(auth.key());
String headerValue = clarify4jService.resolveValue(auth.value());
Map<String, Object> headers = Request4j.getHeaders(Clarify4j.getRequest());
if (!headers.containsKey(auth.key())) {
String message = String.format("Authentication header by key: '%s' not found", auth.key());
if (!headers.containsKey(headerKey)) {
String message = String.format("Authentication header by key: '%s' not found", headerKey);
throw new AccessDeniedException(message);
}
if (!headers.get(auth.key()).equals(auth.value())) {
if (!headers.get(headerKey).equals(headerValue)) {
throw new AccessDeniedException(auth.message());
}
return proceed;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
package org.clarify4j.service;

public interface Clarify4jService {

String resolveValue(String value);
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,47 @@
package org.clarify4j.service.impl;

import org.clarify4j.service.Clarify4jService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service;
import org.clarify4j.service.Clarify4jService;
import org.unify4j.common.String4j;

@SuppressWarnings({"FieldCanBeLocal", "DuplicatedCode"})
@Service
public class Clarify4jServiceImpl implements Clarify4jService {
protected static final Logger logger = LoggerFactory.getLogger(Clarify4jServiceImpl.class);

protected final Environment environment;

@Autowired
public Clarify4jServiceImpl(Environment environment) {
this.environment = environment;
}

/**
* Resolves placeholders in a given string value using Spring's environment property resolution.
* <p>
* This method checks if the provided value string contains placeholders in the format of
* "${property.name}". If it does, the method uses Spring's `Environment` to resolve these
* placeholders to their actual values from the application's property sources (such as
* application.yml or application.properties). If the value does not contain placeholders,
* it is returned as-is.
*
* @param value The string value to be resolved. This can be a literal string or a string
* containing placeholders.
* @return The resolved value if it contains placeholders, or the original value if no
* placeholders are present.
*/
@Override
public String resolveValue(String value) {
if (String4j.isEmpty(value)) {
return value;
}
if (value.startsWith("${") && value.endsWith("}")) {
return environment.resolvePlaceholders(value);
}
return value;
}
}

0 comments on commit 852cf97

Please sign in to comment.