Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .idea/.gitignore

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

18 changes: 18 additions & 0 deletions .idea/compiler.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions .idea/encodings.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

20 changes: 20 additions & 0 deletions .idea/jarRepositories.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 9 additions & 0 deletions .idea/lab-java-springboot-rest-api.iml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 14 additions & 0 deletions .idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions .idea/vcs.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

69 changes: 69 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>4.0.6</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.ironhack</groupId>
<artifactId>lab-springboot-api</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name/>
<description/>
<url/>
<licenses>
<license/>
</licenses>
<developers>
<developer/>
</developers>
<scm>
<connection/>
<developerConnection/>
<tag/>
<url/>
</scm>
<properties>
<java.version>25</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webmvc</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webmvc-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>

</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.ironhack.lab_springboot_api;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class LabSpringbootApiApplication {

public static void main(String[] args) {
SpringApplication.run(LabSpringbootApiApplication.class, args);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package com.ironhack.lab_springboot_api.controller;

import com.ironhack.lab_springboot_api.model.Customer;
import jakarta.validation.Valid;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.List;

@RestController
@RequestMapping("/customers")
public class CustomerController {

private List<Customer> customers = new ArrayList<>();

@PostMapping
public ResponseEntity<Customer> createCustomer(@Valid @RequestBody Customer customer) {
customers.add(customer);
return new ResponseEntity<>(customer, HttpStatus.CREATED);
}

@GetMapping
public List<Customer> getAll() {
return customers;
}

@GetMapping("/{email}")
public ResponseEntity<Customer> getByEmail(@PathVariable String email) {
for (Customer c : customers) {
if (c.getEmail().equalsIgnoreCase(email)) {
return ResponseEntity.ok(c);
}
}
return ResponseEntity.notFound().build();
}

@PutMapping("/{email}")
public ResponseEntity<Customer> updateCustomer(@PathVariable String email, @Valid @RequestBody Customer updated) {
for (Customer c : customers) {
if (c.getEmail().equalsIgnoreCase(email)) {
c.setName(updated.getName());
c.setAge(updated.getAge());
c.setAddress(updated.getAddress());
return ResponseEntity.ok(c);
}
}
return ResponseEntity.notFound().build();
}

@DeleteMapping("/{email}")
public ResponseEntity<Void> deleteCustomer(@PathVariable String email) {
customers.removeIf(c -> c.getEmail().equalsIgnoreCase(email));
return ResponseEntity.noContent().build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
package com.ironhack.lab_springboot_api.controller;

import com.ironhack.lab_springboot_api.model.Product;
import com.ironhack.lab_springboot_api.service.ProductService;
import jakarta.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/products")
public class ProductController {

private final ProductService productService;

public ProductController(ProductService productService) {
this.productService = productService;
}

@PostMapping
public ResponseEntity<?> createProduct(
@RequestHeader(value = "API-Key", required = false) String apiKey,
@Valid @RequestBody Product product) {
if (apiKey == null || !apiKey.equals("123456")) {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("Invalid API Key");
}
return new ResponseEntity<>(productService.addProduct(product), HttpStatus.CREATED);
}
@GetMapping
public ResponseEntity<?> getProducts(@RequestHeader String apiKey) {
if (apiKey == null || !apiKey.equals("123456")) {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("Invalid API Key");
}
return ResponseEntity.ok(productService.getProductList());
}

@GetMapping("/{name}")
public ResponseEntity<?> getProduct(@PathVariable String name,
@RequestHeader("API-Key") String apiKey) {

if (apiKey == null || !apiKey.equals("123456")) {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("Invalid API Key");
}

Product product = productService.getProductByName(name);


if (product == null) {
return ResponseEntity.status(HttpStatus.NOT_FOUND).body("Producto no encontrado");
}

return ResponseEntity.ok(product);
}

@GetMapping("/price")
public ResponseEntity<?> getProductPrice(
@RequestHeader("API-Key") String apiKey,
@RequestParam double min,
@RequestParam double max) {

if (apiKey == null || !apiKey.equals("123456")) {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("Invalid API Key");
}
return ResponseEntity.ok(productService.getByPriceRange(min, max));
}

// 1. Obtener por categoría
@GetMapping("/category/{category}")
public ResponseEntity<?> getProductByCategory(@RequestHeader("API-Key") String apiKey, @PathVariable String category) {
if (apiKey == null || !apiKey.equals("123456")) {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("Invalid API Key");
}
return ResponseEntity.ok(productService.getByCategory(category));
}

@PutMapping("/{name}")
public ResponseEntity<?> updateProduct(@RequestHeader("API-Key") String apiKey,
@PathVariable String name,
@Valid @RequestBody Product product) {
if (apiKey == null || !apiKey.equals("123456")) {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("Invalid API Key");
}
Product updated = productService.updateProduct(name, product);
if (updated == null) return ResponseEntity.notFound().build();
return ResponseEntity.ok(updated);
}

@DeleteMapping("/{name}")
public ResponseEntity<?> deleteProduct(@RequestHeader("API-Key") String apiKey, @PathVariable String name) {
if (apiKey == null || !apiKey.equals("123456")) {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("Invalid API Key");
}
productService.deleteProduct(name);
return ResponseEntity.noContent().build();
}



}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package com.ironhack.lab_springboot_api.exception;

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.bind.MissingRequestHeaderException;

import java.util.HashMap;
import java.util.Map;

@RestControllerAdvice
public class GlobalExceptionHandler {

@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<Map<String, String>> handleValidationExceptions(MethodArgumentNotValidException ex) {
Map<String, String> errors = new HashMap<>();
ex.getBindingResult().getFieldErrors().forEach(error ->
errors.put(error.getField(), error.getDefaultMessage()));
return new ResponseEntity<>(errors, HttpStatus.BAD_REQUEST);
}

@ExceptionHandler(MissingRequestHeaderException.class)
public ResponseEntity<String> handleMissingHeader(MissingRequestHeaderException ex) {
if (ex.getHeaderName().equals("API-Key")) {
return new ResponseEntity<>("Falta el encabezado API-Key obligatorio", HttpStatus.UNAUTHORIZED);
}
return new ResponseEntity<>(ex.getMessage(), HttpStatus.BAD_REQUEST);
}
}
Loading