├── .mvn └── wrapper │ ├── maven-wrapper.jar │ └── maven-wrapper.properties ├── src ├── main │ ├── java │ │ └── com │ │ │ └── example │ │ │ ├── constant │ │ │ ├── RoleName.java │ │ │ ├── ResponseStatus.java │ │ │ ├── ResponseCode.java │ │ │ └── Constants.java │ │ │ ├── service │ │ │ ├── AdminService.java │ │ │ ├── AuthService.java │ │ │ ├── ClientService.java │ │ │ └── impl │ │ │ │ ├── AdminServiceImpl.java │ │ │ │ ├── AuthServiceImpl.java │ │ │ │ └── ClientServiceImpl.java │ │ │ ├── entity │ │ │ ├── base │ │ │ │ ├── IdEntity.java │ │ │ │ └── BaseEntity.java │ │ │ ├── Role.java │ │ │ ├── Client.java │ │ │ └── User.java │ │ │ ├── repository │ │ │ ├── RoleRepository.java │ │ │ ├── UserRepository.java │ │ │ └── ClientRepository.java │ │ │ ├── exception │ │ │ ├── NotFoundException.java │ │ │ ├── AuthorizationException.java │ │ │ ├── BadRequestException.java │ │ │ ├── EmptyFieldException.java │ │ │ └── ErrorsHandler.java │ │ │ ├── model │ │ │ ├── PageRequestModel.java │ │ │ ├── LoginModel.java │ │ │ ├── SignUpModel.java │ │ │ └── ClientModel.java │ │ │ ├── response │ │ │ └── base │ │ │ │ ├── JwtAuthenticationResponse.java │ │ │ │ ├── ListResponse.java │ │ │ │ ├── SingleResponse.java │ │ │ │ └── BaseResponse.java │ │ │ ├── controller │ │ │ ├── AdminController.java │ │ │ ├── AuthController.java │ │ │ └── ClientController.java │ │ │ ├── util │ │ │ ├── Haversine.java │ │ │ ├── CommonUtils.java │ │ │ ├── AppLogger.java │ │ │ └── CommonsValidator.java │ │ │ ├── config │ │ │ ├── CORSFilter.java │ │ │ └── SecurityConfig.java │ │ │ ├── security │ │ │ ├── JwtAuthenticationEntryPoint.java │ │ │ ├── CustomUserDetailService.java │ │ │ ├── JwtAuthenticationFilter.java │ │ │ ├── JwtTokenProvider.java │ │ │ └── AuthenticatedUser.java │ │ │ └── demo │ │ │ └── BasesProjectApplication.java │ └── resources │ │ └── application.properties └── test │ └── java │ └── com │ └── example │ └── demo │ └── BasesProjectApplicationTests.java ├── .gitignore ├── pom.xml ├── README.md ├── mvnw.cmd └── mvnw /.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlaaMezian/SpringBoot-Haversine-Jwt/HEAD/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.5.3/apache-maven-3.5.3-bin.zip 2 | -------------------------------------------------------------------------------- /src/main/java/com/example/constant/RoleName.java: -------------------------------------------------------------------------------- 1 | package com.example.constant; 2 | 3 | public enum RoleName { 4 | 5 | ROLE_ADMIN, ROLE_USER,ROLE_CLIENT 6 | 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/com/example/constant/ResponseStatus.java: -------------------------------------------------------------------------------- 1 | package com.example.constant; 2 | 3 | public final class ResponseStatus { 4 | 5 | public final static String RESPONSE_STATUS_SUCCESS = "Success"; 6 | public final static String RESPONSE_STATUS_FAILED = "Failed"; 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/com/example/service/AdminService.java: -------------------------------------------------------------------------------- 1 | package com.example.service; 2 | 3 | import javax.servlet.http.HttpServletRequest; 4 | 5 | import com.example.response.base.BaseResponse; 6 | 7 | public interface AdminService { 8 | public BaseResponse createDefaultAdmin(HttpServletRequest request); 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/com/example/entity/base/IdEntity.java: -------------------------------------------------------------------------------- 1 | package com.example.entity.base; 2 | 3 | import javax.persistence.GeneratedValue; 4 | import javax.persistence.GenerationType; 5 | import javax.persistence.Id; 6 | import javax.persistence.MappedSuperclass; 7 | 8 | @MappedSuperclass 9 | public abstract class IdEntity { 10 | 11 | 12 | 13 | } 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | 4 | ### STS ### 5 | .apt_generated 6 | .classpath 7 | .factorypath 8 | .project 9 | .settings 10 | .springBeans 11 | .sts4-cache 12 | 13 | ### IntelliJ IDEA ### 14 | .idea 15 | *.iws 16 | *.iml 17 | *.ipr 18 | 19 | ### NetBeans ### 20 | /nbproject/private/ 21 | /build/ 22 | /nbbuild/ 23 | /dist/ 24 | /nbdist/ 25 | /.nb-gradle/ -------------------------------------------------------------------------------- /src/test/java/com/example/demo/BasesProjectApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.example.demo; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class BasesProjectApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/com/example/repository/RoleRepository.java: -------------------------------------------------------------------------------- 1 | package com.example.repository; 2 | 3 | import java.util.Optional; 4 | 5 | import org.springframework.data.jpa.repository.JpaRepository; 6 | import org.springframework.stereotype.Repository; 7 | 8 | import com.example.constant.RoleName; 9 | import com.example.entity.Role; 10 | 11 | @Repository 12 | public interface RoleRepository extends JpaRepository { 13 | Optional findByName(RoleName roleName); 14 | } -------------------------------------------------------------------------------- /src/main/java/com/example/service/AuthService.java: -------------------------------------------------------------------------------- 1 | package com.example.service; 2 | 3 | import javax.servlet.http.HttpServletRequest; 4 | 5 | import com.example.model.LoginModel; 6 | import com.example.model.SignUpModel; 7 | import com.example.response.base.BaseResponse; 8 | import com.example.response.base.JwtAuthenticationResponse; 9 | 10 | public interface AuthService { 11 | BaseResponse signUp(SignUpModel signUpRequest); 12 | 13 | JwtAuthenticationResponse logIn(LoginModel loginRequest, HttpServletRequest req); 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/com/example/exception/NotFoundException.java: -------------------------------------------------------------------------------- 1 | package com.example.exception; 2 | 3 | import org.springframework.http.HttpStatus; 4 | import org.springframework.web.bind.annotation.ResponseStatus; 5 | 6 | @ResponseStatus(HttpStatus.NOT_FOUND) 7 | public class NotFoundException extends RuntimeException { 8 | 9 | private static final long serialVersionUID = 1L; 10 | 11 | public NotFoundException(String message) { 12 | super(message); 13 | } 14 | 15 | public NotFoundException(Throwable cause) { 16 | super(cause); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/com/example/model/PageRequestModel.java: -------------------------------------------------------------------------------- 1 | package com.example.model; 2 | 3 | public class PageRequestModel { 4 | private String page; 5 | private Integer size; 6 | private String sort; 7 | 8 | public String getPage() { 9 | return page; 10 | } 11 | public void setPage(String page) { 12 | this.page = page; 13 | } 14 | public Integer getSize() { 15 | return size; 16 | } 17 | public void setSize(Integer size) { 18 | this.size = size; 19 | } 20 | public String getSort() { 21 | return sort; 22 | } 23 | public void setSort(String sort) { 24 | this.sort = sort; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/com/example/exception/AuthorizationException.java: -------------------------------------------------------------------------------- 1 | package com.example.exception; 2 | 3 | import org.springframework.http.HttpStatus; 4 | import org.springframework.web.bind.annotation.ResponseStatus; 5 | 6 | @ResponseStatus(HttpStatus.UNAUTHORIZED) 7 | public class AuthorizationException extends RuntimeException { 8 | 9 | /** 10 | * 11 | */ 12 | private static final long serialVersionUID = 1L; 13 | 14 | public AuthorizationException(String message) { 15 | super(message); 16 | } 17 | public AuthorizationException(Throwable cause) { 18 | super(cause); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/example/exception/BadRequestException.java: -------------------------------------------------------------------------------- 1 | package com.example.exception; 2 | 3 | import org.springframework.http.HttpStatus; 4 | import org.springframework.web.bind.annotation.ResponseStatus; 5 | 6 | @ResponseStatus(HttpStatus.BAD_REQUEST) 7 | public class BadRequestException extends RuntimeException { 8 | 9 | 10 | /** 11 | * 12 | */ 13 | private static final long serialVersionUID = 1L; 14 | 15 | public BadRequestException(String message) { 16 | super(message); 17 | } 18 | public BadRequestException(Throwable cause) { 19 | super(cause); 20 | } 21 | 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/com/example/exception/EmptyFieldException.java: -------------------------------------------------------------------------------- 1 | package com.example.exception; 2 | 3 | import org.springframework.http.HttpStatus; 4 | import org.springframework.web.bind.annotation.ResponseStatus; 5 | 6 | 7 | @ResponseStatus(HttpStatus.BAD_REQUEST) 8 | public class EmptyFieldException extends RuntimeException{ 9 | 10 | /** 11 | * 12 | */ 13 | private static final long serialVersionUID = 1L; 14 | 15 | public EmptyFieldException(String message) { 16 | super(message + " " + "this field is required"); 17 | } 18 | 19 | public EmptyFieldException(Throwable cause) { 20 | super(cause); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/com/example/model/LoginModel.java: -------------------------------------------------------------------------------- 1 | package com.example.model; 2 | 3 | import org.springframework.validation.annotation.Validated; 4 | 5 | @Validated 6 | public class LoginModel { 7 | private String usernameOrEmail; 8 | 9 | 10 | private String password; 11 | 12 | public String getUsernameOrEmail() { 13 | return usernameOrEmail; 14 | } 15 | 16 | public void setUsernameOrEmail(String usernameOrEmail) { 17 | this.usernameOrEmail = usernameOrEmail; 18 | } 19 | 20 | public String getPassword() { 21 | return password; 22 | } 23 | 24 | public void setPassword(String password) { 25 | this.password = password; 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/com/example/service/ClientService.java: -------------------------------------------------------------------------------- 1 | package com.example.service; 2 | 3 | import javax.servlet.http.HttpServletRequest; 4 | 5 | import com.example.model.ClientModel; 6 | import com.example.response.base.BaseResponse; 7 | 8 | public interface ClientService { 9 | 10 | BaseResponse createClient(ClientModel clientMdl); 11 | 12 | BaseResponse updateClient(long id, ClientModel clientMdl, HttpServletRequest request); 13 | 14 | BaseResponse deleteClient(long id); 15 | 16 | BaseResponse getAll(); 17 | 18 | BaseResponse getById(long id); 19 | 20 | BaseResponse findAllNearestClientWithIndistance(double latitude, double longtitude, double distance); 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/com/example/response/base/JwtAuthenticationResponse.java: -------------------------------------------------------------------------------- 1 | package com.example.response.base; 2 | 3 | public class JwtAuthenticationResponse { 4 | 5 | private String accessToken; 6 | private String tokenType = "Bearer"; 7 | 8 | public JwtAuthenticationResponse(String accessToken) { 9 | this.accessToken = accessToken; 10 | } 11 | 12 | public String getAccessToken() { 13 | return accessToken; 14 | } 15 | 16 | public void setAccessToken(String accessToken) { 17 | this.accessToken = accessToken; 18 | } 19 | 20 | public String getTokenType() { 21 | return tokenType; 22 | } 23 | 24 | public void setTokenType(String tokenType) { 25 | this.tokenType = tokenType; 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.datasource.url=jdbc:mysql://localhost:3306/demoApp?autoReconnect=true&characterEncoding=utf-8&useSSL=false 2 | 3 | spring.datasource.username=root 4 | spring.datasource.password= 5 | 6 | # hibernate configurations 7 | spring.jpa.show-sql = true 8 | spring.jpa.hibernate.ddl-auto= update 9 | spring.jpa.properties.hibernate.dialet= org.hibernate.dialect.MySQL5Dialect 10 | 11 | spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.security.SecurityAutoConfiguration 12 | 13 | 14 | 15 | server.port = 8080 16 | 17 | ##JWT-Configuration## 18 | app.jwtSecret= JWTSuperSecretKey 19 | app.jwtExpirationInMs = 604800000 20 | 21 | ##CREATE DATABASE demoApp; 22 | -------------------------------------------------------------------------------- /src/main/java/com/example/constant/ResponseCode.java: -------------------------------------------------------------------------------- 1 | package com.example.constant; 2 | 3 | public final class ResponseCode { 4 | 5 | public final static String SUCCESS_RESPONSE_CODE = "200" ; 6 | public final static String SUCCESS_CREATE_CODE = "201"; 7 | public final static String FAILED_RESPONSE_CODE = "400" ; 8 | public final static String NO_CONTENT = "204"; 9 | public final static String RESPONSE_CODE_SUCCESS = "200" ; 10 | public final static String RESPONSE_CODE_CREATED = "201"; 11 | public final static String RESPONSE_CODE_BAD_REQUEST = "400" ; 12 | public final static String RESPONSE_CODE_NOT_FOUND = "404" ; 13 | public final static String RESPONSE_CODE_UNAUTHORIZED = "401"; 14 | public final static String RESPONSE_CODE_FORBIDDEN = "403"; 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/com/example/model/SignUpModel.java: -------------------------------------------------------------------------------- 1 | package com.example.model; 2 | 3 | import org.springframework.validation.annotation.Validated; 4 | 5 | @Validated 6 | public class SignUpModel { 7 | 8 | private String username; 9 | 10 | private String email; 11 | 12 | private String password; 13 | 14 | public String getUsername() { 15 | return username; 16 | } 17 | 18 | public void setUsername(String username) { 19 | this.username = username; 20 | } 21 | 22 | public String getEmail() { 23 | return email; 24 | } 25 | 26 | public void setEmail(String email) { 27 | this.email = email; 28 | } 29 | 30 | public String getPassword() { 31 | return password; 32 | } 33 | 34 | public void setPassword(String password) { 35 | this.password = password; 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/com/example/repository/UserRepository.java: -------------------------------------------------------------------------------- 1 | package com.example.repository; 2 | 3 | import java.util.List; 4 | import java.util.Optional; 5 | 6 | import org.springframework.data.repository.PagingAndSortingRepository; 7 | import org.springframework.stereotype.Repository; 8 | 9 | import com.example.entity.User; 10 | 11 | @Repository 12 | public interface UserRepository extends PagingAndSortingRepository { 13 | 14 | User findByEmail(String email); 15 | 16 | Optional findByUsernameOrEmail(String username, String email); 17 | 18 | List findAllByActive(boolean status); 19 | 20 | Optional findByUsername(String username); 21 | 22 | Boolean existsByUsername(String username); 23 | 24 | Boolean existsByEmail(String email); 25 | 26 | User findByActiveAndId(boolean status, long id); 27 | } -------------------------------------------------------------------------------- /src/main/java/com/example/constant/Constants.java: -------------------------------------------------------------------------------- 1 | package com.example.constant; 2 | 3 | public final class Constants { 4 | 5 | public static final String BLANK = ""; 6 | public static final String COLON = " : "; 7 | public static final String DASH = " - "; 8 | public static final String ENTRY = "Entry"; 9 | public static final String EXIT = "Exit"; 10 | 11 | public static final boolean ENTITY_STATUS_ACTIVE = true; 12 | public static final boolean ENTITY_STATUS_NOT_ACTIVE = false; 13 | 14 | public static final int USERNAME_MIN_CHAR_COUNT = 3; 15 | public static final int USERNAME_MAX_CHAR_COUNT = 25; 16 | public static final int PASSWORD_MIN_CHAR_COUNT = 8; 17 | public static final int PASSWORD_MAX_CHAR_COUNT = 16; 18 | 19 | public static final String LONG = "35.934413"; 20 | public static final String LATT = "31.951309"; 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/com/example/controller/AdminController.java: -------------------------------------------------------------------------------- 1 | package com.example.controller; 2 | 3 | import javax.servlet.http.HttpServletRequest; 4 | 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.security.access.prepost.PreAuthorize; 7 | import org.springframework.web.bind.annotation.RequestMapping; 8 | import org.springframework.web.bind.annotation.RequestMethod; 9 | import org.springframework.web.bind.annotation.RestController; 10 | 11 | import com.example.response.base.BaseResponse; 12 | import com.example.service.AdminService; 13 | 14 | @RestController 15 | @RequestMapping(value = "/api/v1") 16 | public class AdminController { 17 | @Autowired 18 | private AdminService adminService; 19 | 20 | @RequestMapping(value = "/admin", method = RequestMethod.POST) 21 | public BaseResponse createAdmin(HttpServletRequest request) { 22 | return adminService.createDefaultAdmin(request); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/com/example/entity/Role.java: -------------------------------------------------------------------------------- 1 | package com.example.entity; 2 | 3 | import javax.persistence.Entity; 4 | import javax.persistence.EnumType; 5 | import javax.persistence.Enumerated; 6 | import javax.persistence.GeneratedValue; 7 | import javax.persistence.GenerationType; 8 | import javax.persistence.Id; 9 | import javax.persistence.Table; 10 | 11 | import org.hibernate.annotations.NaturalId; 12 | 13 | import com.example.constant.RoleName; 14 | 15 | @Entity 16 | @Table(name = "role") 17 | public class Role { 18 | 19 | @Id 20 | @GeneratedValue(strategy = GenerationType.AUTO) 21 | protected Long id; 22 | 23 | @Enumerated(EnumType.STRING) 24 | @NaturalId 25 | private RoleName name; 26 | 27 | public RoleName getName() { 28 | return name; 29 | } 30 | 31 | public void setName(RoleName name) { 32 | this.name = name; 33 | } 34 | 35 | public Long getId() { 36 | return id; 37 | } 38 | 39 | public void setId(Long id) { 40 | this.id = id; 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/com/example/model/ClientModel.java: -------------------------------------------------------------------------------- 1 | package com.example.model; 2 | 3 | import org.springframework.validation.annotation.Validated; 4 | 5 | @Validated 6 | public class ClientModel { 7 | 8 | private String name; 9 | private double latitude; 10 | private double longitude; 11 | private String phoneNumber; 12 | 13 | public double getLatitude() { 14 | return latitude; 15 | } 16 | 17 | public void setLatitude(double latitude) { 18 | this.latitude = latitude; 19 | } 20 | 21 | public double getLongitude() { 22 | return longitude; 23 | } 24 | 25 | public void setLongitude(double longitude) { 26 | this.longitude = longitude; 27 | } 28 | 29 | public String getPhoneNumber() { 30 | return phoneNumber; 31 | } 32 | 33 | public void setPhoneNumber(String phoneNumber) { 34 | this.phoneNumber = phoneNumber; 35 | } 36 | 37 | public String getName() { 38 | return name; 39 | } 40 | 41 | public void setName(String name) { 42 | this.name = name; 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/com/example/util/Haversine.java: -------------------------------------------------------------------------------- 1 | package com.example.util; 2 | //this is a class based solution using haversine ,just another way to use it 3 | public class Haversine { 4 | 5 | private static final int EARTH_RADIUS = 6371; // Approx Earth radius in KM 6 | 7 | public static double distance(double startLat, double startLong, 8 | double endLat, double endLong) { 9 | 10 | double dLat = Math.toRadians((endLat - startLat)); 11 | double dLong = Math.toRadians((endLong - startLong)); 12 | 13 | startLat = Math.toRadians(startLat); 14 | endLat = Math.toRadians(endLat); 15 | 16 | double a = haversin(dLat) + Math.cos(startLat) * Math.cos(endLat) * haversin(dLong); 17 | double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); 18 | 19 | return EARTH_RADIUS * c; // <-- d 20 | } 21 | 22 | public static double haversin(double val) { 23 | return Math.pow(Math.sin(val / 2), 2); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/com/example/entity/base/BaseEntity.java: -------------------------------------------------------------------------------- 1 | package com.example.entity.base; 2 | 3 | import java.util.Date; 4 | 5 | import javax.persistence.GeneratedValue; 6 | import javax.persistence.GenerationType; 7 | import javax.persistence.Id; 8 | import javax.persistence.MappedSuperclass; 9 | import javax.validation.constraints.NotNull; 10 | 11 | import com.example.constant.Constants; 12 | 13 | @MappedSuperclass 14 | public abstract class BaseEntity { 15 | 16 | @NotNull 17 | private Date createdAt; 18 | @NotNull 19 | private boolean active; 20 | @Id 21 | @GeneratedValue(strategy = GenerationType.AUTO) 22 | protected Long id; 23 | 24 | public BaseEntity() { 25 | setStatus(Constants.ENTITY_STATUS_ACTIVE); 26 | createdAt = new Date(); 27 | } 28 | 29 | public Long getId() { 30 | return id; 31 | } 32 | 33 | public void setId(Long id) { 34 | this.id = id; 35 | } 36 | 37 | public void setStatus(boolean active) { 38 | this.active = active; 39 | } 40 | 41 | public boolean isActive() { 42 | return active; 43 | } 44 | 45 | public Date getCreatedAt() { 46 | return createdAt; 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/com/example/config/CORSFilter.java: -------------------------------------------------------------------------------- 1 | package com.example.config; 2 | 3 | 4 | import java.io.IOException; 5 | 6 | import javax.servlet.FilterChain; 7 | import javax.servlet.ServletException; 8 | import javax.servlet.http.HttpServletRequest; 9 | import javax.servlet.http.HttpServletResponse; 10 | 11 | import org.springframework.web.filter.OncePerRequestFilter; 12 | 13 | public class CORSFilter extends OncePerRequestFilter { 14 | 15 | @Override 16 | protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { 17 | response.addHeader("Access-Control-Allow-Origin", "*"); 18 | 19 | if (request.getHeader("Access-Control-Request-Method") != null && "OPTIONS".equals(request.getMethod())) { 20 | response.addHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE"); 21 | response.addHeader("Access-Control-Allow-Headers", "Authorization"); 22 | response.addHeader("Access-Control-Allow-Headers", "Content-Type"); 23 | response.addHeader("Access-Control-Max-Age", "1"); 24 | } 25 | 26 | filterChain.doFilter(request, response); 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/com/example/security/JwtAuthenticationEntryPoint.java: -------------------------------------------------------------------------------- 1 | package com.example.security; 2 | 3 | import java.io.IOException; 4 | 5 | import javax.servlet.ServletException; 6 | import javax.servlet.http.HttpServletRequest; 7 | import javax.servlet.http.HttpServletResponse; 8 | 9 | import org.slf4j.Logger; 10 | import org.slf4j.LoggerFactory; 11 | import org.springframework.security.core.AuthenticationException; 12 | import org.springframework.security.web.AuthenticationEntryPoint; 13 | import org.springframework.stereotype.Component; 14 | 15 | @Component 16 | public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint { 17 | 18 | private static final Logger logger = LoggerFactory.getLogger(JwtAuthenticationEntryPoint.class); 19 | 20 | @Override 21 | public void commence(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, 22 | AuthenticationException e) throws IOException, ServletException { 23 | logger.error("Responding with unauthorized error. Message - {}", e.getMessage()); 24 | httpServletResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED, 25 | "Sorry, You're not authorized to access this resource."); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/com/example/repository/ClientRepository.java: -------------------------------------------------------------------------------- 1 | package com.example.repository; 2 | 3 | import java.util.List; 4 | 5 | import org.springframework.data.jpa.repository.Query; 6 | import org.springframework.data.repository.PagingAndSortingRepository; 7 | import org.springframework.data.repository.query.Param; 8 | import org.springframework.stereotype.Repository; 9 | 10 | import com.example.entity.Client; 11 | 12 | @Repository 13 | public interface ClientRepository extends PagingAndSortingRepository { 14 | 15 | Boolean existsByPhoneNumber(String phoneNumber); 16 | 17 | Client findByPhoneNumber(String phoneNumber); 18 | 19 | List findAllByActive(boolean status); 20 | 21 | static String HAVERSINE_PART = "(6371 * acos(cos(radians(:latitude)) * cos(radians(c.latitude)) * cos(radians(c.longitude) - radians(:longitude)) + sin(radians(:latitude)) * sin(radians(c.latitude))))"; 22 | 23 | @Query("SELECT c FROM Client c WHERE " + HAVERSINE_PART + " < :distance ORDER BY " + HAVERSINE_PART + " DESC") 24 | public List findClientWithNearestLocation(@Param("latitude") double latitude, 25 | @Param("longitude") double longitude, @Param("distance") double distance); 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/com/example/demo/BasesProjectApplication.java: -------------------------------------------------------------------------------- 1 | package com.example.demo; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.EnableAutoConfiguration; 5 | import org.springframework.boot.autoconfigure.SpringBootApplication; 6 | import org.springframework.boot.autoconfigure.domain.EntityScan; 7 | import org.springframework.boot.autoconfigure.security.SecurityAutoConfiguration; 8 | import org.springframework.context.annotation.ComponentScan; 9 | import org.springframework.data.jpa.convert.threeten.Jsr310JpaConverters; 10 | import org.springframework.data.jpa.repository.config.EnableJpaRepositories; 11 | 12 | @SpringBootApplication(exclude = { SecurityAutoConfiguration.class }) 13 | @EnableAutoConfiguration 14 | @ComponentScan(basePackages = { "com.example.service", "com.example.model", "com.example.security","com.example.controller", 15 | "com.example.config" ,"com.example.response.base", "com.example.util", "com.example.service.impl" }) 16 | @EnableJpaRepositories("com.example.repository") 17 | @EntityScan(basePackageClasses = { Jsr310JpaConverters.class, BasesProjectApplication.class, }, basePackages = { 18 | "com.example.entity", "com.example.entity.base" }) 19 | public class BasesProjectApplication { 20 | 21 | public static void main(String[] args) { 22 | SpringApplication.run(BasesProjectApplication.class, args); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/com/example/entity/Client.java: -------------------------------------------------------------------------------- 1 | package com.example.entity; 2 | 3 | import java.io.Serializable; 4 | 5 | import javax.persistence.Column; 6 | import javax.persistence.Entity; 7 | import javax.persistence.Table; 8 | 9 | import com.example.entity.base.BaseEntity; 10 | 11 | @Entity 12 | @Table(name = "client") 13 | public class Client extends BaseEntity implements Serializable { 14 | 15 | private static final long serialVersionUID = 1L; 16 | 17 | @Column(name = "client_name") 18 | private String clientName; 19 | 20 | @Column(name = "latitude") 21 | private double latitude; 22 | 23 | @Column(name = "longitude") 24 | private double longitude; 25 | 26 | @Column(name = "phone_number") 27 | private String phoneNumber; 28 | 29 | 30 | public double getLatitude() { 31 | return latitude; 32 | } 33 | public void setLatitude(double latitude) { 34 | this.latitude = latitude; 35 | } 36 | public double getLongitude() { 37 | return longitude; 38 | } 39 | public void setLongitude(double longitude) { 40 | this.longitude = longitude; 41 | } 42 | public String getPhoneNumber() { 43 | return phoneNumber; 44 | } 45 | public void setPhoneNumber(String phoneNumber) { 46 | this.phoneNumber = phoneNumber; 47 | } 48 | public String getClientName() { 49 | return clientName; 50 | } 51 | public void setClientName(String clientName) { 52 | this.clientName = clientName; 53 | } 54 | 55 | 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/com/example/controller/AuthController.java: -------------------------------------------------------------------------------- 1 | package com.example.controller; 2 | 3 | import javax.servlet.http.HttpServletRequest; 4 | import javax.validation.Valid; 5 | 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.http.ResponseEntity; 8 | import org.springframework.security.access.prepost.PreAuthorize; 9 | import org.springframework.web.bind.annotation.RequestBody; 10 | import org.springframework.web.bind.annotation.RequestMapping; 11 | import org.springframework.web.bind.annotation.RequestMethod; 12 | import org.springframework.web.bind.annotation.RestController; 13 | 14 | import com.example.model.LoginModel; 15 | import com.example.model.SignUpModel; 16 | import com.example.response.base.BaseResponse; 17 | import com.example.service.AuthService; 18 | 19 | @RestController 20 | @RequestMapping(value = "/api/v1/auth") 21 | public class AuthController { 22 | 23 | @Autowired 24 | private AuthService authService; 25 | 26 | @RequestMapping(value = "/login", method = RequestMethod.POST) 27 | public ResponseEntity authenticateUser(@Valid @RequestBody LoginModel loginRequest, HttpServletRequest req) { 28 | 29 | return ResponseEntity.ok(authService.logIn(loginRequest, req)); 30 | } 31 | 32 | @RequestMapping(value = "/signup", method = RequestMethod.POST) 33 | public BaseResponse registerUser(@Valid @RequestBody SignUpModel signUpRequest) { 34 | return authService.signUp(signUpRequest); 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/com/example/security/CustomUserDetailService.java: -------------------------------------------------------------------------------- 1 | package com.example.security; 2 | 3 | import javax.persistence.EntityNotFoundException; 4 | import javax.transaction.Transactional; 5 | 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.security.core.userdetails.UserDetailsService; 8 | import org.springframework.security.core.userdetails.UsernameNotFoundException; 9 | import org.springframework.stereotype.Service; 10 | 11 | import com.example.entity.User; 12 | import com.example.exception.BadRequestException; 13 | import com.example.repository.UserRepository; 14 | 15 | @Service 16 | public class CustomUserDetailService implements UserDetailsService { 17 | 18 | @Autowired 19 | private UserRepository userRepository; 20 | 21 | @Override 22 | @Transactional 23 | public AuthenticatedUser loadUserByUsername(String usernameOrEmail) throws UsernameNotFoundException { 24 | // Let people login with either username or email 25 | User user = userRepository.findByUsernameOrEmail(usernameOrEmail, usernameOrEmail) 26 | .orElseThrow(() -> new UsernameNotFoundException("User not found with username : " + usernameOrEmail)); 27 | 28 | if (user == null) { 29 | throw new BadRequestException("the user cant be authenticated"); 30 | } 31 | return AuthenticatedUser.create(user); 32 | } 33 | 34 | @Transactional 35 | public AuthenticatedUser loadUserById(Long id) { 36 | 37 | User user = userRepository.findOne(id); 38 | if (user == null) { 39 | new EntityNotFoundException("User not found"); 40 | } 41 | return AuthenticatedUser.create(user); 42 | } 43 | } -------------------------------------------------------------------------------- /src/main/java/com/example/exception/ErrorsHandler.java: -------------------------------------------------------------------------------- 1 | package com.example.exception; 2 | 3 | import javax.persistence.EntityNotFoundException; 4 | 5 | import org.springframework.http.HttpStatus; 6 | import org.springframework.http.ResponseEntity; 7 | import org.springframework.web.bind.annotation.ControllerAdvice; 8 | import org.springframework.web.bind.annotation.ExceptionHandler; 9 | import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler; 10 | 11 | import com.example.response.base.BaseResponse; 12 | 13 | @ControllerAdvice 14 | public class ErrorsHandler extends ResponseEntityExceptionHandler { 15 | 16 | @ExceptionHandler(value = EntityNotFoundException.class) 17 | public ResponseEntity notFoundException(final NotFoundException e) { 18 | return ResponseEntity.status(HttpStatus.NOT_FOUND).body(BaseResponse.notFound(e.getMessage())); 19 | } 20 | 21 | @ExceptionHandler(value = BadRequestException.class) 22 | public ResponseEntity badRequest(final BadRequestException e) { 23 | return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(BaseResponse.failed(e.getMessage())); 24 | } 25 | 26 | @ExceptionHandler(value = EmptyFieldException.class) 27 | public ResponseEntity emptryFieldException(final EmptyFieldException e) { 28 | return ResponseEntity.badRequest().body(BaseResponse.failed(e.getMessage())); 29 | } 30 | 31 | @ExceptionHandler(value = AuthorizationException.class) 32 | public ResponseEntity authException(final AuthorizationException e) { 33 | return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(BaseResponse.unAuthorized(e.getMessage())); 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/com/example/util/CommonUtils.java: -------------------------------------------------------------------------------- 1 | package com.example.util; 2 | 3 | import java.util.ArrayList; 4 | 5 | import javax.servlet.http.HttpServletRequest; 6 | 7 | import org.springframework.util.StringUtils; 8 | 9 | import com.example.constant.RoleName; 10 | 11 | import io.jsonwebtoken.Claims; 12 | import io.jsonwebtoken.Jws; 13 | import io.jsonwebtoken.Jwts; 14 | 15 | public class CommonUtils { 16 | 17 | public static RoleName getRoleFromJWT(HttpServletRequest request) { 18 | String token = getJwtFromRequest(request); 19 | 20 | Jws claims = Jwts.parser().setSigningKey("JWTSuperSecretKey").parseClaimsJws(token); 21 | 22 | String userId = claims.getBody().get("id", String.class); 23 | ArrayList roleName = claims.getBody().get("Role", ArrayList.class); 24 | 25 | String rep = roleName.get(0).toString(); 26 | String roleNameS = rep.replace("{authority=", ""); 27 | String ro = roleNameS.substring(0, roleNameS.indexOf('}')); 28 | 29 | return RoleName.valueOf(ro); 30 | } 31 | 32 | public static long getIdFromJWT(HttpServletRequest request) { 33 | String token = getJwtFromRequest(request); 34 | 35 | Jws claims = Jwts.parser().setSigningKey("JWTSuperSecretKey").parseClaimsJws(token); 36 | 37 | String userId = claims.getBody().get("id", String.class); 38 | 39 | Long userIdLong = Long.parseLong(userId); 40 | 41 | return userIdLong; 42 | } 43 | 44 | public static String getJwtFromRequest(HttpServletRequest request) { 45 | String bearerToken = request.getHeader("Authorization"); 46 | if (StringUtils.hasText(bearerToken) && bearerToken.startsWith("Bearer ")) { 47 | return bearerToken.substring(7, bearerToken.length()); 48 | } 49 | return null; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/com/example/service/impl/AdminServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.example.service.impl; 2 | 3 | import javax.servlet.http.HttpServletRequest; 4 | 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.context.annotation.Bean; 7 | import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; 8 | import org.springframework.stereotype.Service; 9 | 10 | import com.example.constant.RoleName; 11 | import com.example.entity.Role; 12 | import com.example.entity.User; 13 | import com.example.exception.BadRequestException; 14 | import com.example.repository.RoleRepository; 15 | import com.example.repository.UserRepository; 16 | import com.example.response.base.BaseResponse; 17 | import com.example.service.AdminService; 18 | 19 | @Service 20 | public class AdminServiceImpl implements AdminService { 21 | @Autowired 22 | private UserRepository userRepo; 23 | 24 | @Autowired 25 | private BCryptPasswordEncoder passwordEncoder; 26 | 27 | @Autowired 28 | private RoleRepository roleRepo; 29 | 30 | @Bean 31 | public BCryptPasswordEncoder bryptPasswordEncoder() { 32 | return new BCryptPasswordEncoder(); 33 | } 34 | 35 | @Override 36 | public BaseResponse createDefaultAdmin(HttpServletRequest request) { 37 | 38 | User user = new User(); 39 | if (userRepo.count() == 0) { 40 | user.setEmail("admin@gmail.com"); 41 | user.setPassword(passwordEncoder.encode("123456789")); 42 | user.setUsername("mainAdmin"); 43 | user.setFirstName("Admin"); 44 | user.setLastName("Admin"); 45 | 46 | Role userRole = roleRepo.findByName(RoleName.ROLE_ADMIN) 47 | .orElseThrow(() -> new BadRequestException("User Role not set.")); 48 | 49 | user.setRole(userRole); 50 | userRepo.save(user); 51 | return BaseResponse.created("default admin created successfully"); 52 | } 53 | return BaseResponse.failed("a default admin already existed"); 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/com/example/response/base/ListResponse.java: -------------------------------------------------------------------------------- 1 | 2 | package com.example.response.base; 3 | 4 | import java.util.ArrayList; 5 | import java.util.List; 6 | 7 | import com.example.constant.ResponseCode; 8 | import com.example.constant.ResponseStatus; 9 | public class ListResponse extends BaseResponse { 10 | 11 | private int size; 12 | private List data; 13 | 14 | public ListResponse(String status, String code, String message , List data) { 15 | super(status, code, message); 16 | this.setData(data); 17 | this.setSize(data.size()); 18 | } 19 | 20 | private ListResponse(Builder builder) { 21 | super(builder); 22 | this.size = builder.size; 23 | this.data = builder.data; 24 | } 25 | 26 | public void setData(List data) { 27 | this.data = data; 28 | } 29 | 30 | public void setSize(int size) { 31 | this.size = size; 32 | } 33 | 34 | public int getSize() { 35 | return size; 36 | } 37 | 38 | public List getData() { 39 | return data; 40 | } 41 | 42 | public static Builder builder(){ 43 | return new Builder(); 44 | } 45 | 46 | private static class Builder extends BaseBuilder>{ 47 | private List data; 48 | private int size; 49 | 50 | public Builder data(Iterable data) { 51 | 52 | List list = new ArrayList<>(); 53 | for (T object : data) { 54 | list.add(object); 55 | } 56 | 57 | this.data = list; 58 | size = this.data.size(); 59 | return this; 60 | } 61 | 62 | public ListResponse build() { 63 | return new ListResponse(this); 64 | } 65 | 66 | @Override 67 | protected Builder getInstance() { 68 | return this; 69 | } 70 | } 71 | 72 | public static ListResponse found(Iterable data){ 73 | return (ListResponse) new Builder() 74 | .data(data) 75 | .code(ResponseCode.RESPONSE_CODE_SUCCESS) 76 | .status(ResponseStatus.RESPONSE_STATUS_SUCCESS) 77 | .message("Found") 78 | .build(); 79 | } 80 | 81 | } 82 | -------------------------------------------------------------------------------- /src/main/java/com/example/entity/User.java: -------------------------------------------------------------------------------- 1 | package com.example.entity; 2 | 3 | import java.io.Serializable; 4 | 5 | import javax.persistence.Column; 6 | import javax.persistence.Entity; 7 | import javax.persistence.FetchType; 8 | import javax.persistence.OneToOne; 9 | import javax.persistence.Table; 10 | 11 | import com.example.entity.base.BaseEntity; 12 | 13 | @Entity 14 | @Table(name = "user") 15 | public class User extends BaseEntity implements Serializable { 16 | 17 | /** 18 | * 19 | */ 20 | private static final long serialVersionUID = 1L; 21 | @Column(name = "user_name") 22 | private String username; 23 | 24 | @Column(name = "password") 25 | private String password; 26 | 27 | @Column(name = "email") 28 | private String email; 29 | 30 | @Column(name = "first_name") 31 | private String firstName; 32 | 33 | @Column(name = "last_name") 34 | private String lastName; 35 | 36 | @OneToOne(fetch = FetchType.LAZY) 37 | private Role role ; 38 | 39 | public String getUsername() { 40 | return username; 41 | } 42 | 43 | public void setUsername(String username) { 44 | this.username = username; 45 | } 46 | 47 | public String getPassword() { 48 | return password; 49 | } 50 | 51 | public void setPassword(String password) { 52 | this.password = password; 53 | } 54 | 55 | public String getEmail() { 56 | return email; 57 | } 58 | 59 | public void setEmail(String email) { 60 | this.email = email; 61 | } 62 | 63 | public String getFirstName() { 64 | return firstName; 65 | } 66 | 67 | public void setFirstName(String firstName) { 68 | this.firstName = firstName; 69 | } 70 | 71 | public String getLastName() { 72 | return lastName; 73 | } 74 | 75 | public void setLastName(String lastName) { 76 | this.lastName = lastName; 77 | } 78 | 79 | 80 | public User(String username, String password, String email) { 81 | super(); 82 | this.username = username; 83 | this.password = password; 84 | this.email = email; 85 | } 86 | 87 | public User() { 88 | // TODO Auto-generated constructor stub 89 | } 90 | 91 | public Role getRole() { 92 | return role; 93 | } 94 | 95 | public void setRole(Role role) { 96 | this.role = role; 97 | } 98 | 99 | } 100 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | com.example 8 | basesProject 9 | 0.0.1-SNAPSHOT 10 | jar 11 | 12 | basesProject 13 | Demo project for Spring Boot project with base and generic structure 14 | 15 | 16 | org.springframework.boot 17 | spring-boot-starter-parent 18 | 1.5.9.RELEASE 19 | 20 | 21 | 22 | 23 | UTF-8 24 | UTF-8 25 | 1.8 26 | 27 | 28 | 29 | 30 | org.springframework.boot 31 | spring-boot-starter-data-jpa 32 | 33 | 34 | org.springframework.boot 35 | spring-boot-starter-security 36 | 37 | 38 | org.springframework.boot 39 | spring-boot-starter-web 40 | 41 | 42 | 43 | mysql 44 | mysql-connector-java 45 | runtime 46 | 47 | 48 | 49 | org.springframework.boot 50 | spring-boot-starter-jdbc 51 | 52 | 53 | io.jsonwebtoken 54 | jjwt 55 | 0.6.0 56 | 57 | 58 | 59 | org.springframework.boot 60 | spring-boot-starter-test 61 | test 62 | 63 | 64 | org.springframework.security 65 | spring-security-test 66 | test 67 | 68 | 69 | 70 | 71 | 72 | 73 | org.springframework.boot 74 | spring-boot-maven-plugin 75 | 76 | 77 | 78 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /src/main/java/com/example/security/JwtAuthenticationFilter.java: -------------------------------------------------------------------------------- 1 | package com.example.security; 2 | 3 | import java.io.IOException; 4 | 5 | import javax.servlet.FilterChain; 6 | import javax.servlet.ServletException; 7 | import javax.servlet.http.HttpServletRequest; 8 | import javax.servlet.http.HttpServletResponse; 9 | 10 | import org.springframework.beans.factory.annotation.Autowired; 11 | import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; 12 | import org.springframework.security.core.context.SecurityContextHolder; 13 | import org.springframework.security.core.userdetails.UserDetails; 14 | import org.springframework.security.web.authentication.WebAuthenticationDetailsSource; 15 | import org.springframework.util.StringUtils; 16 | import org.springframework.web.filter.OncePerRequestFilter; 17 | 18 | import com.example.util.AppLogger; 19 | 20 | public class JwtAuthenticationFilter extends OncePerRequestFilter { 21 | 22 | @Autowired 23 | private JwtTokenProvider tokenProvider; 24 | 25 | @Autowired 26 | private CustomUserDetailService customUserDetailsService; 27 | 28 | 29 | @Override 30 | protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) 31 | throws ServletException, IOException { 32 | try { 33 | String jwt = getJwtFromRequest(request); 34 | 35 | if (StringUtils.hasText(jwt) && tokenProvider.validateToken(jwt)) { 36 | Long userId = tokenProvider.getUserIdFromJWT(jwt); 37 | 38 | /* 39 | * Note that you could also encode the user's username and roles inside JWT 40 | * claims and create the UserDetails object by parsing those claims from the 41 | * JWT. That would avoid the following database hit. It's completely up to you. 42 | */ 43 | UserDetails userDetails = customUserDetailsService.loadUserById(userId); 44 | UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken( 45 | userDetails, null, userDetails.getAuthorities()); 46 | authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); 47 | 48 | SecurityContextHolder.getContext().setAuthentication(authentication); 49 | } 50 | } catch (Exception ex) { 51 | AppLogger.getInstance().error("Could not set user authentication in security context", ex); 52 | } 53 | 54 | filterChain.doFilter(request, response); 55 | } 56 | 57 | private String getJwtFromRequest(HttpServletRequest request) { 58 | String bearerToken = request.getHeader("Authorization"); 59 | if (StringUtils.hasText(bearerToken) && bearerToken.startsWith("Bearer ")) { 60 | return bearerToken.substring(7, bearerToken.length()); 61 | } 62 | return null; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/main/java/com/example/security/JwtTokenProvider.java: -------------------------------------------------------------------------------- 1 | package com.example.security; 2 | 3 | import java.util.Date; 4 | 5 | import org.springframework.beans.factory.annotation.Value; 6 | import org.springframework.security.core.Authentication; 7 | import org.springframework.stereotype.Component; 8 | 9 | import com.example.exception.BadRequestException; 10 | import com.example.util.AppLogger; 11 | 12 | import io.jsonwebtoken.Claims; 13 | import io.jsonwebtoken.ExpiredJwtException; 14 | import io.jsonwebtoken.Jwts; 15 | import io.jsonwebtoken.MalformedJwtException; 16 | import io.jsonwebtoken.SignatureAlgorithm; 17 | import io.jsonwebtoken.SignatureException; 18 | import io.jsonwebtoken.UnsupportedJwtException; 19 | 20 | @Component 21 | public class JwtTokenProvider { 22 | 23 | @Value("${app.jwtSecret}") 24 | private String jwtSecret; 25 | 26 | @Value("${app.jwtExpirationInMs}") 27 | private int jwtExpirationInMs; 28 | 29 | public String generateToken(Authentication authentication) { 30 | 31 | AuthenticatedUser userPrincipal = (AuthenticatedUser) authentication.getPrincipal(); 32 | 33 | Date now = new Date(); 34 | Date expiryDate = new Date(now.getTime() + jwtExpirationInMs); 35 | 36 | return Jwts.builder().setSubject("Jwt Token").setIssuedAt(new Date()).setExpiration(expiryDate) 37 | .claim("id", Long.toString(userPrincipal.getId())).claim("Role", userPrincipal.getAuthorities()) 38 | .signWith(SignatureAlgorithm.HS512, jwtSecret).compact(); 39 | } 40 | 41 | public Long getUserIdFromJWT(String token) { 42 | Claims claims = Jwts.parser().setSigningKey(jwtSecret).parseClaimsJws(token).getBody(); 43 | 44 | String idString = claims.get("id", String.class); 45 | Long idLong = Long.valueOf(idString); 46 | return idLong; 47 | } 48 | 49 | public boolean validateToken(String authToken) { 50 | try { 51 | Jwts.parser().setSigningKey(jwtSecret).parseClaimsJws(authToken); 52 | return true; 53 | } catch (SignatureException ex) { 54 | AppLogger.getInstance().error("Invalid JWT signature"); 55 | throw new BadRequestException("Invalid JWT signature"); 56 | } catch (MalformedJwtException ex) { 57 | AppLogger.getInstance().error("Invalid JWT token"); 58 | throw new BadRequestException("Invalid JWT token"); 59 | } catch (ExpiredJwtException ex) { 60 | AppLogger.getInstance().error("Expired JWT token"); 61 | throw new BadRequestException("Expired Jwt Token"); 62 | } catch (UnsupportedJwtException ex) { 63 | AppLogger.getInstance().error("Unsupported JWT token"); 64 | throw new BadRequestException("Unsupported JWT token"); 65 | } catch (IllegalArgumentException ex) { 66 | AppLogger.getInstance().error("JWT claims string is empty."); 67 | } 68 | return false; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SpringBoot-Haversine-Jwt 2 | this repository contains a demonstration on how to use haversine formula to get the nearest locations to a given location with in distance ,also the project is built around jwt authentication and role based access authorization using spring boot framework ,please consider rating and leaving a start if you find it useful 3 | 4 | # What is Haversine Formula 5 | this is a formula that is used to calculate the distance between 2 location and it goes as the following : 6 | a = sin²(Δφ/2) + cos φ1 ⋅ cos φ2 ⋅ sin²(Δλ/2) 7 | c = 2 ⋅ atan2( √a, √(1−a) ) 8 | d = R ⋅ c 9 | where φ is latitude, λ is longitude, R is earth’s radius (mean radius = 6,371km); 10 | note that angles need to be in radians to pass to trig functions! 11 | 12 | # How Can We Make A good Use of it 13 | imagine you have a list of long and lat of locations in a database and a user provided you with his location ,using haver sine formula we can do magic, haver sine going to calculate the distance between the user location and a given point so we can then use it ,to display locations near user with in a radius . 14 | 15 | other use we can query directly to the data base using haversine forumla which mean we can retrive entites based on there locations with in distance from neareast to farthest using this magical query 16 | 17 | :boom::boom: 18 | ```java 19 | static String HAVERSINE_PART = "(6371 * acos(cos(radians(:latitude)) * cos(radians(c.latitude)) * cos(radians(c.longitude) - radians(:longitude)) + sin(radians(:latitude)) * sin(radians(c.latitude))))"; 20 | 21 | @Query("SELECT c FROM Client c WHERE " + HAVERSINE_PART + " < :distance ORDER BY " + HAVERSINE_PART + " DESC") 22 | public List findClientWithNearestLocation(@Param("latitude") double latitude, 23 | @Param("longitude") double longitude, @Param("distance") double distance); 24 | ```` 25 | # Jwt authentication And Role Based Access 26 | also in this repository you will find an insight on how to implement role based authorization and jwt athentication 27 | 28 | # What is Jwt Authentication ?! 29 | 30 | its an authentication mechanism based aroud if user is authenticated he/she will obtain an encrypted token and that token will be used to authenticate the user ,the user will provide the token on each request and the server will decide if its a valid token or not and then grant access for the user on that resource. 31 | 32 | we integrated role based access by putting the role of the user inside the token and then use spring security annotations such as @PreAuthorized("hasRole('ROLE-CUSTOMER')") to know whether the user is authorized to perform an action / get access to a specific end point 33 | 34 | please feel free to rate :star: happy programming :v: 35 | 36 | [![Tweet](https://img.shields.io/twitter/url/http/shields.io.svg?style=social)](https://twitter.com/intent/tweet) 37 | 38 | 39 | -------------------------------------------------------------------------------- /src/main/java/com/example/controller/ClientController.java: -------------------------------------------------------------------------------- 1 | package com.example.controller; 2 | 3 | import javax.servlet.http.HttpServletRequest; 4 | 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.security.access.prepost.PreAuthorize; 7 | import org.springframework.web.bind.annotation.PathVariable; 8 | import org.springframework.web.bind.annotation.RequestBody; 9 | import org.springframework.web.bind.annotation.RequestMapping; 10 | import org.springframework.web.bind.annotation.RequestMethod; 11 | import org.springframework.web.bind.annotation.RequestParam; 12 | import org.springframework.web.bind.annotation.RestController; 13 | 14 | import com.example.model.ClientModel; 15 | import com.example.response.base.BaseResponse; 16 | import com.example.service.ClientService; 17 | 18 | @RestController 19 | @RequestMapping(value = "/api/v1") 20 | public class ClientController { 21 | 22 | @Autowired 23 | private ClientService clientService; 24 | 25 | // only user logged in to the system can retrieve all clients 26 | @PreAuthorize("hasRole('ROLE_USER')") 27 | @RequestMapping(value = "/clients", method = RequestMethod.GET) 28 | public BaseResponse getAllClients() { 29 | return clientService.getAll(); 30 | } 31 | 32 | // only admin can create clients 33 | @PreAuthorize("hasRole('ROLE_ADMIN')") 34 | @RequestMapping(value = "/client", method = RequestMethod.POST) 35 | public BaseResponse createClient(@RequestBody ClientModel clientMdl) { 36 | return clientService.createClient(clientMdl); 37 | } 38 | 39 | @PreAuthorize("hasRole('ROLE_ADMIN')") 40 | @RequestMapping(value = "/client/{id}", method = RequestMethod.PUT) 41 | public BaseResponse updateClient(@RequestBody ClientModel clientMdl, @PathVariable long id, 42 | HttpServletRequest request) { 43 | return clientService.updateClient(id, clientMdl, request); 44 | } 45 | 46 | // only admin can delete clients 47 | @PreAuthorize("hasRole('ROLE_ADMIN')") 48 | @RequestMapping(value = "/client/{id}", method = RequestMethod.DELETE) 49 | public BaseResponse deleteClient(@PathVariable long id) { 50 | return clientService.deleteClient(id); 51 | } 52 | 53 | // only users and admin can get client by id 54 | @PreAuthorize("hasAnyRole('ROLE_ADMIN', 'ROLE_USER')") 55 | @RequestMapping(value = "/client/{id}", method = RequestMethod.GET) 56 | public BaseResponse getClient(@PathVariable long id) { 57 | return clientService.getById(id); 58 | } 59 | // only logged in user can get nearest client 60 | @PreAuthorize("hasAnyRole('ROLE_USER')") 61 | @RequestMapping(value = "/nearestClient", method = RequestMethod.GET) 62 | public BaseResponse getNearestClient(@RequestParam(value = "distance") double distance, 63 | @RequestParam(value = "longitude") double longitude, @RequestParam(value = "latitude") double latitude, 64 | HttpServletRequest request) { 65 | return clientService.findAllNearestClientWithIndistance(latitude ,longitude ,distance); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/main/java/com/example/response/base/SingleResponse.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018. Lorem ipsum dolor sit amet, consectetur adipiscing elit. 3 | * Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan. 4 | * Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna. 5 | * Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus. 6 | * Vestibulum commodo. Ut rhoncus gravida arcu. 7 | */ 8 | 9 | package com.example.response.base; 10 | 11 | import com.example.constant.ResponseCode; 12 | import com.example.constant.ResponseStatus; 13 | 14 | public class SingleResponse extends BaseResponse { 15 | 16 | private Object data; 17 | 18 | public SingleResponse(String status, String code, String message , Object data ) { 19 | super(status, code, message); 20 | this.setData(data); 21 | } 22 | 23 | private SingleResponse(Builder builder) { 24 | super(builder); 25 | this.data = builder.data; 26 | } 27 | 28 | public void setData(Object data) { 29 | this.data = data; 30 | } 31 | 32 | public Object getData() { 33 | return data; 34 | } 35 | 36 | public static Builder builder(){ 37 | return new Builder(); 38 | } 39 | 40 | 41 | public static class Builder extends BaseBuilder{ 42 | private Object data; 43 | 44 | public Builder data(Object data) { 45 | this.data = data; 46 | return this; 47 | } 48 | 49 | public Builder fromPrototype(SingleResponse prototype) { 50 | super.fromPrototype(prototype); 51 | data = prototype.data; 52 | return this; 53 | } 54 | 55 | public SingleResponse build() { 56 | return new SingleResponse(this); 57 | } 58 | 59 | @Override 60 | protected Builder getInstance() { 61 | return this; 62 | } 63 | } 64 | 65 | public static SingleResponse found(Object data){ 66 | return (SingleResponse) builder() 67 | .data(data) 68 | .code(ResponseCode.RESPONSE_CODE_SUCCESS) 69 | .status(ResponseStatus.RESPONSE_STATUS_SUCCESS) 70 | .message("Found") 71 | .build(); 72 | } 73 | 74 | public static SingleResponse create(Object data){ 75 | return (SingleResponse) builder() 76 | .data(data) 77 | .code(ResponseCode.RESPONSE_CODE_CREATED) 78 | .status(ResponseStatus.RESPONSE_STATUS_SUCCESS) 79 | .message("Created") 80 | .build(); 81 | } 82 | 83 | 84 | public static BaseResponse updated(Object data) { 85 | return (SingleResponse) builder() 86 | .data(data) 87 | .code(ResponseCode.RESPONSE_CODE_SUCCESS) 88 | .status(ResponseStatus.RESPONSE_STATUS_SUCCESS) 89 | .message("Updated") 90 | .build(); 91 | } 92 | 93 | public static SingleResponse notFound(){ 94 | return (SingleResponse) builder() 95 | .data(null) 96 | .code(ResponseCode.RESPONSE_CODE_SUCCESS) 97 | .status(ResponseStatus.RESPONSE_STATUS_SUCCESS) 98 | .message("Not Found") 99 | .build(); 100 | } 101 | 102 | } 103 | -------------------------------------------------------------------------------- /src/main/java/com/example/config/SecurityConfig.java: -------------------------------------------------------------------------------- 1 | package com.example.config; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.context.annotation.Bean; 5 | import org.springframework.context.annotation.Configuration; 6 | import org.springframework.security.authentication.AuthenticationManager; 7 | import org.springframework.security.config.BeanIds; 8 | import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; 9 | import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; 10 | import org.springframework.security.config.annotation.web.builders.HttpSecurity; 11 | import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; 12 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; 13 | import org.springframework.security.config.http.SessionCreationPolicy; 14 | import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; 15 | import org.springframework.security.crypto.password.PasswordEncoder; 16 | import org.springframework.security.web.access.channel.ChannelProcessingFilter; 17 | import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; 18 | 19 | import com.example.security.CustomUserDetailService; 20 | import com.example.security.JwtAuthenticationEntryPoint; 21 | import com.example.security.JwtAuthenticationFilter; 22 | 23 | @Configuration 24 | @EnableWebSecurity 25 | @EnableGlobalMethodSecurity(securedEnabled = true, jsr250Enabled = true, prePostEnabled = true) 26 | public class SecurityConfig extends WebSecurityConfigurerAdapter { 27 | 28 | @Autowired 29 | private CustomUserDetailService customUserDetailsService; 30 | 31 | @Bean 32 | public PasswordEncoder passwordEncoder() { 33 | return new BCryptPasswordEncoder(); 34 | } 35 | 36 | @Autowired 37 | private JwtAuthenticationEntryPoint unauthorizedHandler; 38 | 39 | @Bean 40 | public JwtAuthenticationFilter jwtAuthenticationFilter() { 41 | return new JwtAuthenticationFilter(); 42 | } 43 | 44 | @Override 45 | public void configure(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception { 46 | authenticationManagerBuilder.userDetailsService(customUserDetailsService).passwordEncoder(passwordEncoder()); 47 | } 48 | 49 | @Bean(BeanIds.AUTHENTICATION_MANAGER) 50 | @Override 51 | public AuthenticationManager authenticationManagerBean() throws Exception { 52 | return super.authenticationManagerBean(); 53 | } 54 | 55 | @Override 56 | protected void configure(HttpSecurity http) throws Exception { 57 | http.cors().and().csrf().disable().exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and() 58 | .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and().authorizeRequests() 59 | .antMatchers("/", "/favicon.ico").permitAll().antMatchers("/api/v1/auth/**").permitAll() 60 | .antMatchers("/api/v1/admin").permitAll() 61 | // .antMatchers("/api/v1/client/*").permitAll() 62 | 63 | .anyRequest().authenticated(); 64 | // adding CORSFilter 65 | http.addFilterBefore(new CORSFilter(), ChannelProcessingFilter.class); 66 | // Add our custom JWT security filter 67 | http.addFilterBefore(jwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class); 68 | } 69 | 70 | } 71 | -------------------------------------------------------------------------------- /src/main/java/com/example/security/AuthenticatedUser.java: -------------------------------------------------------------------------------- 1 | package com.example.security; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Collection; 5 | import java.util.List; 6 | import java.util.Objects; 7 | import java.util.stream.Collectors; 8 | 9 | import org.springframework.security.core.GrantedAuthority; 10 | import org.springframework.security.core.authority.SimpleGrantedAuthority; 11 | import org.springframework.security.core.userdetails.UserDetails; 12 | 13 | import com.example.entity.Role; 14 | import com.example.entity.User; 15 | 16 | /* 17 | * created by Ala'a Mezian 18 | */ 19 | 20 | public class AuthenticatedUser implements UserDetails { 21 | 22 | private static final long serialVersionUID = 2245251454156719626L; 23 | 24 | private Long id; 25 | private String username; 26 | private String password; 27 | private String email; 28 | private Long refrencedId; 29 | private Collection authorities; 30 | 31 | public AuthenticatedUser(Long id, String username, String email, String password, 32 | Collection authorities) { 33 | this.id = id; 34 | this.username = username; 35 | this.password = password; 36 | this.setEmail(email); 37 | this.authorities = authorities; 38 | 39 | } 40 | 41 | public static AuthenticatedUser create(User user) { 42 | List roles = new ArrayList<>(); 43 | roles.add(user.getRole()); 44 | List authorities = roles.stream() 45 | .map(role -> new SimpleGrantedAuthority(role.getName().name())).collect(Collectors.toList()); 46 | 47 | return new AuthenticatedUser(user.getId(), user.getUsername(), user.getEmail(), user.getPassword(), 48 | authorities); 49 | } 50 | 51 | public void setRefrencedId(long refrencedId) { 52 | this.refrencedId = refrencedId; 53 | } 54 | 55 | public Long getId() { 56 | return id; 57 | } 58 | 59 | public Long getRefrencedId() { 60 | return refrencedId; 61 | } 62 | 63 | public void setRefrencedId(Long refrencedId) { 64 | this.refrencedId = refrencedId; 65 | } 66 | 67 | public void setId(Long id) { 68 | this.id = id; 69 | } 70 | 71 | @Override 72 | public String getUsername() { 73 | return username; 74 | } 75 | 76 | @Override 77 | public String getPassword() { 78 | return password; 79 | } 80 | 81 | @Override 82 | public Collection getAuthorities() { 83 | return authorities; 84 | } 85 | 86 | @Override 87 | public boolean isAccountNonExpired() { 88 | return true; 89 | } 90 | 91 | @Override 92 | public boolean isAccountNonLocked() { 93 | return true; 94 | } 95 | 96 | @Override 97 | public boolean isCredentialsNonExpired() { 98 | return true; 99 | } 100 | 101 | @Override 102 | public boolean isEnabled() { 103 | return true; 104 | } 105 | 106 | @Override 107 | public boolean equals(Object o) { 108 | if (this == o) 109 | return true; 110 | if (o == null || getClass() != o.getClass()) 111 | return false; 112 | AuthenticatedUser that = (AuthenticatedUser) o; 113 | return Objects.equals(id, that.id); 114 | } 115 | 116 | @Override 117 | public int hashCode() { 118 | 119 | return Objects.hash(id); 120 | } 121 | 122 | public String getEmail() { 123 | return email; 124 | } 125 | 126 | public void setEmail(String email) { 127 | this.email = email; 128 | } 129 | 130 | } 131 | -------------------------------------------------------------------------------- /src/main/java/com/example/response/base/BaseResponse.java: -------------------------------------------------------------------------------- 1 | 2 | package com.example.response.base; 3 | 4 | import com.example.constant.ResponseCode; 5 | import com.example.constant.ResponseStatus; 6 | 7 | public class BaseResponse { 8 | 9 | protected String status; 10 | protected String code; 11 | protected String message; 12 | 13 | public BaseResponse(String status, String code, String message) { 14 | this.setStatus(status); 15 | this.setCode(code); 16 | this.setMessage(message); 17 | } 18 | 19 | protected BaseResponse(BaseBuilder builder) { 20 | this.status = builder.status; 21 | this.code = builder.code; 22 | this.message = builder.message; 23 | } 24 | 25 | public void setStatus(String status) { 26 | this.status = status; 27 | } 28 | 29 | public void setCode(String code) { 30 | this.code = code; 31 | } 32 | 33 | public void setMessage(String message) { 34 | this.message = message; 35 | } 36 | 37 | public String getStatus() { 38 | return status; 39 | } 40 | 41 | public String getCode() { 42 | return code; 43 | } 44 | 45 | public String getMessage() { 46 | return message; 47 | } 48 | 49 | public static abstract class BaseBuilder { 50 | public String status; 51 | public String code; 52 | public String message; 53 | 54 | public T status(String status) { 55 | this.status = status; 56 | return getInstance(); 57 | } 58 | 59 | public T code(String code) { 60 | this.code = code; 61 | return getInstance(); 62 | } 63 | 64 | public T message(String message) { 65 | this.message = message; 66 | return getInstance(); 67 | } 68 | 69 | public T fromPrototype(BaseResponse prototype) { 70 | status = prototype.status; 71 | code = prototype.code; 72 | message = prototype.message; 73 | return getInstance(); 74 | } 75 | 76 | protected abstract T getInstance(); 77 | 78 | public BaseResponse baseBuild() { 79 | return new BaseResponse(this); 80 | } 81 | 82 | } 83 | 84 | public static BaseResponse unAuthorized(String msg) { 85 | return new BaseResponse(ResponseStatus.RESPONSE_STATUS_FAILED, ResponseCode.RESPONSE_CODE_UNAUTHORIZED, msg); 86 | } 87 | 88 | public static BaseResponse forbidden() { 89 | return new BaseResponse(ResponseStatus.RESPONSE_STATUS_FAILED, ResponseCode.RESPONSE_CODE_FORBIDDEN, 90 | "Forbidden"); 91 | } 92 | 93 | public static BaseResponse notFound() { 94 | return new BaseResponse(ResponseStatus.RESPONSE_STATUS_FAILED, ResponseCode.RESPONSE_CODE_NOT_FOUND, 95 | "Sorry Not Found"); 96 | } 97 | 98 | 99 | public static BaseResponse notFound(String fieldName) { 100 | return new BaseResponse(ResponseStatus.RESPONSE_STATUS_FAILED, ResponseCode.RESPONSE_CODE_NOT_FOUND, fieldName); 101 | } 102 | 103 | public static BaseResponse noContent() { 104 | return new BaseResponse(ResponseStatus.RESPONSE_STATUS_SUCCESS, ResponseCode.NO_CONTENT, "No Content"); 105 | } 106 | 107 | public static BaseResponse failed(String message) { 108 | return new BaseResponse(ResponseStatus.RESPONSE_STATUS_FAILED, ResponseCode.RESPONSE_CODE_BAD_REQUEST, message); 109 | } 110 | 111 | public static BaseResponse success(String message) { 112 | return new BaseResponse(ResponseStatus.RESPONSE_STATUS_SUCCESS, ResponseCode.RESPONSE_CODE_SUCCESS, message); 113 | } 114 | 115 | public static BaseResponse created(String message) { 116 | return new BaseResponse(ResponseStatus.RESPONSE_STATUS_SUCCESS, ResponseCode.RESPONSE_CODE_CREATED, message); 117 | } 118 | 119 | } 120 | -------------------------------------------------------------------------------- /src/main/java/com/example/service/impl/AuthServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.example.service.impl; 2 | 3 | import static com.example.util.CommonsValidator.isValidUserName; 4 | import static com.example.util.CommonsValidator.validateEmail; 5 | import static com.example.util.CommonsValidator.validatePassword; 6 | import static com.example.util.CommonsValidator.validateString; 7 | 8 | import javax.servlet.http.HttpServletRequest; 9 | 10 | import org.springframework.beans.factory.annotation.Autowired; 11 | import org.springframework.context.annotation.Lazy; 12 | import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; 13 | import org.springframework.security.core.Authentication; 14 | import org.springframework.security.core.context.SecurityContextHolder; 15 | import org.springframework.security.crypto.password.PasswordEncoder; 16 | import org.springframework.stereotype.Service; 17 | 18 | import com.example.constant.RoleName; 19 | import com.example.entity.Role; 20 | import com.example.entity.User; 21 | import com.example.exception.BadRequestException; 22 | import com.example.model.LoginModel; 23 | import com.example.model.SignUpModel; 24 | import com.example.repository.RoleRepository; 25 | import com.example.repository.UserRepository; 26 | import com.example.response.base.BaseResponse; 27 | import com.example.response.base.JwtAuthenticationResponse; 28 | import com.example.security.AuthenticatedUser; 29 | import com.example.security.JwtTokenProvider; 30 | import com.example.service.AuthService; 31 | import org.springframework.security.authentication.AuthenticationManager; 32 | 33 | @Service 34 | public class AuthServiceImpl implements AuthService { 35 | 36 | @Autowired 37 | UserRepository userRepository; 38 | 39 | @Autowired 40 | RoleRepository roleRepository; 41 | 42 | // instantiating a bean to use password encoder 43 | @Autowired 44 | @Lazy 45 | private PasswordEncoder passwordEncoder; 46 | 47 | @Autowired 48 | AuthenticationManager authenticationManager; 49 | 50 | @Autowired 51 | JwtTokenProvider tokenProvider; 52 | 53 | @Override 54 | public BaseResponse signUp(SignUpModel signUpRequest) { 55 | 56 | validatePassword(signUpRequest.getPassword(), "password"); 57 | isValidUserName(signUpRequest.getUsername()); 58 | validateEmail(signUpRequest.getEmail()); 59 | if (userRepository.existsByUsername(signUpRequest.getUsername())) { 60 | throw new BadRequestException("UserName is already taken!"); 61 | } 62 | if (userRepository.existsByEmail(signUpRequest.getEmail())) { 63 | throw new BadRequestException("email is already taken !"); 64 | } 65 | 66 | // Creating user's account 67 | User user = new User(signUpRequest.getUsername(), signUpRequest.getPassword(), signUpRequest.getEmail()); 68 | 69 | user.setPassword(passwordEncoder.encode(user.getPassword())); 70 | 71 | Role userRole = roleRepository.findByName(RoleName.ROLE_USER) 72 | .orElseThrow(() -> new BadRequestException("User Role not set.")); 73 | 74 | user.setRole(userRole); 75 | 76 | userRepository.save(user); 77 | return BaseResponse.created("user signed Up Successfully"); 78 | 79 | } 80 | 81 | @Override 82 | public JwtAuthenticationResponse logIn(LoginModel loginRequest, HttpServletRequest req) { 83 | validateString(loginRequest.getUsernameOrEmail(), "usernameOrEmail"); 84 | Authentication authentication; 85 | try { 86 | authentication = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken( 87 | loginRequest.getUsernameOrEmail(), loginRequest.getPassword())); 88 | } catch (Exception e) { 89 | e.printStackTrace(); 90 | throw new BadRequestException("Bad Credintials"); 91 | } 92 | 93 | SecurityContextHolder.getContext().setAuthentication(authentication); 94 | 95 | // from the authenticated user we can access all current authenticated user data 96 | // such as id for example 97 | Object userPrinciple = SecurityContextHolder.getContext().getAuthentication().getPrincipal(); 98 | AuthenticatedUser user = ((AuthenticatedUser) userPrinciple); 99 | 100 | String jwt = tokenProvider.generateToken(authentication); 101 | return new JwtAuthenticationResponse(jwt); 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /src/main/java/com/example/util/AppLogger.java: -------------------------------------------------------------------------------- 1 | package com.example.util; 2 | 3 | 4 | import org.slf4j.Logger; 5 | import org.slf4j.LoggerFactory; 6 | 7 | import com.example.constant.Constants; 8 | 9 | 10 | public class AppLogger { 11 | 12 | 13 | /** The app logger. */ 14 | private static AppLogger appLogger = null; 15 | 16 | /** The logger. */ 17 | private static Logger logger = null; 18 | 19 | /** The stack trace level. */ 20 | private static int stackTraceLevel = 4; 21 | 22 | /** 23 | * Instantiates a new application logger. 24 | */ 25 | private AppLogger() { 26 | logger = LoggerFactory.getLogger(AppLogger.class); 27 | } 28 | 29 | /** 30 | * Gets the single instance of ApplicationLogger. 31 | * 32 | * @return single instance of ApplicationLogger 33 | */ 34 | public static AppLogger getInstance() { 35 | if (appLogger == null) { 36 | synchronized (AppLogger.class) { 37 | if (appLogger == null) { 38 | appLogger = new AppLogger(); 39 | } 40 | } 41 | } 42 | return appLogger; 43 | } 44 | 45 | /** 46 | * Gets the class name. 47 | * 48 | * @return the class name 49 | */ 50 | private String getClassName() { 51 | String className = Constants.BLANK; 52 | try { 53 | className = Thread.currentThread().getStackTrace()[stackTraceLevel] 54 | .getClassName(); 55 | } catch (Exception e) { 56 | e.printStackTrace(); 57 | } 58 | return className; 59 | } 60 | 61 | /** 62 | * Gets the method name. 63 | * 64 | * @return the method name 65 | */ 66 | private String getMethodName() { 67 | String methodName = Constants.BLANK; 68 | try { 69 | methodName = Thread.currentThread().getStackTrace()[stackTraceLevel] 70 | .getMethodName(); 71 | } catch (Exception e) { 72 | e.printStackTrace(); 73 | } 74 | return methodName; 75 | } 76 | 77 | /** 78 | * Gets the base message. 79 | * 80 | * @param message the message 81 | * @return the base message 82 | */ 83 | private String getBaseMessage(String message) { 84 | String logMsg = getClassName() + Constants.COLON + getMethodName() + Constants.DASH + message; 85 | return logMsg; 86 | } 87 | 88 | /** 89 | * Entry. 90 | */ 91 | public void entry() { 92 | logger.info(getBaseMessage(Constants.ENTRY)); 93 | } 94 | 95 | /** 96 | * Exit. 97 | */ 98 | public void exit() { 99 | logger.info(getBaseMessage(Constants.EXIT)); 100 | } 101 | 102 | /** 103 | * Info. 104 | * 105 | * @param message the message 106 | */ 107 | public void info(String message) { 108 | logger.info(getBaseMessage(message)); 109 | } 110 | 111 | /** 112 | * Info. 113 | * 114 | * @param message the message 115 | * @param objects the objects 116 | */ 117 | public void info(String message, Object...objects) { 118 | logger.info(getBaseMessage(message), objects); 119 | } 120 | 121 | /** 122 | * Warn. 123 | * 124 | * @param message the message 125 | */ 126 | public void warn(String message) { 127 | logger.warn(getBaseMessage(message)); 128 | } 129 | 130 | /** 131 | * Warn. 132 | * 133 | * @param message the message 134 | * @param objects the objects 135 | */ 136 | public void warn(String message, Object... objects) { 137 | logger.warn(getBaseMessage(message), objects); 138 | } 139 | 140 | /** 141 | * Warn. 142 | * 143 | * @param message the message 144 | * @param t the t 145 | */ 146 | public void warn(String message, Throwable t) { 147 | logger.warn(getBaseMessage(message), t); 148 | } 149 | 150 | /** 151 | * Debug. 152 | * 153 | * @param message the message 154 | */ 155 | public void debug(String message) { 156 | logger.debug(getBaseMessage(message)); 157 | } 158 | 159 | /** 160 | * Debug. 161 | * 162 | * @param message the message 163 | * @param objects the objects 164 | */ 165 | public void debug(String message, Object... objects) { 166 | logger.debug(getBaseMessage(message), objects); 167 | } 168 | 169 | /** 170 | * Debug. 171 | * 172 | * @param message the message 173 | * @param t the t 174 | */ 175 | public void debug(String message, Throwable t) { 176 | logger.debug(getBaseMessage(message),t); 177 | } 178 | 179 | /** 180 | * Error. 181 | * 182 | * @param message the message 183 | */ 184 | public void error(String message) { 185 | logger.error(getBaseMessage(message)); 186 | } 187 | 188 | /** 189 | * Error. 190 | * 191 | * @param message the message 192 | * @param objects the objects 193 | */ 194 | public void error(String message, Object... objects) { 195 | logger.error(getBaseMessage(message), objects); 196 | } 197 | 198 | /** 199 | * Error. 200 | * 201 | * @param message the message 202 | * @param t the t 203 | */ 204 | public void error(String message, Throwable t) { 205 | logger.error(getBaseMessage(message), t); 206 | } 207 | 208 | } 209 | 210 | -------------------------------------------------------------------------------- /mvnw.cmd: -------------------------------------------------------------------------------- 1 | @REM ---------------------------------------------------------------------------- 2 | @REM Licensed to the Apache Software Foundation (ASF) under one 3 | @REM or more contributor license agreements. See the NOTICE file 4 | @REM distributed with this work for additional information 5 | @REM regarding copyright ownership. The ASF licenses this file 6 | @REM to you under the Apache License, Version 2.0 (the 7 | @REM "License"); you may not use this file except in compliance 8 | @REM with the License. You may obtain a copy of the License at 9 | @REM 10 | @REM http://www.apache.org/licenses/LICENSE-2.0 11 | @REM 12 | @REM Unless required by applicable law or agreed to in writing, 13 | @REM software distributed under the License is distributed on an 14 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | @REM KIND, either express or implied. See the License for the 16 | @REM specific language governing permissions and limitations 17 | @REM under the License. 18 | @REM ---------------------------------------------------------------------------- 19 | 20 | @REM ---------------------------------------------------------------------------- 21 | @REM Maven2 Start Up Batch script 22 | @REM 23 | @REM Required ENV vars: 24 | @REM JAVA_HOME - location of a JDK home dir 25 | @REM 26 | @REM Optional ENV vars 27 | @REM M2_HOME - location of maven2's installed home dir 28 | @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands 29 | @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending 30 | @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven 31 | @REM e.g. to debug Maven itself, use 32 | @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 33 | @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files 34 | @REM ---------------------------------------------------------------------------- 35 | 36 | @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' 37 | @echo off 38 | @REM enable echoing my setting MAVEN_BATCH_ECHO to 'on' 39 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% 40 | 41 | @REM set %HOME% to equivalent of $HOME 42 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") 43 | 44 | @REM Execute a user defined script before this one 45 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre 46 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending 47 | if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" 48 | if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" 49 | :skipRcPre 50 | 51 | @setlocal 52 | 53 | set ERROR_CODE=0 54 | 55 | @REM To isolate internal variables from possible post scripts, we use another setlocal 56 | @setlocal 57 | 58 | @REM ==== START VALIDATION ==== 59 | if not "%JAVA_HOME%" == "" goto OkJHome 60 | 61 | echo. 62 | echo Error: JAVA_HOME not found in your environment. >&2 63 | echo Please set the JAVA_HOME variable in your environment to match the >&2 64 | echo location of your Java installation. >&2 65 | echo. 66 | goto error 67 | 68 | :OkJHome 69 | if exist "%JAVA_HOME%\bin\java.exe" goto init 70 | 71 | echo. 72 | echo Error: JAVA_HOME is set to an invalid directory. >&2 73 | echo JAVA_HOME = "%JAVA_HOME%" >&2 74 | echo Please set the JAVA_HOME variable in your environment to match the >&2 75 | echo location of your Java installation. >&2 76 | echo. 77 | goto error 78 | 79 | @REM ==== END VALIDATION ==== 80 | 81 | :init 82 | 83 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn". 84 | @REM Fallback to current working directory if not found. 85 | 86 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% 87 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir 88 | 89 | set EXEC_DIR=%CD% 90 | set WDIR=%EXEC_DIR% 91 | :findBaseDir 92 | IF EXIST "%WDIR%"\.mvn goto baseDirFound 93 | cd .. 94 | IF "%WDIR%"=="%CD%" goto baseDirNotFound 95 | set WDIR=%CD% 96 | goto findBaseDir 97 | 98 | :baseDirFound 99 | set MAVEN_PROJECTBASEDIR=%WDIR% 100 | cd "%EXEC_DIR%" 101 | goto endDetectBaseDir 102 | 103 | :baseDirNotFound 104 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR% 105 | cd "%EXEC_DIR%" 106 | 107 | :endDetectBaseDir 108 | 109 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig 110 | 111 | @setlocal EnableExtensions EnableDelayedExpansion 112 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a 113 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% 114 | 115 | :endReadAdditionalConfig 116 | 117 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" 118 | 119 | set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" 120 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 121 | 122 | %MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* 123 | if ERRORLEVEL 1 goto error 124 | goto end 125 | 126 | :error 127 | set ERROR_CODE=1 128 | 129 | :end 130 | @endlocal & set ERROR_CODE=%ERROR_CODE% 131 | 132 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost 133 | @REM check for post script, once with legacy .bat ending and once with .cmd ending 134 | if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" 135 | if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" 136 | :skipRcPost 137 | 138 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' 139 | if "%MAVEN_BATCH_PAUSE%" == "on" pause 140 | 141 | if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% 142 | 143 | exit /B %ERROR_CODE% 144 | -------------------------------------------------------------------------------- /src/main/java/com/example/service/impl/ClientServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.example.service.impl; 2 | 3 | import static com.example.util.CommonsValidator.notEmpty; 4 | import static com.example.util.CommonsValidator.validateEntity; 5 | import static com.example.util.CommonsValidator.validateName; 6 | import static com.example.util.CommonsValidator.validateNumber; 7 | 8 | import java.util.ArrayList; 9 | import java.util.Date; 10 | import java.util.List; 11 | 12 | import javax.servlet.http.HttpServletRequest; 13 | 14 | import org.springframework.beans.factory.annotation.Autowired; 15 | import org.springframework.stereotype.Service; 16 | 17 | import com.example.constant.Constants; 18 | import com.example.entity.Client; 19 | import com.example.exception.AuthorizationException; 20 | import com.example.exception.BadRequestException; 21 | import com.example.model.ClientModel; 22 | import com.example.repository.ClientRepository; 23 | import com.example.response.base.BaseResponse; 24 | import com.example.response.base.ListResponse; 25 | import com.example.response.base.SingleResponse; 26 | import com.example.service.ClientService; 27 | import com.example.util.CommonUtils; 28 | import com.example.util.Haversine; 29 | 30 | @Service 31 | public class ClientServiceImpl implements ClientService { 32 | 33 | @Autowired 34 | private ClientRepository clientRepo; 35 | 36 | @Override 37 | public BaseResponse createClient(ClientModel clientMdl) { 38 | validateName(clientMdl.getName()); 39 | validateNumber(clientMdl.getLatitude(), "latitude"); 40 | validateNumber(clientMdl.getLongitude(), "longitude"); 41 | if (clientRepo.existsByPhoneNumber(clientMdl.getPhoneNumber())) { 42 | throw new BadRequestException("client with this phone number is already existed"); 43 | } 44 | try { 45 | Client client = new Client(); 46 | client.setClientName(clientMdl.getName()); 47 | client.setLatitude(clientMdl.getLatitude()); 48 | client.setLongitude(clientMdl.getLongitude()); 49 | client.setPhoneNumber(clientMdl.getPhoneNumber()); 50 | clientRepo.save(client); 51 | } catch (Exception e) { 52 | e.printStackTrace(); 53 | } 54 | return BaseResponse.created("client created succesfully"); 55 | } 56 | 57 | @Override 58 | public BaseResponse updateClient(long id, ClientModel clientMdl, HttpServletRequest request) { 59 | Client client = clientRepo.findOne(id); 60 | validateEntity(client, "client"); 61 | long idFromToken = CommonUtils.getIdFromJWT(request); 62 | // to ensure the this update is done by the record owner 63 | // if (idFromToken != client.getId()) { 64 | // throw new AuthorizationException("Sorry you are not authorized to perform this action"); 65 | // } 66 | 67 | if (notEmpty(clientMdl.getName())) { 68 | validateName(clientMdl.getName()); 69 | client.setClientName(clientMdl.getName()); 70 | } 71 | if (notEmpty(clientMdl.getLongitude())) { 72 | validateNumber(clientMdl.getLongitude(), "longitude"); 73 | client.setLongitude(clientMdl.getLongitude()); 74 | } 75 | if (notEmpty(clientMdl.getLatitude())) { 76 | validateNumber(clientMdl.getLatitude(), "latitude"); 77 | client.setLatitude(clientMdl.getLatitude()); 78 | } 79 | // phone number is unique 80 | if (notEmpty(clientMdl.getPhoneNumber())) { 81 | if (clientRepo.existsByPhoneNumber(clientMdl.getPhoneNumber())) { 82 | Client clinetFromDataBase = clientRepo.findByPhoneNumber(clientMdl.getPhoneNumber()); 83 | if (clinetFromDataBase != client) { 84 | throw new BadRequestException("a user with this phone number is already exist"); 85 | } 86 | } 87 | clientMdl.setPhoneNumber(clientMdl.getPhoneNumber()); 88 | } 89 | clientRepo.save(client); 90 | return SingleResponse.updated(client); 91 | } 92 | 93 | @Override 94 | public BaseResponse deleteClient(long id) { 95 | Client client = clientRepo.findOne(id); 96 | validateEntity(client, "Client"); 97 | client.setStatus(Constants.ENTITY_STATUS_NOT_ACTIVE); 98 | clientRepo.save(client); 99 | return BaseResponse.success("client deleted succesfully"); 100 | } 101 | 102 | @Override 103 | public BaseResponse getAll() { 104 | 105 | List clients = clientRepo.findAllByActive(true); 106 | 107 | if (clients.size() == 0) 108 | return BaseResponse.noContent(); 109 | 110 | return ListResponse.found(clients); 111 | } 112 | 113 | @Override 114 | public BaseResponse getById(long id) { 115 | Client client = clientRepo.findOne(id); 116 | validateEntity(client, "client"); 117 | return SingleResponse.found(client); 118 | } 119 | 120 | @Override 121 | public BaseResponse findAllNearestClientWithIndistance(double latitude, double longtitude, double distance) { 122 | // we can do this in 2 way and i am going to demonstrate each one 123 | longtitude = checkLng(longtitude); 124 | latitude = checkLat(latitude); 125 | 126 | // first get nearest client to a user location with in distance from the data 127 | // base directly 128 | // apply haversine formula as a JPQL in the repository and that will return 129 | // clients with distance ordered from nearest to farthest like below 130 | 131 | List clients = clientRepo.findClientWithNearestLocation(latitude, longtitude, distance); 132 | 133 | if (clients.size() < 0) 134 | return BaseResponse.noContent(); 135 | 136 | // or we can retrieve all clients and then apply haversine to calculate the 137 | // distance between the user and the client location and if it pass certain 138 | // criteria we will add it to and 139 | // list which will be returned as the final result 140 | 141 | List allActiveClients = clientRepo.findAllByActive(true); 142 | List nearestClients = new ArrayList<>(); 143 | for (Client client : allActiveClients) { 144 | Double haversineDistance = Haversine.distance(latitude, longtitude, client.getLatitude(), 145 | client.getLongitude()); 146 | if (distance >= haversineDistance) { 147 | nearestClients.add(client); 148 | } 149 | } 150 | 151 | if (nearestClients.isEmpty()) 152 | return BaseResponse.noContent(); 153 | 154 | return ListResponse.found(clients); 155 | } 156 | 157 | // if user send 0 long and 0 lat the default will ab amman down town 158 | private double checkLng(double longtitude) { 159 | if (longtitude == 0.0) 160 | longtitude = Double.parseDouble(Constants.LONG); 161 | return longtitude; 162 | } 163 | 164 | private double checkLat(double latitude) { 165 | if (latitude == 0.0) 166 | latitude = Double.parseDouble(Constants.LATT); 167 | return latitude; 168 | } 169 | 170 | } 171 | -------------------------------------------------------------------------------- /mvnw: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # ---------------------------------------------------------------------------- 3 | # Licensed to the Apache Software Foundation (ASF) under one 4 | # or more contributor license agreements. See the NOTICE file 5 | # distributed with this work for additional information 6 | # regarding copyright ownership. The ASF licenses this file 7 | # to you under the Apache License, Version 2.0 (the 8 | # "License"); you may not use this file except in compliance 9 | # with the License. You may obtain a copy of the License at 10 | # 11 | # http://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, 14 | # software distributed under the License is distributed on an 15 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 | # KIND, either express or implied. See the License for the 17 | # specific language governing permissions and limitations 18 | # under the License. 19 | # ---------------------------------------------------------------------------- 20 | 21 | # ---------------------------------------------------------------------------- 22 | # Maven2 Start Up Batch script 23 | # 24 | # Required ENV vars: 25 | # ------------------ 26 | # JAVA_HOME - location of a JDK home dir 27 | # 28 | # Optional ENV vars 29 | # ----------------- 30 | # M2_HOME - location of maven2's installed home dir 31 | # MAVEN_OPTS - parameters passed to the Java VM when running Maven 32 | # e.g. to debug Maven itself, use 33 | # set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 34 | # MAVEN_SKIP_RC - flag to disable loading of mavenrc files 35 | # ---------------------------------------------------------------------------- 36 | 37 | if [ -z "$MAVEN_SKIP_RC" ] ; then 38 | 39 | if [ -f /etc/mavenrc ] ; then 40 | . /etc/mavenrc 41 | fi 42 | 43 | if [ -f "$HOME/.mavenrc" ] ; then 44 | . "$HOME/.mavenrc" 45 | fi 46 | 47 | fi 48 | 49 | # OS specific support. $var _must_ be set to either true or false. 50 | cygwin=false; 51 | darwin=false; 52 | mingw=false 53 | case "`uname`" in 54 | CYGWIN*) cygwin=true ;; 55 | MINGW*) mingw=true;; 56 | Darwin*) darwin=true 57 | # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home 58 | # See https://developer.apple.com/library/mac/qa/qa1170/_index.html 59 | if [ -z "$JAVA_HOME" ]; then 60 | if [ -x "/usr/libexec/java_home" ]; then 61 | export JAVA_HOME="`/usr/libexec/java_home`" 62 | else 63 | export JAVA_HOME="/Library/Java/Home" 64 | fi 65 | fi 66 | ;; 67 | esac 68 | 69 | if [ -z "$JAVA_HOME" ] ; then 70 | if [ -r /etc/gentoo-release ] ; then 71 | JAVA_HOME=`java-config --jre-home` 72 | fi 73 | fi 74 | 75 | if [ -z "$M2_HOME" ] ; then 76 | ## resolve links - $0 may be a link to maven's home 77 | PRG="$0" 78 | 79 | # need this for relative symlinks 80 | while [ -h "$PRG" ] ; do 81 | ls=`ls -ld "$PRG"` 82 | link=`expr "$ls" : '.*-> \(.*\)$'` 83 | if expr "$link" : '/.*' > /dev/null; then 84 | PRG="$link" 85 | else 86 | PRG="`dirname "$PRG"`/$link" 87 | fi 88 | done 89 | 90 | saveddir=`pwd` 91 | 92 | M2_HOME=`dirname "$PRG"`/.. 93 | 94 | # make it fully qualified 95 | M2_HOME=`cd "$M2_HOME" && pwd` 96 | 97 | cd "$saveddir" 98 | # echo Using m2 at $M2_HOME 99 | fi 100 | 101 | # For Cygwin, ensure paths are in UNIX format before anything is touched 102 | if $cygwin ; then 103 | [ -n "$M2_HOME" ] && 104 | M2_HOME=`cygpath --unix "$M2_HOME"` 105 | [ -n "$JAVA_HOME" ] && 106 | JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 107 | [ -n "$CLASSPATH" ] && 108 | CLASSPATH=`cygpath --path --unix "$CLASSPATH"` 109 | fi 110 | 111 | # For Migwn, ensure paths are in UNIX format before anything is touched 112 | if $mingw ; then 113 | [ -n "$M2_HOME" ] && 114 | M2_HOME="`(cd "$M2_HOME"; pwd)`" 115 | [ -n "$JAVA_HOME" ] && 116 | JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" 117 | # TODO classpath? 118 | fi 119 | 120 | if [ -z "$JAVA_HOME" ]; then 121 | javaExecutable="`which javac`" 122 | if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then 123 | # readlink(1) is not available as standard on Solaris 10. 124 | readLink=`which readlink` 125 | if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then 126 | if $darwin ; then 127 | javaHome="`dirname \"$javaExecutable\"`" 128 | javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" 129 | else 130 | javaExecutable="`readlink -f \"$javaExecutable\"`" 131 | fi 132 | javaHome="`dirname \"$javaExecutable\"`" 133 | javaHome=`expr "$javaHome" : '\(.*\)/bin'` 134 | JAVA_HOME="$javaHome" 135 | export JAVA_HOME 136 | fi 137 | fi 138 | fi 139 | 140 | if [ -z "$JAVACMD" ] ; then 141 | if [ -n "$JAVA_HOME" ] ; then 142 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 143 | # IBM's JDK on AIX uses strange locations for the executables 144 | JAVACMD="$JAVA_HOME/jre/sh/java" 145 | else 146 | JAVACMD="$JAVA_HOME/bin/java" 147 | fi 148 | else 149 | JAVACMD="`which java`" 150 | fi 151 | fi 152 | 153 | if [ ! -x "$JAVACMD" ] ; then 154 | echo "Error: JAVA_HOME is not defined correctly." >&2 155 | echo " We cannot execute $JAVACMD" >&2 156 | exit 1 157 | fi 158 | 159 | if [ -z "$JAVA_HOME" ] ; then 160 | echo "Warning: JAVA_HOME environment variable is not set." 161 | fi 162 | 163 | CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher 164 | 165 | # traverses directory structure from process work directory to filesystem root 166 | # first directory with .mvn subdirectory is considered project base directory 167 | find_maven_basedir() { 168 | 169 | if [ -z "$1" ] 170 | then 171 | echo "Path not specified to find_maven_basedir" 172 | return 1 173 | fi 174 | 175 | basedir="$1" 176 | wdir="$1" 177 | while [ "$wdir" != '/' ] ; do 178 | if [ -d "$wdir"/.mvn ] ; then 179 | basedir=$wdir 180 | break 181 | fi 182 | # workaround for JBEAP-8937 (on Solaris 10/Sparc) 183 | if [ -d "${wdir}" ]; then 184 | wdir=`cd "$wdir/.."; pwd` 185 | fi 186 | # end of workaround 187 | done 188 | echo "${basedir}" 189 | } 190 | 191 | # concatenates all lines of a file 192 | concat_lines() { 193 | if [ -f "$1" ]; then 194 | echo "$(tr -s '\n' ' ' < "$1")" 195 | fi 196 | } 197 | 198 | BASE_DIR=`find_maven_basedir "$(pwd)"` 199 | if [ -z "$BASE_DIR" ]; then 200 | exit 1; 201 | fi 202 | 203 | export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} 204 | echo $MAVEN_PROJECTBASEDIR 205 | MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" 206 | 207 | # For Cygwin, switch paths to Windows format before running java 208 | if $cygwin; then 209 | [ -n "$M2_HOME" ] && 210 | M2_HOME=`cygpath --path --windows "$M2_HOME"` 211 | [ -n "$JAVA_HOME" ] && 212 | JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` 213 | [ -n "$CLASSPATH" ] && 214 | CLASSPATH=`cygpath --path --windows "$CLASSPATH"` 215 | [ -n "$MAVEN_PROJECTBASEDIR" ] && 216 | MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` 217 | fi 218 | 219 | WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 220 | 221 | exec "$JAVACMD" \ 222 | $MAVEN_OPTS \ 223 | -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ 224 | "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ 225 | ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" 226 | -------------------------------------------------------------------------------- /src/main/java/com/example/util/CommonsValidator.java: -------------------------------------------------------------------------------- 1 | package com.example.util; 2 | 3 | import java.text.DateFormat; 4 | import java.text.ParseException; 5 | import java.text.SimpleDateFormat; 6 | import java.util.Date; 7 | 8 | import javax.persistence.EntityNotFoundException; 9 | import javax.servlet.http.HttpServletRequest; 10 | 11 | import org.springframework.util.StringUtils; 12 | 13 | import com.example.constant.Constants; 14 | import com.example.constant.ResponseCode; 15 | import com.example.constant.ResponseStatus; 16 | import com.example.entity.base.BaseEntity; 17 | import com.example.exception.BadRequestException; 18 | import com.example.exception.EmptyFieldException; 19 | import com.example.response.base.BaseResponse; 20 | 21 | public class CommonsValidator { 22 | 23 | public static void validateEmail(String email, String fieldName) { 24 | String regex = "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,6}$"; 25 | validateString(email, fieldName); 26 | 27 | if (!email.matches(regex)) { 28 | 29 | throw new BadRequestException("invalid email address"); 30 | } 31 | if (isSpecialCharacter(email.charAt(0))) { 32 | throw new BadRequestException("email cant start with special charachter"); 33 | } 34 | 35 | String[] split = email.split("@"); 36 | 37 | if (split[1] != null && split[1].contains("..")) 38 | throw new BadRequestException("invalid email format please enter valid email such as test@gmail.com"); 39 | } 40 | 41 | public static void validateEmail(String email) { 42 | validateEmail(email, "email"); 43 | } 44 | 45 | public static boolean isNumeric(String s) { 46 | return s != null && s.matches("[-+]?\\d*\\.?\\d+"); 47 | } 48 | 49 | 50 | private static boolean containsOnlyLetters(String s) { 51 | return s.chars().allMatch(value -> Character.isLetter(value) || Character.isWhitespace(value)); 52 | } 53 | 54 | private static boolean containsOnlyNumber(String s) { 55 | return s.chars().allMatch(value -> Character.isDigit(value) || Character.isWhitespace(value)); 56 | } 57 | 58 | public static void validateNumber(String name, int min, int max, String fieldName) { 59 | validateString(name, fieldName); 60 | validateLength(name, min, max, fieldName); 61 | if (!containsOnlyNumber(name)) 62 | throw new BadRequestException("please enter a valid number" + fieldName); 63 | } 64 | 65 | 66 | public static void validateName(String name) { 67 | validateString(name, "name"); 68 | if (!containsOnlyLetters(name)) 69 | throw new BadRequestException("name must only contain letters"); 70 | } 71 | 72 | public static boolean isProbablyArabic(String s) { 73 | String textWithoutSpace = s.trim().replaceAll(" ", ""); // to ignore whitepace 74 | for (int i = 0; i < textWithoutSpace.length();) { 75 | int c = textWithoutSpace.codePointAt(i); 76 | // 0*002D is for hyphen 77 | if (c >= 0x0600 && c <= 0x06FF || (c >= 0xFE70 && c <= 0xFEFF) || (c == 0x002D)) 78 | i += Character.charCount(c); 79 | else 80 | return false; 81 | } 82 | return true; 83 | } 84 | 85 | public static void validateArabicText(String s, String fieldName) { 86 | validateString(s, fieldName); 87 | if (!isProbablyArabic(s)) 88 | throw new BadRequestException(fieldName + " : " + "must be in arabic"); 89 | } 90 | 91 | public static BaseResponse isValidUserName(String userName) { 92 | BaseResponse response = null; 93 | if (userName == null || userName.equals("")) { 94 | response = new BaseResponse(ResponseStatus.RESPONSE_STATUS_FAILED, ResponseCode.FAILED_RESPONSE_CODE, 95 | "user name is required"); 96 | } else if (userName.length() > 20 || userName.length() < 6) { 97 | response = new BaseResponse(ResponseStatus.RESPONSE_STATUS_FAILED, ResponseCode.FAILED_RESPONSE_CODE, 98 | "userNameIsRequired"); 99 | } 100 | return response; 101 | } 102 | 103 | // check whether it contain hyphen or not 104 | public static boolean validateHyphen(String s) { 105 | if (s.length() > 0) { 106 | if (s.contains("-") && !s.endsWith("-") && !s.startsWith("-")) { 107 | return true; 108 | } 109 | } 110 | return false; 111 | 112 | } 113 | 114 | public static void validatePassword(String password, String fieldName) { 115 | validateString(password, fieldName); 116 | 117 | if (isProbablyArabic(password)) 118 | throw new BadRequestException("password should be in english"); 119 | 120 | validatePasswordLength(password, fieldName); 121 | } 122 | 123 | public static void validatePasswordLength(String password, String fieldName) { 124 | validateLength(password, Constants.PASSWORD_MIN_CHAR_COUNT, Constants.PASSWORD_MAX_CHAR_COUNT, fieldName); 125 | } 126 | 127 | public static void validateString(String toValidate, String fieldName) throws EmptyFieldException { 128 | if (toValidate == null) 129 | throw new EmptyFieldException(fieldName); 130 | 131 | toValidate = toValidate.trim(); 132 | if (toValidate.isEmpty()) { 133 | throw new EmptyFieldException(fieldName); 134 | } 135 | 136 | if (toValidate.length() > 255) 137 | throw new BadRequestException(fieldName + " exceeded the limit"); 138 | } 139 | 140 | public static void validateLength(String toValidate, int minSize, int maxSize, String fieldName) { 141 | validateString(toValidate, fieldName); 142 | if (toValidate.length() < minSize || toValidate.length() > maxSize) { 143 | throw new BadRequestException(fieldName + " exceeded the limit"); 144 | } 145 | } 146 | 147 | public static void validateLength(String toValidate, int maxSize, String fieldName) { 148 | validateLength(toValidate, 1, maxSize, fieldName); 149 | } 150 | 151 | public static void validateNumber(Double num, String fieldName) throws EmptyFieldException { 152 | if (num == null || num < 0 || num > 2000000000) 153 | throw new BadRequestException(fieldName + "exceed the limit "); 154 | } 155 | 156 | public static void validateNumber(Long num, String fieldName) throws EmptyFieldException { 157 | if (num == null || num < 0 || num > 2000000000) 158 | throw new BadRequestException(fieldName + "exceed the limit "); 159 | } 160 | 161 | public static void validateNumber(Integer num, String fieldName) throws EmptyFieldException { 162 | if (num == null || num < 0 || num > 2000000000) 163 | throw new BadRequestException(fieldName + "exceed the limit "); 164 | } 165 | 166 | public static void validateEntity(BaseEntity baseEntity, String fieldName) throws EntityNotFoundException { 167 | if (baseEntity.isActive() == Constants.ENTITY_STATUS_NOT_ACTIVE) 168 | throw new BadRequestException(fieldName +" is deleted"); 169 | } 170 | 171 | private static boolean isSpecialCharacter(char c) { 172 | String specialCharacters = " !#$%&'()*+,-./:;<=>?@[]^_`{|}"; 173 | String s = Character.toString(c); 174 | return specialCharacters.contains(s); 175 | } 176 | 177 | public static void validateBoolean(Boolean toCheck, String fieldName) { 178 | if (toCheck == null) 179 | throw new EmptyFieldException(fieldName); 180 | } 181 | 182 | public static void validateObject(Object value, String fieldName) { 183 | if (value == null) 184 | throw new EmptyFieldException(fieldName); 185 | } 186 | 187 | public static Date convertToDate(String dateToValidate) { 188 | SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); 189 | try { 190 | return sdf.parse(dateToValidate); 191 | } catch (ParseException e) { 192 | return null; 193 | } 194 | } 195 | 196 | public static boolean notEmpty(String text) { 197 | return text != null && !text.isEmpty(); 198 | } 199 | 200 | public static boolean notEmpty(int[] text) { 201 | return text != null && text.length != 0; 202 | } 203 | 204 | public static boolean notEmpty(Boolean text) { 205 | return text != null; 206 | } 207 | 208 | public static boolean isEmptyArray(int[] text) { 209 | return text == null && text.length == 0; 210 | } 211 | 212 | public static boolean notEmpty(Double text) { 213 | return text != null && text != 0; 214 | } 215 | 216 | public static boolean notEmpty(Long text) { 217 | return text != null; 218 | } 219 | 220 | public static void validateEnglishString(String englishName, String fieldName) { 221 | validateString(englishName, fieldName); 222 | if (!isEnglish(englishName)) 223 | throw new BadRequestException(fieldName + "only english letters allowed"); 224 | } 225 | 226 | public static boolean isAlphaNumericWithSpecial(String name) { 227 | return name.matches("^[a-zA-Z0-9-.,_'\\s]*$"); 228 | } 229 | 230 | private static boolean isAlphaNumeric(String name) { 231 | return name.matches("^[a-zA-Z0-9-]*$"); 232 | } 233 | 234 | private static boolean isEnglish(String name) { 235 | return name.matches("[a-zA-Z-\\s]+"); 236 | } 237 | 238 | public static Date convertStringToDate(String date) { 239 | String startDateString = date; 240 | DateFormat df = new SimpleDateFormat("yyyy-MM-dd"); 241 | Date startDate = null; 242 | try { 243 | startDate = df.parse(startDateString); 244 | String newDateString = df.format(startDate); 245 | 246 | } catch (ParseException e) { 247 | e.printStackTrace(); 248 | } 249 | return startDate; 250 | } 251 | 252 | 253 | 254 | public static boolean validArabic(String s) { 255 | for (int i = 0; i < s.length();) { 256 | int c = s.codePointAt(i); 257 | if (c >= 0x0600 && c <= 0x06E0) 258 | return true; 259 | i += Character.charCount(c); 260 | } 261 | return false; 262 | } 263 | 264 | } 265 | --------------------------------------------------------------------------------