Saturday, 30 August 2025

SpringBoot jpa project with basic authentication swagger

 


entity class
package com.javatechnology.springboot.employees.entity;


import jakarta.persistence.*;


@Entity
@Table(name = "employee")

public class Employee {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column
private long id;

@Column(name = "first_name")
private String firstName;
@Column(name = "last_name")
private String lastName;

@Column(name = "email")
private String email;

public Employee(){
}
public Employee(long id, String firstName, String lastName, String email) {
this.id = id;
this.firstName = firstName;
this.lastName = lastName;
this.email = email;
}

public long getId() {
return id;
}

public void setId(long id) {
this.id = id;
}

public String getFirstName() {
return firstName;
}

public void setFirstName(String firstName) {
this.firstName = firstName;
}

public String getLastName() {
return lastName;
}

public void setLastName(String lastName) {
this.lastName = lastName;
}

public String getEmail() {
return email;
}

public void setEmail(String email) {
this.email = email;
}

@Override
public String toString() {
return "Employee{" +
"id=" + id +
", firstName='" + firstName + '\'' +
", lastName='" + lastName + '\'' +
", email='" + email + '\'' +
'}';
}
}



====================================================================================
request
package com.javatechnology.springboot.employees.request;

import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;

public class EmployeeRequest {


@NotBlank(message = "First name is mandatory")
@Size(min = 2,max = 50,message = "First Name mst be between 2 and 50 character")
private String firstName;

@NotBlank(message = "Last name is mandatory")
@Size(min = 2,max = 50,message = "Last Name mst be between 2 and 50 character")
private String lastName;

@NotBlank(message = "Email is mandatory")
@Email(message = "Please provide a valid email")
private String email;

public String getFirstName() {
return firstName;
}

public void setFirstName(String firstName) {
this.firstName = firstName;
}

public String getLastName() {
return lastName;
}

public void setLastName(String lastName) {
this.lastName = lastName;
}

public String getEmail() {
return email;
}

public void setEmail(String email) {
this.email = email;
}

public EmployeeRequest(String firstName, String lastName, String email) {
this.firstName = firstName;
this.lastName = lastName;
this.email = email;
}


}
=================================================================
dao
package com.javatechnology.springboot.employees.dao;

import com.javatechnology.springboot.employees.entity.Employee;
import org.springframework.data.jpa.repository.JpaRepository;

public interface EmployeeRepository extends JpaRepository<Employee,Long> {

}

============================================================
service
package com.javatechnology.springboot.employees.service;

import com.javatechnology.springboot.employees.entity.Employee;
import com.javatechnology.springboot.employees.request.EmployeeRequest;

import java.util.List;

public interface EmployeeService {


List<Employee> findAll();

public Employee findById(long theId);

public Employee save(EmployeeRequest theEmployeeRequest);

public Employee convertToEmployee(long id,EmployeeRequest employeeRequest);

public Employee update(long id,EmployeeRequest employeeRequest);

void deleteById(long theId);
}

=====================================================================

package com.javatechnology.springboot.employees.service;

import com.javatechnology.springboot.employees.dao.EmployeeRepository;
import com.javatechnology.springboot.employees.entity.Employee;
import com.javatechnology.springboot.employees.request.EmployeeRequest;
import jakarta.transaction.Transactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Optional;

@Service
public class EmployeeServiceImpl implements EmployeeService {

private EmployeeRepository employeeRepository;

@Autowired
public EmployeeServiceImpl(EmployeeRepository employeeRepository) {
this.employeeRepository = employeeRepository;
}


@Override
public List<Employee> findAll() {
return employeeRepository.findAll();
}

@Override
public Employee findById(long theId) {
Optional<Employee> result = employeeRepository.findById(theId);

Employee theEmployee = null;
if (result.isPresent()) {
theEmployee = result.get();
} else {
throw new RuntimeException("Did not find employee id" + theId);
}
return theEmployee;
}

@Transactional
@Override
public Employee save(EmployeeRequest theEmployeeRequest) {
Employee theEmployee = convertToEmployee(0, theEmployeeRequest);
return employeeRepository.save(theEmployee);

}

@Override
public Employee convertToEmployee(long id, EmployeeRequest employeeRequest) {


return new Employee(id, employeeRequest.getFirstName(), employeeRequest.getLastName(), employeeRequest.getEmail());
}

@Transactional
@Override
public Employee update(long id, EmployeeRequest theEmployeeRequest) {
Employee theEmployee = convertToEmployee(id, theEmployeeRequest);
return employeeRepository.save(theEmployee);
}

@Transactional
@Override
public void deleteById(long theId) {
employeeRepository.deleteById(theId);
}


}

=====================================================================================
security

package com.javatechnology.springboot.employees.security;


import org.springframework.boot.autoconfigure.security.SecurityProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.provisioning.JdbcUserDetailsManager;
import org.springframework.security.provisioning.UserDetailsManager;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.SecurityFilterChain;

import javax.sql.DataSource;
import java.net.http.HttpRequest;

@Configuration
public class SecurityConfig {

// hardcoded users
/* @Bean
public InMemoryUserDetailsManager userDetailsManager() {
UserDetails Govind = User.builder().username("Govind").password("{noop}Pass@123456").roles("EMPLOYEE").build();
UserDetails Rishabh = User.builder().username("Rishabh").password("{noop}Pass@123456").roles("EMPLOYEE", "MANAGER").build();
UserDetails Vicky = User.builder().username("Vicky").password("{noop}Pass@123456").roles("EMPLOYEE", "MANAGER", "ADMIN").build();
return new InMemoryUserDetailsManager(Govind, Rishabh, Vicky);

}*/


//add support for jdbc no more hardcoded users
/* @Bean
public UserDetailsManager userDetailsManager(DataSource datasource)
{
return new JdbcUserDetailsManager(datasource);
}*/


@Bean
public UserDetailsManager userDetailsManager(DataSource datasource)
{
JdbcUserDetailsManager jdbcUserDetailsManager=new JdbcUserDetailsManager(datasource);
//define query to retrieve a user by username
jdbcUserDetailsManager.setUsersByUsernameQuery("select user_id,password,active from system_users where user_id=?");
//define query to retrieve a roles/authorities by username

jdbcUserDetailsManager.setAuthoritiesByUsernameQuery("select user_id,role from roles where user_id=?");

return jdbcUserDetailsManager;
}


@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.authorizeHttpRequests(configurer -> configurer.
requestMatchers(HttpMethod.GET, "/h2-console/**").permitAll().
requestMatchers(HttpMethod.POST, "/h2-console/**").permitAll().
requestMatchers("/docs/**", "/swagger-ui/**", "/v3/api-docs/**", "/swagger-ui.html").permitAll().
requestMatchers(HttpMethod.GET, "/api/employees").hasRole("EMPLOYEE").
requestMatchers(HttpMethod.GET, "/api/employees/**").hasRole("EMPLOYEE").
requestMatchers(HttpMethod.POST, "/api/employees").hasRole("MANAGER").
requestMatchers(HttpMethod.PUT, "/api/employees/**").hasRole("MANAGER").
requestMatchers(HttpMethod.DELETE, "/api/employees/**").hasRole("ADMIN")

);
http.httpBasic(httpBasicCustomizer -> httpBasicCustomizer.disable());
//use http basic authentication
http.httpBasic(Customizer.withDefaults());
http.csrf(csrf -> csrf.disable());
http.exceptionHandling(exceptionHandling -> exceptionHandling.authenticationEntryPoint(authenticationEntryPoint()));
http.headers(header -> header.frameOptions(frameOptions -> frameOptions.disable()));

return http.build();
}


@Bean
public AuthenticationEntryPoint authenticationEntryPoint() {
return ((request, response, authException) -> {
//send 401 unauthorized status without triggering a basic auth
response.setStatus(HttpStatus.UNAUTHORIZED.value());
response.setContentType("application/json");
//removes the WWW-Authenticate header to prevent browser popup
response.setHeader("WWW-Authenticate", "");
response.getWriter().write("{\"error\":\"Unauthorized access\"}");
});

}
}

===================================================================================

package com.javatechnology.springboot.employees.security;

import io.swagger.v3.oas.annotations.OpenAPIDefinition;
import io.swagger.v3.oas.annotations.enums.SecuritySchemeType;
import io.swagger.v3.oas.annotations.info.Info;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import io.swagger.v3.oas.annotations.security.SecurityScheme;
import org.springframework.context.annotation.Configuration;

@Configuration
@OpenAPIDefinition(info=@Info(title = "My API",version = "v1"),security = @SecurityRequirement(name = "basicAuth"))
@SecurityScheme(name = "basicAuth",type = SecuritySchemeType.HTTP ,scheme = "basic")
public class SwaggerConfig {
}

======================================================================================

package com.javatechnology.springboot.employees;

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

@SpringBootApplication
public class EmployeesApplication {

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

}

============================================================================
application.properties
spring.application.name=employees
springdoc.swagger-ui.path=/docs

#H2 Database configurations

spring.datasource.url=jdbc:h2:file:./data/employeedb
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.userName=sa
spring.datasource.password=password
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect

#H2 console configurations

spring.h2.console.enabled=true
spring.h2.console.path=/h2-console
spring.jpa.hibernate.ddl-auto=update


spring.security.user.name=scott
spring.security.user.password=Pass@123456

==============================================================================


DROP TABLE IF EXISTS authorities;
DROP TABLE IF EXISTS users;

--
-- Table structure for table `users`
--

CREATE TABLE users (
username VARCHAR(50) NOT NULL,
password VARCHAR(50) NOT NULL,
enabled BOOLEAN NOT NULL,
PRIMARY KEY (username)
);

--
-- Inserting data for table `users`
--

INSERT INTO users (username, password, enabled)
VALUES
('john', '{noop}test123', TRUE),
('mary', '{noop}test123', TRUE),
('susan', '{noop}test123', TRUE);

--
-- Table structure for table `authorities`
--

CREATE TABLE authorities (
username VARCHAR(50) NOT NULL,
authority VARCHAR(50) NOT NULL,
UNIQUE (username, authority),
FOREIGN KEY (username) REFERENCES users (username)
);

--
-- Inserting data for table `authorities`
--

INSERT INTO authorities (username, authority)
VALUES
('john', 'ROLE_EMPLOYEE'),
('mary', 'ROLE_EMPLOYEE'),
('mary', 'ROLE_MANAGER'),
('susan', 'ROLE_EMPLOYEE'),
('susan', 'ROLE_MANAGER'),
('susan', 'ROLE_ADMIN');


=========================================================


-- Drop tables if they exist
DROP TABLE IF EXISTS authorities;
DROP TABLE IF EXISTS users;

--
-- Table structure for table `users`
--

CREATE TABLE users (
username VARCHAR(50) NOT NULL,
password CHAR(68) NOT NULL,
enabled BOOLEAN NOT NULL,
PRIMARY KEY (username)
);

--
-- Inserting data for table `users`
--
-- The passwords are encrypted using BCrypt
-- A generation tool is available at: https://www.luv2code.com/generate-bcrypt-password
-- Default passwords here are: fun123
--

INSERT INTO users (username, password, enabled)
VALUES
('john', '{bcrypt}$2a$10$qeS0HEh7urweMojsnwNAR.vcXJeXR1UcMRZ2WcGQl9YeuspUdgF.q', TRUE),
('mary', '{bcrypt}$2a$10$qeS0HEh7urweMojsnwNAR.vcXJeXR1UcMRZ2WcGQl9YeuspUdgF.q', TRUE),
('susan', '{bcrypt}$2a$10$qeS0HEh7urweMojsnwNAR.vcXJeXR1UcMRZ2WcGQl9YeuspUdgF.q', TRUE);

--
-- Table structure for table `authorities`
--

CREATE TABLE authorities (
username VARCHAR(50) NOT NULL,
authority VARCHAR(50) NOT NULL,
UNIQUE (username, authority),
FOREIGN KEY (username) REFERENCES users (username)
);

--
-- Inserting data for table `authorities`
--

INSERT INTO authorities (username, authority)
VALUES
('john', 'ROLE_EMPLOYEE'),
('mary', 'ROLE_EMPLOYEE'),
('mary', 'ROLE_MANAGER'),
('susan', 'ROLE_EMPLOYEE'),
('susan', 'ROLE_MANAGER'),
('susan', 'ROLE_ADMIN');


=========================================================================================




-- Drop tables if they exist
DROP TABLE IF EXISTS authorities;
DROP TABLE IF EXISTS users;

CREATE TABLE system_users (
user_id VARCHAR(50) NOT NULL,
password CHAR(68) NOT NULL,
active BOOLEAN NOT NULL,
PRIMARY KEY (user_id)
);

INSERT INTO system_users (user_id, password, active)
VALUES
('john', '{bcrypt}$2a$10$qeS0HEh7urweMojsnwNAR.vcXJeXR1UcMRZ2WcGQl9YeuspUdgF.q', TRUE),
('mary', '{bcrypt}$2a$10$qeS0HEh7urweMojsnwNAR.vcXJeXR1UcMRZ2WcGQl9YeuspUdgF.q', TRUE),
('susan', '{bcrypt}$2a$10$qeS0HEh7urweMojsnwNAR.vcXJeXR1UcMRZ2WcGQl9YeuspUdgF.q', TRUE);

CREATE TABLE roles (
user_id VARCHAR(50) NOT NULL,
role VARCHAR(50) NOT NULL,
UNIQUE (user_id, role),
FOREIGN KEY (user_id) REFERENCES system_users (user_id)
);

INSERT INTO roles (user_id, role)
VALUES
('john', 'ROLE_EMPLOYEE'),
('mary', 'ROLE_EMPLOYEE'),
('mary', 'ROLE_MANAGER'),
('susan', 'ROLE_EMPLOYEE'),
('susan', 'ROLE_MANAGER'),
('susan', 'ROLE_ADMIN');

===================================================================================


<?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>3.5.5</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.javatechnology.springboot</groupId>
<artifactId>employees</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>employees</name>
<description>employees project for Spring Boot</description>
<url/>
<licenses>
<license/>
</licenses>
<developers>
<developer/>
</developers>
<scm>
<connection/>
<developerConnection/>
<tag/>
<url/>
</scm>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>

<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
<version>2.8.3</version>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>

</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-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>













No comments:

Post a Comment