├── .mvn └── wrapper │ ├── maven-wrapper.jar │ ├── maven-wrapper.properties │ └── MavenWrapperDownloader.java ├── mysql-apt-config_0.8.16-1_all.deb ├── src ├── main │ ├── resources │ │ ├── static │ │ │ ├── img │ │ │ │ ├── blue.jpg │ │ │ │ ├── blueImg.png │ │ │ │ ├── coverImg.png │ │ │ │ ├── Grid-05.svg │ │ │ │ ├── cart.svg │ │ │ │ ├── paypal.svg │ │ │ │ └── logo.svg │ │ │ └── css │ │ │ │ └── reset-css.css │ │ ├── templates │ │ │ ├── handler.html │ │ │ ├── home │ │ │ │ ├── index.html │ │ │ │ ├── business_owner.html │ │ │ │ └── user_home.html │ │ │ ├── shopping │ │ │ │ ├── success.html │ │ │ │ └── shoppingCart.html │ │ │ ├── account │ │ │ │ ├── account-info.html │ │ │ │ ├── business-account-info.html │ │ │ │ ├── update-business.html │ │ │ │ └── update-user.html │ │ │ ├── abo │ │ │ │ ├── my-abos.html │ │ │ │ └── abo.html │ │ │ ├── login │ │ │ │ └── login.html │ │ │ ├── offer │ │ │ │ ├── offer-details.html │ │ │ │ ├── hobby-details.html │ │ │ │ ├── create_offer.html │ │ │ │ └── update-hobby.html │ │ │ ├── signup │ │ │ │ └── register-business.html │ │ │ └── fragments │ │ │ │ └── fragments.html │ │ ├── application.properties │ │ └── META-INF │ │ │ └── additional-spring-configuration-metadata.json │ └── java │ │ └── com │ │ └── example │ │ └── hobbie │ │ ├── model │ │ ├── entities │ │ │ ├── enums │ │ │ │ ├── GenderEnum.java │ │ │ │ ├── LocationEnum.java │ │ │ │ ├── UserRoleEnum.java │ │ │ │ └── CategoryNameEnum.java │ │ │ ├── BaseEntity.java │ │ │ ├── UserRoleEntity.java │ │ │ ├── Location.java │ │ │ ├── Category.java │ │ │ ├── Entry.java │ │ │ ├── BusinessOwner.java │ │ │ ├── UserEntity.java │ │ │ ├── Abo.java │ │ │ ├── Hobby.java │ │ │ ├── AppClient.java │ │ │ └── Test.java │ │ ├── repostiory │ │ │ ├── TestRepository.java │ │ │ ├── AppClientRepository.java │ │ │ ├── EntryRepository.java │ │ │ ├── UserRepository.java │ │ │ ├── LocationRepository.java │ │ │ ├── CategoryRepository.java │ │ │ ├── UserRoleRepository.java │ │ │ ├── BusinessOwnerRepository.java │ │ │ ├── HobbyRepository.java │ │ │ └── AboRepository.java │ │ ├── service │ │ │ ├── RegisterBusinessServiceModel.java │ │ │ ├── SignUpServiceModel.java │ │ │ ├── HobbyServiceModel.java │ │ │ ├── UpdateHobbyServiceModel.java │ │ │ └── TestServiceModel.java │ │ └── binding │ │ │ ├── SignUpBindingModel.java │ │ │ ├── UpdateClientBindingModel.java │ │ │ ├── RegisterBusinessBindingModel.java │ │ │ ├── UpdateBusinessBindingModel.java │ │ │ ├── HobbyBindingModel.java │ │ │ ├── UpdateHobbyBindingModel.java │ │ │ └── TestBindingModel.java │ │ ├── handler │ │ ├── NotFoundException.java │ │ ├── FailToDeleteException.java │ │ └── GlobalAdvice.java │ │ ├── service │ │ ├── TestService.java │ │ ├── CloudinaryService.java │ │ ├── NotificationService.java │ │ ├── CategoryService.java │ │ ├── LocationService.java │ │ ├── UserRoleService.java │ │ ├── ShoppingCartService.java │ │ ├── EntryService.java │ │ ├── AboService.java │ │ ├── impl │ │ │ ├── CloudinaryServiceImpl.java │ │ │ ├── UserRoleServiceImpl.java │ │ │ ├── NotificationServiceImpl.java │ │ │ ├── LocationServiceImpl.java │ │ │ ├── CategoryServiceImpl.java │ │ │ ├── TestServiceImpl.java │ │ │ ├── EntryServiceImpl.java │ │ │ ├── ShoppingCartServiceImpl.java │ │ │ └── AboServiceImpl.java │ │ ├── HobbyService.java │ │ └── UserService.java │ │ ├── HobbieApplication.java │ │ ├── config │ │ ├── ListenerConfig.java │ │ ├── MvcConfig.java │ │ ├── CloudConfig.java │ │ ├── HobbieConfigurationBeans.java │ │ ├── SecurityConfig.java │ │ ├── SessionTimerInterceptor.java │ │ └── UserInterceptor.java │ │ ├── view │ │ ├── EntryViewModel.java │ │ ├── AboViewModel.java │ │ ├── HobbyCardViewModel.java │ │ └── HobbyViewModel.java │ │ ├── init │ │ └── DBInit.java │ │ ├── security │ │ └── HobbieUserDetailsService.java │ │ └── web │ │ ├── ShoppingCartController.java │ │ ├── TestController.java │ │ ├── HomeController.java │ │ └── AboController.java └── test │ └── java │ └── com │ └── example │ └── hobbie │ ├── HobbieApplicationTests.java │ ├── service │ └── impl │ │ ├── TestServiceImplTest.java │ │ ├── CategoryServiceTest.java │ │ ├── LocationServiceImplTest.java │ │ └── UserRoleServiceImplTest.java │ └── web │ ├── AboControllerTest.java │ ├── TestControllerTest.java │ ├── HobbyControllerTest.java │ └── UserControllerTest.java ├── .gitignore └── README.md /.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/purshink/Spring-Boot-Thymeleaf-App/HEAD/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /mysql-apt-config_0.8.16-1_all.deb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/purshink/Spring-Boot-Thymeleaf-App/HEAD/mysql-apt-config_0.8.16-1_all.deb -------------------------------------------------------------------------------- /src/main/resources/static/img/blue.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/purshink/Spring-Boot-Thymeleaf-App/HEAD/src/main/resources/static/img/blue.jpg -------------------------------------------------------------------------------- /src/main/resources/static/img/blueImg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/purshink/Spring-Boot-Thymeleaf-App/HEAD/src/main/resources/static/img/blueImg.png -------------------------------------------------------------------------------- /src/main/resources/static/img/coverImg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/purshink/Spring-Boot-Thymeleaf-App/HEAD/src/main/resources/static/img/coverImg.png -------------------------------------------------------------------------------- /src/main/java/com/example/hobbie/model/entities/enums/GenderEnum.java: -------------------------------------------------------------------------------- 1 | package com.example.hobbie.model.entities.enums; 2 | 3 | public enum GenderEnum { 4 | MALE, FEMALE, OTHER; 5 | } 6 | -------------------------------------------------------------------------------- /src/main/java/com/example/hobbie/model/entities/enums/LocationEnum.java: -------------------------------------------------------------------------------- 1 | package com.example.hobbie.model.entities.enums; 2 | 3 | public enum LocationEnum { 4 | ZURICH, OTHER; 5 | } 6 | -------------------------------------------------------------------------------- /src/main/java/com/example/hobbie/model/entities/enums/UserRoleEnum.java: -------------------------------------------------------------------------------- 1 | package com.example.hobbie.model.entities.enums; 2 | 3 | public enum UserRoleEnum { 4 | ADMIN, USER, BUSINESS_USER; 5 | } 6 | -------------------------------------------------------------------------------- /src/main/resources/templates/handler.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |

Uuups, we are truly sorry!

5 |

6 | 7 | 8 | -------------------------------------------------------------------------------- /src/main/java/com/example/hobbie/model/entities/enums/CategoryNameEnum.java: -------------------------------------------------------------------------------- 1 | package com.example.hobbie.model.entities.enums; 2 | 3 | public enum CategoryNameEnum { 4 | ACTIVE, FUN, CREATIVE, RELAX, INTELLECTUAL, SOCIAL, OTHER; 5 | } 6 | -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar 3 | -------------------------------------------------------------------------------- /src/main/java/com/example/hobbie/handler/NotFoundException.java: -------------------------------------------------------------------------------- 1 | package com.example.hobbie.handler; 2 | 3 | public class NotFoundException extends RuntimeException { 4 | public NotFoundException(String message) { 5 | super(message); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/com/example/hobbie/handler/FailToDeleteException.java: -------------------------------------------------------------------------------- 1 | package com.example.hobbie.handler; 2 | 3 | public class FailToDeleteException extends RuntimeException { 4 | public FailToDeleteException(String message) { 5 | super(message); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/com/example/hobbie/service/TestService.java: -------------------------------------------------------------------------------- 1 | package com.example.hobbie.service; 2 | 3 | import com.example.hobbie.model.entities.Test; 4 | import com.example.hobbie.model.service.TestServiceModel; 5 | 6 | public interface TestService { 7 | void saveTest(TestServiceModel map); 8 | } 9 | -------------------------------------------------------------------------------- /src/test/java/com/example/hobbie/HobbieApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.example.hobbie; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | class HobbieApplicationTests { 8 | @Test 9 | void contextLoads() { 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/com/example/hobbie/service/CloudinaryService.java: -------------------------------------------------------------------------------- 1 | package com.example.hobbie.service; 2 | 3 | import org.springframework.web.multipart.MultipartFile; 4 | 5 | import java.io.IOException; 6 | 7 | public interface CloudinaryService { 8 | String uploadImage(MultipartFile multipartFile) throws IOException; 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/com/example/hobbie/model/repostiory/TestRepository.java: -------------------------------------------------------------------------------- 1 | package com.example.hobbie.model.repostiory; 2 | 3 | import com.example.hobbie.model.entities.Test; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | import org.springframework.stereotype.Repository; 6 | 7 | @Repository 8 | public interface TestRepository extends JpaRepository { 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/com/example/hobbie/service/NotificationService.java: -------------------------------------------------------------------------------- 1 | package com.example.hobbie.service; 2 | 3 | import com.example.hobbie.model.entities.AppClient; 4 | import com.example.hobbie.model.entities.Entry; 5 | import org.springframework.scheduling.annotation.Async; 6 | 7 | public interface NotificationService { 8 | @Async 9 | void sendNotification(AppClient appClient, Entry entry); 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/com/example/hobbie/service/CategoryService.java: -------------------------------------------------------------------------------- 1 | package com.example.hobbie.service; 2 | 3 | import com.example.hobbie.model.entities.Category; 4 | import com.example.hobbie.model.entities.enums.CategoryNameEnum; 5 | 6 | import java.util.List; 7 | 8 | public interface CategoryService { 9 | Category findByName(CategoryNameEnum category); 10 | 11 | List initCategories(); 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/com/example/hobbie/service/LocationService.java: -------------------------------------------------------------------------------- 1 | package com.example.hobbie.service; 2 | 3 | import com.example.hobbie.model.entities.Location; 4 | import com.example.hobbie.model.entities.enums.LocationEnum; 5 | 6 | import java.util.List; 7 | 8 | public interface LocationService { 9 | List initLocations(); 10 | 11 | Location getLocationByName(LocationEnum locationEnum); 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/com/example/hobbie/service/UserRoleService.java: -------------------------------------------------------------------------------- 1 | package com.example.hobbie.service; 2 | 3 | import com.example.hobbie.model.entities.UserRoleEntity; 4 | import com.example.hobbie.model.entities.enums.UserRoleEnum; 5 | 6 | public interface UserRoleService { 7 | UserRoleEntity getUserRoleByEnumName(UserRoleEnum userRoleEnum); 8 | 9 | UserRoleEntity saveRole(UserRoleEntity userRoleEntity); 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/com/example/hobbie/model/repostiory/AppClientRepository.java: -------------------------------------------------------------------------------- 1 | package com.example.hobbie.model.repostiory; 2 | 3 | import com.example.hobbie.model.entities.AppClient; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | import org.springframework.stereotype.Repository; 6 | 7 | import java.util.Optional; 8 | 9 | @Repository 10 | public interface AppClientRepository extends JpaRepository { 11 | Optional findByUsername(String username); 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/com/example/hobbie/model/repostiory/EntryRepository.java: -------------------------------------------------------------------------------- 1 | package com.example.hobbie.model.repostiory; 2 | 3 | import com.example.hobbie.model.entities.Entry; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | import org.springframework.stereotype.Repository; 6 | 7 | import java.util.List; 8 | import java.util.Optional; 9 | 10 | @Repository 11 | public interface EntryRepository extends JpaRepository { 12 | 13 | List findAllByAboId(Long id); 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/com/example/hobbie/HobbieApplication.java: -------------------------------------------------------------------------------- 1 | package com.example.hobbie; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.scheduling.annotation.EnableAsync; 6 | 7 | @SpringBootApplication 8 | @EnableAsync 9 | public class HobbieApplication { 10 | 11 | public static void main(String[] args) { 12 | SpringApplication.run(HobbieApplication.class, args); 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/com/example/hobbie/service/ShoppingCartService.java: -------------------------------------------------------------------------------- 1 | package com.example.hobbie.service; 2 | 3 | import com.example.hobbie.model.entities.Abo; 4 | import com.example.hobbie.model.entities.Hobby; 5 | 6 | import java.math.BigDecimal; 7 | import java.util.List; 8 | 9 | public interface ShoppingCartService { 10 | void addAboToCart(Hobby hobieById); 11 | 12 | void removeProductFromCart(Long hobbyId); 13 | 14 | BigDecimal getTotal(); 15 | 16 | List getAbosInCart(); 17 | 18 | void checkout(); 19 | } 20 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/**/target/ 5 | !**/src/test/**/target/ 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | !**/src/main/**/build/ 30 | !**/src/test/**/build/ 31 | 32 | ### VS Code ### 33 | .vscode/ 34 | -------------------------------------------------------------------------------- /src/main/java/com/example/hobbie/config/ListenerConfig.java: -------------------------------------------------------------------------------- 1 | package com.example.hobbie.config; 2 | 3 | import org.springframework.web.WebApplicationInitializer; 4 | import org.springframework.web.context.request.RequestContextListener; 5 | 6 | import javax.servlet.ServletContext; 7 | import javax.servlet.ServletException; 8 | 9 | public class ListenerConfig implements WebApplicationInitializer { 10 | @Override 11 | public void onStartup(ServletContext sc) throws ServletException { 12 | sc.addListener(new RequestContextListener()); 13 | } 14 | } -------------------------------------------------------------------------------- /src/main/java/com/example/hobbie/model/repostiory/UserRepository.java: -------------------------------------------------------------------------------- 1 | package com.example.hobbie.model.repostiory; 2 | 3 | 4 | import com.example.hobbie.model.entities.UserEntity; 5 | import org.springframework.data.jpa.repository.JpaRepository; 6 | import org.springframework.stereotype.Repository; 7 | 8 | import java.util.Optional; 9 | 10 | @Repository 11 | public interface UserRepository extends JpaRepository { 12 | Optional findByUsername(String username); 13 | 14 | Optional findByEmail(String email); 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/com/example/hobbie/model/repostiory/LocationRepository.java: -------------------------------------------------------------------------------- 1 | package com.example.hobbie.model.repostiory; 2 | 3 | import com.example.hobbie.model.entities.Location; 4 | import com.example.hobbie.model.entities.enums.LocationEnum; 5 | import org.springframework.data.jpa.repository.JpaRepository; 6 | import org.springframework.stereotype.Repository; 7 | 8 | import java.util.Optional; 9 | 10 | @Repository 11 | public interface LocationRepository extends JpaRepository { 12 | Optional findByName(LocationEnum locationEnum); 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/com/example/hobbie/model/entities/BaseEntity.java: -------------------------------------------------------------------------------- 1 | package com.example.hobbie.model.entities; 2 | 3 | import javax.persistence.*; 4 | 5 | @MappedSuperclass 6 | public abstract class BaseEntity { 7 | 8 | protected Long id; 9 | 10 | public BaseEntity() { 11 | } 12 | 13 | @Id 14 | @GeneratedValue(strategy = GenerationType.IDENTITY) 15 | @Column(name = "id", nullable = false, updatable = false) 16 | public Long getId() { 17 | return id; 18 | } 19 | 20 | public void setId(Long id) { 21 | this.id = id; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/com/example/hobbie/model/repostiory/CategoryRepository.java: -------------------------------------------------------------------------------- 1 | package com.example.hobbie.model.repostiory; 2 | 3 | import com.example.hobbie.model.entities.Category; 4 | import com.example.hobbie.model.entities.enums.CategoryNameEnum; 5 | import org.springframework.data.jpa.repository.JpaRepository; 6 | import org.springframework.stereotype.Repository; 7 | 8 | import java.util.Optional; 9 | 10 | @Repository 11 | public interface CategoryRepository extends JpaRepository { 12 | 13 | Optional findByName(CategoryNameEnum category); 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/com/example/hobbie/model/repostiory/UserRoleRepository.java: -------------------------------------------------------------------------------- 1 | package com.example.hobbie.model.repostiory; 2 | 3 | import com.example.hobbie.model.entities.UserRoleEntity; 4 | import com.example.hobbie.model.entities.enums.UserRoleEnum; 5 | import org.springframework.data.jpa.repository.JpaRepository; 6 | import org.springframework.stereotype.Repository; 7 | 8 | import java.util.Optional; 9 | 10 | @Repository 11 | public interface UserRoleRepository extends JpaRepository { 12 | Optional findByRole(UserRoleEnum roleEnum); 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/com/example/hobbie/service/EntryService.java: -------------------------------------------------------------------------------- 1 | package com.example.hobbie.service; 2 | 3 | import com.example.hobbie.model.entities.AppClient; 4 | import com.example.hobbie.model.entities.Entry; 5 | import com.example.hobbie.view.EntryViewModel; 6 | 7 | import java.util.List; 8 | 9 | public interface EntryService { 10 | List getAboEntries(Long id); 11 | 12 | List saveAboEntries(List aboEntries); 13 | 14 | void saveUpdatedEntry(AppClient appClient, Long entryId); 15 | 16 | void confirmUpdatedEntry(Long entryId); 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/com/example/hobbie/model/repostiory/BusinessOwnerRepository.java: -------------------------------------------------------------------------------- 1 | package com.example.hobbie.model.repostiory; 2 | 3 | import com.example.hobbie.model.entities.BusinessOwner; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | import org.springframework.stereotype.Repository; 6 | 7 | import java.util.Optional; 8 | 9 | @Repository 10 | public interface BusinessOwnerRepository extends JpaRepository { 11 | Optional findByUsername(String username); 12 | 13 | Optional findByBusinessName(String businessName); 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/com/example/hobbie/model/repostiory/HobbyRepository.java: -------------------------------------------------------------------------------- 1 | package com.example.hobbie.model.repostiory; 2 | 3 | import com.example.hobbie.model.entities.Hobby; 4 | import com.example.hobbie.model.entities.Location; 5 | import org.springframework.data.jpa.repository.JpaRepository; 6 | import org.springframework.stereotype.Repository; 7 | 8 | import java.util.List; 9 | 10 | @Repository 11 | public interface HobbyRepository extends JpaRepository { 12 | 13 | List findAllByBusinessOwnerBusinessName(String businessName); 14 | 15 | List findAllByLocation(Location location); 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/com/example/hobbie/model/repostiory/AboRepository.java: -------------------------------------------------------------------------------- 1 | package com.example.hobbie.model.repostiory; 2 | 3 | import com.example.hobbie.model.entities.Abo; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | import org.springframework.stereotype.Repository; 6 | 7 | import java.util.List; 8 | import java.util.Optional; 9 | 10 | @Repository 11 | public interface AboRepository extends JpaRepository { 12 | 13 | List findByClientId(Long id); 14 | 15 | Optional findByEntriesId(Long entryId); 16 | 17 | List findByHobbyId(Long id); 18 | 19 | List findAllByBusinessOwnerId(Long id); 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/example/hobbie/model/entities/UserRoleEntity.java: -------------------------------------------------------------------------------- 1 | package com.example.hobbie.model.entities; 2 | 3 | import com.example.hobbie.model.entities.enums.UserRoleEnum; 4 | 5 | import javax.persistence.Entity; 6 | import javax.persistence.EnumType; 7 | import javax.persistence.Enumerated; 8 | import javax.persistence.Table; 9 | 10 | @Entity 11 | @Table(name = "roles") 12 | public class UserRoleEntity extends BaseEntity { 13 | private UserRoleEnum role; 14 | 15 | @Enumerated(EnumType.STRING) 16 | public UserRoleEnum getRole() { 17 | return role; 18 | } 19 | 20 | public void setRole(UserRoleEnum role) { 21 | this.role = role; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/com/example/hobbie/model/entities/Location.java: -------------------------------------------------------------------------------- 1 | package com.example.hobbie.model.entities; 2 | 3 | import com.example.hobbie.model.entities.enums.LocationEnum; 4 | 5 | import javax.persistence.*; 6 | 7 | @Entity 8 | @Table(name = "locations") 9 | public class Location extends BaseEntity { 10 | 11 | private LocationEnum name; 12 | 13 | public Location(LocationEnum locationEnum) { 14 | this.name = locationEnum; 15 | } 16 | 17 | public Location() { 18 | } 19 | 20 | @Column(unique = true) 21 | @Enumerated(EnumType.STRING) 22 | public LocationEnum getName() { 23 | return name; 24 | } 25 | 26 | public void setName(LocationEnum name) { 27 | this.name = name; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/com/example/hobbie/model/entities/Category.java: -------------------------------------------------------------------------------- 1 | package com.example.hobbie.model.entities; 2 | 3 | import com.example.hobbie.model.entities.enums.CategoryNameEnum; 4 | 5 | import javax.persistence.*; 6 | 7 | @Entity 8 | @Table(name = "categories") 9 | public class Category extends BaseEntity { 10 | private CategoryNameEnum name; 11 | 12 | public Category(CategoryNameEnum categoryNameEnum) { 13 | this.name = categoryNameEnum; 14 | } 15 | 16 | public Category() { 17 | } 18 | 19 | @Column(unique = true) 20 | @Enumerated(EnumType.STRING) 21 | public CategoryNameEnum getName() { 22 | return name; 23 | } 24 | 25 | public void setName(CategoryNameEnum name) { 26 | this.name = name; 27 | } 28 | } -------------------------------------------------------------------------------- /src/main/java/com/example/hobbie/handler/GlobalAdvice.java: -------------------------------------------------------------------------------- 1 | package com.example.hobbie.handler; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | import org.springframework.web.bind.annotation.ControllerAdvice; 6 | import org.springframework.web.bind.annotation.ExceptionHandler; 7 | import org.springframework.web.servlet.ModelAndView; 8 | 9 | @ControllerAdvice 10 | class GlobalAdvise { 11 | 12 | private static final Logger LOGGER = LoggerFactory.getLogger(GlobalAdvise.class); 13 | 14 | @ExceptionHandler({FailToDeleteException.class, NotFoundException.class}) 15 | public ModelAndView handleDBInconsistentException(RuntimeException ex) { 16 | ModelAndView modelAndView = new ModelAndView("handler"); 17 | modelAndView.addObject("message", ex.getMessage()); 18 | return modelAndView; 19 | } 20 | } 21 | 22 | -------------------------------------------------------------------------------- /src/main/java/com/example/hobbie/service/AboService.java: -------------------------------------------------------------------------------- 1 | package com.example.hobbie.service; 2 | 3 | import com.example.hobbie.model.entities.Abo; 4 | import com.example.hobbie.model.entities.AppClient; 5 | import com.example.hobbie.view.AboViewModel; 6 | 7 | import java.util.List; 8 | 9 | public interface AboService { 10 | List saveAbos(List inCart); 11 | 12 | List getUserAbos(Long id); 13 | 14 | void updateAbosWithEntries(List abos); 15 | 16 | Long findAboId(Long id); 17 | 18 | List getAbosPerBusiness(); 19 | 20 | AppClient getClientDetails(Long id); 21 | 22 | AboViewModel findAboById(Long id); 23 | 24 | List getExcistingAbosForClient(Long id); 25 | 26 | void deleteAbo(Long id); 27 | 28 | void findExcistingAbosWithHobbyId(Long id); 29 | 30 | Abo findAbo(Long id); 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/com/example/hobbie/config/MvcConfig.java: -------------------------------------------------------------------------------- 1 | package com.example.hobbie.config; 2 | 3 | import org.springframework.context.annotation.Configuration; 4 | import org.springframework.web.servlet.config.annotation.InterceptorRegistry; 5 | import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; 6 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; 7 | 8 | @Configuration 9 | public class MvcConfig implements WebMvcConfigurer { 10 | 11 | @Override 12 | public void addResourceHandlers(final ResourceHandlerRegistry registry) { 13 | 14 | registry.addResourceHandler("/hobby-photos/**").addResourceLocations("file:hobby-photos/"); 15 | } 16 | 17 | @Override 18 | public void addInterceptors(InterceptorRegistry registry) { 19 | registry.addInterceptor(new UserInterceptor()); 20 | registry.addInterceptor(new SessionTimerInterceptor()); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/com/example/hobbie/model/entities/Entry.java: -------------------------------------------------------------------------------- 1 | package com.example.hobbie.model.entities; 2 | 3 | import javax.persistence.*; 4 | 5 | @Entity 6 | @Table(name = "entries") 7 | public class Entry extends BaseEntity { 8 | 9 | private String date; 10 | private Abo abo; 11 | private boolean isInProcess; 12 | 13 | public Entry() { 14 | } 15 | 16 | @ManyToOne(cascade = CascadeType.ALL) 17 | public Abo getAbo() { 18 | return abo; 19 | } 20 | 21 | public void setAbo(Abo abo) { 22 | this.abo = abo; 23 | } 24 | 25 | @Column 26 | public String getDate() { 27 | return date; 28 | } 29 | 30 | public void setDate(String date) { 31 | this.date = date; 32 | } 33 | 34 | public boolean isInProcess() { 35 | return isInProcess; 36 | } 37 | 38 | public void setInProcess(boolean inProcess) { 39 | isInProcess = inProcess; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/com/example/hobbie/config/CloudConfig.java: -------------------------------------------------------------------------------- 1 | package com.example.hobbie.config; 2 | 3 | import com.cloudinary.Cloudinary; 4 | import org.springframework.beans.factory.annotation.Value; 5 | import org.springframework.context.annotation.Bean; 6 | import org.springframework.context.annotation.Configuration; 7 | 8 | import java.util.HashMap; 9 | import java.util.Map; 10 | 11 | @Configuration 12 | public class CloudConfig { 13 | 14 | @Value("${cloudinary.cloud-name}") 15 | private String cloudName; 16 | @Value("${cloudinary.api-key}") 17 | private String apiKey; 18 | @Value("${cloudinary.api-secret}") 19 | private String apiSecret; 20 | 21 | @Bean 22 | public Cloudinary createCloudinaryConfig() { 23 | Map config = new HashMap<>(); 24 | config.put("cloud_name", cloudName); 25 | config.put("api_key", apiKey); 26 | config.put("api_secret", apiSecret); 27 | return new Cloudinary(config); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/com/example/hobbie/view/EntryViewModel.java: -------------------------------------------------------------------------------- 1 | package com.example.hobbie.view; 2 | 3 | import java.util.Date; 4 | 5 | public class EntryViewModel { 6 | private Long id; 7 | private String date; 8 | private Long aboId; 9 | private boolean isInProcess; 10 | 11 | public EntryViewModel() { 12 | } 13 | 14 | public Long getAboId() { 15 | return aboId; 16 | } 17 | 18 | public void setAboId(Long abId) { 19 | this.aboId = abId; 20 | } 21 | 22 | public String getDate() { 23 | return date; 24 | } 25 | 26 | public void setDate(String date) { 27 | this.date = date; 28 | } 29 | 30 | 31 | public Long getId() { 32 | return id; 33 | } 34 | 35 | public void setId(Long id) { 36 | this.id = id; 37 | } 38 | 39 | public boolean isInProcess() { 40 | return isInProcess; 41 | } 42 | 43 | public void setInProcess(boolean inProcess) { 44 | isInProcess = inProcess; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/com/example/hobbie/config/HobbieConfigurationBeans.java: -------------------------------------------------------------------------------- 1 | package com.example.hobbie.config; 2 | 3 | import org.modelmapper.ModelMapper; 4 | import org.springframework.context.annotation.Bean; 5 | import org.springframework.context.annotation.Configuration; 6 | import org.springframework.security.core.session.SessionRegistry; 7 | import org.springframework.security.core.session.SessionRegistryImpl; 8 | import org.springframework.security.crypto.password.PasswordEncoder; 9 | import org.springframework.security.crypto.password.Pbkdf2PasswordEncoder; 10 | 11 | @Configuration 12 | public class HobbieConfigurationBeans { 13 | 14 | @Bean 15 | public PasswordEncoder createPasswordEncoder() { 16 | return new Pbkdf2PasswordEncoder(); 17 | } 18 | 19 | @Bean 20 | public ModelMapper createModelMapper() { 21 | return new ModelMapper(); 22 | } 23 | 24 | @Bean 25 | public SessionRegistry sessionRegistry() { 26 | return new SessionRegistryImpl(); 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /src/main/resources/static/img/Grid-05.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 8 | 9 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/main/java/com/example/hobbie/service/impl/CloudinaryServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.example.hobbie.service.impl; 2 | 3 | import com.cloudinary.Cloudinary; 4 | import com.example.hobbie.service.CloudinaryService; 5 | import org.springframework.stereotype.Service; 6 | import org.springframework.web.multipart.MultipartFile; 7 | 8 | import java.io.File; 9 | import java.io.IOException; 10 | import java.util.Collections; 11 | 12 | @Service 13 | public class CloudinaryServiceImpl implements CloudinaryService { 14 | private static final String TEMP_FILE = "temp-file"; 15 | private static final String URL = "url"; 16 | private final Cloudinary cloudinary; 17 | 18 | public CloudinaryServiceImpl(Cloudinary cloudinary) { 19 | this.cloudinary = cloudinary; 20 | } 21 | 22 | @Override 23 | public String uploadImage(MultipartFile multipartFile) throws IOException { 24 | File file = File.createTempFile(TEMP_FILE, multipartFile.getOriginalFilename()); 25 | multipartFile.transferTo(file); 26 | 27 | return this.cloudinary 28 | .uploader() 29 | .upload(file, Collections.emptyMap()) 30 | .get(URL) 31 | .toString(); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/com/example/hobbie/service/HobbyService.java: -------------------------------------------------------------------------------- 1 | package com.example.hobbie.service; 2 | 3 | import com.example.hobbie.model.entities.AppClient; 4 | import com.example.hobbie.model.entities.Hobby; 5 | import com.example.hobbie.model.service.HobbyServiceModel; 6 | import com.example.hobbie.model.service.UpdateHobbyServiceModel; 7 | import com.example.hobbie.view.HobbyCardViewModel; 8 | import com.example.hobbie.view.HobbyViewModel; 9 | 10 | import java.io.IOException; 11 | import java.util.List; 12 | 13 | public interface HobbyService { 14 | Long createHobby(HobbyServiceModel hobbyServiceModel, String fileName) throws IOException; 15 | 16 | List getAllHobbyOffers(); 17 | 18 | Hobby findHobbieById(Long id); 19 | 20 | void saveUpdatedHobby(UpdateHobbyServiceModel map, String fileName) throws IOException; 21 | 22 | void deleteHobby(long id) throws IOException; 23 | 24 | List initHobbyOffers(); 25 | 26 | List findHobbyMatches(AppClient currentUserAppClient); 27 | 28 | List getHobbyMatches(AppClient currentAppClient); 29 | 30 | void saveHobbyForClient(Hobby hobby); 31 | 32 | void removeHobbyForClient(Hobby hobby); 33 | 34 | boolean isHobbySaved(Long hobbyId); 35 | 36 | List findSavedHobbies(AppClient appClient); 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/main/resources/static/css/reset-css.css: -------------------------------------------------------------------------------- 1 | /* http://meyerweb.com/eric/tools/css/reset/ 2 | v2.0 | 20110126 3 | License: none (public domain) 4 | */ 5 | 6 | html, body, div, span, applet, object, iframe, 7 | h1, h2, h3, h4, h5, h6, p, blockquote, pre, 8 | a, abbr, acronym, address, big, cite, code, 9 | del, dfn, em, img, ins, kbd, q, s, samp, 10 | small, strike, strong, sub, sup, tt, var, 11 | b, u, i, center, 12 | dl, dt, dd, ol, ul, li, 13 | fieldset, form, label, legend, 14 | table, caption, tbody, tfoot, thead, tr, th, td, 15 | article, aside, canvas, details, embed, 16 | figure, figcaption, footer, header, hgroup, 17 | menu, nav, output, ruby, section, summary, 18 | time, mark, audio, video { 19 | margin: 0; 20 | padding: 0; 21 | border: 0; 22 | font-size: 100%; 23 | font: inherit; 24 | vertical-align: baseline; 25 | } 26 | 27 | /* HTML5 display-role reset for older browsers */ 28 | article, aside, details, figcaption, figure, 29 | footer, header, hgroup, menu, nav, section { 30 | display: block; 31 | } 32 | 33 | body { 34 | line-height: 1; 35 | } 36 | 37 | ol, ul { 38 | list-style: none; 39 | } 40 | 41 | blockquote, q { 42 | quotes: none; 43 | } 44 | 45 | blockquote:before, blockquote:after, 46 | q:before, q:after { 47 | content: ''; 48 | content: none; 49 | } 50 | 51 | table { 52 | border-collapse: collapse; 53 | border-spacing: 0; 54 | } -------------------------------------------------------------------------------- /src/main/java/com/example/hobbie/view/AboViewModel.java: -------------------------------------------------------------------------------- 1 | package com.example.hobbie.view; 2 | 3 | import com.example.hobbie.model.entities.AppClient; 4 | import com.example.hobbie.model.entities.Hobby; 5 | import com.sun.xml.bind.v2.TODO; 6 | 7 | import java.math.BigDecimal; 8 | 9 | public class AboViewModel { 10 | private Long id; 11 | private String clientName; 12 | private Long hobbyId; 13 | private String name; 14 | private BigDecimal aboPrice; 15 | 16 | public AboViewModel() { 17 | } 18 | 19 | public Long getId() { 20 | return id; 21 | } 22 | 23 | public void setId(Long id) { 24 | this.id = id; 25 | } 26 | 27 | public String getClientName() { 28 | return clientName; 29 | } 30 | 31 | public void setClientName(String clientName) { 32 | this.clientName = clientName; 33 | } 34 | 35 | public BigDecimal getAboPrice() { 36 | return aboPrice; 37 | } 38 | 39 | public void setAboPrice(BigDecimal aboPrice) { 40 | this.aboPrice = aboPrice; 41 | } 42 | 43 | public Long getHobbyId() { 44 | return hobbyId; 45 | } 46 | 47 | public void setHobbyId(Long hobbyId) { 48 | this.hobbyId = hobbyId; 49 | } 50 | 51 | public String getName() { 52 | return name; 53 | } 54 | 55 | public void setName(String name) { 56 | this.name = name; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | cloudinary.api-key=682484861437535 2 | cloudinary.api-secret=W1ns5yui4XHI6wtoZ9mMZUOe2AA 3 | cloudinary.cloud-name=duyxug7zo 4 | spring.datasource.driverClassName=com.mysql.cj.jdbc.Driver 5 | spring.datasource.password=1 6 | spring.datasource.url=jdbc:mysql://localhost:3306/hobbie_db?allowPublicKeyRetrieval=true&useSSL=false&createDatabaseIfNotExist=true&useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC 7 | spring.datasource.username=root 8 | spring.jpa.database-platform=org.hibernate.dialect.MySQL5InnoDBDialect 9 | spring.jpa.hibernate.ddl-auto=create 10 | spring.jpa.hibernate.use-new-id-generator-mappings=false 11 | spring.jpa.open-in-view=false 12 | spring.jpa.properties.hibernate.format_sql=true 13 | spring.jpa.properties.hibernate.mvc.hiddenmethod.enabled=true 14 | spring.rsocket.server.error.include-message=always 15 | spring.rsocket.server.error.include-stacktrace=never 16 | spring.rsocket.server.port=8080 17 | spring.servlet.multipart.enabled=true 18 | spring.servlet.multipart.max-file-size=10MB 19 | spring.servlet.multipart.max-request-size=10MB 20 | spring.mail.host=smtp.gmail.com 21 | spring.mail.port=25 22 | spring.mail.username=findyourhobbie@gmail.com 23 | spring.mail.password=scejyiuhzjzqhezl 24 | spring.mail.protocol=smtp 25 | spring.mail.properties.mail.smtp.starttls.enable=true 26 | spring.mail.default-encoding=UTF-8 27 | -------------------------------------------------------------------------------- /src/main/java/com/example/hobbie/init/DBInit.java: -------------------------------------------------------------------------------- 1 | package com.example.hobbie.init; 2 | 3 | import com.example.hobbie.service.CategoryService; 4 | import com.example.hobbie.service.HobbyService; 5 | import com.example.hobbie.service.LocationService; 6 | import com.example.hobbie.service.UserService; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.boot.CommandLineRunner; 9 | import org.springframework.stereotype.Component; 10 | 11 | @Component 12 | public class DBInit implements CommandLineRunner { 13 | 14 | private final UserService userService; 15 | private final CategoryService categoryService; 16 | private final HobbyService hobbyService; 17 | private final LocationService locationService; 18 | 19 | @Autowired 20 | public DBInit(UserService userService, CategoryService categoryService, HobbyService hobbyService, LocationService locationService) { 21 | this.userService = userService; 22 | this.categoryService = categoryService; 23 | this.hobbyService = hobbyService; 24 | this.locationService = locationService; 25 | } 26 | 27 | 28 | @Override 29 | public void run(String... args) throws Exception { 30 | this.userService.seedUsersAndUserRoles(); 31 | this.categoryService.initCategories(); 32 | this.locationService.initLocations(); 33 | this.hobbyService.initHobbyOffers(); 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/com/example/hobbie/model/entities/BusinessOwner.java: -------------------------------------------------------------------------------- 1 | package com.example.hobbie.model.entities; 2 | 3 | import javax.persistence.*; 4 | import java.util.List; 5 | 6 | @Entity 7 | @Table(name = "business_owners") 8 | public class BusinessOwner extends UserEntity { 9 | private String businessName; 10 | private String address; 11 | private List hobby_offers; 12 | 13 | public BusinessOwner(String username, String email, List roles, String password, String businessName, String address) { 14 | super(username, email, roles, password); 15 | this.businessName = businessName; 16 | this.address = address; 17 | } 18 | 19 | public BusinessOwner() { 20 | } 21 | 22 | @Column(name = "business_name", nullable = false) 23 | public String getBusinessName() { 24 | return businessName; 25 | } 26 | 27 | public void setBusinessName(String businessName) { 28 | this.businessName = businessName; 29 | } 30 | 31 | @Column(nullable = false) 32 | public String getAddress() { 33 | return address; 34 | } 35 | 36 | public void setAddress(String address) { 37 | this.address = address; 38 | } 39 | 40 | @OneToMany 41 | public List getHobby_offers() { 42 | return hobby_offers; 43 | } 44 | 45 | public void setHobby_offers(List hobby_offers) { 46 | this.hobby_offers = hobby_offers; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/main/resources/templates/home/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
5 | 6 |
7 |
8 |
9 |
10 | 11 | 12 |
13 | 14 |
15 |
16 | 17 |
18 |
19 |

Ready to have fun?

20 |

Find out the best activities for you in your area. Take our personalised test and help us help you discover your new passion.

21 |
22 |
23 | 24 |
25 |
26 |
27 | blueImg 28 | coverImg 29 | 30 |
31 | © Hobbie 2021. All rights reserved. 32 |
33 | 34 | 35 |
36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /src/main/java/com/example/hobbie/service/impl/UserRoleServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.example.hobbie.service.impl; 2 | 3 | import com.example.hobbie.handler.NotFoundException; 4 | import com.example.hobbie.model.entities.UserRoleEntity; 5 | import com.example.hobbie.model.entities.enums.UserRoleEnum; 6 | import com.example.hobbie.model.repostiory.UserRoleRepository; 7 | import com.example.hobbie.service.UserRoleService; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.stereotype.Service; 10 | 11 | import java.util.Optional; 12 | 13 | @Service 14 | public class UserRoleServiceImpl implements UserRoleService { 15 | private final UserRoleRepository userRoleRepository; 16 | 17 | @Autowired 18 | public UserRoleServiceImpl(UserRoleRepository userRoleRepository) { 19 | this.userRoleRepository = userRoleRepository; 20 | } 21 | 22 | @Override 23 | public UserRoleEntity getUserRoleByEnumName(UserRoleEnum userRoleEnum) { 24 | Optional byRole = this.userRoleRepository.findByRole(userRoleEnum); 25 | 26 | if (byRole.isPresent()) { 27 | return byRole.get(); 28 | } else { 29 | throw new NotFoundException("User role not found. Please seed the roles."); 30 | } 31 | } 32 | 33 | @Override 34 | public UserRoleEntity saveRole(UserRoleEntity userRoleEntity) { 35 | return this.userRoleRepository.save(userRoleEntity); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/com/example/hobbie/service/impl/NotificationServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.example.hobbie.service.impl; 2 | 3 | import com.example.hobbie.model.entities.AppClient; 4 | import com.example.hobbie.model.entities.Entry; 5 | import com.example.hobbie.service.NotificationService; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.mail.SimpleMailMessage; 8 | import org.springframework.mail.javamail.JavaMailSender; 9 | import org.springframework.stereotype.Service; 10 | 11 | import java.text.SimpleDateFormat; 12 | import java.util.Calendar; 13 | 14 | @Service 15 | public class NotificationServiceImpl implements NotificationService { 16 | private final JavaMailSender javaMailSender; 17 | 18 | @Autowired 19 | public NotificationServiceImpl(JavaMailSender javaMailSender) { 20 | this.javaMailSender = javaMailSender; 21 | } 22 | 23 | @Override 24 | public void sendNotification(AppClient appClient, Entry entry) { 25 | SimpleMailMessage mail = new SimpleMailMessage(); 26 | String mailBody = "http://localhost:8080/confirm-update-entry/" + entry.getId(); 27 | String date = (new SimpleDateFormat("MM/dd/yyyy").format(Calendar.getInstance().getTime())); 28 | mail.setTo(appClient.getEmail()); 29 | mail.setFrom("findyourhobbie@gmail.com"); 30 | mail.setSubject("New Entry!"); 31 | mail.setText("You made a new entry on: " + date + ". Click the link to confirm your entry: " + mailBody); 32 | 33 | javaMailSender.send(mail); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/com/example/hobbie/view/HobbyCardViewModel.java: -------------------------------------------------------------------------------- 1 | package com.example.hobbie.view; 2 | 3 | import com.example.hobbie.model.entities.enums.CategoryNameEnum; 4 | 5 | import javax.persistence.Transient; 6 | import java.math.BigDecimal; 7 | 8 | public class HobbyCardViewModel { 9 | private Long id; 10 | private String name; 11 | private BigDecimal price; 12 | private String profilePhoto; 13 | private String imgUrl; 14 | 15 | public HobbyCardViewModel() { 16 | } 17 | 18 | public Long getId() { 19 | return id; 20 | } 21 | 22 | public void setId(Long id) { 23 | this.id = id; 24 | } 25 | 26 | public String getName() { 27 | return name; 28 | } 29 | 30 | public void setName(String name) { 31 | this.name = name; 32 | } 33 | 34 | public String getProfilePhoto() { 35 | return profilePhoto; 36 | } 37 | 38 | public void setProfilePhoto(String profilePhoto) { 39 | this.profilePhoto = profilePhoto; 40 | } 41 | 42 | public BigDecimal getPrice() { 43 | return price; 44 | } 45 | 46 | public void setPrice(BigDecimal price) { 47 | this.price = price; 48 | } 49 | 50 | @Transient() 51 | public String getProfilePhotoImagePath() { 52 | if (profilePhoto == null || id == null) return null; 53 | 54 | return "/hobby-photos/" + id + "/" + profilePhoto; 55 | } 56 | 57 | public String getImgUrl() { 58 | return imgUrl; 59 | } 60 | 61 | public void setImgUrl(String imgUrl) { 62 | this.imgUrl = imgUrl; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/main/java/com/example/hobbie/model/service/RegisterBusinessServiceModel.java: -------------------------------------------------------------------------------- 1 | package com.example.hobbie.model.service; 2 | 3 | public class RegisterBusinessServiceModel { 4 | 5 | private String username; 6 | private String businessName; 7 | private String address; 8 | private String email; 9 | private String password; 10 | private String confirmPassword; 11 | 12 | public RegisterBusinessServiceModel() { 13 | } 14 | 15 | public String getUsername() { 16 | return username; 17 | } 18 | 19 | public void setUsername(String username) { 20 | this.username = username; 21 | } 22 | 23 | public String getBusinessName() { 24 | return businessName; 25 | } 26 | 27 | public void setBusinessName(String businessName) { 28 | this.businessName = businessName; 29 | } 30 | 31 | public String getAddress() { 32 | return address; 33 | } 34 | 35 | public void setAddress(String address) { 36 | this.address = address; 37 | } 38 | 39 | public String getEmail() { 40 | return email; 41 | } 42 | 43 | public void setEmail(String email) { 44 | this.email = email; 45 | } 46 | 47 | public String getPassword() { 48 | return password; 49 | } 50 | 51 | public void setPassword(String password) { 52 | this.password = password; 53 | } 54 | 55 | public String getConfirmPassword() { 56 | return confirmPassword; 57 | } 58 | 59 | public void setConfirmPassword(String confirmPassword) { 60 | this.confirmPassword = confirmPassword; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/com/example/hobbie/model/service/SignUpServiceModel.java: -------------------------------------------------------------------------------- 1 | package com.example.hobbie.model.service; 2 | 3 | import com.example.hobbie.model.entities.enums.GenderEnum; 4 | 5 | public class SignUpServiceModel { 6 | private String username; 7 | private String fullName; 8 | private GenderEnum gender; 9 | private String email; 10 | private String password; 11 | private String confirmPassword; 12 | 13 | public SignUpServiceModel() { 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 getFullName() { 25 | return fullName; 26 | } 27 | 28 | public void setFullName(String fullName) { 29 | this.fullName = fullName; 30 | } 31 | 32 | public GenderEnum getGender() { 33 | return gender; 34 | } 35 | 36 | public void setGender(GenderEnum gender) { 37 | this.gender = gender; 38 | } 39 | 40 | public String getEmail() { 41 | return email; 42 | } 43 | 44 | public void setEmail(String email) { 45 | this.email = email; 46 | } 47 | 48 | public String getPassword() { 49 | return password; 50 | } 51 | 52 | public void setPassword(String password) { 53 | this.password = password; 54 | } 55 | 56 | public String getConfirmPassword() { 57 | return confirmPassword; 58 | } 59 | 60 | public void setConfirmPassword(String confirmPassword) { 61 | this.confirmPassword = confirmPassword; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/main/resources/templates/shopping/success.html: -------------------------------------------------------------------------------- 1 | 2 | 4 |
5 | 6 |
7 |
8 |
9 |
10 |
11 | 12 |
13 |

Order completed

14 |
15 |
16 |
17 | 18 |
19 |
20 |
21 |
22 |
23 |
24 | Thank you for your order. 25 |
26 | 27 |
28 |
29 |
30 | 31 |
32 | 33 |
34 | 35 | 36 |
37 |
38 | 41 |
42 |
43 | 44 | blueImg3 45 | blueImg4 46 | blue 47 | 48 | 49 | -------------------------------------------------------------------------------- /src/main/java/com/example/hobbie/service/UserService.java: -------------------------------------------------------------------------------- 1 | package com.example.hobbie.service; 2 | 3 | import com.example.hobbie.model.entities.AppClient; 4 | import com.example.hobbie.model.entities.BusinessOwner; 5 | import com.example.hobbie.model.entities.Hobby; 6 | import com.example.hobbie.model.entities.UserEntity; 7 | import com.example.hobbie.model.service.RegisterBusinessServiceModel; 8 | import com.example.hobbie.model.service.SignUpServiceModel; 9 | 10 | import java.util.List; 11 | 12 | public interface UserService { 13 | List seedUsersAndUserRoles(); 14 | 15 | AppClient register(SignUpServiceModel signUpServiceModel); 16 | 17 | BusinessOwner findCurrentUserBusinessOwner(); 18 | 19 | AppClient findCurrentUserAppClient(); 20 | 21 | String findCurrentUsername(); 22 | 23 | BusinessOwner registerBusiness(RegisterBusinessServiceModel map); 24 | 25 | BusinessOwner saveUpdatedUser(BusinessOwner businessOwner); 26 | 27 | AppClient saveUpdatedUserClient(AppClient appClient); 28 | 29 | UserEntity findUserById(Long userId); 30 | 31 | void deleteUser(Long id); 32 | 33 | BusinessOwner findBusinessOwnerById(Long id); 34 | 35 | UserEntity findUserByUsername(String username); 36 | 37 | boolean userExists(String username, String email); 38 | 39 | void deleteBusinessOwner(Long id); 40 | 41 | void deleteAppClient(Long id); 42 | 43 | AppClient findAppClientById(Long clientId); 44 | 45 | void findAndRemoveHobbyFromClientsRecords(Hobby hobby); 46 | 47 | void expireUserSessions(); 48 | 49 | boolean businessExists(String businessName); 50 | 51 | boolean emailExists(String email); 52 | 53 | boolean businessNameExists(String businessName, Long userId); 54 | } 55 | 56 | 57 | -------------------------------------------------------------------------------- /src/main/java/com/example/hobbie/model/entities/UserEntity.java: -------------------------------------------------------------------------------- 1 | package com.example.hobbie.model.entities; 2 | 3 | import javax.persistence.*; 4 | import java.io.Serializable; 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | 8 | @Entity 9 | @Inheritance(strategy = InheritanceType.JOINED) 10 | @Table(name = "users") 11 | public class UserEntity extends BaseEntity implements Serializable { 12 | 13 | private String username; 14 | private String email; 15 | private List roles = new ArrayList<>(); 16 | private String password; 17 | 18 | public UserEntity(String username, String email, List roles, String password) { 19 | this.username = username; 20 | this.email = email; 21 | this.roles = roles; 22 | this.password = password; 23 | } 24 | 25 | public UserEntity() { 26 | } 27 | 28 | @Column(nullable = false, unique = true) 29 | public String getUsername() { 30 | return username; 31 | } 32 | 33 | public void setUsername(String username) { 34 | this.username = username; 35 | } 36 | 37 | @Column(nullable = false) 38 | public String getPassword() { 39 | return password; 40 | } 41 | 42 | public void setPassword(String password) { 43 | this.password = password; 44 | } 45 | 46 | @Column(nullable = false, unique = true) 47 | public String getEmail() { 48 | return email; 49 | } 50 | 51 | public void setEmail(String email) { 52 | this.email = email; 53 | } 54 | 55 | @ManyToMany(fetch = FetchType.EAGER) 56 | public List getRoles() { 57 | return roles; 58 | } 59 | 60 | public void setRoles(List roles) { 61 | this.roles = roles; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/main/java/com/example/hobbie/service/impl/LocationServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.example.hobbie.service.impl; 2 | 3 | import com.example.hobbie.handler.NotFoundException; 4 | import com.example.hobbie.model.entities.Location; 5 | import com.example.hobbie.model.entities.enums.LocationEnum; 6 | import com.example.hobbie.model.repostiory.LocationRepository; 7 | import com.example.hobbie.service.LocationService; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.stereotype.Service; 10 | 11 | import java.util.ArrayList; 12 | import java.util.Arrays; 13 | import java.util.List; 14 | import java.util.Optional; 15 | 16 | @Service 17 | public class LocationServiceImpl implements LocationService { 18 | private final LocationRepository locationRepository; 19 | 20 | @Autowired 21 | public LocationServiceImpl(LocationRepository locationRepository) { 22 | this.locationRepository = locationRepository; 23 | } 24 | 25 | @Override 26 | public List initLocations() { 27 | List init = new ArrayList<>(); 28 | if (locationRepository.count() == 0) { 29 | Arrays.stream(LocationEnum.values()).forEach(locationEnum -> { 30 | Location location = new Location(locationEnum); 31 | this.locationRepository.save(location); 32 | init.add(location); 33 | }); 34 | } 35 | return init; 36 | } 37 | 38 | @Override 39 | public Location getLocationByName(LocationEnum locationEnum) { 40 | Optional location = this.locationRepository.findByName(locationEnum); 41 | 42 | if (location.isPresent()) { 43 | return location.get(); 44 | } else { 45 | throw new NotFoundException("Location not found"); 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Spring & Thymeleaf project 2 | 3 | * * * * * 4 | 5 | A Spring Web MVC application that renders thymeleaf templates as HTML. Supports integration with Spring Security and provides login logout support. 6 | Uses Spring Data to persist data into the MYSQL db. 7 | 8 | NOTE: Thymeleaf is an HTML template engine that does not support PUT or DELETE HTTP methods for its method attribute. 9 | 10 | Prerequisites 11 | 12 | * * * * * 13 | 14 | - JDK 11 and JAVA_HOME environment variable set 15 | 16 | 17 | 18 | Database 19 | 20 | * * * * * 21 | 22 | Install local mysql server -v 8.0.25, then create a user with credentials (you can use workbench ui) and specify spring.datasource.username and spring.datasource.password in application.properties file. On building the project, the DB should be created automatically 23 | 24 | 25 | Building the project 26 | 27 | * * * * * 28 | 29 | Clone the repository: 30 | 31 |
git clone https://github.com/purshink/Spring-Boot-Thymeleaf-App
32 | Navigate to the newly created folder: 33 | 34 |
cd Spring-Boot-Thymeleaf-App
35 | 36 | Run the project with: 37 | 38 |
./mvnw clean spring-boot:run
39 | 40 | Or on Windows: 41 | 42 |
mvnw.cmd clean spring-boot:run
43 | 44 | Navigate to: 45 | 46 | http://localhost:8080 47 | 48 | Login with: 49 |
user or business,
50 | password:topsecret
51 | 52 | * * * * * 53 | 54 | Spring Mail 55 | 56 | Make sure to specify a valid spring.mail.username and spring.mail.password in the application.properties file in order to be able to send an Email confirmation for updating user entries. 57 | 58 | IMPORTANT: if you decide not to specify mail credentials, you will get javax.mail.AuthenticationFailedException. The rest of the application should work normally despite this exception. 59 | 60 | 61 | -------------------------------------------------------------------------------- /src/main/java/com/example/hobbie/service/impl/CategoryServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.example.hobbie.service.impl; 2 | 3 | import com.example.hobbie.handler.NotFoundException; 4 | import com.example.hobbie.model.entities.Category; 5 | import com.example.hobbie.model.entities.enums.CategoryNameEnum; 6 | import com.example.hobbie.model.repostiory.CategoryRepository; 7 | import com.example.hobbie.service.CategoryService; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.stereotype.Service; 10 | 11 | import java.util.ArrayList; 12 | import java.util.Arrays; 13 | import java.util.List; 14 | import java.util.Optional; 15 | 16 | @Service 17 | public class CategoryServiceImpl implements CategoryService { 18 | private final CategoryRepository categoryRepository; 19 | 20 | @Autowired 21 | public CategoryServiceImpl(CategoryRepository categoryRepository) { 22 | this.categoryRepository = categoryRepository; 23 | } 24 | 25 | @Override 26 | public Category findByName(CategoryNameEnum category) { 27 | Optional byName = this.categoryRepository.findByName(category); 28 | 29 | if (byName.isPresent()) { 30 | return byName.get(); 31 | } else { 32 | throw new NotFoundException("Category with this name not found"); 33 | } 34 | } 35 | 36 | @Override 37 | public List initCategories() { 38 | List init = new ArrayList<>(); 39 | if (categoryRepository.count() == 0) { 40 | Arrays.stream(CategoryNameEnum.values()).forEach(categoryNameEnum -> { 41 | Category category = new Category(categoryNameEnum); 42 | this.categoryRepository.save(category); 43 | init.add(category); 44 | }); 45 | } 46 | return init; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/main/resources/templates/account/account-info.html: -------------------------------------------------------------------------------- 1 | 2 | 4 |
5 | 6 |
7 |
8 |
9 |
10 |
11 |
12 | 13 |
14 | 15 | 33 |
34 | 35 | 36 | 37 | 38 | blueImg 39 | blueImg 40 | blue 41 | 42 |
43 | © Hobbie 2021. All rights reserved. 44 |
45 | 46 | 47 | -------------------------------------------------------------------------------- /src/test/java/com/example/hobbie/service/impl/TestServiceImplTest.java: -------------------------------------------------------------------------------- 1 | package com.example.hobbie.service.impl; 2 | 3 | import com.example.hobbie.model.entities.Hobby; 4 | import com.example.hobbie.model.entities.UserRoleEntity; 5 | import com.example.hobbie.model.entities.enums.CategoryNameEnum; 6 | import com.example.hobbie.model.entities.enums.LocationEnum; 7 | import com.example.hobbie.model.repostiory.TestRepository; 8 | import com.example.hobbie.model.service.TestServiceModel; 9 | import com.example.hobbie.service.TestService; 10 | import org.junit.jupiter.api.Test; 11 | import org.mockito.Mockito; 12 | 13 | import static org.junit.jupiter.api.Assertions.*; 14 | import static org.mockito.Mockito.times; 15 | import static org.mockito.Mockito.when; 16 | 17 | class TestServiceImplTest { 18 | private TestRepository mockTestRepository = Mockito.mock(TestRepository.class); 19 | private TestService mockTestService = Mockito.mock(TestService.class); 20 | @Test 21 | void saveTest() { 22 | 23 | TestServiceModel testServiceModel = new TestServiceModel(); 24 | // testServiceModel.setCategoryFive(CategoryNameEnum.ACTIVE); 25 | // testServiceModel.setCategoryFour(CategoryNameEnum.OTHER); 26 | // testServiceModel.setCategorySeven(CategoryNameEnum.RELAX); 27 | // testServiceModel.setCategoryOne(CategoryNameEnum.FUN); 28 | // testServiceModel.setCategoryTwo(CategoryNameEnum.CREATIVE); 29 | // testServiceModel.setCategoryThree(CategoryNameEnum.INTELLECTUAL); 30 | // testServiceModel.setLocation(LocationEnum.ZURICH); 31 | 32 | when(mockTestRepository.save(Mockito.any( com.example.hobbie.model.entities.Test.class))) 33 | .thenAnswer(i -> i.getArguments()[0]); 34 | mockTestService.saveTest(testServiceModel); 35 | 36 | assertNotNull(mockTestRepository.findById(1L)); 37 | 38 | } 39 | } -------------------------------------------------------------------------------- /src/main/java/com/example/hobbie/security/HobbieUserDetailsService.java: -------------------------------------------------------------------------------- 1 | package com.example.hobbie.security; 2 | 3 | import com.example.hobbie.model.entities.UserEntity; 4 | import com.example.hobbie.model.repostiory.UserRepository; 5 | import org.springframework.security.core.GrantedAuthority; 6 | import org.springframework.security.core.authority.SimpleGrantedAuthority; 7 | import org.springframework.security.core.userdetails.User; 8 | import org.springframework.security.core.userdetails.UserDetails; 9 | import org.springframework.security.core.userdetails.UserDetailsService; 10 | import org.springframework.security.core.userdetails.UsernameNotFoundException; 11 | import org.springframework.stereotype.Component; 12 | 13 | import java.util.List; 14 | import java.util.stream.Collectors; 15 | 16 | @Component 17 | public class HobbieUserDetailsService implements UserDetailsService { 18 | private final UserRepository userRepository; 19 | 20 | public HobbieUserDetailsService(UserRepository userRepository) { 21 | this.userRepository = userRepository; 22 | } 23 | 24 | @Override 25 | public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { 26 | UserEntity userEntity = userRepository.findByUsername(username).orElseThrow( 27 | () -> new UsernameNotFoundException("User with username " + username + " was not found.")); 28 | 29 | return mapToUserDetails(userEntity); 30 | } 31 | 32 | private UserDetails mapToUserDetails(UserEntity userEntity) { 33 | 34 | List authorities = userEntity.getRoles().stream() 35 | .map(ur -> new SimpleGrantedAuthority("ROLE_" + ur.getRole().name())).collect(Collectors.toList()); 36 | return new User( 37 | userEntity.getUsername(), 38 | userEntity.getPassword(), 39 | authorities 40 | ); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/com/example/hobbie/view/HobbyViewModel.java: -------------------------------------------------------------------------------- 1 | package com.example.hobbie.view; 2 | 3 | import com.example.hobbie.model.entities.Category; 4 | import com.example.hobbie.model.entities.enums.CategoryNameEnum; 5 | import com.example.hobbie.model.entities.enums.LocationEnum; 6 | 7 | import java.math.BigDecimal; 8 | 9 | public class HobbyViewModel { 10 | private Long id; 11 | private String name; 12 | private String description; 13 | private String profilePhoto; 14 | private BigDecimal price; 15 | private LocationEnum location; 16 | private String imgUrl; 17 | 18 | public HobbyViewModel() { 19 | } 20 | 21 | public Long getId() { 22 | return id; 23 | } 24 | 25 | public void setId(Long id) { 26 | this.id = id; 27 | } 28 | 29 | public String getName() { 30 | return name; 31 | } 32 | 33 | public void setName(String name) { 34 | this.name = name; 35 | } 36 | 37 | public String getDescription() { 38 | return description; 39 | } 40 | 41 | public void setDescription(String description) { 42 | this.description = description; 43 | } 44 | 45 | public String getProfilePhoto() { 46 | return profilePhoto; 47 | } 48 | 49 | public void setProfilePhoto(String profilePhoto) { 50 | this.profilePhoto = profilePhoto; 51 | } 52 | 53 | public BigDecimal getPrice() { 54 | return price; 55 | } 56 | 57 | public void setPrice(BigDecimal price) { 58 | this.price = price; 59 | } 60 | 61 | public LocationEnum getLocation() { 62 | return location; 63 | } 64 | 65 | public void setLocation(LocationEnum location) { 66 | this.location = location; 67 | } 68 | 69 | public String getImgUrl() { 70 | return imgUrl; 71 | } 72 | 73 | public void setImgUrl(String imgUrl) { 74 | this.imgUrl = imgUrl; 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/main/resources/templates/shopping/shoppingCart.html: -------------------------------------------------------------------------------- 1 | 2 | 4 |
5 | 6 |
7 |
8 |
9 |
10 |
11 |
12 | 13 |
14 | 34 | 35 | 36 |
37 | blueImg 38 | blueImg 39 | blue 40 | 41 |
42 | © Hobbie 2021. All rights reserved. 43 |
44 | 45 | -------------------------------------------------------------------------------- /src/main/resources/templates/home/business_owner.html: -------------------------------------------------------------------------------- 1 | 2 | 4 |
5 | 6 |
7 |
8 |
9 |
10 |
11 | 12 |
13 | 32 |
33 | blueImg 34 | blueImg 35 | blue 36 | 37 |
38 | © Hobbie 2021. All rights reserved. 39 |
40 | 41 | -------------------------------------------------------------------------------- /src/main/resources/templates/abo/my-abos.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 |
6 |
7 |
8 |
9 |
10 |
11 | 12 |
13 |
35 | blueImg 36 | blueImg 37 | blue 38 | 39 |
40 | © Hobbie 2021. All rights reserved. 41 |
42 | 43 | -------------------------------------------------------------------------------- /src/test/java/com/example/hobbie/service/impl/CategoryServiceTest.java: -------------------------------------------------------------------------------- 1 | package com.example.hobbie.service.impl; 2 | 3 | import com.example.hobbie.model.entities.Category; 4 | import com.example.hobbie.model.entities.Location; 5 | import com.example.hobbie.model.entities.enums.CategoryNameEnum; 6 | import com.example.hobbie.model.entities.enums.LocationEnum; 7 | import com.example.hobbie.model.repostiory.CategoryRepository; 8 | import com.example.hobbie.model.repostiory.LocationRepository; 9 | import com.example.hobbie.service.CategoryService; 10 | import com.example.hobbie.service.impl.CategoryServiceImpl; 11 | import com.example.hobbie.service.impl.LocationServiceImpl; 12 | import org.junit.jupiter.api.BeforeEach; 13 | import org.junit.jupiter.api.Test; 14 | import org.mockito.Mockito; 15 | 16 | import java.util.Optional; 17 | 18 | import static org.junit.jupiter.api.Assertions.*; 19 | import static org.mockito.Mockito.mock; 20 | 21 | class CategoryServiceTest { 22 | private CategoryService categoryServiceTest; 23 | private CategoryRepository mockCategoryRepository; 24 | private Category category; 25 | 26 | @BeforeEach 27 | public void setUp() { 28 | mockCategoryRepository = mock(CategoryRepository.class); 29 | categoryServiceTest =new CategoryServiceImpl(mockCategoryRepository); 30 | category = new Category(); 31 | category.setName(CategoryNameEnum.ACTIVE); 32 | } 33 | 34 | @Test 35 | void findByName_should_Work() { 36 | Mockito.when(mockCategoryRepository.findByName(CategoryNameEnum.ACTIVE)). 37 | thenReturn(Optional.of(category)); 38 | Category byName = categoryServiceTest.findByName(CategoryNameEnum.ACTIVE); 39 | 40 | assertEquals(category.getName(),byName.getName()); 41 | } 42 | 43 | @Test 44 | void initCategories_should_Work() { 45 | categoryServiceTest.initCategories(); 46 | assertEquals(7,categoryServiceTest.initCategories().size()); 47 | } 48 | } -------------------------------------------------------------------------------- /src/main/resources/templates/account/business-account-info.html: -------------------------------------------------------------------------------- 1 | 2 | 4 |
5 | 6 |
7 |
8 |
9 |
10 |
11 | 12 | cart 13 | 14 |
15 |
16 |
17 | 18 | 36 |
37 | 38 | 39 | 40 | 41 | blueImg 42 | blueImg 43 | blue 44 | 45 |
46 | © Hobbie 2021. All rights reserved. 47 |
48 | 49 | 50 | -------------------------------------------------------------------------------- /src/main/java/com/example/hobbie/model/service/HobbyServiceModel.java: -------------------------------------------------------------------------------- 1 | package com.example.hobbie.model.service; 2 | 3 | import com.example.hobbie.model.entities.Category; 4 | import com.example.hobbie.model.entities.enums.CategoryNameEnum; 5 | import com.example.hobbie.model.entities.enums.LocationEnum; 6 | import org.springframework.web.multipart.MultipartFile; 7 | 8 | import java.math.BigDecimal; 9 | 10 | public class HobbyServiceModel { 11 | private String name; 12 | private String description; 13 | private CategoryNameEnum category; 14 | private String photos; 15 | private BigDecimal price; 16 | private LocationEnum location; 17 | private MultipartFile img; 18 | 19 | public HobbyServiceModel() { 20 | } 21 | 22 | 23 | public String getName() { 24 | return name; 25 | } 26 | 27 | public void setName(String name) { 28 | this.name = name; 29 | } 30 | 31 | public String getDescription() { 32 | return description; 33 | } 34 | 35 | public void setDescription(String description) { 36 | this.description = description; 37 | } 38 | 39 | public CategoryNameEnum getCategory() { 40 | return category; 41 | } 42 | 43 | public void setCategory(CategoryNameEnum category) { 44 | this.category = category; 45 | } 46 | 47 | public BigDecimal getPrice() { 48 | return price; 49 | } 50 | 51 | public void setPrice(BigDecimal price) { 52 | this.price = price; 53 | } 54 | 55 | public String getPhotos() { 56 | return photos; 57 | } 58 | 59 | public void setPhotos(String photos) { 60 | this.photos = photos; 61 | } 62 | 63 | public LocationEnum getLocation() { 64 | return location; 65 | } 66 | 67 | public void setLocation(LocationEnum location) { 68 | this.location = location; 69 | } 70 | 71 | public MultipartFile getImg() { 72 | return img; 73 | } 74 | 75 | public void setImg(MultipartFile img) { 76 | this.img = img; 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/test/java/com/example/hobbie/web/AboControllerTest.java: -------------------------------------------------------------------------------- 1 | package com.example.hobbie.web; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; 7 | import org.springframework.boot.test.context.SpringBootTest; 8 | import org.springframework.security.test.context.support.WithMockUser; 9 | import org.springframework.test.context.junit4.SpringRunner; 10 | import org.springframework.test.web.servlet.MockMvc; 11 | 12 | import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; 13 | import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; 14 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; 15 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view; 16 | 17 | @RunWith(SpringRunner.class) 18 | @SpringBootTest 19 | @AutoConfigureMockMvc 20 | class AboControllerTest { 21 | private static final String ABO_CONTROLLER_PREFIX = "/my-abos"; 22 | 23 | @Autowired 24 | private MockMvc mockMvc; 25 | 26 | @Test 27 | @WithMockUser(value = "user", roles = {"USER", "ADMIN"}) 28 | public void testShowAllAbosOK() throws Exception { 29 | this.mockMvc.perform(get("/my-abos")). 30 | andExpect(view().name("abo/my-abos")). 31 | andExpect(status().isOk()); 32 | } 33 | 34 | @Test 35 | @WithMockUser(value = "user", roles = {"USER", "ADMIN"}) 36 | public void testShowAboOK() throws Exception { 37 | this.mockMvc. 38 | perform(get("/abo/{id}", 1L)). 39 | andExpect(status().isOk()); 40 | } 41 | 42 | @Test 43 | @WithMockUser(value = "user", roles = {"USER", "ADMIN"}) 44 | void deleteAboThrows() throws Exception { 45 | this.mockMvc. 46 | perform(post("/delete-abo/{id}", 1L)). 47 | andExpect(status().is(403)); 48 | } 49 | } -------------------------------------------------------------------------------- /src/main/resources/META-INF/additional-spring-configuration-metadata.json: -------------------------------------------------------------------------------- 1 | { 2 | "properties": [ 3 | { 4 | "name": "paypal.mode", 5 | "type": "java.lang.String" 6 | }, 7 | { 8 | "name": "paypal.client.id", 9 | "type": "java.lang.String", 10 | "description": "Description for paypal.client.id." 11 | }, 12 | { 13 | "name": "paypal.client.secret", 14 | "type": "java.lang.String", 15 | "description": "Description for paypal.client.secret." 16 | }, 17 | { 18 | "name": "spring.servlet.multipart.cloudinary.api-key", 19 | "type": "java.lang.String", 20 | "description": "Description for spring.servlet.multipart.cloudinary.api-key." 21 | }, 22 | { 23 | "name": "spring.rsocket.server.error.include-message", 24 | "type": "java.lang.String", 25 | "description": "Description for spring.rsocket.server.error.include-message." 26 | }, 27 | { 28 | "name": "spring.rsocket.server.error.include-stacktrace", 29 | "type": "java.lang.String", 30 | "description": "Description for spring.rsocket.server.error.include-stacktrace." 31 | }, 32 | { 33 | "name": "spring.servlet.multipart.cloudinary.cloud-name", 34 | "type": "java.lang.String", 35 | "description": "Description for spring.servlet.multipart.cloudinary.cloud-name." 36 | }, 37 | { 38 | "name": "spring.servlet.multipart.cloudinary.api-secret", 39 | "type": "java.lang.String", 40 | "description": "Description for spring.servlet.multipart.cloudinary.api-secret." 41 | }, 42 | { 43 | "name": "cloudinary.cloud-name", 44 | "type": "java.lang.String", 45 | "description": "Description for cloudinary.cloud-name." 46 | }, 47 | { 48 | "name": "cloudinary.api-key", 49 | "type": "java.lang.String", 50 | "description": "Description for cloudinary.api-key." 51 | }, 52 | { 53 | "name": "cloudinary.api-secret", 54 | "type": "java.lang.String", 55 | "description": "Description for cloudinary.api-secret." 56 | } 57 | ] 58 | } -------------------------------------------------------------------------------- /src/main/java/com/example/hobbie/model/entities/Abo.java: -------------------------------------------------------------------------------- 1 | package com.example.hobbie.model.entities; 2 | 3 | import javax.persistence.*; 4 | import java.math.BigDecimal; 5 | import java.util.List; 6 | 7 | @Entity 8 | @Table(name = "abos") 9 | public class Abo extends BaseEntity { 10 | private Long clientId; 11 | private Long businessOwnerId; 12 | private Long hobbyId; 13 | private List entries; 14 | private BigDecimal aboPrice; 15 | private String name; 16 | private String clientName; 17 | 18 | public Abo() { 19 | } 20 | 21 | @Column 22 | public String getClientName() { 23 | return clientName; 24 | } 25 | 26 | public void setClientName(String clientName) { 27 | this.clientName = clientName; 28 | } 29 | 30 | @Column(nullable = false) 31 | public String getName() { 32 | return name; 33 | } 34 | 35 | public void setName(String name) { 36 | this.name = name; 37 | } 38 | 39 | @OneToMany(cascade = CascadeType.REMOVE) 40 | public List getEntries() { 41 | return entries; 42 | } 43 | 44 | public void setEntries(List entries) { 45 | this.entries = entries; 46 | } 47 | 48 | @Column(nullable = false) 49 | public Long getClientId() { 50 | return clientId; 51 | } 52 | 53 | public void setClientId(Long clientId) { 54 | this.clientId = clientId; 55 | } 56 | 57 | @Column(nullable = false) 58 | public Long getBusinessOwnerId() { 59 | return businessOwnerId; 60 | } 61 | 62 | public void setBusinessOwnerId(Long businessOwnerId) { 63 | this.businessOwnerId = businessOwnerId; 64 | } 65 | 66 | @Column(nullable = false) 67 | public Long getHobbyId() { 68 | return hobbyId; 69 | } 70 | 71 | public void setHobbyId(Long hobbyId) { 72 | this.hobbyId = hobbyId; 73 | } 74 | 75 | @Column 76 | public BigDecimal getAboPrice() { 77 | return aboPrice; 78 | } 79 | 80 | public void setAboPrice(BigDecimal aboPrice) { 81 | this.aboPrice = aboPrice; 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/main/java/com/example/hobbie/model/entities/Hobby.java: -------------------------------------------------------------------------------- 1 | package com.example.hobbie.model.entities; 2 | 3 | import javax.persistence.*; 4 | import java.math.BigDecimal; 5 | 6 | @Entity 7 | @Table(name = "hobbies") 8 | public class Hobby extends BaseEntity { 9 | 10 | private String name; 11 | private String description; 12 | private Category category; 13 | ; 14 | private BusinessOwner businessOwner; 15 | private BigDecimal price; 16 | private Location location; 17 | private String imgUrl; 18 | 19 | public Hobby() { 20 | } 21 | 22 | @Column(name = "image_url") 23 | public String getImgUrl() { 24 | return imgUrl; 25 | } 26 | 27 | public void setImgUrl(String imgUrl) { 28 | this.imgUrl = imgUrl; 29 | } 30 | 31 | @Column(nullable = false) 32 | public String getName() { 33 | return name; 34 | } 35 | 36 | public void setName(String name) { 37 | this.name = name; 38 | } 39 | 40 | @Column(columnDefinition = "TEXT") 41 | public String getDescription() { 42 | return description; 43 | } 44 | 45 | public void setDescription(String description) { 46 | this.description = description; 47 | } 48 | 49 | @ManyToOne(fetch = FetchType.EAGER) 50 | public Category getCategory() { 51 | return category; 52 | } 53 | 54 | public void setCategory(Category category) { 55 | this.category = category; 56 | } 57 | 58 | @Column(nullable = false) 59 | public BigDecimal getPrice() { 60 | return price; 61 | } 62 | 63 | public void setPrice(BigDecimal price) { 64 | this.price = price; 65 | } 66 | 67 | @ManyToOne(fetch = FetchType.EAGER) 68 | public BusinessOwner getBusinessOwner() { 69 | return businessOwner; 70 | } 71 | 72 | public void setBusinessOwner(BusinessOwner businessOwner) { 73 | this.businessOwner = businessOwner; 74 | } 75 | 76 | @ManyToOne 77 | public Location getLocation() { 78 | return location; 79 | } 80 | 81 | public void setLocation(Location location) { 82 | this.location = location; 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/main/java/com/example/hobbie/model/binding/SignUpBindingModel.java: -------------------------------------------------------------------------------- 1 | package com.example.hobbie.model.binding; 2 | 3 | import com.example.hobbie.model.entities.enums.GenderEnum; 4 | import com.sun.istack.NotNull; 5 | 6 | import javax.validation.constraints.Pattern; 7 | import javax.validation.constraints.Size; 8 | 9 | public class SignUpBindingModel { 10 | 11 | private String username; 12 | private String fullName; 13 | private GenderEnum gender; 14 | private String email; 15 | private String password; 16 | private String confirmPassword; 17 | 18 | public SignUpBindingModel() { 19 | } 20 | 21 | @Size(min = 3, max = 20, message = " must be between 3 and 20 symbols.") 22 | public String getUsername() { 23 | return username; 24 | } 25 | 26 | public void setUsername(String username) { 27 | this.username = username; 28 | } 29 | 30 | @Size(min = 3, max = 20, message = " must be between 3 and 20 symbols.") 31 | public String getFullName() { 32 | return fullName; 33 | } 34 | 35 | public void setFullName(String fullName) { 36 | this.fullName = fullName; 37 | } 38 | 39 | @NotNull 40 | public GenderEnum getGender() { 41 | return gender; 42 | } 43 | 44 | public void setGender(GenderEnum gender) { 45 | this.gender = gender; 46 | } 47 | 48 | @NotNull 49 | @Pattern(regexp = ".+@.+\\..+", message = " must be valid.") 50 | public String getEmail() { 51 | return email; 52 | } 53 | 54 | public void setEmail(String email) { 55 | this.email = email; 56 | } 57 | 58 | @Size(min = 3, max = 20, message = " must be between 3 and 20 symbols.") 59 | public String getPassword() { 60 | return password; 61 | } 62 | 63 | public void setPassword(String password) { 64 | this.password = password; 65 | } 66 | 67 | @Size(min = 3, max = 20, message = " must be between 3 and 20 symbols.") 68 | public String getConfirmPassword() { 69 | return confirmPassword; 70 | } 71 | 72 | public void setConfirmPassword(String confirmPassword) { 73 | this.confirmPassword = confirmPassword; 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/main/java/com/example/hobbie/model/service/UpdateHobbyServiceModel.java: -------------------------------------------------------------------------------- 1 | package com.example.hobbie.model.service; 2 | 3 | import com.example.hobbie.model.entities.enums.CategoryNameEnum; 4 | import com.example.hobbie.model.entities.enums.LocationEnum; 5 | import org.springframework.web.multipart.MultipartFile; 6 | 7 | import java.math.BigDecimal; 8 | 9 | public class UpdateHobbyServiceModel { 10 | private Long id; 11 | private String name; 12 | private String description; 13 | private CategoryNameEnum category; 14 | private String photos; 15 | private BigDecimal price; 16 | private LocationEnum location; 17 | private MultipartFile img; 18 | 19 | 20 | public UpdateHobbyServiceModel() { 21 | } 22 | 23 | 24 | public String getName() { 25 | return name; 26 | } 27 | 28 | public void setName(String name) { 29 | this.name = name; 30 | } 31 | 32 | public String getDescription() { 33 | return description; 34 | } 35 | 36 | public void setDescription(String description) { 37 | this.description = description; 38 | } 39 | 40 | public CategoryNameEnum getCategory() { 41 | return category; 42 | } 43 | 44 | public void setCategory(CategoryNameEnum category) { 45 | this.category = category; 46 | } 47 | 48 | public BigDecimal getPrice() { 49 | return price; 50 | } 51 | 52 | public void setPrice(BigDecimal price) { 53 | this.price = price; 54 | } 55 | 56 | public String getPhotos() { 57 | return photos; 58 | } 59 | 60 | public void setPhotos(String photos) { 61 | this.photos = photos; 62 | } 63 | 64 | public Long getId() { 65 | return id; 66 | } 67 | 68 | public void setId(Long id) { 69 | this.id = id; 70 | } 71 | 72 | public LocationEnum getLocation() { 73 | return location; 74 | } 75 | 76 | public void setLocation(LocationEnum location) { 77 | this.location = location; 78 | } 79 | 80 | public MultipartFile getImg() { 81 | return img; 82 | } 83 | 84 | public void setImg(MultipartFile img) { 85 | this.img = img; 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/main/java/com/example/hobbie/model/binding/UpdateClientBindingModel.java: -------------------------------------------------------------------------------- 1 | package com.example.hobbie.model.binding; 2 | 3 | import com.example.hobbie.model.entities.enums.GenderEnum; 4 | import com.sun.istack.NotNull; 5 | 6 | import javax.validation.constraints.Pattern; 7 | import javax.validation.constraints.Size; 8 | 9 | public class UpdateClientBindingModel { 10 | 11 | private String username; 12 | private String fullName; 13 | private GenderEnum gender; 14 | private String email; 15 | private String password; 16 | private String confirmPassword; 17 | 18 | public UpdateClientBindingModel() { 19 | } 20 | 21 | @Size(min = 3, max = 20, message = " must be between 3 and 20 symbols.") 22 | public String getUsername() { 23 | return username; 24 | } 25 | 26 | public void setUsername(String username) { 27 | this.username = username; 28 | } 29 | 30 | @Size(min = 3, max = 20, message = " must be between 3 and 20 symbols.") 31 | public String getFullName() { 32 | return fullName; 33 | } 34 | 35 | public void setFullName(String fullName) { 36 | this.fullName = fullName; 37 | } 38 | 39 | @NotNull 40 | public GenderEnum getGender() { 41 | return gender; 42 | } 43 | 44 | public void setGender(GenderEnum gender) { 45 | this.gender = gender; 46 | } 47 | 48 | @NotNull 49 | @Pattern(regexp = ".+@.+\\..+", message = " must be valid.") 50 | public String getEmail() { 51 | return email; 52 | } 53 | 54 | public void setEmail(String email) { 55 | this.email = email; 56 | } 57 | 58 | @Size(min = 3, max = 20, message = " must be between 3 and 20 symbols.") 59 | public String getPassword() { 60 | return password; 61 | } 62 | 63 | public void setPassword(String password) { 64 | this.password = password; 65 | } 66 | 67 | @Size(min = 3, max = 20, message = " must be between 3 and 20 symbols.") 68 | public String getConfirmPassword() { 69 | return confirmPassword; 70 | } 71 | 72 | public void setConfirmPassword(String confirmPassword) { 73 | this.confirmPassword = confirmPassword; 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/main/java/com/example/hobbie/model/binding/RegisterBusinessBindingModel.java: -------------------------------------------------------------------------------- 1 | package com.example.hobbie.model.binding; 2 | 3 | import com.sun.istack.NotNull; 4 | 5 | import javax.validation.constraints.Pattern; 6 | import javax.validation.constraints.Size; 7 | 8 | public class RegisterBusinessBindingModel { 9 | private String username; 10 | private String businessName; 11 | private String address; 12 | private String email; 13 | private String password; 14 | private String confirmPassword; 15 | 16 | public RegisterBusinessBindingModel() { 17 | } 18 | 19 | @Size(min = 3, max = 20, message = " must be between 3 and 20 symbols") 20 | public String getUsername() { 21 | return username; 22 | } 23 | 24 | public void setUsername(String username) { 25 | this.username = username; 26 | } 27 | 28 | @Size(min = 2, max = 30, message = " must be between 2 and 30 symbols") 29 | public String getBusinessName() { 30 | return businessName; 31 | } 32 | 33 | public void setBusinessName(String businessName) { 34 | this.businessName = businessName; 35 | } 36 | 37 | @Size(min = 3, max = 30, message = " must be between 3 and 30 symbols") 38 | public String getAddress() { 39 | return address; 40 | } 41 | 42 | public void setAddress(String address) { 43 | this.address = address; 44 | } 45 | 46 | @NotNull 47 | @Pattern(regexp = ".+@.+\\..+", message = " must be valid") 48 | public String getEmail() { 49 | return email; 50 | } 51 | 52 | public void setEmail(String email) { 53 | this.email = email; 54 | } 55 | 56 | @Size(min = 3, max = 20, message = " must be between 3 and 20 symbols") 57 | public String getPassword() { 58 | return password; 59 | } 60 | 61 | public void setPassword(String password) { 62 | this.password = password; 63 | } 64 | 65 | @Size(min = 3, max = 20, message = " must be between 3 and 20 symbols") 66 | public String getConfirmPassword() { 67 | return confirmPassword; 68 | } 69 | 70 | public void setConfirmPassword(String confirmPassword) { 71 | this.confirmPassword = confirmPassword; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/main/java/com/example/hobbie/model/binding/UpdateBusinessBindingModel.java: -------------------------------------------------------------------------------- 1 | package com.example.hobbie.model.binding; 2 | 3 | import com.sun.istack.NotNull; 4 | 5 | import javax.validation.constraints.Pattern; 6 | import javax.validation.constraints.Size; 7 | 8 | public class UpdateBusinessBindingModel { 9 | 10 | private String username; 11 | private String businessName; 12 | private String address; 13 | private String email; 14 | private String password; 15 | private String confirmPassword; 16 | 17 | public UpdateBusinessBindingModel() { 18 | } 19 | 20 | @Size(min = 3, max = 20, message = " must be between 3 and 20 symbols") 21 | public String getUsername() { 22 | return username; 23 | } 24 | 25 | public void setUsername(String username) { 26 | this.username = username; 27 | } 28 | 29 | @Size(min = 2, max = 30, message = " must be between 2 and 30 symbols") 30 | public String getBusinessName() { 31 | return businessName; 32 | } 33 | 34 | public void setBusinessName(String businessName) { 35 | this.businessName = businessName; 36 | } 37 | 38 | @Size(min = 3, max = 30, message = " must be between 3 and 30 symbols") 39 | public String getAddress() { 40 | return address; 41 | } 42 | 43 | public void setAddress(String address) { 44 | this.address = address; 45 | } 46 | 47 | @NotNull 48 | @Pattern(regexp = ".+@.+\\..+", message = " must be valid") 49 | public String getEmail() { 50 | return email; 51 | } 52 | 53 | public void setEmail(String email) { 54 | this.email = email; 55 | } 56 | 57 | @Size(min = 3, max = 20, message = " must be between 3 and 20 symbols") 58 | public String getPassword() { 59 | return password; 60 | } 61 | 62 | public void setPassword(String password) { 63 | this.password = password; 64 | } 65 | 66 | @Size(min = 3, max = 20, message = " must be between 3 and 20 symbols") 67 | public String getConfirmPassword() { 68 | return confirmPassword; 69 | } 70 | 71 | public void setConfirmPassword(String confirmPassword) { 72 | this.confirmPassword = confirmPassword; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/main/java/com/example/hobbie/web/ShoppingCartController.java: -------------------------------------------------------------------------------- 1 | package com.example.hobbie.web; 2 | 3 | import com.example.hobbie.model.entities.Hobby; 4 | import com.example.hobbie.service.AboService; 5 | import com.example.hobbie.service.HobbyService; 6 | import com.example.hobbie.service.ShoppingCartService; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.stereotype.Controller; 9 | import org.springframework.web.bind.annotation.*; 10 | import org.springframework.web.servlet.ModelAndView; 11 | 12 | @Controller 13 | public class ShoppingCartController { 14 | private final ShoppingCartService shoppingCartService; 15 | private final HobbyService hobbyService; 16 | private final AboService aboService; 17 | 18 | 19 | @Autowired 20 | public ShoppingCartController(ShoppingCartService shoppingCartService, HobbyService hobbyService, AboService aboService) { 21 | this.shoppingCartService = shoppingCartService; 22 | this.hobbyService = hobbyService; 23 | this.aboService = aboService; 24 | } 25 | 26 | @GetMapping("/shoppingCart") 27 | public ModelAndView shoppingCart() { 28 | ModelAndView modelAndView = new ModelAndView("shopping/shoppingCart"); 29 | modelAndView.addObject("abos", shoppingCartService.getAbosInCart()); 30 | modelAndView.addObject("total", shoppingCartService.getTotal().toString()); 31 | return modelAndView; 32 | } 33 | 34 | @GetMapping("/shoppingCart/addProduct/{hobbyId}") 35 | public ModelAndView addProductToCart(@PathVariable("hobbyId") Long hobbyId) { 36 | Hobby hobbieById = this.hobbyService.findHobbieById(hobbyId); 37 | this.shoppingCartService.addAboToCart(hobbieById); 38 | return shoppingCart(); 39 | } 40 | 41 | @GetMapping("/shoppingCart/removeProduct/{hobbyId}") 42 | public ModelAndView removeProductFromCart(@PathVariable("hobbyId") Long hobbyId) { 43 | this.shoppingCartService.removeProductFromCart(hobbyId); 44 | return shoppingCart(); 45 | } 46 | 47 | @GetMapping("/shoppingCart/checkout") 48 | public String checkout() { 49 | shoppingCartService.checkout(); 50 | 51 | return "shopping/success"; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/test/java/com/example/hobbie/service/impl/LocationServiceImplTest.java: -------------------------------------------------------------------------------- 1 | package com.example.hobbie.service.impl; 2 | 3 | import com.example.hobbie.handler.NotFoundException; 4 | import com.example.hobbie.model.entities.Location; 5 | import com.example.hobbie.model.entities.UserRoleEntity; 6 | import com.example.hobbie.model.entities.enums.LocationEnum; 7 | import com.example.hobbie.model.entities.enums.UserRoleEnum; 8 | import com.example.hobbie.model.repostiory.LocationRepository; 9 | import com.example.hobbie.service.LocationService; 10 | import org.junit.jupiter.api.Assertions; 11 | import org.junit.jupiter.api.BeforeEach; 12 | import org.junit.jupiter.api.Test; 13 | import org.mockito.Mockito; 14 | 15 | import java.util.Optional; 16 | 17 | import static org.junit.jupiter.api.Assertions.assertEquals; 18 | import static org.mockito.ArgumentMatchers.any; 19 | import static org.mockito.Mockito.mock; 20 | import static org.mockito.Mockito.when; 21 | 22 | class LocationServiceImplTest { 23 | private LocationRepository mockLocationRepository; 24 | private LocationService locationServiceToTest; 25 | private Location location; 26 | 27 | @BeforeEach 28 | public void setUp() { 29 | mockLocationRepository = mock(LocationRepository.class); 30 | locationServiceToTest =new LocationServiceImpl(mockLocationRepository); 31 | location = new Location(); 32 | location.setName(LocationEnum.ZURICH); 33 | 34 | 35 | 36 | } 37 | 38 | @Test 39 | void getLocationByName_should_work() { 40 | 41 | Mockito.when(mockLocationRepository.findByName(LocationEnum.ZURICH)). 42 | thenReturn(Optional.of(location)); 43 | Location locationByName = locationServiceToTest.getLocationByName(LocationEnum.ZURICH); 44 | 45 | assertEquals(location.getName(),locationByName.getName()); 46 | } 47 | @Test 48 | void testUserNotFound() { 49 | 50 | Assertions.assertThrows( 51 | NotFoundException.class, 52 | () -> locationServiceToTest.getLocationByName(LocationEnum.ZURICH)); 53 | } 54 | 55 | // 56 | @Test 57 | void initLocations_should_work() { 58 | 59 | locationServiceToTest.initLocations(); 60 | assertEquals(2, locationServiceToTest.initLocations().size()); 61 | } 62 | } -------------------------------------------------------------------------------- /src/main/java/com/example/hobbie/model/entities/AppClient.java: -------------------------------------------------------------------------------- 1 | package com.example.hobbie.model.entities; 2 | 3 | import com.example.hobbie.model.entities.enums.GenderEnum; 4 | import org.hibernate.annotations.LazyCollection; 5 | import org.hibernate.annotations.LazyCollectionOption; 6 | 7 | import javax.persistence.*; 8 | import java.io.Serializable; 9 | import java.util.List; 10 | 11 | @Entity 12 | @Table(name = "app_clients") 13 | public class AppClient extends UserEntity implements Serializable { 14 | private String fullName; 15 | private GenderEnum gender; 16 | private Test testResults; 17 | private List hobby_matches; 18 | private List saved_hobbies; 19 | 20 | 21 | public AppClient() { 22 | } 23 | 24 | public AppClient(String username, String email, List roles, String password, String fullName, GenderEnum gender) { 25 | super(username, email, roles, password); 26 | this.fullName = fullName; 27 | this.gender = gender; 28 | } 29 | 30 | @Column(name = "full_name", nullable = false) 31 | public String getFullName() { 32 | return fullName; 33 | } 34 | 35 | public void setFullName(String fullName) { 36 | this.fullName = fullName; 37 | } 38 | 39 | @Column(nullable = false) 40 | @Enumerated(EnumType.STRING) 41 | public GenderEnum getGender() { 42 | return gender; 43 | } 44 | 45 | public void setGender(GenderEnum gender) { 46 | this.gender = gender; 47 | } 48 | 49 | @ManyToMany 50 | public List getHobby_matches() { 51 | return hobby_matches; 52 | } 53 | 54 | public void setHobby_matches(List hobby_matches) { 55 | this.hobby_matches = hobby_matches; 56 | } 57 | 58 | @OneToOne(cascade = CascadeType.REMOVE) 59 | public Test getTestResults() { 60 | return testResults; 61 | } 62 | 63 | public void setTestResults(Test testResults) { 64 | this.testResults = testResults; 65 | } 66 | 67 | @OneToMany 68 | @LazyCollection(LazyCollectionOption.FALSE) 69 | public List getSaved_hobbies() { 70 | return saved_hobbies; 71 | } 72 | 73 | public void setSaved_hobbies(List saved_hobbies) { 74 | this.saved_hobbies = saved_hobbies; 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/main/java/com/example/hobbie/service/impl/TestServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.example.hobbie.service.impl; 2 | 3 | import com.example.hobbie.model.entities.AppClient; 4 | import com.example.hobbie.model.entities.Hobby; 5 | import com.example.hobbie.model.entities.Test; 6 | import com.example.hobbie.model.repostiory.TestRepository; 7 | import com.example.hobbie.model.service.TestServiceModel; 8 | import com.example.hobbie.service.HobbyService; 9 | import com.example.hobbie.service.TestService; 10 | import com.example.hobbie.service.UserService; 11 | import org.modelmapper.ModelMapper; 12 | import org.springframework.beans.factory.annotation.Autowired; 13 | import org.springframework.stereotype.Service; 14 | import org.springframework.transaction.annotation.Transactional; 15 | 16 | import java.util.List; 17 | 18 | @Service 19 | @Transactional 20 | public class TestServiceImpl implements TestService { 21 | private final TestRepository testRepository; 22 | private final ModelMapper modelMapper; 23 | private final UserService userService; 24 | private final HobbyService hobbyService; 25 | 26 | @Autowired 27 | public TestServiceImpl(TestRepository testRepository, ModelMapper modelMapper, UserService userService, HobbyService hobbyService) { 28 | this.testRepository = testRepository; 29 | this.modelMapper = modelMapper; 30 | this.userService = userService; 31 | this.hobbyService = hobbyService; 32 | } 33 | 34 | @Override 35 | public void saveTest(TestServiceModel testServiceModel) { 36 | Test test = this.modelMapper.map(testServiceModel, Test.class); 37 | AppClient currentUserAppClient = this.userService.findCurrentUserAppClient(); 38 | test.setAppClient(currentUserAppClient); 39 | test.setLocation((testServiceModel.getLocation())); 40 | if (currentUserAppClient.getTestResults() != null) { 41 | test.setId(currentUserAppClient.getTestResults().getId()); 42 | } 43 | this.testRepository.save(test); 44 | currentUserAppClient.setTestResults(test); 45 | List hobbyMatches = this.hobbyService.findHobbyMatches(currentUserAppClient); 46 | currentUserAppClient.setHobby_matches(hobbyMatches); 47 | this.userService.saveUpdatedUserClient(currentUserAppClient); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/resources/templates/login/login.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 |
6 | 7 | 8 | 9 |
10 |
11 | logo 12 | 13 |
14 | 15 |
16 |
17 |
18 |
19 | 20 |
21 | 22 |
23 |

Login

24 |
LOGIN_PAGE_IDENTIFIER
25 | 56 |
57 | 58 |
59 | © Hobbie 2021. All rights reserved. 60 |
61 | 62 | blueImg 63 | 64 | -------------------------------------------------------------------------------- /src/main/java/com/example/hobbie/model/binding/HobbyBindingModel.java: -------------------------------------------------------------------------------- 1 | package com.example.hobbie.model.binding; 2 | 3 | import com.example.hobbie.model.entities.enums.CategoryNameEnum; 4 | import com.example.hobbie.model.entities.enums.LocationEnum; 5 | import org.springframework.web.multipart.MultipartFile; 6 | 7 | import javax.validation.constraints.NotNull; 8 | import javax.validation.constraints.Size; 9 | import java.math.BigDecimal; 10 | 11 | public class HobbyBindingModel { 12 | private String name; 13 | private String description; 14 | private CategoryNameEnum category; 15 | private BigDecimal price; 16 | private LocationEnum location; 17 | private MultipartFile img; 18 | 19 | public HobbyBindingModel() { 20 | } 21 | 22 | @Size(min = 3, max = 20, message = "Name must be between 3 and 20 symbols.") 23 | @NotNull(message = "Hobby name can not be empty.") 24 | public String getName() { 25 | return name; 26 | } 27 | 28 | public void setName(String name) { 29 | this.name = name; 30 | } 31 | 32 | @Size(min = 30, max = 1050, message = "Description must be between 30 and 1050 symbols") 33 | @NotNull(message = "You need to have a description") 34 | public String getDescription() { 35 | return description; 36 | } 37 | 38 | public void setDescription(String description) { 39 | this.description = description; 40 | } 41 | 42 | @NotNull(message = "You have to choose category") 43 | public CategoryNameEnum getCategory() { 44 | return category; 45 | } 46 | 47 | public void setCategory(CategoryNameEnum category) { 48 | this.category = category; 49 | } 50 | 51 | @NotNull(message = "You have to set price") 52 | public BigDecimal getPrice() { 53 | return price; 54 | } 55 | 56 | public void setPrice(BigDecimal price) { 57 | this.price = price; 58 | } 59 | 60 | @NotNull(message = "You have to choose a location") 61 | public LocationEnum getLocation() { 62 | return location; 63 | } 64 | 65 | public void setLocation(LocationEnum location) { 66 | this.location = location; 67 | } 68 | 69 | @NotNull(message = "You have to choose profile picture") 70 | public MultipartFile getImg() { 71 | return img; 72 | } 73 | 74 | public void setImg(MultipartFile img) { 75 | this.img = img; 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/main/java/com/example/hobbie/web/TestController.java: -------------------------------------------------------------------------------- 1 | package com.example.hobbie.web; 2 | 3 | import com.example.hobbie.config.UserInterceptor; 4 | import com.example.hobbie.model.binding.TestBindingModel; 5 | import com.example.hobbie.model.service.TestServiceModel; 6 | import com.example.hobbie.service.TestService; 7 | import org.modelmapper.ModelMapper; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.stereotype.Controller; 10 | import org.springframework.ui.Model; 11 | import org.springframework.validation.BindingResult; 12 | import org.springframework.web.bind.annotation.GetMapping; 13 | import org.springframework.web.bind.annotation.PostMapping; 14 | import org.springframework.web.servlet.mvc.support.RedirectAttributes; 15 | 16 | import javax.validation.Valid; 17 | 18 | @Controller 19 | public class TestController { 20 | private final TestService testService; 21 | private final ModelMapper modelMapper; 22 | 23 | @Autowired 24 | public TestController(TestService testService, ModelMapper modelMapper) { 25 | this.testService = testService; 26 | this.modelMapper = modelMapper; 27 | } 28 | 29 | @GetMapping("/test") 30 | public String showTest(Model model) { 31 | if (UserInterceptor.isUserLogged()) { 32 | if (!model.containsAttribute("testBindingModel")) { 33 | model.addAttribute("testBindingModel", new TestBindingModel()); 34 | } 35 | return "test/test"; 36 | } else { 37 | return "home/index"; 38 | } 39 | } 40 | 41 | @PostMapping("/test") 42 | public String saveTestResults(@Valid TestBindingModel testBindingModel, BindingResult bindingResult, RedirectAttributes redirectAttributes) { 43 | if (UserInterceptor.isUserLogged()) { 44 | if (bindingResult.hasErrors()) { 45 | redirectAttributes.addFlashAttribute("testBindingModel", testBindingModel); 46 | redirectAttributes.addFlashAttribute("org.springframework.validation.BindingResult.testBindingModel", bindingResult); 47 | return "redirect:/test"; 48 | } else { 49 | this.testService.saveTest(this.modelMapper.map(testBindingModel, TestServiceModel.class)); 50 | 51 | return "redirect:/"; 52 | } 53 | } else { 54 | return "home/index"; 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/main/java/com/example/hobbie/model/service/TestServiceModel.java: -------------------------------------------------------------------------------- 1 | package com.example.hobbie.model.service; 2 | 3 | import com.example.hobbie.model.entities.enums.CategoryNameEnum; 4 | import com.example.hobbie.model.entities.enums.LocationEnum; 5 | 6 | public class TestServiceModel { 7 | private CategoryNameEnum categoryOne; 8 | private CategoryNameEnum categoryTwo; 9 | private CategoryNameEnum categoryThree; 10 | private CategoryNameEnum categoryFour; 11 | private CategoryNameEnum categoryFive; 12 | private CategoryNameEnum categorySix; 13 | private CategoryNameEnum categorySeven; 14 | private LocationEnum location; 15 | 16 | public TestServiceModel() { 17 | } 18 | 19 | public CategoryNameEnum getCategoryOne() { 20 | return categoryOne; 21 | } 22 | 23 | public void setCategoryOne(CategoryNameEnum categoryOne) { 24 | this.categoryOne = categoryOne; 25 | } 26 | 27 | public CategoryNameEnum getCategoryTwo() { 28 | return categoryTwo; 29 | } 30 | 31 | public void setCategoryTwo(CategoryNameEnum categoryTwo) { 32 | this.categoryTwo = categoryTwo; 33 | } 34 | 35 | public CategoryNameEnum getCategoryThree() { 36 | return categoryThree; 37 | } 38 | 39 | public void setCategoryThree(CategoryNameEnum categoryThree) { 40 | this.categoryThree = categoryThree; 41 | } 42 | 43 | public CategoryNameEnum getCategoryFour() { 44 | return categoryFour; 45 | } 46 | 47 | public void setCategoryFour(CategoryNameEnum categoryFour) { 48 | this.categoryFour = categoryFour; 49 | } 50 | 51 | public CategoryNameEnum getCategoryFive() { 52 | return categoryFive; 53 | } 54 | 55 | public void setCategoryFive(CategoryNameEnum categoryFive) { 56 | this.categoryFive = categoryFive; 57 | } 58 | 59 | public CategoryNameEnum getCategorySix() { 60 | return categorySix; 61 | } 62 | 63 | public void setCategorySix(CategoryNameEnum categorySix) { 64 | this.categorySix = categorySix; 65 | } 66 | 67 | public CategoryNameEnum getCategorySeven() { 68 | return categorySeven; 69 | } 70 | 71 | public void setCategorySeven(CategoryNameEnum categorySeven) { 72 | this.categorySeven = categorySeven; 73 | } 74 | 75 | public LocationEnum getLocation() { 76 | return location; 77 | } 78 | 79 | public void setLocation(LocationEnum location) { 80 | this.location = location; 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/main/resources/templates/home/user_home.html: -------------------------------------------------------------------------------- 1 | 2 | 4 |
5 | 6 |
7 |
8 |
9 |
10 |
11 | 12 |
13 |

Your hobbies

14 |
15 |
16 |
17 | We're sorry but no matches for you have been found. 18 |
19 |
20 |
21 |
22 |
23 |
24 | Please take the test to find out the best hobbies for you in your aria: 25 |
26 | 27 |
28 |
29 |
30 | 31 |
32 | 33 |
34 | 35 |
36 | 37 | 38 |
39 | 40 | 41 |
42 | Hobby picture 43 |
44 | 45 |
46 |

47 | Hiking 48 |

49 |
50 |

Find out more...

51 |

500 CHF

52 |
53 |
54 |
55 |
56 |
57 | 58 |
59 | © Hobbie 2021. All rights reserved. 60 |
61 | 62 | blueImg3 63 | blueImg4 64 | blue 65 | 66 | 67 | -------------------------------------------------------------------------------- /src/test/java/com/example/hobbie/web/TestControllerTest.java: -------------------------------------------------------------------------------- 1 | package com.example.hobbie.web; 2 | 3 | import com.example.hobbie.model.entities.enums.CategoryNameEnum; 4 | import com.example.hobbie.model.entities.enums.LocationEnum; 5 | import org.junit.jupiter.api.Test; 6 | import org.junit.runner.RunWith; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; 9 | import org.springframework.boot.test.context.SpringBootTest; 10 | import org.springframework.security.test.context.support.WithMockUser; 11 | import org.springframework.test.context.junit4.SpringRunner; 12 | import org.springframework.test.web.servlet.MockMvc; 13 | import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; 14 | 15 | import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; 16 | import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; 17 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; 18 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view; 19 | 20 | @RunWith(SpringRunner.class) 21 | @SpringBootTest 22 | @AutoConfigureMockMvc 23 | class TestControllerTest { 24 | @Autowired 25 | private MockMvc mockMvc; 26 | 27 | @Test 28 | @WithMockUser(value = "user", roles = {"USER", "ADMIN"}) 29 | void showTest_should_work() throws Exception { 30 | this.mockMvc.perform(get("/test")). 31 | andExpect(view().name("test/test")). 32 | andExpect(status().isOk()); 33 | } 34 | 35 | @Test 36 | @WithMockUser(value = "user", roles = {"USER", "ADMIN"}) 37 | void saveTestResults_should_work() throws Exception { 38 | mockMvc.perform(MockMvcRequestBuilders.post("/test") 39 | .param("categoryOne", CategoryNameEnum.CREATIVE.name()) 40 | .param("categoryTwo", CategoryNameEnum.CREATIVE.name()) 41 | .param("categoryThree", CategoryNameEnum.CREATIVE.name()) 42 | .param("categoryFour", CategoryNameEnum.CREATIVE.name()) 43 | .param("categoryFive", CategoryNameEnum.CREATIVE.name()) 44 | .param("categorySix", CategoryNameEnum.CREATIVE.name()) 45 | .param("categorySeven", CategoryNameEnum.CREATIVE.name()) 46 | .param("location", LocationEnum.ZURICH.name()) 47 | .with(csrf())). 48 | andExpect(status().is3xxRedirection()); 49 | } 50 | } -------------------------------------------------------------------------------- /src/main/java/com/example/hobbie/model/binding/UpdateHobbyBindingModel.java: -------------------------------------------------------------------------------- 1 | package com.example.hobbie.model.binding; 2 | 3 | import com.example.hobbie.model.entities.enums.CategoryNameEnum; 4 | import com.example.hobbie.model.entities.enums.LocationEnum; 5 | import org.springframework.web.multipart.MultipartFile; 6 | 7 | import javax.validation.constraints.NotNull; 8 | import javax.validation.constraints.Size; 9 | import java.math.BigDecimal; 10 | 11 | public class UpdateHobbyBindingModel { 12 | private Long id; 13 | private String name; 14 | private String description; 15 | private CategoryNameEnum category; 16 | private BigDecimal price; 17 | private LocationEnum location; 18 | private MultipartFile img; 19 | 20 | public UpdateHobbyBindingModel() { 21 | } 22 | 23 | @Size(min = 3, max = 20, message = "Name must be between 3 and 20 symbols.") 24 | @NotNull(message = "Hobby name can not be empty.") 25 | public String getName() { 26 | return name; 27 | } 28 | 29 | public void setName(String name) { 30 | this.name = name; 31 | } 32 | 33 | @Size(min = 30, max = 1050, message = "Description must be between 30 and 1050 symbols") 34 | @NotNull(message = "You need to have a description") 35 | public String getDescription() { 36 | return description; 37 | } 38 | 39 | public void setDescription(String description) { 40 | this.description = description; 41 | } 42 | 43 | 44 | @NotNull(message = "You have to choose category") 45 | public CategoryNameEnum getCategory() { 46 | return category; 47 | } 48 | 49 | public void setCategory(CategoryNameEnum category) { 50 | this.category = category; 51 | } 52 | 53 | @NotNull(message = "You have to set price") 54 | public BigDecimal getPrice() { 55 | return price; 56 | } 57 | 58 | public void setPrice(BigDecimal price) { 59 | this.price = price; 60 | } 61 | 62 | @NotNull 63 | public Long getId() { 64 | return id; 65 | } 66 | 67 | public void setId(Long id) { 68 | this.id = id; 69 | } 70 | 71 | @NotNull(message = "You have to choose location") 72 | public LocationEnum getLocation() { 73 | return location; 74 | } 75 | 76 | public void setLocation(LocationEnum location) { 77 | this.location = location; 78 | } 79 | 80 | @NotNull(message = "You have to choose profile picture") 81 | public MultipartFile getImg() { 82 | return img; 83 | } 84 | 85 | public void setImg(MultipartFile img) { 86 | this.img = img; 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/main/java/com/example/hobbie/config/SecurityConfig.java: -------------------------------------------------------------------------------- 1 | package com.example.hobbie.config; 2 | 3 | import com.example.hobbie.security.HobbieUserDetailsService; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.context.annotation.Configuration; 6 | import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; 7 | import org.springframework.security.config.annotation.web.builders.HttpSecurity; 8 | import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; 9 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; 10 | import org.springframework.security.crypto.password.PasswordEncoder; 11 | import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; 12 | 13 | @Configuration 14 | @EnableWebSecurity 15 | public class SecurityConfig extends WebSecurityConfigurerAdapter { 16 | private final HobbieUserDetailsService hobbieUserDetailsService; 17 | private final PasswordEncoder passwordEncoder; 18 | 19 | @Autowired 20 | public SecurityConfig(HobbieUserDetailsService hobbieUserDetailsService, PasswordEncoder passwordEncoder) { 21 | this.hobbieUserDetailsService = hobbieUserDetailsService; 22 | this.passwordEncoder = passwordEncoder; 23 | } 24 | 25 | @Override 26 | protected void configure(AuthenticationManagerBuilder auth) throws Exception { 27 | auth.userDetailsService(hobbieUserDetailsService).passwordEncoder(passwordEncoder); 28 | } 29 | 30 | @Override 31 | protected void configure(HttpSecurity http) throws Exception { 32 | 33 | http.authorizeRequests().antMatchers("/css/**", "/img/**", "/js/**").permitAll() 34 | .antMatchers("/", "/users/login", "/users/signup", "/users/register-business").permitAll() 35 | .antMatchers("/**").authenticated() 36 | .and() 37 | .formLogin().loginPage("/users/login") 38 | .usernameParameter(UsernamePasswordAuthenticationFilter.SPRING_SECURITY_FORM_USERNAME_KEY) 39 | .passwordParameter(UsernamePasswordAuthenticationFilter.SPRING_SECURITY_FORM_PASSWORD_KEY) 40 | .defaultSuccessUrl("/") 41 | .failureForwardUrl("/users/login-error") 42 | .and() 43 | .logout() 44 | .logoutSuccessUrl("/") 45 | // remove the session from the server 46 | .invalidateHttpSession(true). 47 | // delete the session cookie 48 | deleteCookies("JSESSIONID"); 49 | 50 | } 51 | 52 | 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/com/example/hobbie/config/SessionTimerInterceptor.java: -------------------------------------------------------------------------------- 1 | package com.example.hobbie.config; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.security.core.context.SecurityContextHolder; 7 | import org.springframework.stereotype.Component; 8 | import org.springframework.web.servlet.HandlerInterceptor; 9 | import org.springframework.web.servlet.ModelAndView; 10 | 11 | import javax.servlet.http.HttpServletRequest; 12 | import javax.servlet.http.HttpServletResponse; 13 | import javax.servlet.http.HttpSession; 14 | 15 | @Component 16 | public class SessionTimerInterceptor implements HandlerInterceptor { 17 | private static final long MAX_INACTIVE_SESSION_TIME = 12 * 10000; 18 | 19 | private HttpSession session; 20 | 21 | Logger log = LoggerFactory.getLogger(SessionTimerInterceptor.class); 22 | 23 | @Autowired 24 | public SessionTimerInterceptor(HttpSession session) { 25 | this.session = session; 26 | } 27 | 28 | public SessionTimerInterceptor() { 29 | } 30 | 31 | 32 | @Override 33 | public boolean preHandle( 34 | HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { 35 | log.info("Pre handle method - check handling start time"); 36 | long startTime = System.currentTimeMillis(); 37 | request.setAttribute("executionTime", startTime); 38 | if (UserInterceptor.isUserLogged()) { 39 | session = request.getSession(); 40 | log.info(String.format("Time since last request in this session: %d ms", 41 | System.currentTimeMillis() - request.getSession().getLastAccessedTime())); 42 | if (System.currentTimeMillis() - session.getLastAccessedTime() 43 | > MAX_INACTIVE_SESSION_TIME) { 44 | log.warn("Logging out, due to inactive session"); 45 | SecurityContextHolder.clearContext(); 46 | request.logout(); 47 | response.sendRedirect("/default"); 48 | 49 | } 50 | } 51 | return true; 52 | } 53 | 54 | @Override 55 | public void postHandle( 56 | HttpServletRequest request, 57 | HttpServletResponse response, 58 | Object handler, 59 | ModelAndView model) throws Exception { 60 | log.info("Post handle method - check execution time of handling"); 61 | long startTime = (Long) request.getAttribute("executionTime"); 62 | log.info("Execution time for handling the request was: {} ms", 63 | System.currentTimeMillis() - startTime); 64 | } 65 | 66 | } 67 | -------------------------------------------------------------------------------- /src/test/java/com/example/hobbie/service/impl/UserRoleServiceImplTest.java: -------------------------------------------------------------------------------- 1 | package com.example.hobbie.service.impl; 2 | 3 | import com.example.hobbie.handler.NotFoundException; 4 | import com.example.hobbie.model.entities.UserRoleEntity; 5 | import com.example.hobbie.model.entities.enums.UserRoleEnum; 6 | import com.example.hobbie.model.repostiory.AppClientRepository; 7 | import com.example.hobbie.model.repostiory.BusinessOwnerRepository; 8 | import com.example.hobbie.model.repostiory.UserRepository; 9 | import com.example.hobbie.model.repostiory.UserRoleRepository; 10 | import com.example.hobbie.service.UserRoleService; 11 | import org.junit.Assert; 12 | 13 | import org.junit.jupiter.api.Assertions; 14 | import org.junit.jupiter.api.BeforeEach; 15 | import org.junit.jupiter.api.Test; 16 | import org.mockito.Mockito; 17 | 18 | import org.modelmapper.ModelMapper; 19 | import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; 20 | 21 | import java.util.Optional; 22 | 23 | import static org.junit.jupiter.api.Assertions.*; 24 | import static org.mockito.ArgumentMatchers.any; 25 | import static org.mockito.Mockito.mock; 26 | import static org.mockito.Mockito.when; 27 | 28 | class UserRoleServiceImplTest { 29 | private UserRoleService mockUserRoleServiceToTest; 30 | private UserRoleEntity userRoleEntity; 31 | private UserRoleRepository mockUserRoleRepository; 32 | 33 | @BeforeEach 34 | public void setUp() { 35 | mockUserRoleRepository = mock(UserRoleRepository.class); 36 | mockUserRoleServiceToTest = new UserRoleServiceImpl(mockUserRoleRepository); 37 | userRoleEntity = new UserRoleEntity(); 38 | userRoleEntity.setRole(UserRoleEnum.USER); 39 | when(mockUserRoleRepository.save(any(UserRoleEntity.class))) 40 | .thenAnswer(i -> i.getArguments()[0]); 41 | 42 | } 43 | 44 | @Test 45 | void getUserRoleByEnumName_Should_Work() { 46 | 47 | Mockito.when(mockUserRoleRepository.findByRole(UserRoleEnum.USER)). 48 | thenReturn(Optional.of(userRoleEntity)); 49 | UserRoleEntity userRoleByEnumName = mockUserRoleServiceToTest.getUserRoleByEnumName(UserRoleEnum.USER); 50 | 51 | assertEquals(userRoleEntity.getRole(),userRoleByEnumName.getRole()); 52 | } 53 | 54 | @Test 55 | void role_should_be_Saved() { 56 | Mockito.when(mockUserRoleRepository.save(any(UserRoleEntity.class))). 57 | thenReturn(userRoleEntity); 58 | UserRoleEntity userRole= mockUserRoleServiceToTest.saveRole(this.userRoleEntity); 59 | 60 | assertEquals(userRole.getId(), userRoleEntity.getId()); 61 | } 62 | 63 | @Test 64 | void testUserNotFound() { 65 | Assertions.assertThrows( 66 | NotFoundException.class, 67 | () -> mockUserRoleServiceToTest.getUserRoleByEnumName(UserRoleEnum.USER)); 68 | } 69 | 70 | 71 | 72 | } -------------------------------------------------------------------------------- /src/test/java/com/example/hobbie/web/HobbyControllerTest.java: -------------------------------------------------------------------------------- 1 | package com.example.hobbie.web; 2 | 3 | import com.example.hobbie.model.entities.enums.CategoryNameEnum; 4 | import com.example.hobbie.model.entities.enums.LocationEnum; 5 | import org.junit.jupiter.api.Test; 6 | import org.junit.runner.RunWith; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; 9 | import org.springframework.boot.test.context.SpringBootTest; 10 | import org.springframework.security.test.context.support.WithMockUser; 11 | import org.springframework.test.context.junit4.SpringRunner; 12 | import org.springframework.test.web.servlet.MockMvc; 13 | import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; 14 | 15 | import java.math.BigDecimal; 16 | 17 | import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; 18 | import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; 19 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; 20 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view; 21 | 22 | @RunWith(SpringRunner.class) 23 | @SpringBootTest 24 | @AutoConfigureMockMvc 25 | class HobbyControllerTest { 26 | 27 | @Autowired 28 | private MockMvc mockMvc; 29 | 30 | @Test 31 | @WithMockUser(value = "user", roles = {"USER", "ADMIN"}) 32 | void showOffer_should_work() throws Exception { 33 | this.mockMvc.perform(get("/hobbies/create-offer-page")). 34 | andExpect(view().name("offer/create_offer")). 35 | andExpect(status().isOk()); 36 | } 37 | 38 | @Test 39 | void saveHobby_should_work() throws Exception { 40 | mockMvc.perform(MockMvcRequestBuilders.post("/hobbies/create_offer") 41 | .param("img", "file") 42 | .param("name", "Nikoleta"). 43 | param("description", "bla"). 44 | param("category", CategoryNameEnum.ACTIVE.name()). 45 | param("price", String.valueOf(new BigDecimal("100"))). 46 | param("location", LocationEnum.ZURICH.name()). 47 | with(csrf())). 48 | andExpect(status().is3xxRedirection()); 49 | } 50 | 51 | @Test 52 | @WithMockUser(value = "user", roles = {"USER", "ADMIN"}) 53 | void showHome_should_work() throws Exception { 54 | this.mockMvc. 55 | perform(get("/hobbies/save-hobby/{id}", 1L)). 56 | andExpect(status().isOk()); 57 | } 58 | 59 | @Test 60 | @WithMockUser(value = "user", roles = {"USER", "ADMIN"}) 61 | void removeHobby_should_work() throws Exception { 62 | this.mockMvc. 63 | perform(get("/hobbies/remove-hobby/{id}", 1L)). 64 | andExpect(status().isOk()); 65 | } 66 | } -------------------------------------------------------------------------------- /src/main/resources/templates/offer/offer-details.html: -------------------------------------------------------------------------------- 1 | 2 | 4 |
5 | 6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | Title 15 |

16 | Bouldering at an indoors bouldering centre in Pasila, Helsinki, Finland 17 | Climbing activities include: 18 | Bouldering: Ascending boulders or small outcrops, often with climbing shoes and a chalk bag or bucket. Usually, instead of using a safety rope from above, injury is avoided using a crash pad and a human spotter (to direct a falling climber on to the pad. They can also give beta, or advice)[2] 19 | Buildering: Ascending the exterior skeletons of buildings, typically without protective equipment. 20 | Canyoneering: Climbing along canyons for sport or recreation. 21 | Chalk climbing: Ascending chalk cliffs uses some of the same techniques as ice climbing. 22 | Competition climbing: A formal, competitive sport of recent origins, normally practiced on artificial walls that resemble natural formations. The International Federation of Sport Climbing (IFSC) is the official organization governing competition rock climbing worldwide and is recognized by the IOC and GAISF and is a member of the International World Games Association (IWGA). The UIAA is the official organization governing competition ice climbing worldwide. Competition climbing has three major disciplines: Lead, Bouldering and Speed. 23 | 24 | Pole climbing: Climbing poles and masts without equipment.

25 |
26 | 27 | Edit 28 | Delete 29 | 30 |
31 |
32 |
33 | blueImg 34 | blueImg 35 | 36 | 37 |
38 | © Hobbie 2021. All rights reserved. 39 |
40 | 41 | 42 | -------------------------------------------------------------------------------- /src/main/java/com/example/hobbie/service/impl/EntryServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.example.hobbie.service.impl; 2 | 3 | import com.example.hobbie.handler.NotFoundException; 4 | import com.example.hobbie.model.entities.AppClient; 5 | import com.example.hobbie.service.NotificationService; 6 | import com.example.hobbie.view.EntryViewModel; 7 | import com.example.hobbie.model.entities.Entry; 8 | import com.example.hobbie.model.repostiory.EntryRepository; 9 | import com.example.hobbie.service.EntryService; 10 | import org.modelmapper.ModelMapper; 11 | import org.springframework.beans.factory.annotation.Autowired; 12 | import org.springframework.mail.MailException; 13 | import org.springframework.stereotype.Service; 14 | 15 | import java.text.SimpleDateFormat; 16 | import java.util.Calendar; 17 | import java.util.List; 18 | import java.util.Optional; 19 | import java.util.stream.Collectors; 20 | 21 | @Service 22 | public class EntryServiceImpl implements EntryService { 23 | private final EntryRepository entryRepository; 24 | private final ModelMapper modelMapper; 25 | private final NotificationService notificationService; 26 | 27 | @Autowired 28 | public EntryServiceImpl(EntryRepository entryRepository, ModelMapper modelMapper, NotificationService notificationService) { 29 | this.entryRepository = entryRepository; 30 | this.modelMapper = modelMapper; 31 | this.notificationService = notificationService; 32 | } 33 | 34 | @Override 35 | public List getAboEntries(Long id) { 36 | List allByAboId = this.entryRepository.findAllByAboId(id); 37 | return allByAboId.stream().map(entry -> this.modelMapper.map(entry, EntryViewModel.class)).collect(Collectors.toList()); 38 | } 39 | 40 | @Override 41 | public List saveAboEntries(List aboEntries) { 42 | return this.entryRepository.saveAll(aboEntries); 43 | } 44 | 45 | @Override 46 | public void saveUpdatedEntry(AppClient appClient, Long entryId) { 47 | Optional entry = this.entryRepository.findById(entryId); 48 | if (entry.isPresent()) { 49 | try { 50 | this.notificationService.sendNotification(appClient, entry.get()); 51 | } catch (MailException e) { 52 | System.out.println(e.toString()); 53 | } 54 | entry.get().setInProcess(true); 55 | this.entryRepository.save(entry.get()); 56 | } else { 57 | throw new NotFoundException("Entry not found"); 58 | } 59 | } 60 | 61 | @Override 62 | public void confirmUpdatedEntry(Long entryId) { 63 | Optional entry = this.entryRepository.findById(entryId); 64 | if (entry.isPresent()) { 65 | entry.get().setDate(new SimpleDateFormat("MM.dd.yyyy").format(Calendar.getInstance().getTime())); 66 | entry.get().setInProcess(false); 67 | this.entryRepository.save(entry.get()); 68 | 69 | } else { 70 | throw new NotFoundException("Entry not found"); 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/main/resources/static/img/cart.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | 8 | 9 | 12 | 13 | 16 | 19 | 21 | 24 | 27 | 28 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /src/main/java/com/example/hobbie/model/binding/TestBindingModel.java: -------------------------------------------------------------------------------- 1 | package com.example.hobbie.model.binding; 2 | 3 | import com.example.hobbie.model.entities.AppClient; 4 | import com.example.hobbie.model.entities.enums.CategoryNameEnum; 5 | import com.example.hobbie.model.entities.enums.LocationEnum; 6 | 7 | import javax.validation.constraints.NotNull; 8 | 9 | public class TestBindingModel { 10 | 11 | private CategoryNameEnum categoryOne; 12 | private CategoryNameEnum categoryTwo; 13 | private CategoryNameEnum categoryThree; 14 | private CategoryNameEnum categoryFour; 15 | private CategoryNameEnum categoryFive; 16 | private CategoryNameEnum categorySix; 17 | private CategoryNameEnum categorySeven; 18 | private LocationEnum location; 19 | 20 | public TestBindingModel() { 21 | } 22 | 23 | @NotNull(message = "You have to choose an answer") 24 | public CategoryNameEnum getCategoryOne() { 25 | return categoryOne; 26 | } 27 | 28 | public void setCategoryOne(CategoryNameEnum categoryOne) { 29 | this.categoryOne = categoryOne; 30 | } 31 | 32 | @NotNull(message = "You have to choose an answer") 33 | public CategoryNameEnum getCategoryTwo() { 34 | return categoryTwo; 35 | } 36 | 37 | public void setCategoryTwo(CategoryNameEnum categoryTwo) { 38 | this.categoryTwo = categoryTwo; 39 | } 40 | 41 | @NotNull(message = "You have to choose an answer") 42 | public CategoryNameEnum getCategoryThree() { 43 | return categoryThree; 44 | } 45 | 46 | public void setCategoryThree(CategoryNameEnum categoryThree) { 47 | this.categoryThree = categoryThree; 48 | } 49 | 50 | @NotNull(message = "You have to choose an answer") 51 | public CategoryNameEnum getCategoryFour() { 52 | return categoryFour; 53 | } 54 | 55 | public void setCategoryFour(CategoryNameEnum categoryFour) { 56 | this.categoryFour = categoryFour; 57 | } 58 | 59 | @NotNull(message = "You have to choose an answer") 60 | public CategoryNameEnum getCategoryFive() { 61 | return categoryFive; 62 | } 63 | 64 | public void setCategoryFive(CategoryNameEnum categoryFive) { 65 | this.categoryFive = categoryFive; 66 | } 67 | 68 | @NotNull(message = "You have to choose an answer") 69 | public CategoryNameEnum getCategorySix() { 70 | return categorySix; 71 | } 72 | 73 | public void setCategorySix(CategoryNameEnum categorySix) { 74 | this.categorySix = categorySix; 75 | } 76 | 77 | @NotNull(message = "You have to choose an answer") 78 | public CategoryNameEnum getCategorySeven() { 79 | return categorySeven; 80 | } 81 | 82 | public void setCategorySeven(CategoryNameEnum categorySeven) { 83 | this.categorySeven = categorySeven; 84 | } 85 | 86 | @NotNull(message = "You have to choose a location") 87 | public LocationEnum getLocation() { 88 | return location; 89 | } 90 | 91 | public void setLocation(LocationEnum location) { 92 | this.location = location; 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /src/main/resources/static/img/paypal.svg: -------------------------------------------------------------------------------- 1 | paypal-seeklogo.com -------------------------------------------------------------------------------- /src/test/java/com/example/hobbie/web/UserControllerTest.java: -------------------------------------------------------------------------------- 1 | package com.example.hobbie.web; 2 | 3 | import com.example.hobbie.model.entities.enums.GenderEnum; 4 | import org.junit.jupiter.api.Test; 5 | import org.junit.runner.RunWith; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; 8 | import org.springframework.boot.test.context.SpringBootTest; 9 | import org.springframework.security.test.context.support.WithMockUser; 10 | import org.springframework.test.context.junit4.SpringRunner; 11 | import org.springframework.test.web.servlet.MockMvc; 12 | import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; 13 | 14 | import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; 15 | import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; 16 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; 17 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view; 18 | 19 | @RunWith(SpringRunner.class) 20 | @SpringBootTest 21 | @AutoConfigureMockMvc 22 | class UserControllerTest { 23 | 24 | @Autowired 25 | private MockMvc mockMvc; 26 | 27 | @Test 28 | @WithMockUser(value = "user", roles = {"USER", "ADMIN"}) 29 | void showSignUp_should_work() throws Exception { 30 | this.mockMvc.perform(get("/users/signup")). 31 | andExpect(view().name("signup/signup")). 32 | andExpect(status().isOk()); 33 | } 34 | 35 | @Test 36 | void signup_should_work() throws Exception { 37 | mockMvc.perform(MockMvcRequestBuilders.post("/users/signup") 38 | .param("username", "user") 39 | .param("fullName", "full name"). 40 | param("gender", GenderEnum.FEMALE.name()). 41 | param("email", "test@patient.com"). 42 | param("password", "h[v`8r2TA')!-Ln3"). 43 | param("confirmPassword", "h[v`8r2TA')!-Ln3"). 44 | with(csrf())). 45 | andExpect(status().is3xxRedirection()); 46 | } 47 | 48 | @Test 49 | @WithMockUser(value = "user", roles = {"USER", "ADMIN"}) 50 | void showRegisterBusiness_should_work() throws Exception { 51 | this.mockMvc.perform(get("/users/register-business")). 52 | andExpect(view().name("signup/register-business")). 53 | andExpect(status().isOk()); 54 | } 55 | 56 | @Test 57 | void registerBusiness_should_work() throws Exception { 58 | mockMvc.perform(MockMvcRequestBuilders.post("/users/signup") 59 | .param("username", "business") 60 | .param("businessName", "business name"). 61 | param("address", "address 7"). 62 | param("email", "test@patient.com"). 63 | param("password", "h[v`8r2TA')!-Ln3"). 64 | param("confirmPassword", "h[v`8r2TA')!-Ln3"). 65 | with(csrf())). 66 | andExpect(status().is3xxRedirection()); 67 | } 68 | } -------------------------------------------------------------------------------- /src/main/resources/templates/offer/hobby-details.html: -------------------------------------------------------------------------------- 1 | 2 | 4 |
5 | 6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | Title 15 |

16 | Bouldering at an indoors bouldering centre in Pasila, Helsinki, Finland 17 | Climbing activities include: 18 | Bouldering: Ascending boulders or small outcrops, often with climbing shoes and a chalk bag or bucket. Usually, instead of using a safety rope from above, injury is avoided using a crash pad and a human spotter (to direct a falling climber on to the pad. They can also give beta, or advice)[2] 19 | Buildering: Ascending the exterior skeletons of buildings, typically without protective equipment. 20 | Canyoneering: Climbing along canyons for sport or recreation. 21 | Chalk climbing: Ascending chalk cliffs uses some of the same techniques as ice climbing. 22 | Competition climbing: A formal, competitive sport of recent origins, normally practiced on artificial walls that resemble natural formations. The International Federation of Sport Climbing (IFSC) is the official organization governing competition rock climbing worldwide and is recognized by the IOC and GAISF and is a member of the International World Games Association (IWGA). The UIAA is the official organization governing competition ice climbing worldwide. Competition climbing has three major disciplines: Lead, Bouldering and Speed. 23 | 24 | Pole climbing: Climbing poles and masts without equipment.

25 |
26 | 27 | 28 | 29 | Remove 30 | Save 31 | Add to cart 32 | 33 |
34 | 35 |
36 | 37 |
38 | blueImg 39 | blueImg 40 | 41 |
42 | © Hobbie 2021. All rights reserved. 43 |
44 | 45 | 46 | -------------------------------------------------------------------------------- /src/main/java/com/example/hobbie/config/UserInterceptor.java: -------------------------------------------------------------------------------- 1 | package com.example.hobbie.config; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | import org.springframework.security.core.context.SecurityContextHolder; 6 | import org.springframework.stereotype.Component; 7 | import org.springframework.web.servlet.HandlerInterceptor; 8 | import org.springframework.web.servlet.ModelAndView; 9 | import org.springframework.web.servlet.SmartView; 10 | import org.springframework.web.servlet.View; 11 | 12 | import javax.servlet.http.HttpServletRequest; 13 | import javax.servlet.http.HttpServletResponse; 14 | import javax.servlet.http.HttpSession; 15 | 16 | @Component 17 | public class UserInterceptor implements HandlerInterceptor { 18 | 19 | Logger log = LoggerFactory.getLogger(UserInterceptor.class); 20 | 21 | public static boolean isUserLogged() { 22 | try { 23 | return !SecurityContextHolder.getContext().getAuthentication() 24 | .getName().equals("anonymousUser"); 25 | } catch (Exception e) { 26 | return false; 27 | } 28 | } 29 | 30 | @Override 31 | public boolean preHandle(HttpServletRequest request, 32 | HttpServletResponse response, Object object) throws Exception { 33 | if (isUserLogged()) { 34 | addToModelUserDetails(request.getSession()); 35 | } 36 | return true; 37 | } 38 | 39 | private void addToModelUserDetails(HttpSession session) { 40 | log.info("=============== addToModelUserDetails ========================="); 41 | 42 | String loggedUsername 43 | = SecurityContextHolder.getContext().getAuthentication().getName(); 44 | session.setAttribute("username", loggedUsername); 45 | 46 | log.info("user(" + loggedUsername + ") session : " + session); 47 | log.info("=============== addToModelUserDetails ========================="); 48 | } 49 | 50 | @Override 51 | public void postHandle( 52 | HttpServletRequest req, 53 | HttpServletResponse res, 54 | Object o, 55 | ModelAndView model) throws Exception { 56 | 57 | if (model != null && !isRedirectView(model)) { 58 | if (isUserLogged()) { 59 | addToModelUserDetails(model); 60 | } 61 | } 62 | } 63 | 64 | public static boolean isRedirectView(ModelAndView mv) { 65 | String viewName = mv.getViewName(); 66 | if (viewName.startsWith("redirect:/")) { 67 | return true; 68 | } 69 | View view = mv.getView(); 70 | return (view != null && view instanceof SmartView 71 | && ((SmartView) view).isRedirectView()); 72 | } 73 | 74 | private void addToModelUserDetails(ModelAndView model) { 75 | log.info("=============== addToModelUserDetails ========================="); 76 | 77 | String loggedUsername = SecurityContextHolder.getContext() 78 | .getAuthentication().getName(); 79 | model.addObject("loggedUsername", loggedUsername); 80 | 81 | log.trace("session : " + model.getModel()); 82 | log.info("=============== addToModelUserDetails ========================="); 83 | } 84 | 85 | } 86 | -------------------------------------------------------------------------------- /src/main/java/com/example/hobbie/model/entities/Test.java: -------------------------------------------------------------------------------- 1 | package com.example.hobbie.model.entities; 2 | 3 | import com.example.hobbie.model.entities.enums.CategoryNameEnum; 4 | import com.example.hobbie.model.entities.enums.LocationEnum; 5 | 6 | import javax.persistence.*; 7 | 8 | @Entity 9 | @Table(name = "test_results") 10 | public class Test extends BaseEntity { 11 | private AppClient appClient; 12 | private CategoryNameEnum categoryOne; 13 | private CategoryNameEnum categoryTwo; 14 | private CategoryNameEnum categoryThree; 15 | private CategoryNameEnum categoryFour; 16 | private CategoryNameEnum categoryFive; 17 | private CategoryNameEnum categorySix; 18 | private CategoryNameEnum categorySeven; 19 | private LocationEnum location; 20 | 21 | public Test() { 22 | } 23 | 24 | @OneToOne 25 | public AppClient getAppClient() { 26 | return appClient; 27 | } 28 | 29 | public void setAppClient(AppClient appClient) { 30 | this.appClient = appClient; 31 | } 32 | 33 | @Enumerated(EnumType.STRING) 34 | @Column(name = "category_one") 35 | public CategoryNameEnum getCategoryOne() { 36 | return categoryOne; 37 | } 38 | 39 | public void setCategoryOne(CategoryNameEnum categoryOne) { 40 | this.categoryOne = categoryOne; 41 | } 42 | 43 | @Enumerated(EnumType.STRING) 44 | @Column(name = "category_two") 45 | public CategoryNameEnum getCategoryTwo() { 46 | return categoryTwo; 47 | } 48 | 49 | public void setCategoryTwo(CategoryNameEnum categoryTwo) { 50 | this.categoryTwo = categoryTwo; 51 | } 52 | 53 | @Enumerated(EnumType.STRING) 54 | @Column(name = "category_three") 55 | public CategoryNameEnum getCategoryThree() { 56 | return categoryThree; 57 | } 58 | 59 | public void setCategoryThree(CategoryNameEnum categoryThree) { 60 | this.categoryThree = categoryThree; 61 | } 62 | 63 | @Enumerated(EnumType.STRING) 64 | @Column(name = "category_four") 65 | public CategoryNameEnum getCategoryFour() { 66 | return categoryFour; 67 | } 68 | 69 | public void setCategoryFour(CategoryNameEnum categoryFour) { 70 | this.categoryFour = categoryFour; 71 | } 72 | 73 | @Enumerated(EnumType.STRING) 74 | @Column(name = "category_five") 75 | public CategoryNameEnum getCategoryFive() { 76 | return categoryFive; 77 | } 78 | 79 | public void setCategoryFive(CategoryNameEnum categoryFive) { 80 | this.categoryFive = categoryFive; 81 | } 82 | 83 | @Enumerated(EnumType.STRING) 84 | @Column(name = "category_six") 85 | public CategoryNameEnum getCategorySix() { 86 | return categorySix; 87 | } 88 | 89 | public void setCategorySix(CategoryNameEnum categorySix) { 90 | this.categorySix = categorySix; 91 | } 92 | 93 | @Enumerated(EnumType.STRING) 94 | @Column(name = "category_seven") 95 | public CategoryNameEnum getCategorySeven() { 96 | return categorySeven; 97 | } 98 | 99 | public void setCategorySeven(CategoryNameEnum categorySeven) { 100 | this.categorySeven = categorySeven; 101 | } 102 | 103 | @Enumerated(EnumType.STRING) 104 | public LocationEnum getLocation() { 105 | return location; 106 | } 107 | 108 | public void setLocation(LocationEnum location) { 109 | this.location = location; 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /src/main/java/com/example/hobbie/web/HomeController.java: -------------------------------------------------------------------------------- 1 | package com.example.hobbie.web; 2 | 3 | import com.example.hobbie.config.UserInterceptor; 4 | import com.example.hobbie.model.entities.AppClient; 5 | import com.example.hobbie.service.AboService; 6 | import com.example.hobbie.service.HobbyService; 7 | import com.example.hobbie.service.UserService; 8 | import com.example.hobbie.view.HobbyCardViewModel; 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.security.core.annotation.AuthenticationPrincipal; 11 | import org.springframework.security.core.userdetails.UserDetails; 12 | import org.springframework.stereotype.Controller; 13 | import org.springframework.web.bind.annotation.GetMapping; 14 | import org.springframework.web.bind.annotation.RequestMapping; 15 | import org.springframework.web.servlet.ModelAndView; 16 | 17 | import javax.servlet.http.HttpServletRequest; 18 | import java.util.List; 19 | 20 | @Controller 21 | @RequestMapping("/") 22 | public class HomeController { 23 | private final HobbyService hobbyService; 24 | private final UserService userService; 25 | private final AboService aboService; 26 | 27 | @Autowired 28 | public HomeController(HobbyService hobbyService, UserService userService, AboService aboService) { 29 | this.hobbyService = hobbyService; 30 | this.userService = userService; 31 | this.aboService = aboService; 32 | } 33 | 34 | @RequestMapping("/") 35 | public String showHome(HttpServletRequest request) { 36 | if (UserInterceptor.isUserLogged()) { 37 | if (request.isUserInRole("ROLE_BUSINESS_USER")) { 38 | return "redirect:/business_owner"; 39 | } else if (request.isUserInRole("ROLE_USER")) { 40 | return "redirect:/user_home"; 41 | } 42 | return "redirect:/"; 43 | } 44 | return "home/index"; 45 | } 46 | 47 | @GetMapping("/business_owner") 48 | public ModelAndView adminShow(@AuthenticationPrincipal UserDetails principal) { 49 | if (UserInterceptor.isUserLogged()) { 50 | ModelAndView mav = new ModelAndView("home/business_owner"); 51 | mav.addObject("user", principal); 52 | mav.addObject("hobby_offers", hobbyService.getAllHobbyOffers()); 53 | mav.addObject("abos", this.aboService.getAbosPerBusiness()); 54 | return mav; 55 | } else { 56 | ModelAndView mav = new ModelAndView("home/index"); 57 | return mav; 58 | } 59 | } 60 | 61 | @GetMapping("/user_home") 62 | public ModelAndView userHomeShow(@AuthenticationPrincipal UserDetails principal) { 63 | if (UserInterceptor.isUserLogged()) { 64 | boolean isEmpty = false; 65 | boolean hasNoResults = false; 66 | ModelAndView mav = new ModelAndView("home/user_home"); 67 | mav.addObject("user", principal); 68 | AppClient currentUserAppClient = this.userService.findCurrentUserAppClient(); 69 | List hobbyMatches = this.hobbyService.getHobbyMatches(currentUserAppClient); 70 | if (currentUserAppClient.getTestResults() == null) { 71 | hasNoResults = true; 72 | } else if (hobbyMatches.isEmpty()) { 73 | isEmpty = true; 74 | } 75 | 76 | mav.addObject("hobby_matches", hobbyMatches); 77 | mav.addObject("hasNoMatches", isEmpty); 78 | mav.addObject("hasNoResults", hasNoResults); 79 | 80 | return mav; 81 | } else { 82 | ModelAndView mav = new ModelAndView("home/index"); 83 | return mav; 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/main/resources/templates/abo/abo.html: -------------------------------------------------------------------------------- 1 | 2 | 4 |
5 | 6 |
7 |
8 |
9 |
10 |
11 |
12 | 13 |
14 | 56 | 57 | 58 |
59 | blueImg 60 | blueImg 61 | blue 62 | 63 |
64 | © Hobbie 2021. All rights reserved. 65 |
66 | 67 | -------------------------------------------------------------------------------- /src/main/java/com/example/hobbie/service/impl/ShoppingCartServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.example.hobbie.service.impl; 2 | 3 | import com.example.hobbie.model.entities.Abo; 4 | import com.example.hobbie.model.entities.AppClient; 5 | import com.example.hobbie.model.entities.Entry; 6 | import com.example.hobbie.model.entities.Hobby; 7 | import com.example.hobbie.service.*; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.stereotype.Service; 10 | import org.springframework.transaction.annotation.Transactional; 11 | 12 | import java.math.BigDecimal; 13 | import java.math.RoundingMode; 14 | import java.util.ArrayList; 15 | import java.util.List; 16 | 17 | @Service 18 | @Transactional 19 | public class ShoppingCartServiceImpl implements ShoppingCartService { 20 | private final UserService userService; 21 | private final AboService aboService; 22 | private final EntryService entryService; 23 | private List inCart = new ArrayList<>(); 24 | 25 | @Autowired 26 | public ShoppingCartServiceImpl(UserService userService, AboService aboService, EntryService entryService) { 27 | this.userService = userService; 28 | this.aboService = aboService; 29 | this.entryService = entryService; 30 | } 31 | 32 | @Override 33 | public void addAboToCart(Hobby hobby) { 34 | Abo abo = new Abo(); 35 | AppClient currentUserAppClient = this.userService.findCurrentUserAppClient(); 36 | abo.setClientId(currentUserAppClient.getId()); 37 | abo.setBusinessOwnerId(hobby.getBusinessOwner().getId()); 38 | abo.setHobbyId(hobby.getId()); 39 | abo.setName(hobby.getName()); 40 | abo.setClientName(currentUserAppClient.getFullName()); 41 | 42 | BigDecimal price = hobby.getPrice().multiply(new BigDecimal(5)); 43 | price = price.add(price.multiply(new BigDecimal("0.1"))); 44 | price = price.setScale(2, RoundingMode.HALF_EVEN); 45 | abo.setAboPrice(price); 46 | 47 | if (!inCart.contains(abo)) { 48 | inCart.add(abo); 49 | } 50 | } 51 | 52 | @Override 53 | public void removeProductFromCart(Long hobbyId) { 54 | for (Abo abo : inCart) { 55 | if (abo.getHobbyId().equals(hobbyId)) { 56 | inCart.remove(abo); 57 | break; 58 | } 59 | } 60 | } 61 | 62 | @Override 63 | public BigDecimal getTotal() { 64 | return inCart.stream().map(Abo::getAboPrice).reduce(BigDecimal::add).orElse(BigDecimal.ZERO); 65 | } 66 | 67 | @Override 68 | public List getAbosInCart() { 69 | return inCart; 70 | } 71 | 72 | @Override 73 | public void checkout() { 74 | List abos = this.aboService.saveAbos(inCart); 75 | abos.forEach(this::fillEntries); 76 | this.aboService.updateAbosWithEntries(abos); 77 | inCart.clear(); 78 | } 79 | 80 | private void fillEntries(Abo abo) { 81 | List aboEntries = new ArrayList<>(); 82 | for (int i = 0; i < 5; i++) { 83 | Entry entry = new Entry(); 84 | entry.setAbo(abo); 85 | aboEntries.add(entry); 86 | } 87 | List entries = this.entryService.saveAboEntries(aboEntries); 88 | abo.setEntries(entries); 89 | } 90 | 91 | public UserService getUserService() { 92 | return userService; 93 | } 94 | 95 | public AboService getAboService() { 96 | return aboService; 97 | } 98 | 99 | public EntryService getEntryService() { 100 | return entryService; 101 | } 102 | 103 | public List getInCart() { 104 | return inCart; 105 | } 106 | 107 | public void setInCart(List inCart) { 108 | this.inCart = inCart; 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /src/main/resources/templates/account/update-business.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
5 | 6 | 7 |
8 |
9 |
10 | 11 |
12 | 13 |
14 |

Edit account info

15 |
16 | Passwords don't match 17 |
18 |
19 | This business name or email already exist. 20 |
21 |
22 |
23 |
24 |
25 | 26 | 30 |
31 |
32 |
33 |
34 |
35 | 36 | 40 |
41 |
42 | 43 |
44 |
45 |
46 | 47 | 51 |
52 |
53 |
54 |
55 |
56 |
57 | 58 | 62 |
63 |
64 |
65 |
66 |
67 |
68 | 69 | 73 |
74 |
75 |
76 | 77 |
78 | 79 |
80 |
81 | 82 |
83 | 84 |
85 | © Hobbie 2021. All rights reserved. 86 |
87 | 88 | blueImg2 89 | 90 | -------------------------------------------------------------------------------- /src/main/java/com/example/hobbie/web/AboController.java: -------------------------------------------------------------------------------- 1 | package com.example.hobbie.web; 2 | 3 | import com.example.hobbie.config.UserInterceptor; 4 | import com.example.hobbie.model.entities.Abo; 5 | import com.example.hobbie.model.entities.AppClient; 6 | import com.example.hobbie.view.AboViewModel; 7 | import com.example.hobbie.view.EntryViewModel; 8 | import com.example.hobbie.service.AboService; 9 | import com.example.hobbie.service.EntryService; 10 | import com.example.hobbie.service.HobbyService; 11 | import com.example.hobbie.service.UserService; 12 | import org.modelmapper.ModelMapper; 13 | import org.springframework.beans.factory.annotation.Autowired; 14 | import org.springframework.stereotype.Controller; 15 | import org.springframework.ui.Model; 16 | import org.springframework.web.bind.annotation.*; 17 | import org.springframework.web.servlet.ModelAndView; 18 | 19 | import java.text.ParseException; 20 | import java.util.List; 21 | 22 | @Controller 23 | public class AboController { 24 | private final UserService userService; 25 | private final AboService aboService; 26 | private final HobbyService hobbyService; 27 | private final EntryService entryService; 28 | private final ModelMapper modelMapper; 29 | 30 | @Autowired 31 | public AboController(UserService userService, AboService aboService, HobbyService hobbyService, EntryService entryService, ModelMapper modelMapper) { 32 | this.userService = userService; 33 | this.aboService = aboService; 34 | this.hobbyService = hobbyService; 35 | this.entryService = entryService; 36 | this.modelMapper = modelMapper; 37 | } 38 | 39 | @GetMapping("/my-abos") 40 | public ModelAndView ShowAllAbos() { 41 | if (UserInterceptor.isUserLogged()) { 42 | ModelAndView mav = new ModelAndView("abo/my-abos"); 43 | mav.addObject("liked", this.hobbyService.findSavedHobbies(this.userService.findCurrentUserAppClient())); 44 | mav.addObject("abos", this.aboService.getUserAbos(this.userService.findCurrentUserAppClient().getId())); 45 | return mav; 46 | } else { 47 | ModelAndView mav = new ModelAndView("home/index"); 48 | return mav; 49 | } 50 | } 51 | 52 | @GetMapping("/abo/{id}") 53 | public String showAbo(@PathVariable Long id, Model model) { 54 | if (UserInterceptor.isUserLogged()) { 55 | model.addAttribute("clientDetails", this.aboService.getClientDetails(id)); 56 | AboViewModel aboById = this.aboService.findAboById(id); 57 | model.addAttribute("aboDetails", aboById); 58 | List aboEntries = this.entryService.getAboEntries(id); 59 | model.addAttribute("entries", aboEntries); 60 | model.addAttribute("aboId", id); 61 | model.addAttribute("hobbyName", this.hobbyService.findHobbieById(aboById.getHobbyId()).getName()); 62 | return "abo/abo"; 63 | } else { 64 | return "home/index"; 65 | } 66 | } 67 | 68 | @GetMapping("/confirm-update-entry/{id}") 69 | public String confirmUpdateEntry(@PathVariable Long id) { 70 | Long aboId = this.aboService.findAboId(id); 71 | this.entryService.confirmUpdatedEntry(id); 72 | return "redirect:/abo/" + aboId; 73 | } 74 | 75 | @PostMapping("/entry/{id}") 76 | public String updateEntry(@PathVariable Long id) throws ParseException { 77 | if (UserInterceptor.isUserLogged()) { 78 | Long aboId = this.aboService.findAboId(id); 79 | Abo abo = this.aboService.findAbo(aboId); 80 | AppClient appClientById = this.userService.findAppClientById(abo.getClientId()); 81 | this.entryService.saveUpdatedEntry(appClientById, id); 82 | return "redirect:/abo/" + aboId; 83 | } else { 84 | return "home/index"; 85 | } 86 | } 87 | 88 | @PostMapping("/delete-abo/{id}") 89 | public String deleteAbo(@PathVariable Long id, Model model) { 90 | if (UserInterceptor.isUserLogged()) { 91 | this.aboService.deleteAbo(id); 92 | return "redirect:/default"; 93 | } else { 94 | return "home/index"; 95 | } 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /src/main/resources/static/img/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 9 | 11 | 12 | 20 | 24 | 25 | 31 | 35 | 36 | 38 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /src/main/java/com/example/hobbie/service/impl/AboServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.example.hobbie.service.impl; 2 | 3 | import com.example.hobbie.handler.FailToDeleteException; 4 | import com.example.hobbie.handler.NotFoundException; 5 | import com.example.hobbie.model.entities.Abo; 6 | import com.example.hobbie.model.entities.AppClient; 7 | import com.example.hobbie.model.repostiory.AboRepository; 8 | import com.example.hobbie.service.AboService; 9 | import com.example.hobbie.service.UserService; 10 | import com.example.hobbie.view.AboViewModel; 11 | import org.modelmapper.ModelMapper; 12 | import org.springframework.beans.factory.annotation.Autowired; 13 | import org.springframework.stereotype.Service; 14 | 15 | import java.util.List; 16 | import java.util.Optional; 17 | import java.util.stream.Collectors; 18 | 19 | @Service 20 | public class AboServiceImpl implements AboService { 21 | private final AboRepository aboRepository; 22 | private final UserService userService; 23 | private final ModelMapper modelMapper; 24 | 25 | @Autowired 26 | public AboServiceImpl(AboRepository aboRepository, UserService userService, ModelMapper modelMapper) { 27 | this.aboRepository = aboRepository; 28 | this.userService = userService; 29 | this.modelMapper = modelMapper; 30 | } 31 | 32 | @Override 33 | public List saveAbos(List inCart) { 34 | return this.aboRepository.saveAll(inCart); 35 | } 36 | 37 | @Override 38 | public List getUserAbos(Long id) { 39 | 40 | List byClientId = this.aboRepository.findByClientId(id); 41 | 42 | return byClientId.stream().map(abo -> this.modelMapper.map(abo, AboViewModel.class)).collect(Collectors.toList()); 43 | } 44 | 45 | @Override 46 | public void updateAbosWithEntries(List abos) { 47 | this.aboRepository.saveAll(abos); 48 | } 49 | 50 | @Override 51 | public Long findAboId(Long id) { 52 | Optional byEntriesId = this.aboRepository.findByEntriesId(id); 53 | if (byEntriesId.isPresent()) { 54 | return byEntriesId.get().getId(); 55 | } else { 56 | throw new NotFoundException("This abo does not exist."); 57 | } 58 | } 59 | 60 | @Override 61 | public List getAbosPerBusiness() { 62 | Long id = this.userService.findCurrentUserBusinessOwner().getId(); 63 | List abos = this.aboRepository.findAllByBusinessOwnerId(id); 64 | return abos.stream().map(abo -> this.modelMapper.map(abo, AboViewModel.class)).collect(Collectors.toList()); 65 | } 66 | 67 | @Override 68 | public AppClient getClientDetails(Long id) { 69 | Optional byId = this.aboRepository.findById(id); 70 | 71 | if (byId.isPresent()) { 72 | return this.userService.findAppClientById(byId.get().getClientId()); 73 | } else { 74 | throw new NotFoundException("No such client. This abo does not exist."); 75 | } 76 | } 77 | 78 | @Override 79 | public AboViewModel findAboById(Long id) { 80 | Optional byId = this.aboRepository.findById(id); 81 | 82 | if (byId.isPresent()) { 83 | return this.modelMapper.map(byId.get(), AboViewModel.class); 84 | } else { 85 | throw new NotFoundException("This abo does not exist."); 86 | } 87 | } 88 | 89 | @Override 90 | public List getExcistingAbosForClient(Long id) { 91 | return this.aboRepository.findByClientId(id); 92 | } 93 | 94 | @Override 95 | public void deleteAbo(Long id) { 96 | Optional byId = this.aboRepository.findById(id); 97 | if (byId.isPresent()) { 98 | this.aboRepository.delete(byId.get()); 99 | } else { 100 | throw new NotFoundException("Abo does not exist"); 101 | } 102 | } 103 | 104 | @Override 105 | public void findExcistingAbosWithHobbyId(Long id) { 106 | List byHobbyId = this.aboRepository.findByHobbyId(id); 107 | if (byHobbyId.size() > 0) { 108 | throw new FailToDeleteException("Can not delete hobby. There are existing Abos for this offer."); 109 | } 110 | } 111 | 112 | @Override 113 | public Abo findAbo(Long id) { 114 | Optional byId = this.aboRepository.findById(id); 115 | 116 | if (byId.isPresent()) { 117 | return byId.get(); 118 | } else { 119 | throw new NotFoundException("Abo does not exist"); 120 | } 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /src/main/resources/templates/signup/register-business.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
5 | 6 | 7 |
8 |
9 |
10 |
11 | 12 |
13 | 14 |
15 |

Register your business

16 |
17 | Passwords don't match 18 |
19 |
20 | This username, business name or email already exist. 21 |
22 |
23 | 24 |
25 |
26 |
27 | 28 | 32 |
33 |
34 |
35 |
36 |
37 |
38 | 39 | 43 |
44 |
45 |
46 |
47 |
48 | 49 | 53 |
54 |
55 | 56 |
57 |
58 |
59 | 60 | 64 |
65 |
66 |
67 |
68 |
69 |
70 | 71 | 75 |
76 |
77 |
78 |
79 |
80 |
81 | 82 | 86 |
87 |
88 |
89 | 90 |
91 | 92 |
93 |
94 |
95 | © Hobbie 2021. All rights reserved. 96 |
97 |
98 | blueImg2 99 | 100 | -------------------------------------------------------------------------------- /src/main/resources/templates/fragments/fragments.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | Hobbie 17 | 18 | 35 | 36 |
37 | 38 | logo 39 | 40 | 41 | 42 | logo 43 | 44 | 45 |
46 | 66 | 67 | 68 | 69 |
70 | cart 71 |
72 |
73 | 74 | 94 |
95 | 96 | 97 | 98 | -------------------------------------------------------------------------------- /src/main/resources/templates/account/update-user.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
5 | 6 | 7 |
8 |
9 |
10 | 11 |
12 | 13 |
14 |

Edit account info

15 |
16 | Passwords don't match 17 |
18 |
19 | This email already exist. 20 |
21 |
22 |
23 |
24 |
25 | 26 | 30 |
31 |
32 |
33 | 34 |
35 |
36 |
37 | 41 |
42 |
43 |
44 |
45 |
46 | 47 | 48 | 49 | 50 | 51 | 52 |
53 |
54 |
55 |
56 |
57 | 58 | 62 |
63 |
64 |
65 |
66 |
67 |
68 | 69 | 73 |
74 |
75 |
76 |
77 |
78 |
79 | 80 | 84 |
85 |
86 |
87 | 88 |
89 | 90 |
91 |
92 |
93 | 94 |
95 | © Hobbie 2021. All rights reserved. 96 |
97 | blueImg2 98 | 99 | 108 | 109 | -------------------------------------------------------------------------------- /src/main/resources/templates/offer/create_offer.html: -------------------------------------------------------------------------------- 1 | 2 | 4 |
5 | 6 | 7 |
8 |
9 |
10 |
11 | 12 |
13 |
14 |
15 |

Create offer

16 |
17 | 18 |
19 |
20 |
21 | 24 | 25 | 26 |
27 | Error message 28 |
29 |
30 |
31 |
32 |
33 | 36 | 37 | 38 |
39 | Error message 40 |
41 |
42 | 43 |
44 | Category 45 | 53 | Error message 54 |
55 |
56 |
57 | 58 |
59 | 62 | 63 |
64 | 65 | Error message 66 |
67 |
68 |
69 | Location 70 | 78 | Error message 79 |
80 |
81 |
82 |
83 |
84 | Please upload a profile photo 85 |
86 |
87 | 90 |
91 | 92 |
93 | 94 | 95 |
96 | 97 |
98 |
99 |
100 | 101 |
102 | 103 |
104 |
105 |
106 | 107 |
108 | © Hobbie 2021. All rights reserved. 109 |
110 | blueImg 111 | blueImg 112 |
113 | 114 | 115 | 116 | 117 | 118 | -------------------------------------------------------------------------------- /.mvn/wrapper/MavenWrapperDownloader.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2007-present the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import java.net.*; 18 | import java.io.*; 19 | import java.nio.channels.*; 20 | import java.util.Properties; 21 | 22 | public class MavenWrapperDownloader { 23 | 24 | private static final String WRAPPER_VERSION = "0.5.6"; 25 | /** 26 | * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided. 27 | */ 28 | private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/" 29 | + WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar"; 30 | 31 | /** 32 | * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to 33 | * use instead of the default one. 34 | */ 35 | private static final String MAVEN_WRAPPER_PROPERTIES_PATH = 36 | ".mvn/wrapper/maven-wrapper.properties"; 37 | 38 | /** 39 | * Path where the maven-wrapper.jar will be saved to. 40 | */ 41 | private static final String MAVEN_WRAPPER_JAR_PATH = 42 | ".mvn/wrapper/maven-wrapper.jar"; 43 | 44 | /** 45 | * Name of the property which should be used to override the default download url for the wrapper. 46 | */ 47 | private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl"; 48 | 49 | public static void main(String args[]) { 50 | System.out.println("- Downloader started"); 51 | File baseDirectory = new File(args[0]); 52 | System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath()); 53 | 54 | // If the maven-wrapper.properties exists, read it and check if it contains a custom 55 | // wrapperUrl parameter. 56 | File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH); 57 | String url = DEFAULT_DOWNLOAD_URL; 58 | if (mavenWrapperPropertyFile.exists()) { 59 | FileInputStream mavenWrapperPropertyFileInputStream = null; 60 | try { 61 | mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile); 62 | Properties mavenWrapperProperties = new Properties(); 63 | mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream); 64 | url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url); 65 | } catch (IOException e) { 66 | System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'"); 67 | } finally { 68 | try { 69 | if (mavenWrapperPropertyFileInputStream != null) { 70 | mavenWrapperPropertyFileInputStream.close(); 71 | } 72 | } catch (IOException e) { 73 | // Ignore ... 74 | } 75 | } 76 | } 77 | System.out.println("- Downloading from: " + url); 78 | 79 | File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH); 80 | if (!outputFile.getParentFile().exists()) { 81 | if (!outputFile.getParentFile().mkdirs()) { 82 | System.out.println( 83 | "- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'"); 84 | } 85 | } 86 | System.out.println("- Downloading to: " + outputFile.getAbsolutePath()); 87 | try { 88 | downloadFileFromURL(url, outputFile); 89 | System.out.println("Done"); 90 | System.exit(0); 91 | } catch (Throwable e) { 92 | System.out.println("- Error downloading"); 93 | e.printStackTrace(); 94 | System.exit(1); 95 | } 96 | } 97 | 98 | private static void downloadFileFromURL(String urlString, File destination) throws Exception { 99 | if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) { 100 | String username = System.getenv("MVNW_USERNAME"); 101 | char[] password = System.getenv("MVNW_PASSWORD").toCharArray(); 102 | Authenticator.setDefault(new Authenticator() { 103 | @Override 104 | protected PasswordAuthentication getPasswordAuthentication() { 105 | return new PasswordAuthentication(username, password); 106 | } 107 | }); 108 | } 109 | URL website = new URL(urlString); 110 | ReadableByteChannel rbc; 111 | rbc = Channels.newChannel(website.openStream()); 112 | FileOutputStream fos = new FileOutputStream(destination); 113 | fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE); 114 | fos.close(); 115 | rbc.close(); 116 | } 117 | 118 | } 119 | -------------------------------------------------------------------------------- /src/main/resources/templates/offer/update-hobby.html: -------------------------------------------------------------------------------- 1 | 2 | 4 |
5 | 6 | 7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |

Edit hobby offer

16 |
17 | 18 |
19 |
20 |
21 | 24 | 25 | 26 |
27 | Error message 28 |
29 |
30 |
31 |
32 |
33 | 36 | 37 | 38 |
39 | Error message 40 |
41 |
42 | 43 |
44 | Category 45 | 53 | Error message 54 |
55 |
56 |
57 | 58 |
59 | 62 | 63 |
64 | 65 | Error message 66 |
67 |
68 |
69 | Location 70 | 78 | Error message 79 |
80 |
81 |
82 |
83 |
84 |
85 | Please upload a profile photo 86 |
87 | 90 | 91 |
92 | 93 |
94 | 95 |
96 | 97 |
98 |
99 |
100 | 101 |
102 | 103 |
104 |
105 |
106 | 107 |
108 | © Hobbie 2021. All rights reserved. 109 |
110 | blueImg 111 | blueImg 112 |
113 | 114 | 115 | 116 | 117 | 118 | --------------------------------------------------------------------------------