Github : projectquestion

4. Basic Project

    4. 1 Question & Answer 

 

Question table : This table stores questions posted on the forum. It includes fields for the title (`qtitle`), content (`qcontent`), author information (`qauthor`), and creation timestamp (`qdate`).

 

      Answer table : This table stores answers to questions. It includes fields for the question's ID (`aqid`), answer content (`acontent`), author information (`aauthor`), and creation timestamp (`adate`).

 

With this setup, each question and its corresponding answers are stored in separate tables, allowing for efficient management of questions and answers.

 

        Here's a detailed list of the topics

 

  • 4.1.1 Basic Board Project:
  • 4.1.2 Project Configuration:
  • 4.1.3 Question C,R,U,D:
  • 4.1.4 Answer with Board:

 

4.1.1 Basic Board Project:

 

 

4.1.2 Project Configuration:

spring.application.name=projectquestion
# Database Setting
spring.datasource.dbcp2.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/securityexam
spring.datasource.username=root
spring.datasource.password=1111
# JPA
spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.show_sql=true

 

 

 

 

     create Database

 

 

 

       create Customer.java

 

 

package com.example.projectquestion;

import java.time.LocalDateTime;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import lombok.Data;

@Data
@Entity
public class Customer {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer cid;

@Column(unique = true)
private String username// for SpringSecurity Policy
private String password// for SpringSecurity Policy
private boolean enabled// for SpringSecurity Policy
private String role;           // for SpringSecurity Policy

@Column(unique = true)
private String cemail;
private String cimage;
private LocalDateTime cdate;

}

 

 

 

 

 

 

 

 

      create SecurityConfig.java Class

package com.example.projectquestion.customer;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
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;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

@Configuration
@EnableWebSecurity
public class SecurityConfig {

@Bean
SecurityFilterChain filterChain(HttpSecurity httpthrows Exception {
http
.authorizeHttpRequests((authorizeHttpRequests) -> authorizeHttpRequests
.requestMatchers(new AntPathRequestMatcher("/**")).permitAll())
.formLogin((formLogin) -> formLogin
.loginPage("/signin")
.defaultSuccessUrl("/")
)
.logout((logout) -> logout
.logoutRequestMatcher(new AntPathRequestMatcher("/signout"))
.logoutSuccessUrl("/")
.invalidateHttpSession(true))
;
return http.build();
}
@Bean
PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfigurationthrows Exception {
return authenticationConfiguration.getAuthenticationManager();

}

}

 

      create CustomerRepository.java

 

package com.example.projectquestion.customer;
import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository;
public interface CustomerRepository extends JpaRepository<Customer, Integer> {

Optional<Customer> findByusername(String username); // login check

}

 

 

 

 

 

      CustomerService.java

package com.example.projectquestion.customer;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
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.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;

@Service
public class CustomerService implements UserDetailsService {

@Autowired
private CustomerRepository customerRepository;

@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {

Optional<Customer> tcustomer = customerRepository.findByusername(username);

if (tcustomer.isEmpty()) {
throw new UsernameNotFoundException("You need to Sign up first...");
}
Customer customer = tcustomer.get();
List<GrantedAuthority> authorities = new ArrayList<>();
if ("ROLE_USER".equals(customer.getRole())) {
authorities.add(new SimpleGrantedAuthority("ROLE_USER"));
} else if ("ROLE_MANAGER".equals(customer.getRole())) {
authorities.add(new SimpleGrantedAuthority("ROLE_MANAGER"));
} else {
authorities.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
}

return new User(customer.getUsername(), customer.getPassword(), authorities);

}

public void create(Customer customer) {

customer.setEnabled(true);
customer.setRole("ROLE_USER"); //ROLE_ADMIN, ROLE_MANAGER, ROLE_PAID...
customer.setCdate(LocalDateTime.now());
BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
customer.setPassword(passwordEncoder.encode(customer.getPassword()));
customerRepository.save(customer);

}
}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

      CustomerController.java

package com.example.projectquestion.customer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;

@Controller
public class CustomerController {

@Autowired
private CustomerService customerService;

@GetMapping("/")
public String signup() {
return "signup";
}

@PostMapping("/signup")
public String signup(Customer customer) {
customerService.create(customer);
return "signup";
}

@GetMapping("/signin")
public String signin(){
return "signin";
}
}

 

 

 

 

 

 

 

 

   

 

      Views

 

 

      signup.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<span sec:authorize="isAnonymous()">Signin First...<a href="/signin">Sign in</a></span>
<span sec:authorize="isAuthenticated()">Welcome...<span th:text="${#authentication.name}"></span>
<span th:text="${#authentication.authorities}"></span>
<a href="/signout">Sign out</a>
</span>


<form action="/signup" method="post">
<input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}" />
<p>ID : <input type="text" name="username">
<p>PW : <input type="password" name="password">
<p>Mail : <input type="text" name="cemail">
<p><input type="submit" value="Sign up">
</form>
</body>
</html>

 

      signin.html

<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
<form action="/signin" method="post">
<div th:if="${param.error}">
<div class="alert alert-danger">
Please, Check your ID or Password...
</div>
</div>
<input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}" />
<p>ID : <input type="text" name="username">
<p>PW : <input type="password" name="password">
<p><input type="submit" value="Sign in">
</form>
</body>
</html>

 

    

 

 

  

  

 

 

 

4.1.3 Question C,R,U,D:

 

  Question Table : This table stores questions posted on the forum. It can include the following fields:

- `qid`: The unique identifier for each question, typically auto-generated as a number or UUID.

- `qtitle`: A string field representing the title of the question.

- `qcontent`: A string field containing the content of the question.

- `qauthor`: A field storing information about the user who posted the question, often set up as a foreign key relationship with another user table. For example, it can contain the user's OBJECT.

- 'qanswer': A object field indicating which answer the question is related to. This relates to the `aquestion` field in the Anawer table.

- `qdate`: A field storing the timestamp when the question was posted.

 

 

      Question.java

package com.example.projectquestion.question;
import java.time.LocalDateTime;
import com.example.projectquestion.customer.Customer;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.ManyToOne;
import lombok.Data;

@Data
@Entity
public class Question {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer qid;

@Column(length = 200)
private String qtitle;

@Column(columnDefinition = "TEXT")
private String qcontent;

@ManyToOne
private Customer qauthor; // User's Object

private LocalDateTime qdate;
}

 

 

 

 

 

 

 

 

 

 

      QuestionRepository.java

 

 

package com.example.projectquestion.question;
import org.springframework.data.jpa.repository.JpaRepository;
public interface QuestionRepository extends JpaRepository<Question, Integer> {

}

 

 

 

 

 

      QuestionService.java & QuestionServiceImpl.java

package com.example.projectquestion.question;
import java.util.List;

public interface QuestionService {

void create(Question question, Principal principal);
List<Question> readlist();
Question readdetail(Integer qid);
void update(Question question);
void delete(Integer qid);

}

 

 

 

 

 

 

 

 

package com.example.projectquestion.question;
import java.security.Principal;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.example.projectquestion.customer.Customer;
import com.example.projectquestion.customer.CustomerRepository;

@Service
public class QuestionServiceImpl implements QuestionService {

@Autowired
private QuestionRepository questionRepository;

@Autowired
private CustomerRepository customerRepository;

@Override
public void create(Question question, Principal principal) {
question.setQdate(LocalDateTime.now());
Optional<Customer> tc = customerRepository.findByusername(principal.getName());
question.setQauthor(tc.get());
questionRepository.save(question);
}
@Override
public List<Question> readlist() {
return questionRepository.findAll();
}
@Override
public Question readdetail(Integer qid) {
Optional<Question> tq = questionRepository.findById(qid);
return tq.get();
}
@Override
public void update(Question question) {
questionRepository.save(question);
}
@Override
public void delete(Integer qid) {
Optional<Question> tq = questionRepository.findById(qid);
questionRepository.delete(tq.get());
}

}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

       QuestionController.java

 

package com.example.projectquestion.question;
import java.security.Principal;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;

@RequestMapping("/question")
@Controller
public class QuestionController {

@Autowired
private QuestionService questionService;
@GetMapping("/create")
public String create() {
return "question/create";
}
@PostMapping("/create")
public String create(Question question, Principal principal) {
questionService.create(question, principal);
return "redirect:/question/readlist";
}
@GetMapping("/readlist")
public String readlist(Model model) {
model.addAttribute("questions", questionService.readlist());
return "question/readlist";
}
@GetMapping("/readdetail/{qid}")
public String readdetail(@PathVariable("qid") Integer qid,
Model model) {
model.addAttribute("question", questionService.readdetail(qid));
return "question/readdetail";
}

}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

      create.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<span sec:authorize="isAnonymous()">Signin First...<a href="/signin">Sign in</a></span>
<span sec:authorize="isAuthenticated()">Welcome...<span th:text="${#authentication.name}"></span>
<span th:text="${#authentication.authorities}"></span>
<a href="/signout">Sign out</a>
</span>
<form action="/question/create" method="post">
<input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}" />
<p>Title : <input type="text" name="qtitle">
<p>Content : <input type="password" name="qcontent">
<p><input type="submit" value="submit">
</form>
<p><a href="/question/readlist">Question List</a>
</body>
</html>

 

 

      readlist.html

<!DOCTYPE html>
<html>
<head>
<meta charset="EUC-KR">
<title>Insert title here</title>
</head>
<body>
<h2> Read List </h2>
<a href="/question/create">CREATE</a><br><br>
<th:block th:each="question: ${questions}">
[[${question.qid}]] /
<a th:href="@{|/question/readdetail/${question.qid}|}" th:text="${question.qtitle}"></a>
/ [[${question.qauthor.username}]] / [[${question.qdate}]]<br>
</th:block>
</body>
</html>

 

 

 

      readdetail.html

<!DOCTYPE html>
<html>
<head>
<meta charset="EUC-KR">
<title>Insert title here</title>
</head>
<body>
<h2> Read Detail </h2>
<a href="/question/readlist">List</a><br><br>
[[${question.qid}]] <br>
[[${question.qtitle}]]<br>
[[${question.qauthor.username}]] <br>
[[${question.qdate}]]<br>
</body>
</html>

 

 

 

ㅅㄷㄴㅅ

 

4.1.4 Answer with Question:

 

  Answer Table : This table stores answers to each question on the question board. It can have the following fields:

- `aid`: The unique identifier for each answer, typically auto-generated as a number or UUID.

- `aquestion`: A object field indicating which question the answer is related to. This relates to the `qanswer` field in the Question table.

- `acontent`: A string field containing the content of the answer.

- `aauthor`: A field storing information about the user who posted the answer, often set up as a foreign key relationship with another user table.

- `adate`: A field storing the timestamp when the answer was posted.

한국정보시스템개발원 |
Hankook Information System Institute

austiny@snu.ac.kr / austiny@gatech.edu