Add a PortfolioController to retrieve all data relevant to portfolio (Other controllers) with authentication (api-key)
This commit is contained in:
parent
e22d2b6fca
commit
dccae4cad0
7 changed files with 145 additions and 30 deletions
14
pom.xml
14
pom.xml
|
|
@ -71,6 +71,20 @@
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter-data-mongodb</artifactId>
|
<artifactId>spring-boot-starter-data-mongodb</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-security</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- https://mvnrepository.com/artifact/jakarta.servlet/jakarta.servlet-api -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>jakarta.servlet</groupId>
|
||||||
|
<artifactId>jakarta.servlet-api</artifactId>
|
||||||
|
<version>6.1.0</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
|
|
||||||
30
src/main/java/io/titan/portfolio/config/SecurityConfig.java
Normal file
30
src/main/java/io/titan/portfolio/config/SecurityConfig.java
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
package io.titan.portfolio.config;
|
||||||
|
|
||||||
|
import io.titan.portfolio.security.ApiKeyFilter;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||||
|
import org.springframework.security.web.SecurityFilterChain;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
public class SecurityConfig {
|
||||||
|
|
||||||
|
private final ApiKeyFilter apiKeyFilter;
|
||||||
|
|
||||||
|
public SecurityConfig(ApiKeyFilter apiKeyFilter) {
|
||||||
|
this.apiKeyFilter = apiKeyFilter;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
|
||||||
|
http
|
||||||
|
.csrf(csrf -> csrf.disable()) // Disable CSRF for APIs
|
||||||
|
.addFilterBefore(apiKeyFilter, org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter.class)
|
||||||
|
.authorizeHttpRequests(auth -> auth
|
||||||
|
.requestMatchers("/api/portfolio").authenticated() // Secure the endpoint
|
||||||
|
.anyRequest().permitAll() // Allow other requests
|
||||||
|
);
|
||||||
|
|
||||||
|
return http.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -3,22 +3,14 @@ package io.titan.portfolio.controller;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
// import org.springframework.web.bind.annotation.DeleteMapping;
|
|
||||||
// import org.springframework.web.bind.annotation.GetMapping;
|
|
||||||
// import org.springframework.web.bind.annotation.PathVariable;
|
|
||||||
// import org.springframework.web.bind.annotation.PostMapping;
|
|
||||||
// import org.springframework.web.bind.annotation.PutMapping;
|
|
||||||
// import org.springframework.web.bind.annotation.RequestBody;
|
|
||||||
// import org.springframework.web.bind.annotation.RequestMapping;
|
|
||||||
// import org.springframework.web.bind.annotation.RestController;
|
|
||||||
|
|
||||||
import io.titan.portfolio.model.Education;
|
import io.titan.portfolio.model.Education;
|
||||||
import io.titan.portfolio.service.EducationService;
|
import io.titan.portfolio.service.EducationService;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@RestController
|
// @RestController
|
||||||
@RequestMapping("/api/portfolio/education")
|
// @RequestMapping("/api/portfolio/education")
|
||||||
public class EducationController {
|
public class EducationController {
|
||||||
private final EducationService educationService;
|
private final EducationService educationService;
|
||||||
|
|
||||||
|
|
@ -26,25 +18,25 @@ public class EducationController {
|
||||||
this.educationService = educationService;
|
this.educationService = educationService;
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping
|
// @GetMapping
|
||||||
List<Education> getAllEducation(){
|
List<Education> getAllEducation(){
|
||||||
return educationService.getAllEducation();
|
return educationService.getAllEducation();
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/{id}")
|
// @GetMapping("/{id}")
|
||||||
ResponseEntity<Education> getEducationById(@PathVariable String id) {
|
ResponseEntity<Education> getEducationById(@PathVariable String id) {
|
||||||
return educationService.getEducationById(id)
|
return educationService.getEducationById(id)
|
||||||
.map(ResponseEntity::ok)
|
.map(ResponseEntity::ok)
|
||||||
.orElse(ResponseEntity.notFound().build());
|
.orElse(ResponseEntity.notFound().build());
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping
|
// @PostMapping
|
||||||
ResponseEntity<Void> createEducation(@RequestBody Education education) {
|
ResponseEntity<Void> createEducation(@RequestBody Education education) {
|
||||||
educationService.createEducation(education);
|
educationService.createEducation(education);
|
||||||
return ResponseEntity.status(HttpStatus.CREATED).build();
|
return ResponseEntity.status(HttpStatus.CREATED).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@PutMapping("/{id}")
|
// @PutMapping("/{id}")
|
||||||
ResponseEntity<Education> updateEducation(@PathVariable String id, @RequestBody Education education) {
|
ResponseEntity<Education> updateEducation(@PathVariable String id, @RequestBody Education education) {
|
||||||
if (!id.equals(education.id())) {
|
if (!id.equals(education.id())) {
|
||||||
return ResponseEntity.badRequest().build();
|
return ResponseEntity.badRequest().build();
|
||||||
|
|
@ -53,7 +45,7 @@ public class EducationController {
|
||||||
return ResponseEntity.ok(education);
|
return ResponseEntity.ok(education);
|
||||||
}
|
}
|
||||||
|
|
||||||
@DeleteMapping("/{id}")
|
// @DeleteMapping("/{id}")
|
||||||
ResponseEntity<Void> deleteEducation(@PathVariable String id) {
|
ResponseEntity<Void> deleteEducation(@PathVariable String id) {
|
||||||
boolean deleted = educationService.deleteEducation(id);
|
boolean deleted = educationService.deleteEducation(id);
|
||||||
return deleted ? ResponseEntity.ok().build() : ResponseEntity.notFound().build();
|
return deleted ? ResponseEntity.ok().build() : ResponseEntity.notFound().build();
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,39 @@
|
||||||
|
package io.titan.portfolio.controller;
|
||||||
|
|
||||||
|
import io.titan.portfolio.model.Education;
|
||||||
|
// import io.titan.portfolio.model.Experience;
|
||||||
|
import io.titan.portfolio.service.EducationService;
|
||||||
|
// import io.titan.portfolio.service.ExperienceService;
|
||||||
|
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
// import org.springframework.beans.factory.annotation.Value;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/api/portfolio")
|
||||||
|
public class PortfolioController {
|
||||||
|
private final EducationService educationService;
|
||||||
|
|
||||||
|
// @Value("${api.key}")
|
||||||
|
// private String apiKey;
|
||||||
|
|
||||||
|
PortfolioController(EducationService educationService){
|
||||||
|
this.educationService = educationService;
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping
|
||||||
|
public ResponseEntity<Map<String, Object>> getPortfolio() {
|
||||||
|
List<Education> educationList = educationService.getAllEducation();
|
||||||
|
// List<Experience> experienceList = experienceService.getAllExperience();
|
||||||
|
|
||||||
|
Map<String, Object> portfolio = Map.of(
|
||||||
|
"education", educationList
|
||||||
|
// "experience", experienceList
|
||||||
|
);
|
||||||
|
|
||||||
|
return ResponseEntity.ok(portfolio);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -4,17 +4,6 @@ import io.titan.portfolio.model.Education;
|
||||||
|
|
||||||
import org.springframework.data.mongodb.repository.MongoRepository;
|
import org.springframework.data.mongodb.repository.MongoRepository;
|
||||||
import org.springframework.stereotype.Repository;
|
import org.springframework.stereotype.Repository;
|
||||||
// import org.springframework.jdbc.core.JdbcTemplate;
|
|
||||||
// import org.springframework.jdbc.core.RowMapper;
|
|
||||||
// import org.springframework.jdbc.support.GeneratedKeyHolder;
|
|
||||||
// import org.springframework.jdbc.support.KeyHolder;
|
|
||||||
// import org.springframework.stereotype.Repository;
|
|
||||||
|
|
||||||
// import java.sql.PreparedStatement;
|
|
||||||
// import java.sql.Statement;
|
|
||||||
// import java.util.Arrays;
|
|
||||||
// import java.util.List;
|
|
||||||
// import java.util.Optional;
|
|
||||||
|
|
||||||
@Repository
|
@Repository
|
||||||
public interface EducationRepository extends MongoRepository<Education, String>{
|
public interface EducationRepository extends MongoRepository<Education, String>{
|
||||||
|
|
|
||||||
39
src/main/java/io/titan/portfolio/security/ApiKeyFilter.java
Normal file
39
src/main/java/io/titan/portfolio/security/ApiKeyFilter.java
Normal file
|
|
@ -0,0 +1,39 @@
|
||||||
|
package io.titan.portfolio.security;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.http.HttpHeaders;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.security.core.Authentication;
|
||||||
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
|
import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.web.filter.OncePerRequestFilter;
|
||||||
|
|
||||||
|
import jakarta.servlet.FilterChain;
|
||||||
|
import jakarta.servlet.ServletException;
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class ApiKeyFilter extends OncePerRequestFilter {
|
||||||
|
|
||||||
|
@Value("${api.key}")
|
||||||
|
private String apiKey;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
|
||||||
|
throws ServletException, IOException {
|
||||||
|
String requestApiKey = request.getHeader("X-API-KEY");
|
||||||
|
|
||||||
|
if (apiKey.equals(requestApiKey)) {
|
||||||
|
Authentication auth = new PreAuthenticatedAuthenticationToken("apiKeyUser", null, null);
|
||||||
|
SecurityContextHolder.getContext().setAuthentication(auth);
|
||||||
|
} else {
|
||||||
|
response.sendError(HttpStatus.UNAUTHORIZED.value(), "Invalid API Key");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
filterChain.doFilter(request, response);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,6 +1,18 @@
|
||||||
spring.data.mongodb.uri=mongodb://portfolio_user:portfolio_P%40ssword@localhost:27017/portfolio_db
|
# spring.application.name=titan_backend
|
||||||
spring.application.name=titan_backend
|
# spring.devtools.restart.enabled=true
|
||||||
spring.devtools.restart.enabled=true
|
# server.port=8282
|
||||||
|
|
||||||
|
# spring.data.mongodb.uri=${MONGO_URL}
|
||||||
|
# api.key=${API_KEY}
|
||||||
|
|
||||||
|
spring.profiles.active=dev
|
||||||
|
|
||||||
|
# # Logging level
|
||||||
|
# logging.level.root=INFO
|
||||||
|
# Development MongoDB connection
|
||||||
|
spring.data.mongodb.uri=mongodb://portfolio_user:portfolio_P%40ssword@localhost:27017/portfolio_db
|
||||||
|
# api.key=dev-api-key-12345
|
||||||
server.port=8282
|
server.port=8282
|
||||||
# logging.level.root=DEBUG
|
|
||||||
|
# Logging Level
|
||||||
|
logging.level.root=DEBUG
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue