├── common-lib ├── src │ ├── main │ │ ├── resources │ │ │ ├── application.yml │ │ │ └── email-templates │ │ │ │ └── user-verification.html │ │ └── java │ │ │ └── com │ │ │ └── quebic │ │ │ └── common │ │ │ ├── sse │ │ │ ├── ListenerType.java │ │ │ ├── SseConfig.java │ │ │ ├── SubmissionEvent.java │ │ │ └── SseEmitterApplicationEventListener.java │ │ │ ├── dao │ │ │ ├── SequenceDao.java │ │ │ ├── DaoConfig.java │ │ │ ├── GenericDao.java │ │ │ └── impl │ │ │ │ ├── SequenceDaoImpl.java │ │ │ │ └── GenericDaoImpl.java │ │ │ ├── exception │ │ │ ├── ServiceException.java │ │ │ ├── ListenerTypeNotFound.java │ │ │ ├── ProductNotFoundException.java │ │ │ ├── OrderProcessNotFoundException.java │ │ │ ├── BadRequestException.java │ │ │ ├── RequiredFieldMissingException.java │ │ │ ├── OldPasswordNotMatch.java │ │ │ ├── DuplicateEmailRegisteredException.java │ │ │ ├── DuplicateStoreRegisteredException.java │ │ │ ├── ResourceNotFoundException.java │ │ │ ├── UnAuthorizedAccessException.java │ │ │ └── DataAccessException.java │ │ │ ├── messages │ │ │ ├── InfoMessage.java │ │ │ └── ErrorMessage.java │ │ │ ├── service │ │ │ ├── GenericService.java │ │ │ └── impl │ │ │ │ └── GenericServiceImpl.java │ │ │ ├── constants │ │ │ ├── ImageResizeLevel.java │ │ │ └── ConfigConstants.java │ │ │ ├── security │ │ │ ├── SecurityConfig.java │ │ │ ├── SecurityUtil.java │ │ │ ├── CommonAuthenticationEntryPoint.java │ │ │ ├── AuthUser.java │ │ │ └── CommonAuthenticationTokenFilter.java │ │ │ ├── model │ │ │ ├── image │ │ │ │ ├── Image.java │ │ │ │ └── ImageContainer.java │ │ │ ├── Sequence.java │ │ │ ├── Permission.java │ │ │ └── EntityBase.java │ │ │ ├── response │ │ │ └── CommonResponse.java │ │ │ ├── cache │ │ │ ├── MethodSignatureBasedKeyGenerator.java │ │ │ ├── ClassNameBasedCacheResolver.java │ │ │ └── CacheConfig.java │ │ │ ├── async │ │ │ ├── deferred │ │ │ │ ├── SingleDeferredResult.java │ │ │ │ ├── ObservableDeferredResult.java │ │ │ │ └── DeferredResultWriter.java │ │ │ ├── AsyncConfig.java │ │ │ ├── handlers │ │ │ │ └── AsyncResponseEntityReturnHandler.java │ │ │ └── response │ │ │ │ └── AsyncResponseEntity.java │ │ │ └── util │ │ │ ├── image │ │ │ ├── ImageUtil.java │ │ │ └── impl │ │ │ │ ├── LocalStorageImageUtil.java │ │ │ │ └── DropBoxStorageImageUtil.java │ │ │ └── ControllerBase.java │ └── test │ │ └── java │ │ └── com │ │ └── nexca │ │ └── core │ │ └── AppTest.java └── pom.xml ├── auth-service ├── src │ ├── main │ │ ├── java │ │ │ └── com │ │ │ │ └── quebic │ │ │ │ └── auth │ │ │ │ └── api │ │ │ │ ├── common │ │ │ │ └── util │ │ │ │ │ └── email │ │ │ │ │ ├── template │ │ │ │ │ ├── EmailTemplate.java │ │ │ │ │ └── impl │ │ │ │ │ │ └── UserVerificationEmailTemplate.java │ │ │ │ │ └── EmailUtil.java │ │ │ │ ├── dao │ │ │ │ ├── RoleDao.java │ │ │ │ ├── PermissionDao.java │ │ │ │ ├── impl │ │ │ │ │ ├── RoleDaoImpl.java │ │ │ │ │ ├── PermissionDaoImpl.java │ │ │ │ │ └── UserDaoImpl.java │ │ │ │ └── UserDao.java │ │ │ │ ├── service │ │ │ │ ├── RoleService.java │ │ │ │ ├── PermissionService.java │ │ │ │ ├── SellerService.java │ │ │ │ ├── UserService.java │ │ │ │ └── impl │ │ │ │ │ ├── RoleServiceImpl.java │ │ │ │ │ ├── PermissionServiceImpl.java │ │ │ │ │ ├── SellerServiceImpl.java │ │ │ │ │ └── UserServiceImpl.java │ │ │ │ ├── model │ │ │ │ ├── BuyerProfile.java │ │ │ │ ├── EmailVerification.java │ │ │ │ ├── Role.java │ │ │ │ ├── User.java │ │ │ │ └── SellerProfile.java │ │ │ │ ├── dto │ │ │ │ ├── PasswordDto.java │ │ │ │ ├── UserImageDto.java │ │ │ │ └── SellerDto.java │ │ │ │ ├── App.java │ │ │ │ ├── security │ │ │ │ ├── dto │ │ │ │ │ ├── JwtResponse.java │ │ │ │ │ └── JwtAuthenticationDto.java │ │ │ │ ├── SecurityUtil.java │ │ │ │ ├── JwtAuthenticationEntryPoint.java │ │ │ │ ├── JwtUser.java │ │ │ │ ├── JwtAuthenticationTokenFilter.java │ │ │ │ ├── service │ │ │ │ │ └── JwtUserDetailsServiceImpl.java │ │ │ │ ├── controller │ │ │ │ │ └── AuthController.java │ │ │ │ ├── config │ │ │ │ │ └── WebSecurityConfig.java │ │ │ │ └── JwtTokenUtil.java │ │ │ │ ├── controller │ │ │ │ ├── BuyerController.java │ │ │ │ ├── SellerController.java │ │ │ │ ├── UserController.java │ │ │ │ └── setup │ │ │ │ │ └── RolesPermissionsSetupController.java │ │ │ │ └── config │ │ │ │ └── AppConfiguration.java │ │ └── resources │ │ │ ├── email-templates │ │ │ └── user-verification.html │ │ │ ├── _logback.xml │ │ │ └── application.yml │ └── test │ │ └── java │ │ └── com │ │ └── nexca │ │ └── core │ │ └── AppTest.java └── pom.xml ├── product-service ├── src │ ├── main │ │ ├── java │ │ │ └── com │ │ │ │ └── quebic │ │ │ │ └── product │ │ │ │ └── api │ │ │ │ ├── dao │ │ │ │ ├── ProductDao.java │ │ │ │ └── impl │ │ │ │ │ └── ProductDaoImpl.java │ │ │ │ ├── service │ │ │ │ ├── ProductService.java │ │ │ │ └── impl │ │ │ │ │ └── ProductServiceImpl.java │ │ │ │ ├── App.java │ │ │ │ ├── model │ │ │ │ └── Product.java │ │ │ │ ├── controller │ │ │ │ └── ProductController.java │ │ │ │ ├── config │ │ │ │ └── AppConfiguration.java │ │ │ │ └── security │ │ │ │ └── config │ │ │ │ └── WebSecurityConfig.java │ │ └── resources │ │ │ ├── application.yml │ │ │ └── _logback.xml │ └── test │ │ └── java │ │ └── com │ │ └── nexca │ │ └── core │ │ └── AppTest.java └── pom.xml ├── discovery-server ├── src │ ├── main │ │ ├── resources │ │ │ ├── application.yml │ │ │ └── _logback.xml │ │ └── java │ │ │ └── com │ │ │ └── quebic │ │ │ └── discoveryserver │ │ │ └── App.java │ └── test │ │ └── java │ │ └── com │ │ └── nexca │ │ └── regserver │ │ └── AppTest.java └── pom.xml ├── api-gateway ├── src │ ├── main │ │ ├── java │ │ │ └── com │ │ │ │ └── quebic │ │ │ │ └── apigateway │ │ │ │ └── App.java │ │ └── resources │ │ │ └── application.yml │ └── test │ │ └── java │ │ └── com │ │ └── nexca │ │ └── apigateway │ │ └── AppTest.java └── pom.xml ├── README.md └── LICENSE /common-lib/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /auth-service/src/main/java/com/quebic/auth/api/common/util/email/template/EmailTemplate.java: -------------------------------------------------------------------------------- 1 | package com.quebic.auth.api.common.util.email.template; 2 | 3 | public interface EmailTemplate { 4 | String getTextContent() throws Exception; 5 | } 6 | -------------------------------------------------------------------------------- /auth-service/src/main/java/com/quebic/auth/api/dao/RoleDao.java: -------------------------------------------------------------------------------- 1 | package com.quebic.auth.api.dao; 2 | 3 | import com.quebic.auth.api.model.Role; 4 | import com.quebic.common.dao.GenericDao; 5 | 6 | public interface RoleDao extends GenericDao{ 7 | 8 | } 9 | -------------------------------------------------------------------------------- /common-lib/src/main/java/com/quebic/common/sse/ListenerType.java: -------------------------------------------------------------------------------- 1 | package com.quebic.common.sse; 2 | 3 | public enum ListenerType { 4 | 5 | USER, 6 | VEHICLE; 7 | 8 | public String prepareKey(String id){ 9 | return this.name() + "-" + id; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /auth-service/src/main/java/com/quebic/auth/api/dao/PermissionDao.java: -------------------------------------------------------------------------------- 1 | package com.quebic.auth.api.dao; 2 | 3 | import com.quebic.common.dao.GenericDao; 4 | import com.quebic.common.model.Permission; 5 | 6 | public interface PermissionDao extends GenericDao{ 7 | 8 | } 9 | -------------------------------------------------------------------------------- /auth-service/src/main/java/com/quebic/auth/api/service/RoleService.java: -------------------------------------------------------------------------------- 1 | package com.quebic.auth.api.service; 2 | 3 | import com.quebic.auth.api.model.Role; 4 | import com.quebic.common.service.GenericService; 5 | 6 | public interface RoleService extends GenericService{ 7 | } 8 | -------------------------------------------------------------------------------- /product-service/src/main/java/com/quebic/product/api/dao/ProductDao.java: -------------------------------------------------------------------------------- 1 | package com.quebic.product.api.dao; 2 | 3 | import com.quebic.common.dao.GenericDao; 4 | import com.quebic.product.api.model.Product; 5 | 6 | public interface ProductDao extends GenericDao { 7 | 8 | } 9 | -------------------------------------------------------------------------------- /auth-service/src/main/java/com/quebic/auth/api/service/PermissionService.java: -------------------------------------------------------------------------------- 1 | package com.quebic.auth.api.service; 2 | 3 | import com.quebic.common.model.Permission; 4 | import com.quebic.common.service.GenericService; 5 | 6 | public interface PermissionService extends GenericService{ 7 | } 8 | -------------------------------------------------------------------------------- /product-service/src/main/java/com/quebic/product/api/service/ProductService.java: -------------------------------------------------------------------------------- 1 | package com.quebic.product.api.service; 2 | 3 | import com.quebic.common.service.GenericService; 4 | import com.quebic.product.api.model.Product; 5 | 6 | public interface ProductService extends GenericService{ 7 | } 8 | -------------------------------------------------------------------------------- /discovery-server/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | # Configure this Discovery Server 2 | eureka: 3 | instance: 4 | hostname: localhost 5 | client: # Not a client, don't register with yourself 6 | registerWithEureka: false 7 | fetchRegistry: false 8 | 9 | # HTTP Server 10 | server: 11 | port: @http.port@ -------------------------------------------------------------------------------- /common-lib/src/main/java/com/quebic/common/dao/SequenceDao.java: -------------------------------------------------------------------------------- 1 | package com.quebic.common.dao; 2 | 3 | import com.quebic.common.exception.DataAccessException; 4 | import com.quebic.common.model.Sequence; 5 | 6 | public interface SequenceDao extends GenericDao{ 7 | 8 | int getNextSequenceId(String key) throws DataAccessException; 9 | } 10 | -------------------------------------------------------------------------------- /auth-service/src/main/java/com/quebic/auth/api/service/SellerService.java: -------------------------------------------------------------------------------- 1 | package com.quebic.auth.api.service; 2 | 3 | import com.quebic.auth.api.model.User; 4 | import com.quebic.common.service.GenericService; 5 | 6 | import rx.Single; 7 | 8 | public interface SellerService extends GenericService{ 9 | Single registerOtherSeller(User seller); 10 | } 11 | -------------------------------------------------------------------------------- /auth-service/src/main/resources/email-templates/user-verification.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | User Verification 6 | 7 | 8 |
9 |

Welcome to Quebic

10 |

Hi %s

11 | Verify your account 12 |
13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /common-lib/src/main/java/com/quebic/common/exception/ServiceException.java: -------------------------------------------------------------------------------- 1 | package com.quebic.common.exception; 2 | 3 | public class ServiceException extends Exception { 4 | 5 | /** 6 | * 7 | */ 8 | private static final long serialVersionUID = -6790978749789863233L; 9 | 10 | public ServiceException(String message) { 11 | super(message); 12 | } 13 | 14 | } -------------------------------------------------------------------------------- /common-lib/src/main/java/com/quebic/common/messages/InfoMessage.java: -------------------------------------------------------------------------------- 1 | package com.quebic.common.messages; 2 | 3 | public class InfoMessage { 4 | public static final String USER_PROFILE_IMAGE_SAVED = "USER_PROFILE_IMAGE_SAVED : {}"; 5 | public static final String USER_COVER_IMAGE_SAVED = "USER_PROFILE_IMAGE_SAVED : {}"; 6 | public static final String VEHICLE_IMAGE_SAVED = "VEHICLE_IMAGE_SAVED : {}"; 7 | } 8 | -------------------------------------------------------------------------------- /common-lib/src/main/java/com/quebic/common/service/GenericService.java: -------------------------------------------------------------------------------- 1 | package com.quebic.common.service; 2 | 3 | import rx.Observable; 4 | import rx.Single; 5 | 6 | public interface GenericService{ 7 | 8 | Single getById(String id); 9 | 10 | Single add(T obj); 11 | 12 | Single edit(T obj); 13 | 14 | Single delete(T object); 15 | 16 | Observable getAll(); 17 | 18 | } 19 | -------------------------------------------------------------------------------- /common-lib/src/main/resources/email-templates/user-verification.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Nexca - User Verification 6 | 7 | 8 |
9 |

Welcome to Nexca

10 |

Hi %s

11 | Verify your account 12 |
13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /common-lib/src/main/java/com/quebic/common/constants/ImageResizeLevel.java: -------------------------------------------------------------------------------- 1 | package com.quebic.common.constants; 2 | 3 | public enum ImageResizeLevel { 4 | 5 | HIGH(400), 6 | MEDIUM(200), 7 | LOW(100); 8 | 9 | private final int size; 10 | 11 | ImageResizeLevel(int size) { 12 | this.size = size; 13 | } 14 | 15 | public int getSize() { 16 | return this.size; 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /common-lib/src/main/java/com/quebic/common/exception/ListenerTypeNotFound.java: -------------------------------------------------------------------------------- 1 | package com.quebic.common.exception; 2 | 3 | import org.springframework.web.bind.annotation.ResponseStatus; 4 | 5 | @ResponseStatus(reason="ListenerType Not Found") //500 6 | public class ListenerTypeNotFound extends RuntimeException{ 7 | 8 | /** 9 | * 10 | */ 11 | private static final long serialVersionUID = -6747852635122018488L; 12 | 13 | } 14 | -------------------------------------------------------------------------------- /common-lib/src/main/java/com/quebic/common/sse/SseConfig.java: -------------------------------------------------------------------------------- 1 | package com.quebic.common.sse; 2 | 3 | import org.springframework.context.annotation.Bean; 4 | import org.springframework.context.annotation.Configuration; 5 | 6 | @Configuration 7 | public class SseConfig { 8 | 9 | @Bean 10 | public SseEmitterApplicationEventListener sseEventListener() { 11 | return new SseEmitterApplicationEventListener(); 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /common-lib/src/main/java/com/quebic/common/dao/DaoConfig.java: -------------------------------------------------------------------------------- 1 | package com.quebic.common.dao; 2 | 3 | import org.springframework.context.annotation.Bean; 4 | import org.springframework.context.annotation.Configuration; 5 | 6 | import com.quebic.common.dao.impl.SequenceDaoImpl; 7 | 8 | @Configuration 9 | public class DaoConfig { 10 | 11 | @Bean 12 | public SequenceDao sequenceDao() { 13 | return new SequenceDaoImpl(); 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /common-lib/src/main/java/com/quebic/common/security/SecurityConfig.java: -------------------------------------------------------------------------------- 1 | package com.quebic.common.security; 2 | 3 | import org.springframework.context.annotation.Bean; 4 | import org.springframework.context.annotation.Configuration; 5 | 6 | @Configuration 7 | public class SecurityConfig { 8 | 9 | @Bean 10 | public CommonAuthenticationEntryPoint jwtAuthenticationEntryPoint() { 11 | return new CommonAuthenticationEntryPoint(); 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /common-lib/src/main/java/com/quebic/common/exception/ProductNotFoundException.java: -------------------------------------------------------------------------------- 1 | package com.quebic.common.exception; 2 | 3 | import org.springframework.http.HttpStatus; 4 | import org.springframework.web.bind.annotation.ResponseStatus; 5 | 6 | @ResponseStatus(value = HttpStatus.NOT_FOUND, reason = "Product not found") 7 | public class ProductNotFoundException extends RuntimeException{ 8 | private static final long serialVersionUID = 6920349436066566185L; 9 | } 10 | -------------------------------------------------------------------------------- /common-lib/src/main/java/com/quebic/common/exception/OrderProcessNotFoundException.java: -------------------------------------------------------------------------------- 1 | package com.quebic.common.exception; 2 | 3 | import org.springframework.http.HttpStatus; 4 | import org.springframework.web.bind.annotation.ResponseStatus; 5 | 6 | @ResponseStatus(value = HttpStatus.NOT_FOUND, reason = "Order not found") 7 | public class OrderProcessNotFoundException extends RuntimeException{ 8 | private static final long serialVersionUID = 6920349436066566185L; 9 | } 10 | -------------------------------------------------------------------------------- /auth-service/src/main/java/com/quebic/auth/api/model/BuyerProfile.java: -------------------------------------------------------------------------------- 1 | package com.quebic.auth.api.model; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | public class BuyerProfile { 7 | 8 | //temp fields 9 | private List orders = new ArrayList<>(); 10 | 11 | public List getOrders() { 12 | return orders; 13 | } 14 | 15 | public void setOrders(List orders) { 16 | this.orders = orders; 17 | } 18 | 19 | 20 | 21 | } 22 | -------------------------------------------------------------------------------- /common-lib/src/main/java/com/quebic/common/model/image/Image.java: -------------------------------------------------------------------------------- 1 | package com.quebic.common.model.image; 2 | 3 | public class Image { 4 | 5 | private String fileName; 6 | 7 | public Image() { 8 | } 9 | 10 | 11 | 12 | public Image(String fileName) { 13 | this.fileName = fileName; 14 | } 15 | 16 | public String getFileName() { 17 | return fileName; 18 | } 19 | 20 | public void setFileName(String fileName) { 21 | this.fileName = fileName; 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /auth-service/src/main/java/com/quebic/auth/api/dao/impl/RoleDaoImpl.java: -------------------------------------------------------------------------------- 1 | package com.quebic.auth.api.dao.impl; 2 | 3 | import org.springframework.stereotype.Repository; 4 | 5 | import com.quebic.auth.api.dao.RoleDao; 6 | import com.quebic.auth.api.model.Role; 7 | import com.quebic.common.dao.impl.GenericDaoImpl; 8 | 9 | @Repository 10 | public class RoleDaoImpl extends GenericDaoImpl implements RoleDao { 11 | 12 | public RoleDaoImpl() { 13 | super(Role.class); 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /discovery-server/src/main/java/com/quebic/discoveryserver/App.java: -------------------------------------------------------------------------------- 1 | package com.quebic.discoveryserver; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; 6 | 7 | @SpringBootApplication 8 | @EnableEurekaServer 9 | public class App 10 | { 11 | public static void main( String[] args ) 12 | { 13 | SpringApplication.run(App.class, args); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /product-service/src/main/java/com/quebic/product/api/dao/impl/ProductDaoImpl.java: -------------------------------------------------------------------------------- 1 | package com.quebic.product.api.dao.impl; 2 | 3 | import org.springframework.stereotype.Repository; 4 | import com.quebic.common.dao.impl.GenericDaoImpl; 5 | import com.quebic.product.api.dao.ProductDao; 6 | import com.quebic.product.api.model.Product; 7 | 8 | @Repository 9 | public class ProductDaoImpl extends GenericDaoImpl implements ProductDao{ 10 | 11 | public ProductDaoImpl() { 12 | super(Product.class); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /auth-service/src/main/java/com/quebic/auth/api/dao/impl/PermissionDaoImpl.java: -------------------------------------------------------------------------------- 1 | package com.quebic.auth.api.dao.impl; 2 | 3 | import org.springframework.stereotype.Repository; 4 | 5 | import com.quebic.auth.api.dao.PermissionDao; 6 | import com.quebic.common.dao.impl.GenericDaoImpl; 7 | import com.quebic.common.model.Permission; 8 | 9 | @Repository 10 | public class PermissionDaoImpl extends GenericDaoImpl implements PermissionDao { 11 | 12 | public PermissionDaoImpl() { 13 | super(Permission.class); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /api-gateway/src/main/java/com/quebic/apigateway/App.java: -------------------------------------------------------------------------------- 1 | package com.quebic.apigateway; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.cloud.client.discovery.EnableDiscoveryClient; 6 | import org.springframework.cloud.netflix.zuul.EnableZuulProxy; 7 | 8 | @EnableZuulProxy 9 | @EnableDiscoveryClient 10 | @SpringBootApplication 11 | public class App 12 | { 13 | public static void main( String[] args ) 14 | { 15 | SpringApplication.run(App.class, args); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /common-lib/src/main/java/com/quebic/common/exception/BadRequestException.java: -------------------------------------------------------------------------------- 1 | package com.quebic.common.exception; 2 | 3 | import org.springframework.http.HttpStatus; 4 | import org.springframework.web.bind.annotation.ResponseStatus; 5 | 6 | @ResponseStatus(value=HttpStatus.BAD_REQUEST) //400 7 | public class BadRequestException extends RuntimeException{ 8 | 9 | private static final long serialVersionUID = -6659322898478118584L; 10 | 11 | public BadRequestException() { 12 | this("Bad Request"); 13 | } 14 | 15 | public BadRequestException(String message) { 16 | super(message); 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /common-lib/src/main/java/com/quebic/common/exception/RequiredFieldMissingException.java: -------------------------------------------------------------------------------- 1 | package com.quebic.common.exception; 2 | 3 | import org.springframework.http.HttpStatus; 4 | import org.springframework.web.bind.annotation.ResponseStatus; 5 | 6 | @ResponseStatus(value=HttpStatus.BAD_REQUEST) //400 7 | public class RequiredFieldMissingException extends RuntimeException{ 8 | 9 | private static final long serialVersionUID = 1537589278610015552L; 10 | 11 | public RequiredFieldMissingException(Object... fields) { 12 | super(String.format("Required Field Missing [%s]", fields)); 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /common-lib/src/main/java/com/quebic/common/exception/OldPasswordNotMatch.java: -------------------------------------------------------------------------------- 1 | package com.quebic.common.exception; 2 | 3 | import org.springframework.http.HttpStatus; 4 | import org.springframework.web.bind.annotation.ResponseStatus; 5 | 6 | @ResponseStatus(value=HttpStatus.BAD_REQUEST, reason="Old Password Not Match") //400 7 | public class OldPasswordNotMatch extends RuntimeException{ 8 | 9 | private static final long serialVersionUID = -7106944187406637244L; 10 | 11 | public OldPasswordNotMatch() { 12 | } 13 | 14 | public OldPasswordNotMatch(String message) { 15 | super(message); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /common-lib/src/main/java/com/quebic/common/model/Sequence.java: -------------------------------------------------------------------------------- 1 | package com.quebic.common.model; 2 | 3 | import org.springframework.data.annotation.Id; 4 | import org.springframework.data.mongodb.core.mapping.Document; 5 | 6 | @Document(collection="Sequence") 7 | public class Sequence { 8 | 9 | @Id 10 | private String id; 11 | 12 | private int seq; 13 | 14 | public String getId() { 15 | return id; 16 | } 17 | 18 | public void setId(String id) { 19 | this.id = id; 20 | } 21 | 22 | public int getSeq() { 23 | return seq; 24 | } 25 | 26 | public void setSeq(int seq) { 27 | this.seq = seq; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /auth-service/src/main/java/com/quebic/auth/api/dto/PasswordDto.java: -------------------------------------------------------------------------------- 1 | package com.quebic.auth.api.dto; 2 | 3 | public class PasswordDto { 4 | 5 | private String oldPassword; 6 | private String newPassword; 7 | 8 | public String getOldPassword() { 9 | return oldPassword; 10 | } 11 | 12 | public void setOldPassword(String oldPassword) { 13 | this.oldPassword = oldPassword; 14 | } 15 | 16 | public String getNewPassword() { 17 | return newPassword; 18 | } 19 | 20 | public void setNewPassword(String newPassword) { 21 | this.newPassword = newPassword; 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /common-lib/src/main/java/com/quebic/common/response/CommonResponse.java: -------------------------------------------------------------------------------- 1 | package com.quebic.common.response; 2 | 3 | public class CommonResponse { 4 | 5 | private int status; 6 | private Object message; 7 | 8 | public CommonResponse(int status, Object message) { 9 | this.status = status; 10 | this.message = message; 11 | } 12 | public int getStatus() { 13 | return status; 14 | } 15 | public void setStatus(int status) { 16 | this.status = status; 17 | } 18 | public Object getMessage() { 19 | return message; 20 | } 21 | public void setMessage(Object message) { 22 | this.message = message; 23 | } 24 | 25 | 26 | 27 | } 28 | -------------------------------------------------------------------------------- /common-lib/src/main/java/com/quebic/common/sse/SubmissionEvent.java: -------------------------------------------------------------------------------- 1 | package com.quebic.common.sse; 2 | 3 | public class SubmissionEvent { 4 | 5 | private String key; 6 | private Object message; 7 | 8 | public SubmissionEvent(ListenerType type , String id, Object message) { 9 | this.key = type.prepareKey(id); 10 | this.message = message; 11 | } 12 | public String getKey() { 13 | return key; 14 | } 15 | public void setKey(String key) { 16 | this.key = key; 17 | } 18 | public Object getMessage() { 19 | return message; 20 | } 21 | public void setMessage(Object message) { 22 | this.message = message; 23 | } 24 | 25 | 26 | 27 | } 28 | -------------------------------------------------------------------------------- /common-lib/src/main/java/com/quebic/common/exception/DuplicateEmailRegisteredException.java: -------------------------------------------------------------------------------- 1 | package com.quebic.common.exception; 2 | 3 | import org.springframework.http.HttpStatus; 4 | import org.springframework.web.bind.annotation.ResponseStatus; 5 | 6 | @ResponseStatus(value=HttpStatus.FORBIDDEN, reason="Duplicate Email Registered") //403 7 | public class DuplicateEmailRegisteredException extends RuntimeException{ 8 | 9 | private static final long serialVersionUID = 4333940983178070455L; 10 | 11 | public DuplicateEmailRegisteredException() { 12 | } 13 | 14 | public DuplicateEmailRegisteredException(String message) { 15 | super(message); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /common-lib/src/main/java/com/quebic/common/exception/DuplicateStoreRegisteredException.java: -------------------------------------------------------------------------------- 1 | package com.quebic.common.exception; 2 | 3 | import org.springframework.http.HttpStatus; 4 | import org.springframework.web.bind.annotation.ResponseStatus; 5 | 6 | @ResponseStatus(value=HttpStatus.FORBIDDEN, reason="Duplicate Store Registered") //403 7 | public class DuplicateStoreRegisteredException extends RuntimeException{ 8 | 9 | private static final long serialVersionUID = 4333940983178070455L; 10 | 11 | public DuplicateStoreRegisteredException() { 12 | } 13 | 14 | public DuplicateStoreRegisteredException(String message) { 15 | super(message); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /auth-service/src/main/java/com/quebic/auth/api/App.java: -------------------------------------------------------------------------------- 1 | package com.quebic.auth.api; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.cache.annotation.EnableCaching; 6 | import org.springframework.cloud.client.discovery.EnableDiscoveryClient; 7 | import org.springframework.scheduling.annotation.EnableScheduling; 8 | 9 | @SpringBootApplication 10 | @EnableDiscoveryClient 11 | @EnableCaching 12 | @EnableScheduling 13 | public class App 14 | { 15 | public static void main( String[] args ) 16 | { 17 | SpringApplication.run(App.class, args); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /product-service/src/main/java/com/quebic/product/api/App.java: -------------------------------------------------------------------------------- 1 | package com.quebic.product.api; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.cache.annotation.EnableCaching; 6 | import org.springframework.cloud.client.discovery.EnableDiscoveryClient; 7 | import org.springframework.scheduling.annotation.EnableScheduling; 8 | 9 | @SpringBootApplication 10 | @EnableDiscoveryClient 11 | @EnableCaching 12 | @EnableScheduling 13 | public class App 14 | { 15 | public static void main( String[] args ) 16 | { 17 | SpringApplication.run(App.class, args); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /common-lib/src/main/java/com/quebic/common/model/image/ImageContainer.java: -------------------------------------------------------------------------------- 1 | package com.quebic.common.model.image; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | public class ImageContainer { 7 | 8 | private int selectedImageIndex = 0; 9 | private List images = new ArrayList<>(); 10 | 11 | public int getSelectedImageIndex() { 12 | return selectedImageIndex; 13 | } 14 | public void setSelectedImageIndex(int selectedImageIndex) { 15 | this.selectedImageIndex = selectedImageIndex; 16 | } 17 | public List getImages() { 18 | return images; 19 | } 20 | public void setImages(List images) { 21 | this.images = images; 22 | } 23 | 24 | 25 | 26 | } 27 | -------------------------------------------------------------------------------- /auth-service/src/main/java/com/quebic/auth/api/dao/UserDao.java: -------------------------------------------------------------------------------- 1 | package com.quebic.auth.api.dao; 2 | 3 | import java.util.List; 4 | 5 | import com.quebic.auth.api.model.User; 6 | import com.quebic.common.dao.GenericDao; 7 | import com.quebic.common.exception.DataAccessException; 8 | import com.quebic.common.model.Permission; 9 | 10 | public interface UserDao extends GenericDao{ 11 | 12 | User findByEmail(String email) throws DataAccessException; 13 | 14 | List findUserPermissions()throws DataAccessException; 15 | 16 | User findUserByToken(String token)throws DataAccessException; 17 | 18 | User findByUsernameOrEmail(String username, String email) throws DataAccessException; 19 | 20 | } 21 | -------------------------------------------------------------------------------- /auth-service/src/main/java/com/quebic/auth/api/security/dto/JwtResponse.java: -------------------------------------------------------------------------------- 1 | package com.quebic.auth.api.security.dto; 2 | 3 | public class JwtResponse { 4 | 5 | private String token; 6 | private String expiration; 7 | 8 | public JwtResponse() { 9 | } 10 | 11 | public JwtResponse(String token, String expiration) { 12 | this.token = token; 13 | this.expiration = expiration; 14 | } 15 | 16 | public String getToken() { 17 | return token; 18 | } 19 | 20 | public void setToken(String token) { 21 | this.token = token; 22 | } 23 | 24 | public String getExpiration() { 25 | return expiration; 26 | } 27 | 28 | public void setExpiration(String expiration) { 29 | this.expiration = expiration; 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /common-lib/src/main/java/com/quebic/common/exception/ResourceNotFoundException.java: -------------------------------------------------------------------------------- 1 | package com.quebic.common.exception; 2 | 3 | import org.springframework.http.HttpStatus; 4 | import org.springframework.web.bind.annotation.ResponseStatus; 5 | 6 | import com.quebic.common.messages.ErrorMessage; 7 | 8 | @ResponseStatus(value=HttpStatus.NOT_FOUND) //404 9 | public class ResourceNotFoundException extends RuntimeException{ 10 | 11 | private static final long serialVersionUID = -2217466109027636423L; 12 | 13 | public ResourceNotFoundException() { 14 | super(ErrorMessage.RESOURCE_NOT_FOUND); 15 | } 16 | 17 | public ResourceNotFoundException(String message){ 18 | super(String.format(ErrorMessage.RESOURCE_NOT_FOUND, message)); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /common-lib/src/main/java/com/quebic/common/cache/MethodSignatureBasedKeyGenerator.java: -------------------------------------------------------------------------------- 1 | package com.quebic.common.cache; 2 | 3 | import java.lang.reflect.Method; 4 | import org.springframework.cache.interceptor.KeyGenerator; 5 | 6 | public class MethodSignatureBasedKeyGenerator implements KeyGenerator { 7 | 8 | @Override 9 | public Object generate(Object target, Method method, Object... params) { 10 | StringBuilder key = new StringBuilder(); 11 | key.append(method.getName()); 12 | if (params.length > 0) { 13 | key.append(':'); 14 | for (Object argument : params) { 15 | key.append(argument); 16 | key.append(':'); 17 | } 18 | } 19 | System.out.println("key : " + key.toString()); 20 | return key.toString(); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /common-lib/src/main/java/com/quebic/common/exception/UnAuthorizedAccessException.java: -------------------------------------------------------------------------------- 1 | package com.quebic.common.exception; 2 | 3 | import org.springframework.http.HttpStatus; 4 | import org.springframework.web.bind.annotation.ResponseStatus; 5 | 6 | import com.quebic.common.messages.ErrorMessage; 7 | 8 | @ResponseStatus(value = HttpStatus.UNAUTHORIZED) 9 | public class UnAuthorizedAccessException extends RuntimeException{ 10 | private static final long serialVersionUID = 1571945318849673209L; 11 | 12 | public UnAuthorizedAccessException() { 13 | super(ErrorMessage.UNAUTHORIZED_ACCESS); 14 | } 15 | 16 | public UnAuthorizedAccessException(String message) { 17 | super(String.format(ErrorMessage.UNAUTHORIZED_ACCESS, message)); 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /auth-service/src/main/java/com/quebic/auth/api/security/dto/JwtAuthenticationDto.java: -------------------------------------------------------------------------------- 1 | package com.quebic.auth.api.security.dto; 2 | 3 | public class JwtAuthenticationDto { 4 | 5 | private String username; 6 | private String password; 7 | 8 | public JwtAuthenticationDto() { 9 | } 10 | 11 | public JwtAuthenticationDto(String username, String password) { 12 | this.username = username; 13 | this.password = password; 14 | } 15 | 16 | public String getUsername() { 17 | return username; 18 | } 19 | 20 | public void setUsername(String username) { 21 | this.username = username; 22 | } 23 | 24 | public String getPassword() { 25 | return this.password; 26 | } 27 | 28 | public void setPassword(String password) { 29 | this.password = password; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /product-service/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | # Spring properties 2 | spring: 3 | application: 4 | name: product-service 5 | 6 | # Mongo properties 7 | data: 8 | mongodb: 9 | host: @mongo.host@ 10 | port: @mongo.port@ 11 | database: @mongo.database@ 12 | 13 | 14 | # HTTP Server 15 | server: 16 | port: @http.port@ 17 | 18 | # Discovery Server Access 19 | eureka: 20 | client: 21 | serviceUrl: 22 | defaultZone: http://localhost:1111/eureka/ 23 | instance: 24 | leaseRenewalIntervalInSeconds: 5 # DO NOT DO THIS IN PRODUCTION 25 | 26 | # Auth JWT 27 | jwt: 28 | header: Authorization 29 | secret: quebic_secret 30 | expiration: 172800 #seconds 31 | route: 32 | authentication: 33 | path: auth 34 | refresh: refresh 35 | 36 | -------------------------------------------------------------------------------- /common-lib/src/main/java/com/quebic/common/model/Permission.java: -------------------------------------------------------------------------------- 1 | package com.quebic.common.model; 2 | 3 | import org.springframework.data.mongodb.core.mapping.Document; 4 | 5 | import com.quebic.common.model.EntityBase; 6 | 7 | @Document(collection="Permission") 8 | public class Permission extends EntityBase{ 9 | 10 | public static String USER = "USER"; 11 | public static String USER_ADMIN = "USER_ADMIN"; 12 | public static String USER_SELLER_ADMIN = "USER_SELLER_ADMIN"; 13 | public static String USER_SELLER = "USER_SELLER"; 14 | public static String USER_BUYER = "USER_BUYER"; 15 | 16 | private String code; 17 | 18 | public String getCode() { 19 | return this.code; 20 | } 21 | 22 | public void setCode(String name) { 23 | this.code = name; 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /auth-service/src/main/java/com/quebic/auth/api/service/UserService.java: -------------------------------------------------------------------------------- 1 | package com.quebic.auth.api.service; 2 | 3 | import java.util.List; 4 | 5 | import com.quebic.auth.api.dto.UserImageDto; 6 | import com.quebic.auth.api.model.User; 7 | import com.quebic.common.service.GenericService; 8 | 9 | import rx.Single; 10 | 11 | public interface UserService extends GenericService{ 12 | 13 | Single findByEmail(String email); 14 | 15 | Single findByUsernameOrEmail(String username, String email); 16 | 17 | Single edit(User user, UserImageDto imageDto); 18 | 19 | Single delete(String id); 20 | 21 | Single delete(List idList); 22 | 23 | Single findUserByToken(String token); 24 | 25 | Single changePassword(String oldPassword, String newPassword); 26 | 27 | } 28 | -------------------------------------------------------------------------------- /common-lib/src/main/java/com/quebic/common/constants/ConfigConstants.java: -------------------------------------------------------------------------------- 1 | package com.quebic.common.constants; 2 | 3 | public class ConfigConstants { 4 | 5 | public static final String IMAGE_UPLOAD_LOCATION = "${image.upload.location}"; 6 | public static final String IMAGE_VEHICLE_EXTERIOR_UPLOAD_LOCATION = "vehicle_exterior_images"; 7 | public static final String IMAGE_VEHICLE_INTERIOR_UPLOAD_LOCATION = "vehicle_interior_images"; 8 | public static final String IMAGE_PROFILE_UPLOAD_LOCATION = "profile_images"; 9 | public static final String IMAGE_COVER_UPLOAD_LOCATION = "cover_images"; 10 | public static final String EMAIL_USERNAME = "${email.userName}"; 11 | public static final String EMAIL_PASSWORD = "${email.password}"; 12 | public static final String SYSTEM_INTERNAL_AUTH_KEY = "${system-internal-auth-key}"; 13 | 14 | } 15 | -------------------------------------------------------------------------------- /product-service/src/main/java/com/quebic/product/api/model/Product.java: -------------------------------------------------------------------------------- 1 | package com.quebic.product.api.model; 2 | 3 | import org.springframework.data.mongodb.core.mapping.Document; 4 | 5 | import com.quebic.common.model.EntityBase; 6 | 7 | @Document(collection = "Product") 8 | public class Product extends EntityBase{ 9 | 10 | private String sellerId; 11 | private String name; 12 | private double price; 13 | 14 | public String getSellerId() { 15 | return sellerId; 16 | } 17 | public void setSellerId(String sellerId) { 18 | this.sellerId = sellerId; 19 | } 20 | public String getName() { 21 | return name; 22 | } 23 | public void setName(String name) { 24 | this.name = name; 25 | } 26 | public double getPrice() { 27 | return price; 28 | } 29 | public void setPrice(double price) { 30 | this.price = price; 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /auth-service/src/test/java/com/nexca/core/AppTest.java: -------------------------------------------------------------------------------- 1 | package com.nexca.core; 2 | 3 | import junit.framework.Test; 4 | import junit.framework.TestCase; 5 | import junit.framework.TestSuite; 6 | 7 | /** 8 | * Unit test for simple App. 9 | */ 10 | public class AppTest 11 | extends TestCase 12 | { 13 | /** 14 | * Create the test case 15 | * 16 | * @param testName name of the test case 17 | */ 18 | public AppTest( String testName ) 19 | { 20 | super( testName ); 21 | } 22 | 23 | /** 24 | * @return the suite of tests being tested 25 | */ 26 | public static Test suite() 27 | { 28 | return new TestSuite( AppTest.class ); 29 | } 30 | 31 | /** 32 | * Rigourous Test :-) 33 | */ 34 | public void testApp() 35 | { 36 | assertTrue( true ); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /common-lib/src/test/java/com/nexca/core/AppTest.java: -------------------------------------------------------------------------------- 1 | package com.nexca.core; 2 | 3 | import junit.framework.Test; 4 | import junit.framework.TestCase; 5 | import junit.framework.TestSuite; 6 | 7 | /** 8 | * Unit test for simple App. 9 | */ 10 | public class AppTest 11 | extends TestCase 12 | { 13 | /** 14 | * Create the test case 15 | * 16 | * @param testName name of the test case 17 | */ 18 | public AppTest( String testName ) 19 | { 20 | super( testName ); 21 | } 22 | 23 | /** 24 | * @return the suite of tests being tested 25 | */ 26 | public static Test suite() 27 | { 28 | return new TestSuite( AppTest.class ); 29 | } 30 | 31 | /** 32 | * Rigourous Test :-) 33 | */ 34 | public void testApp() 35 | { 36 | assertTrue( true ); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /product-service/src/test/java/com/nexca/core/AppTest.java: -------------------------------------------------------------------------------- 1 | package com.nexca.core; 2 | 3 | import junit.framework.Test; 4 | import junit.framework.TestCase; 5 | import junit.framework.TestSuite; 6 | 7 | /** 8 | * Unit test for simple App. 9 | */ 10 | public class AppTest 11 | extends TestCase 12 | { 13 | /** 14 | * Create the test case 15 | * 16 | * @param testName name of the test case 17 | */ 18 | public AppTest( String testName ) 19 | { 20 | super( testName ); 21 | } 22 | 23 | /** 24 | * @return the suite of tests being tested 25 | */ 26 | public static Test suite() 27 | { 28 | return new TestSuite( AppTest.class ); 29 | } 30 | 31 | /** 32 | * Rigourous Test :-) 33 | */ 34 | public void testApp() 35 | { 36 | assertTrue( true ); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /api-gateway/src/test/java/com/nexca/apigateway/AppTest.java: -------------------------------------------------------------------------------- 1 | package com.nexca.apigateway; 2 | 3 | import junit.framework.Test; 4 | import junit.framework.TestCase; 5 | import junit.framework.TestSuite; 6 | 7 | /** 8 | * Unit test for simple App. 9 | */ 10 | public class AppTest 11 | extends TestCase 12 | { 13 | /** 14 | * Create the test case 15 | * 16 | * @param testName name of the test case 17 | */ 18 | public AppTest( String testName ) 19 | { 20 | super( testName ); 21 | } 22 | 23 | /** 24 | * @return the suite of tests being tested 25 | */ 26 | public static Test suite() 27 | { 28 | return new TestSuite( AppTest.class ); 29 | } 30 | 31 | /** 32 | * Rigourous Test :-) 33 | */ 34 | public void testApp() 35 | { 36 | assertTrue( true ); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /discovery-server/src/test/java/com/nexca/regserver/AppTest.java: -------------------------------------------------------------------------------- 1 | package com.nexca.regserver; 2 | 3 | import junit.framework.Test; 4 | import junit.framework.TestCase; 5 | import junit.framework.TestSuite; 6 | 7 | /** 8 | * Unit test for simple App. 9 | */ 10 | public class AppTest 11 | extends TestCase 12 | { 13 | /** 14 | * Create the test case 15 | * 16 | * @param testName name of the test case 17 | */ 18 | public AppTest( String testName ) 19 | { 20 | super( testName ); 21 | } 22 | 23 | /** 24 | * @return the suite of tests being tested 25 | */ 26 | public static Test suite() 27 | { 28 | return new TestSuite( AppTest.class ); 29 | } 30 | 31 | /** 32 | * Rigourous Test :-) 33 | */ 34 | public void testApp() 35 | { 36 | assertTrue( true ); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /auth-service/src/main/java/com/quebic/auth/api/dto/UserImageDto.java: -------------------------------------------------------------------------------- 1 | package com.quebic.auth.api.dto; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | import org.springframework.web.multipart.MultipartFile; 6 | 7 | public class UserImageDto { 8 | 9 | private List profileImagesFiles = new ArrayList<>(); 10 | private List coverImagesFiles = new ArrayList<>(); 11 | 12 | public List getProfileImagesFiles() { 13 | return profileImagesFiles; 14 | } 15 | public void setProfileImagesFiles(List profileImagesFiles) { 16 | this.profileImagesFiles = profileImagesFiles; 17 | } 18 | public List getCoverImagesFiles() { 19 | return coverImagesFiles; 20 | } 21 | public void setCoverImagesFiles(List coverImagesFiles) { 22 | this.coverImagesFiles = coverImagesFiles; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /auth-service/src/main/resources/_logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | %d{HH:mm:ss} [%level] [%logger{36}] %msg%n 11 | 12 | 13 | 14 | 15 | ${LOG_FILE} 16 | 17 | %d{HH:mm:ss} [%level] [%logger{36}] %msg%n 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /common-lib/src/main/java/com/quebic/common/security/SecurityUtil.java: -------------------------------------------------------------------------------- 1 | package com.quebic.common.security; 2 | 3 | import org.springframework.security.core.context.SecurityContextHolder; 4 | import org.springframework.security.core.userdetails.UserDetails; 5 | 6 | public class SecurityUtil { 7 | 8 | public static UserDetails getLoggedUserDetails() { 9 | Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal(); 10 | 11 | if (principal instanceof UserDetails) 12 | return (UserDetails) principal; 13 | 14 | return null; 15 | } 16 | 17 | public static AuthUser getAuthUserDetails() { 18 | UserDetails userDetails = getLoggedUserDetails(); 19 | 20 | if (userDetails != null && (userDetails instanceof AuthUser)) 21 | return (AuthUser) userDetails; 22 | 23 | return null; 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /discovery-server/src/main/resources/_logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | %d{HH:mm:ss} [%level] [%logger{36}] %msg%n 11 | 12 | 13 | 14 | 15 | ${LOG_FILE} 16 | 17 | %d{HH:mm:ss} [%level] [%logger{36}] %msg%n 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /product-service/src/main/resources/_logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | %d{HH:mm:ss} [%level] [%logger{36}] %msg%n 11 | 12 | 13 | 14 | 15 | ${LOG_FILE} 16 | 17 | %d{HH:mm:ss} [%level] [%logger{36}] %msg%n 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /auth-service/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | # Spring properties 2 | spring: 3 | application: 4 | name: auth-service 5 | 6 | # Mongo properties 7 | data: 8 | mongodb: 9 | host: @mongo.host@ 10 | port: @mongo.port@ 11 | database: @mongo.database@ 12 | 13 | 14 | # HTTP Server 15 | server: 16 | port: @http.port@ 17 | 18 | # Discovery Server Access 19 | eureka: 20 | client: 21 | serviceUrl: 22 | defaultZone: http://localhost:1111/eureka/ 23 | instance: 24 | leaseRenewalIntervalInSeconds: 5 # DO NOT DO THIS IN PRODUCTION 25 | 26 | # Auth JWT 27 | jwt: 28 | header: Authorization 29 | secret: quebic_secret 30 | expiration: 172800 #seconds 31 | route: 32 | authentication: 33 | path: auth 34 | refresh: refresh 35 | 36 | # Image Upload Location 37 | image: 38 | upload: 39 | location: @image.upload.location@ 40 | 41 | # Email 42 | email: 43 | userName: @email.userName@ 44 | password: @email.password@ 45 | -------------------------------------------------------------------------------- /api-gateway/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | # Spring properties 2 | spring: 3 | application: 4 | name: api-gateway # Identify this application 5 | 6 | # Server 7 | server: 8 | port: @http.port@ # HTTP (Tomcat) port 9 | 10 | # Discovery Server Access 11 | eureka: 12 | client: 13 | serviceUrl: 14 | defaultZone: http://localhost:1111/eureka/ 15 | instance: 16 | leaseRenewalIntervalInSeconds: 5 # DO NOT DO THIS IN PRODUCTION 17 | 18 | # Api-Gate-Way 19 | zuul: 20 | prefix: /api 21 | routes: 22 | auth-service: 23 | path: /auth-service/** 24 | serviceId: AUTH-SERVICE 25 | sensitiveHeaders: Cookie,Set-Cookie 26 | 27 | product-service: 28 | path: /product-service/** 29 | serviceId: PRODUCT-SERVICE 30 | sensitiveHeaders: Cookie,Set-Cookie 31 | 32 | 33 | # Increase the Hystrix timeout to 60s (globally) 34 | hystrix: 35 | command: 36 | default: 37 | execution: 38 | isolation: 39 | thread: 40 | timeoutInMilliseconds: 60000 41 | -------------------------------------------------------------------------------- /auth-service/src/main/java/com/quebic/auth/api/controller/BuyerController.java: -------------------------------------------------------------------------------- 1 | package com.quebic.auth.api.controller; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.http.HttpStatus; 5 | import org.springframework.web.bind.annotation.*; 6 | 7 | import com.quebic.auth.api.model.Role; 8 | import com.quebic.auth.api.model.User; 9 | import com.quebic.auth.api.service.UserService; 10 | import com.quebic.common.async.response.AsyncResponseEntity; 11 | import com.quebic.common.util.ControllerBase; 12 | 13 | @RestController 14 | @RequestMapping("/buyers") 15 | public class BuyerController extends ControllerBase { 16 | 17 | @Autowired 18 | private UserService userService; 19 | 20 | @RequestMapping(method = RequestMethod.POST) 21 | public AsyncResponseEntity save(@ModelAttribute User user) { 22 | user.getRoles().add(Role.Create_Buyer()); 23 | user.setSellerProfile(null); 24 | return makeAsyncResponse(userService.add(user), HttpStatus.CREATED); 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /common-lib/src/main/java/com/quebic/common/cache/ClassNameBasedCacheResolver.java: -------------------------------------------------------------------------------- 1 | package com.quebic.common.cache; 2 | 3 | import java.util.Collection; 4 | import java.util.Collections; 5 | import org.springframework.cache.CacheManager; 6 | import org.springframework.cache.interceptor.AbstractCacheResolver; 7 | import org.springframework.cache.interceptor.CacheOperationInvocationContext; 8 | 9 | public class ClassNameBasedCacheResolver extends AbstractCacheResolver{ 10 | 11 | public String suffix = ""; 12 | public String concat; 13 | 14 | public ClassNameBasedCacheResolver(CacheManager cacheManager){ 15 | super(cacheManager); 16 | } 17 | 18 | public ClassNameBasedCacheResolver(CacheManager cacheManager, String suffix, String concat){ 19 | super(cacheManager); 20 | this.suffix = suffix; 21 | this.concat = concat; 22 | } 23 | 24 | @Override 25 | protected Collection getCacheNames(CacheOperationInvocationContext context) { 26 | String cls = context.getTarget().getClass().getSimpleName() 27 | + (suffix.equals("")?suffix:concat+suffix); 28 | return Collections.singletonList(cls); 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /common-lib/src/main/java/com/quebic/common/exception/DataAccessException.java: -------------------------------------------------------------------------------- 1 | 2 | package com.quebic.common.exception; 3 | 4 | public class DataAccessException extends Exception { 5 | 6 | private static final long serialVersionUID = -1227936014166460133L; 7 | public static final int PROCESSING_FAILED = 1; 8 | public static final int VALIDATION_FAILED = 2; 9 | 10 | private int code; 11 | 12 | public DataAccessException() { 13 | super(); 14 | } 15 | 16 | public DataAccessException(Exception e) { 17 | super(e); 18 | } 19 | 20 | public DataAccessException(int code, String message) { 21 | super(message); 22 | this.code = code; 23 | } 24 | 25 | public DataAccessException(String message, Throwable cause) { 26 | super(message, cause); 27 | } 28 | 29 | public DataAccessException(int code, String message, Throwable cause) { 30 | super(message, cause); 31 | this.code = code; 32 | } 33 | 34 | public int getCode() { 35 | return code; 36 | } 37 | 38 | public void setCode(int code) { 39 | this.code = code; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /auth-service/src/main/java/com/quebic/auth/api/service/impl/RoleServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.quebic.auth.api.service.impl; 2 | 3 | import javax.annotation.PostConstruct; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.stereotype.Service; 6 | 7 | import com.quebic.auth.api.dao.RoleDao; 8 | import com.quebic.auth.api.model.Role; 9 | import com.quebic.auth.api.service.RoleService; 10 | import com.quebic.common.dao.SequenceDao; 11 | import com.quebic.common.exception.DataAccessException; 12 | import com.quebic.common.service.impl.GenericServiceImpl; 13 | 14 | import rx.Single; 15 | 16 | @Service 17 | public class RoleServiceImpl extends GenericServiceImpl implements RoleService{ 18 | 19 | @Autowired 20 | protected RoleDao roleDao; 21 | 22 | @Autowired 23 | protected SequenceDao sequenceDao; 24 | 25 | @PostConstruct 26 | void init() { 27 | init(Role.class, roleDao); 28 | } 29 | 30 | @Override 31 | public Single add(Role role){ 32 | try{ 33 | roleDao.add(role); 34 | return Single.just(role); 35 | }catch (DataAccessException e) { 36 | return Single.error(e); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /auth-service/src/main/java/com/quebic/auth/api/security/SecurityUtil.java: -------------------------------------------------------------------------------- 1 | package com.quebic.auth.api.security; 2 | 3 | import org.springframework.security.core.context.SecurityContextHolder; 4 | import org.springframework.security.core.userdetails.UserDetails; 5 | 6 | import com.quebic.auth.api.model.User; 7 | 8 | public class SecurityUtil { 9 | 10 | public static UserDetails getLoggedUserDetails() { 11 | Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal(); 12 | 13 | if (principal instanceof UserDetails) 14 | return (UserDetails) principal; 15 | 16 | return null; 17 | } 18 | 19 | public static JwtUser getLoggedJwtUser() { 20 | Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal(); 21 | 22 | if (principal instanceof UserDetails) { 23 | 24 | UserDetails userDetails = (UserDetails) principal; 25 | JwtUser jwtUser = (JwtUser) userDetails; 26 | 27 | return jwtUser; 28 | } 29 | 30 | return null; 31 | } 32 | 33 | public static User getLoggedDbUser() { 34 | return getLoggedJwtUser().getDbUser(); 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /auth-service/src/main/java/com/quebic/auth/api/security/JwtAuthenticationEntryPoint.java: -------------------------------------------------------------------------------- 1 | package com.quebic.auth.api.security; 2 | 3 | import org.springframework.security.core.AuthenticationException; 4 | import org.springframework.security.web.AuthenticationEntryPoint; 5 | import org.springframework.stereotype.Component; 6 | 7 | import javax.servlet.http.HttpServletRequest; 8 | import javax.servlet.http.HttpServletResponse; 9 | import java.io.IOException; 10 | import java.io.Serializable; 11 | 12 | @Component 13 | public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint, Serializable { 14 | 15 | private static final long serialVersionUID = -8970718410437077606L; 16 | 17 | @Override 18 | public void commence(HttpServletRequest request, 19 | HttpServletResponse response, 20 | AuthenticationException authException) throws IOException { 21 | // This is invoked when user tries to access a secured REST resource without supplying any credentials 22 | // We should just send a 401 Unauthorized response because there is no 'login page' to redirect to 23 | response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized"); 24 | } 25 | } -------------------------------------------------------------------------------- /common-lib/src/main/java/com/quebic/common/security/CommonAuthenticationEntryPoint.java: -------------------------------------------------------------------------------- 1 | package com.quebic.common.security; 2 | 3 | import org.springframework.security.core.AuthenticationException; 4 | import org.springframework.security.web.AuthenticationEntryPoint; 5 | import org.springframework.stereotype.Component; 6 | 7 | import javax.servlet.http.HttpServletRequest; 8 | import javax.servlet.http.HttpServletResponse; 9 | import java.io.IOException; 10 | import java.io.Serializable; 11 | 12 | @Component 13 | public class CommonAuthenticationEntryPoint implements AuthenticationEntryPoint, Serializable { 14 | 15 | private static final long serialVersionUID = -8970718410437077606L; 16 | 17 | @Override 18 | public void commence(HttpServletRequest request, 19 | HttpServletResponse response, 20 | AuthenticationException authException) throws IOException { 21 | // This is invoked when user tries to access a secured REST resource without supplying any credentials 22 | // We should just send a 401 Unauthorized response because there is no 'login page' to redirect to 23 | response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized"); 24 | } 25 | } -------------------------------------------------------------------------------- /auth-service/src/main/java/com/quebic/auth/api/controller/SellerController.java: -------------------------------------------------------------------------------- 1 | package com.quebic.auth.api.controller; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.http.HttpStatus; 5 | import org.springframework.web.bind.annotation.*; 6 | import com.quebic.auth.api.model.Role; 7 | import com.quebic.auth.api.model.SellerProfile; 8 | import com.quebic.auth.api.model.User; 9 | import com.quebic.auth.api.service.UserService; 10 | import com.quebic.common.async.response.AsyncResponseEntity; 11 | import com.quebic.common.util.ControllerBase; 12 | 13 | @RestController 14 | @RequestMapping("/sellers") 15 | public class SellerController extends ControllerBase { 16 | 17 | @Autowired 18 | private UserService userService; 19 | 20 | @RequestMapping(method = RequestMethod.POST) 21 | public AsyncResponseEntity save(@ModelAttribute User user) { 22 | user.getRoles().add(Role.Create_Seller_Admin()); 23 | 24 | SellerProfile sellerProfile = new SellerProfile(); 25 | user.setSellerProfile(sellerProfile); 26 | 27 | user.setBuyerProfile(null); 28 | return makeAsyncResponse(userService.add(user), HttpStatus.CREATED); 29 | } 30 | 31 | 32 | } 33 | -------------------------------------------------------------------------------- /common-lib/src/main/java/com/quebic/common/sse/SseEmitterApplicationEventListener.java: -------------------------------------------------------------------------------- 1 | package com.quebic.common.sse; 2 | 3 | import java.io.IOException; 4 | import java.util.Hashtable; 5 | import java.util.Map; 6 | import org.springframework.context.event.EventListener; 7 | import org.springframework.http.MediaType; 8 | import org.springframework.stereotype.Component; 9 | import org.springframework.web.servlet.mvc.method.annotation.SseEmitter; 10 | 11 | @Component 12 | public class SseEmitterApplicationEventListener { 13 | 14 | @EventListener 15 | public void submissionEventHandler(SubmissionEvent event) throws IOException { 16 | 17 | String key = event.getKey(); 18 | Object message = event.getMessage(); 19 | 20 | SseEmitter sseEmitter = sseEmitters.get(key); 21 | 22 | if ( sseEmitter == null ) { 23 | return; 24 | } 25 | 26 | sseEmitter.send(message, MediaType.APPLICATION_JSON); 27 | } 28 | 29 | public void addSseEmitters(ListenerType listenerType ,String id, SseEmitter sseEmitter) { 30 | sseEmitters.put(listenerType.prepareKey(id), sseEmitter); 31 | } 32 | 33 | private static Map sseEmitters = new Hashtable<>(); 34 | 35 | } 36 | -------------------------------------------------------------------------------- /auth-service/src/main/java/com/quebic/auth/api/model/EmailVerification.java: -------------------------------------------------------------------------------- 1 | package com.quebic.auth.api.model; 2 | 3 | import java.sql.Timestamp; 4 | import java.util.Calendar; 5 | import java.util.Date; 6 | 7 | public class EmailVerification { 8 | 9 | private static final int EXPIRATION = 60 * 24; 10 | 11 | private String token; 12 | 13 | private Date expiryDate; 14 | 15 | //true => if user verify from email 16 | private boolean isVerify; 17 | 18 | public String getToken() { 19 | return token; 20 | } 21 | 22 | public void setToken(String token) { 23 | this.token = token; 24 | } 25 | 26 | public Date getExpiryDate() { 27 | return expiryDate; 28 | } 29 | 30 | public void setExpiryDate(Date expiryDate) { 31 | this.expiryDate = expiryDate; 32 | } 33 | 34 | public boolean isVerify() { 35 | return isVerify; 36 | } 37 | 38 | public void setVerify(boolean isVerify) { 39 | this.isVerify = isVerify; 40 | } 41 | 42 | public EmailVerification calculateExpiryDate() { 43 | Calendar cal = Calendar.getInstance(); 44 | cal.setTime(new Timestamp(cal.getTime().getTime())); 45 | cal.add(Calendar.MINUTE, EXPIRATION); 46 | this.expiryDate = new Date(cal.getTime().getTime()); 47 | return this; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /auth-service/src/main/java/com/quebic/auth/api/service/impl/PermissionServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.quebic.auth.api.service.impl; 2 | 3 | import javax.annotation.PostConstruct; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.stereotype.Service; 6 | 7 | import com.quebic.auth.api.dao.PermissionDao; 8 | import com.quebic.auth.api.service.PermissionService; 9 | import com.quebic.common.dao.SequenceDao; 10 | import com.quebic.common.exception.DataAccessException; 11 | import com.quebic.common.model.Permission; 12 | import com.quebic.common.service.impl.GenericServiceImpl; 13 | 14 | import rx.Single;; 15 | 16 | @Service 17 | public class PermissionServiceImpl extends GenericServiceImpl implements PermissionService{ 18 | 19 | @Autowired 20 | protected PermissionDao permissionDao; 21 | 22 | @Autowired 23 | protected SequenceDao sequenceDao; 24 | 25 | @PostConstruct 26 | void init() { 27 | init(Permission.class, permissionDao); 28 | } 29 | 30 | @Override 31 | public Single add(Permission permission){ 32 | try{ 33 | permissionDao.add(permission); 34 | return Single.just(permission); 35 | }catch (DataAccessException e) { 36 | return Single.error(e); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # microservices-sample-project 2 | 3 | ### Prerequisities 4 | * JDK 1.8.X 5 | * Maven 3.3.X 6 | * MongoDB 7 | 8 | ### install common-lib 9 | * go inside to the common-lib project folder 10 | * then run ``` mvn clean install ``` 11 | 12 | ### run discovery-server 13 | * go inside to the discovery-server project folder 14 | * then run ``` mvn clean package ``` 15 | * then run ``` java -jar target\discovery-server-0.0.1-SNAPSHOT.jar ``` 16 | 17 | ### run api-gateway 18 | * go inside to the api-gateway project folder 19 | * then run ``` mvn clean package ``` 20 | * then run ``` java -jar target\api-gateway-0.0.1-SNAPSHOT.jar ``` 21 | 22 | ### run auth-service 23 | * go inside to the auth-service project folder 24 | * then run ``` mvn clean package ``` 25 | * then run ``` java -jar target\auth-service-0.0.1-SNAPSHOT.jar ``` 26 | 27 | ### auth-service init 28 | * make request for the auth-service for setup roles and permissions. 29 | * ``` POST /api/auth-service/roles-permissions-setup/init ``` 30 | 31 | ### run product-service 32 | * go inside to the product-service project folder 33 | * then run ``` mvn clean package ``` 34 | * then run ``` java -jar target\product-service-0.0.1-SNAPSHOT.jar ``` 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /product-service/src/main/java/com/quebic/product/api/service/impl/ProductServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.quebic.product.api.service.impl; 2 | 3 | import javax.annotation.PostConstruct; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.stereotype.Service; 6 | 7 | import com.quebic.common.security.SecurityUtil; 8 | import com.quebic.common.service.impl.GenericServiceImpl; 9 | import com.quebic.product.api.dao.ProductDao; 10 | import com.quebic.product.api.model.Product; 11 | import com.quebic.product.api.service.ProductService; 12 | 13 | import rx.Single; 14 | 15 | @Service 16 | public class ProductServiceImpl extends GenericServiceImpl implements ProductService { 17 | 18 | @Autowired 19 | private ProductDao productDao; 20 | 21 | @PostConstruct 22 | void init() { 23 | init(Product.class, productDao); 24 | } 25 | 26 | @Override 27 | public Single add(Product product) { 28 | String sellerId = SecurityUtil.getAuthUserDetails().getUserId(); 29 | product.setSellerId(sellerId); 30 | return super.add(product); 31 | } 32 | 33 | @Override 34 | public Single edit(Product product) { 35 | String sellerId = SecurityUtil.getAuthUserDetails().getUserId(); 36 | product.setSellerId(sellerId); 37 | return super.edit(product); 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /common-lib/src/main/java/com/quebic/common/async/deferred/SingleDeferredResult.java: -------------------------------------------------------------------------------- 1 | package com.quebic.common.async.deferred; 2 | 3 | import org.springframework.http.HttpStatus; 4 | import org.springframework.http.ResponseEntity; 5 | import org.springframework.util.MultiValueMap; 6 | import org.springframework.web.context.request.async.DeferredResult; 7 | import rx.Single; 8 | 9 | public class SingleDeferredResult extends DeferredResult> { 10 | 11 | private static final Object EMPTY_RESULT = new Object(); 12 | 13 | public SingleDeferredResult( 14 | Single single 15 | , MultiValueMap headers 16 | , HttpStatus status) { 17 | this(null, EMPTY_RESULT, single, headers, status); 18 | } 19 | 20 | public SingleDeferredResult( 21 | long timeout 22 | , Single single 23 | , MultiValueMap headers 24 | , HttpStatus status) { 25 | this(timeout, EMPTY_RESULT, single, headers, status); 26 | } 27 | 28 | public SingleDeferredResult( 29 | Long timeout 30 | , Object timeoutResult 31 | , Single single 32 | , MultiValueMap headers 33 | , HttpStatus status) { 34 | super(timeout, timeoutResult); 35 | new DeferredResultWriter(single.toObservable(), this, headers, status); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /common-lib/src/main/java/com/quebic/common/async/AsyncConfig.java: -------------------------------------------------------------------------------- 1 | package com.quebic.common.async; 2 | 3 | import java.util.List; 4 | import org.springframework.context.annotation.Bean; 5 | import org.springframework.context.annotation.Configuration; 6 | import org.springframework.web.method.support.AsyncHandlerMethodReturnValueHandler; 7 | import org.springframework.web.method.support.HandlerMethodReturnValueHandler; 8 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; 9 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; 10 | 11 | import com.quebic.common.async.handlers.AsyncResponseEntityReturnHandler; 12 | 13 | @Configuration 14 | public class AsyncConfig { 15 | 16 | @Bean 17 | public AsyncResponseEntityReturnHandler asyncResponseEntityHandler() { 18 | return new AsyncResponseEntityReturnHandler(); 19 | } 20 | 21 | @Bean 22 | public WebMvcConfigurer rxJavaWebMvcConfiguration(List handlers) { 23 | return new WebMvcConfigurerAdapter() { 24 | @Override 25 | public void addReturnValueHandlers(List returnValueHandlers) { 26 | if (handlers != null) { 27 | returnValueHandlers.addAll(handlers); 28 | } 29 | } 30 | }; 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /common-lib/src/main/java/com/quebic/common/async/deferred/ObservableDeferredResult.java: -------------------------------------------------------------------------------- 1 | package com.quebic.common.async.deferred; 2 | 3 | import org.springframework.http.HttpStatus; 4 | import org.springframework.http.ResponseEntity; 5 | import org.springframework.util.MultiValueMap; 6 | import org.springframework.web.context.request.async.DeferredResult; 7 | import rx.Observable; 8 | import java.util.List; 9 | 10 | public class ObservableDeferredResult extends DeferredResult>> { 11 | 12 | private static final Object EMPTY_RESULT = new Object(); 13 | 14 | public ObservableDeferredResult( 15 | Observable observable 16 | , MultiValueMap headers 17 | , HttpStatus status) { 18 | this(null, EMPTY_RESULT, observable, headers, status); 19 | } 20 | 21 | public ObservableDeferredResult( 22 | Long timeout 23 | , Observable observable 24 | , MultiValueMap headers 25 | , HttpStatus status) { 26 | this(timeout, EMPTY_RESULT, observable, headers, status); 27 | } 28 | 29 | public ObservableDeferredResult( 30 | Long timeout 31 | , Object timeoutResult 32 | , Observable observable 33 | , MultiValueMap headers 34 | , HttpStatus status) { 35 | super(timeout, timeoutResult); 36 | new DeferredResultWriter>(observable.toList(), this, headers, status); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /auth-service/src/main/java/com/quebic/auth/api/common/util/email/template/impl/UserVerificationEmailTemplate.java: -------------------------------------------------------------------------------- 1 | package com.quebic.auth.api.common.util.email.template.impl; 2 | 3 | import java.io.IOException; 4 | import java.io.InputStream; 5 | import org.springframework.core.io.ClassPathResource; 6 | import org.springframework.core.io.Resource; 7 | 8 | import com.quebic.auth.api.common.util.email.template.EmailTemplate; 9 | import com.quebic.auth.api.model.User; 10 | 11 | public class UserVerificationEmailTemplate implements EmailTemplate{ 12 | 13 | private String templateFile; 14 | private User user; 15 | private String token; 16 | 17 | public UserVerificationEmailTemplate(String templateFile, User user, String token) { 18 | this.templateFile = templateFile; 19 | this.user = user; 20 | this.token = token; 21 | } 22 | 23 | @Override 24 | public String getTextContent() throws Exception{ 25 | 26 | Resource resource = new ClassPathResource(templateFile); 27 | try { 28 | byte[] bytes = new byte[1024]; 29 | InputStream resourceInputStream = resource.getInputStream(); 30 | StringBuilder str = new StringBuilder(); 31 | int read = resourceInputStream.read(bytes); 32 | while(read != -1){ 33 | str.append(new String(bytes)); 34 | read = resourceInputStream.read(bytes); 35 | } 36 | String htmlString = str.toString(); 37 | return String.format(htmlString, user.getFirstName(), token); 38 | } catch (IOException e) { 39 | throw new Exception("UserVerificationEmailTemplate Genarating Error", e); 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /common-lib/src/main/java/com/quebic/common/model/EntityBase.java: -------------------------------------------------------------------------------- 1 | package com.quebic.common.model; 2 | 3 | import org.springframework.data.annotation.Id; 4 | 5 | public abstract class EntityBase{ 6 | 7 | public static final Integer STATUS_INACTIVE = 0; 8 | public static final Integer STATUS_ACTIVE = 1; 9 | public static final Integer STATUS_DELETED = -1; 10 | 11 | @Id 12 | private String id; 13 | 14 | private Integer status = 1; //default status 15 | 16 | public EntityBase() { 17 | } 18 | 19 | public EntityBase(String id) { 20 | this.id = id; 21 | } 22 | 23 | public String getId() { 24 | return id; 25 | } 26 | 27 | public void setId(String id) { 28 | this.id = id; 29 | } 30 | 31 | public Integer getStatus() { 32 | return status; 33 | } 34 | 35 | public void setStatus(Integer status) { 36 | this.status = status; 37 | } 38 | 39 | @Override 40 | public int hashCode() { 41 | int hash = 0; 42 | hash += (id != null ? id.hashCode() : 0); 43 | return hash; 44 | } 45 | 46 | @Override 47 | public boolean equals(Object object) { 48 | if (!(object instanceof EntityBase)) { 49 | return false; 50 | } 51 | EntityBase other = (EntityBase) object; 52 | return !((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))); 53 | } 54 | 55 | @Override 56 | public String toString() { 57 | return "EntityBase{" + 58 | "id=" + id + 59 | '}'; 60 | } 61 | 62 | 63 | } 64 | -------------------------------------------------------------------------------- /common-lib/src/main/java/com/quebic/common/async/deferred/DeferredResultWriter.java: -------------------------------------------------------------------------------- 1 | package com.quebic.common.async.deferred; 2 | 3 | import org.springframework.http.HttpStatus; 4 | import org.springframework.http.ResponseEntity; 5 | import org.springframework.util.MultiValueMap; 6 | import org.springframework.web.context.request.async.DeferredResult; 7 | import rx.Observable; 8 | import rx.Subscriber; 9 | 10 | public class DeferredResultWriter extends Subscriber implements Runnable{ 11 | 12 | private final DeferredResult> deferredResult; 13 | private final MultiValueMap headers; 14 | private final HttpStatus status; 15 | 16 | public DeferredResultWriter( 17 | Observable observable 18 | , DeferredResult> deferredResult 19 | , MultiValueMap headers 20 | , HttpStatus status) { 21 | 22 | this.deferredResult = deferredResult; 23 | this.headers = headers; 24 | this.status = status; 25 | 26 | this.deferredResult.onTimeout(this); 27 | this.deferredResult.onCompletion(this); 28 | observable.subscribe(this); 29 | } 30 | 31 | @Override 32 | public void onNext(T value) { 33 | deferredResult.setResult(new ResponseEntity<>(value, headers, status)); 34 | } 35 | 36 | @Override 37 | public void onError(Throwable e) { 38 | deferredResult.setErrorResult(e); 39 | } 40 | 41 | @Override 42 | public void run() { 43 | this.unsubscribe(); 44 | } 45 | 46 | @Override 47 | public void onCompleted() { 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /common-lib/src/main/java/com/quebic/common/dao/GenericDao.java: -------------------------------------------------------------------------------- 1 | package com.quebic.common.dao; 2 | 3 | import java.util.List; 4 | import org.springframework.data.mongodb.core.MongoOperations; 5 | 6 | import com.quebic.common.exception.DataAccessException; 7 | 8 | public interface GenericDao { 9 | /** 10 | * This method delete given object from the database. 11 | * 12 | * @param id - Object id to load 13 | * @throws DataAccessException - throws if an error occurs 14 | */ 15 | T getById(Object id) throws DataAccessException; 16 | 17 | /** 18 | * This method queries all the objects 19 | * 20 | * @throws DataAccessException - throws if an error occurs 21 | */ 22 | List getAll() throws DataAccessException; 23 | 24 | /** 25 | * This method insert a given object to the database. 26 | * 27 | * @param object - instance of Object class 28 | * @throws DataAccessException - throws if an error occurs 29 | */ 30 | T add(T object) throws DataAccessException; 31 | 32 | /** 33 | * This method update given object in the database. 34 | * 35 | * @param object - instance of Object class 36 | * @throws DataAccessException - throws if an error occurs 37 | */ 38 | T modify(T object) throws DataAccessException; 39 | 40 | /** 41 | * This method delete given object from the database. 42 | * 43 | * @param object - instance of Object class 44 | * @throws DataAccessException - throws if an error occurs 45 | */ 46 | T delete(T object) throws DataAccessException; 47 | 48 | MongoOperations getMongoOperations(); 49 | 50 | 51 | } 52 | -------------------------------------------------------------------------------- /common-lib/src/main/java/com/quebic/common/dao/impl/SequenceDaoImpl.java: -------------------------------------------------------------------------------- 1 | package com.quebic.common.dao.impl; 2 | 3 | import org.springframework.data.mongodb.core.FindAndModifyOptions; 4 | import org.springframework.data.mongodb.core.query.Criteria; 5 | import org.springframework.data.mongodb.core.query.Query; 6 | import org.springframework.data.mongodb.core.query.Update; 7 | import org.springframework.stereotype.Repository; 8 | 9 | import com.quebic.common.dao.SequenceDao; 10 | import com.quebic.common.exception.DataAccessException; 11 | import com.quebic.common.model.Sequence; 12 | 13 | @Repository 14 | public class SequenceDaoImpl extends GenericDaoImplimplements SequenceDao { 15 | 16 | public SequenceDaoImpl() { 17 | super(Sequence.class); 18 | } 19 | 20 | @Override 21 | public int getNextSequenceId(String key) throws DataAccessException { 22 | 23 | //get sequence id 24 | Query query = new Query(Criteria.where("id").is(key)); 25 | 26 | //increase sequence id by 1 27 | Update update = new Update(); 28 | update.inc("seq", 1); 29 | 30 | //return new increased id 31 | FindAndModifyOptions options = new FindAndModifyOptions(); 32 | options.returnNew(true); 33 | 34 | //this is the magic happened. 35 | Sequence seqId = mongoOperations.findAndModify(query, update, options, Sequence.class); 36 | 37 | // if no id, throws SequenceException 38 | // optional, just a way to tell user when the sequence id is failed to 39 | // generate. 40 | if (seqId == null) { 41 | seqId = new Sequence(); 42 | seqId.setId(key); 43 | seqId.setSeq(1); 44 | mongoOperations.insert(seqId); 45 | return 1; 46 | }else{ 47 | return seqId.getSeq(); 48 | } 49 | 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /common-lib/src/main/java/com/quebic/common/cache/CacheConfig.java: -------------------------------------------------------------------------------- 1 | package com.quebic.common.cache; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | import org.springframework.cache.CacheManager; 6 | import org.springframework.cache.concurrent.ConcurrentMapCache; 7 | import org.springframework.cache.interceptor.CacheResolver; 8 | import org.springframework.cache.interceptor.KeyGenerator; 9 | import org.springframework.cache.support.SimpleCacheManager; 10 | import org.springframework.context.annotation.Bean; 11 | import org.springframework.context.annotation.Configuration; 12 | 13 | @Configuration 14 | public class CacheConfig { 15 | 16 | private static final String SUFFIX = "secondary"; 17 | private static final String CONCAT = ":"; 18 | 19 | public static CacheManager createCacheManager(String... caches) { 20 | List concurrentMapCaches = new ArrayList<>(); 21 | for(String cacheName : caches){ 22 | concurrentMapCaches.add(new ConcurrentMapCache(cacheName)); 23 | concurrentMapCaches.add(new ConcurrentMapCache(cacheName + CONCAT + SUFFIX)); 24 | } 25 | 26 | SimpleCacheManager cacheManager = new SimpleCacheManager(); 27 | cacheManager.setCaches(concurrentMapCaches); 28 | return cacheManager; 29 | } 30 | 31 | @Bean 32 | public CacheResolver primaryCacheResolver(CacheManager cacheManager){ 33 | return new ClassNameBasedCacheResolver(cacheManager); 34 | } 35 | 36 | @Bean 37 | public CacheResolver secondaryCacheResolver(CacheManager cacheManager){ 38 | return new ClassNameBasedCacheResolver(cacheManager, SUFFIX, CONCAT); 39 | } 40 | 41 | @Bean 42 | public KeyGenerator customKeyGenerator(){ 43 | return new MethodSignatureBasedKeyGenerator(); 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /product-service/src/main/java/com/quebic/product/api/controller/ProductController.java: -------------------------------------------------------------------------------- 1 | package com.quebic.product.api.controller; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.http.HttpStatus; 5 | import org.springframework.web.bind.annotation.ModelAttribute; 6 | import org.springframework.web.bind.annotation.PathVariable; 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.quebic.common.async.response.AsyncResponseEntity; 12 | import com.quebic.common.util.ControllerBase; 13 | import com.quebic.product.api.model.Product; 14 | import com.quebic.product.api.service.ProductService; 15 | 16 | @RestController 17 | @RequestMapping("/products") 18 | public class ProductController extends ControllerBase{ 19 | 20 | @Autowired 21 | private ProductService productService; 22 | 23 | @RequestMapping 24 | public AsyncResponseEntity getAll() { 25 | return makeAsyncResponse(productService.getAll()); 26 | } 27 | 28 | @RequestMapping("/{id}") 29 | public AsyncResponseEntity getById(@PathVariable("id") String id) { 30 | return makeAsyncResponse(productService.getById(id)); 31 | } 32 | 33 | @RequestMapping(method = RequestMethod.POST) 34 | public AsyncResponseEntity add(@ModelAttribute Product product) { 35 | return makeAsyncResponse(productService.add(product), HttpStatus.CREATED); 36 | } 37 | 38 | @RequestMapping(method = RequestMethod.PUT) 39 | public AsyncResponseEntity edit(@ModelAttribute Product product) { 40 | return makeAsyncResponse(productService.edit(product), HttpStatus.ACCEPTED); 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /auth-service/src/main/java/com/quebic/auth/api/service/impl/SellerServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.quebic.auth.api.service.impl; 2 | 3 | import javax.annotation.PostConstruct; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.stereotype.Service; 6 | import org.springframework.util.StringUtils; 7 | 8 | import com.quebic.auth.api.dao.UserDao; 9 | import com.quebic.auth.api.model.Role; 10 | import com.quebic.auth.api.model.User; 11 | import com.quebic.auth.api.security.SecurityUtil; 12 | import com.quebic.auth.api.service.SellerService; 13 | import com.quebic.auth.api.service.UserService; 14 | import com.quebic.common.exception.BadRequestException; 15 | import com.quebic.common.messages.ErrorMessage; 16 | import com.quebic.common.service.impl.GenericServiceImpl; 17 | 18 | import rx.Single; 19 | import rx.exceptions.Exceptions; 20 | 21 | @Service 22 | public class SellerServiceImpl extends GenericServiceImpl implements SellerService { 23 | 24 | @Autowired 25 | private UserDao sellerDao; 26 | 27 | @Autowired 28 | private UserService userService; 29 | 30 | @PostConstruct 31 | void init() { 32 | init(User.class, sellerDao); 33 | } 34 | 35 | @Override 36 | public Single registerOtherSeller(User seller) { 37 | 38 | User loggedUser = SecurityUtil.getLoggedDbUser(); 39 | 40 | return getById(loggedUser.getId()).flatMap(u->{ 41 | 42 | String storeId = u.getSellerProfile().getStoreId(); 43 | 44 | if(StringUtils.isEmpty(storeId)) 45 | Exceptions.propagate(new BadRequestException(ErrorMessage.STORE_ID_IS_NULL)); 46 | 47 | seller.getSellerProfile().setStoreId(storeId); 48 | seller.getRoles().add(Role.Create_Seller()); 49 | seller.setBuyerProfile(null); 50 | 51 | return userService.add(seller); 52 | 53 | }); 54 | 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /common-lib/src/main/java/com/quebic/common/security/AuthUser.java: -------------------------------------------------------------------------------- 1 | package com.quebic.common.security; 2 | 3 | import java.util.Collection; 4 | import org.springframework.security.core.GrantedAuthority; 5 | import org.springframework.security.core.userdetails.UserDetails; 6 | 7 | public class AuthUser implements UserDetails { 8 | 9 | private static final long serialVersionUID = 2061709915172252885L; 10 | private String userId; 11 | private String username; 12 | private Collection authorities; 13 | private boolean enabled; 14 | 15 | public AuthUser(String userId, String username, Collection authorities, boolean enabled) { 16 | this.userId = userId; 17 | this.username = username; 18 | this.authorities = authorities; 19 | this.enabled = enabled; 20 | } 21 | 22 | public String getUserId() { 23 | return userId; 24 | } 25 | 26 | @Override 27 | public String getUsername() { 28 | return username; 29 | } 30 | 31 | @Override 32 | public String getPassword() { 33 | return ""; 34 | } 35 | 36 | @Override 37 | public boolean isAccountNonExpired() { 38 | return true; 39 | } 40 | 41 | @Override 42 | public boolean isAccountNonLocked() { 43 | return true; 44 | } 45 | 46 | @Override 47 | public boolean isCredentialsNonExpired() { 48 | return true; 49 | } 50 | 51 | @Override 52 | public Collection getAuthorities() { 53 | return authorities; 54 | } 55 | 56 | @Override 57 | public boolean isEnabled() { 58 | return enabled; 59 | } 60 | 61 | @Override 62 | public String toString() { 63 | return "AuthUser [userId=" + userId + ", username=" + username + ", authorities=" + authorities + ", enabled=" 64 | + enabled + "]"; 65 | } 66 | 67 | } 68 | -------------------------------------------------------------------------------- /common-lib/src/main/java/com/quebic/common/messages/ErrorMessage.java: -------------------------------------------------------------------------------- 1 | package com.quebic.common.messages; 2 | 3 | public class ErrorMessage { 4 | public static final String USER_OBJECT_IS_NULL = "USER_OBJECT_IS_NULL"; 5 | public static final String SELLER_OBJECT_IS_NULL = "SELLER_OBJECT_IS_NULL"; 6 | public static final String CONTACT_INFO_OBJECT_IS_NULL = "CONTACT_INFO_OBJECT_IS_NULL"; 7 | public static final String MESSAGE_OBJECT_IS_NULL = "MESSAGE_OBJECT_IS_NULL"; 8 | public static final String COUNTERY_OBJECT_IS_NULL = "COUNTERY_OBJECT_IS_NULL"; 9 | public static final String ORDER_PROCESS_OBJECT_IS_NULL = "ORDER_PROCESS_OBJECT_IS_NULL"; 10 | public static final String STORE_OBJECT_IS_NULL = "STORE_OBJECT_IS_NULL"; 11 | public static final String STORE_ID_IS_NULL = "STORE_ID_IS_NULL"; 12 | public static final String VEHICLE_BODY_TYPE_OBJECT_IS_NULL = "VEHICLE_BODY_TYPE_OBJECT_IS_NULL"; 13 | public static final String VEHICLE_LOCATION_CONTAINER_OBJECT_IS_NULL = "VEHICLE_LOCATION_CONTAINER_OBJECT_IS_NULL"; 14 | public static final String VEHICLE_MAKE_OBJECT_IS_NULL = "VEHICLE_MAKE_OBJECT_IS_NULL"; 15 | public static final String VEHICLE_MODEL_OBJECT_IS_NULL = "VEHICLE_MODEL_OBJECT_IS_NULL"; 16 | public static final String VEHICLE_OBJECT_IS_NULL = "VEHICLE_OBJECT_IS_NULL"; 17 | public static final String SYSTEM_INTERNAL_AUTH_KEY_FAIL = "SYSTEM_INTERNAL_AUTH_KEY_FAIL"; 18 | 19 | public static final String USER_UNABLE_TO_LOAD_TOKEN = "USER_UNABLE_TO_LOAD_TOKEN"; 20 | public static final String USER_NOT_FOUND = "USER_NOT_FOUND"; 21 | public static final String EMPTY_USER_ID = "EMPTY_USER_ID"; 22 | public static final String DUPLICATE_USER = "DUPLICATE_USER"; 23 | public static final String RESOURCE_NOT_FOUND = "Resource Not Found (%1$s)"; 24 | public static final String UNAUTHORIZED_ACCESS = "Unauthorized Access (%1$s)"; 25 | public static final String VEHICLE_BODY_NAME_EMPTY = "VEHICLE_BODY_NAME_EMPTY"; 26 | } 27 | -------------------------------------------------------------------------------- /auth-service/src/main/java/com/quebic/auth/api/dao/impl/UserDaoImpl.java: -------------------------------------------------------------------------------- 1 | package com.quebic.auth.api.dao.impl; 2 | 3 | import java.util.List; 4 | 5 | import org.springframework.cache.annotation.CacheConfig; 6 | import org.springframework.cache.annotation.Cacheable; 7 | import org.springframework.data.mongodb.core.query.Criteria; 8 | import org.springframework.data.mongodb.core.query.Query; 9 | import org.springframework.stereotype.Repository; 10 | 11 | import com.quebic.auth.api.dao.UserDao; 12 | import com.quebic.auth.api.model.User; 13 | import com.quebic.common.dao.impl.GenericDaoImpl; 14 | import com.quebic.common.exception.DataAccessException; 15 | import com.quebic.common.model.Permission; 16 | 17 | @Repository 18 | @CacheConfig(cacheResolver="secondaryCacheResolver", keyGenerator="customKeyGenerator") 19 | @Cacheable(unless="#result == null") 20 | public class UserDaoImpl extends GenericDaoImpl implements UserDao{ 21 | 22 | public UserDaoImpl() { 23 | super(User.class); 24 | } 25 | 26 | @Override 27 | public User findByEmail(String email) throws DataAccessException { 28 | Query query = new Query(Criteria.where("email").is(email).and("status").is(1)); 29 | return mongoOperations.findOne(query, User.class); 30 | } 31 | 32 | @Override 33 | public User findByUsernameOrEmail(String username, String email) throws DataAccessException { 34 | Query query = new Query( 35 | Criteria 36 | .where("status").ne(-1) 37 | .orOperator( 38 | Criteria.where("username").is(username) 39 | ,Criteria.where("email").is(email) 40 | ) 41 | ); 42 | 43 | return mongoOperations.findOne(query, User.class); 44 | } 45 | 46 | @Override 47 | public List findUserPermissions() { 48 | return null; 49 | } 50 | 51 | @Override 52 | public User findUserByToken(String token) throws DataAccessException { 53 | Query query = new Query(Criteria.where("emailVerification.token").is(token)); 54 | return mongoOperations.findOne(query, User.class); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /auth-service/src/main/java/com/quebic/auth/api/security/JwtUser.java: -------------------------------------------------------------------------------- 1 | package com.quebic.auth.api.security; 2 | 3 | import java.util.Collection; 4 | import java.util.Date; 5 | import org.springframework.security.core.GrantedAuthority; 6 | import org.springframework.security.core.userdetails.UserDetails; 7 | import com.fasterxml.jackson.annotation.JsonIgnore; 8 | import com.quebic.auth.api.model.User; 9 | 10 | public class JwtUser implements UserDetails { 11 | 12 | private static final long serialVersionUID = -1728234246191170692L; 13 | 14 | private User user; 15 | private final Collection authorities; 16 | private final boolean enabled; 17 | 18 | public JwtUser( 19 | User user 20 | , Collection authorities 21 | , boolean enabled) { 22 | 23 | this.user = user; 24 | this.authorities = authorities; 25 | this.enabled = enabled; 26 | 27 | } 28 | 29 | public User getDbUser() { 30 | return user; 31 | } 32 | 33 | public Date getLastPasswordResetDate() { 34 | return user.getLastPasswordResetDate(); 35 | } 36 | 37 | @Override 38 | public String getUsername() { 39 | return user.getEmail(); 40 | } 41 | 42 | @JsonIgnore 43 | @Override 44 | public String getPassword() { 45 | return user.getPassword(); 46 | } 47 | 48 | @JsonIgnore 49 | @Override 50 | public boolean isAccountNonExpired() { 51 | return true; 52 | } 53 | 54 | @JsonIgnore 55 | @Override 56 | public boolean isAccountNonLocked() { 57 | return true; 58 | } 59 | 60 | @JsonIgnore 61 | @Override 62 | public boolean isCredentialsNonExpired() { 63 | return true; 64 | } 65 | 66 | @Override 67 | public Collection getAuthorities() { 68 | return authorities; 69 | } 70 | 71 | @Override 72 | public boolean isEnabled() { 73 | return enabled; 74 | } 75 | 76 | } 77 | -------------------------------------------------------------------------------- /common-lib/src/main/java/com/quebic/common/service/impl/GenericServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.quebic.common.service.impl; 2 | 3 | import com.quebic.common.dao.GenericDao; 4 | import com.quebic.common.exception.DataAccessException; 5 | import com.quebic.common.exception.ResourceNotFoundException; 6 | import com.quebic.common.service.GenericService; 7 | 8 | import rx.Observable; 9 | import rx.Single; 10 | import rx.exceptions.Exceptions; 11 | 12 | public class GenericServiceImpl implements GenericService { 13 | 14 | private Class type; 15 | protected GenericDao genericDao; 16 | 17 | protected void init(Class type, GenericDao dao) { 18 | this.type = type; 19 | this.genericDao = dao; 20 | } 21 | 22 | @Override 23 | public Single getById(String id){ 24 | try { 25 | return Single.just(genericDao.getById(id)).map(o->{ 26 | if(o == null) 27 | throw Exceptions.propagate(new ResourceNotFoundException(type.getSimpleName() + " : " + id)); 28 | return o; 29 | }); 30 | } catch (DataAccessException de) { 31 | return Single.error(de); 32 | } 33 | } 34 | 35 | @Override 36 | public Single add(T obj){ 37 | try { 38 | genericDao.add(obj); 39 | return Single.just(obj); 40 | } catch (DataAccessException de) { 41 | return Single.error(de); 42 | } 43 | } 44 | 45 | @Override 46 | public Single edit(T obj){ 47 | try { 48 | genericDao.modify(obj); 49 | return Single.just(obj); 50 | } catch (DataAccessException de) { 51 | return Single.error(de); 52 | } 53 | } 54 | 55 | @Override 56 | public Single delete(T obj){ 57 | try { 58 | genericDao.delete(obj); 59 | return Single.just(true); 60 | } catch (DataAccessException de) { 61 | return Single.error(de); 62 | } 63 | } 64 | 65 | @Override 66 | public Observable getAll(){ 67 | try { 68 | return Observable.from(genericDao.getAll()); 69 | } catch (DataAccessException de) { 70 | return Observable.error(de); 71 | } 72 | } 73 | 74 | } 75 | -------------------------------------------------------------------------------- /common-lib/src/main/java/com/quebic/common/util/image/ImageUtil.java: -------------------------------------------------------------------------------- 1 | package com.quebic.common.util.image; 2 | 3 | import java.util.concurrent.ThreadLocalRandom; 4 | import org.springframework.http.ResponseEntity; 5 | import org.springframework.web.multipart.MultipartFile; 6 | import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody; 7 | 8 | import com.quebic.common.util.image.impl.DropBoxStorageImageUtil; 9 | import com.quebic.common.util.image.impl.LocalStorageImageUtil; 10 | 11 | import rx.Single; 12 | 13 | public abstract class ImageUtil { 14 | 15 | public abstract Single storeFile(String id, String fileName, String fileLocation, String imageDir, MultipartFile multipartFile); 16 | public abstract ResponseEntity readFile(String fileLocation, String imageDir, String id, String fileName); 17 | public abstract void resizeImage(byte[] bytes, String dirStr, String fileName, int targetSize) throws Exception; 18 | 19 | public static ImageUtil createLocalStorageImageUtil(){ 20 | return new LocalStorageImageUtil(); 21 | } 22 | 23 | public static ImageUtil createDropBoxStorageImageUtil(){ 24 | return new DropBoxStorageImageUtil(); 25 | } 26 | 27 | protected String getFileExtension(String fileName) { 28 | if(fileName.lastIndexOf(".") != -1 && fileName.lastIndexOf(".") != 0) 29 | return fileName.substring(fileName.lastIndexOf(".")+1); 30 | else return ""; 31 | } 32 | 33 | protected String[] splitFileName(String fileName) { 34 | int splitPoint = fileName.lastIndexOf("."); 35 | String randomFileName =fileName.substring(0, splitPoint); 36 | String fileExtension = fileName.substring(splitPoint + 1, fileName.length()); 37 | 38 | return new String[]{randomFileName, fileExtension}; 39 | } 40 | 41 | public String genarateFileName(MultipartFile file){ 42 | 43 | String randomFileName = createRandomFileName(); 44 | 45 | String fileExtension = getFileExtension(file.getOriginalFilename()); 46 | 47 | String fileName = randomFileName + "." + fileExtension; 48 | 49 | return fileName; 50 | 51 | } 52 | 53 | protected String createRandomFileName(){ 54 | int min = 100; 55 | int max = 1000000; 56 | return String.valueOf(ThreadLocalRandom.current().nextInt(min, max + 1)); 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /common-lib/src/main/java/com/quebic/common/async/handlers/AsyncResponseEntityReturnHandler.java: -------------------------------------------------------------------------------- 1 | package com.quebic.common.async.handlers; 2 | 3 | import org.springframework.core.MethodParameter; 4 | import org.springframework.http.HttpStatus; 5 | import org.springframework.util.MultiValueMap; 6 | import org.springframework.web.context.request.NativeWebRequest; 7 | import org.springframework.web.context.request.async.WebAsyncUtils; 8 | import org.springframework.web.method.support.AsyncHandlerMethodReturnValueHandler; 9 | import org.springframework.web.method.support.ModelAndViewContainer; 10 | 11 | import com.quebic.common.async.deferred.ObservableDeferredResult; 12 | import com.quebic.common.async.deferred.SingleDeferredResult; 13 | import com.quebic.common.async.response.AsyncResponseEntity; 14 | 15 | import rx.Observable; 16 | import rx.Single; 17 | 18 | public class AsyncResponseEntityReturnHandler implements AsyncHandlerMethodReturnValueHandler{ 19 | 20 | @Override 21 | public boolean isAsyncReturnValue(Object returnValue, MethodParameter returnType) { 22 | return returnValue != null && supportsReturnType(returnType); 23 | } 24 | 25 | @Override 26 | public boolean supportsReturnType(MethodParameter returnType) { 27 | return AsyncResponseEntity.class.isAssignableFrom(returnType.getParameterType()); 28 | } 29 | 30 | @Override 31 | public void handleReturnValue(Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception { 32 | 33 | if (returnValue == null) { 34 | mavContainer.setRequestHandled(true); 35 | return; 36 | } 37 | 38 | final AsyncResponseEntity asyncResponseEntity = AsyncResponseEntity.class.cast(returnValue); 39 | 40 | Observable observable = asyncResponseEntity.getObservable(); 41 | Single single = asyncResponseEntity.getSingle(); 42 | MultiValueMap headers = asyncResponseEntity.getHeaders(); 43 | HttpStatus status = asyncResponseEntity.getStatus(); 44 | 45 | if(observable != null) 46 | WebAsyncUtils.getAsyncManager(webRequest).startDeferredResultProcessing(new ObservableDeferredResult<>(observable, headers, status), mavContainer); 47 | else if(single != null) 48 | WebAsyncUtils.getAsyncManager(webRequest).startDeferredResultProcessing(new SingleDeferredResult<>(single, headers, status), mavContainer); 49 | 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /auth-service/src/main/java/com/quebic/auth/api/model/Role.java: -------------------------------------------------------------------------------- 1 | package com.quebic.auth.api.model; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | import org.springframework.data.mongodb.core.mapping.DBRef; 6 | import org.springframework.data.mongodb.core.mapping.Document; 7 | import com.fasterxml.jackson.annotation.JsonIgnore; 8 | import com.quebic.common.model.EntityBase; 9 | import com.quebic.common.model.Permission; 10 | 11 | @Document(collection="Role") 12 | public class Role extends EntityBase{ 13 | 14 | public static final String ROLE_ADMIN = "role.admin"; 15 | public static final String ROLE_SELLER_ADMIN = "role.seller.admin"; 16 | public static final String ROLE_SELLER = "role.seller"; 17 | public static final String ROLE_BUYER = "role.buyer"; 18 | 19 | private String code; 20 | 21 | @DBRef 22 | private List permissions = new ArrayList<>(); 23 | 24 | public Role() { 25 | } 26 | 27 | public Role(String id){ 28 | setId(id); 29 | } 30 | 31 | public String getCode() { 32 | return this.code; 33 | } 34 | 35 | public void setCode(String name) { 36 | this.code = name; 37 | } 38 | 39 | @JsonIgnore 40 | public List getPermissions() { 41 | return permissions; 42 | } 43 | 44 | public void setPermissions(List permissions) { 45 | this.permissions = permissions; 46 | } 47 | 48 | public static Role Create_Admin(){ 49 | return new Role(Role.ROLE_ADMIN); 50 | } 51 | 52 | public static Role Create_Seller_Admin(){ 53 | return new Role(Role.ROLE_SELLER_ADMIN); 54 | } 55 | 56 | public static Role Create_Seller(){ 57 | return new Role(Role.ROLE_SELLER); 58 | } 59 | 60 | public static Role Create_Buyer(){ 61 | return new Role(Role.ROLE_BUYER); 62 | } 63 | 64 | public static boolean checkUserIs_Admin(User user){ 65 | return checkUserType(user, Role.Create_Admin()); 66 | } 67 | 68 | public static boolean checkUserIs_Seller_Admin(User user){ 69 | return checkUserType(user, Role.Create_Seller_Admin()); 70 | } 71 | 72 | public static boolean checkUserIs_Seller(User user){ 73 | return checkUserType(user, Role.Create_Seller()); 74 | } 75 | 76 | public static boolean checkUserIs_Buyer(User user){ 77 | return checkUserType(user, Role.Create_Buyer()); 78 | } 79 | 80 | public static boolean checkUserType(User user, Role... roles){ 81 | 82 | for(Role checkRole : roles){ 83 | 84 | if(user.getRoles().contains(checkRole)) 85 | return true; 86 | 87 | } 88 | 89 | return false; 90 | 91 | 92 | } 93 | 94 | 95 | 96 | } 97 | -------------------------------------------------------------------------------- /auth-service/src/main/java/com/quebic/auth/api/controller/UserController.java: -------------------------------------------------------------------------------- 1 | package com.quebic.auth.api.controller; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.http.HttpStatus; 5 | import org.springframework.web.bind.annotation.ModelAttribute; 6 | import org.springframework.web.bind.annotation.PathVariable; 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.quebic.auth.api.dto.PasswordDto; 12 | import com.quebic.auth.api.dto.UserImageDto; 13 | import com.quebic.auth.api.model.User; 14 | import com.quebic.auth.api.service.UserService; 15 | import com.quebic.common.async.response.AsyncResponseEntity; 16 | import com.quebic.common.response.CommonResponse; 17 | import com.quebic.common.sse.ListenerType; 18 | import com.quebic.common.util.ControllerBase; 19 | 20 | @RestController 21 | @RequestMapping("/users") 22 | public class UserController extends ControllerBase { 23 | 24 | @Autowired 25 | private UserService userService; 26 | 27 | public UserController() { 28 | super(ListenerType.USER); 29 | } 30 | 31 | @RequestMapping 32 | public AsyncResponseEntity getAll() { 33 | return makeAsyncResponse(userService.getAll()); 34 | } 35 | 36 | @RequestMapping("/{id}") 37 | public AsyncResponseEntity getById(@PathVariable("id") String id) { 38 | return makeAsyncResponse(userService.getById(id)); 39 | } 40 | 41 | @RequestMapping(value = "/changePassword", method = RequestMethod.POST) 42 | public AsyncResponseEntity passwordChange(@ModelAttribute PasswordDto passwordDto) { 43 | return makeAsyncResponse( 44 | userService.changePassword(passwordDto.getOldPassword(), passwordDto.getNewPassword()) 45 | .map(r->new CommonResponse(1, r))); 46 | } 47 | 48 | @RequestMapping(method = RequestMethod.PUT) 49 | public AsyncResponseEntity update(@ModelAttribute User user) { 50 | return makeAsyncResponse(userService.edit(user, new UserImageDto()).map(i->{ 51 | publishMessage(i.getId(), i); 52 | return i; 53 | }), HttpStatus.ACCEPTED); 54 | } 55 | 56 | @RequestMapping(value="/updateFullProfile", method = RequestMethod.POST) 57 | public AsyncResponseEntity updateFullProfile(@ModelAttribute User user, @ModelAttribute UserImageDto imageDto) { 58 | return makeAsyncResponse(userService.edit(user, imageDto).map(i->{ 59 | publishMessage(i.getId(), i); 60 | return i; 61 | }), HttpStatus.ACCEPTED); 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /auth-service/src/main/java/com/quebic/auth/api/security/JwtAuthenticationTokenFilter.java: -------------------------------------------------------------------------------- 1 | package com.quebic.auth.api.security; 2 | 3 | import java.io.IOException; 4 | import javax.servlet.FilterChain; 5 | import javax.servlet.ServletException; 6 | import javax.servlet.http.HttpServletRequest; 7 | import javax.servlet.http.HttpServletResponse; 8 | 9 | import org.apache.commons.logging.Log; 10 | import org.apache.commons.logging.LogFactory; 11 | import org.springframework.beans.factory.annotation.Autowired; 12 | import org.springframework.beans.factory.annotation.Value; 13 | import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; 14 | import org.springframework.security.core.context.SecurityContextHolder; 15 | import org.springframework.security.core.userdetails.UserDetails; 16 | import org.springframework.security.core.userdetails.UserDetailsService; 17 | import org.springframework.security.web.authentication.WebAuthenticationDetailsSource; 18 | import org.springframework.web.filter.OncePerRequestFilter; 19 | 20 | public class JwtAuthenticationTokenFilter extends OncePerRequestFilter { 21 | 22 | private final Log logger = LogFactory.getLog(this.getClass()); 23 | 24 | @Autowired 25 | private UserDetailsService userDetailsService; 26 | 27 | @Autowired 28 | private JwtTokenUtil jwtTokenUtil; 29 | 30 | @Value("${jwt.header}") 31 | private String tokenHeader; 32 | 33 | @Override 34 | protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException { 35 | String authToken = request.getHeader(this.tokenHeader); 36 | // authToken.startsWith("Bearer ") 37 | // String authToken = header.substring(7); 38 | String username = jwtTokenUtil.getUsernameFromToken(authToken); 39 | 40 | logger.info("checking authentication user " + username); 41 | 42 | if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) { 43 | 44 | UserDetails userDetails = this.userDetailsService.loadUserByUsername(username); 45 | 46 | if (jwtTokenUtil.validateToken(authToken, userDetails)) { 47 | UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities()); 48 | authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); 49 | logger.info("authenticated user " + username + ", setting security context"); 50 | SecurityContextHolder.getContext().setAuthentication(authentication); 51 | } 52 | } 53 | 54 | chain.doFilter(request, response); 55 | } 56 | } -------------------------------------------------------------------------------- /auth-service/src/main/java/com/quebic/auth/api/security/service/JwtUserDetailsServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.quebic.auth.api.security.service; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Collection; 5 | import java.util.List; 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.security.core.GrantedAuthority; 10 | import org.springframework.security.core.authority.SimpleGrantedAuthority; 11 | import org.springframework.security.core.userdetails.UserDetails; 12 | import org.springframework.security.core.userdetails.UserDetailsService; 13 | import org.springframework.security.core.userdetails.UsernameNotFoundException; 14 | import org.springframework.stereotype.Service; 15 | 16 | import com.quebic.auth.api.model.User; 17 | import com.quebic.auth.api.security.JwtUser; 18 | import com.quebic.auth.api.service.UserService; 19 | import com.quebic.common.model.Permission; 20 | 21 | @Service 22 | public class JwtUserDetailsServiceImpl implements UserDetailsService { 23 | 24 | private Logger logger = LoggerFactory.getLogger(JwtUserDetailsServiceImpl.class); 25 | 26 | @Autowired 27 | private UserService userService; 28 | 29 | @Override 30 | public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { 31 | logger.debug("Loading user - {}", username); 32 | 33 | UserDetails userDetails; 34 | 35 | User user; 36 | 37 | try { 38 | 39 | if (logger.isDebugEnabled()) 40 | logger.debug("userService-{}", userService); 41 | 42 | //username may be email 43 | user = userService.findByUsernameOrEmail(username, username).toBlocking().value(); 44 | 45 | if (logger.isDebugEnabled()) 46 | logger.debug("user - {}", user); 47 | 48 | if (user == null) { 49 | throw new UsernameNotFoundException(username); 50 | } 51 | 52 | userDetails = new JwtUser( 53 | user 54 | , getAuthorities(user) 55 | , (user.getStatus() == 1)?true:false); 56 | 57 | if (userDetails.getAuthorities().isEmpty()) { 58 | logger.debug("User - {}, Permission count - 0", username); 59 | throw new UsernameNotFoundException(username); 60 | } 61 | 62 | return userDetails; 63 | 64 | } catch (Exception e) { 65 | if (logger.isErrorEnabled()) 66 | logger.error("Service call error", e); 67 | throw new UsernameNotFoundException(username); 68 | } 69 | 70 | } 71 | 72 | public Collection getAuthorities(User user) { 73 | 74 | List authList = new ArrayList<>(); 75 | for(Permission permission : user.getPermissions()){ 76 | authList.add(new SimpleGrantedAuthority("ROLE_" + permission.getCode())); 77 | } 78 | return authList; 79 | 80 | } 81 | 82 | } 83 | -------------------------------------------------------------------------------- /auth-service/src/main/java/com/quebic/auth/api/config/AppConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.quebic.auth.api.config; 2 | 3 | import java.util.Map; 4 | import org.springframework.boot.autoconfigure.web.DefaultErrorAttributes; 5 | import org.springframework.boot.autoconfigure.web.ErrorAttributes; 6 | import org.springframework.cache.CacheManager; 7 | import org.springframework.cloud.client.loadbalancer.LoadBalanced; 8 | import org.springframework.context.annotation.Bean; 9 | import org.springframework.context.annotation.Configuration; 10 | import org.springframework.context.annotation.Import; 11 | import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; 12 | import org.springframework.security.crypto.password.PasswordEncoder; 13 | import org.springframework.web.client.RestTemplate; 14 | import org.springframework.web.context.request.RequestAttributes; 15 | import org.springframework.web.servlet.config.annotation.CorsRegistry; 16 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; 17 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; 18 | 19 | import com.quebic.common.async.AsyncConfig; 20 | import com.quebic.common.cache.CacheConfig; 21 | import com.quebic.common.dao.DaoConfig; 22 | import com.quebic.common.sse.SseConfig; 23 | 24 | @Configuration 25 | @Import({AsyncConfig.class, SseConfig.class, DaoConfig.class, CacheConfig.class}) 26 | public class AppConfiguration { 27 | 28 | @Bean 29 | public ErrorAttributes errorAttributes() { 30 | 31 | return new DefaultErrorAttributes(){ 32 | @Override 33 | public Map getErrorAttributes(RequestAttributes requestAttributes, boolean includeStackTrace) { 34 | Map errorAttributes = super.getErrorAttributes(requestAttributes, includeStackTrace); 35 | errorAttributes.remove("exception"); 36 | return errorAttributes; 37 | } 38 | }; 39 | 40 | } 41 | 42 | @Bean 43 | public PasswordEncoder loadPasswordEncoder() { 44 | return new BCryptPasswordEncoder(); 45 | } 46 | 47 | /** 48 | * allow all origins - only for development mode 49 | * @return 50 | */ 51 | @Bean 52 | public WebMvcConfigurer corsConfigurer() { 53 | return new WebMvcConfigurerAdapter() { 54 | @Override 55 | public void addCorsMappings(CorsRegistry registry) { 56 | registry.addMapping("/**") 57 | .allowedMethods("*"); 58 | } 59 | }; 60 | } 61 | 62 | @Bean 63 | public CacheManager cacheManager() { 64 | return CacheConfig.createCacheManager( 65 | "UserDaoImpl" 66 | , "RoleDaoImpl" 67 | , "PermissionDaoImpl"); 68 | } 69 | 70 | @LoadBalanced 71 | @Bean 72 | public RestTemplate restTemplate() { 73 | return new RestTemplate(); 74 | } 75 | 76 | } 77 | -------------------------------------------------------------------------------- /product-service/src/main/java/com/quebic/product/api/config/AppConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.quebic.product.api.config; 2 | 3 | import java.util.Map; 4 | import org.springframework.boot.autoconfigure.web.DefaultErrorAttributes; 5 | import org.springframework.boot.autoconfigure.web.ErrorAttributes; 6 | import org.springframework.cache.CacheManager; 7 | import org.springframework.cloud.client.loadbalancer.LoadBalanced; 8 | import org.springframework.context.annotation.Bean; 9 | import org.springframework.context.annotation.Configuration; 10 | import org.springframework.context.annotation.Import; 11 | import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; 12 | import org.springframework.security.crypto.password.PasswordEncoder; 13 | import org.springframework.web.client.RestTemplate; 14 | import org.springframework.web.context.request.RequestAttributes; 15 | import org.springframework.web.servlet.config.annotation.CorsRegistry; 16 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; 17 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; 18 | import com.quebic.common.async.AsyncConfig; 19 | import com.quebic.common.cache.CacheConfig; 20 | import com.quebic.common.dao.DaoConfig; 21 | import com.quebic.common.security.SecurityConfig; 22 | import com.quebic.common.sse.SseConfig; 23 | 24 | @Configuration 25 | @Import({AsyncConfig.class, SseConfig.class, DaoConfig.class, SecurityConfig.class, CacheConfig.class}) 26 | public class AppConfiguration { 27 | 28 | @Bean 29 | public ErrorAttributes errorAttributes() { 30 | 31 | return new DefaultErrorAttributes(){ 32 | @Override 33 | public Map getErrorAttributes(RequestAttributes requestAttributes, boolean includeStackTrace) { 34 | Map errorAttributes = super.getErrorAttributes(requestAttributes, includeStackTrace); 35 | errorAttributes.remove("exception"); 36 | return errorAttributes; 37 | } 38 | }; 39 | 40 | } 41 | 42 | @Bean 43 | public PasswordEncoder loadPasswordEncoder() { 44 | return new BCryptPasswordEncoder(); 45 | } 46 | 47 | /** 48 | * allow all origins - only for development mode 49 | * @return 50 | */ 51 | @Bean 52 | public WebMvcConfigurer corsConfigurer() { 53 | return new WebMvcConfigurerAdapter() { 54 | @Override 55 | public void addCorsMappings(CorsRegistry registry) { 56 | registry.addMapping("/**") 57 | .allowedMethods("*"); 58 | } 59 | }; 60 | } 61 | 62 | @Bean 63 | public CacheManager cacheManager() { 64 | return CacheConfig.createCacheManager("ProductDaoImpl"); 65 | } 66 | 67 | @LoadBalanced 68 | @Bean 69 | public RestTemplate restTemplate() { 70 | return new RestTemplate(); 71 | } 72 | 73 | } 74 | -------------------------------------------------------------------------------- /product-service/src/main/java/com/quebic/product/api/security/config/WebSecurityConfig.java: -------------------------------------------------------------------------------- 1 | package com.quebic.product.api.security.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.http.HttpMethod; 7 | import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; 8 | import org.springframework.security.config.annotation.web.builders.HttpSecurity; 9 | import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; 10 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; 11 | import org.springframework.security.config.http.SessionCreationPolicy; 12 | import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; 13 | 14 | import com.quebic.common.model.Permission; 15 | import com.quebic.common.security.CommonAuthenticationEntryPoint; 16 | import com.quebic.common.security.CommonAuthenticationTokenFilter; 17 | 18 | @Configuration 19 | @EnableWebSecurity 20 | @EnableGlobalMethodSecurity(prePostEnabled = true) 21 | public class WebSecurityConfig extends WebSecurityConfigurerAdapter { 22 | 23 | @Autowired 24 | private CommonAuthenticationEntryPoint unauthorizedHandler; 25 | 26 | @Bean 27 | public CommonAuthenticationTokenFilter authenticationTokenFilterBean() throws Exception { 28 | return new CommonAuthenticationTokenFilter(); 29 | } 30 | 31 | @Override 32 | protected void configure(HttpSecurity httpSecurity) throws Exception { 33 | httpSecurity 34 | // we don't need CSRF because our token is invulnerable 35 | .csrf().disable() 36 | 37 | .exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and() 38 | 39 | // don't create session 40 | .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and() 41 | 42 | .authorizeRequests() 43 | .antMatchers(HttpMethod.OPTIONS, "/**").permitAll() 44 | 45 | .antMatchers(HttpMethod.GET, "/products/**").permitAll() 46 | .antMatchers(HttpMethod.POST, "/products/**").hasRole(Permission.USER_SELLER) 47 | .antMatchers(HttpMethod.PUT, "/products/**").hasRole(Permission.USER_SELLER) 48 | 49 | //authenticated requests 50 | .anyRequest().authenticated(); 51 | 52 | // Custom JWT based security filter 53 | httpSecurity 54 | .addFilterBefore(authenticationTokenFilterBean(), UsernamePasswordAuthenticationFilter.class); 55 | 56 | // disable page caching 57 | httpSecurity.headers().cacheControl(); 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /discovery-server/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | 5 | com.quebic.discoveryserver 6 | discovery-server 7 | 0.0.1-SNAPSHOT 8 | jar 9 | 10 | discovery-server 11 | http://maven.apache.org 12 | 13 | 14 | 1.8 15 | 1111 16 | 17 | 18 | 19 | org.springframework.boot 20 | spring-boot-starter-parent 21 | 1.4.2.RELEASE 22 | 23 | 24 | 25 | 26 | 27 | 28 | org.springframework.boot 29 | spring-boot-starter-web 30 | 31 | 32 | 33 | 34 | org.springframework.cloud 35 | spring-cloud-starter 36 | 37 | 38 | 39 | 40 | org.springframework.cloud 41 | spring-cloud-starter-eureka-server 42 | 43 | 44 | 45 | 46 | org.springframework.boot 47 | spring-boot-devtools 48 | true 49 | 50 | 51 | 52 | 53 | ch.qos.logback 54 | logback-classic 55 | 56 | 57 | 58 | ch.qos.logback 59 | logback-core 60 | 61 | 62 | 63 | 64 | org.springframework.boot 65 | spring-boot-starter-test 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | org.springframework.cloud 74 | spring-cloud-dependencies 75 | Dalston.RELEASE 76 | pom 77 | import 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | org.springframework.boot 87 | spring-boot-maven-plugin 88 | 89 | 90 | 91 | repackage 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | -------------------------------------------------------------------------------- /common-lib/src/main/java/com/quebic/common/async/response/AsyncResponseEntity.java: -------------------------------------------------------------------------------- 1 | package com.quebic.common.async.response; 2 | 3 | import org.springframework.http.HttpStatus; 4 | import org.springframework.util.MultiValueMap; 5 | import rx.Observable; 6 | import rx.Single; 7 | 8 | public class AsyncResponseEntity{ 9 | 10 | private Observable observable; 11 | private Single single; 12 | private MultiValueMap headers; 13 | private HttpStatus status; 14 | 15 | public AsyncResponseEntity( 16 | Observable observable 17 | , MultiValueMap headers, 19 | HttpStatus status 20 | ) { 21 | this.observable = observable; 22 | this.headers = headers; 23 | this.status = status; 24 | } 25 | 26 | public AsyncResponseEntity( 27 | Single single 28 | , MultiValueMap headers, 30 | HttpStatus status 31 | ) { 32 | this.single = single; 33 | this.headers = headers; 34 | this.status = status; 35 | } 36 | 37 | public AsyncResponseEntity(HttpStatus status) { 38 | this.status = status; 39 | } 40 | 41 | public Observable getObservable() { 42 | return observable; 43 | } 44 | 45 | public Single getSingle() { 46 | return single; 47 | } 48 | 49 | public MultiValueMap getHeaders() { 50 | return headers; 51 | } 52 | 53 | public HttpStatus getStatus() { 54 | return status; 55 | } 56 | 57 | public static AsyncResponseEntity status(HttpStatus status){ 58 | return new AsyncResponseEntity(status); 59 | } 60 | 61 | public AsyncResponseEntity headers(MultiValueMap headers){ 62 | this.headers = headers; 63 | return this; 64 | } 65 | 66 | public AsyncResponseEntity observable(Observable observable){ 67 | this.observable = observable; 68 | this.single = null; 69 | return this; 70 | } 71 | 72 | public AsyncResponseEntity single(Single single){ 73 | this.single = single; 74 | this.observable = null; 75 | return this; 76 | } 77 | 78 | public static AsyncResponseEntity ok(){ 79 | return AsyncResponseEntity.status(HttpStatus.OK); 80 | } 81 | 82 | public static AsyncResponseEntity created(){ 83 | return AsyncResponseEntity.status(HttpStatus.CREATED); 84 | } 85 | 86 | public static AsyncResponseEntity accepted(){ 87 | return AsyncResponseEntity.status(HttpStatus.ACCEPTED); 88 | } 89 | 90 | public static AsyncResponseEntity noContent(){ 91 | return AsyncResponseEntity.status(HttpStatus.NO_CONTENT); 92 | } 93 | 94 | public static AsyncResponseEntity badRequest(){ 95 | return AsyncResponseEntity.status(HttpStatus.BAD_REQUEST); 96 | } 97 | 98 | public static AsyncResponseEntity notFound(){ 99 | return AsyncResponseEntity.status(HttpStatus.NOT_FOUND); 100 | } 101 | 102 | public static AsyncResponseEntity unprocessableEntity(){ 103 | return AsyncResponseEntity.status(HttpStatus.UNPROCESSABLE_ENTITY); 104 | } 105 | 106 | } 107 | -------------------------------------------------------------------------------- /api-gateway/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | 5 | com.quebic.apigateway 6 | api-gateway 7 | 0.0.1-SNAPSHOT 8 | jar 9 | 10 | api-gateway 11 | http://maven.apache.org 12 | 13 | 14 | 15 | 1.8 16 | 17 | 18 | 8080 19 | 20 | 21 | 22 | 23 | org.springframework.boot 24 | spring-boot-starter-parent 25 | 1.4.2.RELEASE 26 | 27 | 28 | 29 | 30 | 31 | org.springframework.boot 32 | spring-boot-starter-web 33 | 34 | 35 | 36 | 37 | org.springframework.cloud 38 | spring-cloud-starter 39 | 40 | 41 | 42 | 43 | org.springframework.cloud 44 | spring-cloud-starter-eureka-server 45 | 46 | 47 | 48 | 49 | org.springframework.cloud 50 | spring-cloud-starter-zuul 51 | 52 | 53 | 54 | 55 | ch.qos.logback 56 | logback-classic 57 | 58 | 59 | 60 | ch.qos.logback 61 | logback-core 62 | 63 | 64 | 65 | 66 | 67 | org.springframework.boot 68 | spring-boot-devtools 69 | true 70 | 71 | 72 | 73 | 74 | org.springframework.boot 75 | spring-boot-starter-test 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | org.springframework.cloud 84 | spring-cloud-dependencies 85 | Dalston.RELEASE 86 | pom 87 | import 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | org.springframework.boot 96 | spring-boot-maven-plugin 97 | 98 | 99 | 100 | repackage 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | -------------------------------------------------------------------------------- /auth-service/src/main/java/com/quebic/auth/api/security/controller/AuthController.java: -------------------------------------------------------------------------------- 1 | package com.quebic.auth.api.security.controller; 2 | 3 | import java.text.DateFormat; 4 | import java.text.SimpleDateFormat; 5 | import java.util.Date; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.beans.factory.annotation.Value; 8 | import org.springframework.http.ResponseEntity; 9 | import org.springframework.mobile.device.Device; 10 | import org.springframework.security.authentication.AuthenticationManager; 11 | import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; 12 | import org.springframework.security.core.Authentication; 13 | import org.springframework.security.core.context.SecurityContextHolder; 14 | import org.springframework.security.core.userdetails.UserDetails; 15 | import org.springframework.security.core.userdetails.UserDetailsService; 16 | import org.springframework.web.bind.annotation.ModelAttribute; 17 | import org.springframework.web.bind.annotation.RequestMapping; 18 | import org.springframework.web.bind.annotation.RequestMethod; 19 | import org.springframework.web.bind.annotation.RestController; 20 | 21 | import com.quebic.auth.api.security.JwtTokenUtil; 22 | import com.quebic.auth.api.security.dto.JwtAuthenticationDto; 23 | import com.quebic.auth.api.security.dto.JwtResponse; 24 | import com.quebic.common.exception.UnAuthorizedAccessException; 25 | import com.quebic.common.util.ControllerBase; 26 | 27 | @RestController 28 | @RequestMapping("/auth") 29 | public class AuthController extends ControllerBase { 30 | 31 | @Value("${jwt.header}") 32 | private String tokenHeader; 33 | 34 | @Autowired 35 | private AuthenticationManager authenticationManager; 36 | 37 | @Autowired 38 | private JwtTokenUtil jwtTokenUtil; 39 | 40 | @Autowired 41 | private UserDetailsService userDetailsService; 42 | 43 | @RequestMapping(method = RequestMethod.POST) 44 | public ResponseEntity createAuthenticationToken( 45 | @ModelAttribute JwtAuthenticationDto jwtAuthenticationDto, Device device) 46 | throws Exception { 47 | 48 | // Checking username|email and password 49 | Authentication authentication = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken( 50 | jwtAuthenticationDto.getUsername(), jwtAuthenticationDto.getPassword())); 51 | 52 | SecurityContextHolder.getContext().setAuthentication(authentication); 53 | 54 | UserDetails userDetails = userDetailsService.loadUserByUsername(jwtAuthenticationDto.getUsername()); 55 | String token = jwtTokenUtil.generateToken(userDetails, device); 56 | 57 | Date expiration = jwtTokenUtil.getExpirationDateFromToken(token); 58 | DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss"); 59 | 60 | return makeResponse(new JwtResponse(token, dateFormat.format(expiration))); 61 | 62 | } 63 | 64 | @RequestMapping("/current") 65 | public ResponseEntity getCurrent() throws Exception{ 66 | Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); 67 | 68 | String authenticatedUserName = authentication.getName(); 69 | if(authenticatedUserName.equals("anonymousUser")) 70 | throw new UnAuthorizedAccessException(authenticatedUserName); 71 | else 72 | return makeResponse((UserDetails)authentication.getPrincipal()); 73 | } 74 | 75 | } 76 | -------------------------------------------------------------------------------- /common-lib/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | 5 | com.quebic.common 6 | common-lib 7 | 0.0.1-SNAPSHOT 8 | jar 9 | 10 | common-lib 11 | http://maven.apache.org 12 | 13 | 14 | 1.8 15 | 0.7.0 16 | 1.1.6 17 | 2.1.1 18 | 19 | 20 | 21 | org.springframework.boot 22 | spring-boot-starter-parent 23 | 1.4.2.RELEASE 24 | 25 | 26 | 27 | 28 | 29 | 30 | org.springframework.boot 31 | spring-boot-starter-web 32 | 33 | 34 | 35 | 36 | org.springframework.data 37 | spring-data-mongodb 38 | 39 | 40 | 41 | 42 | org.springframework.security 43 | spring-security-web 44 | 45 | 46 | 47 | 48 | org.springframework.mobile 49 | spring-mobile-device 50 | 51 | 52 | 53 | 54 | io.jsonwebtoken 55 | jjwt 56 | ${jjwt.version} 57 | 58 | 59 | 60 | 61 | io.reactivex 62 | rxjava 63 | ${rxjava.version} 64 | 65 | 66 | 67 | 68 | ch.qos.logback 69 | logback-classic 70 | 71 | 72 | 73 | ch.qos.logback 74 | logback-core 75 | 76 | 77 | 78 | 79 | 80 | com.dropbox.core 81 | dropbox-core-sdk 82 | ${dropbox.version} 83 | 84 | 85 | 86 | 87 | org.imgscalr 88 | imgscalr-lib 89 | 4.2 90 | 91 | 92 | 93 | 94 | org.springframework.boot 95 | spring-boot-devtools 96 | true 97 | 98 | 99 | 100 | 101 | org.springframework.boot 102 | spring-boot-starter-test 103 | 104 | 105 | 106 | 107 | 108 | -------------------------------------------------------------------------------- /common-lib/src/main/java/com/quebic/common/dao/impl/GenericDaoImpl.java: -------------------------------------------------------------------------------- 1 | package com.quebic.common.dao.impl; 2 | 3 | import java.util.List; 4 | import org.slf4j.Logger; 5 | import org.slf4j.LoggerFactory; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.data.mongodb.core.MongoOperations; 8 | 9 | import com.quebic.common.dao.GenericDao; 10 | import com.quebic.common.exception.DataAccessException; 11 | 12 | import org.springframework.cache.annotation.CacheConfig; 13 | import org.springframework.cache.annotation.CacheEvict; 14 | import org.springframework.cache.annotation.CachePut; 15 | import org.springframework.cache.annotation.Cacheable; 16 | import org.springframework.cache.annotation.Caching; 17 | 18 | @CacheConfig(cacheResolver="primaryCacheResolver") 19 | public class GenericDaoImpl implements GenericDao { 20 | 21 | private static final Logger logger = LoggerFactory.getLogger(GenericDaoImpl.class); 22 | 23 | @Autowired 24 | protected MongoOperations mongoOperations; 25 | 26 | private Class type; 27 | 28 | public GenericDaoImpl(Class type) { 29 | this.type = type; 30 | } 31 | 32 | @Override 33 | @Caching( 34 | put={@CachePut(key="#object.id")}, 35 | evict={@CacheEvict(cacheResolver="secondaryCacheResolver", allEntries=true)} 36 | ) 37 | public T add(T object) throws DataAccessException { 38 | if (logger.isDebugEnabled()) 39 | logger.debug("type {} add", type); 40 | try { 41 | mongoOperations.insert(object); 42 | return object; 43 | } catch (Exception e) { 44 | throw new DataAccessException(e); 45 | } 46 | } 47 | 48 | @Override 49 | @Caching( 50 | put={@CachePut(key="#object.id")}, 51 | evict={@CacheEvict(cacheResolver="secondaryCacheResolver", allEntries=true)} 52 | ) 53 | public T modify(T object) throws DataAccessException { 54 | if (logger.isDebugEnabled()) 55 | logger.debug("type {} modify", type); 56 | try { 57 | mongoOperations.save(object); 58 | return object; 59 | } catch (Exception e) { 60 | throw new DataAccessException(e); 61 | } 62 | } 63 | 64 | @Override 65 | @Caching( 66 | evict = { 67 | @CacheEvict(key="#object.id"), 68 | @CacheEvict(cacheResolver="secondaryCacheResolver", allEntries=true) 69 | } 70 | ) 71 | public T delete(T object) throws DataAccessException { 72 | if (logger.isDebugEnabled()) 73 | logger.debug("type {} delete", type); 74 | try { 75 | mongoOperations.remove(object); 76 | return object; 77 | } catch (Exception e) { 78 | throw new DataAccessException(e); 79 | } 80 | 81 | } 82 | 83 | @Override 84 | @Cacheable(key="#id" ,unless="#result == null") 85 | public T getById(Object id) throws DataAccessException { 86 | if (logger.isDebugEnabled()) 87 | logger.debug("type {} getById", type); 88 | try{ 89 | return mongoOperations.findById(id, type); 90 | }catch(Exception e){ 91 | throw new DataAccessException(e); 92 | } 93 | } 94 | 95 | @Override 96 | @Cacheable(cacheResolver="secondaryCacheResolver" ,unless="#result == null") 97 | public List getAll() throws DataAccessException { 98 | if (logger.isDebugEnabled()) 99 | logger.debug("type {} getAll", type); 100 | try { 101 | return mongoOperations.findAll(type); 102 | } catch (Exception e) { 103 | throw new DataAccessException(e); 104 | } 105 | } 106 | 107 | @Override 108 | public MongoOperations getMongoOperations() { 109 | return mongoOperations; 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /auth-service/src/main/java/com/quebic/auth/api/security/config/WebSecurityConfig.java: -------------------------------------------------------------------------------- 1 | package com.quebic.auth.api.security.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.http.HttpMethod; 7 | import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; 8 | import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; 9 | import org.springframework.security.config.annotation.web.builders.HttpSecurity; 10 | import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; 11 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; 12 | import org.springframework.security.config.http.SessionCreationPolicy; 13 | import org.springframework.security.core.userdetails.UserDetailsService; 14 | import org.springframework.security.crypto.password.PasswordEncoder; 15 | import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; 16 | 17 | import com.quebic.auth.api.security.JwtAuthenticationEntryPoint; 18 | import com.quebic.auth.api.security.JwtAuthenticationTokenFilter; 19 | import com.quebic.common.model.Permission; 20 | 21 | @Configuration 22 | @EnableWebSecurity 23 | @EnableGlobalMethodSecurity(prePostEnabled = true) 24 | public class WebSecurityConfig extends WebSecurityConfigurerAdapter { 25 | 26 | @Autowired 27 | private JwtAuthenticationEntryPoint unauthorizedHandler; 28 | 29 | @Autowired 30 | private UserDetailsService userDetailsService; 31 | 32 | @Autowired 33 | private PasswordEncoder passwordEncoder; 34 | 35 | @Autowired 36 | public void configureAuthentication(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception { 37 | authenticationManagerBuilder 38 | .userDetailsService(this.userDetailsService) 39 | .passwordEncoder(passwordEncoder); 40 | } 41 | 42 | @Bean 43 | public JwtAuthenticationTokenFilter authenticationTokenFilterBean() throws Exception { 44 | return new JwtAuthenticationTokenFilter(); 45 | } 46 | 47 | @Override 48 | protected void configure(HttpSecurity httpSecurity) throws Exception { 49 | httpSecurity 50 | // we don't need CSRF because our token is invulnerable 51 | .csrf().disable() 52 | 53 | .exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and() 54 | 55 | // don't create session 56 | .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and() 57 | 58 | .authorizeRequests() 59 | .antMatchers(HttpMethod.OPTIONS, "/**").permitAll() 60 | 61 | //allow anonymous auth requests 62 | .antMatchers("/auth/**").permitAll() 63 | 64 | //allow requests 65 | .antMatchers(HttpMethod.GET, "/users/**").permitAll() 66 | .antMatchers(HttpMethod.POST, "/buyers/**").permitAll() 67 | .antMatchers(HttpMethod.POST, "/sellers/**").permitAll() 68 | .antMatchers("/test/images/**").permitAll() 69 | .antMatchers("/roles-permissions-setup/init/**").permitAll() 70 | 71 | .antMatchers(HttpMethod.POST, "/registerOtherSeller/**").hasRole(Permission.USER_SELLER_ADMIN) 72 | 73 | //authenticated requests 74 | .anyRequest().authenticated(); 75 | 76 | // Custom JWT based security filter 77 | httpSecurity 78 | .addFilterBefore(authenticationTokenFilterBean(), UsernamePasswordAuthenticationFilter.class); 79 | 80 | // disable page caching 81 | httpSecurity.headers().cacheControl(); 82 | } 83 | 84 | } 85 | -------------------------------------------------------------------------------- /common-lib/src/main/java/com/quebic/common/util/ControllerBase.java: -------------------------------------------------------------------------------- 1 | package com.quebic.common.util; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.context.ApplicationEventPublisher; 5 | import org.springframework.http.HttpStatus; 6 | import org.springframework.http.ResponseEntity; 7 | import org.springframework.util.MultiValueMap; 8 | import org.springframework.web.bind.annotation.PathVariable; 9 | import org.springframework.web.bind.annotation.RequestMapping; 10 | import org.springframework.web.servlet.mvc.method.annotation.SseEmitter; 11 | 12 | import com.quebic.common.async.response.AsyncResponseEntity; 13 | import com.quebic.common.exception.ListenerTypeNotFound; 14 | import com.quebic.common.sse.ListenerType; 15 | import com.quebic.common.sse.SseEmitterApplicationEventListener; 16 | import com.quebic.common.sse.SubmissionEvent; 17 | 18 | import rx.Observable; 19 | import rx.Single; 20 | 21 | public class ControllerBase { 22 | 23 | @Autowired 24 | private SseEmitterApplicationEventListener applicationEventListener; 25 | 26 | @Autowired 27 | private ApplicationEventPublisher eventPublisher; 28 | 29 | private ListenerType listenerType; 30 | 31 | public ControllerBase() { 32 | } 33 | 34 | public ControllerBase(ListenerType listenerType){ 35 | this.listenerType = listenerType; 36 | } 37 | 38 | protected ResponseEntity makeResponse(T message) { 39 | return makeResponse(message, null, HttpStatus.OK); 40 | } 41 | 42 | protected ResponseEntity makeResponse(T message, HttpStatus status) { 43 | return makeResponse(message, null, status); 44 | } 45 | 46 | protected ResponseEntity makeResponse(T message, MultiValueMap headers, HttpStatus status) { 47 | return new ResponseEntity(message, headers, status); 48 | } 49 | 50 | /* 51 | * Observable 52 | */ 53 | protected AsyncResponseEntity makeAsyncResponse(Observable observable) { 54 | return makeAsyncResponse(observable, null, HttpStatus.OK); 55 | } 56 | 57 | protected AsyncResponseEntity makeAsyncResponse(Observable observable, HttpStatus status) { 58 | return makeAsyncResponse(observable, null, status); 59 | } 60 | 61 | protected AsyncResponseEntity makeAsyncResponse(Observable observable, MultiValueMap headers,HttpStatus status) { 62 | return AsyncResponseEntity.status(status).headers(headers).observable(observable); 63 | } 64 | /* 65 | * Observable 66 | */ 67 | 68 | /* 69 | * Single 70 | */ 71 | protected AsyncResponseEntity makeAsyncResponse(Single single) { 72 | return makeAsyncResponse(single, null, HttpStatus.OK); 73 | } 74 | 75 | protected AsyncResponseEntity makeAsyncResponse(Single single, HttpStatus status) { 76 | return makeAsyncResponse(single, null, status); 77 | } 78 | 79 | protected AsyncResponseEntity makeAsyncResponse(Single single, MultiValueMap headers,HttpStatus status) { 80 | return AsyncResponseEntity.status(status).headers(headers).single(single); 81 | } 82 | /* 83 | * Single 84 | */ 85 | 86 | /* 87 | * Server-Sent-Event 88 | */ 89 | @RequestMapping("/listener/{id}") 90 | public SseEmitter listen(@PathVariable("id") String id){ 91 | 92 | if(this.listenerType == null) 93 | throw new ListenerTypeNotFound(); 94 | 95 | final SseEmitter sseEmitter = new SseEmitter(); 96 | applicationEventListener.addSseEmitters(this.listenerType , id, sseEmitter); 97 | return sseEmitter; 98 | 99 | } 100 | 101 | public void publishMessage(String id, Object message){ 102 | 103 | if(this.listenerType == null) 104 | throw new ListenerTypeNotFound(); 105 | 106 | SubmissionEvent submissionEvent = new SubmissionEvent(this.listenerType, id, message); 107 | eventPublisher.publishEvent(submissionEvent); 108 | 109 | } 110 | 111 | /* 112 | * Server-Sent-Event 113 | */ 114 | 115 | } 116 | -------------------------------------------------------------------------------- /auth-service/src/main/java/com/quebic/auth/api/controller/setup/RolesPermissionsSetupController.java: -------------------------------------------------------------------------------- 1 | package com.quebic.auth.api.controller.setup; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.http.ResponseEntity; 5 | import org.springframework.web.bind.annotation.RequestMapping; 6 | import org.springframework.web.bind.annotation.RequestMethod; 7 | import org.springframework.web.bind.annotation.RestController; 8 | 9 | import com.quebic.auth.api.model.Role; 10 | import com.quebic.auth.api.service.PermissionService; 11 | import com.quebic.auth.api.service.RoleService; 12 | import com.quebic.common.model.Permission; 13 | import com.quebic.common.util.ControllerBase; 14 | 15 | /** 16 | * Only for development 17 | */ 18 | @RestController 19 | @RequestMapping("/roles-permissions-setup") 20 | public class RolesPermissionsSetupController extends ControllerBase{ 21 | 22 | @Autowired 23 | private PermissionService permissionService; 24 | 25 | @Autowired 26 | private RoleService roleService; 27 | 28 | @RequestMapping(value="/init", method=RequestMethod.POST) 29 | public ResponseEntity init(){ 30 | 31 | //Permission 32 | Permission permission_USER = new Permission(); 33 | permission_USER.setId(Permission.USER); 34 | permission_USER.setCode(Permission.USER); 35 | permission_USER.setStatus(1); 36 | 37 | Permission permission_ADMIN = new Permission(); 38 | permission_ADMIN.setId(Permission.USER_ADMIN); 39 | permission_ADMIN.setCode(Permission.USER_ADMIN); 40 | permission_ADMIN.setStatus(1); 41 | 42 | Permission permission_SELLER_ADMIN = new Permission(); 43 | permission_SELLER_ADMIN.setId(Permission.USER_SELLER_ADMIN); 44 | permission_SELLER_ADMIN.setCode(Permission.USER_SELLER_ADMIN); 45 | permission_SELLER_ADMIN.setStatus(1); 46 | 47 | Permission permission_SELLER = new Permission(); 48 | permission_SELLER.setId(Permission.USER_SELLER); 49 | permission_SELLER.setCode(Permission.USER_SELLER); 50 | permission_SELLER.setStatus(1); 51 | 52 | Permission permission_BUYER = new Permission(); 53 | permission_BUYER.setId(Permission.USER_BUYER); 54 | permission_BUYER.setCode(Permission.USER_BUYER); 55 | permission_BUYER.setStatus(1); 56 | 57 | permissionService.add(permission_USER); 58 | permissionService.add(permission_ADMIN); 59 | permissionService.add(permission_SELLER_ADMIN); 60 | permissionService.add(permission_SELLER); 61 | permissionService.add(permission_BUYER); 62 | //Permission 63 | 64 | //Role ROLE_ADMIN 65 | Role role_ADMIN = new Role(); 66 | role_ADMIN.setId(Role.ROLE_ADMIN); 67 | role_ADMIN.setCode(Role.ROLE_ADMIN); 68 | role_ADMIN.setStatus(1); 69 | role_ADMIN.getPermissions().add(permission_USER); 70 | role_ADMIN.getPermissions().add(permission_ADMIN); 71 | 72 | //Role ROLE_SELLER_ADMIN 73 | Role role_SELLER_ADMIN = new Role(); 74 | role_SELLER_ADMIN.setId(Role.ROLE_SELLER_ADMIN); 75 | role_SELLER_ADMIN.setCode(Role.ROLE_SELLER_ADMIN); 76 | role_SELLER_ADMIN.setStatus(1); 77 | role_SELLER_ADMIN.getPermissions().add(permission_USER); 78 | role_SELLER_ADMIN.getPermissions().add(permission_SELLER_ADMIN); 79 | role_SELLER_ADMIN.getPermissions().add(permission_SELLER); 80 | 81 | //Role ROLE_SELLER 82 | Role role_SELLER = new Role(); 83 | role_SELLER.setId(Role.ROLE_SELLER); 84 | role_SELLER.setCode(Role.ROLE_SELLER); 85 | role_SELLER.setStatus(1); 86 | role_SELLER.getPermissions().add(permission_USER); 87 | role_SELLER.getPermissions().add(permission_SELLER); 88 | 89 | //Role ROLE_BUYER 90 | Role role_BUYER = new Role(); 91 | role_BUYER.setId(Role.ROLE_BUYER); 92 | role_BUYER.setCode(Role.ROLE_BUYER); 93 | role_BUYER.setStatus(1); 94 | role_BUYER.getPermissions().add(permission_USER); 95 | role_BUYER.getPermissions().add(permission_BUYER); 96 | 97 | roleService.add(role_ADMIN); 98 | roleService.add(role_SELLER_ADMIN); 99 | roleService.add(role_SELLER); 100 | roleService.add(role_BUYER); 101 | 102 | return makeResponse("roles-permissions : init"); 103 | 104 | } 105 | 106 | 107 | } 108 | -------------------------------------------------------------------------------- /common-lib/src/main/java/com/quebic/common/util/image/impl/LocalStorageImageUtil.java: -------------------------------------------------------------------------------- 1 | package com.quebic.common.util.image.impl; 2 | 3 | import java.awt.image.BufferedImage; 4 | import java.io.ByteArrayInputStream; 5 | import java.io.File; 6 | import java.io.IOException; 7 | import java.io.OutputStream; 8 | import java.io.RandomAccessFile; 9 | import java.nio.ByteBuffer; 10 | import java.nio.channels.FileChannel; 11 | import java.nio.file.Files; 12 | import java.nio.file.Path; 13 | import java.nio.file.Paths; 14 | import javax.imageio.ImageIO; 15 | import org.imgscalr.Scalr; 16 | import org.slf4j.Logger; 17 | import org.slf4j.LoggerFactory; 18 | import org.springframework.http.HttpHeaders; 19 | import org.springframework.http.HttpStatus; 20 | import org.springframework.http.ResponseEntity; 21 | import org.springframework.util.StringUtils; 22 | import org.springframework.web.multipart.MultipartFile; 23 | import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody; 24 | 25 | import com.quebic.common.constants.ImageResizeLevel; 26 | import com.quebic.common.exception.ResourceNotFoundException; 27 | import com.quebic.common.util.image.ImageUtil; 28 | 29 | import rx.Single; 30 | import rx.schedulers.Schedulers; 31 | 32 | public class LocalStorageImageUtil extends ImageUtil { 33 | 34 | private Logger logger = LoggerFactory.getLogger(LocalStorageImageUtil.class); 35 | 36 | @Override 37 | public Single storeFile(String id, String fileName, String fileLocation, String imageDir, 38 | MultipartFile multipartFile){ 39 | 40 | return Single.create(s->{ 41 | 42 | try { 43 | String dirStr; 44 | if (!StringUtils.isEmpty(id)) 45 | dirStr = fileLocation + File.separator + imageDir + File.separator + id; 46 | else 47 | dirStr = fileLocation + File.separator + imageDir; 48 | 49 | Path dir = Paths.get(dirStr); 50 | if (!Files.exists(dir)) { 51 | Files.createDirectories(dir); 52 | } 53 | 54 | Path file = Paths.get(dirStr + File.separator + fileName); 55 | 56 | byte[] bytes = multipartFile.getBytes(); 57 | Files.write(file, bytes); 58 | 59 | resizeImage(bytes, dirStr, fileName, ImageResizeLevel.HIGH.getSize()); 60 | resizeImage(bytes, dirStr, fileName, ImageResizeLevel.MEDIUM.getSize()); 61 | resizeImage(bytes, dirStr, fileName, ImageResizeLevel.LOW.getSize()); 62 | 63 | s.onSuccess(fileName);; 64 | 65 | } catch (Exception e) { 66 | logger.error(e.getMessage()); 67 | s.onError(e); 68 | } 69 | 70 | }).subscribeOn(Schedulers.io()); 71 | } 72 | 73 | @Override 74 | public void resizeImage(byte[] bytes, String dirStr, String fileName, int targetSize) throws Exception{ 75 | 76 | BufferedImage orginalImage = ImageIO.read(new ByteArrayInputStream(bytes)); 77 | 78 | String[] splt = splitFileName(fileName); 79 | String randomFileName = splt[0]; 80 | String fileExtension = splt[1]; 81 | 82 | String savedImage = targetSize + "-" + randomFileName + "." + fileExtension; 83 | 84 | BufferedImage scaledImage = Scalr.resize(orginalImage, targetSize); 85 | ImageIO.write(scaledImage, fileExtension, new File(dirStr + File.separator + savedImage)); 86 | 87 | } 88 | 89 | @Override 90 | public ResponseEntity readFile(String fileLocation, String imageDir, String id, 91 | String fileName) { 92 | StreamingResponseBody streamingResponseBody = new StreamingResponseBody() { 93 | 94 | @Override 95 | public void writeTo(OutputStream outputStream) { 96 | try { 97 | 98 | String fileStr = fileLocation + File.separator + imageDir + File.separator + id + File.separator 99 | + fileName; 100 | 101 | RandomAccessFile file = new RandomAccessFile(fileStr, "r"); 102 | FileChannel inChannel = file.getChannel(); 103 | ByteBuffer buffer = ByteBuffer.allocate(1024); 104 | while (inChannel.read(buffer) > 0) { 105 | buffer.flip(); 106 | for (int i = 0; i < buffer.limit(); i++) { 107 | outputStream.write(buffer.get()); 108 | } 109 | buffer.clear(); 110 | outputStream.flush(); 111 | } 112 | inChannel.close(); 113 | file.close(); 114 | 115 | } catch (IOException e) { 116 | logger.error("Image Not Found : error " + e.getMessage()); 117 | throw new ResourceNotFoundException("Image Not Found : " + id + "/" + fileName); 118 | } 119 | } 120 | }; 121 | 122 | HttpHeaders headers = new HttpHeaders(); 123 | headers.add(HttpHeaders.CONTENT_TYPE, "image/*"); 124 | return new ResponseEntity(streamingResponseBody, headers, HttpStatus.OK); 125 | } 126 | 127 | } 128 | -------------------------------------------------------------------------------- /common-lib/src/main/java/com/quebic/common/security/CommonAuthenticationTokenFilter.java: -------------------------------------------------------------------------------- 1 | package com.quebic.common.security; 2 | 3 | import java.io.IOException; 4 | import java.util.ArrayList; 5 | import java.util.Arrays; 6 | import java.util.Iterator; 7 | import java.util.List; 8 | 9 | import javax.servlet.FilterChain; 10 | import javax.servlet.ServletException; 11 | import javax.servlet.http.HttpServletRequest; 12 | import javax.servlet.http.HttpServletResponse; 13 | 14 | import org.slf4j.Logger; 15 | import org.slf4j.LoggerFactory; 16 | import org.springframework.beans.factory.annotation.Autowired; 17 | import org.springframework.beans.factory.annotation.Value; 18 | import org.springframework.http.HttpEntity; 19 | import org.springframework.http.HttpHeaders; 20 | import org.springframework.http.HttpMethod; 21 | import org.springframework.http.MediaType; 22 | import org.springframework.http.ResponseEntity; 23 | import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; 24 | import org.springframework.security.core.authority.SimpleGrantedAuthority; 25 | import org.springframework.security.core.context.SecurityContextHolder; 26 | import org.springframework.security.core.userdetails.UserDetails; 27 | import org.springframework.security.web.authentication.WebAuthenticationDetailsSource; 28 | import org.springframework.util.StringUtils; 29 | import org.springframework.web.client.RestTemplate; 30 | import org.springframework.web.filter.OncePerRequestFilter; 31 | 32 | import com.fasterxml.jackson.core.JsonProcessingException; 33 | import com.fasterxml.jackson.databind.JsonNode; 34 | import com.fasterxml.jackson.databind.ObjectMapper; 35 | import com.quebic.common.security.AuthUser; 36 | 37 | public class CommonAuthenticationTokenFilter extends OncePerRequestFilter { 38 | 39 | private Logger logger = LoggerFactory.getLogger(CommonAuthenticationTokenFilter.class); 40 | 41 | @Value("${jwt.header}") 42 | private String tokenHeader; 43 | 44 | @Autowired 45 | private RestTemplate restTemplate; 46 | 47 | @Override 48 | protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException { 49 | 50 | String authToken = request.getHeader(this.tokenHeader); 51 | 52 | if (!StringUtils.isEmpty(authToken) && SecurityContextHolder.getContext().getAuthentication() == null) { 53 | 54 | try{ 55 | 56 | HttpHeaders headers = new HttpHeaders(); 57 | headers.add("Authorization", authToken); 58 | headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON)); 59 | 60 | HttpEntity entity = new HttpEntity("", headers); 61 | 62 | ResponseEntity responseEntity = 63 | restTemplate.exchange( 64 | "http://AUTH-SERVICE/auth/current" 65 | , HttpMethod.POST 66 | , entity 67 | , String.class); 68 | 69 | String jsonUserDetails = responseEntity.getBody(); 70 | UserDetails userDetails = prepareUserDetails(jsonUserDetails); 71 | 72 | if (userDetails != null) { 73 | UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities()); 74 | authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); 75 | SecurityContextHolder.getContext().setAuthentication(authentication); 76 | } 77 | 78 | }catch(Exception e){ 79 | logger.error(e.getMessage()); 80 | } 81 | 82 | } 83 | 84 | chain.doFilter(request, response); 85 | } 86 | 87 | private UserDetails prepareUserDetails(String jsonUserDetails) throws JsonProcessingException, IOException{ 88 | 89 | ObjectMapper objectMapper = new ObjectMapper(); 90 | JsonNode root = objectMapper.readTree(jsonUserDetails); 91 | 92 | String userId = root.get("dbUser").get("id").asText(); 93 | String username = root.get("username").asText(); 94 | boolean isEnabled = root.get("enabled").asBoolean(); 95 | 96 | List authorities = new ArrayList<>(); 97 | 98 | Iterator authoritiesIterator = root.get("authorities").elements(); 99 | while(authoritiesIterator.hasNext()){ 100 | JsonNode authorityNode = authoritiesIterator.next(); 101 | authorities.add(new SimpleGrantedAuthority(authorityNode.get("authority").asText())); 102 | } 103 | 104 | return new AuthUser(userId, username, authorities, isEnabled); 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /product-service/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | 5 | com.quebic.product.api 6 | product-service 7 | 0.0.1-SNAPSHOT 8 | jar 9 | 10 | product-service 11 | http://maven.apache.org 12 | 13 | 14 | 15 | 16 | 1.8 17 | 0.7.0 18 | 1.1.6 19 | 4.2 20 | 1.4 21 | 3.10.1 22 | 0.0.1-SNAPSHOT 23 | 24 | 25 | 82 26 | localhost 27 | 27017 28 | product-service-db 29 | 30 | 31 | 32 | 33 | 34 | 35 | org.springframework.boot 36 | spring-boot-starter-parent 37 | 1.4.2.RELEASE 38 | 39 | 40 | 41 | 42 | 43 | 44 | org.springframework.boot 45 | spring-boot-starter-web 46 | 47 | 48 | 49 | 50 | org.springframework.cloud 51 | spring-cloud-starter 52 | 53 | 54 | 55 | 56 | org.springframework.cloud 57 | spring-cloud-starter-eureka-server 58 | 59 | 60 | 61 | 62 | org.springframework.boot 63 | spring-boot-starter-security 64 | 65 | 66 | 67 | 68 | org.springframework.data 69 | spring-data-mongodb 70 | 71 | 72 | 73 | 74 | org.springframework.mobile 75 | spring-mobile-device 76 | 77 | 78 | 79 | 80 | io.jsonwebtoken 81 | jjwt 82 | ${jjwt.version} 83 | 84 | 85 | 86 | 87 | io.reactivex 88 | rxjava 89 | ${rxjava.version} 90 | 91 | 92 | 93 | 94 | ch.qos.logback 95 | logback-classic 96 | 97 | 98 | 99 | ch.qos.logback 100 | logback-core 101 | 102 | 103 | 104 | 105 | 106 | com.quebic.common 107 | common-lib 108 | ${common.lib.version} 109 | 110 | 111 | 112 | 113 | org.springframework.boot 114 | spring-boot-devtools 115 | true 116 | 117 | 118 | 119 | 120 | org.springframework.boot 121 | spring-boot-starter-test 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | org.springframework.cloud 130 | spring-cloud-dependencies 131 | Dalston.RELEASE 132 | pom 133 | import 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | org.springframework.boot 143 | spring-boot-maven-plugin 144 | 145 | 146 | 147 | repackage 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | -------------------------------------------------------------------------------- /common-lib/src/main/java/com/quebic/common/util/image/impl/DropBoxStorageImageUtil.java: -------------------------------------------------------------------------------- 1 | package com.quebic.common.util.image.impl; 2 | 3 | import java.awt.image.BufferedImage; 4 | import java.io.ByteArrayInputStream; 5 | import java.io.ByteArrayOutputStream; 6 | import java.io.InputStream; 7 | import java.io.OutputStream; 8 | import javax.imageio.ImageIO; 9 | import org.imgscalr.Scalr; 10 | import org.slf4j.Logger; 11 | import org.slf4j.LoggerFactory; 12 | import org.springframework.http.HttpHeaders; 13 | import org.springframework.http.HttpStatus; 14 | import org.springframework.http.ResponseEntity; 15 | import org.springframework.util.StringUtils; 16 | import org.springframework.web.multipart.MultipartFile; 17 | import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody; 18 | import com.dropbox.core.DbxRequestConfig; 19 | import com.dropbox.core.v2.DbxClientV2; 20 | import com.dropbox.core.v2.files.FileMetadata; 21 | import com.quebic.common.constants.ImageResizeLevel; 22 | import com.quebic.common.exception.ResourceNotFoundException; 23 | import com.quebic.common.util.image.ImageUtil; 24 | 25 | import rx.Single; 26 | import rx.schedulers.Schedulers; 27 | 28 | public class DropBoxStorageImageUtil extends ImageUtil{ 29 | 30 | private Logger logger = LoggerFactory.getLogger(DropBoxStorageImageUtil.class); 31 | 32 | private final String APP_IDENTIFIER = "xx"; 33 | private final String ACCESS_TOKEN = "xx"; 34 | private final String SEPARATOR = "/"; 35 | 36 | @Override 37 | public Single storeFile(String id, String fileName, String fileLocation, String imageDir, 38 | MultipartFile multipartFile){ 39 | 40 | return Single.create(s->{ 41 | 42 | try{ 43 | 44 | String dirStr; 45 | if (!StringUtils.isEmpty(id)) 46 | dirStr = SEPARATOR + imageDir + SEPARATOR + id; 47 | else 48 | dirStr = SEPARATOR + imageDir; 49 | 50 | byte[] bytes = multipartFile.getBytes(); 51 | InputStream inputStream = multipartFile.getInputStream(); 52 | 53 | String uploadPath = dirStr + SEPARATOR + fileName; 54 | FileMetadata metadata = dropBoxSave(uploadPath, inputStream);//orginal file 55 | 56 | resizeImage(bytes, dirStr, fileName, ImageResizeLevel.HIGH.getSize()); 57 | resizeImage(bytes, dirStr, fileName, ImageResizeLevel.MEDIUM.getSize()); 58 | resizeImage(bytes, dirStr, fileName, ImageResizeLevel.LOW.getSize()); 59 | 60 | s.onSuccess(metadata.getName()); 61 | 62 | }catch(Exception e){ 63 | logger.error(e.getMessage()); 64 | s.onError(e); 65 | } 66 | 67 | }).subscribeOn(Schedulers.io()); 68 | } 69 | 70 | @Override 71 | public ResponseEntity readFile(String fileLocation, String imageDir, String id, 72 | String fileName) { 73 | 74 | StreamingResponseBody streamingResponseBody = new StreamingResponseBody() { 75 | 76 | @Override 77 | public void writeTo(OutputStream outputStream) { 78 | try { 79 | 80 | String fileStr = SEPARATOR + imageDir + SEPARATOR + id + SEPARATOR + fileName; 81 | 82 | DbxRequestConfig config = new DbxRequestConfig(APP_IDENTIFIER); 83 | DbxClientV2 client = new DbxClientV2(config, ACCESS_TOKEN); 84 | client.files().download(fileStr).download(outputStream); 85 | 86 | } catch (Exception e) { 87 | logger.error(e.getMessage()); 88 | throw new ResourceNotFoundException("Image Not Found : " + id + "/" + fileName); 89 | } 90 | } 91 | }; 92 | 93 | HttpHeaders headers = new HttpHeaders(); 94 | headers.add(HttpHeaders.CONTENT_TYPE, "image/*"); 95 | return new ResponseEntity(streamingResponseBody, headers, HttpStatus.OK); 96 | } 97 | 98 | @Override 99 | public void resizeImage(byte[] bytes, String dirStr, String fileName, int targetSize) throws Exception { 100 | BufferedImage orginalImage = ImageIO.read(new ByteArrayInputStream(bytes)); 101 | 102 | String[] splt = splitFileName(fileName); 103 | String randomFileName = splt[0]; 104 | String fileExtension = splt[1]; 105 | 106 | String savedImageName = targetSize + "-" + randomFileName + "." + fileExtension; 107 | String uploadPath = dirStr + SEPARATOR + savedImageName; 108 | 109 | BufferedImage scaledImage = Scalr.resize(orginalImage, targetSize); 110 | ByteArrayOutputStream os = new ByteArrayOutputStream(); 111 | ImageIO.write(scaledImage, fileExtension, os); 112 | InputStream is = new ByteArrayInputStream(os.toByteArray()); 113 | 114 | dropBoxSave(uploadPath, is); 115 | 116 | } 117 | 118 | private FileMetadata dropBoxSave(String uploadPath, InputStream inputStream)throws Exception{ 119 | DbxRequestConfig config = new DbxRequestConfig(APP_IDENTIFIER); 120 | DbxClientV2 client = new DbxClientV2(config, ACCESS_TOKEN); 121 | return client.files().uploadBuilder(uploadPath).uploadAndFinish(inputStream); 122 | } 123 | 124 | } 125 | -------------------------------------------------------------------------------- /auth-service/src/main/java/com/quebic/auth/api/model/User.java: -------------------------------------------------------------------------------- 1 | package com.quebic.auth.api.model; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Date; 5 | import java.util.List; 6 | import org.springframework.data.mongodb.core.mapping.DBRef; 7 | import org.springframework.data.mongodb.core.mapping.Document; 8 | import com.fasterxml.jackson.annotation.JsonIgnore; 9 | import com.quebic.common.model.EntityBase; 10 | import com.quebic.common.model.Permission; 11 | import com.quebic.common.model.image.ImageContainer; 12 | 13 | @Document(collection="User") 14 | public class User extends EntityBase{ 15 | 16 | private String email; 17 | 18 | private String username; 19 | 20 | private String password; 21 | 22 | private String firstName; 23 | 24 | private String lastName; 25 | 26 | private ImageContainer profileImageContainer = new ImageContainer(); 27 | 28 | private ImageContainer coverImageContainer = new ImageContainer(); 29 | 30 | private Date lastLoggedOn; 31 | 32 | private Date registeredOn; 33 | 34 | private Integer attempts; 35 | 36 | @DBRef 37 | private List roles = new ArrayList<>(); 38 | 39 | @DBRef 40 | private List permissions = new ArrayList<>(); 41 | 42 | private EmailVerification emailVerification; 43 | 44 | private Date lastPasswordResetDate; 45 | 46 | private SellerProfile sellerProfile = new SellerProfile(); 47 | private BuyerProfile buyerProfile = new BuyerProfile(); 48 | 49 | public String getEmail() { 50 | return email; 51 | } 52 | 53 | public void setEmail(String email) { 54 | this.email = email; 55 | } 56 | 57 | public String getUsername() { 58 | return username; 59 | } 60 | 61 | public void setUsername(String username) { 62 | this.username = username; 63 | } 64 | 65 | @JsonIgnore 66 | public String getPassword() { 67 | return password; 68 | } 69 | 70 | public void setPassword(String password) { 71 | this.password = password; 72 | } 73 | 74 | public String getFirstName() { 75 | return firstName; 76 | } 77 | 78 | public void setFirstName(String firstName) { 79 | this.firstName = firstName; 80 | } 81 | 82 | public String getLastName() { 83 | return lastName; 84 | } 85 | 86 | public void setLastName(String lastName) { 87 | this.lastName = lastName; 88 | } 89 | 90 | public ImageContainer getProfileImageContainer() { 91 | return profileImageContainer; 92 | } 93 | 94 | public void setProfileImageContainer(ImageContainer profileImageContainer) { 95 | this.profileImageContainer = profileImageContainer; 96 | } 97 | 98 | public ImageContainer getCoverImageContainer() { 99 | return coverImageContainer; 100 | } 101 | 102 | public void setCoverImageContainer(ImageContainer coverImageContainer) { 103 | this.coverImageContainer = coverImageContainer; 104 | } 105 | 106 | public Date getLastLoggedOn() { 107 | return lastLoggedOn; 108 | } 109 | 110 | public void setLastLoggedOn(Date lastLoggedOn) { 111 | this.lastLoggedOn = lastLoggedOn; 112 | } 113 | 114 | public Date getRegisteredOn() { 115 | return registeredOn; 116 | } 117 | 118 | public void setRegisteredOn(Date registeredOn) { 119 | this.registeredOn = registeredOn; 120 | } 121 | 122 | public Integer getAttempts() { 123 | return attempts; 124 | } 125 | 126 | public void setAttempts(Integer attempts) { 127 | this.attempts = attempts; 128 | } 129 | 130 | public List getRoles() { 131 | return roles; 132 | } 133 | 134 | public void setRoles(List roles) { 135 | this.roles = roles; 136 | } 137 | 138 | @JsonIgnore 139 | public List getPermissions() { 140 | return permissions; 141 | } 142 | 143 | public void setPermissions(List permissions) { 144 | this.permissions = permissions; 145 | } 146 | 147 | @JsonIgnore 148 | public EmailVerification getEmailVerification() { 149 | return emailVerification; 150 | } 151 | 152 | public void setEmailVerification(EmailVerification emailVerification) { 153 | this.emailVerification = emailVerification; 154 | } 155 | 156 | @JsonIgnore 157 | public Date getLastPasswordResetDate() { 158 | return lastPasswordResetDate; 159 | } 160 | 161 | public void setLastPasswordResetDate(Date lastPasswordResetDate) { 162 | this.lastPasswordResetDate = lastPasswordResetDate; 163 | } 164 | 165 | public SellerProfile getSellerProfile() { 166 | return sellerProfile; 167 | } 168 | 169 | public void setSellerProfile(SellerProfile sellerProfile) { 170 | this.sellerProfile = sellerProfile; 171 | } 172 | 173 | public BuyerProfile getBuyerProfile() { 174 | return buyerProfile; 175 | } 176 | 177 | public void setBuyerProfile(BuyerProfile buyerProfile) { 178 | this.buyerProfile = buyerProfile; 179 | } 180 | 181 | } 182 | -------------------------------------------------------------------------------- /auth-service/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | 5 | com.quebic.auth.api 6 | auth-service 7 | 0.0.1-SNAPSHOT 8 | jar 9 | 10 | auth-service 11 | http://maven.apache.org 12 | 13 | 14 | 15 | 16 | 1.8 17 | 0.7.0 18 | 1.1.6 19 | 4.2 20 | 1.4 21 | 3.10.1 22 | 0.0.1-SNAPSHOT 23 | 24 | 25 | 81 26 | localhost 27 | 27017 28 | auth-service-db 29 | 30 | 31 | C:/quebic-images 32 | quebic.test@gmail.com 33 | quebic 34 | 35 | 36 | 37 | 38 | org.springframework.boot 39 | spring-boot-starter-parent 40 | 1.4.2.RELEASE 41 | 42 | 43 | 44 | 45 | 46 | 47 | org.springframework.boot 48 | spring-boot-starter-web 49 | 50 | 51 | 52 | 53 | org.springframework.cloud 54 | spring-cloud-starter 55 | 56 | 57 | 58 | 59 | org.springframework.cloud 60 | spring-cloud-starter-eureka-server 61 | 62 | 63 | 64 | 65 | org.springframework.boot 66 | spring-boot-starter-security 67 | 68 | 69 | 70 | 71 | org.springframework.data 72 | spring-data-mongodb 73 | 74 | 75 | 76 | 77 | org.springframework.mobile 78 | spring-mobile-device 79 | 80 | 81 | 82 | 83 | io.jsonwebtoken 84 | jjwt 85 | ${jjwt.version} 86 | 87 | 88 | 89 | 90 | io.reactivex 91 | rxjava 92 | ${rxjava.version} 93 | 94 | 95 | 96 | 97 | ch.qos.logback 98 | logback-classic 99 | 100 | 101 | 102 | ch.qos.logback 103 | logback-core 104 | 105 | 106 | 107 | 108 | 109 | javax.mail 110 | mail 111 | ${mail.version} 112 | 113 | 114 | 115 | 116 | com.quebic.common 117 | common-lib 118 | ${common.lib.version} 119 | 120 | 121 | 122 | 123 | org.springframework.boot 124 | spring-boot-devtools 125 | true 126 | 127 | 128 | 129 | 130 | org.springframework.boot 131 | spring-boot-starter-test 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | org.springframework.cloud 140 | spring-cloud-dependencies 141 | Dalston.RELEASE 142 | pom 143 | import 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | org.springframework.boot 152 | spring-boot-maven-plugin 153 | 154 | 155 | 156 | repackage 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | -------------------------------------------------------------------------------- /auth-service/src/main/java/com/quebic/auth/api/model/SellerProfile.java: -------------------------------------------------------------------------------- 1 | package com.quebic.auth.api.model; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | public class SellerProfile { 7 | 8 | private String storeId; 9 | 10 | //temp fields 11 | private List businessClariifications = new ArrayList<>(); 12 | private List deals = new ArrayList<>(); 13 | 14 | private String legalBusinessName; 15 | private String businessAddress; 16 | private String physicalAddress; 17 | private String city; 18 | private String state; 19 | private String zipCode; 20 | private String businessLocatedCountry; 21 | private String businessPhone; 22 | private String businessWebsite; 23 | 24 | private String contactFirstName; 25 | private String contactLastName; 26 | private String contactBusinessAddress; 27 | private String contactPhysicalAddress; 28 | private String contactCity; 29 | private String contactState; 30 | private String contactZipCode; 31 | private String contactPhone; 32 | private String contactEmail; 33 | 34 | public String getStoreId() { 35 | return storeId; 36 | } 37 | public void setStoreId(String storeId) { 38 | this.storeId = storeId; 39 | } 40 | public List getBusinessClariifications() { 41 | return businessClariifications; 42 | } 43 | public void setBusinessClariifications(List businessClariifications) { 44 | this.businessClariifications = businessClariifications; 45 | } 46 | public List getDeals() { 47 | return deals; 48 | } 49 | public void setDeals(List deals) { 50 | this.deals = deals; 51 | } 52 | public String getLegalBusinessName() { 53 | return legalBusinessName; 54 | } 55 | public void setLegalBusinessName(String legalBusinessName) { 56 | this.legalBusinessName = legalBusinessName; 57 | } 58 | public String getBusinessAddress() { 59 | return businessAddress; 60 | } 61 | public void setBusinessAddress(String businessAddress) { 62 | this.businessAddress = businessAddress; 63 | } 64 | public String getPhysicalAddress() { 65 | return physicalAddress; 66 | } 67 | public void setPhysicalAddress(String physicalAddress) { 68 | this.physicalAddress = physicalAddress; 69 | } 70 | public String getCity() { 71 | return city; 72 | } 73 | public void setCity(String city) { 74 | this.city = city; 75 | } 76 | public String getState() { 77 | return state; 78 | } 79 | public void setState(String state) { 80 | this.state = state; 81 | } 82 | public String getZipCode() { 83 | return zipCode; 84 | } 85 | public void setZipCode(String zipCode) { 86 | this.zipCode = zipCode; 87 | } 88 | public String getBusinessLocatedCountry() { 89 | return businessLocatedCountry; 90 | } 91 | public void setBusinessLocatedCountry(String businessLocatedCountry) { 92 | this.businessLocatedCountry = businessLocatedCountry; 93 | } 94 | public String getBusinessPhone() { 95 | return businessPhone; 96 | } 97 | public void setBusinessPhone(String businessPhone) { 98 | this.businessPhone = businessPhone; 99 | } 100 | public String getBusinessWebsite() { 101 | return businessWebsite; 102 | } 103 | public void setBusinessWebsite(String businessWebsite) { 104 | this.businessWebsite = businessWebsite; 105 | } 106 | public String getContactFirstName() { 107 | return contactFirstName; 108 | } 109 | public void setContactFirstName(String contactFirstName) { 110 | this.contactFirstName = contactFirstName; 111 | } 112 | public String getContactLastName() { 113 | return contactLastName; 114 | } 115 | public void setContactLastName(String contactLastName) { 116 | this.contactLastName = contactLastName; 117 | } 118 | public String getContactBusinessAddress() { 119 | return contactBusinessAddress; 120 | } 121 | public void setContactBusinessAddress(String contactBusinessAddress) { 122 | this.contactBusinessAddress = contactBusinessAddress; 123 | } 124 | public String getContactPhysicalAddress() { 125 | return contactPhysicalAddress; 126 | } 127 | public void setContactPhysicalAddress(String contactPhysicalAddress) { 128 | this.contactPhysicalAddress = contactPhysicalAddress; 129 | } 130 | public String getContactCity() { 131 | return contactCity; 132 | } 133 | public void setContactCity(String contactCity) { 134 | this.contactCity = contactCity; 135 | } 136 | public String getContactState() { 137 | return contactState; 138 | } 139 | public void setContactState(String contactState) { 140 | this.contactState = contactState; 141 | } 142 | public String getContactZipCode() { 143 | return contactZipCode; 144 | } 145 | public void setContactZipCode(String contactZipCode) { 146 | this.contactZipCode = contactZipCode; 147 | } 148 | public String getContactPhone() { 149 | return contactPhone; 150 | } 151 | public void setContactPhone(String contactPhone) { 152 | this.contactPhone = contactPhone; 153 | } 154 | public String getContactEmail() { 155 | return contactEmail; 156 | } 157 | public void setContactEmail(String contactEmail) { 158 | this.contactEmail = contactEmail; 159 | } 160 | 161 | 162 | 163 | } 164 | -------------------------------------------------------------------------------- /auth-service/src/main/java/com/quebic/auth/api/dto/SellerDto.java: -------------------------------------------------------------------------------- 1 | package com.quebic.auth.api.dto; 2 | 3 | import com.quebic.auth.api.model.User; 4 | 5 | public class SellerDto extends User{ 6 | 7 | private Boolean isExporter; 8 | 9 | private Boolean isDealer; 10 | 11 | private Boolean isAuctionAgent; 12 | 13 | private String bizType; 14 | 15 | private Boolean isSupplier; 16 | 17 | private Boolean isDistributor; 18 | 19 | private Boolean isDealsCar; 20 | 21 | private Boolean isDealsMachinery; 22 | 23 | private Boolean isDealsSpareParts; 24 | 25 | private String bizName; 26 | 27 | private String bizEstablishedOn; 28 | 29 | private String operationalCountry; 30 | 31 | private String currencyId; 32 | 33 | private String bizRegCertificatePath; 34 | 35 | private String bizPoliceCertificatePath; 36 | 37 | private String bizRegCardPath; 38 | 39 | private String letterOfCardAccepted; 40 | 41 | private String bankTransferAccepted; 42 | 43 | private String aboutCompany; 44 | 45 | private String notifyLogins; 46 | 47 | public Boolean getIsExporter() { 48 | return isExporter; 49 | } 50 | 51 | public void setIsExporter(Boolean isExporter) { 52 | this.isExporter = isExporter; 53 | } 54 | 55 | public Boolean getIsDealer() { 56 | return isDealer; 57 | } 58 | 59 | public void setIsDealer(Boolean isDealer) { 60 | this.isDealer = isDealer; 61 | } 62 | 63 | public Boolean getIsAuctionAgent() { 64 | return isAuctionAgent; 65 | } 66 | 67 | public void setIsAuctionAgent(Boolean isAuctionAgent) { 68 | this.isAuctionAgent = isAuctionAgent; 69 | } 70 | 71 | public String getBizType() { 72 | return bizType; 73 | } 74 | 75 | public void setBizType(String bizType) { 76 | this.bizType = bizType; 77 | } 78 | 79 | public Boolean getIsSupplier() { 80 | return isSupplier; 81 | } 82 | 83 | public void setIsSupplier(Boolean isSupplier) { 84 | this.isSupplier = isSupplier; 85 | } 86 | 87 | public Boolean getIsDistributor() { 88 | return isDistributor; 89 | } 90 | 91 | public void setIsDistributor(Boolean isDistributor) { 92 | this.isDistributor = isDistributor; 93 | } 94 | 95 | public Boolean getIsDealsCar() { 96 | return isDealsCar; 97 | } 98 | 99 | public void setIsDealsCar(Boolean isDealsCar) { 100 | this.isDealsCar = isDealsCar; 101 | } 102 | 103 | public Boolean getIsDealsMachinery() { 104 | return isDealsMachinery; 105 | } 106 | 107 | public void setIsDealsMachinery(Boolean isDealsMachinery) { 108 | this.isDealsMachinery = isDealsMachinery; 109 | } 110 | 111 | public Boolean getIsDealsSpareParts() { 112 | return isDealsSpareParts; 113 | } 114 | 115 | public void setIsDealsSpareParts(Boolean isDealsSpareParts) { 116 | this.isDealsSpareParts = isDealsSpareParts; 117 | } 118 | 119 | public String getBizName() { 120 | return bizName; 121 | } 122 | 123 | public void setBizName(String bizName) { 124 | this.bizName = bizName; 125 | } 126 | 127 | public String getBizEstablishedOn() { 128 | return bizEstablishedOn; 129 | } 130 | 131 | public void setBizEstablishedOn(String bizEstablishedOn) { 132 | this.bizEstablishedOn = bizEstablishedOn; 133 | } 134 | 135 | public String getOperationalCountry() { 136 | return operationalCountry; 137 | } 138 | 139 | public void setOperationalCountry(String operationalCountry) { 140 | this.operationalCountry = operationalCountry; 141 | } 142 | 143 | public String getCurrencyId() { 144 | return currencyId; 145 | } 146 | 147 | public void setCurrencyId(String currencyId) { 148 | this.currencyId = currencyId; 149 | } 150 | 151 | public String getBizRegCertificatePath() { 152 | return bizRegCertificatePath; 153 | } 154 | 155 | public void setBizRegCertificatePath(String bizRegCertificatePath) { 156 | this.bizRegCertificatePath = bizRegCertificatePath; 157 | } 158 | 159 | public String getBizPoliceCertificatePath() { 160 | return bizPoliceCertificatePath; 161 | } 162 | 163 | public void setBizPoliceCertificatePath(String bizPoliceCertificatePath) { 164 | this.bizPoliceCertificatePath = bizPoliceCertificatePath; 165 | } 166 | 167 | public String getBizRegCardPath() { 168 | return bizRegCardPath; 169 | } 170 | 171 | public void setBizRegCardPath(String bizRegCardPath) { 172 | this.bizRegCardPath = bizRegCardPath; 173 | } 174 | 175 | public String getLetterOfCardAccepted() { 176 | return letterOfCardAccepted; 177 | } 178 | 179 | public void setLetterOfCardAccepted(String letterOfCardAccepted) { 180 | this.letterOfCardAccepted = letterOfCardAccepted; 181 | } 182 | 183 | public String getBankTransferAccepted() { 184 | return bankTransferAccepted; 185 | } 186 | 187 | public void setBankTransferAccepted(String bankTransferAccepted) { 188 | this.bankTransferAccepted = bankTransferAccepted; 189 | } 190 | 191 | public String getAboutCompany() { 192 | return aboutCompany; 193 | } 194 | 195 | public void setAboutCompany(String aboutCompany) { 196 | this.aboutCompany = aboutCompany; 197 | } 198 | 199 | public String getNotifyLogins() { 200 | return notifyLogins; 201 | } 202 | 203 | public void setNotifyLogins(String notifyLogins) { 204 | this.notifyLogins = notifyLogins; 205 | } 206 | 207 | } 208 | -------------------------------------------------------------------------------- /auth-service/src/main/java/com/quebic/auth/api/common/util/email/EmailUtil.java: -------------------------------------------------------------------------------- 1 | package com.quebic.auth.api.common.util.email; 2 | 3 | import java.util.Properties; 4 | import java.util.concurrent.CompletableFuture; 5 | import java.util.function.Function; 6 | import java.util.function.Supplier; 7 | import javax.mail.Message; 8 | import javax.mail.PasswordAuthentication; 9 | import javax.mail.Session; 10 | import javax.mail.Transport; 11 | import javax.mail.internet.InternetAddress; 12 | import javax.mail.internet.MimeMessage; 13 | import org.slf4j.Logger; 14 | import org.slf4j.LoggerFactory; 15 | import org.springframework.beans.factory.annotation.Value; 16 | import org.springframework.context.annotation.Configuration; 17 | 18 | import com.quebic.auth.api.common.util.email.template.EmailTemplate; 19 | import com.quebic.common.constants.ConfigConstants; 20 | 21 | @Configuration 22 | public class EmailUtil { 23 | 24 | private static Logger logger = LoggerFactory.getLogger(EmailUtil.class); 25 | 26 | @Value(ConfigConstants.EMAIL_USERNAME) 27 | private String EMAIL_USERNAME; 28 | 29 | @Value(ConfigConstants.EMAIL_PASSWORD) 30 | private String EMAIL_PASSWORD; 31 | 32 | public void send(final String subject,final EmailTemplate emailTemplate, final String recipientAddress) throws Exception { 33 | 34 | final String htmlContent = emailTemplate.getTextContent(); 35 | 36 | CompletableFuture.supplyAsync(new Supplier() { 37 | @Override 38 | public String get() { 39 | 40 | logger.info("start sending email -> " + recipientAddress); 41 | 42 | // Sender's email ID needs to be mentioned 43 | String from = EMAIL_USERNAME; 44 | final String username = EMAIL_USERNAME;// change accordingly 45 | final String password = EMAIL_PASSWORD;// change accordingly 46 | 47 | // Assuming you are sending email through relay.jangosmtp.net 48 | String host = "pop.gmail.com"; 49 | 50 | Properties props = new Properties(); 51 | props.put("mail.smtp.auth", "true"); 52 | props.put("mail.smtp.starttls.enable", "true"); 53 | props.put("mail.smtp.host", host); 54 | props.put("mail.smtp.port", "25"); 55 | 56 | // Get the Session object. 57 | Session session = Session.getInstance(props, new javax.mail.Authenticator() { 58 | protected PasswordAuthentication getPasswordAuthentication() { 59 | return new PasswordAuthentication(username, password); 60 | } 61 | }); 62 | 63 | try { 64 | // Create a default MimeMessage object. 65 | Message message = new MimeMessage(session); 66 | 67 | // Set From: header field of the header. 68 | message.setFrom(new InternetAddress(from)); 69 | 70 | // Set To: header field of the header. 71 | message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(recipientAddress)); 72 | 73 | // Set Subject: header field 74 | message.setSubject(subject); 75 | 76 | message.setContent( 77 | htmlContent, 78 | "text/html"); 79 | 80 | // Send message 81 | Transport.send(message); 82 | 83 | logger.info("sent message successfully -> " + recipientAddress); 84 | 85 | } catch (Exception e) { 86 | throw new RuntimeException(e); 87 | } 88 | 89 | return "sent"; 90 | } 91 | }).exceptionally(new Function() { 92 | 93 | @Override 94 | public String apply(Throwable t) { 95 | logger.error(t.getMessage()); 96 | return null; 97 | } 98 | }); 99 | 100 | 101 | 102 | } 103 | 104 | public void send(final String subject,final String messageText,final String htmlContent,final String recipientAddress) { 105 | 106 | CompletableFuture.supplyAsync(new Supplier() { 107 | @Override 108 | public String get() { 109 | 110 | logger.info("start sending email -> " + recipientAddress); 111 | 112 | // Sender's email ID needs to be mentioned 113 | String from = EMAIL_USERNAME; 114 | final String username = EMAIL_USERNAME;// change accordingly 115 | final String password = EMAIL_PASSWORD;// change accordingly 116 | 117 | // Assuming you are sending email through relay.jangosmtp.net 118 | String host = "pop.gmail.com"; 119 | 120 | Properties props = new Properties(); 121 | props.put("mail.smtp.auth", "true"); 122 | props.put("mail.smtp.starttls.enable", "true"); 123 | props.put("mail.smtp.host", host); 124 | props.put("mail.smtp.port", "25"); 125 | 126 | // Get the Session object. 127 | Session session = Session.getInstance(props, new javax.mail.Authenticator() { 128 | protected PasswordAuthentication getPasswordAuthentication() { 129 | return new PasswordAuthentication(username, password); 130 | } 131 | }); 132 | 133 | try { 134 | // Create a default MimeMessage object. 135 | Message message = new MimeMessage(session); 136 | 137 | // Set From: header field of the header. 138 | message.setFrom(new InternetAddress(from)); 139 | 140 | // Set To: header field of the header. 141 | message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(recipientAddress)); 142 | 143 | // Set Subject: header field 144 | message.setSubject(subject); 145 | 146 | // Now set the actual message 147 | message.setText(messageText); 148 | 149 | message.setContent( 150 | htmlContent, 151 | "text/html"); 152 | 153 | // Send message 154 | Transport.send(message); 155 | 156 | logger.info("sent message successfully -> " + recipientAddress); 157 | 158 | } catch (Exception e) { 159 | throw new RuntimeException(e); 160 | } 161 | 162 | return "sent"; 163 | } 164 | }).exceptionally(new Function() { 165 | 166 | @Override 167 | public String apply(Throwable t) { 168 | logger.error(t.getMessage()); 169 | return null; 170 | } 171 | }); 172 | 173 | 174 | 175 | } 176 | 177 | } 178 | -------------------------------------------------------------------------------- /auth-service/src/main/java/com/quebic/auth/api/security/JwtTokenUtil.java: -------------------------------------------------------------------------------- 1 | package com.quebic.auth.api.security; 2 | 3 | import io.jsonwebtoken.Claims; 4 | import io.jsonwebtoken.Jwts; 5 | import io.jsonwebtoken.SignatureAlgorithm; 6 | import org.springframework.beans.factory.annotation.Value; 7 | import org.springframework.mobile.device.Device; 8 | import org.springframework.security.core.userdetails.UserDetails; 9 | import org.springframework.stereotype.Component; 10 | 11 | import java.io.Serializable; 12 | import java.util.Date; 13 | import java.util.HashMap; 14 | import java.util.Map; 15 | 16 | @Component 17 | public class JwtTokenUtil implements Serializable { 18 | 19 | private static final long serialVersionUID = -3301605591108950415L; 20 | 21 | static final String CLAIM_KEY_USERNAME = "sub"; 22 | static final String CLAIM_KEY_AUDIENCE = "audience"; 23 | static final String CLAIM_KEY_CREATED = "created"; 24 | 25 | private static final String AUDIENCE_UNKNOWN = "unknown"; 26 | private static final String AUDIENCE_WEB = "web"; 27 | private static final String AUDIENCE_MOBILE = "mobile"; 28 | private static final String AUDIENCE_TABLET = "tablet"; 29 | 30 | @Value("${jwt.secret}") 31 | private String secret; 32 | 33 | @Value("${jwt.expiration}") 34 | private Long expiration; 35 | 36 | public String getUsernameFromToken(String token) { 37 | String username; 38 | try { 39 | final Claims claims = getClaimsFromToken(token); 40 | username = claims.getSubject(); 41 | } catch (Exception e) { 42 | username = null; 43 | } 44 | return username; 45 | } 46 | 47 | public Date getCreatedDateFromToken(String token) { 48 | Date created; 49 | try { 50 | final Claims claims = getClaimsFromToken(token); 51 | created = new Date((Long) claims.get(CLAIM_KEY_CREATED)); 52 | } catch (Exception e) { 53 | created = null; 54 | } 55 | return created; 56 | } 57 | 58 | public Date getExpirationDateFromToken(String token) { 59 | Date expiration; 60 | try { 61 | final Claims claims = getClaimsFromToken(token); 62 | expiration = claims.getExpiration(); 63 | } catch (Exception e) { 64 | expiration = null; 65 | } 66 | return expiration; 67 | } 68 | 69 | public String getAudienceFromToken(String token) { 70 | String audience; 71 | try { 72 | final Claims claims = getClaimsFromToken(token); 73 | audience = (String) claims.get(CLAIM_KEY_AUDIENCE); 74 | } catch (Exception e) { 75 | audience = null; 76 | } 77 | return audience; 78 | } 79 | 80 | private Claims getClaimsFromToken(String token) { 81 | Claims claims; 82 | try { 83 | claims = Jwts.parser() 84 | .setSigningKey(secret) 85 | .parseClaimsJws(token) 86 | .getBody(); 87 | } catch (Exception e) { 88 | claims = null; 89 | } 90 | return claims; 91 | } 92 | 93 | private Date generateExpirationDate() { 94 | return new Date(System.currentTimeMillis() + expiration * 1000); 95 | } 96 | 97 | private Boolean isTokenExpired(String token) { 98 | final Date expiration = getExpirationDateFromToken(token); 99 | return expiration.before(new Date()); 100 | } 101 | 102 | private Boolean isCreatedBeforeLastPasswordReset(Date created, Date lastPasswordReset) { 103 | return (lastPasswordReset != null && created.before(lastPasswordReset)); 104 | } 105 | 106 | private String generateAudience(Device device) { 107 | String audience = AUDIENCE_UNKNOWN; 108 | if (device.isNormal()) { 109 | audience = AUDIENCE_WEB; 110 | } else if (device.isTablet()) { 111 | audience = AUDIENCE_TABLET; 112 | } else if (device.isMobile()) { 113 | audience = AUDIENCE_MOBILE; 114 | } 115 | return audience; 116 | } 117 | 118 | private Boolean ignoreTokenExpiration(String token) { 119 | String audience = getAudienceFromToken(token); 120 | return (AUDIENCE_TABLET.equals(audience) || AUDIENCE_MOBILE.equals(audience)); 121 | } 122 | 123 | public String generateToken(UserDetails userDetails, Device device) { 124 | Map claims = new HashMap<>(); 125 | claims.put(CLAIM_KEY_USERNAME, userDetails.getUsername()); 126 | claims.put(CLAIM_KEY_AUDIENCE, generateAudience(device)); 127 | claims.put(CLAIM_KEY_CREATED, new Date()); 128 | return generateToken(claims); 129 | } 130 | 131 | String generateToken(Map claims) { 132 | return Jwts.builder() 133 | .setClaims(claims) 134 | .setExpiration(generateExpirationDate()) 135 | .signWith(SignatureAlgorithm.HS512, secret) 136 | .compact(); 137 | } 138 | 139 | public Boolean canTokenBeRefreshed(String token, Date lastPasswordReset) { 140 | final Date created = getCreatedDateFromToken(token); 141 | return !isCreatedBeforeLastPasswordReset(created, lastPasswordReset) 142 | && (!isTokenExpired(token) || ignoreTokenExpiration(token)); 143 | } 144 | 145 | public String refreshToken(String token) { 146 | String refreshedToken; 147 | try { 148 | final Claims claims = getClaimsFromToken(token); 149 | claims.put(CLAIM_KEY_CREATED, new Date()); 150 | refreshedToken = generateToken(claims); 151 | } catch (Exception e) { 152 | refreshedToken = null; 153 | } 154 | return refreshedToken; 155 | } 156 | 157 | public Boolean validateToken(String token, UserDetails userDetails) { 158 | JwtUser user = (JwtUser) userDetails; 159 | final String username = getUsernameFromToken(token); 160 | final Date created = getCreatedDateFromToken(token); 161 | return ( 162 | username.equals(user.getUsername()) 163 | && !isTokenExpired(token) 164 | && !isCreatedBeforeLastPasswordReset(created, user.getLastPasswordResetDate())); 165 | } 166 | } -------------------------------------------------------------------------------- /auth-service/src/main/java/com/quebic/auth/api/service/impl/UserServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.quebic.auth.api.service.impl; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Date; 5 | import java.util.List; 6 | import java.util.stream.IntStream; 7 | import javax.annotation.PostConstruct; 8 | import org.slf4j.Logger; 9 | import org.slf4j.LoggerFactory; 10 | import org.springframework.beans.factory.annotation.Autowired; 11 | import org.springframework.beans.factory.annotation.Value; 12 | import org.springframework.security.crypto.password.PasswordEncoder; 13 | import org.springframework.stereotype.Service; 14 | import org.springframework.util.StringUtils; 15 | import org.springframework.web.multipart.MultipartFile; 16 | import com.quebic.auth.api.dao.RoleDao; 17 | import com.quebic.auth.api.dao.UserDao; 18 | import com.quebic.auth.api.dto.UserImageDto; 19 | import com.quebic.auth.api.model.Role; 20 | import com.quebic.auth.api.model.User; 21 | import com.quebic.auth.api.security.SecurityUtil; 22 | import com.quebic.auth.api.service.UserService; 23 | import com.quebic.common.constants.ConfigConstants; 24 | import com.quebic.common.exception.DataAccessException; 25 | import com.quebic.common.exception.DuplicateEmailRegisteredException; 26 | import com.quebic.common.exception.OldPasswordNotMatch; 27 | import com.quebic.common.exception.RequiredFieldMissingException; 28 | import com.quebic.common.exception.ServiceException; 29 | import com.quebic.common.messages.ErrorMessage; 30 | import com.quebic.common.messages.InfoMessage; 31 | import com.quebic.common.model.Permission; 32 | import com.quebic.common.model.image.Image; 33 | import com.quebic.common.service.impl.GenericServiceImpl; 34 | import com.quebic.common.util.image.ImageUtil; 35 | 36 | import rx.Single; 37 | import rx.exceptions.Exceptions; 38 | 39 | @Service 40 | public class UserServiceImpl extends GenericServiceImpl implements UserService{ 41 | 42 | private static Logger logger = LoggerFactory.getLogger(UserServiceImpl.class); 43 | 44 | @Autowired 45 | private UserDao userDao; 46 | 47 | @Autowired 48 | private RoleDao roleDao; 49 | 50 | @Autowired 51 | private PasswordEncoder passwordEncoder; 52 | 53 | @Value(ConfigConstants.IMAGE_UPLOAD_LOCATION) 54 | private String IMAGE_LOCATION; 55 | 56 | @PostConstruct 57 | void init() { 58 | init(User.class, userDao); 59 | } 60 | 61 | @Override 62 | public Single findByEmail(String email){ 63 | try{ 64 | return Single.just(userDao.findByEmail(email)); 65 | }catch (DataAccessException e) { 66 | return Single.error(e); 67 | } 68 | } 69 | 70 | @Override 71 | public Single findByUsernameOrEmail(String username, String email){ 72 | try{ 73 | return Single.just(userDao.findByUsernameOrEmail(username, email)); 74 | }catch (DataAccessException e) { 75 | return Single.error(e); 76 | } 77 | } 78 | 79 | @Override 80 | public Single add(User user){ 81 | 82 | registerValidation(user); 83 | 84 | return findByEmail(user.getEmail()).flatMap(checkUser->{ 85 | 86 | //check email already registered 87 | if(checkUser != null) 88 | throw Exceptions.propagate(new DuplicateEmailRegisteredException()); 89 | 90 | //setting default username, if username is empty 91 | if(StringUtils.isEmpty(user.getUsername())){ 92 | String[] splictedEmail = user.getEmail().split("@"); 93 | if(splictedEmail.length >= 2) user.setUsername(splictedEmail[0]); 94 | } 95 | 96 | //encode password 97 | user.setPassword(passwordEncoder.encode(user.getPassword())); 98 | user.setRegisteredOn(new Date()); 99 | user.setLastPasswordResetDate(new Date()); 100 | 101 | for(Role r : user.getRoles()){ 102 | 103 | Role role; 104 | try { 105 | role = roleDao.getById(r.getId()); 106 | //set user_permission 107 | List permissions = role.getPermissions(); 108 | for(Permission permission : permissions){ 109 | user.getPermissions().add(permission); 110 | } 111 | 112 | } catch (DataAccessException e) { 113 | throw Exceptions.propagate(e); 114 | } 115 | 116 | } 117 | 118 | user.setStatus(User.STATUS_ACTIVE); 119 | 120 | return super.add(user); 121 | 122 | }); 123 | 124 | } 125 | 126 | @Override 127 | public Single edit(User user, UserImageDto imageDto){ 128 | 129 | User loggedUser = SecurityUtil.getLoggedDbUser(); 130 | 131 | ImageUtil imageUtil = ImageUtil.createDropBoxStorageImageUtil(); 132 | 133 | //Prepare Profile Picture File Names 134 | List tmpProfilePictures = new ArrayList<>(); 135 | for(MultipartFile file : imageDto.getProfileImagesFiles()){ 136 | String fileName = imageUtil.genarateFileName(file); 137 | tmpProfilePictures.add(new Image(fileName)); 138 | } 139 | //Prepare Profile Picture File Names 140 | 141 | //Prepare Cover Picture File Names 142 | List tmpCoverPictures = new ArrayList<>(); 143 | for(MultipartFile file : imageDto.getCoverImagesFiles()){ 144 | String fileName = imageUtil.genarateFileName(file); 145 | tmpCoverPictures.add(new Image(fileName)); 146 | } 147 | //Prepare Cover Picture File Names 148 | 149 | return getById(loggedUser.getId()).flatMap(savedUser->{ 150 | if(savedUser != null){ 151 | 152 | /** 153 | * email, username, password, can't update by common edit function 154 | */ 155 | user.setId(savedUser.getId()); 156 | user.setEmail(savedUser.getEmail()); 157 | user.setUsername(savedUser.getUsername()); 158 | user.setPassword(savedUser.getPassword()); 159 | user.setRoles(savedUser.getRoles()); 160 | user.setPermissions(savedUser.getPermissions()); 161 | user.setRegisteredOn(savedUser.getRegisteredOn()); 162 | user.setLastPasswordResetDate(savedUser.getLastPasswordResetDate()); 163 | user.setLastLoggedOn(savedUser.getLastLoggedOn()); 164 | user.setAttempts(savedUser.getAttempts()); 165 | user.setStatus(savedUser.getStatus()); 166 | 167 | //add images with existing images 168 | user.setProfileImageContainer(savedUser.getProfileImageContainer()); 169 | user.getProfileImageContainer().getImages().addAll(tmpProfilePictures); 170 | 171 | user.setCoverImageContainer(savedUser.getCoverImageContainer()); 172 | user.getCoverImageContainer().getImages().addAll(tmpCoverPictures); 173 | 174 | if(Role.checkUserIs_Seller_Admin(savedUser) || Role.checkUserIs_Seller(savedUser)){ 175 | user.setSellerProfile(savedUser.getSellerProfile()); 176 | user.setBuyerProfile(null); 177 | } 178 | else if(Role.checkUserIs_Buyer(savedUser)){ 179 | user.setBuyerProfile(savedUser.getBuyerProfile()); 180 | user.setSellerProfile(null); 181 | } 182 | 183 | return super.edit(user); 184 | 185 | }else{ 186 | throw Exceptions.propagate(new ServiceException(ErrorMessage.USER_NOT_FOUND)); 187 | } 188 | }).map(u->{ 189 | 190 | IntStream.range(0, imageDto.getProfileImagesFiles().size()).forEach(idx->{ 191 | 192 | String id = u.getId(); 193 | String fileName = tmpProfilePictures.get(idx).getFileName(); 194 | MultipartFile file = imageDto.getProfileImagesFiles().get(idx); 195 | 196 | try{ 197 | imageUtil.storeFile(String.valueOf(id), fileName, IMAGE_LOCATION, ConfigConstants.IMAGE_PROFILE_UPLOAD_LOCATION, file).subscribe(s->{ 198 | logger.info(InfoMessage.USER_PROFILE_IMAGE_SAVED, s); 199 | }); 200 | }catch(Exception e){ 201 | throw Exceptions.propagate(e); 202 | } 203 | }); 204 | 205 | IntStream.range(0, imageDto.getCoverImagesFiles().size()).forEach(idx->{ 206 | 207 | String id = u.getId(); 208 | String fileName = tmpCoverPictures.get(idx).getFileName(); 209 | MultipartFile file = imageDto.getCoverImagesFiles().get(idx); 210 | 211 | try{ 212 | imageUtil.storeFile(String.valueOf(id), fileName, IMAGE_LOCATION, ConfigConstants.IMAGE_COVER_UPLOAD_LOCATION, file).subscribe(s->{ 213 | logger.info(InfoMessage.USER_COVER_IMAGE_SAVED, s); 214 | }); 215 | }catch(Exception e){ 216 | throw Exceptions.propagate(e); 217 | } 218 | }); 219 | 220 | return u; 221 | }); 222 | 223 | } 224 | 225 | @Override 226 | public Single changePassword(String oldPassword, String newPassword){ 227 | 228 | User loggedUser = SecurityUtil.getLoggedDbUser(); 229 | 230 | if(passwordEncoder.matches(oldPassword, loggedUser.getPassword())){ 231 | 232 | return getById(loggedUser.getId()).flatMap(savedUser->{ 233 | 234 | savedUser.setPassword(passwordEncoder.encode(newPassword)); 235 | savedUser.setLastPasswordResetDate(new Date()); 236 | super.edit(savedUser); 237 | return Single.just(true); 238 | 239 | }); 240 | 241 | }else 242 | return Single.error(new OldPasswordNotMatch()); 243 | } 244 | 245 | @Override 246 | public Single delete(String id){ 247 | User user= new User(); 248 | user.setId(id); 249 | super.delete(user); 250 | return Single.just(true); 251 | } 252 | 253 | @Override 254 | public Single delete(List idList){ 255 | for(String id : idList){ 256 | this.delete(id); 257 | } 258 | return Single.just(true); 259 | } 260 | 261 | @Override 262 | public Single findUserByToken(String token){ 263 | try{ 264 | return Single.just(userDao.findUserByToken(token)); 265 | }catch (Exception e) { 266 | return Single.error(e); 267 | } 268 | } 269 | 270 | private boolean registerValidation(User user){ 271 | 272 | List missingFields = new ArrayList<>(); 273 | 274 | if(StringUtils.isEmpty(user.getEmail())) 275 | missingFields.add("user.email"); 276 | 277 | if(StringUtils.isEmpty(user.getPassword())) 278 | missingFields.add("user.password"); 279 | 280 | if(!missingFields.isEmpty()) 281 | throw new RequiredFieldMissingException(missingFields.toArray()); 282 | 283 | return true; 284 | 285 | } 286 | 287 | } 288 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | --------------------------------------------------------------------------------