├── src └── main │ ├── java │ └── com │ │ └── zufar │ │ └── requestsystem │ │ ├── repository │ │ ├── RequestRepository.java │ │ ├── RoleRepository.java │ │ └── UserRepository.java │ │ ├── dto │ │ ├── RequestDTO.java │ │ └── UserDTO.java │ │ ├── RequestSystemApplication.java │ │ ├── exception │ │ ├── UserNotFoundException.java │ │ └── RequestNotFoundException.java │ │ ├── configuration │ │ ├── CustomUserDetails.java │ │ ├── SecurityConfig.java │ │ └── CustomUserDetailsService.java │ │ ├── entity │ │ ├── Role.java │ │ ├── Request.java │ │ └── User.java │ │ ├── uicontroller │ │ ├── RequestUIController.java │ │ └── UserUIController.java │ │ ├── restcontroller │ │ ├── UserController.java │ │ └── RequestController.java │ │ └── service │ │ ├── UserService.java │ │ └── RequestService.java │ └── resources │ ├── application.yaml │ ├── banner.txt │ ├── static │ ├── js │ │ └── script.js │ └── css │ │ └── mainStyle.css │ └── templates │ ├── requests.ftl │ └── users.ftl ├── .gitignore ├── pom.xml └── script.sql /src/main/java/com/zufar/requestsystem/repository/RequestRepository.java: -------------------------------------------------------------------------------- 1 | package com.zufar.requestsystem.repository; 2 | 3 | import com.zufar.requestsystem.entity.Request; 4 | import org.springframework.data.repository.CrudRepository; 5 | import org.springframework.stereotype.Repository; 6 | 7 | @Repository 8 | public interface RequestRepository extends CrudRepository { 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/com/zufar/requestsystem/repository/RoleRepository.java: -------------------------------------------------------------------------------- 1 | package com.zufar.requestsystem.repository; 2 | 3 | import com.zufar.requestsystem.entity.Role; 4 | import com.zufar.requestsystem.entity.User; 5 | import org.springframework.data.repository.CrudRepository; 6 | import org.springframework.stereotype.Repository; 7 | 8 | import java.util.Optional; 9 | 10 | @Repository 11 | public interface RoleRepository extends CrudRepository { 12 | } 13 | 14 | -------------------------------------------------------------------------------- /src/main/java/com/zufar/requestsystem/repository/UserRepository.java: -------------------------------------------------------------------------------- 1 | package com.zufar.requestsystem.repository; 2 | 3 | import com.zufar.requestsystem.entity.User; 4 | import org.springframework.data.repository.CrudRepository; 5 | import org.springframework.stereotype.Repository; 6 | 7 | import java.util.Optional; 8 | 9 | @Repository 10 | public interface UserRepository extends CrudRepository { 11 | Optional findByLogin(String login); 12 | } 13 | 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/** 5 | !**/src/test/** 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 | 30 | ### VS Code ### 31 | .vscode/ 32 | -------------------------------------------------------------------------------- /src/main/java/com/zufar/requestsystem/dto/RequestDTO.java: -------------------------------------------------------------------------------- 1 | package com.zufar.requestsystem.dto; 2 | 3 | import lombok.Setter; 4 | import lombok.Getter; 5 | import lombok.AllArgsConstructor; 6 | import lombok.EqualsAndHashCode; 7 | import lombok.NoArgsConstructor; 8 | import lombok.ToString; 9 | 10 | @Getter 11 | @Setter 12 | @EqualsAndHashCode 13 | @ToString 14 | @AllArgsConstructor 15 | @NoArgsConstructor 16 | public class RequestDTO { 17 | 18 | private Long id; 19 | private String title; 20 | private String description; 21 | private UserDTO user; 22 | } -------------------------------------------------------------------------------- /src/main/java/com/zufar/requestsystem/RequestSystemApplication.java: -------------------------------------------------------------------------------- 1 | package com.zufar.requestsystem; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.context.annotation.Bean; 6 | import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; 7 | 8 | @SpringBootApplication 9 | public class RequestSystemApplication { 10 | 11 | public static void main(String[] args) { 12 | SpringApplication.run(RequestSystemApplication.class, args); 13 | } 14 | 15 | @Bean 16 | public BCryptPasswordEncoder getEncoder() { 17 | return new BCryptPasswordEncoder(); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/resources/application.yaml: -------------------------------------------------------------------------------- 1 | spring: 2 | freemarker: 3 | template-loader-path: classpath:/templates 4 | suffix: .ftl 5 | datasource: 6 | url: 'jdbc:postgresql://localhost:5432/requestsystem' 7 | username: 'Zufar' 8 | password: 'zufar' 9 | driver-class-name: org.postgresql.Driver 10 | hikari: 11 | connectionTimeout: 20000 12 | maximumPoolSize: 5 13 | jpa: 14 | hibernate: 15 | ddl-auto: update 16 | properties: 17 | hibernate: 18 | dialect: 'org.hibernate.dialect.PostgreSQLDialect' 19 | security: 20 | user: 21 | name: zufar 22 | password: zufar 23 | roles: admin 24 | banner: 25 | location: 'classpath:/banner.txt' -------------------------------------------------------------------------------- /src/main/resources/banner.txt: -------------------------------------------------------------------------------- 1 | _____ _ _____ _ 2 | | __ \ | | / ____| | | 3 | | |__) | ___ __ _ _ _ ___ ___ | |_ | (___ _ _ ___ | |_ ___ _ __ ___ 4 | | _ / / _ \ / _` | | | | | / _ \ / __| | __| \___ \ | | | | / __| | __| / _ \ | '_ ` _ \ 5 | | | \ \ | __/ | (_| | | |_| | | __/ \__ \ | |_ ____) | | |_| | \__ \ | |_ | __/ | | | | | | 6 | |_| \_\ \___| \__, | \__,_| \___| |___/ \__| |_____/ \__, | |___/ \__| \___| |_| |_| |_| 7 | | | __/ | 8 | |_| |___/ -------------------------------------------------------------------------------- /src/main/java/com/zufar/requestsystem/exception/UserNotFoundException.java: -------------------------------------------------------------------------------- 1 | package com.zufar.requestsystem.exception; 2 | 3 | import org.springframework.http.HttpStatus; 4 | import org.springframework.web.bind.annotation.ResponseStatus; 5 | 6 | @ResponseStatus(value = HttpStatus.NOT_FOUND) 7 | public class UserNotFoundException extends RuntimeException { 8 | 9 | public UserNotFoundException() { 10 | super(); 11 | } 12 | 13 | public UserNotFoundException(String message, Throwable cause) { 14 | super(message, cause); 15 | } 16 | 17 | public UserNotFoundException(String message) { 18 | super(message); 19 | } 20 | 21 | public UserNotFoundException(Throwable cause) { 22 | super(cause); 23 | } 24 | } -------------------------------------------------------------------------------- /src/main/java/com/zufar/requestsystem/exception/RequestNotFoundException.java: -------------------------------------------------------------------------------- 1 | package com.zufar.requestsystem.exception; 2 | 3 | import org.springframework.http.HttpStatus; 4 | import org.springframework.web.bind.annotation.ResponseStatus; 5 | 6 | @ResponseStatus(value = HttpStatus.NOT_FOUND) 7 | public class RequestNotFoundException extends RuntimeException { 8 | 9 | public RequestNotFoundException() { 10 | super(); 11 | } 12 | 13 | public RequestNotFoundException(String message, Throwable cause) { 14 | super(message, cause); 15 | } 16 | 17 | public RequestNotFoundException(String message) { 18 | super(message); 19 | } 20 | 21 | public RequestNotFoundException(Throwable cause) { 22 | super(cause); 23 | } 24 | } -------------------------------------------------------------------------------- /src/main/java/com/zufar/requestsystem/dto/UserDTO.java: -------------------------------------------------------------------------------- 1 | package com.zufar.requestsystem.dto; 2 | 3 | import com.zufar.requestsystem.entity.Role; 4 | 5 | import lombok.Setter; 6 | import lombok.Getter; 7 | import lombok.AllArgsConstructor; 8 | import lombok.EqualsAndHashCode; 9 | import lombok.NoArgsConstructor; 10 | import lombok.ToString; 11 | 12 | import javax.persistence.Column; 13 | import java.util.Set; 14 | 15 | @Getter 16 | @Setter 17 | @EqualsAndHashCode 18 | @ToString 19 | @AllArgsConstructor 20 | @NoArgsConstructor 21 | public class UserDTO { 22 | 23 | private Long id; 24 | private String firstName; 25 | private String lastName; 26 | private String nickname; 27 | private String login; 28 | private String password; 29 | private Set roles; 30 | } -------------------------------------------------------------------------------- /src/main/java/com/zufar/requestsystem/configuration/CustomUserDetails.java: -------------------------------------------------------------------------------- 1 | package com.zufar.requestsystem.configuration; 2 | 3 | import com.zufar.requestsystem.entity.Role; 4 | import org.springframework.security.core.userdetails.UserDetails; 5 | import java.util.Collection; 6 | 7 | import lombok.AllArgsConstructor; 8 | import lombok.Builder; 9 | import lombok.Data; 10 | import lombok.NoArgsConstructor; 11 | 12 | @Data 13 | @Builder 14 | @NoArgsConstructor 15 | @AllArgsConstructor 16 | public class CustomUserDetails implements UserDetails { 17 | 18 | private String password; 19 | private String username; 20 | private boolean accountNonExpired; 21 | private boolean accountNonLocked; 22 | private boolean credentialsNonExpired; 23 | private boolean enabled; 24 | private Collection authorities; 25 | } 26 | -------------------------------------------------------------------------------- /src/main/resources/static/js/script.js: -------------------------------------------------------------------------------- 1 | $(document).ready(function() { 2 | var panelOne = $('.form-panel.two').height(), 3 | panelTwo = $('.form-panel.two')[0].scrollHeight; 4 | 5 | $('.form-panel.two').not('.form-panel.two.active').on('click', function(e) { 6 | e.preventDefault(); 7 | 8 | $('.form-toggle').addClass('visible'); 9 | $('.form-panel.one').addClass('hidden'); 10 | $('.form-panel.two').addClass('active'); 11 | $('.form').animate({ 12 | 'height': panelTwo 13 | }, 200); 14 | }); 15 | 16 | $('.form-toggle').on('click', function(e) { 17 | e.preventDefault(); 18 | $(this).removeClass('visible'); 19 | $('.form-panel.one').removeClass('hidden'); 20 | $('.form-panel.two').removeClass('active'); 21 | $('.form').animate({ 22 | 'height': panelOne 23 | }, 200); 24 | }); 25 | }); -------------------------------------------------------------------------------- /src/main/java/com/zufar/requestsystem/entity/Role.java: -------------------------------------------------------------------------------- 1 | package com.zufar.requestsystem.entity; 2 | 3 | import lombok.Setter; 4 | import lombok.Getter; 5 | import lombok.AllArgsConstructor; 6 | import lombok.EqualsAndHashCode; 7 | import lombok.NoArgsConstructor; 8 | import lombok.ToString; 9 | 10 | import javax.persistence.Entity; 11 | import javax.persistence.Table; 12 | import javax.persistence.Id; 13 | import javax.persistence.GeneratedValue; 14 | import javax.persistence.SequenceGenerator; 15 | import javax.persistence.Column; 16 | import javax.persistence.GenerationType; 17 | 18 | import org.springframework.security.core.GrantedAuthority; 19 | 20 | @Entity 21 | @Getter 22 | @Setter 23 | @EqualsAndHashCode 24 | @ToString 25 | @AllArgsConstructor 26 | @NoArgsConstructor 27 | @Table(name = "roles") 28 | public class Role implements GrantedAuthority { 29 | 30 | @Id 31 | @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "role_sequence") 32 | @SequenceGenerator(name = "role_sequence", sequenceName = "role_seq") 33 | private Long id; 34 | 35 | @Column(name = "name", length = 256, nullable = false, unique = true) 36 | private String name; 37 | 38 | @Override 39 | public String getAuthority() { 40 | return name; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/com/zufar/requestsystem/entity/Request.java: -------------------------------------------------------------------------------- 1 | package com.zufar.requestsystem.entity; 2 | 3 | import lombok.Setter; 4 | import lombok.Getter; 5 | import lombok.AllArgsConstructor; 6 | import lombok.EqualsAndHashCode; 7 | import lombok.NoArgsConstructor; 8 | import lombok.ToString; 9 | 10 | import org.hibernate.annotations.Fetch; 11 | import org.hibernate.annotations.FetchMode; 12 | 13 | import javax.persistence.Entity; 14 | import javax.persistence.Table; 15 | import javax.persistence.Id; 16 | import javax.persistence.GeneratedValue; 17 | import javax.persistence.SequenceGenerator; 18 | import javax.persistence.Column; 19 | import javax.persistence.FetchType; 20 | import javax.persistence.OneToOne; 21 | import javax.persistence.JoinColumn; 22 | import javax.persistence.GenerationType; 23 | 24 | @Entity 25 | @Getter 26 | @Setter 27 | @EqualsAndHashCode 28 | @ToString 29 | @AllArgsConstructor 30 | @NoArgsConstructor 31 | @Table(name = "requests") 32 | public class Request { 33 | 34 | @Id 35 | @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "order_sequence") 36 | @SequenceGenerator(name = "order_sequence", sequenceName = "order_seq") 37 | private Long id; 38 | 39 | @Column(name = "title", length = 256, nullable = false) 40 | private String title; 41 | 42 | @Column(name = "description", length = 256, nullable = false) 43 | private String description; 44 | 45 | @OneToOne(fetch = FetchType.EAGER) 46 | @Fetch(value = FetchMode.JOIN) 47 | @JoinColumn(name = "user_id") 48 | private User user; 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/com/zufar/requestsystem/uicontroller/RequestUIController.java: -------------------------------------------------------------------------------- 1 | package com.zufar.requestsystem.uicontroller; 2 | 3 | import com.zufar.requestsystem.dto.RequestDTO; 4 | import com.zufar.requestsystem.service.RequestService; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.stereotype.Controller; 7 | import org.springframework.ui.ModelMap; 8 | import org.springframework.web.bind.annotation.GetMapping; 9 | import org.springframework.web.bind.annotation.PostMapping; 10 | import org.springframework.web.bind.annotation.RequestParam; 11 | 12 | import java.util.List; 13 | 14 | @Controller 15 | public class RequestUIController { 16 | 17 | private final RequestService requestService; 18 | 19 | @Autowired 20 | public RequestUIController(RequestService requestService) { 21 | this.requestService = requestService; 22 | } 23 | 24 | @GetMapping(value = "/requests") 25 | public String getAllRequests(ModelMap modelMap) { 26 | List requests = requestService.getAll(); 27 | modelMap.addAttribute("requests", requests); 28 | return "requests"; 29 | } 30 | 31 | @PostMapping("/addRequest") 32 | public String addRequest( 33 | @RequestParam("title") String title, 34 | @RequestParam("description") String description, 35 | ModelMap modelMap 36 | ) { 37 | RequestDTO request = requestService.createRequest(title, description); 38 | requestService.save(request); 39 | return "requests"; 40 | } 41 | 42 | 43 | } -------------------------------------------------------------------------------- /src/main/java/com/zufar/requestsystem/uicontroller/UserUIController.java: -------------------------------------------------------------------------------- 1 | package com.zufar.requestsystem.uicontroller; 2 | 3 | import com.zufar.requestsystem.dto.UserDTO; 4 | import com.zufar.requestsystem.service.UserService; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.stereotype.Controller; 7 | import org.springframework.ui.ModelMap; 8 | import org.springframework.web.bind.annotation.GetMapping; 9 | import org.springframework.web.bind.annotation.PostMapping; 10 | import org.springframework.web.bind.annotation.RequestParam; 11 | 12 | import java.util.List; 13 | 14 | @Controller 15 | public class UserUIController { 16 | 17 | private final UserService userService; 18 | 19 | @Autowired 20 | public UserUIController(UserService userService) { 21 | this.userService = userService; 22 | } 23 | 24 | @GetMapping(value = "/users") 25 | public String home(ModelMap modelMap) { 26 | List users = userService.getAll(); 27 | modelMap.addAttribute("users", users); 28 | return "users"; 29 | } 30 | 31 | @PostMapping("/addUser") 32 | public String addUser( 33 | @RequestParam("firstname") String firstName, 34 | @RequestParam("lastname") String lastName, 35 | @RequestParam("nickname") String nickname, 36 | @RequestParam("login") String login, 37 | @RequestParam("password") String password 38 | ) { 39 | UserDTO user = new UserDTO(null, firstName, lastName, nickname, login, password, null); 40 | userService.save(user); 41 | return "users"; 42 | } 43 | 44 | } -------------------------------------------------------------------------------- /src/main/resources/templates/requests.ftl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Requests 8 | 9 | 10 |
11 |
12 |
13 |

New request

14 |
15 |
16 |
17 |
18 | 19 | 20 |
21 |
22 | 23 | 24 |
25 |
26 | 27 |
28 |
29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | <#list requests as request> 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 |
IdTitleDescription
${request.id}${request.title}${request.description}
47 |
48 |
49 |
50 | 51 | 52 | -------------------------------------------------------------------------------- /src/main/java/com/zufar/requestsystem/restcontroller/UserController.java: -------------------------------------------------------------------------------- 1 | package com.zufar.requestsystem.restcontroller; 2 | 3 | import com.zufar.requestsystem.dto.UserDTO; 4 | import com.zufar.requestsystem.service.UserService; 5 | import java.util.Collection; 6 | 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.http.MediaType; 9 | import org.springframework.web.bind.annotation.RestController; 10 | import org.springframework.web.bind.annotation.RequestMapping; 11 | import org.springframework.web.bind.annotation.GetMapping; 12 | import org.springframework.web.bind.annotation.ResponseBody; 13 | import org.springframework.web.bind.annotation.PathVariable; 14 | import org.springframework.web.bind.annotation.DeleteMapping; 15 | import org.springframework.web.bind.annotation.RequestBody; 16 | import org.springframework.web.bind.annotation.PostMapping; 17 | import org.springframework.web.bind.annotation.PutMapping; 18 | 19 | @RestController 20 | @RequestMapping(value = "api/users", produces = {MediaType.APPLICATION_JSON_VALUE}) 21 | public class UserController { 22 | 23 | private final UserService userService; 24 | 25 | @Autowired 26 | public UserController(UserService userService) { 27 | this.userService = userService; 28 | } 29 | 30 | @GetMapping 31 | public @ResponseBody 32 | Collection getAll() { 33 | return this.userService.getAll(); 34 | } 35 | 36 | @GetMapping(value = "/{id}") 37 | public @ResponseBody 38 | UserDTO getById(@PathVariable Long id) { 39 | return this.userService.getById(id); 40 | } 41 | 42 | @DeleteMapping(value = "/{id}") 43 | public void deleteById(@PathVariable Long id) { 44 | this.userService.deleteById(id); 45 | } 46 | 47 | @PostMapping 48 | public @ResponseBody 49 | UserDTO save(@RequestBody UserDTO user) { 50 | return this.userService.save(user); 51 | } 52 | 53 | @PutMapping 54 | public @ResponseBody 55 | UserDTO update(@RequestBody UserDTO user) { 56 | return this.userService.update(user); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/com/zufar/requestsystem/entity/User.java: -------------------------------------------------------------------------------- 1 | package com.zufar.requestsystem.entity; 2 | 3 | 4 | import lombok.Setter; 5 | import lombok.Getter; 6 | import lombok.AllArgsConstructor; 7 | import lombok.EqualsAndHashCode; 8 | import lombok.NoArgsConstructor; 9 | import lombok.ToString; 10 | 11 | import org.hibernate.annotations.Fetch; 12 | import org.hibernate.annotations.FetchMode; 13 | 14 | import javax.persistence.Entity; 15 | import javax.persistence.Table; 16 | import javax.persistence.Id; 17 | import javax.persistence.GeneratedValue; 18 | import javax.persistence.OneToMany; 19 | import javax.persistence.JoinTable; 20 | import javax.persistence.JoinColumn; 21 | import javax.persistence.FetchType; 22 | import javax.persistence.SequenceGenerator; 23 | import javax.persistence.Column; 24 | import javax.persistence.CascadeType; 25 | import javax.persistence.GenerationType; 26 | 27 | import java.util.Set; 28 | 29 | @Entity 30 | @Getter 31 | @Setter 32 | @EqualsAndHashCode 33 | @ToString 34 | @AllArgsConstructor 35 | @NoArgsConstructor 36 | @Table(name = "users") 37 | public class User { 38 | 39 | @Id 40 | @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "user_sequence") 41 | @SequenceGenerator(name = "user_sequence", sequenceName = "user_seq") 42 | private Long id; 43 | 44 | @Column(name = "firstname", length = 256, nullable = false) 45 | private String firstName; 46 | 47 | @Column(name = "lastname", length = 256, nullable = false) 48 | private String lastName; 49 | 50 | @Column(name = "nickname", length = 256, nullable = false, unique = true) 51 | private String nickname; 52 | 53 | @Column(name = "login", length = 256, nullable = false, unique = true) 54 | private String login; 55 | 56 | @Column(name = "password", length = 256, nullable = false) 57 | private String password; 58 | 59 | @OneToMany(fetch = FetchType.EAGER, cascade = {CascadeType.ALL}) 60 | @Fetch(FetchMode.JOIN) 61 | @JoinTable(name = "user_roles", 62 | joinColumns = {@JoinColumn(name = "user_id")}, 63 | inverseJoinColumns = {@JoinColumn(name = "role_id")}) 64 | private Set roles; 65 | } -------------------------------------------------------------------------------- /src/main/java/com/zufar/requestsystem/restcontroller/RequestController.java: -------------------------------------------------------------------------------- 1 | package com.zufar.requestsystem.restcontroller; 2 | 3 | import com.zufar.requestsystem.dto.RequestDTO; 4 | import com.zufar.requestsystem.service.RequestService; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.http.MediaType; 7 | import org.springframework.web.bind.annotation.RestController; 8 | import org.springframework.web.bind.annotation.RequestMapping; 9 | import org.springframework.web.bind.annotation.GetMapping; 10 | import org.springframework.web.bind.annotation.ResponseBody; 11 | import org.springframework.web.bind.annotation.PathVariable; 12 | import org.springframework.web.bind.annotation.DeleteMapping; 13 | import org.springframework.web.bind.annotation.RequestBody; 14 | import org.springframework.web.bind.annotation.PostMapping; 15 | import org.springframework.web.bind.annotation.PutMapping; 16 | 17 | import java.util.Collection; 18 | 19 | @RestController 20 | @RequestMapping(value = "api/requests", produces = {MediaType.APPLICATION_JSON_VALUE}) 21 | public class RequestController { 22 | 23 | private final RequestService requestService; 24 | 25 | @Autowired 26 | public RequestController(RequestService requestService) { 27 | this.requestService = requestService; 28 | } 29 | 30 | @GetMapping 31 | public @ResponseBody 32 | Collection getAll() { 33 | return this.requestService.getAll(); 34 | } 35 | 36 | @GetMapping(value = "/{id}") 37 | public @ResponseBody 38 | RequestDTO getById(@PathVariable Long id) { 39 | return this.requestService.getById(id); 40 | } 41 | 42 | @DeleteMapping(value = "/{id}") 43 | public void deleteById(@PathVariable Long id) { 44 | this.requestService.deleteById(id); 45 | } 46 | 47 | @PostMapping 48 | public @ResponseBody 49 | RequestDTO save(@RequestBody RequestDTO order) { 50 | return this.requestService.save(order); 51 | } 52 | 53 | @PutMapping 54 | public @ResponseBody 55 | RequestDTO update(@RequestBody RequestDTO order) { 56 | return this.requestService.update(order); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/main/resources/templates/users.ftl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Login Form - Modal 8 | 9 | 10 | 11 |
12 |
13 |
14 |

Sign up

15 |
16 |
17 |
18 |
19 | 20 | 21 |
22 |
23 | 24 | 25 |
26 |
27 | 28 | 29 |
30 |
31 | 32 | 33 |
34 |
35 | 36 | 37 |
38 |
39 | 40 |
41 |
42 |
43 |
44 |
45 |
46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | <#list users as user> 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 |
IdFirst nameLast nameNicknameLogin
${user.id}${user.firstName}${user.lastName}${user.nickname}${user.login}
65 | 66 |
67 | 68 | 69 | -------------------------------------------------------------------------------- /src/main/java/com/zufar/requestsystem/configuration/SecurityConfig.java: -------------------------------------------------------------------------------- 1 | package com.zufar.requestsystem.configuration; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.http.HttpMethod; 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.util.matcher.AntPathRequestMatcher; 12 | 13 | @Configuration 14 | @EnableWebSecurity 15 | public class SecurityConfig extends WebSecurityConfigurerAdapter { 16 | 17 | private final PasswordEncoder passwordEncoder; 18 | private final CustomUserDetailsService userDetailsService; 19 | 20 | public SecurityConfig(PasswordEncoder passwordEncoder, 21 | CustomUserDetailsService userDetailsService) { 22 | this.passwordEncoder = passwordEncoder; 23 | this.userDetailsService = userDetailsService; 24 | } 25 | 26 | @Autowired 27 | public void configureUserDetails(AuthenticationManagerBuilder auth) throws Exception { 28 | auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder); 29 | } 30 | 31 | @Override 32 | protected void configure(HttpSecurity http) throws Exception { 33 | http 34 | .httpBasic() 35 | .and() 36 | .authorizeRequests() 37 | .antMatchers(HttpMethod.GET,"requests", "users", "api/requests/*", "api/users/*").access("hasAnyRole('ADMIN_ROLE', 'USER_ROLE')") 38 | .antMatchers(HttpMethod.POST, "addRequest", "addUser", "api/requests/*", "api/users/*").access("hasAnyRole('ADMIN_ROLE', 'USER_ROLE')") 39 | .antMatchers(HttpMethod.PUT, "api/requests/*", "api/users/*").access("hasRole('ADMIN_ROLE')") 40 | .antMatchers(HttpMethod.DELETE, "api/requests/", "api/users/").access("hasRole('ADMIN_ROLE')") 41 | .anyRequest().authenticated() 42 | .and() 43 | .formLogin().disable() 44 | .csrf().disable() 45 | .logout().logoutRequestMatcher(new AntPathRequestMatcher("/logout")).permitAll(); 46 | } 47 | } -------------------------------------------------------------------------------- /src/main/java/com/zufar/requestsystem/configuration/CustomUserDetailsService.java: -------------------------------------------------------------------------------- 1 | package com.zufar.requestsystem.configuration; 2 | 3 | 4 | import com.zufar.requestsystem.dto.UserDTO; 5 | import com.zufar.requestsystem.exception.UserNotFoundException; 6 | import com.zufar.requestsystem.service.UserService; 7 | import org.apache.logging.log4j.LogManager; 8 | import org.apache.logging.log4j.Logger; 9 | 10 | import org.springframework.beans.factory.annotation.Autowired; 11 | import org.springframework.security.core.context.SecurityContextHolder; 12 | import org.springframework.security.core.userdetails.UserDetails; 13 | import org.springframework.security.core.userdetails.UserDetailsService; 14 | import org.springframework.security.core.userdetails.UsernameNotFoundException; 15 | import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; 16 | import org.springframework.stereotype.Service; 17 | import org.springframework.transaction.annotation.Transactional; 18 | 19 | @Service 20 | public class CustomUserDetailsService implements UserDetailsService { 21 | 22 | private static final Logger LOGGER = LogManager.getLogger(CustomUserDetailsService.class); 23 | 24 | private final UserService userService; 25 | private final BCryptPasswordEncoder passwordEncoder; 26 | 27 | @Autowired 28 | public CustomUserDetailsService(UserService userService, BCryptPasswordEncoder passwordEncoder) { 29 | this.userService = userService; 30 | this.passwordEncoder = passwordEncoder; 31 | } 32 | 33 | @Override 34 | @Transactional(readOnly = true) 35 | public UserDetails loadUserByUsername(String login) throws UsernameNotFoundException { 36 | final UserDTO user; 37 | try { 38 | user = userService.getByLogin(login); 39 | } catch (Exception exc) { 40 | final String errorMessage = "Loading user details is impossible."; 41 | LOGGER.error(exc.getMessage() + errorMessage, exc); 42 | throw new UsernameNotFoundException(errorMessage, exc); 43 | } 44 | return CustomUserDetails.builder() 45 | .username(user.getLogin()) 46 | .password(passwordEncoder.encode(user.getPassword())) 47 | .authorities(user.getRoles()) 48 | .credentialsNonExpired(true) 49 | .accountNonExpired(true) 50 | .accountNonLocked(true) 51 | .enabled(true) 52 | .build(); 53 | } 54 | 55 | public UserDTO getCurrentUser() { 56 | Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal(); 57 | String username; 58 | if (principal instanceof UserDetails) { 59 | username = ((UserDetails) principal).getUsername(); 60 | } else { 61 | username = principal.toString(); 62 | } 63 | UserDTO user = userService.getByLogin(username); 64 | if (user == null) throw new UserNotFoundException(); 65 | return user; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | 7 | com.zufar 8 | requestsystem 9 | 0.0.1-SNAPSHOT 10 | jar 11 | RequestSystem 12 | System for working with requests for maintenance, repair of PC. 13 | 14 | 15 | 16 | Zufar Sunagatov 17 | zufar.sunagatov@gmail.com 18 | 19 | architect 20 | developer 21 | tester 22 | 23 | Samara (UTC+4:00) 24 | 25 | 26 | 27 | 28 | 1.8 29 | UTF-8 30 | 1.8 31 | 32 | 33 | 34 | org.springframework.boot 35 | spring-boot-starter-parent 36 | 2.2.5.RELEASE 37 | 38 | 39 | 40 | 41 | 42 | org.springframework.boot 43 | spring-boot-starter-web 44 | 45 | 46 | org.springframework.boot 47 | spring-boot-starter-data-jpa 48 | 49 | 50 | org.postgresql 51 | postgresql 52 | 53 | 54 | org.springframework.boot 55 | spring-boot-starter-freemarker 56 | 57 | 58 | org.springframework.boot 59 | spring-boot-starter-security 60 | 61 | 62 | org.projectlombok 63 | lombok 64 | true 65 | 66 | 67 | org.springframework.boot 68 | spring-boot-starter-test 69 | test 70 | 71 | 72 | org.junit.vintage 73 | junit-vintage-engine 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | org.springframework.boot 83 | spring-boot-maven-plugin 84 | 85 | 86 | 87 | 88 | 89 | -------------------------------------------------------------------------------- /script.sql: -------------------------------------------------------------------------------- 1 | -- Database: requestsystem 2 | 3 | -- DROP DATABASE requestsystem; 4 | 5 | CREATE DATABASE requestsystem 6 | WITH 7 | OWNER = "Zufar" 8 | ENCODING = 'UTF8' 9 | LC_COLLATE = 'Russian_Russia.1252' 10 | LC_CTYPE = 'Russian_Russia.1252' 11 | TABLESPACE = pg_default 12 | CONNECTION LIMIT = -1; 13 | 14 | -- SCHEMA: public 15 | 16 | -- DROP SCHEMA public ; 17 | 18 | CREATE SCHEMA public 19 | AUTHORIZATION postgres; 20 | 21 | COMMENT ON SCHEMA public 22 | IS 'standard public schema'; 23 | 24 | GRANT ALL ON SCHEMA public TO PUBLIC; 25 | 26 | GRANT ALL ON SCHEMA public TO postgres; 27 | 28 | 29 | -- SEQUENCE: public.order_seq 30 | 31 | -- DROP SEQUENCE public.order_seq; 32 | 33 | CREATE SEQUENCE public.order_seq 34 | INCREMENT 50 35 | START 101 36 | MINVALUE 1 37 | MAXVALUE 9223372036854775807 38 | CACHE 1; 39 | 40 | ALTER SEQUENCE public.order_seq 41 | OWNER TO "Zufar"; 42 | 43 | -- SEQUENCE: public.role_seq 44 | 45 | -- DROP SEQUENCE public.role_seq; 46 | 47 | CREATE SEQUENCE public.role_seq 48 | INCREMENT 50 49 | START 1 50 | MINVALUE 1 51 | MAXVALUE 9223372036854775807 52 | CACHE 1; 53 | 54 | ALTER SEQUENCE public.role_seq 55 | OWNER TO "Zufar"; 56 | 57 | -- SEQUENCE: public.user_seq 58 | 59 | -- DROP SEQUENCE public.user_seq; 60 | 61 | CREATE SEQUENCE public.user_seq 62 | INCREMENT 50 63 | START 101 64 | MINVALUE 1 65 | MAXVALUE 9223372036854775807 66 | CACHE 1; 67 | 68 | ALTER SEQUENCE public.user_seq 69 | OWNER TO "Zufar"; 70 | 71 | -- Table: public.orders 72 | 73 | -- DROP TABLE public.orders; 74 | 75 | CREATE TABLE public.orders 76 | ( 77 | id bigint NOT NULL, 78 | title character varying(256) COLLATE pg_catalog."default" NOT NULL, 79 | user_id bigint, 80 | description character varying(256) COLLATE pg_catalog."default" NOT NULL, 81 | CONSTRAINT orders_pkey PRIMARY KEY (id), 82 | CONSTRAINT fk32ql8ubntj5uh44ph9659tiih FOREIGN KEY (user_id) 83 | REFERENCES public.users (id) MATCH SIMPLE 84 | ON UPDATE NO ACTION 85 | ON DELETE NO ACTION 86 | ) 87 | 88 | TABLESPACE pg_default; 89 | 90 | ALTER TABLE public.orders 91 | OWNER to "Zufar"; 92 | 93 | -- Table: public.roles 94 | 95 | -- DROP TABLE public.roles; 96 | 97 | CREATE TABLE public.roles 98 | ( 99 | id bigint NOT NULL, 100 | name character varying(256) COLLATE pg_catalog."default" NOT NULL, 101 | CONSTRAINT roles_pkey PRIMARY KEY (id), 102 | CONSTRAINT uk_ofx66keruapi6vyqpv6f2or37 UNIQUE (name) 103 | ) 104 | 105 | TABLESPACE pg_default; 106 | 107 | ALTER TABLE public.roles 108 | OWNER to "Zufar"; 109 | 110 | -- Table: public.user_roles 111 | 112 | -- DROP TABLE public.user_roles; 113 | 114 | CREATE TABLE public.user_roles 115 | ( 116 | user_id bigint NOT NULL, 117 | role_id bigint NOT NULL, 118 | CONSTRAINT user_roles_pkey PRIMARY KEY (user_id, role_id), 119 | CONSTRAINT uk_5q4rc4fh1on6567qk69uesvyf UNIQUE (role_id), 120 | CONSTRAINT fkh8ciramu9cc9q3qcqiv4ue8a6 FOREIGN KEY (role_id) 121 | REFERENCES public.roles (id) MATCH SIMPLE 122 | ON UPDATE NO ACTION 123 | ON DELETE NO ACTION, 124 | CONSTRAINT fkhfh9dx7w3ubf1co1vdev94g3f FOREIGN KEY (user_id) 125 | REFERENCES public.users (id) MATCH SIMPLE 126 | ON UPDATE NO ACTION 127 | ON DELETE NO ACTION 128 | ) 129 | 130 | TABLESPACE pg_default; 131 | 132 | ALTER TABLE public.user_roles 133 | OWNER to "Zufar"; 134 | 135 | 136 | -- Table: public.users 137 | 138 | -- DROP TABLE public.users; 139 | 140 | CREATE TABLE public.users 141 | ( 142 | id bigint NOT NULL, 143 | firstname character varying(256) COLLATE pg_catalog."default" NOT NULL, 144 | lastname character varying(256) COLLATE pg_catalog."default" NOT NULL, 145 | login character varying(256) COLLATE pg_catalog."default" NOT NULL, 146 | nickname character varying(256) COLLATE pg_catalog."default" NOT NULL, 147 | password character varying(256) COLLATE pg_catalog."default" NOT NULL, 148 | CONSTRAINT users_pkey PRIMARY KEY (id), 149 | CONSTRAINT uk_2ty1xmrrgtn89xt7kyxx6ta7h UNIQUE (nickname), 150 | CONSTRAINT uk_ow0gan20590jrb00upg3va2fn UNIQUE (login) 151 | ) 152 | 153 | TABLESPACE pg_default; 154 | 155 | ALTER TABLE public.users 156 | OWNER to "Zufar"; -------------------------------------------------------------------------------- /src/main/java/com/zufar/requestsystem/service/UserService.java: -------------------------------------------------------------------------------- 1 | package com.zufar.requestsystem.service; 2 | 3 | import com.zufar.requestsystem.dto.UserDTO; 4 | import com.zufar.requestsystem.entity.Role; 5 | import com.zufar.requestsystem.entity.User; 6 | import com.zufar.requestsystem.exception.UserNotFoundException; 7 | import com.zufar.requestsystem.repository.RoleRepository; 8 | import com.zufar.requestsystem.repository.UserRepository; 9 | 10 | import org.apache.logging.log4j.LogManager; 11 | import org.apache.logging.log4j.Logger; 12 | 13 | import org.springframework.beans.factory.annotation.Autowired; 14 | import org.springframework.stereotype.Service; 15 | import org.springframework.transaction.annotation.Transactional; 16 | 17 | import java.util.*; 18 | import java.util.stream.Collectors; 19 | 20 | @Service 21 | @Transactional 22 | public class UserService { 23 | 24 | private static final Logger LOGGER = LogManager.getLogger(UserService.class); 25 | private final UserRepository userRepository; 26 | private final RoleRepository roleRepository; 27 | 28 | 29 | @Autowired 30 | public UserService(UserRepository userRepository, RoleRepository roleRepository) { 31 | this.userRepository = userRepository; 32 | this.roleRepository = roleRepository; 33 | } 34 | 35 | public List getAll() { 36 | return ((List) this.userRepository.findAll()) 37 | .stream() 38 | .map(UserService::convertToUserDTO) 39 | .collect(Collectors.toList()); 40 | } 41 | 42 | public UserDTO getById(Long id) { 43 | User userEntity = this.userRepository.findById(id).orElseThrow(() -> { 44 | final String errorMessage = "The user with id = " + id + " not found."; 45 | UserNotFoundException userNotFoundException = new UserNotFoundException(errorMessage); 46 | LOGGER.error(errorMessage, userNotFoundException); 47 | return userNotFoundException; 48 | }); 49 | return UserService.convertToUserDTO(userEntity); 50 | } 51 | 52 | public UserDTO getByLogin(String login) { 53 | User userEntity = this.userRepository.findByLogin(login).orElseThrow(() -> { 54 | final String errorMessage = "The user with login = " + login + " not found."; 55 | UserNotFoundException userNotFoundException = new UserNotFoundException(errorMessage); 56 | LOGGER.error(errorMessage, userNotFoundException); 57 | return userNotFoundException; 58 | }); 59 | return UserService.convertToUserDTO(userEntity); 60 | } 61 | 62 | public UserDTO save(UserDTO user) { 63 | User userEntity = UserService.convertToUser(user); 64 | Set roles = new HashSet<>(); 65 | userEntity.setRoles(roles); 66 | roles.add(roleRepository.findById(2L).orElse(null)); 67 | userEntity = this.userRepository.save(userEntity); 68 | return UserService.convertToUserDTO(userEntity); 69 | } 70 | 71 | public UserDTO update(UserDTO user) { 72 | this.isExists(user.getId()); 73 | User userEntity = UserService.convertToUser(user); 74 | userEntity = this.userRepository.save(userEntity); 75 | return UserService.convertToUserDTO(userEntity); 76 | } 77 | 78 | public void deleteById(Long id) { 79 | this.isExists(id); 80 | this.userRepository.deleteById(id); 81 | } 82 | 83 | public Boolean isExists(Long id) { 84 | if (!this.userRepository.existsById(id)) { 85 | final String errorMessage = "The user with id = " + id + " not found."; 86 | UserNotFoundException userNotFoundException = new UserNotFoundException(errorMessage); 87 | LOGGER.error(errorMessage, userNotFoundException); 88 | throw userNotFoundException; 89 | } 90 | return true; 91 | } 92 | 93 | public static User convertToUser(UserDTO user) { 94 | Objects.requireNonNull(user, "There is no user to convert."); 95 | return new User( 96 | user.getId(), 97 | user.getFirstName(), 98 | user.getLastName(), 99 | user.getNickname(), 100 | user.getLogin(), 101 | user.getPassword(), 102 | user.getRoles()); 103 | } 104 | 105 | public static UserDTO convertToUserDTO(User user) { 106 | Objects.requireNonNull(user, "There is no user to convert."); 107 | return new UserDTO( 108 | user.getId(), 109 | user.getFirstName(), 110 | user.getLastName(), 111 | user.getNickname(), 112 | user.getLogin(), 113 | user.getPassword(), 114 | user.getRoles()); 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /src/main/java/com/zufar/requestsystem/service/RequestService.java: -------------------------------------------------------------------------------- 1 | package com.zufar.requestsystem.service; 2 | 3 | import com.zufar.requestsystem.configuration.CustomUserDetailsService; 4 | import com.zufar.requestsystem.dto.RequestDTO; 5 | import com.zufar.requestsystem.dto.UserDTO; 6 | import com.zufar.requestsystem.entity.Request; 7 | import com.zufar.requestsystem.entity.User; 8 | import com.zufar.requestsystem.exception.RequestNotFoundException; 9 | import com.zufar.requestsystem.repository.RequestRepository; 10 | 11 | import org.apache.logging.log4j.LogManager; 12 | import org.apache.logging.log4j.Logger; 13 | import org.springframework.beans.factory.annotation.Autowired; 14 | import org.springframework.stereotype.Service; 15 | import org.springframework.transaction.annotation.Transactional; 16 | 17 | import java.util.List; 18 | import java.util.Objects; 19 | import java.util.stream.Collectors; 20 | 21 | @Service 22 | @Transactional 23 | public class RequestService { 24 | 25 | private static final Logger LOGGER = LogManager.getLogger(RequestService.class); 26 | private final RequestRepository requestRepository; 27 | private final CustomUserDetailsService userDetailsService; 28 | 29 | @Autowired 30 | public RequestService(RequestRepository requestRepository, CustomUserDetailsService userDetailsService) { 31 | this.requestRepository = requestRepository; 32 | this.userDetailsService = userDetailsService; 33 | } 34 | 35 | public List getAll() { 36 | return ((List) this.requestRepository.findAll()) 37 | .stream() 38 | .map(RequestService::convertToRequestDTO) 39 | .collect(Collectors.toList()); 40 | } 41 | 42 | public RequestDTO getById(Long id) { 43 | Request statusEntity = this.requestRepository.findById(id).orElseThrow(() -> { 44 | String errorMessage = "Getting an request with id=" + id + " is impossible. There is no a sort attribute."; 45 | RequestNotFoundException requestNotFoundException = new RequestNotFoundException(errorMessage); 46 | LOGGER.error(errorMessage, requestNotFoundException); 47 | return requestNotFoundException; 48 | }); 49 | return RequestService.convertToRequestDTO(statusEntity); 50 | } 51 | 52 | public RequestDTO save(RequestDTO request) { 53 | Request requestEntity = RequestService.convertToRequest(request); 54 | requestEntity = this.requestRepository.save(requestEntity); 55 | return RequestService.convertToRequestDTO(requestEntity); 56 | } 57 | 58 | public RequestDTO update(RequestDTO request) { 59 | this.isExists(request.getId()); 60 | Request requestEntity = RequestService.convertToRequest(request); 61 | requestEntity = this.requestRepository.save(requestEntity); 62 | return RequestService.convertToRequestDTO(requestEntity); 63 | } 64 | 65 | public void deleteById(Long id) { 66 | this.isExists(id); 67 | this.requestRepository.deleteById(id); 68 | } 69 | 70 | public Boolean isExists(Long id) { 71 | if (!this.requestRepository.existsById(id)) { 72 | String errorMessage = "The request with id = " + id + " not found."; 73 | RequestNotFoundException requestNotFoundException = new RequestNotFoundException(errorMessage); 74 | LOGGER.error(errorMessage, requestNotFoundException); 75 | throw requestNotFoundException; 76 | } 77 | return true; 78 | } 79 | 80 | public static RequestDTO convertToRequestDTO(Request request) { 81 | Objects.requireNonNull(request, "There is no request to convert."); 82 | UserDTO user = UserService.convertToUserDTO(request.getUser()); 83 | return new RequestDTO( 84 | request.getId(), 85 | request.getTitle(), 86 | request.getDescription(), 87 | user 88 | ); 89 | } 90 | 91 | public static Request convertToRequest(RequestDTO request) { 92 | Objects.requireNonNull(request, "There is no request to convert."); 93 | User user = UserService.convertToUser(request.getUser()); 94 | return new Request( 95 | request.getId(), 96 | request.getTitle(), 97 | request.getDescription(), 98 | user 99 | ); 100 | } 101 | 102 | public RequestDTO createRequest(String title, String description) { 103 | RequestDTO request = new RequestDTO(); 104 | request.setId(null); 105 | request.setTitle(title); 106 | request.setDescription(description); 107 | UserDTO currentUser = userDetailsService.getCurrentUser(); 108 | request.setUser(currentUser); 109 | return request; 110 | } 111 | 112 | public RequestDTO createRequest(String title, String description, UserDTO user) { 113 | RequestDTO request = new RequestDTO(); 114 | request.setId(null); 115 | request.setTitle(title); 116 | request.setDescription(description); 117 | request.setUser(user); 118 | return request; 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /src/main/resources/static/css/mainStyle.css: -------------------------------------------------------------------------------- 1 | html { 2 | width: 100%; 3 | height: 100%; 4 | } 5 | 6 | body { 7 | background: -webkit-linear-gradient(45deg, rgba(66, 183, 245, 0.8) 0%, rgba(66, 245, 189, 0.4) 100%); 8 | background: linear-gradient(45deg, rgba(66, 183, 245, 0.8) 0%, rgba(66, 245, 189, 0.4) 100%); 9 | color: rgba(0, 0, 0, 0.6); 10 | font-family: "Roboto", sans-serif; 11 | font-size: 14px; 12 | line-height: 1.6em; 13 | -webkit-font-smoothing: antialiased; 14 | -moz-osx-font-smoothing: grayscale; 15 | } 16 | 17 | .overlay, .form-panel.one:before { 18 | position: absolute; 19 | top: 0; 20 | left: 0; 21 | display: none; 22 | background: rgba(0, 0, 0, 0.8); 23 | width: 100%; 24 | height: 100%; 25 | } 26 | 27 | .form { 28 | z-index: 15; 29 | position: relative; 30 | background: #FFFFFF; 31 | width: 600px; 32 | border-radius: 4px; 33 | box-shadow: 0 0 30px rgba(0, 0, 0, 0.1); 34 | box-sizing: border-box; 35 | margin: 100px auto 10px; 36 | overflow: hidden; 37 | } 38 | .form-toggle { 39 | z-index: 10; 40 | position: absolute; 41 | top: 60px; 42 | right: 60px; 43 | background: #FFFFFF; 44 | width: 60px; 45 | height: 60px; 46 | border-radius: 100%; 47 | -webkit-transform-origin: center; 48 | transform-origin: center; 49 | -webkit-transform: translate(0, -25%) scale(0); 50 | transform: translate(0, -25%) scale(0); 51 | opacity: 0; 52 | cursor: pointer; 53 | -webkit-transition: all 0.3s ease; 54 | transition: all 0.3s ease; 55 | } 56 | .form-toggle:before, .form-toggle:after { 57 | content: ''; 58 | display: block; 59 | position: absolute; 60 | top: 50%; 61 | left: 50%; 62 | width: 30px; 63 | height: 4px; 64 | background: #4285F4; 65 | -webkit-transform: translate(-50%, -50%); 66 | transform: translate(-50%, -50%); 67 | } 68 | .form-toggle:before { 69 | -webkit-transform: translate(-50%, -50%) rotate(45deg); 70 | transform: translate(-50%, -50%) rotate(45deg); 71 | } 72 | .form-toggle:after { 73 | -webkit-transform: translate(-50%, -50%) rotate(-45deg); 74 | transform: translate(-50%, -50%) rotate(-45deg); 75 | } 76 | .form-toggle.visible { 77 | -webkit-transform: translate(0, -25%) scale(1); 78 | transform: translate(0, -25%) scale(1); 79 | opacity: 1; 80 | } 81 | .form-group { 82 | display: -webkit-box; 83 | display: -ms-flexbox; 84 | display: flex; 85 | -ms-flex-wrap: wrap; 86 | flex-wrap: wrap; 87 | -webkit-box-pack: justify; 88 | -ms-flex-pack: justify; 89 | justify-content: space-between; 90 | margin: 0 0 20px; 91 | } 92 | .form-group:last-child { 93 | margin: 0; 94 | } 95 | .form-group label { 96 | display: block; 97 | margin: 0 0 10px; 98 | color: rgba(0, 0, 0, 0.6); 99 | font-size: 12px; 100 | font-weight: 500; 101 | line-height: 1; 102 | text-transform: uppercase; 103 | letter-spacing: .2em; 104 | } 105 | .two .form-group label { 106 | color: #FFFFFF; 107 | } 108 | .form-group input { 109 | outline: none; 110 | display: block; 111 | background: rgba(0, 0, 0, 0.1); 112 | width: 100%; 113 | border: 0; 114 | border-radius: 4px; 115 | box-sizing: border-box; 116 | padding: 12px 20px; 117 | color: rgba(0, 0, 0, 0.6); 118 | font-family: inherit; 119 | font-size: inherit; 120 | font-weight: 500; 121 | line-height: inherit; 122 | -webkit-transition: 0.3s ease; 123 | transition: 0.3s ease; 124 | } 125 | .form-group input:focus { 126 | color: rgba(0, 0, 0, 0.8); 127 | } 128 | .two .form-group input { 129 | color: #FFFFFF; 130 | } 131 | .two .form-group input:focus { 132 | color: #FFFFFF; 133 | } 134 | .form-group button { 135 | outline: none; 136 | background: #4285F4; 137 | width: 100%; 138 | border: 0; 139 | border-radius: 4px; 140 | padding: 12px 20px; 141 | color: #FFFFFF; 142 | font-family: inherit; 143 | font-size: inherit; 144 | font-weight: 500; 145 | line-height: inherit; 146 | text-transform: uppercase; 147 | cursor: pointer; 148 | } 149 | .two .form-group button { 150 | background: #FFFFFF; 151 | color: #4285F4; 152 | } 153 | .form-group .form-remember { 154 | font-size: 12px; 155 | font-weight: 400; 156 | letter-spacing: 0; 157 | text-transform: none; 158 | } 159 | .form-group .form-remember input[type='checkbox'] { 160 | display: inline-block; 161 | width: auto; 162 | margin: 0 10px 0 0; 163 | } 164 | .form-group .form-recovery { 165 | color: #4285F4; 166 | font-size: 12px; 167 | text-decoration: none; 168 | } 169 | .form-panel { 170 | padding: 60px calc(5% + 60px) 60px 60px; 171 | box-sizing: border-box; 172 | } 173 | .form-panel.one:before { 174 | content: ''; 175 | display: block; 176 | opacity: 0; 177 | visibility: hidden; 178 | -webkit-transition: 0.3s ease; 179 | transition: 0.3s ease; 180 | } 181 | .form-panel.one.hidden:before { 182 | display: block; 183 | opacity: 1; 184 | visibility: visible; 185 | } 186 | .form-panel.two { 187 | z-index: 5; 188 | position: absolute; 189 | top: 0; 190 | left: 95%; 191 | background: #4285F4; 192 | width: 100%; 193 | min-height: 100%; 194 | padding: 60px calc(10% + 60px) 60px 60px; 195 | -webkit-transition: 0.3s ease; 196 | transition: 0.3s ease; 197 | cursor: pointer; 198 | } 199 | .form-panel.two:before, .form-panel.two:after { 200 | content: ''; 201 | display: block; 202 | position: absolute; 203 | top: 60px; 204 | left: 1.5%; 205 | background: rgba(255, 255, 255, 0.2); 206 | height: 30px; 207 | width: 2px; 208 | -webkit-transition: 0.3s ease; 209 | transition: 0.3s ease; 210 | } 211 | .form-panel.two:after { 212 | left: 3%; 213 | } 214 | .form-panel.two:hover { 215 | left: 93%; 216 | box-shadow: 0 0 10px rgba(0, 0, 0, 0.2); 217 | } 218 | .form-panel.two:hover:before, .form-panel.two:hover:after { 219 | opacity: 0; 220 | } 221 | .form-panel.two.active { 222 | left: 10%; 223 | box-shadow: 0 0 10px rgba(0, 0, 0, 0.2); 224 | cursor: default; 225 | } 226 | .form-panel.two.active:before, .form-panel.two.active:after { 227 | opacity: 0; 228 | } 229 | .form-header { 230 | margin: 0 0 40px; 231 | } 232 | .form-header h1 { 233 | padding: 4px 0; 234 | color: #4285F4; 235 | font-size: 24px; 236 | font-weight: 700; 237 | text-transform: uppercase; 238 | } 239 | .two .form-header h1 { 240 | position: relative; 241 | z-index: 40; 242 | color: #FFFFFF; 243 | } 244 | 245 | .pen-footer { 246 | display: -webkit-box; 247 | display: -ms-flexbox; 248 | display: flex; 249 | -webkit-box-orient: horizontal; 250 | -webkit-box-direction: normal; 251 | -ms-flex-direction: row; 252 | flex-direction: row; 253 | -webkit-box-pack: justify; 254 | -ms-flex-pack: justify; 255 | justify-content: space-between; 256 | width: 600px; 257 | margin: 20px auto 100px; 258 | } 259 | .pen-footer a { 260 | color: #FFFFFF; 261 | font-size: 12px; 262 | text-decoration: none; 263 | text-shadow: 1px 2px 0 rgba(0, 0, 0, 0.1); 264 | } 265 | .pen-footer a .material-icons { 266 | width: 12px; 267 | margin: 0 5px; 268 | vertical-align: middle; 269 | font-size: 12px; 270 | } 271 | 272 | .cp-fab { 273 | background: #FFFFFF !important; 274 | color: #4285F4 !important; 275 | } 276 | 277 | body, input { 278 | font-family: Calibri, Arial, serif; 279 | margin: 0; 280 | padding: 0; 281 | } 282 | 283 | #header h2 { 284 | color: white; 285 | background-color: #3275A8; 286 | height: 50px; 287 | padding: 5px 0 0 5px; 288 | font-size: 20px; 289 | } 290 | 291 | .datatable { 292 | margin-top: 15px; 293 | border: 1px solid #eee; 294 | border-collapse: collapse; 295 | width: 400px; 296 | max-width: 100%; 297 | font-family: Calibri, serif; 298 | } 299 | 300 | .datatable th { 301 | padding: 3px; 302 | border: 1px solid #888; 303 | height: 30px; 304 | background-color: #B2D487; 305 | text-align: center; 306 | vertical-align: middle; 307 | color: #444444 308 | } 309 | 310 | .datatable tr { 311 | border: 1px solid #888 312 | } 313 | 314 | .datatable tr.odd { 315 | background-color: #eee 316 | } 317 | 318 | .datatable td { 319 | padding: 2px; 320 | border: 1px solid #888 321 | } 322 | 323 | #content { 324 | padding: 5px; 325 | margin: 5px; 326 | text-align: center 327 | } 328 | 329 | fieldset { 330 | width: 300px; 331 | padding: 5px; 332 | margin-bottom: 0; 333 | } 334 | 335 | legend { 336 | font-weight: bold; 337 | } 338 | --------------------------------------------------------------------------------