diff --git a/build.gradle b/build.gradle index 3182e82..694498c 100644 --- a/build.gradle +++ b/build.gradle @@ -30,6 +30,11 @@ dependencies { implementation 'org.springdoc:springdoc-openapi-ui:1.6.5' testImplementation 'org.springframework.boot:spring-boot-starter-test' + + implementation 'org.springframework.boot:spring-boot-starter-security' + implementation 'com.auth0:java-jwt:4.4.0' + implementation 'org.thymeleaf.extras:thymeleaf-extras-springsecurity6' + annotationProcessor "org.springframework.boot:spring-boot-configuration-processor" } tasks.named('test') { diff --git a/data.mv.db b/data.mv.db index 6f0a0af..493b1b1 100644 Binary files a/data.mv.db and b/data.mv.db differ diff --git a/data.trace.db b/data.trace.db index dd0c1bb..b34a08a 100644 --- a/data.trace.db +++ b/data.trace.db @@ -11857,3 +11857,183 @@ Caused by: org.h2.mvstore.MVStoreException: The file is locked: C:/Users/Admin/D at org.h2.mvstore.FileStore.open(FileStore.java:163) at org.h2.mvstore.MVStore.(MVStore.java:444) ... 28 more +2023-05-23 21:22:53 jdbc[3]: exception +org.h2.jdbc.JdbcSQLSyntaxErrorException: Столбец "USER_ID" не найден +Column "USER_ID" not found; SQL statement: +alter table if exists groups add constraint FK4cygfv5el2o2v3hbkdkscfw5q foreign key (user_id) references users [42122-210] + at org.h2.message.DbException.getJdbcSQLException(DbException.java:521) + at org.h2.message.DbException.getJdbcSQLException(DbException.java:496) + at org.h2.message.DbException.get(DbException.java:227) + at org.h2.message.DbException.get(DbException.java:203) + at org.h2.table.Table.getColumn(Table.java:754) + at org.h2.table.IndexColumn.mapColumns(IndexColumn.java:184) + at org.h2.command.ddl.AlterTableAddConstraint.tryUpdate(AlterTableAddConstraint.java:214) + at org.h2.command.ddl.AlterTableAddConstraint.update(AlterTableAddConstraint.java:72) + at org.h2.command.ddl.AlterTable.update(AlterTable.java:46) + at org.h2.command.CommandContainer.update(CommandContainer.java:174) + at org.h2.command.Command.executeUpdate(Command.java:252) + at org.h2.jdbc.JdbcStatement.executeInternal(JdbcStatement.java:252) + at org.h2.jdbc.JdbcStatement.execute(JdbcStatement.java:223) + at com.zaxxer.hikari.pool.ProxyStatement.execute(ProxyStatement.java:94) + at com.zaxxer.hikari.pool.HikariProxyStatement.execute(HikariProxyStatement.java) + at org.hibernate.tool.schema.internal.exec.GenerationTargetToDatabase.accept(GenerationTargetToDatabase.java:54) + at org.hibernate.tool.schema.internal.AbstractSchemaMigrator.applySqlString(AbstractSchemaMigrator.java:587) + at org.hibernate.tool.schema.internal.AbstractSchemaMigrator.applySqlStrings(AbstractSchemaMigrator.java:532) + at org.hibernate.tool.schema.internal.AbstractSchemaMigrator.applyForeignKeys(AbstractSchemaMigrator.java:458) + at org.hibernate.tool.schema.internal.AbstractSchemaMigrator.performMigration(AbstractSchemaMigrator.java:278) + at org.hibernate.tool.schema.internal.AbstractSchemaMigrator.doMigration(AbstractSchemaMigrator.java:126) + at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.performDatabaseAction(SchemaManagementToolCoordinator.java:284) + at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.lambda$process$5(SchemaManagementToolCoordinator.java:143) + at java.base/java.util.HashMap.forEach(HashMap.java:1421) + at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.process(SchemaManagementToolCoordinator.java:140) + at org.hibernate.internal.SessionFactoryImpl.(SessionFactoryImpl.java:336) + at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:415) + at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:1425) + at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:66) + at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:376) + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:409) + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:396) + at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:352) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1797) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1747) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:599) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:521) + at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:326) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:324) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200) + at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1130) + at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:905) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:584) + at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:730) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:432) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:308) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:1302) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:1291) + at ru.IP_LabWorks.IP.IpApplication.main(IpApplication.java:14) + at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) + at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) + at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) + at java.base/java.lang.reflect.Method.invoke(Method.java:568) + at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49) +2023-05-23 21:22:53 jdbc[3]: exception +org.h2.jdbc.JdbcSQLSyntaxErrorException: Столбец "USER_ID" не найден +Column "USER_ID" not found; SQL statement: +alter table if exists students add constraint FKdt1cjx5ve5bdabmuuf3ibrwaq foreign key (user_id) references users [42122-210] + at org.h2.message.DbException.getJdbcSQLException(DbException.java:521) + at org.h2.message.DbException.getJdbcSQLException(DbException.java:496) + at org.h2.message.DbException.get(DbException.java:227) + at org.h2.message.DbException.get(DbException.java:203) + at org.h2.table.Table.getColumn(Table.java:754) + at org.h2.table.IndexColumn.mapColumns(IndexColumn.java:184) + at org.h2.command.ddl.AlterTableAddConstraint.tryUpdate(AlterTableAddConstraint.java:214) + at org.h2.command.ddl.AlterTableAddConstraint.update(AlterTableAddConstraint.java:72) + at org.h2.command.ddl.AlterTable.update(AlterTable.java:46) + at org.h2.command.CommandContainer.update(CommandContainer.java:174) + at org.h2.command.Command.executeUpdate(Command.java:252) + at org.h2.jdbc.JdbcStatement.executeInternal(JdbcStatement.java:252) + at org.h2.jdbc.JdbcStatement.execute(JdbcStatement.java:223) + at com.zaxxer.hikari.pool.ProxyStatement.execute(ProxyStatement.java:94) + at com.zaxxer.hikari.pool.HikariProxyStatement.execute(HikariProxyStatement.java) + at org.hibernate.tool.schema.internal.exec.GenerationTargetToDatabase.accept(GenerationTargetToDatabase.java:54) + at org.hibernate.tool.schema.internal.AbstractSchemaMigrator.applySqlString(AbstractSchemaMigrator.java:587) + at org.hibernate.tool.schema.internal.AbstractSchemaMigrator.applySqlStrings(AbstractSchemaMigrator.java:532) + at org.hibernate.tool.schema.internal.AbstractSchemaMigrator.applyForeignKeys(AbstractSchemaMigrator.java:458) + at org.hibernate.tool.schema.internal.AbstractSchemaMigrator.performMigration(AbstractSchemaMigrator.java:278) + at org.hibernate.tool.schema.internal.AbstractSchemaMigrator.doMigration(AbstractSchemaMigrator.java:126) + at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.performDatabaseAction(SchemaManagementToolCoordinator.java:284) + at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.lambda$process$5(SchemaManagementToolCoordinator.java:143) + at java.base/java.util.HashMap.forEach(HashMap.java:1421) + at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.process(SchemaManagementToolCoordinator.java:140) + at org.hibernate.internal.SessionFactoryImpl.(SessionFactoryImpl.java:336) + at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:415) + at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:1425) + at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:66) + at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:376) + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:409) + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:396) + at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:352) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1797) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1747) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:599) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:521) + at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:326) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:324) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200) + at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1130) + at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:905) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:584) + at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:730) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:432) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:308) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:1302) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:1291) + at ru.IP_LabWorks.IP.IpApplication.main(IpApplication.java:14) + at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) + at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) + at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) + at java.base/java.lang.reflect.Method.invoke(Method.java:568) + at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49) +2023-05-23 21:22:53 jdbc[3]: exception +org.h2.jdbc.JdbcSQLSyntaxErrorException: Столбец "USER_ID" не найден +Column "USER_ID" not found; SQL statement: +alter table if exists subjects add constraint FKm9k2q12kousqip4g5spqrm2am foreign key (user_id) references users [42122-210] + at org.h2.message.DbException.getJdbcSQLException(DbException.java:521) + at org.h2.message.DbException.getJdbcSQLException(DbException.java:496) + at org.h2.message.DbException.get(DbException.java:227) + at org.h2.message.DbException.get(DbException.java:203) + at org.h2.table.Table.getColumn(Table.java:754) + at org.h2.table.IndexColumn.mapColumns(IndexColumn.java:184) + at org.h2.command.ddl.AlterTableAddConstraint.tryUpdate(AlterTableAddConstraint.java:214) + at org.h2.command.ddl.AlterTableAddConstraint.update(AlterTableAddConstraint.java:72) + at org.h2.command.ddl.AlterTable.update(AlterTable.java:46) + at org.h2.command.CommandContainer.update(CommandContainer.java:174) + at org.h2.command.Command.executeUpdate(Command.java:252) + at org.h2.jdbc.JdbcStatement.executeInternal(JdbcStatement.java:252) + at org.h2.jdbc.JdbcStatement.execute(JdbcStatement.java:223) + at com.zaxxer.hikari.pool.ProxyStatement.execute(ProxyStatement.java:94) + at com.zaxxer.hikari.pool.HikariProxyStatement.execute(HikariProxyStatement.java) + at org.hibernate.tool.schema.internal.exec.GenerationTargetToDatabase.accept(GenerationTargetToDatabase.java:54) + at org.hibernate.tool.schema.internal.AbstractSchemaMigrator.applySqlString(AbstractSchemaMigrator.java:587) + at org.hibernate.tool.schema.internal.AbstractSchemaMigrator.applySqlStrings(AbstractSchemaMigrator.java:532) + at org.hibernate.tool.schema.internal.AbstractSchemaMigrator.applyForeignKeys(AbstractSchemaMigrator.java:458) + at org.hibernate.tool.schema.internal.AbstractSchemaMigrator.performMigration(AbstractSchemaMigrator.java:278) + at org.hibernate.tool.schema.internal.AbstractSchemaMigrator.doMigration(AbstractSchemaMigrator.java:126) + at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.performDatabaseAction(SchemaManagementToolCoordinator.java:284) + at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.lambda$process$5(SchemaManagementToolCoordinator.java:143) + at java.base/java.util.HashMap.forEach(HashMap.java:1421) + at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.process(SchemaManagementToolCoordinator.java:140) + at org.hibernate.internal.SessionFactoryImpl.(SessionFactoryImpl.java:336) + at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:415) + at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:1425) + at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:66) + at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:376) + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:409) + at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:396) + at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:352) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1797) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1747) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:599) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:521) + at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:326) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:324) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200) + at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1130) + at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:905) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:584) + at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:730) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:432) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:308) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:1302) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:1291) + at ru.IP_LabWorks.IP.IpApplication.main(IpApplication.java:14) + at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) + at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) + at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) + at java.base/java.lang.reflect.Method.invoke(Method.java:568) + at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49) diff --git a/frontend/package-lock.json b/frontend/package-lock.json new file mode 100644 index 0000000..4df0c4b --- /dev/null +++ b/frontend/package-lock.json @@ -0,0 +1,6 @@ +{ + "name": "frontend", + "lockfileVersion": 2, + "requires": true, + "packages": {} +} diff --git a/src/main/java/ru/IP_LabWorks/IP/University/Configuration/PasswordEncoderConfiguration.java b/src/main/java/ru/IP_LabWorks/IP/University/Configuration/PasswordEncoderConfiguration.java new file mode 100644 index 0000000..867a225 --- /dev/null +++ b/src/main/java/ru/IP_LabWorks/IP/University/Configuration/PasswordEncoderConfiguration.java @@ -0,0 +1,14 @@ +package ru.IP_LabWorks.IP.University.Configuration; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; + +@Configuration +public class PasswordEncoderConfiguration { + @Bean + public PasswordEncoder createPasswordEncoder() { + return new BCryptPasswordEncoder(); + } +} \ No newline at end of file diff --git a/src/main/java/ru/IP_LabWorks/IP/University/Configuration/SecurityConfiguration.java b/src/main/java/ru/IP_LabWorks/IP/University/Configuration/SecurityConfiguration.java new file mode 100644 index 0000000..613a2e8 --- /dev/null +++ b/src/main/java/ru/IP_LabWorks/IP/University/Configuration/SecurityConfiguration.java @@ -0,0 +1,68 @@ +package ru.IP_LabWorks.IP.University.Configuration; + + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.HttpMethod; +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.config.annotation.web.configuration.WebSecurityCustomizer; +import org.springframework.security.web.SecurityFilterChain; +import ru.IP_LabWorks.IP.University.Contoller.MVC.UserSignUpMvcController; +import ru.IP_LabWorks.IP.University.Model.UserRole; +import ru.IP_LabWorks.IP.University.Service.UserService; + +@Configuration +@EnableWebSecurity +@EnableMethodSecurity( + securedEnabled = true +) +public class SecurityConfiguration { + private final Logger log = LoggerFactory.getLogger(SecurityConfiguration.class); + private static final String LOGIN_URL = "/login"; + private final UserService userService; + + public SecurityConfiguration(UserService userService) { + this.userService = userService; + createAdminOnStartup(); + } + + private void createAdminOnStartup() { + final String admin = "admin"; + if (userService.findByLogin(admin) == null) { + log.info("Admin user successfully created"); + userService.createUser(admin, admin, admin, UserRole.ADMIN); + } + } + + @Bean + public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { + http.headers().frameOptions().sameOrigin().and() + .cors().and() + .csrf().disable() + .authorizeHttpRequests() + .requestMatchers(UserSignUpMvcController.SIGNUP_URL).permitAll() + .requestMatchers(HttpMethod.GET, LOGIN_URL).permitAll() + .anyRequest().authenticated() + .and() + .formLogin() + .loginPage(LOGIN_URL).permitAll() + .defaultSuccessUrl("/student", true) + .and() + .logout().permitAll(); + return http.userDetailsService(userService).build(); + } + + + @Bean + public WebSecurityCustomizer webSecurityCustomizer() { + return (web) -> web.ignoring() + .requestMatchers("/css/**") + .requestMatchers("/js/**") + .requestMatchers("/templates/**") + .requestMatchers("/webjars/**"); + } +} \ No newline at end of file diff --git a/src/main/java/ru/IP_LabWorks/IP/WebConfiguration.java b/src/main/java/ru/IP_LabWorks/IP/University/Configuration/WebConfiguration.java similarity index 87% rename from src/main/java/ru/IP_LabWorks/IP/WebConfiguration.java rename to src/main/java/ru/IP_LabWorks/IP/University/Configuration/WebConfiguration.java index 99c2321..243f274 100644 --- a/src/main/java/ru/IP_LabWorks/IP/WebConfiguration.java +++ b/src/main/java/ru/IP_LabWorks/IP/University/Configuration/WebConfiguration.java @@ -1,4 +1,4 @@ -package ru.IP_LabWorks.IP; +package ru.IP_LabWorks.IP.University.Configuration; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.CorsRegistry; @@ -15,6 +15,6 @@ public class WebConfiguration implements WebMvcConfigurer { @Override public void addViewControllers(ViewControllerRegistry registry) { WebMvcConfigurer.super.addViewControllers(registry); - registry.addViewController("student"); + registry.addViewController("login"); } } diff --git a/src/main/java/ru/IP_LabWorks/IP/University/Contoller/DTO/UserDTO.java b/src/main/java/ru/IP_LabWorks/IP/University/Contoller/DTO/UserDTO.java new file mode 100644 index 0000000..4ce0324 --- /dev/null +++ b/src/main/java/ru/IP_LabWorks/IP/University/Contoller/DTO/UserDTO.java @@ -0,0 +1,28 @@ +package ru.IP_LabWorks.IP.University.Contoller.DTO; + +import ru.IP_LabWorks.IP.University.Model.User; +import ru.IP_LabWorks.IP.University.Model.UserRole; + +public class UserDTO { + private final long id; + private final String login; + private final UserRole role; + + public UserDTO(User user) { + this.id = user.getId(); + this.login = user.getLogin(); + this.role = user.getRole(); + } + + public long getId() { + return id; + } + + public String getLogin() { + return login; + } + + public UserRole getRole() { + return role; + } +} diff --git a/src/main/java/ru/IP_LabWorks/IP/University/Contoller/DTO/UserSignUpDTO.java b/src/main/java/ru/IP_LabWorks/IP/University/Contoller/DTO/UserSignUpDTO.java new file mode 100644 index 0000000..7f29348 --- /dev/null +++ b/src/main/java/ru/IP_LabWorks/IP/University/Contoller/DTO/UserSignUpDTO.java @@ -0,0 +1,40 @@ +package ru.IP_LabWorks.IP.University.Contoller.DTO; + +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.Size; + +public class UserSignUpDTO { + @NotBlank + @Size(min = 3, max = 64) + private String login; + @NotBlank + @Size(min = 6, max = 64) + private String password; + @NotBlank + @Size(min = 6, max = 64) + private String passwordConfirm; + + public String getLogin() { + return login; + } + + public void setLogin(String login) { + this.login = login; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public String getPasswordConfirm() { + return passwordConfirm; + } + + public void setPasswordConfirm(String passwordConfirm) { + this.passwordConfirm = passwordConfirm; + } +} diff --git a/src/main/java/ru/IP_LabWorks/IP/University/Contoller/MVC/UserMvcController.java b/src/main/java/ru/IP_LabWorks/IP/University/Contoller/MVC/UserMvcController.java new file mode 100644 index 0000000..69628c8 --- /dev/null +++ b/src/main/java/ru/IP_LabWorks/IP/University/Contoller/MVC/UserMvcController.java @@ -0,0 +1,42 @@ +package ru.IP_LabWorks.IP.University.Contoller.MVC; + +import org.springframework.data.domain.Page; +import org.springframework.security.access.annotation.Secured; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import ru.IP_LabWorks.IP.University.Contoller.DTO.UserDTO; +import ru.IP_LabWorks.IP.University.Model.UserRole; +import ru.IP_LabWorks.IP.University.Service.UserService; + +import java.util.List; +import java.util.stream.IntStream; + +@Controller +@RequestMapping("/users") +public class UserMvcController { + private final UserService userService; + + public UserMvcController(UserService userService) { + this.userService = userService; + } + + @GetMapping + @Secured({UserRole.AsString.ADMIN}) + public String getUsers(@RequestParam(defaultValue = "1") int page, + @RequestParam(defaultValue = "5") int size, + Model model) { + final Page users = userService.findAllPages(page, size) + .map(UserDTO::new); + model.addAttribute("users", users); + final int totalPages = users.getTotalPages(); + final List pageNumbers = IntStream.rangeClosed(1, totalPages) + .boxed() + .toList(); + model.addAttribute("pages", pageNumbers); + model.addAttribute("totalPages", totalPages); + return "users"; + } +} diff --git a/src/main/java/ru/IP_LabWorks/IP/University/Contoller/MVC/UserSignUpMvcController.java b/src/main/java/ru/IP_LabWorks/IP/University/Contoller/MVC/UserSignUpMvcController.java new file mode 100644 index 0000000..8a78b66 --- /dev/null +++ b/src/main/java/ru/IP_LabWorks/IP/University/Contoller/MVC/UserSignUpMvcController.java @@ -0,0 +1,48 @@ +package ru.IP_LabWorks.IP.University.Contoller.MVC; + +import jakarta.validation.Valid; +import jakarta.validation.ValidationException; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.validation.BindingResult; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import ru.IP_LabWorks.IP.University.Contoller.DTO.UserSignUpDTO; +import ru.IP_LabWorks.IP.University.Model.User; +import ru.IP_LabWorks.IP.University.Service.UserService; + +@Controller +@RequestMapping(UserSignUpMvcController.SIGNUP_URL) +public class UserSignUpMvcController { + public static final String SIGNUP_URL = "/signup"; + private final UserService userService; + + public UserSignUpMvcController(UserService userService) { + this.userService = userService; + } + + @GetMapping + public String showSignupForm(Model model) { + model.addAttribute("UserDTO", new UserSignUpDTO()); + return "signup"; + } + + @PostMapping + public String signup(@ModelAttribute("UserDTO") @Valid UserSignUpDTO userSignupDto, + BindingResult bindingResult, + Model model) { + if (bindingResult.hasErrors()) { + model.addAttribute("errors", bindingResult.getAllErrors()); + return "signup"; + } + try { + final User user = userService.createUser(userSignupDto.getLogin(), userSignupDto.getPassword(), userSignupDto.getPasswordConfirm()); + return "redirect:/login?created=" + user.getLogin(); + } catch (ValidationException e) { + model.addAttribute("errors", e.getMessage()); + return "signup"; + } + } +} diff --git a/src/main/java/ru/IP_LabWorks/IP/University/Contoller/REST/GroupController.java b/src/main/java/ru/IP_LabWorks/IP/University/Contoller/REST/GroupController.java index 0ab45dd..8258be9 100644 --- a/src/main/java/ru/IP_LabWorks/IP/University/Contoller/REST/GroupController.java +++ b/src/main/java/ru/IP_LabWorks/IP/University/Contoller/REST/GroupController.java @@ -4,11 +4,10 @@ import jakarta.validation.Valid; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import ru.IP_LabWorks.IP.University.Contoller.DTO.GroupDTO; -import ru.IP_LabWorks.IP.University.Contoller.DTO.StudentDTO; import ru.IP_LabWorks.IP.University.Model.Student; import ru.IP_LabWorks.IP.University.Model.Subject; import ru.IP_LabWorks.IP.University.Service.GroupService; -import ru.IP_LabWorks.IP.WebConfiguration; +import ru.IP_LabWorks.IP.University.Configuration.WebConfiguration; import java.util.List; import java.util.Map; diff --git a/src/main/java/ru/IP_LabWorks/IP/University/Contoller/REST/StudentController.java b/src/main/java/ru/IP_LabWorks/IP/University/Contoller/REST/StudentController.java index 2113c61..d951f20 100644 --- a/src/main/java/ru/IP_LabWorks/IP/University/Contoller/REST/StudentController.java +++ b/src/main/java/ru/IP_LabWorks/IP/University/Contoller/REST/StudentController.java @@ -7,9 +7,8 @@ import ru.IP_LabWorks.IP.University.Service.GroupService; import ru.IP_LabWorks.IP.University.Service.StudentService; import jakarta.validation.Valid; -import ru.IP_LabWorks.IP.WebConfiguration; +import ru.IP_LabWorks.IP.University.Configuration.WebConfiguration; -import java.time.LocalDate; import java.util.List; @RestController diff --git a/src/main/java/ru/IP_LabWorks/IP/University/Contoller/REST/SubjectController.java b/src/main/java/ru/IP_LabWorks/IP/University/Contoller/REST/SubjectController.java index d1cfbd6..a0b220d 100644 --- a/src/main/java/ru/IP_LabWorks/IP/University/Contoller/REST/SubjectController.java +++ b/src/main/java/ru/IP_LabWorks/IP/University/Contoller/REST/SubjectController.java @@ -2,14 +2,11 @@ package ru.IP_LabWorks.IP.University.Contoller.REST; import jakarta.validation.Valid; import org.springframework.web.bind.annotation.*; -import ru.IP_LabWorks.IP.University.Contoller.DTO.GroupDTO; import ru.IP_LabWorks.IP.University.Contoller.DTO.SubjectDTO; -import ru.IP_LabWorks.IP.University.Service.GroupService; import ru.IP_LabWorks.IP.University.Service.SubjectService; -import ru.IP_LabWorks.IP.WebConfiguration; +import ru.IP_LabWorks.IP.University.Configuration.WebConfiguration; import java.util.List; -import java.util.Objects; @RestController @RequestMapping(WebConfiguration.REST_API + "/subject") diff --git a/src/main/java/ru/IP_LabWorks/IP/University/Model/Group.java b/src/main/java/ru/IP_LabWorks/IP/University/Model/Group.java index b840921..f05c1ce 100644 --- a/src/main/java/ru/IP_LabWorks/IP/University/Model/Group.java +++ b/src/main/java/ru/IP_LabWorks/IP/University/Model/Group.java @@ -30,6 +30,9 @@ public class Group { inverseJoinColumns = {@JoinColumn(name = "subject_id")}) private List subjects; + @ManyToOne + @JoinColumn(name= "user_id", nullable = false) + private User user; public Group() { this.students = new ArrayList<>(); } @@ -104,4 +107,10 @@ public class Group { return subjectIds; } } + public User getUser() { + return user; + } + public void setUser(User user) { + this.user = user; + } } diff --git a/src/main/java/ru/IP_LabWorks/IP/University/Model/Student.java b/src/main/java/ru/IP_LabWorks/IP/University/Model/Student.java index be46044..c88716a 100644 --- a/src/main/java/ru/IP_LabWorks/IP/University/Model/Student.java +++ b/src/main/java/ru/IP_LabWorks/IP/University/Model/Student.java @@ -22,6 +22,9 @@ public class Student { @JoinColumn(name = "group_id", nullable = true) private Group group; + @ManyToOne + @JoinColumn(name= "user_id", nullable = false) + private User user; public Student() { } @@ -83,4 +86,10 @@ public class Student { } } } + public User getUser() { + return user; + } + public void setUser(User user) { + this.user = user; + } } diff --git a/src/main/java/ru/IP_LabWorks/IP/University/Model/Subject.java b/src/main/java/ru/IP_LabWorks/IP/University/Model/Subject.java index 079cede..7f7030f 100644 --- a/src/main/java/ru/IP_LabWorks/IP/University/Model/Subject.java +++ b/src/main/java/ru/IP_LabWorks/IP/University/Model/Subject.java @@ -26,6 +26,10 @@ public class Subject { inverseJoinColumns = {@JoinColumn(name = "group_id")}) private List groups = new ArrayList<>(); + @ManyToOne + @JoinColumn(name= "user_id", nullable = false) + private User user; + public Subject() { } @@ -79,4 +83,10 @@ public class Subject { return groupIds; } } + public User getUser() { + return user; + } + public void setUser(User user) { + this.user = user; + } } diff --git a/src/main/java/ru/IP_LabWorks/IP/University/Model/User.java b/src/main/java/ru/IP_LabWorks/IP/University/Model/User.java new file mode 100644 index 0000000..7c0c286 --- /dev/null +++ b/src/main/java/ru/IP_LabWorks/IP/University/Model/User.java @@ -0,0 +1,83 @@ +package ru.IP_LabWorks.IP.University.Model; + +import jakarta.persistence.*; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.Size; + +import java.util.Objects; + +@Entity +@Table(name = "users") +public class User { + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private Long id; + @Column(nullable = false, unique = true, length = 64) + @NotBlank + @Size(min = 3, max = 64) + private String login; + @Column(nullable = false, length = 64) + @NotBlank + @Size(min = 6, max = 64) + private String password; + private UserRole role; + + public User() { + } + + public User(String login, String password) { + this(login, password, UserRole.USER); + } + + public User(String login, String password, UserRole role) { + this.login = login; + this.password = password; + this.role = role; + } + + public Long getId() { + return id; + } + + public String getLogin() { + return login; + } + + public void setLogin(String login) { + this.login = login; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public UserRole getRole() { + return role; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + User user = (User) o; + return Objects.equals(id, user.id) && Objects.equals(login, user.login); + } + + @Override + public int hashCode() { + return Objects.hash(id, login); + } + @Override + public String toString() { + return "User{" + + "id=" + id + + ", login='" + login + '\'' + + ", password='" + password + '\'' + + ", role='" + role + '\'' + + '}'; + } +} diff --git a/src/main/java/ru/IP_LabWorks/IP/University/Model/UserRole.java b/src/main/java/ru/IP_LabWorks/IP/University/Model/UserRole.java new file mode 100644 index 0000000..8d749e4 --- /dev/null +++ b/src/main/java/ru/IP_LabWorks/IP/University/Model/UserRole.java @@ -0,0 +1,20 @@ +package ru.IP_LabWorks.IP.University.Model; + +import org.springframework.security.core.GrantedAuthority; + +public enum UserRole implements GrantedAuthority { + ADMIN, + USER; + + private static final String PREFIX = "ROLE_"; + + @Override + public String getAuthority() { + return PREFIX + this.name(); + } + + public static final class AsString { + public static final String ADMIN = PREFIX + "ADMIN"; + public static final String USER = PREFIX + "USER"; + } +} diff --git a/src/main/java/ru/IP_LabWorks/IP/University/Repository/UserRepository.java b/src/main/java/ru/IP_LabWorks/IP/University/Repository/UserRepository.java new file mode 100644 index 0000000..31f646a --- /dev/null +++ b/src/main/java/ru/IP_LabWorks/IP/University/Repository/UserRepository.java @@ -0,0 +1,9 @@ +package ru.IP_LabWorks.IP.University.Repository; + +import org.springframework.data.jpa.repository.JpaRepository; +import ru.IP_LabWorks.IP.University.Model.Student; +import ru.IP_LabWorks.IP.University.Model.User; + +public interface UserRepository extends JpaRepository { + User findOneByLoginIgnoreCase(String login); +} diff --git a/src/main/java/ru/IP_LabWorks/IP/University/Service/UserService.java b/src/main/java/ru/IP_LabWorks/IP/University/Service/UserService.java new file mode 100644 index 0000000..d7fe75e --- /dev/null +++ b/src/main/java/ru/IP_LabWorks/IP/University/Service/UserService.java @@ -0,0 +1,59 @@ +package ru.IP_LabWorks.IP.University.Service; + + +import jakarta.validation.ValidationException; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Sort; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.stereotype.Service; +import ru.IP_LabWorks.IP.University.Model.User; +import ru.IP_LabWorks.IP.University.Model.UserRole; +import ru.IP_LabWorks.IP.University.Repository.UserRepository; + +import java.util.Collections; +import java.util.Objects; + +@Service +public class UserService implements UserDetailsService { + private final UserRepository userRepository; + private final PasswordEncoder passwordEncoder; + + public UserService(UserRepository userRepository, + PasswordEncoder passwordEncoder) { + this.userRepository = userRepository; + this.passwordEncoder = passwordEncoder; + } + public Page findAllPages(int page, int size) { + return userRepository.findAll(PageRequest.of(page - 1, size, Sort.by("id").ascending())); + } + public User findByLogin(String login) { + return userRepository.findOneByLoginIgnoreCase(login); + } + public User createUser(String login, String password, String passwordConfirm) { + return createUser(login, password, passwordConfirm, UserRole.USER); + } + public User createUser(String login, String password, String passwordConfirm, UserRole role) { + if (findByLogin(login) != null) { + throw new ValidationException(String.format("User '%s' already exists", login)); + } + final User user = new User(login, passwordEncoder.encode(password), role); + if (!Objects.equals(password, passwordConfirm)) { + throw new ValidationException("Passwords not equals"); + } + return userRepository.save(user); + } + + @Override + public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { + final User userEntity = findByLogin(username); + if (userEntity == null) { + throw new UsernameNotFoundException(username); + } + return new org.springframework.security.core.userdetails.User( + userEntity.getLogin(), userEntity.getPassword(), Collections.singleton(userEntity.getRole())); + } +} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index e06079d..14d2c47 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -8,4 +8,4 @@ spring.jpa.database-platform=org.hibernate.dialect.H2Dialect spring.jpa.hibernate.ddl-auto=update spring.h2.console.enabled=true spring.h2.console.settings.trace=false -spring.h2.console.settings.web-allow-others=false +spring.h2.console.settings.web-allow-others=false \ No newline at end of file diff --git a/src/main/resources/templates/default.html b/src/main/resources/templates/default.html index 799b596..3c6930f 100644 --- a/src/main/resources/templates/default.html +++ b/src/main/resources/templates/default.html @@ -25,6 +25,7 @@ Студенты Группы Предметы + Пользователи diff --git a/src/main/resources/templates/login.html b/src/main/resources/templates/login.html new file mode 100644 index 0000000..e8b17ca --- /dev/null +++ b/src/main/resources/templates/login.html @@ -0,0 +1,42 @@ + + + +
+
+ User not found +
+
+ Logout success +
+
+ User '' was successfully created +
+
+
+

Login

+ +
+
+

Password

+ +
+
+ +
+
+

+ Not a member yet? + Sign Up here +

+
+
+
+ + \ No newline at end of file diff --git a/src/main/resources/templates/signup.html b/src/main/resources/templates/signup.html new file mode 100644 index 0000000..9f4e0e6 --- /dev/null +++ b/src/main/resources/templates/signup.html @@ -0,0 +1,29 @@ + + + +
+
+
+
+ +
+
+ +
+
+ +
+
+ + Назад +
+
+
+ + \ No newline at end of file diff --git a/src/main/resources/templates/users.html b/src/main/resources/templates/users.html new file mode 100644 index 0000000..34c6cfa --- /dev/null +++ b/src/main/resources/templates/users.html @@ -0,0 +1,38 @@ + + + +
+
+ + + + + + + + + + + + + + + + + +
#IDЛогинРоль
+
+ +
+ + \ No newline at end of file