From 69d0346b2428b61b0305077e1efaa16ff5daa915 Mon Sep 17 00:00:00 2001 From: ArtemEmelyanov Date: Tue, 23 May 2023 21:42:43 +0400 Subject: [PATCH] =?UTF-8?q?=D0=9D=D0=B0=D1=87=D0=B0=D1=82=D0=B0=206=20?= =?UTF-8?q?=D0=BB=D0=B0=D0=B1=D0=B0=20MVC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 5 + data.mv.db | Bin 49152 -> 45056 bytes data.trace.db | 180 ++++++++++++++++++ frontend/package-lock.json | 6 + .../PasswordEncoderConfiguration.java | 14 ++ .../Configuration/SecurityConfiguration.java | 68 +++++++ .../Configuration}/WebConfiguration.java | 4 +- .../IP/University/Contoller/DTO/UserDTO.java | 28 +++ .../Contoller/DTO/UserSignUpDTO.java | 40 ++++ .../Contoller/MVC/UserMvcController.java | 42 ++++ .../MVC/UserSignUpMvcController.java | 48 +++++ .../Contoller/REST/GroupController.java | 3 +- .../Contoller/REST/StudentController.java | 3 +- .../Contoller/REST/SubjectController.java | 5 +- .../IP/University/Model/Group.java | 9 + .../IP/University/Model/Student.java | 9 + .../IP/University/Model/Subject.java | 10 + .../IP_LabWorks/IP/University/Model/User.java | 83 ++++++++ .../IP/University/Model/UserRole.java | 20 ++ .../University/Repository/UserRepository.java | 9 + .../IP/University/Service/UserService.java | 59 ++++++ src/main/resources/application.properties | 2 +- src/main/resources/templates/default.html | 1 + src/main/resources/templates/login.html | 42 ++++ src/main/resources/templates/signup.html | 29 +++ src/main/resources/templates/users.html | 38 ++++ 26 files changed, 746 insertions(+), 11 deletions(-) create mode 100644 frontend/package-lock.json create mode 100644 src/main/java/ru/IP_LabWorks/IP/University/Configuration/PasswordEncoderConfiguration.java create mode 100644 src/main/java/ru/IP_LabWorks/IP/University/Configuration/SecurityConfiguration.java rename src/main/java/ru/IP_LabWorks/IP/{ => University/Configuration}/WebConfiguration.java (87%) create mode 100644 src/main/java/ru/IP_LabWorks/IP/University/Contoller/DTO/UserDTO.java create mode 100644 src/main/java/ru/IP_LabWorks/IP/University/Contoller/DTO/UserSignUpDTO.java create mode 100644 src/main/java/ru/IP_LabWorks/IP/University/Contoller/MVC/UserMvcController.java create mode 100644 src/main/java/ru/IP_LabWorks/IP/University/Contoller/MVC/UserSignUpMvcController.java create mode 100644 src/main/java/ru/IP_LabWorks/IP/University/Model/User.java create mode 100644 src/main/java/ru/IP_LabWorks/IP/University/Model/UserRole.java create mode 100644 src/main/java/ru/IP_LabWorks/IP/University/Repository/UserRepository.java create mode 100644 src/main/java/ru/IP_LabWorks/IP/University/Service/UserService.java create mode 100644 src/main/resources/templates/login.html create mode 100644 src/main/resources/templates/signup.html create mode 100644 src/main/resources/templates/users.html 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 6f0a0afe3f84df88d674861cd922de58df1f2e07..493b1b18db59abd46995ce785d667d6371f50172 100644 GIT binary patch literal 45056 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 literal 49152 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.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