diff --git a/pom.xml b/pom.xml index 1bb1248394aad3aef155ec8edd329409a7cac0e0..baf2e98e3bc642dfef687d92680f72341da78218 100644 --- a/pom.xml +++ b/pom.xml @@ -70,6 +70,11 @@ <artifactId>usertype.core</artifactId> <version>5.0.0.GA</version> </dependency> + + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-security</artifactId> + </dependency> </dependencies> <build> diff --git a/src/main/java/de/deadlocker8/budgetmaster/authentication/User.java b/src/main/java/de/deadlocker8/budgetmaster/authentication/User.java new file mode 100644 index 0000000000000000000000000000000000000000..81bc99dfa0a72e7f888f31a0dc0e347f7576688c --- /dev/null +++ b/src/main/java/de/deadlocker8/budgetmaster/authentication/User.java @@ -0,0 +1,91 @@ +package de.deadlocker8.budgetmaster.authentication; + +import de.deadlocker8.budgetmaster.entities.Account; +import de.deadlocker8.budgetmaster.entities.Payment; + +import javax.persistence.*; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; +import java.util.List; + +@Entity +public class User +{ + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private Integer ID; + + @NotNull + @Size(min = 1) + @Column(unique = true) + private String name; + + @NotNull + @Size(min = 1) + private String password; + + @ManyToOne + private Account selectedAccount; + + + public User(String name, String password) + { + this.name = name; + this.password = password; + } + + public User() + { + } + + public Integer getID() + { + return ID; + } + + public void setID(Integer ID) + { + this.ID = ID; + } + + public String getName() + { + return name; + } + + public void setName(String name) + { + this.name = name; + } + + public String getPassword() + { + return password; + } + + public void setPassword(String password) + { + this.password = password; + } + + public Account getSelectedAccount() + { + return selectedAccount; + } + + public void setSelectedAccount(Account selectedAccount) + { + this.selectedAccount = selectedAccount; + } + + @Override + public String toString() + { + return "User{" + + "ID=" + ID + + ", name='" + name + '\'' + + ", password='" + password + '\'' + + ", selectedAccount=" + selectedAccount + + '}'; + } +} \ No newline at end of file diff --git a/src/main/java/de/deadlocker8/budgetmaster/authentication/UserRepository.java b/src/main/java/de/deadlocker8/budgetmaster/authentication/UserRepository.java new file mode 100644 index 0000000000000000000000000000000000000000..e9d2f14377a3436124ed953e9db2fe47261a8936 --- /dev/null +++ b/src/main/java/de/deadlocker8/budgetmaster/authentication/UserRepository.java @@ -0,0 +1,9 @@ +package de.deadlocker8.budgetmaster.authentication; + +import org.springframework.data.jpa.repository.JpaRepository; + + +public interface UserRepository extends JpaRepository<User, Integer> +{ + User findByName(String name); +} \ No newline at end of file diff --git a/src/main/java/de/deadlocker8/budgetmaster/authentication/UserService.java b/src/main/java/de/deadlocker8/budgetmaster/authentication/UserService.java new file mode 100644 index 0000000000000000000000000000000000000000..60b1786d6e4de0a9ca3509c366531c9a4b992f9c --- /dev/null +++ b/src/main/java/de/deadlocker8/budgetmaster/authentication/UserService.java @@ -0,0 +1,22 @@ +package de.deadlocker8.budgetmaster.authentication; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class UserService +{ + private final Logger LOGGER = LoggerFactory.getLogger(this.getClass()); + + @Autowired + public UserService(UserRepository userRepository) + { + if(userRepository.findAll().size() == 0) + { + userRepository.save(new User("Default", "123")); + LOGGER.debug("Created default user"); + } + } +} diff --git a/src/main/java/de/deadlocker8/budgetmaster/authentication/WebSecurityConfig.java b/src/main/java/de/deadlocker8/budgetmaster/authentication/WebSecurityConfig.java new file mode 100644 index 0000000000000000000000000000000000000000..4c25fdfbd5646e7e4bc85033cab77d7f9768dc3d --- /dev/null +++ b/src/main/java/de/deadlocker8/budgetmaster/authentication/WebSecurityConfig.java @@ -0,0 +1,52 @@ +package de.deadlocker8.budgetmaster.authentication; + +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; +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.WebSecurityConfigurerAdapter; +import org.springframework.security.web.DefaultRedirectStrategy; +import org.springframework.security.web.RedirectStrategy; + +@Configuration +@EnableWebSecurity +@EnableGlobalMethodSecurity(prePostEnabled = true) +public class WebSecurityConfig extends WebSecurityConfigurerAdapter +{ + private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy(); + + @Override + protected void configure(AuthenticationManagerBuilder auth) throws Exception + { + auth.inMemoryAuthentication().withUser("Default").password("1233").roles("USER"); + } + + @Override + protected void configure(HttpSecurity http) throws Exception { + http + .csrf() + .and() + + .authorizeRequests() + .antMatchers("/static/**").permitAll() + .antMatchers("/accounts/**").authenticated() + .antMatchers("/payments/**").authenticated() + .antMatchers("/charts/**").authenticated() + .antMatchers("/reports/**").authenticated() + .antMatchers("/categories/**").authenticated() + .antMatchers("/settings/**").authenticated() + .antMatchers("/about/**").authenticated() + .and() + + .formLogin() + .loginPage("/login") + .successHandler((req, res, auth) -> redirectStrategy.sendRedirect(req, res, "/")) + .failureUrl("/login?error=true") + .permitAll() + .and() + + .logout() + .permitAll(); + } +} diff --git a/src/main/resources/languages/_de.properties b/src/main/resources/languages/_de.properties index d7064a61c7c1234bbcaa712927df65c8edfab65e..3edb7e12d37901ca672d4d07fc6cc2ae5275a4b0 100644 --- a/src/main/resources/languages/_de.properties +++ b/src/main/resources/languages/_de.properties @@ -359,7 +359,8 @@ settingstab.button.save=Speichern settingstab.button.server.online=Online Server settingstab.button.server.local=Lokaler Server -splashscreen.label.password=Passwort: +login.password=Passwort +login.button=Login datepicker.label.month=Monat: datepicker.label.year=Jahr: diff --git a/src/main/resources/languages/_en.properties b/src/main/resources/languages/_en.properties index 0f373a69cae58fb90bd2a1d27401b1b543efe56c..26d990d47e664c35192e1e6cd88b8cbcce41b3c1 100644 --- a/src/main/resources/languages/_en.properties +++ b/src/main/resources/languages/_en.properties @@ -358,7 +358,8 @@ settingstab.button.save=Save settingstab.button.server.online=Online Server settingstab.button.server.local=Local Server -splashscreen.label.password=Password: +login.password=Password +login.button=Login datepicker.label.month=Month: datepicker.label.year=Year: diff --git a/src/main/resources/templates/login.ftl b/src/main/resources/templates/login.ftl index 3dd3d36e114dc1cdf4edf0e585c973295eff6c9f..5d421ace8fd920b331c28c8e3856248683d5f97b 100644 --- a/src/main/resources/templates/login.ftl +++ b/src/main/resources/templates/login.ftl @@ -5,6 +5,7 @@ <link type="text/css" rel="stylesheet" href="/css/login.css"/> <meta name="viewport" content="width=device-width, initial-scale=1.0"/> + <#assign locale = static["tools.Localization"]> </head> <body class="budgetmaster-blue-light"> <main> @@ -15,15 +16,22 @@ <span class="card-title"> <div id="logo-container" class="center-align"><img id="logo" src="/images/Logo_with_text_medium_res.png"></div> </span> - <div class="row"> - <div class="input-field col s12"> - <input id="password" type="password" class="validate"> - <label for="password">Passwort</label> + <form action="/login" method="post"> + <div class="row"> + <div class="input-field col s12"> + <input id="password" type="password" name="name"> + <label for="password">${locale.getString("account.new.label.name")}</label> + </div> </div> - </div> - <div class="right-align"> - <a class="waves-effect waves-light btn budgetmaster-blue"><i class="material-icons right">send</i>Login</a> - </div> + + <div class="row"> + <div class="col s12 right-align"> + <button class="btn waves-effect waves-light budgetmaster-blue" type="submit" name="action"> + <i class="material-icons left">send</i>${locale.getString("login.button")} + </button> + </div> + </div> + </form> </div> </div> </div>