diff --git a/src/main/java/ru/redrise/marinesco/ShinyApplicationRunner.java b/src/main/java/ru/redrise/marinesco/ShinyApplicationRunner.java new file mode 100644 index 0000000..406cbfe --- /dev/null +++ b/src/main/java/ru/redrise/marinesco/ShinyApplicationRunner.java @@ -0,0 +1,62 @@ +package ru.redrise.marinesco; + +import java.util.Arrays; +import java.util.List; + +import org.springframework.boot.ApplicationArguments; +import org.springframework.boot.ApplicationRunner; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import lombok.extern.slf4j.Slf4j; +import ru.redrise.marinesco.data.RolesRepository; +import ru.redrise.marinesco.data.UserRepository; +import ru.redrise.marinesco.security.UserRole; + +@Slf4j +@Configuration +public class ShinyApplicationRunner { + private UserRepository users; + private RolesRepository roles; + + public ShinyApplicationRunner(UserRepository users, RolesRepository roles) { + this.users = users; + this.roles = roles; + } + + @Bean + public ApplicationRunner appRunner() { + return args -> { + if (isFirstRun()) { + setRoles(); + setAdmin(args); + } else + log.info("NOT FIRST APPLICATION RUN; DB Already set up"); + }; + } + + private boolean isFirstRun() { + return (roles.count() <= 0); + } + + private void setRoles() { + roles.saveAll(Arrays.asList( + new UserRole(null, "Admin", UserRole.Type.ADMIN), + new UserRole(null, "User", UserRole.Type.USER))); + } + + private void setAdmin(ApplicationArguments args) { + List login = args.getOptionValues("admin_login"); + List password = args.getOptionValues("admin_password"); + + List adminRoleOnlyAthority = roles.findByType(UserRole.Type.ADMIN); + + if (login == null || login.size() == 0 || password == null || password.size() == 0) { + log.warn("No administrator credentials provided, using defaults:\n * Login: root\n * Password: root\n Expected: --admin_login LOGIN --admin_password PASSWORD "); // TODO: Move into properties i18n + var adminUser = new User("root", "root", "SuperAdmin", adminRoleOnlyAthority); + users.save(adminUser); + return; + } + users.save(new User(login.get(0), password.get(0), "SuperAdmin", adminRoleOnlyAthority)); + } +} \ No newline at end of file diff --git a/src/main/java/ru/redrise/marinesco/User.java b/src/main/java/ru/redrise/marinesco/User.java index 403e3f3..30f49e4 100644 --- a/src/main/java/ru/redrise/marinesco/User.java +++ b/src/main/java/ru/redrise/marinesco/User.java @@ -1,23 +1,25 @@ package ru.redrise.marinesco; -import java.util.Arrays; -import java.util.Collection; +import java.util.ArrayList; +import java.util.List; -import org.springframework.security.core.GrantedAuthority; -import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.userdetails.UserDetails; import jakarta.persistence.Entity; import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; import jakarta.persistence.Id; +import jakarta.persistence.ManyToMany; +import jakarta.persistence.Table; import lombok.AccessLevel; import lombok.Data; import lombok.NoArgsConstructor; import lombok.RequiredArgsConstructor; +import ru.redrise.marinesco.security.UserRole; @Data -@Entity(name = "\"user\"") +@Entity +@Table(name = "\"USER\"") @NoArgsConstructor(access = AccessLevel.PRIVATE, force = true) @RequiredArgsConstructor public class User implements UserDetails{ @@ -32,11 +34,9 @@ public class User implements UserDetails{ private final String password; private final String displayname; - @Override - public Collection getAuthorities() { - return Arrays.asList(new SimpleGrantedAuthority("ROLE_USER")); - } - + @ManyToMany + private final List authorities; + @Override public boolean isAccountNonExpired() { return true; @@ -56,4 +56,8 @@ public class User implements UserDetails{ public boolean isEnabled() { return true; } + + public void setRole(UserRole role){ + this.authorities.add(role); + } } diff --git a/src/main/java/ru/redrise/marinesco/data/RolesRepository.java b/src/main/java/ru/redrise/marinesco/data/RolesRepository.java new file mode 100644 index 0000000..7f5b392 --- /dev/null +++ b/src/main/java/ru/redrise/marinesco/data/RolesRepository.java @@ -0,0 +1,15 @@ +package ru.redrise.marinesco.data; + +import java.util.List; + +import org.springframework.data.repository.CrudRepository; +import org.springframework.stereotype.Repository; + +import ru.redrise.marinesco.security.UserRole; +import ru.redrise.marinesco.security.UserRole.Type; + + +@Repository +public interface RolesRepository extends CrudRepository{ + public List findByType(Type type); +} diff --git a/src/main/java/ru/redrise/marinesco/data/UserRepository.java b/src/main/java/ru/redrise/marinesco/data/UserRepository.java index cd5ace3..fe655b8 100644 --- a/src/main/java/ru/redrise/marinesco/data/UserRepository.java +++ b/src/main/java/ru/redrise/marinesco/data/UserRepository.java @@ -7,5 +7,5 @@ import ru.redrise.marinesco.User; @Repository public interface UserRepository extends CrudRepository{ - User findByUsername(String username); + public User findByUsername(String username); } diff --git a/src/main/java/ru/redrise/marinesco/security/AthorityByIdConverter.java b/src/main/java/ru/redrise/marinesco/security/AthorityByIdConverter.java new file mode 100644 index 0000000..98bd758 --- /dev/null +++ b/src/main/java/ru/redrise/marinesco/security/AthorityByIdConverter.java @@ -0,0 +1,21 @@ +package ru.redrise.marinesco.security; + +import org.springframework.core.convert.converter.Converter; +import org.springframework.stereotype.Component; + +import ru.redrise.marinesco.data.RolesRepository; + +@Component +public class AthorityByIdConverter implements Converter{ + + private RolesRepository rolesRepo; + + public AthorityByIdConverter(RolesRepository rolesRepo){ + this.rolesRepo = rolesRepo; + } + + @Override + public UserRole convert(Long id) { + return rolesRepo.findById(id).orElse(null); + } +} \ No newline at end of file diff --git a/src/main/java/ru/redrise/marinesco/security/RegistrationController.java b/src/main/java/ru/redrise/marinesco/security/RegistrationController.java index 7ffd8c9..8265a6e 100644 --- a/src/main/java/ru/redrise/marinesco/security/RegistrationController.java +++ b/src/main/java/ru/redrise/marinesco/security/RegistrationController.java @@ -6,16 +6,19 @@ import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; +import ru.redrise.marinesco.data.RolesRepository; import ru.redrise.marinesco.data.UserRepository; @Controller @RequestMapping("/register") public class RegistrationController { - private UserRepository userRepo; + private UserRepository userRepo; + private RolesRepository rolesRepo; private PasswordEncoder passwordEncoder; - public RegistrationController(UserRepository userRepo, PasswordEncoder passwordEncoder){ + public RegistrationController(UserRepository userRepo, RolesRepository rolesRepo, PasswordEncoder passwordEncoder){ this.userRepo = userRepo; + this.rolesRepo = rolesRepo; this.passwordEncoder = passwordEncoder; } @@ -26,7 +29,7 @@ public class RegistrationController { @PostMapping public String postMethodName(RegistrationForm registrationForm) { - userRepo.save(registrationForm.toUser(passwordEncoder)); + userRepo.save(registrationForm.toUser(passwordEncoder, rolesRepo)); return "redirect:/login"; } } diff --git a/src/main/java/ru/redrise/marinesco/security/RegistrationForm.java b/src/main/java/ru/redrise/marinesco/security/RegistrationForm.java index 2a07431..65352f2 100644 --- a/src/main/java/ru/redrise/marinesco/security/RegistrationForm.java +++ b/src/main/java/ru/redrise/marinesco/security/RegistrationForm.java @@ -2,20 +2,27 @@ package ru.redrise.marinesco.security; import org.springframework.security.crypto.password.PasswordEncoder; +import jakarta.validation.constraints.NotNull; import lombok.Data; import ru.redrise.marinesco.User; +import ru.redrise.marinesco.data.RolesRepository; @Data public class RegistrationForm { - private String username; + @NotNull + private String username; + @NotNull private String password; + @NotNull private String fullname; + @NotNull private String displayname; - public User toUser(PasswordEncoder passwordEncoder){ + public User toUser(PasswordEncoder passwordEncoder, RolesRepository rolesRepo){ return new User( username, passwordEncoder.encode(password), - displayname); + displayname, + rolesRepo.findByType(UserRole.Type.USER)); } } diff --git a/src/main/java/ru/redrise/marinesco/security/SecurityConfig.java b/src/main/java/ru/redrise/marinesco/security/SecurityConfig.java index 6b683e2..8aefdef 100644 --- a/src/main/java/ru/redrise/marinesco/security/SecurityConfig.java +++ b/src/main/java/ru/redrise/marinesco/security/SecurityConfig.java @@ -1,11 +1,11 @@ package ru.redrise.marinesco.security; -import static org.springframework.security.web.util.matcher.AntPathRequestMatcher.antMatcher; - +import org.springframework.boot.autoconfigure.security.servlet.PathRequest; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.Customizer; +import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity; -import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; @@ -18,7 +18,8 @@ import ru.redrise.marinesco.User; import ru.redrise.marinesco.data.UserRepository; @Configuration -@EnableWebSecurity +//@EnableWebSecurity +@EnableMethodSecurity public class SecurityConfig { @Bean public UserDetailsService userDetailsService(UserRepository repository) { @@ -44,10 +45,30 @@ public class SecurityConfig { public SecurityFilterChain filterChain(HttpSecurity http, MvcRequestMatcher.Builder mvc) throws Exception { return http .authorizeHttpRequests(autorize -> autorize - .requestMatchers(mvc.pattern("/register/**")).hasRole("USER") - //.requestMatchers(antMatcher("/register/**")).hasRole("USER") - .anyRequest().permitAll()) - .formLogin(formLoginConfigurer -> formLoginConfigurer.loginPage("/login")) + .requestMatchers(mvc.pattern("/styles/**")).permitAll() + .requestMatchers(mvc.pattern("/images/*")).permitAll() + .requestMatchers(mvc.pattern("/register")).permitAll() + .requestMatchers(mvc.pattern("/login")).permitAll() + .requestMatchers(PathRequest.toH2Console()).permitAll() + //.requestMatchers(mvc.pattern("/design/**")).hasRole("USER") + .anyRequest().denyAll()) + .formLogin(formLoginConfigurer -> formLoginConfigurer + .loginPage("/login") + .loginProcessingUrl("/auth") + .usernameParameter("login") + .passwordParameter("pwd") + //.defaultSuccessUrl("/", true) + ) +// .formLogin(Customizer.withDefaults()) +//.oauth2Login(c -> c.loginPage("/login")) + .logout(Customizer.withDefaults()) + /* Make temporary access to H2 infrastructure START*/ + .csrf(csrf -> csrf + .ignoringRequestMatchers(PathRequest.toH2Console()) + .disable() + ) + .headers(headers -> headers.frameOptions(frameOptions -> frameOptions.sameOrigin())) + /* Make temporary access to H2 infrastructure END*/ .build(); } } diff --git a/src/main/java/ru/redrise/marinesco/security/UserManagment.java b/src/main/java/ru/redrise/marinesco/security/UserManagment.java new file mode 100644 index 0000000..bb01765 --- /dev/null +++ b/src/main/java/ru/redrise/marinesco/security/UserManagment.java @@ -0,0 +1,16 @@ +package ru.redrise.marinesco.security; + +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; + +@Controller +@RequestMapping("/usersmanagment") +public class UserManagment { + + + @GetMapping + public String getPage(){ + return "/usersmanagment"; + } +} diff --git a/src/main/java/ru/redrise/marinesco/security/UserRole.java b/src/main/java/ru/redrise/marinesco/security/UserRole.java new file mode 100644 index 0000000..40e9f18 --- /dev/null +++ b/src/main/java/ru/redrise/marinesco/security/UserRole.java @@ -0,0 +1,45 @@ +package ru.redrise.marinesco.security; + +import org.springframework.security.core.GrantedAuthority; + +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@Entity +@AllArgsConstructor +@NoArgsConstructor(access=AccessLevel.PRIVATE, force=true) +public class UserRole implements GrantedAuthority{ + private static final long serialVersionUID = 1L; + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private Long id; + private String name; + private Type type; + + @Override + public String getAuthority() { + if (type == null) + throw new UnsupportedOperationException("Unimplemented method 'getAuthority'"); + + switch (type) { + case USER: + return "ROLE_USER"; + case ADMIN: + return "ROLE_ADMIN"; + default: + throw new UnsupportedOperationException("Unimplemented method 'getAuthority'"); + } + } + + public enum Type{ + USER, ADMIN + } +} diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index acc3de2..f9babf2 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -1,6 +1,24 @@ + spring: thymeleaf: cache: false datasource: + driverClassName: org.h2.Driver generate-unique-name: false - name: tacocloud \ No newline at end of file + name: marinesco + url: jdbc:h2:mem:marinesco + username: sa + password: + jpa: + properties: + hibernate: + database-platform: org.hibernate.dialect.H2Dialect + hibernate: + ddl-auto: update + h2: + console: + enabled: true + path: /h2 + settings: + web-allow-others: true + trace: false diff --git a/src/main/resources/static/favicon.ico b/src/main/resources/static/favicon.ico new file mode 100644 index 0000000..48975f4 Binary files /dev/null and b/src/main/resources/static/favicon.ico differ diff --git a/src/main/resources/static/images/logo.svg b/src/main/resources/static/images/logo.svg new file mode 100644 index 0000000..7b90bd4 --- /dev/null +++ b/src/main/resources/static/images/logo.svg @@ -0,0 +1,97 @@ + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/static/styles/TerminusBold.ttf b/src/main/resources/static/styles/TerminusBold.ttf new file mode 100644 index 0000000..9dc2aed Binary files /dev/null and b/src/main/resources/static/styles/TerminusBold.ttf differ diff --git a/src/main/resources/static/styles/styles.css b/src/main/resources/static/styles/styles.css new file mode 100644 index 0000000..fabffdb --- /dev/null +++ b/src/main/resources/static/styles/styles.css @@ -0,0 +1,48 @@ +@font-face{ + font-family: "Terminus"; + src: url('/styles/TerminusBold.ttf'); +} + +body { + margin-top: 0; + margin-bottom: 0; + margin-right: 1%; + margin-left: 1%; + font-family: Terminus; + background-color: #212121; + color: #cfcfcf; +} + +.validationError { + color: red; +} +.header-container { + text-align: left; + position: relative; + color: white; +} +.header-container .header-bar { + position: absolute; + right: 10px; +} + +table, th, td { + border: 1px solid; + border-collapse: collapse; +} + +a { + color: #cfcfcf; + text-align: center; +} +a:link { + color: #cfcfcf; +} + +a:hover { + color: white; +} + +a:visited { + color: #949494; +} \ No newline at end of file diff --git a/src/main/resources/templates/login.html b/src/main/resources/templates/login.html index 9de8ff6..3407fcd 100644 --- a/src/main/resources/templates/login.html +++ b/src/main/resources/templates/login.html @@ -3,10 +3,28 @@ Marinesco + + -

Welcome to LOGIN PAGE

+

FUCKING BRILLIANT LOGIN PAGE

+ - +
+
New here? REGISTER NOW! +
H2 + +
\ No newline at end of file diff --git a/src/main/resources/templates/registration.html b/src/main/resources/templates/registration.html index b681b69..06a9480 100644 --- a/src/main/resources/templates/registration.html +++ b/src/main/resources/templates/registration.html @@ -3,19 +3,23 @@ Marinesco - registration form + +

Register

+
-
+
-
+


+
diff --git a/src/main/resources/templates/root.html b/src/main/resources/templates/root.html index 4e85e2d..df62e2f 100644 --- a/src/main/resources/templates/root.html +++ b/src/main/resources/templates/root.html @@ -3,10 +3,14 @@ Marinesco + +

Welcome to Marinesco

+ +
Login \ No newline at end of file diff --git a/src/main/resources/templates/usersmanagment.html b/src/main/resources/templates/usersmanagment.html new file mode 100644 index 0000000..6203eb5 --- /dev/null +++ b/src/main/resources/templates/usersmanagment.html @@ -0,0 +1,17 @@ + + + + + User managment + + + + + +

User managment

+ +
Log out + + + + \ No newline at end of file diff --git a/target/classes/application.yml b/target/classes/application.yml index acc3de2..f9babf2 100644 --- a/target/classes/application.yml +++ b/target/classes/application.yml @@ -1,6 +1,24 @@ + spring: thymeleaf: cache: false datasource: + driverClassName: org.h2.Driver generate-unique-name: false - name: tacocloud \ No newline at end of file + name: marinesco + url: jdbc:h2:mem:marinesco + username: sa + password: + jpa: + properties: + hibernate: + database-platform: org.hibernate.dialect.H2Dialect + hibernate: + ddl-auto: update + h2: + console: + enabled: true + path: /h2 + settings: + web-allow-others: true + trace: false diff --git a/target/classes/ru/redrise/marinesco/ShinyApplicationRunner.class b/target/classes/ru/redrise/marinesco/ShinyApplicationRunner.class new file mode 100644 index 0000000..4475663 Binary files /dev/null and b/target/classes/ru/redrise/marinesco/ShinyApplicationRunner.class differ diff --git a/target/classes/ru/redrise/marinesco/User.class b/target/classes/ru/redrise/marinesco/User.class index debbd04..8f8f017 100644 Binary files a/target/classes/ru/redrise/marinesco/User.class and b/target/classes/ru/redrise/marinesco/User.class differ diff --git a/target/classes/ru/redrise/marinesco/data/RolesRepository.class b/target/classes/ru/redrise/marinesco/data/RolesRepository.class new file mode 100644 index 0000000..4a241a7 Binary files /dev/null and b/target/classes/ru/redrise/marinesco/data/RolesRepository.class differ diff --git a/target/classes/ru/redrise/marinesco/security/AthorityByIdConverter.class b/target/classes/ru/redrise/marinesco/security/AthorityByIdConverter.class new file mode 100644 index 0000000..91bf99b Binary files /dev/null and b/target/classes/ru/redrise/marinesco/security/AthorityByIdConverter.class differ diff --git a/target/classes/ru/redrise/marinesco/security/RegistrationController.class b/target/classes/ru/redrise/marinesco/security/RegistrationController.class index 26c81aa..dd6cabc 100644 Binary files a/target/classes/ru/redrise/marinesco/security/RegistrationController.class and b/target/classes/ru/redrise/marinesco/security/RegistrationController.class differ diff --git a/target/classes/ru/redrise/marinesco/security/RegistrationForm.class b/target/classes/ru/redrise/marinesco/security/RegistrationForm.class index 0d620a3..d875837 100644 Binary files a/target/classes/ru/redrise/marinesco/security/RegistrationForm.class and b/target/classes/ru/redrise/marinesco/security/RegistrationForm.class differ diff --git a/target/classes/ru/redrise/marinesco/security/SecurityConfig.class b/target/classes/ru/redrise/marinesco/security/SecurityConfig.class index 1e5644c..437cc5e 100644 Binary files a/target/classes/ru/redrise/marinesco/security/SecurityConfig.class and b/target/classes/ru/redrise/marinesco/security/SecurityConfig.class differ diff --git a/target/classes/ru/redrise/marinesco/security/UserManagment.class b/target/classes/ru/redrise/marinesco/security/UserManagment.class new file mode 100644 index 0000000..18ddfe1 Binary files /dev/null and b/target/classes/ru/redrise/marinesco/security/UserManagment.class differ diff --git a/target/classes/ru/redrise/marinesco/security/UserRole$Type.class b/target/classes/ru/redrise/marinesco/security/UserRole$Type.class new file mode 100644 index 0000000..8507a18 Binary files /dev/null and b/target/classes/ru/redrise/marinesco/security/UserRole$Type.class differ diff --git a/target/classes/ru/redrise/marinesco/security/UserRole.class b/target/classes/ru/redrise/marinesco/security/UserRole.class new file mode 100644 index 0000000..cc121f8 Binary files /dev/null and b/target/classes/ru/redrise/marinesco/security/UserRole.class differ diff --git a/target/classes/static/favicon.ico b/target/classes/static/favicon.ico new file mode 100644 index 0000000..48975f4 Binary files /dev/null and b/target/classes/static/favicon.ico differ diff --git a/target/classes/static/images/logo.svg b/target/classes/static/images/logo.svg new file mode 100644 index 0000000..7b90bd4 --- /dev/null +++ b/target/classes/static/images/logo.svg @@ -0,0 +1,97 @@ + + + + + + + + + + + + + + + + + + + diff --git a/target/classes/static/styles/TerminusBold.ttf b/target/classes/static/styles/TerminusBold.ttf new file mode 100644 index 0000000..9dc2aed Binary files /dev/null and b/target/classes/static/styles/TerminusBold.ttf differ diff --git a/target/classes/static/styles/styles.css b/target/classes/static/styles/styles.css new file mode 100644 index 0000000..fabffdb --- /dev/null +++ b/target/classes/static/styles/styles.css @@ -0,0 +1,48 @@ +@font-face{ + font-family: "Terminus"; + src: url('/styles/TerminusBold.ttf'); +} + +body { + margin-top: 0; + margin-bottom: 0; + margin-right: 1%; + margin-left: 1%; + font-family: Terminus; + background-color: #212121; + color: #cfcfcf; +} + +.validationError { + color: red; +} +.header-container { + text-align: left; + position: relative; + color: white; +} +.header-container .header-bar { + position: absolute; + right: 10px; +} + +table, th, td { + border: 1px solid; + border-collapse: collapse; +} + +a { + color: #cfcfcf; + text-align: center; +} +a:link { + color: #cfcfcf; +} + +a:hover { + color: white; +} + +a:visited { + color: #949494; +} \ No newline at end of file diff --git a/target/classes/templates/login.html b/target/classes/templates/login.html index 9de8ff6..3407fcd 100644 --- a/target/classes/templates/login.html +++ b/target/classes/templates/login.html @@ -3,10 +3,28 @@ Marinesco + + -

Welcome to LOGIN PAGE

+

FUCKING BRILLIANT LOGIN PAGE

+ - +
+
New here? REGISTER NOW! +
H2 + +
\ No newline at end of file diff --git a/target/classes/templates/registration.html b/target/classes/templates/registration.html index b681b69..06a9480 100644 --- a/target/classes/templates/registration.html +++ b/target/classes/templates/registration.html @@ -3,19 +3,23 @@ Marinesco - registration form + +

Register

+
-
+
-
+


+
diff --git a/target/classes/templates/root.html b/target/classes/templates/root.html index 4e85e2d..df62e2f 100644 --- a/target/classes/templates/root.html +++ b/target/classes/templates/root.html @@ -3,10 +3,14 @@ Marinesco + +

Welcome to Marinesco

+ +
Login \ No newline at end of file diff --git a/target/classes/templates/usersmanagment.html b/target/classes/templates/usersmanagment.html new file mode 100644 index 0000000..6203eb5 --- /dev/null +++ b/target/classes/templates/usersmanagment.html @@ -0,0 +1,17 @@ + + + + + User managment + + + + + +

User managment

+ +
Log out + + + + \ No newline at end of file