diff --git a/class.png b/class.png index 08eb192..d9c159a 100644 --- a/class.png +++ b/class.png Binary files differ diff --git a/class.pu b/class.pu index 5a78ca7..b239eb7 100644 --- a/class.pu +++ b/class.pu @@ -11,6 +11,18 @@ } note bottom of db : spring.datasource.url=jdbc:h2:mem:taskdb\nspring.jpa.hibernate.ddl-auto=none +class SecurityConfig <> { + + passwordEncoder() : PasswordEncoder + + configure(WebSecurity) + configure(HttpSecurity) + configure(AuthenticationManagerBuilder) +} + +class SecurityController <> { + + success() + + showList(loginUser, model) +} + class City <> { + id : Long - citycode : String diff --git a/controller.png b/controller.png index 91f5648..65f849e 100644 --- a/controller.png +++ b/controller.png Binary files differ diff --git a/controller.pu b/controller.pu index b81bd25..e214122 100644 --- a/controller.pu +++ b/controller.pu @@ -1,22 +1,30 @@ @startuml -[*] --> success : /login -[*] --> index : / +[*] --> sidebar -state success { - state "Sign in" as login - login : Username - login : Password +state sidebar { + state "ユーザ管理" as users + state "ログイン" as login + state "ログアウト" as logout + state "BLDGデータリスト" as indeies + state "BLDGデータ登録" as add } -login --> index : / [success] -login --> login : [!success] -state index { - state cities +state "Sign in" as signin { + signin : Username + signin : Password +} +login --> signin : /login +signin --> signin : [!success] +sidebar <-- signin : [success] + +state cities cities : *{citycode} cities : *{cityname} cities : *{path} } +indeies --> cities : /city + state form { state city { city : citycode @@ -25,10 +33,16 @@ } } -index --> index : /delete/{citycode} -index --> form : /edit/{citycode} -index --> form : /add -form --> index : /process[!hasErrors] -form --> form : /process[hasErrors] +state user { + user : username + user : role +} +users --> user : /user + +cities --> cities : /city/delete/{citycode} +cities --> form : /city/edit/{citycode} +add --> form : /city/add +form --> sidebar : [!hasErrors] +form --> form : [hasErrors] @enduml \ No newline at end of file diff --git a/pom.xml b/pom.xml index 958d5e5..761aa3b 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ org.springframework.boot spring-boot-starter-parent - 2.7.1 + 2.6.2 osm.surveyor.solr diff --git a/src/main/java/osm/surveyor/task/CityController.java b/src/main/java/osm/surveyor/task/CityController.java deleted file mode 100644 index a4baace..0000000 --- a/src/main/java/osm/surveyor/task/CityController.java +++ /dev/null @@ -1,51 +0,0 @@ -package osm.surveyor.task; - -import org.springframework.stereotype.Controller; -import org.springframework.ui.Model; -import org.springframework.validation.BindingResult; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.ModelAttribute; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; - -import lombok.RequiredArgsConstructor; -import osm.surveyor.task.model.City; - -@RequiredArgsConstructor -@Controller -public class CityController { - private final CityRepository repository; - - @GetMapping("/") - public String showList(Model model) { - model.addAttribute("cities", repository.findAll()); - return "index"; - } - - @GetMapping("/add") - public String addCity(@ModelAttribute City city) { - return "form"; - } - - @PostMapping("/process") - public String process(@Validated @ModelAttribute City city, BindingResult result) { - if (result.hasErrors()) { - return "form"; - } - repository.save(city); - return "redirect:/"; - } - - @GetMapping("/edit/{id}") - public String editCity(@PathVariable Long id, Model model) { - model.addAttribute("city", repository.findById(id)); - return "form"; - } - - @GetMapping("/delete/{id}") - public String deleteCity(@PathVariable Long id) { - repository.deleteById(id); - return "redirect:/"; - } -} diff --git a/src/main/java/osm/surveyor/task/CityRepository.java b/src/main/java/osm/surveyor/task/CityRepository.java deleted file mode 100644 index 3145435..0000000 --- a/src/main/java/osm/surveyor/task/CityRepository.java +++ /dev/null @@ -1,8 +0,0 @@ -package osm.surveyor.task; - -import org.springframework.data.jpa.repository.JpaRepository; - -import osm.surveyor.task.model.City; - -public interface CityRepository extends JpaRepository { -} diff --git a/src/main/java/osm/surveyor/task/DataLoader.java b/src/main/java/osm/surveyor/task/DataLoader.java deleted file mode 100644 index 2622a03..0000000 --- a/src/main/java/osm/surveyor/task/DataLoader.java +++ /dev/null @@ -1,29 +0,0 @@ -package osm.surveyor.task; - -import org.springframework.boot.CommandLineRunner; -import org.springframework.stereotype.Component; - -import lombok.RequiredArgsConstructor; -import osm.surveyor.task.model.City; - -@RequiredArgsConstructor -@Component -public class DataLoader implements CommandLineRunner { - private final CityRepository repository; - - @Override - public void run(String... args) throws Exception { - City city = new City(); - city.setCitycode("01100"); - city.setCityname("北海道 札幌市"); - city.setFolder("01100_sapporo-shi_2020"); - repository.save(city); - - city = new City(); - city.setCitycode("07203"); - city.setCityname("福島県 郡山市"); - city.setFolder("07203_koriyama-shi_2020"); - repository.save(city); - } - -} diff --git a/src/main/java/osm/surveyor/task/city/CityController.java b/src/main/java/osm/surveyor/task/city/CityController.java new file mode 100644 index 0000000..3e411fd --- /dev/null +++ b/src/main/java/osm/surveyor/task/city/CityController.java @@ -0,0 +1,51 @@ +package osm.surveyor.task.city; + +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.validation.BindingResult; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; + +import lombok.RequiredArgsConstructor; +import osm.surveyor.task.city.model.City; + +@RequiredArgsConstructor +@Controller +public class CityController { + private final CityRepository repository; + + @GetMapping("/city") + public String showList(Model model) { + model.addAttribute("cities", repository.findAll()); + return "cities"; + } + + @GetMapping("/city/add") + public String addCity(@ModelAttribute City city) { + return "form"; + } + + @PostMapping("/city/process") + public String process(@Validated @ModelAttribute City city, BindingResult result) { + if (result.hasErrors()) { + return "form"; + } + repository.save(city); + return "redirect:/city"; + } + + @GetMapping("/city/edit/{id}") + public String editCity(@PathVariable Long id, Model model) { + model.addAttribute("city", repository.findById(id)); + return "form"; + } + + @GetMapping("/city/delete/{id}") + public String deleteCity(@PathVariable Long id) { + repository.deleteById(id); + return "redirect:/city"; + } +} diff --git a/src/main/java/osm/surveyor/task/city/CityRepository.java b/src/main/java/osm/surveyor/task/city/CityRepository.java new file mode 100644 index 0000000..a53971f --- /dev/null +++ b/src/main/java/osm/surveyor/task/city/CityRepository.java @@ -0,0 +1,8 @@ +package osm.surveyor.task.city; + +import org.springframework.data.jpa.repository.JpaRepository; + +import osm.surveyor.task.city.model.City; + +public interface CityRepository extends JpaRepository { +} diff --git a/src/main/java/osm/surveyor/task/city/DataLoader.java b/src/main/java/osm/surveyor/task/city/DataLoader.java new file mode 100644 index 0000000..2f86601 --- /dev/null +++ b/src/main/java/osm/surveyor/task/city/DataLoader.java @@ -0,0 +1,29 @@ +package osm.surveyor.task.city; + +import org.springframework.boot.CommandLineRunner; +import org.springframework.stereotype.Component; + +import lombok.RequiredArgsConstructor; +import osm.surveyor.task.city.model.City; + +@RequiredArgsConstructor +@Component +public class DataLoader implements CommandLineRunner { + private final CityRepository repository; + + @Override + public void run(String... args) throws Exception { + City city = new City(); + city.setCitycode("01100"); + city.setCityname("北海道 札幌市"); + city.setFolder("01100_sapporo-shi_2020"); + repository.save(city); + + city = new City(); + city.setCitycode("07203"); + city.setCityname("福島県 郡山市"); + city.setFolder("07203_koriyama-shi_2020"); + repository.save(city); + } + +} diff --git a/src/main/java/osm/surveyor/task/city/model/City.java b/src/main/java/osm/surveyor/task/city/model/City.java new file mode 100644 index 0000000..0e4e7be --- /dev/null +++ b/src/main/java/osm/surveyor/task/city/model/City.java @@ -0,0 +1,32 @@ +package osm.surveyor.task.city.model; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.validation.constraints.NotBlank; + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +@Entity +public class City { + @Id + @GeneratedValue(strategy=GenerationType.IDENTITY) + private Long id; + + @NotBlank + private String citycode; + + @NotBlank + private String cityname; + + @NotBlank + private String folder; + + private Double lng; + + private Double lat; +} diff --git a/src/main/java/osm/surveyor/task/config/SecurityConfig.java b/src/main/java/osm/surveyor/task/config/SecurityConfig.java deleted file mode 100644 index e03eb35..0000000 --- a/src/main/java/osm/surveyor/task/config/SecurityConfig.java +++ /dev/null @@ -1,47 +0,0 @@ -package osm.surveyor.task.config; - -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; -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.crypto.bcrypt.BCryptPasswordEncoder; -import org.springframework.security.crypto.password.PasswordEncoder; - -@Configuration -@EnableWebSecurity -public class SecurityConfig extends WebSecurityConfigurerAdapter { - - @Bean - public PasswordEncoder passwordEncoder() { - // パスワードの暗号化用に、BCrypt(ビー・クリプト)を使用します - return new BCryptPasswordEncoder(); - } - - @Override - protected void configure(HttpSecurity http) throws Exception { - http - // 認証リクエストの設定 - .authorizeRequests() - // 認証の必要があるように設定 - .anyRequest().authenticated() - .and() - // フォームベース認証の設定 - .formLogin(); - } - - @Override - protected void configure(AuthenticationManagerBuilder auth) - throws Exception { - auth - // メモリ内認証を設定 - .inMemoryAuthentication() - // "user"を追加 - .withUser("user") - // "password"をBCryptで暗号化 - .password(passwordEncoder().encode("password")) - // 権限(ロール)を設定 - .authorities("ROLE_USER"); - } -} diff --git a/src/main/java/osm/surveyor/task/controller/SecurityController.java b/src/main/java/osm/surveyor/task/controller/SecurityController.java deleted file mode 100644 index 0b61f97..0000000 --- a/src/main/java/osm/surveyor/task/controller/SecurityController.java +++ /dev/null @@ -1,13 +0,0 @@ -package osm.surveyor.task.controller; - -import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.GetMapping; - -@Controller -public class SecurityController { - - @GetMapping("/login") - public String success() { - return "success"; - } -} diff --git a/src/main/java/osm/surveyor/task/model/City.java b/src/main/java/osm/surveyor/task/model/City.java deleted file mode 100644 index 68138ec..0000000 --- a/src/main/java/osm/surveyor/task/model/City.java +++ /dev/null @@ -1,32 +0,0 @@ -package osm.surveyor.task.model; - -import javax.persistence.Entity; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; -import javax.validation.constraints.NotBlank; - -import lombok.Getter; -import lombok.Setter; - -@Getter -@Setter -@Entity -public class City { - @Id - @GeneratedValue(strategy=GenerationType.IDENTITY) - private Long id; - - @NotBlank - private String citycode; - - @NotBlank - private String cityname; - - @NotBlank - private String folder; - - private Double lng; - - private Double lat; -} diff --git a/src/main/java/osm/surveyor/task/user/config/SecurityConfig.java b/src/main/java/osm/surveyor/task/user/config/SecurityConfig.java new file mode 100644 index 0000000..0b9e181 --- /dev/null +++ b/src/main/java/osm/surveyor/task/user/config/SecurityConfig.java @@ -0,0 +1,69 @@ +package osm.surveyor.task.user.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.builders.WebSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.security.web.util.matcher.AntPathRequestMatcher; + +@Configuration +@EnableWebSecurity +public class SecurityConfig extends WebSecurityConfigurerAdapter { + + @Bean + public PasswordEncoder passwordEncoder() { + return new BCryptPasswordEncoder(); + } + + @Override + public void configure(WebSecurity web) throws Exception { + // セキュリティ設定を、無視(ignoring)するパスを指定します + // 通常、cssやjs、imgなどの静的リソースを指定します + web.ignoring().antMatchers("/city/**", "/css/**", "/img/**", "/webjars/**"); + } + + @Override + protected void configure(HttpSecurity http) throws Exception { + http.authorizeRequests() + // 「/login」と「/error」をアクセス可能にします + .antMatchers("/login", "/error").permitAll() + .anyRequest().authenticated() + .and() + .formLogin() + // ログイン時のURLを指定 + .loginPage("/login") + // 認証後にリダイレクトする場所を指定 + .defaultSuccessUrl("/") + .and() + // ログアウトの設定 + .logout() + // ログアウト時のURLを指定 + .logoutRequestMatcher(new AntPathRequestMatcher("/logout")) + .and() + // Remember-Meの認証を許可します + // これを設定すると、ブラウザを閉じて、 + // 再度開いた場合でも「ログインしたまま」にできます + .rememberMe(); + } + + /** + * ユーザ名「admin」と「user」を用意します + * パスワードは両方とも「password」です + */ + @Override + protected void configure(AuthenticationManagerBuilder auth) throws Exception { + auth.inMemoryAuthentication() + .withUser("admin") + .password(passwordEncoder().encode("password")) + .authorities("ROLE_ADMIN") + .and() + .withUser("user") + .password(passwordEncoder().encode("password")) + .authorities("ROLE_USER"); + } +} diff --git a/src/main/java/osm/surveyor/task/user/controller/SecurityController.java b/src/main/java/osm/surveyor/task/user/controller/SecurityController.java new file mode 100644 index 0000000..adfa9de --- /dev/null +++ b/src/main/java/osm/surveyor/task/user/controller/SecurityController.java @@ -0,0 +1,28 @@ +package osm.surveyor.task.user.controller; + +import org.springframework.security.core.Authentication; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.GetMapping; + +@Controller +public class SecurityController { + + @GetMapping("/login") + public String success() { + return "login"; + } + + @GetMapping("/") + public String showList(Authentication loginUser, Model model) { + if (loginUser == null) { + model.addAttribute("username", ""); + model.addAttribute("role", ""); + } + else { + model.addAttribute("username", loginUser.getName()); + model.addAttribute("role", loginUser.getAuthorities()); + } + return "user"; + } +} diff --git a/src/main/resources/templates/cities.html b/src/main/resources/templates/cities.html new file mode 100644 index 0000000..8df72f2 --- /dev/null +++ b/src/main/resources/templates/cities.html @@ -0,0 +1,80 @@ + + + + + + + + +
+
+ + + +
+
+
+ + +
+
+ +
+
+ +
+
+
Plateau 3D都市データ リスト
+
+
+ + + + + + + + + + + + + + + + + + + + + + +
#citycodecitynamefolder
+ + + 編集 + + + + + 削除 + +
+
+
+ +
+
+
+
+
+ + + diff --git a/src/main/resources/templates/error.html b/src/main/resources/templates/error.html index ee0a35d..25d6e0f 100644 --- a/src/main/resources/templates/error.html +++ b/src/main/resources/templates/error.html @@ -7,6 +7,11 @@ + +
+
+
diff --git a/src/main/resources/templates/form.html b/src/main/resources/templates/form.html index 7333438..756e682 100644 --- a/src/main/resources/templates/form.html +++ b/src/main/resources/templates/form.html @@ -7,6 +7,12 @@ + +
+
+ +
@@ -24,7 +30,7 @@
マッパー登録
-
+
diff --git a/src/main/resources/templates/fragments/message.html b/src/main/resources/templates/fragments/message.html new file mode 100644 index 0000000..b0043fa --- /dev/null +++ b/src/main/resources/templates/fragments/message.html @@ -0,0 +1,33 @@ + + + + + + + + +
+
+ ユーザ名またはパスワードが正しくありません +
+
+ ユーザを新規登録しました +
+
+ ログアウトしました +
+
+ + +
+
+
+
+ +
ページを表示できません
+ ← ホームに戻る +
+
+ + + diff --git a/src/main/resources/templates/fragments/sidebar.html b/src/main/resources/templates/fragments/sidebar.html index 46ae356..6200151 100644 --- a/src/main/resources/templates/fragments/sidebar.html +++ b/src/main/resources/templates/fragments/sidebar.html @@ -1,11 +1,81 @@ - + + +