diff --git a/src/main/java/com/example/sinitto/SinittoApplication.java b/src/main/java/com/example/sinitto/SinittoApplication.java
index 7aef98e4..a8243d84 100644
--- a/src/main/java/com/example/sinitto/SinittoApplication.java
+++ b/src/main/java/com/example/sinitto/SinittoApplication.java
@@ -1,5 +1,6 @@
package com.example.sinitto;
+import com.example.sinitto.common.properties.AdminProperties;
import com.example.sinitto.common.properties.DummyProperties;
import com.example.sinitto.common.properties.KakaoProperties;
import org.springframework.boot.SpringApplication;
@@ -10,7 +11,7 @@
@SpringBootApplication
@EnableJpaAuditing
-@EnableConfigurationProperties({KakaoProperties.class, DummyProperties.class})
+@EnableConfigurationProperties({KakaoProperties.class, DummyProperties.class, AdminProperties.class})
@EnableScheduling
public class SinittoApplication {
diff --git a/src/main/java/com/example/sinitto/auth/controller/AuthController.java b/src/main/java/com/example/sinitto/auth/controller/AuthController.java
index fb11918d..ba9750c6 100644
--- a/src/main/java/com/example/sinitto/auth/controller/AuthController.java
+++ b/src/main/java/com/example/sinitto/auth/controller/AuthController.java
@@ -58,7 +58,7 @@ public ResponseEntity kakaoCallback(@RequestParam("code") String
@Operation(summary = "Redis안의 모든 데이터 제거", description = "발급된 refreshToken을 사용하지 못하게 Redis 안의 모든 데이터를 제거합니다.")
@DeleteMapping("/redis")
- public ResponseEntity deleteAllDataFromRedis(){
+ public ResponseEntity deleteAllDataFromRedis() {
tokenService.deleteAllDataFromRedis();
return new ResponseEntity<>(HttpStatus.OK);
}
diff --git a/src/main/java/com/example/sinitto/auth/service/TokenService.java b/src/main/java/com/example/sinitto/auth/service/TokenService.java
index fa972d3d..713708ee 100644
--- a/src/main/java/com/example/sinitto/auth/service/TokenService.java
+++ b/src/main/java/com/example/sinitto/auth/service/TokenService.java
@@ -120,7 +120,7 @@ public TokenResponse refreshAccessToken(String refreshToken) {
return new TokenResponse(newAccessToken, newRefreshToken);
}
- public void deleteAllDataFromRedis(){
+ public void deleteAllDataFromRedis() {
redisTemplate.getConnectionFactory()
.getConnection()
.serverCommands()
diff --git a/src/main/java/com/example/sinitto/common/config/SwaggerConfig.java b/src/main/java/com/example/sinitto/common/config/SwaggerConfig.java
index 9e7a9e76..6e8001c5 100644
--- a/src/main/java/com/example/sinitto/common/config/SwaggerConfig.java
+++ b/src/main/java/com/example/sinitto/common/config/SwaggerConfig.java
@@ -3,9 +3,9 @@
import io.swagger.v3.oas.models.Components;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Info;
-import io.swagger.v3.oas.models.servers.Server;
import io.swagger.v3.oas.models.security.SecurityRequirement;
import io.swagger.v3.oas.models.security.SecurityScheme;
+import io.swagger.v3.oas.models.servers.Server;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
@@ -14,10 +14,9 @@
@Configuration
public class SwaggerConfig {
- private final Environment environment;
-
private static final String LOCAL_SERVER_URL = "http://localhost:8080";
private static final String PROD_SERVER_URL = "https://sinitto.site";
+ private final Environment environment;
public SwaggerConfig(Environment environment) {
this.environment = environment;
diff --git a/src/main/java/com/example/sinitto/common/config/WebConfig.java b/src/main/java/com/example/sinitto/common/config/WebConfig.java
index ae986fd1..75558393 100644
--- a/src/main/java/com/example/sinitto/common/config/WebConfig.java
+++ b/src/main/java/com/example/sinitto/common/config/WebConfig.java
@@ -27,7 +27,7 @@ public class WebConfig implements WebMvcConfigurer {
private static final int CONNECTIONS_PER_IP_PORT_PAIR = 5;
private final JwtInterceptor jwtInterceptor;
- public WebConfig(JwtInterceptor jwtInterceptor){
+ public WebConfig(JwtInterceptor jwtInterceptor) {
this.jwtInterceptor = jwtInterceptor;
}
diff --git a/src/main/java/com/example/sinitto/common/interceptor/JwtInterceptor.java b/src/main/java/com/example/sinitto/common/interceptor/JwtInterceptor.java
index 10b9b13c..9e5ea039 100644
--- a/src/main/java/com/example/sinitto/common/interceptor/JwtInterceptor.java
+++ b/src/main/java/com/example/sinitto/common/interceptor/JwtInterceptor.java
@@ -14,11 +14,12 @@
public class JwtInterceptor implements HandlerInterceptor {
private final MemberTokenService memberTokenService;
- public JwtInterceptor(MemberTokenService memberTokenService){
+ public JwtInterceptor(MemberTokenService memberTokenService) {
this.memberTokenService = memberTokenService;
}
+
@Override
- public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler){
+ public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
if (handler instanceof HandlerMethod) {
HandlerMethod handlerMethod = (HandlerMethod) handler;
Method method = handlerMethod.getMethod();
diff --git a/src/main/java/com/example/sinitto/common/properties/AdminProperties.java b/src/main/java/com/example/sinitto/common/properties/AdminProperties.java
new file mode 100644
index 00000000..a7d6ee35
--- /dev/null
+++ b/src/main/java/com/example/sinitto/common/properties/AdminProperties.java
@@ -0,0 +1,10 @@
+package com.example.sinitto.common.properties;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+
+@ConfigurationProperties(prefix = "admin")
+public record AdminProperties(
+ String adminEmail,
+ String adminPassword
+) {
+}
\ No newline at end of file
diff --git a/src/main/java/com/example/sinitto/common/service/SlackMessageService.java b/src/main/java/com/example/sinitto/common/service/SlackMessageService.java
index 772040ed..59df7d10 100644
--- a/src/main/java/com/example/sinitto/common/service/SlackMessageService.java
+++ b/src/main/java/com/example/sinitto/common/service/SlackMessageService.java
@@ -14,17 +14,14 @@
@Service
public class SlackMessageService {
+ private final RestTemplate restTemplate;
@Value("${slack.notice.webhook.url}")
private String slackNoticeWebhookUrl;
-
@Value("${slack.charge.request.url}")
private String chargeRequestUrl;
-
@Value("${slack.withdraw.request.url}")
private String withdrawRequestUrl;
- private final RestTemplate restTemplate;
-
public SlackMessageService(RestTemplate restTemplate) {
this.restTemplate = restTemplate;
}
diff --git a/src/main/java/com/example/sinitto/guard/service/GuardService.java b/src/main/java/com/example/sinitto/guard/service/GuardService.java
index b08fab92..3d715644 100644
--- a/src/main/java/com/example/sinitto/guard/service/GuardService.java
+++ b/src/main/java/com/example/sinitto/guard/service/GuardService.java
@@ -59,7 +59,7 @@ public void createSenior(Long memberId, SeniorRequest seniorRequest) {
);
if (member.isSinitto()) throw new BadRequestException("보호자만 이용할 수 있습니다.");
- if(seniorRepository.existsByPhoneNumber(seniorRequest.seniorPhoneNumber())) {
+ if (seniorRepository.existsByPhoneNumber(seniorRequest.seniorPhoneNumber())) {
throw new BadRequestException("이미 등록되어 있는 전화번호 입니다.");
}
@@ -90,7 +90,7 @@ public void updateSenior(Long memberId, Long seniorId, SeniorRequest seniorReque
() -> new NotFoundException("이메일에 해당하는 시니어를 찾을 수 없습니다.")
);
- if(!senior.getPhoneNumber().equals(seniorRequest.seniorPhoneNumber())
+ if (!senior.getPhoneNumber().equals(seniorRequest.seniorPhoneNumber())
&& seniorRepository.existsByPhoneNumber(seniorRequest.seniorPhoneNumber())) {
throw new BadRequestException("이미 등록되어 있는 전화번호 입니다.");
}
diff --git a/src/main/java/com/example/sinitto/member/controller/MemberAdminController.java b/src/main/java/com/example/sinitto/member/controller/MemberAdminController.java
index cd05991b..fd1bd10f 100644
--- a/src/main/java/com/example/sinitto/member/controller/MemberAdminController.java
+++ b/src/main/java/com/example/sinitto/member/controller/MemberAdminController.java
@@ -1,9 +1,11 @@
package com.example.sinitto.member.controller;
import com.example.sinitto.auth.service.TokenService;
+import com.example.sinitto.common.properties.AdminProperties;
import com.example.sinitto.common.properties.DummyProperties;
import com.example.sinitto.member.entity.Member;
import com.example.sinitto.member.repository.MemberRepository;
+import jakarta.servlet.http.HttpSession;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
@@ -15,32 +17,61 @@
import java.util.List;
@Controller
-@RequestMapping("/dummy")
+@RequestMapping
public class MemberAdminController {
private final MemberRepository memberRepository;
private final TokenService tokenService;
private final DummyProperties dummyProperties;
-
+ private final AdminProperties adminProperties;
private final List dummyEmails = Arrays.asList(
"1chulsoo@example.com", "2kim@example.com", "3lee@example.com", "4park@example.com", "5choi@example.com",
"6jeong@example.com", "7han@example.com", "8oh@example.com", "9lim@example.com", "10song@example.com"
);
- public MemberAdminController(MemberRepository memberRepository, TokenService tokenService, DummyProperties dummyProperties) {
+ public MemberAdminController(MemberRepository memberRepository, TokenService tokenService, DummyProperties dummyProperties, AdminProperties adminProperties) {
this.memberRepository = memberRepository;
this.tokenService = tokenService;
this.dummyProperties = dummyProperties;
+ this.adminProperties = adminProperties;
}
- @GetMapping
+ @GetMapping("/dummy")
public String showDummyLoginPage(Model model) {
List dummyMembers = memberRepository.findAllByEmailIn(dummyEmails);
model.addAttribute("members", dummyMembers);
return "dummy/login";
}
- @PostMapping
+ @GetMapping("/admin/login")
+ public String showAdminLoginPage(HttpSession session) {
+ if (isAdmin(session)) {
+ return "redirect:/admin/point/charge";
+ }
+ return "point/login";
+ }
+
+ @PostMapping("/admin/login")
+ public String login(@RequestParam String email,
+ @RequestParam String password,
+ HttpSession session) {
+ if (adminProperties.adminEmail().equals(email) && adminProperties.adminPassword().equals(password)) {
+ session.setAttribute("email", email);
+ session.setAttribute("role", "ADMIN");
+ session.setMaxInactiveInterval(1800);
+ return "redirect:/admin/point/charge";
+ } else {
+ return "redirect:/admin/login?error=true";
+ }
+ }
+
+ @PostMapping("/admin/logout")
+ public String logout(HttpSession session) {
+ session.invalidate();
+ return "redirect:/admin/login";
+ }
+
+ @PostMapping("/dummy")
public String login(
@RequestParam("email") String email,
@RequestParam("password") String password,
@@ -67,4 +98,9 @@ public String login(
String frontendRedirectUrl = env.equals("dev") ? dummyProperties.devRedirectUri() : dummyProperties.redirectUri();
return "redirect:" + frontendRedirectUrl + "?accessToken=" + accessToken + "&refreshToken=" + refreshToken + "&isSinitto=" + isSinitto;
}
+
+ private boolean isAdmin(HttpSession session) {
+ String role = (String) session.getAttribute("role");
+ return "ADMIN".equals(role);
+ }
}
diff --git a/src/main/java/com/example/sinitto/member/service/MemberTokenService.java b/src/main/java/com/example/sinitto/member/service/MemberTokenService.java
index fd18ef08..ad029861 100644
--- a/src/main/java/com/example/sinitto/member/service/MemberTokenService.java
+++ b/src/main/java/com/example/sinitto/member/service/MemberTokenService.java
@@ -11,7 +11,7 @@ public class MemberTokenService {
private final TokenService tokenService;
private final MemberRepository memberRepository;
- public MemberTokenService(TokenService tokenService, MemberRepository memberRepository){
+ public MemberTokenService(TokenService tokenService, MemberRepository memberRepository) {
this.tokenService = tokenService;
this.memberRepository = memberRepository;
}
diff --git a/src/main/java/com/example/sinitto/point/controller/PointAdminController.java b/src/main/java/com/example/sinitto/point/controller/PointAdminController.java
index 50be1ec5..07ad9b89 100644
--- a/src/main/java/com/example/sinitto/point/controller/PointAdminController.java
+++ b/src/main/java/com/example/sinitto/point/controller/PointAdminController.java
@@ -3,6 +3,7 @@
import com.example.sinitto.point.dto.PointLogWithBankInfo;
import com.example.sinitto.point.dto.PointLogWithDepositMessage;
import com.example.sinitto.point.service.PointAdminService;
+import jakarta.servlet.http.HttpSession;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
@@ -21,8 +22,10 @@ public PointAdminController(PointAdminService pointAdminService) {
}
@GetMapping("/admin/point/charge")
- public String showAllChargeRequest(Model model) {
-
+ public String showAllChargeRequest(Model model, HttpSession session) {
+ if (!isAdmin(session)) {
+ return "redirect:/admin/login";
+ }
List logWithDepositMessages = pointAdminService.getPointLogWithDepositMessage();
model.addAttribute("logWithDepositMessages", logWithDepositMessages);
@@ -31,28 +34,37 @@ public String showAllChargeRequest(Model model) {
}
@PostMapping("/admin/point/charge/waiting/{pointLogId}")
- public String changeToWaiting(@PathVariable Long pointLogId) {
-
+ public String changeToWaiting(@PathVariable Long pointLogId, HttpSession session) {
+ if (!isAdmin(session)) {
+ return "redirect:/admin/login";
+ }
pointAdminService.changeChargeLogToWaiting(pointLogId);
return "redirect:/admin/point/charge";
}
@PostMapping("/admin/point/charge/complete/{pointLogId}")
- public String changeToCompleteAndEarn(@PathVariable Long pointLogId) {
-
+ public String changeToCompleteAndEarn(@PathVariable Long pointLogId, HttpSession session) {
+ if (!isAdmin(session)) {
+ return "redirect:/admin/login";
+ }
pointAdminService.earnPointAndChangeToChargeComplete(pointLogId);
return "redirect:/admin/point/charge";
}
@PostMapping("/admin/point/charge/fail/{pointLogId}")
- public String changeToFail(@PathVariable Long pointLogId) {
-
+ public String changeToFail(@PathVariable Long pointLogId, HttpSession session) {
+ if (!isAdmin(session)) {
+ return "redirect:/admin/login";
+ }
pointAdminService.changeChargeLogToFail(pointLogId);
return "redirect:/admin/point/charge";
}
@GetMapping("/admin/point/withdraw")
- public String showAllWithdrawRequest(Model model) {
+ public String showAllWithdrawRequest(Model model, HttpSession session) {
+ if (!isAdmin(session)) {
+ return "redirect:/admin/login";
+ }
List logWithBankInfos = pointAdminService.getPointLogWithBankInfo();
@@ -62,24 +74,35 @@ public String showAllWithdrawRequest(Model model) {
}
@PostMapping("/admin/point/withdraw/waiting/{pointLogId}")
- public String changeWithdrawLogToWaiting(@PathVariable Long pointLogId) {
-
+ public String changeWithdrawLogToWaiting(@PathVariable Long pointLogId, HttpSession session) {
+ if (!isAdmin(session)) {
+ return "redirect:/admin/login";
+ }
pointAdminService.changeWithdrawLogToWaiting(pointLogId);
return "redirect:/admin/point/withdraw";
}
@PostMapping("/admin/point/withdraw/complete/{pointLogId}")
- public String changeWithdrawLogToCompleteAndEarn(@PathVariable Long pointLogId) {
-
+ public String changeWithdrawLogToCompleteAndEarn(@PathVariable Long pointLogId, HttpSession session) {
+ if (!isAdmin(session)) {
+ return "redirect:/admin/login";
+ }
pointAdminService.changeWithdrawLogToComplete(pointLogId);
return "redirect:/admin/point/withdraw";
}
@PostMapping("/admin/point/withdraw/fail/{pointLogId}")
- public String changeWithdrawLogToFail(@PathVariable Long pointLogId) {
-
+ public String changeWithdrawLogToFail(@PathVariable Long pointLogId, HttpSession session) {
+ if (!isAdmin(session)) {
+ return "redirect:/admin/login";
+ }
pointAdminService.changeWithdrawLogToFail(pointLogId);
return "redirect:/admin/point/withdraw";
}
+ private boolean isAdmin(HttpSession session) {
+ String role = (String) session.getAttribute("role");
+ return "ADMIN".equals(role);
+ }
+
}
diff --git a/src/main/java/com/example/sinitto/review/entity/Review.java b/src/main/java/com/example/sinitto/review/entity/Review.java
index 1c1f69fb..244e42f4 100644
--- a/src/main/java/com/example/sinitto/review/entity/Review.java
+++ b/src/main/java/com/example/sinitto/review/entity/Review.java
@@ -14,24 +14,18 @@
@Entity
@EntityListeners(AuditingEntityListener.class)
public class Review {
- @Id
- @GeneratedValue(strategy = GenerationType.IDENTITY)
- private Long id;
-
@NotNull
int starCountForRequest;
-
@NotNull
int starCountForService;
-
@NotNull
int starCountForSatisfaction;
-
@CreatedDate
LocalDate postDate;
-
String content;
-
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ private Long id;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "member_id")
@NotNull
diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties
index f0993146..f89fd298 100644
--- a/src/main/resources/application.properties
+++ b/src/main/resources/application.properties
@@ -7,3 +7,4 @@ spring.profiles.active=dev
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQLDialect
spring.h2.console.enabled=false
+server.servlet.session.tracking-modes = cookie
diff --git a/src/main/resources/static/css/header.css b/src/main/resources/static/css/header.css
new file mode 100644
index 00000000..e7da7b67
--- /dev/null
+++ b/src/main/resources/static/css/header.css
@@ -0,0 +1,54 @@
+
+body {
+ font-family: Arial, sans-serif;
+ margin: 0;
+ padding: 20px;
+ color: #333;
+}
+
+.header {
+ background-color: transparent;
+ border: none;
+ padding: 20px;
+ color: #333;
+ margin-bottom: 30px;
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+
+.header h1 {
+ margin: 0;
+ font-size: 24px;
+ font-weight: 600;
+}
+
+
+nav {
+ display: flex;
+ gap: 15px;
+ justify-content: flex-end;
+}
+
+button {
+ background-color: rgba(52, 87, 217, 0.8);
+ color: #ffffff;
+ border: none;
+ padding: 10px 20px;
+ font-size: 14px;
+ cursor: pointer;
+ border-radius: 4px;
+ transition: background-color 0.3s, transform 0.2s;
+}
+
+button:hover {
+ background-color: rgba(52, 87, 217, 0.93);
+ transform: scale(1.03);
+}
+
+button:active {
+ background-color: #00473c;
+}
+
+form {
+ display: inline;
+}
diff --git a/src/main/resources/static/css/login.css b/src/main/resources/static/css/login.css
new file mode 100644
index 00000000..9e004565
--- /dev/null
+++ b/src/main/resources/static/css/login.css
@@ -0,0 +1,71 @@
+/* 기본 스타일 설정 */
+body {
+ font-family: Arial, sans-serif;
+ background-color: #f4f7fb; /* 연한 배경색 */
+ margin: 0;
+ padding: 0;
+ color: #333;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ height: 100vh;
+ flex-direction: column;
+}
+
+h1 {
+ font-size: 32px;
+ color: #344fd9;
+ margin-bottom: 40px;
+ text-align: center;
+}
+
+form {
+ background-color: #ffffff;
+ padding: 40px;
+ border-radius: 8px;
+ box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
+ width: 100%;
+ max-width: 400px;
+}
+
+
+form div {
+ margin-bottom: 20px;
+}
+
+
+label {
+ display: block;
+ margin-bottom: 5px;
+ font-weight: 600;
+ color: #555;
+}
+
+
+input[type="email"], input[type="password"] {
+ width: 100%;
+ padding: 12px;
+ font-size: 16px;
+ border: 1px solid #ddd;
+ border-radius: 4px;
+ box-sizing: border-box;
+ transition: border-color 0.3s;
+}
+
+
+input[type="email"]:focus, input[type="password"]:focus {
+ border-color: #344fd9;
+ outline: none;
+}
+
+
+button {
+ width: 100%;
+ padding: 12px;
+ font-size: 16px;
+ background-color: #344fd9;
+ color: #ffffff;
+ border: none;
+ border-radius: 4px;
+ cursor: pointer;
+}
diff --git a/src/main/resources/templates/dummy/login.html b/src/main/resources/templates/dummy/login.html
index 99921f8d..29aaa17e 100644
--- a/src/main/resources/templates/dummy/login.html
+++ b/src/main/resources/templates/dummy/login.html
@@ -9,24 +9,24 @@ 더미데이터 유저 로그인
해당 페이지는 개발자용 페이지입니다. 더미데이터 유저만 로그인이 가능합니다.
-
+
-
-
+
포인트 충전 관리
diff --git a/src/main/resources/templates/point/header.html b/src/main/resources/templates/point/header.html
new file mode 100644
index 00000000..227f9a43
--- /dev/null
+++ b/src/main/resources/templates/point/header.html
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+ Admin Header
+
+
+
+
+
+
+
diff --git a/src/main/resources/templates/point/login.html b/src/main/resources/templates/point/login.html
new file mode 100644
index 00000000..895b479e
--- /dev/null
+++ b/src/main/resources/templates/point/login.html
@@ -0,0 +1,35 @@
+
+
+
+
+
+ Admin Login
+
+
+Admin Login
+
+
+
+
+
+
+
+
diff --git a/src/main/resources/templates/point/withdraw.html b/src/main/resources/templates/point/withdraw.html
index 14ea5bd5..5c4e86fb 100644
--- a/src/main/resources/templates/point/withdraw.html
+++ b/src/main/resources/templates/point/withdraw.html
@@ -1,12 +1,12 @@
-
+
출금 페이지
-
+
포인트 출금 관리
diff --git a/src/test/java/com/example/sinitto/auth/service/TokenServiceTest.java b/src/test/java/com/example/sinitto/auth/service/TokenServiceTest.java
index d14be2ff..87e087be 100644
--- a/src/test/java/com/example/sinitto/auth/service/TokenServiceTest.java
+++ b/src/test/java/com/example/sinitto/auth/service/TokenServiceTest.java
@@ -80,7 +80,7 @@ void generateRefreshTokenTest() {
@Test
@DisplayName("deleteAllDataFromRedis 메소드 테스트")
- void deleteAllDataFromRedisTest(){
+ void deleteAllDataFromRedisTest() {
//given
String email = "test@email.com";
String refreshToken = "test.Refresh.Token";
diff --git a/src/main/resources/templates/point/charge.html b/src/main/resources/templates/point/charge.html
index 61414c1c..d4edcb17 100644
--- a/src/main/resources/templates/point/charge.html
+++ b/src/main/resources/templates/point/charge.html
@@ -1,12 +1,12 @@
-
+