diff options
Diffstat (limited to 'src/main/java/org/berzerkula/builddb')
13 files changed, 949 insertions, 0 deletions
diff --git a/src/main/java/org/berzerkula/builddb/BuilddbApplication.java b/src/main/java/org/berzerkula/builddb/BuilddbApplication.java new file mode 100644 index 0000000..7ab9042 --- /dev/null +++ b/src/main/java/org/berzerkula/builddb/BuilddbApplication.java @@ -0,0 +1,19 @@ +package org.berzerkula.builddb; + +import com.ulisesbocchio.jasyptspringboot.annotation.EnableEncryptableProperties; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@EnableEncryptableProperties +@SpringBootApplication +public class BuilddbApplication { + + private static final Logger logger = LoggerFactory.getLogger(BuilddbApplication.class); + + public static void main(String[] args) { + SpringApplication.run(BuilddbApplication.class, args); + } + +} diff --git a/src/main/java/org/berzerkula/builddb/config/SecurityConfig.java b/src/main/java/org/berzerkula/builddb/config/SecurityConfig.java new file mode 100644 index 0000000..dbaacd5 --- /dev/null +++ b/src/main/java/org/berzerkula/builddb/config/SecurityConfig.java @@ -0,0 +1,79 @@ +package org.berzerkula.builddb.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +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.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.security.web.SecurityFilterChain; + +@Configuration +@EnableWebSecurity +@EnableMethodSecurity +public class SecurityConfig { + + @Bean + public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { + return http + .authorizeHttpRequests( auth -> auth + .requestMatchers("/").permitAll() + .requestMatchers("/actuator/**").hasRole("admin") + .requestMatchers("/env/**").hasRole("admin") + .requestMatchers("/health/**").hasRole("admin") + .requestMatchers("/info/**").hasRole("admin") + .requestMatchers("/contact").permitAll() + .requestMatchers("/pkgs/**").hasRole("client") + .requestMatchers("/register").permitAll() + .requestMatchers("/login").permitAll() + .requestMatchers("/logout").permitAll() + .anyRequest().authenticated() + ) + .formLogin(form -> form + .loginPage("/login") + .usernameParameter("email") + .passwordParameter("password") + .defaultSuccessUrl("/", true) + ) + .logout(config -> config.logoutSuccessUrl("/")) + .build(); + } + + + @Bean + public PasswordEncoder passwordEncoder() { + return new BCryptPasswordEncoder(); + } +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/java/org/berzerkula/builddb/controllers/AccountController.java b/src/main/java/org/berzerkula/builddb/controllers/AccountController.java new file mode 100644 index 0000000..6cec175 --- /dev/null +++ b/src/main/java/org/berzerkula/builddb/controllers/AccountController.java @@ -0,0 +1,141 @@ +package org.berzerkula.builddb.controllers; + +import java.util.Date; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.core.Authentication; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.validation.BindingResult; +import org.springframework.validation.FieldError; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.PostMapping; + +import org.berzerkula.builddb.models.AppUser; +import org.berzerkula.builddb.models.RegisterDto; +import org.berzerkula.builddb.repositories.AppUserRepository; + +import jakarta.validation.Valid; + +@Controller +public class AccountController { + + @Autowired + private AppUserRepository repo; + + @GetMapping("/profile") + public String profile(Authentication auth, Model model) { + AppUser user = repo.findByEmail(auth.getName()); + model.addAttribute("appUser", user); + + return "profile"; + } + + @GetMapping("/login") + public String login() { + return "login"; + } + + @GetMapping("/register") + public String register(Model model) { + RegisterDto registerDto = new RegisterDto(); + model.addAttribute(registerDto); + model.addAttribute("success", false); + return "register"; + } + + @PostMapping("/register") + public String register( + Model model, + @Valid @ModelAttribute RegisterDto registerDto, + BindingResult result + ) { + + if (!registerDto.getPassword().equals(registerDto.getConfirmPassword())) { + result.addError( + new FieldError("registerDto", "confirmPassword" + , "Password and Confirm Password do not match") + ); + } + + + AppUser appUser = repo.findByEmail(registerDto.getEmail()); + if (appUser != null) { + result.addError( + new FieldError("registerDto", "email" + , "Email address is already used") + ); + } + + + if (result.hasErrors()) { + return "register"; + } + + + try { + // create new account + var bCryptEncoder = new BCryptPasswordEncoder(); + + + AppUser newUser = new AppUser(); + newUser.setFirstName(registerDto.getFirstName()); + newUser.setLastName(registerDto.getLastName()); + newUser.setEmail(registerDto.getEmail()); + newUser.setPhone(registerDto.getPhone()); + newUser.setAddress(registerDto.getAddress()); + newUser.setRole("client"); + newUser.setCreatedAt(new Date()); + newUser.setPassword(bCryptEncoder.encode(registerDto.getPassword())); + + repo.save(newUser); + + + model.addAttribute("registerDto", new RegisterDto()); + model.addAttribute("success", true); + } + catch(Exception ex) { + result.addError( + new FieldError("registerDto", "firstName" + , ex.getMessage()) + ); + } + + return "register"; + } +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/java/org/berzerkula/builddb/controllers/DashboardController.java b/src/main/java/org/berzerkula/builddb/controllers/DashboardController.java new file mode 100644 index 0000000..e928312 --- /dev/null +++ b/src/main/java/org/berzerkula/builddb/controllers/DashboardController.java @@ -0,0 +1,27 @@ +package org.berzerkula.builddb.controllers; + +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; + +@Controller +public class DashboardController { + + @GetMapping("/user") + public String userDashboard() { + return "user"; + } + + @GetMapping("/client") + public String clientDashboard() { + return "client"; + } + + @GetMapping("/admin") + public String adminDashboard() { + return "admin"; + } + + @GetMapping("/actuatorDashboard") + public String actuatorDashboard() { return "actuatorDashboard"; } + +} diff --git a/src/main/java/org/berzerkula/builddb/controllers/HomeController.java b/src/main/java/org/berzerkula/builddb/controllers/HomeController.java new file mode 100644 index 0000000..ad171c8 --- /dev/null +++ b/src/main/java/org/berzerkula/builddb/controllers/HomeController.java @@ -0,0 +1,47 @@ +package org.berzerkula.builddb.controllers; + +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; + +@Controller +public class HomeController { + + @GetMapping("/contact") + public String contact() { + return "contact"; + } + +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/java/org/berzerkula/builddb/controllers/PkgController.java b/src/main/java/org/berzerkula/builddb/controllers/PkgController.java new file mode 100644 index 0000000..404a58b --- /dev/null +++ b/src/main/java/org/berzerkula/builddb/controllers/PkgController.java @@ -0,0 +1,169 @@ +package org.berzerkula.builddb.controllers; + + +import jakarta.persistence.OrderBy; +import jakarta.validation.Valid; +import org.berzerkula.builddb.models.Pkg; +import org.berzerkula.builddb.models.PkgDto; +import org.berzerkula.builddb.repositories.PkgRepository; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Sort; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.validation.BindingResult; +import org.springframework.web.bind.annotation.*; + +import java.util.List; +import java.util.Objects; + +@Controller +@RequestMapping("/pkgs") +public class PkgController { + + private static final Logger logger = LoggerFactory.getLogger(PkgController.class); + + @Autowired + private PkgRepository repo; + + @GetMapping({"", "/", "/index"}) + public String showPkgList(Model model, + @RequestParam(defaultValue = "sequence,asc") String[] sort, + @RequestParam(defaultValue = "") String repotable) { + try { + String sortField = sort[0]; + String sortDirection = sort[1]; + + Sort.Direction direction = sortDirection.equals("desc") ? Sort.Direction.DESC : Sort.Direction.ASC; + Sort.Order order = new Sort.Order(direction, sortField); + + List<Pkg> pkgs = repo.findAll(Sort.by(order)); + + model.addAttribute("pkgs", pkgs); + model.addAttribute("sortField", sortField); + model.addAttribute("sortDirection", sortDirection); + model.addAttribute("reverseSortDirection", sortDirection.equals("asc") ? "desc" : "asc"); + + } catch (Exception e) { + logger.error(e.getMessage()); + } + + return "pkgs/index"; + } + + @GetMapping("/add") + public String showAddPkgForm(Model model) { + PkgDto pkgDto = new PkgDto(); + model.addAttribute("pkgDto", pkgDto); + return "pkgs/add"; + } + + @PostMapping("/add") + public String addPkg( + @Valid + @ModelAttribute + PkgDto pkgDto, BindingResult result ) { + + if (result.hasErrors()) { + return "pkgs/add"; + } + + try { + + Pkg pkg = new Pkg(); + pkg.setSequence(pkgDto.getSequence()); + pkg.setName(pkgDto.getName()); + pkg.setVersion(pkgDto.getVersion()); + pkg.setConfigure(pkgDto.getConfigure()); + pkg.setBuild(pkgDto.getBuild()); + pkg.setInstall(pkgDto.getInstall()); + pkg.setSetup(pkgDto.getSetup()); + pkg.setNotes(pkgDto.getNotes()); + pkg.setUrl(pkgDto.getUrl()); + + repo.save(pkg); + + } catch (Exception e) { + logger.error(e.getMessage()); + } + + return "redirect:/pkgs"; + } + + @GetMapping("/edit") + public String showEditPkgForm(Model model, @RequestParam int id) { + + try { + Pkg pkg = repo.findById(id).get(); + model.addAttribute("pkg", pkg); + + PkgDto pkgDto = new PkgDto(); + pkgDto.setSequence(pkg.getSequence()); + pkgDto.setName(pkg.getName()); + pkgDto.setVersion(pkg.getVersion()); + pkgDto.setConfigure(pkg.getConfigure()); + pkgDto.setBuild(pkg.getBuild()); + pkgDto.setInstall(pkg.getInstall()); + pkgDto.setSetup(pkg.getSetup()); + pkgDto.setNotes(pkg.getNotes()); + pkgDto.setUrl(pkg.getUrl()); + + model.addAttribute("pkgDto", pkgDto); + + } catch(Exception ex) { + logger.error("Exception: {}", ex.getMessage()); + } + + return "pkgs/edit"; + } + + @PostMapping("/edit") + public String editPkg( + Model model, + @RequestParam int id, + @Valid + @ModelAttribute PkgDto pkgDto, BindingResult result ) { + + try { + Pkg pkg = repo.findById(id).get(); + model.addAttribute("pkg", pkg); + + if (result.hasErrors()) { + return "pkgs/edit"; + } + + pkg.setSequence(pkgDto.getSequence()); + pkg.setName(pkgDto.getName()); + pkg.setVersion(pkgDto.getVersion()); + pkg.setConfigure(pkgDto.getConfigure()); + pkg.setBuild(pkgDto.getBuild()); + pkg.setInstall(pkgDto.getInstall()); + pkg.setSetup(pkgDto.getSetup()); + pkg.setNotes(pkgDto.getNotes()); + pkg.setUrl(pkgDto.getUrl()); + + repo.save(pkg); + + } catch(Exception ex) { + logger.error("Exception: {}", ex.getMessage()); + } + return "redirect:/pkgs/#" + id; + + } + + @GetMapping("/delete") + public String deletePkg(@RequestParam int id) { + + try { + Pkg pkg = repo.findById(id).get(); + + repo.delete(pkg); + + } catch (Exception ex) { + logger.error("Exception: {}", ex.getMessage()); + } + + return "redirect:/pkgs/"; + } +} diff --git a/src/main/java/org/berzerkula/builddb/models/AppUser.java b/src/main/java/org/berzerkula/builddb/models/AppUser.java new file mode 100644 index 0000000..21c5a33 --- /dev/null +++ b/src/main/java/org/berzerkula/builddb/models/AppUser.java @@ -0,0 +1,107 @@ +package org.berzerkula.builddb.models; + +import jakarta.persistence.*; + +import java.util.Date; + +@Entity +@Table(name="users") +public class AppUser { + + @Id + @GeneratedValue(strategy=GenerationType.IDENTITY) + private int id; + + private String firstName; + private String lastName; + + @Column(unique = true, nullable = false) + private String email; + + private String phone; + private String address; + private String password; + private String role; + private Date createdAt; + + public AppUser(String firstName, String lastName, String email, String phone, String address, + String password, String role) { + this.firstName = firstName; + this.lastName = lastName; + this.email = email; + this.password = password; + this.role = role; + this.createdAt = new Date(); + } + + public AppUser() {} + + public int getId() { + return id; + } + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + public String getPhone() { + return phone; + } + + public void setPhone(String phone) { + this.phone = phone; + } + + public String getAddress() { + return address; + } + + public void setAddress(String address) { + this.address = address; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public String getRole() { + return role; + } + + public void setRole(String role) { + this.role = role; + } + + public Date getCreatedAt() { + return createdAt; + } + + public void setCreatedAt(Date createdAt) { + this.createdAt = createdAt; + } + +} diff --git a/src/main/java/org/berzerkula/builddb/models/Pkg.java b/src/main/java/org/berzerkula/builddb/models/Pkg.java new file mode 100644 index 0000000..5ce80ba --- /dev/null +++ b/src/main/java/org/berzerkula/builddb/models/Pkg.java @@ -0,0 +1,118 @@ +package org.berzerkula.builddb.models; + +import jakarta.persistence.*; + +@Entity +@Table(name = "rock5b_srv_bld") +public class Pkg { + @Id + @GeneratedValue(strategy= GenerationType.IDENTITY) + private int id; + + private String name; + private Integer sequence; + private String version; + @Column(columnDefinition = "TEXT") + private String configure; + @Column(columnDefinition = "TEXT") + private String build; + @Column(columnDefinition = "TEXT") + private String install; + @Column(columnDefinition = "TEXT") + private String setup; + @Column(columnDefinition = "TEXT") + private String notes; + @Column(columnDefinition = "TEXT") + private String url; + + public Pkg(Integer sequence, String name, String version, String configure, String build, String install, + String setup, String notes, String url) { + this.sequence = sequence; + this.name = name; + this.version = version; + this.configure = configure; + this.build = build; + this.install = install; + this.setup = setup; + this.notes = notes; + this.url = url; + } + + public Pkg() {} + + public int getId() { + return id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Integer getSequence() { + return sequence; + } + + public void setSequence(Integer seq) { + this.sequence = seq; + } + + public String getVersion() { + return version; + } + + public void setVersion(String version) { + this.version = version; + } + + public String getConfigure() { + return configure; + } + + public void setConfigure(String configure) { + this.configure = configure; + } + + public String getBuild() { + return build; + } + + public void setBuild(String build) { + this.build = build; + } + + public String getInstall() { + return install; + } + + public void setInstall(String install) { + this.install = install; + } + + public String getSetup() { + return setup; + } + + public void setSetup(String setup) { + this.setup = setup; + } + + public String getNotes() { + return notes; + } + + public void setNotes(String notes) { + this.notes = notes; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } +} diff --git a/src/main/java/org/berzerkula/builddb/models/PkgDto.java b/src/main/java/org/berzerkula/builddb/models/PkgDto.java new file mode 100644 index 0000000..04c47ea --- /dev/null +++ b/src/main/java/org/berzerkula/builddb/models/PkgDto.java @@ -0,0 +1,104 @@ +package org.berzerkula.builddb.models; + +import jakarta.validation.constraints.Digits; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import org.springframework.data.annotation.ReadOnlyProperty; + +public class PkgDto { + @ReadOnlyProperty + private Integer id; + + @NotNull(message = "Required") + @Digits(integer = 4, fraction = 0) + private Integer sequence; + + @NotEmpty(message = "Required") + private String name; + + @NotEmpty(message = "Required") + private String version; + + private String configure; + private String build; + private String install; + private String setup; + private String notes; + private String url; + + public Integer getSequence() { + return sequence; + } + + public void setSequence(Integer sequence) { + this.sequence = sequence; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getVersion() { + return version; + } + + public void setVersion(String version) { + this.version = version; + } + + public String getConfigure() { + return configure; + } + + public void setConfigure(String configure) { + this.configure = configure; + } + + public String getBuild() { + return build; + } + + public void setBuild(String build) { + this.build = build; + } + + public String getInstall() { + return install; + } + + public void setInstall(String install) { + this.install = install; + } + + public String getSetup() { + return setup; + } + + public void setSetup(String setup) { + this.setup = setup; + } + + public String getNotes() { + return notes; + } + + public void setNotes(String notes) { + this.notes = notes; + } + + public Integer getId() { + return id; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } +} diff --git a/src/main/java/org/berzerkula/builddb/models/RegisterDto.java b/src/main/java/org/berzerkula/builddb/models/RegisterDto.java new file mode 100644 index 0000000..eebf014 --- /dev/null +++ b/src/main/java/org/berzerkula/builddb/models/RegisterDto.java @@ -0,0 +1,84 @@ +package org.berzerkula.builddb.models; + +import jakarta.validation.constraints.*; + +public class RegisterDto { + + @NotEmpty + private String firstName; + + @NotEmpty + private String lastName; + + @NotEmpty + @Email + private String email; + + private String phone; + + private String address; + + @Size(min = 6, message = "Minimum Password length is 6 characters") + private String password; + + private String confirmPassword; + + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + public String getPhone() { + return phone; + } + + public void setPhone(String phone) { + this.phone = phone; + } + + public String getAddress() { + return address; + } + + public void setAddress(String address) { + this.address = address; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public String getConfirmPassword() { + return confirmPassword; + } + + public void setConfirmPassword(String confirmPassword) { + this.confirmPassword = confirmPassword; + } + + +} diff --git a/src/main/java/org/berzerkula/builddb/repositories/AppUserRepository.java b/src/main/java/org/berzerkula/builddb/repositories/AppUserRepository.java new file mode 100644 index 0000000..756d56a --- /dev/null +++ b/src/main/java/org/berzerkula/builddb/repositories/AppUserRepository.java @@ -0,0 +1,10 @@ +package org.berzerkula.builddb.repositories; + +import org.springframework.data.jpa.repository.JpaRepository; + +import org.berzerkula.builddb.models.AppUser; + +public interface AppUserRepository extends JpaRepository<AppUser, Integer> { + + public AppUser findByEmail(String email); +} diff --git a/src/main/java/org/berzerkula/builddb/repositories/PkgRepository.java b/src/main/java/org/berzerkula/builddb/repositories/PkgRepository.java new file mode 100644 index 0000000..30e80eb --- /dev/null +++ b/src/main/java/org/berzerkula/builddb/repositories/PkgRepository.java @@ -0,0 +1,8 @@ +package org.berzerkula.builddb.repositories; + +import org.berzerkula.builddb.models.Pkg; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface PkgRepository extends JpaRepository<Pkg, Integer> { + +} diff --git a/src/main/java/org/berzerkula/builddb/services/AppUserService.java b/src/main/java/org/berzerkula/builddb/services/AppUserService.java new file mode 100644 index 0000000..02cc89f --- /dev/null +++ b/src/main/java/org/berzerkula/builddb/services/AppUserService.java @@ -0,0 +1,36 @@ +package org.berzerkula.builddb.services; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.core.userdetails.User; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.stereotype.Service; + +import org.berzerkula.builddb.models.AppUser; +import org.berzerkula.builddb.repositories.AppUserRepository; + +@Service +public class AppUserService implements UserDetailsService { + @Autowired + private AppUserRepository repo; + + @Override + public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException { + AppUser appUser = repo.findByEmail(email); + + + if (appUser != null) { + var springUser = User.withUsername(appUser.getEmail()) + .password(appUser.getPassword()) + .roles(appUser.getRole()) + .build(); + + return springUser; + } + + + return null; + } + +} |