some fixes, added api key as param
This commit is contained in:
parent
dfbc1e00bd
commit
3c19a9191b
10 changed files with 74 additions and 100 deletions
|
|
@ -21,6 +21,7 @@ import java.util.List;
|
|||
public class ApiKeyFilter extends OncePerRequestFilter {
|
||||
|
||||
private static final String API_KEY_HEADER = "X-API-Key";
|
||||
private static final String API_KEY_PARAM = "apiKey";
|
||||
|
||||
private static final List<String> PUBLIC_PATHS = List.of(
|
||||
"/actuator/health",
|
||||
|
|
@ -29,7 +30,7 @@ public class ApiKeyFilter extends OncePerRequestFilter {
|
|||
"/v3/api-docs"
|
||||
);
|
||||
|
||||
@Value("${taric.api-key}")
|
||||
@Value("${taric.api.key}")
|
||||
private String validApiKey;
|
||||
|
||||
@Override
|
||||
|
|
@ -39,7 +40,6 @@ public class ApiKeyFilter extends OncePerRequestFilter {
|
|||
|
||||
String path = request.getRequestURI();
|
||||
|
||||
|
||||
if ("OPTIONS".equals(request.getMethod())) {
|
||||
filterChain.doFilter(request, response);
|
||||
return;
|
||||
|
|
@ -50,15 +50,9 @@ public class ApiKeyFilter extends OncePerRequestFilter {
|
|||
return;
|
||||
}
|
||||
|
||||
String apiKey = request.getHeader(API_KEY_HEADER);
|
||||
|
||||
if (apiKey == null) {
|
||||
apiKey = request.getHeader(API_KEY_HEADER.toLowerCase());
|
||||
}
|
||||
String apiKey = extractApiKey(request);
|
||||
|
||||
if (validApiKey != null && validApiKey.equals(apiKey)) {
|
||||
|
||||
|
||||
UsernamePasswordAuthenticationToken authentication =
|
||||
new UsernamePasswordAuthenticationToken(
|
||||
"api-user",
|
||||
|
|
@ -76,6 +70,21 @@ public class ApiKeyFilter extends OncePerRequestFilter {
|
|||
}
|
||||
}
|
||||
|
||||
private String extractApiKey(HttpServletRequest request) {
|
||||
|
||||
String apiKey = request.getHeader(API_KEY_HEADER);
|
||||
|
||||
if (apiKey == null) {
|
||||
apiKey = request.getHeader(API_KEY_HEADER.toLowerCase());
|
||||
}
|
||||
|
||||
if (apiKey == null) {
|
||||
apiKey = request.getParameter(API_KEY_PARAM);
|
||||
}
|
||||
|
||||
return apiKey;
|
||||
}
|
||||
|
||||
private boolean isPublicPath(String path) {
|
||||
return PUBLIC_PATHS.stream().anyMatch(path::startsWith);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import de.avatic.taric.repository.MeasureActionRepository;
|
|||
import de.avatic.taric.repository.MeasureRepository;
|
||||
import de.avatic.taric.repository.MeasureSeriesRepository;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.media.Content;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
||||
|
|
@ -14,10 +15,9 @@ import io.swagger.v3.oas.annotations.responses.ApiResponses;
|
|||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/v1/measures")
|
||||
@Tag(name = "Measures", description = "API endpoints for trade measures, measure series, and measure actions")
|
||||
|
|
@ -45,7 +45,12 @@ public class MeasureController {
|
|||
)
|
||||
})
|
||||
@GetMapping
|
||||
public Iterable<Measure> getMeasures() {
|
||||
public Iterable<Measure> getMeasures(@Parameter(description = "Optional series to filter measures by series")
|
||||
@RequestParam(required = false) String series) {
|
||||
|
||||
if( series != null )
|
||||
return measureRepository.findByMeasureSeries(series);
|
||||
|
||||
return measureRepository.findAll();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import io.swagger.v3.oas.annotations.media.Schema;
|
|||
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
||||
import io.swagger.v3.oas.annotations.responses.ApiResponses;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.validation.constraints.Min;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
|
|
@ -65,8 +66,10 @@ public class NomenclatureController {
|
|||
@GetMapping("/declarable")
|
||||
public List<Nomenclature> getDeclarable(
|
||||
@Parameter(description = "Parent HS code to retrieve declarable children from", required = true)
|
||||
@RequestParam String hscode) {
|
||||
return nomenclatureService.getDeclarableChildren(hscode);
|
||||
@RequestParam String hscode,
|
||||
@Parameter(description = "Limit (default =10)", required = true)
|
||||
@RequestParam(required = false, defaultValue = "10") @Min(1) Integer limit) {
|
||||
return nomenclatureService.getDeclarableChildren(hscode, limit);
|
||||
}
|
||||
|
||||
@Operation(
|
||||
|
|
@ -84,7 +87,6 @@ public class NomenclatureController {
|
|||
public List<Nomenclature> getCascade(
|
||||
@Parameter(description = "HS code to retrieve the complete hierarchy for", required = true)
|
||||
@RequestParam String hscode) {
|
||||
var found = nomenclatureService.getNomenclatureCascade(hscode);
|
||||
return found;
|
||||
return nomenclatureService.getNomenclatureCascade(hscode);
|
||||
}
|
||||
}
|
||||
|
|
@ -55,9 +55,9 @@ public class TariffController {
|
|||
@GetMapping("")
|
||||
public Map<String, Map<String, List<AppliedMeasure>>> getTariffRate(
|
||||
@Parameter(description = "Harmonized System code (e.g., 0101210000)", required = true, example = "0101210000")
|
||||
@RequestParam String hsCode,
|
||||
@RequestParam String hscode,
|
||||
@Parameter(description = "ISO country code (e.g., US, CN, GB)", required = true, example = "US")
|
||||
@RequestParam String countryCode) {
|
||||
return tariffService.getAppliedMeasures(hsCode, countryCode);
|
||||
return tariffService.getAppliedMeasures(hscode, countryCode);
|
||||
}
|
||||
}
|
||||
|
|
@ -2,11 +2,15 @@ package de.avatic.taric.model;
|
|||
|
||||
import java.time.LocalDate;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.springframework.data.annotation.Id;
|
||||
|
||||
import jakarta.validation.constraints.Size;
|
||||
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public class MonetaryUnitDesc {
|
||||
|
||||
@Id
|
||||
|
|
@ -19,43 +23,4 @@ public class MonetaryUnitDesc {
|
|||
|
||||
private LocalDate descStartDate;
|
||||
|
||||
public MonetaryUnitDesc(String lang, String desc, LocalDate descStartDate) {
|
||||
this.lang = lang;
|
||||
this.desc = desc;
|
||||
this.descStartDate = descStartDate;
|
||||
}
|
||||
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(final Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getLang() {
|
||||
return lang;
|
||||
}
|
||||
|
||||
public void setLang(final String lang) {
|
||||
this.lang = lang;
|
||||
}
|
||||
|
||||
public String getDesc() {
|
||||
return desc;
|
||||
}
|
||||
|
||||
public void setDescc(final String desc) {
|
||||
this.desc = desc;
|
||||
}
|
||||
|
||||
public LocalDate getDescStartDate() {
|
||||
return descStartDate;
|
||||
}
|
||||
|
||||
public void setDescStartDate(final LocalDate descStartDate) {
|
||||
this.descStartDate = descStartDate;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package de.avatic.taric.repository;
|
||||
|
||||
import org.springframework.data.jdbc.repository.query.Query;
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
|
||||
import de.avatic.taric.model.Measure;
|
||||
|
|
@ -7,4 +8,6 @@ import de.avatic.taric.model.Measure;
|
|||
public interface MeasureRepository extends CrudRepository<Measure, Integer> {
|
||||
|
||||
|
||||
@Query("SELECT * FROM measure m LEFT JOIN measure_series s ON m.measure_series_id = s.id WHERE s.measure_series_code = :series")
|
||||
Iterable<Measure> findByMeasureSeries(String series);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,20 +1,25 @@
|
|||
package de.avatic.taric.repository;
|
||||
|
||||
import de.avatic.taric.model.Nomenclature;
|
||||
import org.springframework.data.domain.Limit;
|
||||
import org.springframework.data.jdbc.repository.query.Query;
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
@Repository
|
||||
public interface NomenclatureRepository extends CrudRepository<Nomenclature, Integer> {
|
||||
|
||||
|
||||
@Query("SELECT * FROM nomenclature WHERE hscode = :hscode AND (end_date IS NULL OR end_date >= CURRENT_DATE)")
|
||||
Optional<Nomenclature> findByHscode(String hscode);
|
||||
|
||||
@Query("SELECT * FROM nomenclature WHERE is_leaf = 1 AND hscode LIKE CONCAT(:code, '%') AND (end_date IS NULL OR end_date >= CURRENT_DATE)")
|
||||
List<Nomenclature> findDeclarableChildren(@Param("code") String code);
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -25,26 +25,32 @@ public class DescSetSerializer extends JsonSerializer<Set<Description>> {
|
|||
|
||||
@Override
|
||||
public void serialize(Set<Description> value, JsonGenerator gen, SerializerProvider serializer) throws IOException {
|
||||
if (value != null) {
|
||||
var filtered = value;
|
||||
if (value == null || value.isEmpty()) {
|
||||
gen.writeNull();
|
||||
return;
|
||||
}
|
||||
|
||||
String language = LANGUAGE_CONTEXT.get();
|
||||
if (language != null) {
|
||||
filtered = value.stream()
|
||||
.filter(desc -> language.equalsIgnoreCase(desc.getLang()))
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
String language = LANGUAGE_CONTEXT.get();
|
||||
|
||||
if (filtered.isEmpty()) {
|
||||
filtered = value.stream()
|
||||
.filter(desc -> "EN".equalsIgnoreCase(desc.getLang()))
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
Set<Description> filtered = Set.of();
|
||||
if (language != null) {
|
||||
filtered = value.stream()
|
||||
.filter(desc -> language.equalsIgnoreCase(desc.getLang()))
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
if(filtered.size() == 1)
|
||||
gen.writeObject(filtered.iterator().next());
|
||||
else
|
||||
gen.writeObject(filtered);
|
||||
if (filtered.isEmpty()) {
|
||||
filtered = value.stream()
|
||||
.filter(desc -> "EN".equalsIgnoreCase(desc.getLang()))
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
if (filtered.isEmpty() && !value.isEmpty()) {
|
||||
filtered = Set.of(value.iterator().next());
|
||||
}
|
||||
|
||||
if (!filtered.isEmpty()) {
|
||||
gen.writeObject(filtered.iterator().next());
|
||||
} else {
|
||||
gen.writeNull();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package de.avatic.taric.service;
|
|||
|
||||
import de.avatic.taric.model.Nomenclature;
|
||||
import de.avatic.taric.repository.NomenclatureRepository;
|
||||
import org.springframework.data.domain.Limit;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.*;
|
||||
|
|
@ -20,16 +21,11 @@ public class NomenclatureService {
|
|||
return nomenclatureRepository.findByHscode(normalize(hscode.replaceAll("[^0-9]", "")));
|
||||
}
|
||||
|
||||
public boolean isDeclarable(String hscode) {
|
||||
var nomenclature = getNomenclature(hscode);
|
||||
if (nomenclature.isEmpty()) return false;
|
||||
return nomenclature.get().getIsLeaf();
|
||||
}
|
||||
public List<Nomenclature> getDeclarableChildren(String hscode, Integer limit) {
|
||||
// var normalized = normalize(hscode.replaceAll("[^0-9]", ""));
|
||||
// var level = getHierarchyLevel(normalized);
|
||||
|
||||
public List<Nomenclature> getDeclarableChildren(String hscode) {
|
||||
var normalized = normalize(hscode.replaceAll("[^0-9]", ""));
|
||||
var level = getHierarchyLevel(normalized);
|
||||
return nomenclatureRepository.findDeclarableChildren(normalized.substring(0, level));
|
||||
return nomenclatureRepository.findDeclarableChildren(hscode).stream().limit(limit).toList();
|
||||
}
|
||||
|
||||
public List<Nomenclature> getNomenclatureCascade(String hscode) {
|
||||
|
|
|
|||
|
|
@ -63,23 +63,6 @@ public class TariffService {
|
|||
|
||||
}
|
||||
|
||||
private Optional<Double> findTariff(Collection<AppliedMeasure> measures, Measure appl) {
|
||||
|
||||
var code = appl.getMeasureCode();
|
||||
|
||||
//TODO return all measures...
|
||||
|
||||
List<AppliedMeasure> filteredMeasures = measures.stream()
|
||||
.filter(meas -> meas.getAmount() != null && meas.getAmount().trim().matches("\\d+\\.\\d+\\s*%"))
|
||||
.toList();
|
||||
|
||||
AppliedMeasure customTariff = filteredMeasures.stream().filter(meas -> meas.getMeasure().getId().equals(appl.getId())).findAny().orElse(filteredMeasures.isEmpty() ? null : filteredMeasures.getFirst());
|
||||
|
||||
if (!filteredMeasures.isEmpty())
|
||||
return Optional.of(customTariff).map(meas -> Double.parseDouble(meas.getAmount().trim().replace("%", "").trim()) / 100);
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
public List<AppliedMeasure> findAppliedMeasureByGeo(Nomenclature nomenclature, Geo geo) {
|
||||
|
||||
var foundImport = importRepository.findByNomenclatureAndGeo(nomenclature.getId(), geo.getId());
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue