diff --git a/README.md b/README.md
index 4d53534..5b8dfa5 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,7 @@
# BasicSpringBootAPI
-Efficient REST API crafted using Core Java and Spring Boot, enabling smooth CRUD operations on an employee database.
+Efficient REST API crafted using Core Java and Spring Boot, enabling smooth CRUD operations on an employee database, that includes the incorporation of a Spring Security layer, using bcrypt-hashed passwords, and executed through the adept utilization of JDBC technology.
+
+# Database Preview
+
+
diff --git a/mysqlscripts/employee-directory.sql b/mysqlscripts/employee-directory.sql
new file mode 100644
index 0000000..ee866ba
--- /dev/null
+++ b/mysqlscripts/employee-directory.sql
@@ -0,0 +1,22 @@
+CREATE DATABASE IF NOT EXISTS `employee_directory`;
+USE `employee_directory`;
+
+
+DROP TABLE IF EXISTS `employee`;
+
+CREATE TABLE `employee` (
+ `id` int NOT NULL AUTO_INCREMENT,
+ `first_name` varchar(45) DEFAULT NULL,
+ `last_name` varchar(45) DEFAULT NULL,
+ `email` varchar(45) DEFAULT NULL,
+ PRIMARY KEY (`id`)
+) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=latin1;
+
+
+INSERT INTO `employee` VALUES
+ (1,'Manuel','Miguez','manum@mail.com'),
+ (2,'Luca','Vinelli','lucav@mail.com'),
+ (3,'Iñaki','Mariño','iñakim@mail.com'),
+ (4,'Manfiu','Puerto','manfiudp@mail.com'),
+ (5,'Juani','Pucheta','juanip@mail.com');
+
diff --git a/mysqlscripts/spring-security-finished.sql b/mysqlscripts/spring-security-finished.sql
new file mode 100644
index 0000000..959a855
--- /dev/null
+++ b/mysqlscripts/spring-security-finished.sql
@@ -0,0 +1,36 @@
+USE `employee_directory`;
+
+DROP TABLE IF EXISTS `roles`;
+DROP TABLE IF EXISTS `members`;
+
+
+CREATE TABLE `members` (
+ `user` varchar(50) NOT NULL,
+ `psw` char(68) NOT NULL,
+ `active` tinyint NOT NULL,
+ PRIMARY KEY (`user`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1;
+
+INSERT INTO `members`
+VALUES
+('ramiro','{bcrypt}$2a$10$S7GTZIc/KfegnP9H4GNaCOxHkvu0M32H7f9wg/lHl/c97VQtIoVvm',1),
+('matias','{bcrypt}$2a$10$DWG0SGnfxqDIjx.LrywatevHjod2EbepV0W3t5d1aOoRLjSQuvszS',1),
+('alejo','{bcrypt}$2a$10$0tqmRxOQufHIrIuQWNHa6.M4ei4LbE4NhN6gfUEOOnxpkbzLABGc6',1);
+
+
+CREATE TABLE `roles` (
+ `user` varchar(50) NOT NULL,
+ `role` varchar(50) NOT NULL,
+ UNIQUE KEY `authorities5_idx_1` (`user`,`role`),
+ CONSTRAINT `authorities5_ibfk_1` FOREIGN KEY (`user`) REFERENCES `members` (`user`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1;
+
+
+INSERT INTO `roles`
+VALUES
+('ramiro','ROLE_EMPLOYEE'),
+('matias','ROLE_EMPLOYEE'),
+('matias','ROLE_MANAGER'),
+('alejo','ROLE_EMPLOYEE'),
+('alejo','ROLE_MANAGER'),
+('alejo','ROLE_ADMIN');
diff --git a/mysqlscripts/spring-security-users-bcrypt.sql b/mysqlscripts/spring-security-users-bcrypt.sql
new file mode 100644
index 0000000..e6002cd
--- /dev/null
+++ b/mysqlscripts/spring-security-users-bcrypt.sql
@@ -0,0 +1,36 @@
+USE `employee_directory`;
+
+DROP TABLE IF EXISTS `authorities`;
+DROP TABLE IF EXISTS `users`;
+
+
+CREATE TABLE `users` (
+ `username` varchar(50) NOT NULL,
+ `password` char(68) NOT NULL,
+ `enabled` tinyint NOT NULL,
+ PRIMARY KEY (`username`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1;
+
+INSERT INTO `users`
+VALUES
+('ramiro','{bcrypt}$2a$10$S7GTZIc/KfegnP9H4GNaCOxHkvu0M32H7f9wg/lHl/c97VQtIoVvm',1),
+('matias','{bcrypt}$2a$10$DWG0SGnfxqDIjx.LrywatevHjod2EbepV0W3t5d1aOoRLjSQuvszS',1),
+('alejo','{bcrypt}$2a$10$0tqmRxOQufHIrIuQWNHa6.M4ei4LbE4NhN6gfUEOOnxpkbzLABGc6',1);
+
+
+CREATE TABLE `authorities` (
+ `username` varchar(50) NOT NULL,
+ `authority` varchar(50) NOT NULL,
+ UNIQUE KEY `authorities4_idx_1` (`username`,`authority`),
+ CONSTRAINT `authorities4_ibfk_1` FOREIGN KEY (`username`) REFERENCES `users` (`username`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1;
+
+
+INSERT INTO `authorities`
+VALUES
+('ramiro','ROLE_EMPLOYEE'),
+('matias','ROLE_EMPLOYEE'),
+('matias','ROLE_MANAGER'),
+('alejo','ROLE_EMPLOYEE'),
+('alejo','ROLE_MANAGER'),
+('alejo','ROLE_ADMIN');
\ No newline at end of file
diff --git a/mysqlscripts/spring-security-users.sql b/mysqlscripts/spring-security-users.sql
new file mode 100644
index 0000000..47363d0
--- /dev/null
+++ b/mysqlscripts/spring-security-users.sql
@@ -0,0 +1,39 @@
+USE `employee_directory`;
+
+DROP TABLE IF EXISTS `authorities`;
+DROP TABLE IF EXISTS `users`;
+
+
+CREATE TABLE `users` (
+ `username` varchar(50) NOT NULL,
+ `password` varchar(50) NOT NULL,
+ `enabled` tinyint NOT NULL,
+ PRIMARY KEY (`username`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1;
+
+
+INSERT INTO `users`
+VALUES
+('ramiro','{noop}examplepass',1),
+('matias','{noop}examplepass',1),
+('alejo','{noop}examplepass',1);
+
+
+CREATE TABLE `authorities` (
+ `username` varchar(50) NOT NULL,
+ `authority` varchar(50) NOT NULL,
+ UNIQUE KEY `authorities_idx_1` (`username`,`authority`),
+ CONSTRAINT `authorities_ibfk_1` FOREIGN KEY (`username`) REFERENCES `users` (`username`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1;
+
+
+INSERT INTO `authorities`
+VALUES
+('ramiro','ROLE_EMPLOYEE'),
+('matias','ROLE_EMPLOYEE'),
+('matias','ROLE_MANAGER'),
+('alejo','ROLE_EMPLOYEE'),
+('alejo','ROLE_MANAGER'),
+('alejo','ROLE_ADMIN');
+
+
diff --git a/pom.xml b/pom.xml
index a4e1e3d..1baccf0 100644
--- a/pom.xml
+++ b/pom.xml
@@ -17,10 +17,22 @@
17
+
+
+ org.springframework.boot
+ spring-boot-starter-security
+
+
+
+ org.springframework.boot
+ spring-boot-starter-data-rest
+
+
org.springframework.boot
spring-boot-starter-data-jpa
+
org.springframework.boot
spring-boot-starter-web
@@ -32,16 +44,19 @@
runtime
true
+
com.mysql
mysql-connector-j
runtime
+
org.springframework.boot
spring-boot-starter-test
test
+
diff --git a/src/main/assets/DatabaseFinalPreview.png b/src/main/assets/DatabaseFinalPreview.png
new file mode 100644
index 0000000..043759d
Binary files /dev/null and b/src/main/assets/DatabaseFinalPreview.png differ
diff --git a/src/main/java/com/manumiguezz/crudapplication/dao/EmployeeDAO.java b/src/main/java/com/manumiguezz/crudapplication/dao/EmployeeDAO.java
deleted file mode 100644
index e6f13fe..0000000
--- a/src/main/java/com/manumiguezz/crudapplication/dao/EmployeeDAO.java
+++ /dev/null
@@ -1,15 +0,0 @@
-//package com.manumiguezz.crudapplication.dao;
-//
-//import com.manumiguezz.crudapplication.entity.Employee;
-//
-//import java.util.List;
-//
-//public interface EmployeeDAO {
-// List findAll();
-//
-// Employee findById(int theId);
-//
-// Employee save(Employee theEmployee);
-//
-// void deleteByID(int theId);
-//}
diff --git a/src/main/java/com/manumiguezz/crudapplication/dao/EmployeeDAOJpaImpl.java b/src/main/java/com/manumiguezz/crudapplication/dao/EmployeeDAOJpaImpl.java
deleted file mode 100644
index 6008827..0000000
--- a/src/main/java/com/manumiguezz/crudapplication/dao/EmployeeDAOJpaImpl.java
+++ /dev/null
@@ -1,50 +0,0 @@
-//package com.manumiguezz.crudapplication.dao;
-//
-//import com.manumiguezz.crudapplication.entity.Employee;
-//import jakarta.persistence.EntityManager;
-//import jakarta.persistence.TypedQuery;
-//import org.springframework.beans.factory.annotation.Autowired;
-//import org.springframework.stereotype.Repository;
-//
-//import java.util.List;
-//
-//@Repository
-//public class EmployeeDAOJpaImpl implements EmployeeDAO {
-//
-// private EntityManager entityManager;
-//
-// @Autowired
-// public EmployeeDAOJpaImpl(EntityManager theEntityManager) {
-// entityManager = theEntityManager;
-// }
-//
-// @Override
-// public List findAll() {
-//
-// TypedQuery theQuery = entityManager.createQuery("from Employee", Employee.class);
-//
-// List employees = theQuery.getResultList();
-//
-// return employees;
-// }
-//
-// @Override
-// public Employee findById(int theId) {
-// Employee theEmployee = entityManager.find(Employee.class, theId);
-// return theEmployee;
-// }
-//
-// @Override
-// public Employee save(Employee theEmployee) {
-// // if ID of passed employee is equal to 0, it will insert a new one, else it will just update
-// Employee dbEmployee = entityManager.merge(theEmployee);
-// return dbEmployee;
-// }
-//
-// @Override
-// public void deleteByID(int theId) {
-// Employee theEmployee = entityManager.find(Employee.class, theId);
-// entityManager.remove(theEmployee);
-// }
-//
-//}
diff --git a/src/main/java/com/manumiguezz/crudapplication/rest/EmployeeRestController.java b/src/main/java/com/manumiguezz/crudapplication/rest/EmployeeRestController.java
index 13a5acd..ad1fc54 100644
--- a/src/main/java/com/manumiguezz/crudapplication/rest/EmployeeRestController.java
+++ b/src/main/java/com/manumiguezz/crudapplication/rest/EmployeeRestController.java
@@ -1,9 +1,8 @@
package com.manumiguezz.crudapplication.rest;
-import com.manumiguezz.crudapplication.dao.EmployeeDAO;
import com.manumiguezz.crudapplication.entity.Employee;
import com.manumiguezz.crudapplication.service.EmployeeService;
-import com.manumiguezz.crudapplication.service.EmployeeServiceImpl;
+import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@@ -14,17 +13,20 @@ public class EmployeeRestController {
private EmployeeService employeeService;
- public EmployeeRestController (EmployeeService theEmployeeService) {
+ @Autowired
+ public EmployeeRestController(EmployeeService theEmployeeService) {
employeeService = theEmployeeService;
}
@GetMapping("/employees")
- public List findAll(){
+ public List findAll() {
return employeeService.findAll();
}
+
@GetMapping("/employees/{employeeId}")
public Employee getEmployee(@PathVariable int employeeId) {
+
Employee theEmployee = employeeService.findById(employeeId);
if (theEmployee == null) {
@@ -34,35 +36,52 @@ public Employee getEmployee(@PathVariable int employeeId) {
return theEmployee;
}
- @PostMapping ("/employees")
+
+ @PostMapping("/employees")
public Employee addEmployee(@RequestBody Employee theEmployee) {
+
theEmployee.setId(0);
Employee dbEmployee = employeeService.save(theEmployee);
+
return dbEmployee;
}
@PutMapping("/employees")
public Employee updateEmployee(@RequestBody Employee theEmployee) {
+
Employee dbEmployee = employeeService.save(theEmployee);
+
return dbEmployee;
}
- @DeleteMapping("/employees/{employeeId} ")
+ @DeleteMapping("/employees/{employeeId}")
public String deleteEmployee(@PathVariable int employeeId) {
+
Employee tempEmployee = employeeService.findById(employeeId);
if (tempEmployee == null) {
- throw new RuntimeException("Employee id: " + employeeId + " not found");
+ throw new RuntimeException("Employee id not found - " + employeeId);
}
- employeeService.deleteByID(employeeId);
+ employeeService.deleteById(employeeId);
- return "Employee with id: " + employeeId + " was deleted";
+ return "Deleted employee id - " + employeeId;
}
+}
+
+
+
+
+
+
+
+
+
+
+
-}
diff --git a/src/main/java/com/manumiguezz/crudapplication/security/SecurityConfig.java b/src/main/java/com/manumiguezz/crudapplication/security/SecurityConfig.java
new file mode 100644
index 0000000..cd5fe8b
--- /dev/null
+++ b/src/main/java/com/manumiguezz/crudapplication/security/SecurityConfig.java
@@ -0,0 +1,49 @@
+package com.manumiguezz.crudapplication.security;
+
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.http.HttpMethod;
+import org.springframework.security.config.Customizer;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.provisioning.JdbcUserDetailsManager;
+import org.springframework.security.provisioning.UserDetailsManager;
+import org.springframework.security.web.SecurityFilterChain;
+
+import javax.sql.DataSource;
+
+@Configuration
+public class SecurityConfig {
+
+ @Bean
+ public UserDetailsManager userDetailsManager (DataSource dataSource){
+ JdbcUserDetailsManager jdbcUserDetailsManager = new JdbcUserDetailsManager(dataSource);
+
+ jdbcUserDetailsManager
+ .setUsersByUsernameQuery("select user, psw, active from members where user=?");
+
+ jdbcUserDetailsManager
+ .setAuthoritiesByUsernameQuery("select user, role from roles where user=?");
+
+ return jdbcUserDetailsManager;
+ }
+
+
+ @Bean
+ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
+
+ http.authorizeHttpRequests(configurer ->
+ configurer
+ .requestMatchers(HttpMethod.GET, "/api/employees").hasRole("EMPLOYEE")
+ .requestMatchers(HttpMethod.GET, "/api/employees/**").hasRole("EMPLOYEE")
+ .requestMatchers(HttpMethod.POST, "/api/employees").hasRole("TL")
+ .requestMatchers(HttpMethod.PUT, "/api/employees").hasRole("TL")
+ .requestMatchers(HttpMethod.DELETE, "/api/employees/**").hasRole("ADMIN")
+ );
+
+ http.httpBasic(Customizer.withDefaults());
+ http.csrf(csrf -> csrf.disable());
+
+ return http.build();
+ }
+}
diff --git a/src/main/java/com/manumiguezz/crudapplication/service/EmployeeService.java b/src/main/java/com/manumiguezz/crudapplication/service/EmployeeService.java
index ff56fdb..ea2f973 100644
--- a/src/main/java/com/manumiguezz/crudapplication/service/EmployeeService.java
+++ b/src/main/java/com/manumiguezz/crudapplication/service/EmployeeService.java
@@ -1,16 +1,18 @@
package com.manumiguezz.crudapplication.service;
+
import com.manumiguezz.crudapplication.entity.Employee;
import java.util.List;
public interface EmployeeService {
+
List findAll();
Employee findById(int theId);
Employee save(Employee theEmployee);
- void deleteByID(int theId);
+ void deleteById(int theId);
}
diff --git a/src/main/java/com/manumiguezz/crudapplication/service/EmployeeServiceImpl.java b/src/main/java/com/manumiguezz/crudapplication/service/EmployeeServiceImpl.java
index 6acf772..8964a1c 100644
--- a/src/main/java/com/manumiguezz/crudapplication/service/EmployeeServiceImpl.java
+++ b/src/main/java/com/manumiguezz/crudapplication/service/EmployeeServiceImpl.java
@@ -1,22 +1,21 @@
package com.manumiguezz.crudapplication.service;
-import com.manumiguezz.crudapplication.dao.EmployeeDAO;
+
import com.manumiguezz.crudapplication.dao.EmployeeRepository;
import com.manumiguezz.crudapplication.entity.Employee;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
-import org.springframework.transaction.annotation.Transactional;
import java.util.List;
import java.util.Optional;
@Service
-public class EmployeeServiceImpl implements EmployeeService{
+public class EmployeeServiceImpl implements EmployeeService {
private EmployeeRepository employeeRepository;
@Autowired
- public EmployeeServiceImpl (EmployeeRepository theEmployeeRepository) {
+ public EmployeeServiceImpl(EmployeeRepository theEmployeeRepository) {
employeeRepository = theEmployeeRepository;
}
@@ -29,13 +28,13 @@ public List findAll() {
public Employee findById(int theId) {
Optional result = employeeRepository.findById(theId);
- Employee theEmployee;
+ Employee theEmployee = null;
if (result.isPresent()) {
theEmployee = result.get();
}
else {
- throw new RuntimeException("Did not find employee id: " + theId);
+ throw new RuntimeException("Did not find employee id - " + theId);
}
return theEmployee;
@@ -47,7 +46,13 @@ public Employee save(Employee theEmployee) {
}
@Override
- public void deleteByID(int theId) {
+ public void deleteById(int theId) {
employeeRepository.deleteById(theId);
}
}
+
+
+
+
+
+
diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties
index 4a4b39a..8e8ddad 100644
--- a/src/main/resources/application.properties
+++ b/src/main/resources/application.properties
@@ -1,4 +1,10 @@
spring.datasource.url=jdbc:mysql://localhost:3306/employee_directory
spring.datasource.username=springstudent
-spring.datasource.password=springstudent
\ No newline at end of file
+spring.datasource.password=springstudent
+
+spring.data.rest.base-path=/company-api
+spring.data.rest.default-page-size=40
+
+spring.security.user.name=example
+spring.security.user.password=example
\ No newline at end of file
diff --git a/target/classes/application.properties b/target/classes/application.properties
index 4a4b39a..8e8ddad 100644
--- a/target/classes/application.properties
+++ b/target/classes/application.properties
@@ -1,4 +1,10 @@
spring.datasource.url=jdbc:mysql://localhost:3306/employee_directory
spring.datasource.username=springstudent
-spring.datasource.password=springstudent
\ No newline at end of file
+spring.datasource.password=springstudent
+
+spring.data.rest.base-path=/company-api
+spring.data.rest.default-page-size=40
+
+spring.security.user.name=example
+spring.security.user.password=example
\ No newline at end of file
diff --git a/target/classes/com/manumiguezz/crudapplication/dao/EmployeeRepository.class b/target/classes/com/manumiguezz/crudapplication/dao/EmployeeRepository.class
new file mode 100644
index 0000000..1d2b904
Binary files /dev/null and b/target/classes/com/manumiguezz/crudapplication/dao/EmployeeRepository.class differ
diff --git a/target/classes/com/manumiguezz/crudapplication/rest/EmployeeRestController.class b/target/classes/com/manumiguezz/crudapplication/rest/EmployeeRestController.class
new file mode 100644
index 0000000..a82df70
Binary files /dev/null and b/target/classes/com/manumiguezz/crudapplication/rest/EmployeeRestController.class differ
diff --git a/target/classes/com/manumiguezz/crudapplication/security/SecurityConfig.class b/target/classes/com/manumiguezz/crudapplication/security/SecurityConfig.class
new file mode 100644
index 0000000..2b7ca08
Binary files /dev/null and b/target/classes/com/manumiguezz/crudapplication/security/SecurityConfig.class differ
diff --git a/target/classes/com/manumiguezz/crudapplication/service/EmployeeService.class b/target/classes/com/manumiguezz/crudapplication/service/EmployeeService.class
index fb6d74a..32b1e27 100644
Binary files a/target/classes/com/manumiguezz/crudapplication/service/EmployeeService.class and b/target/classes/com/manumiguezz/crudapplication/service/EmployeeService.class differ
diff --git a/target/classes/com/manumiguezz/crudapplication/service/EmployeeServiceImpl.class b/target/classes/com/manumiguezz/crudapplication/service/EmployeeServiceImpl.class
new file mode 100644
index 0000000..d74acc3
Binary files /dev/null and b/target/classes/com/manumiguezz/crudapplication/service/EmployeeServiceImpl.class differ