issue # 백엔드 서버 재구성

This commit is contained in:
2025-11-13 02:00:11 +00:00
parent d07a8ec65e
commit 8d0329187b
56 changed files with 99 additions and 1335 deletions

View File

@@ -1,13 +0,0 @@
package com.baekyangdan.scheduler;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SchedulerApplication {
public static void main(String[] args) {
SpringApplication.run(SchedulerApplication.class, args);
}
}

View File

@@ -1,22 +0,0 @@
package com.baekyangdan.scheduler.code.user;
public enum SignUpValidationCode {
ID_EMPTY("ID를 입력해주십시오"),
ID_DUPLICATED("중복된 ID가 존재합니다"),
EMAIL_EMPTY("Email을 입력해주십시오"),
EMAIL_FORM_INVALID("Email 형식이 올바르지 않습니다"),
EMAIL_DUPLICATED("중복된 Email이 존재합니다"),
PASSWORD_EMPTY("비밀번호를 입력해주십시오"),
NAME_EMPTY("이름을 입력해주십시오"),
NICKNAME_EMPTY("닉네임을 입력해주십시오");
private String message;
SignUpValidationCode(String message) {
this.message = message;
}
public String getMessage() {
return message;
}
}

View File

@@ -1,21 +0,0 @@
package com.baekyangdan.scheduler.code.user;
import com.fasterxml.jackson.annotation.JsonValue;
public enum UserStatus {
ACTIVE("active"),
WAIT("wait"),
REST("rest"),
WITHDRAW("withdraw");
private final String value;
UserStatus(String value) {
this.value = value;
}
@JsonValue
public String getValue() {
return value;
}
}

View File

@@ -1,18 +0,0 @@
package com.baekyangdan.scheduler.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.SecurityFilterChain;
@Configuration
public class DisableWebSecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.csrf(csrf -> csrf.disable())
.authorizeHttpRequests(auth -> auth.anyRequest().permitAll());
return http.build();
}
}

View File

@@ -1,52 +0,0 @@
package com.baekyangdan.scheduler.config;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import com.baekyangdan.scheduler.exception.AuthException;
import com.baekyangdan.scheduler.exception.BusinessException;
import com.baekyangdan.scheduler.exception.ValidationException;
import java.util.HashMap;
import java.util.Map;
@RestControllerAdvice
public class GlobalExceptionHandler {
// 에러 핸들러 목록
// 1. 비즈니스 로직 관련 예외 처리
// ex) 중복 데이터
@ExceptionHandler(BusinessException.class)
public ResponseEntity<Map<String, Object>> handleBusinessException(BusinessException e) {
Map<String, Object> body = new HashMap<>();
body.put("message", e.getMessage());
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(body);
}
// 2. 입력값 유효성 검사 관련 예외 처리
// ex) 데이터 타입 검사
@ExceptionHandler(ValidationException.class)
public ResponseEntity<Map<String, Object>> handleValidationException(ValidationException e) {
Map<String, Object> body = new HashMap<>();
body.put("message", e.getMessage());
return ResponseEntity.status(HttpStatus.UNPROCESSABLE_ENTITY).body(body);
}
// 3. 권한/인가 관련 예외 처리
// ex) 로그인이 필요한 서비스에 로그인 안 한 사람이 호출
@ExceptionHandler(AuthException.class)
public ResponseEntity<Map<String, Object>> handleAuthException(ValidationException e) {
Map<String, Object> body = new HashMap<>();
body.put("message", e.getMessage());
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(body);
}
// 4. 기타 예외 처리
@ExceptionHandler(Exception.class)
public ResponseEntity<Map<String, Object>> handleDefaultException(Exception e) {
Map<String, Object> body = new HashMap<>();
body.put("message", e.getMessage());
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(body);
}
}

View File

@@ -1,22 +0,0 @@
package com.baekyangdan.scheduler.config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import lombok.Getter;
@Getter
@Component
public class MailConfig {
@Value("${spring.mail.username}")
private String username;
@Value("${spring.mail.clientId}")
private String clientId;
@Value("${spring.mail.clientSecret}")
private String clientSecret;
@Value("${spring.mail.refreshToken}")
private String refreshToken;
}

View File

@@ -1,15 +0,0 @@
package com.baekyangdan.scheduler.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
@Configuration
public class SecurityConfig {
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder(10);
}
}

View File

@@ -1,17 +0,0 @@
package com.baekyangdan.scheduler.config;
import org.hibernate.boot.model.naming.Identifier;
import org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl;
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
public class SnakeCaseNamingStrategy extends PhysicalNamingStrategyStandardImpl {
@Override
public Identifier toPhysicalColumnName(Identifier name, JdbcEnvironment jdbcEnv) {
String snakeCase = name.getText()
.replaceAll("([a-z])([A-Z])", "$1_$2")
.toLowerCase();
return Identifier.toIdentifier(snakeCase);
}
}

View File

@@ -1,5 +0,0 @@
package com.baekyangdan.scheduler.controller.comment;
public class CommentController {
}

View File

@@ -1,5 +0,0 @@
package com.baekyangdan.scheduler.controller.follow;
public class FollowController {
}

View File

@@ -1,5 +0,0 @@
package com.baekyangdan.scheduler.controller.schedule;
public class ScheduleController {
}

View File

@@ -1,42 +0,0 @@
package com.baekyangdan.scheduler.controller.user;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.baekyangdan.scheduler.repository.user.UserRepository;
import com.baekyangdan.scheduler.request.user.UserRequest;
import com.baekyangdan.scheduler.service.user.UserService;
import com.baekyangdan.scheduler.utils.converter.PasswordConverter;
@RestController
@RequestMapping("/user")
public class UserController {
private final UserService userService;
public UserController(UserService userService) {
this.userService = userService;
}
@PostMapping("/signup")
public ResponseEntity<String> signUp(@RequestBody UserRequest.SignUp body) {
try {
userService.signUp(body);
return new ResponseEntity<String> ("회원가입 완료", HttpStatus.OK);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
return new ResponseEntity<String> (e.getMessage(), HttpStatus.BAD_REQUEST);
}
}
}

View File

@@ -1,5 +0,0 @@
package com.baekyangdan.scheduler.dto.comment;
public class CommentDto {
}

View File

@@ -1,5 +0,0 @@
package com.baekyangdan.scheduler.dto.follow;
public class FollowDto {
}

View File

@@ -1,5 +0,0 @@
package com.baekyangdan.scheduler.dto.schedule;
public class ScheduleDto {
}

View File

@@ -1,5 +0,0 @@
package com.baekyangdan.scheduler.dto.user;
public class UserDto {
}

View File

@@ -1,67 +0,0 @@
package com.baekyangdan.scheduler.entity.user;
import jakarta.persistence.*;
import lombok.*;
import org.hibernate.annotations.CreationTimestamp;
import com.baekyangdan.scheduler.code.user.UserStatus;
import java.time.LocalDateTime;
import java.util.List;
import java.util.UUID;
/**
* DB 상의 "USER" 테이블에 해당하는 Entity
*/
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor(access = AccessLevel.PRIVATE)
@Builder
@Entity
@Table(
name = "account",
indexes = @Index(name = "user_pk", columnList = "id")
)
public class UserEntity {
@Id
@GeneratedValue
@org.hibernate.annotations.UuidGenerator
@Column(nullable = false)
private UUID id;
@Column(nullable=false, length=50)
private String accountId;
@Column(nullable = false, length = 50)
private String name;
@Column(nullable = false, length = 100)
private String email;
@Builder.Default
@Column(nullable = false)
private boolean isDeleted = false;
@Column(nullable = false)
private String password;
@Column
private String nickname;
@Column
private LocalDateTime birthday;
@Builder.Default
@Column
private String status = UserStatus.WAIT.getValue();
@CreationTimestamp
@Column(updatable = false)
private LocalDateTime createdAt;
/**
* 사용자가 참여중인 일정들의 id 목록을 가져오는 1대다 매핑 컬럼
*/
// @OneToMany(mappedBy = "participant_id", cascade = CascadeType.ALL)
// private List<String> participatedScheduleList;
}

View File

@@ -1,7 +0,0 @@
package com.baekyangdan.scheduler.exception;
public class AuthException extends RuntimeException {
public AuthException(String message) {
super(message);
}
}

View File

@@ -1,7 +0,0 @@
package com.baekyangdan.scheduler.exception;
public class BusinessException extends RuntimeException {
public BusinessException(String message) {
super(message);
}
}

View File

@@ -1,7 +0,0 @@
package com.baekyangdan.scheduler.exception;
public class ValidationException extends RuntimeException {
public ValidationException(String message) {
super(message);
}
}

View File

@@ -1,5 +0,0 @@
package com.baekyangdan.scheduler.repository.comment;
public class CommentRepository {
}

View File

@@ -1,5 +0,0 @@
package com.baekyangdan.scheduler.repository.follow;
public class FollowRepository {
}

View File

@@ -1,5 +0,0 @@
package com.baekyangdan.scheduler.repository.schedule;
public class ScheduleRepository {
}

View File

@@ -1,22 +0,0 @@
package com.baekyangdan.scheduler.repository.user;
import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import com.baekyangdan.scheduler.entity.user.UserEntity;
@Repository
public interface UserRepository extends JpaRepository<UserEntity, String> {
Optional<UserEntity> findByEmail(String email);
@Transactional
@Modifying(clearAutomatically = true)
@Query("UPDATE UserEntity u SET u.password = :password WHERE u.email = :email")
int resetPasswordByEmail(@Param("password") String newPassword, @Param("email") String email);
}

View File

@@ -1,84 +0,0 @@
package com.baekyangdan.scheduler.request.user;
import java.time.LocalDateTime;
import com.baekyangdan.scheduler.code.user.UserStatus;
import lombok.Getter;
import lombok.Setter;
/**
* 회원 관련 요청 데이터 클래스
*/
public class UserRequest {
// 프로그램 실행 순서에 맞춰서 클래스 작성
// 1. 회원 가입
// 1-1. Id 중복 검사 요청 클래스
@Getter
@Setter
public static class CheckIdDuplication {
private String id;
}
// 1-2. 이메일 중복 검사 요청 클래스
@Getter
@Setter
public static class CheckEmailDuplication {
private String email;
}
// 1-3. 회원 가입 요청 클래스
@Getter
@Setter
public static class SignUp {
private String accountId;
private String email;
private String name;
private String nickname;
private String password;
}
// 2. 로그인
// 2-1. 비밀번호 초기화 요청 클래스
@Getter
@Setter
public static class ResetPassword {
private String email;
private String passwordResetCode;
}
// 2-2. 로그인 요청 클래스
@Getter
@Setter
public static class Login {
// identifier: id or email
private String identifier;
private String password;
}
// 3. 회원 정보 수정 요청 클래스
@Getter
@Setter
public static class Update {
private String newId;
private String newName;
private String newEmail;
private String newPassword;
private LocalDateTime newBirthday;
private UserStatus newUserStatus;
}
// 4. 회원 탈퇴 요청 클래스
@Getter
@Setter
public static class Delete {
private String id;
}
// 5. id로 회원 목록 검색 요청 클래스
@Getter
@Setter
public static class FindById {
private String id;
}
}

View File

@@ -1,5 +0,0 @@
package com.baekyangdan.scheduler.service.comment;
public class CommentService {
}

View File

@@ -1,5 +0,0 @@
package com.baekyangdan.scheduler.service.follow;
public class FollowService {
}

View File

@@ -1,57 +0,0 @@
package com.baekyangdan.scheduler.service.mail;
import java.util.Properties;
import org.springframework.stereotype.Service;
import com.google.auth.oauth2.AccessToken;
import com.google.auth.oauth2.UserCredentials;
import jakarta.mail.Message;
import jakarta.mail.Session;
import jakarta.mail.Transport;
import jakarta.mail.internet.InternetAddress;
import jakarta.mail.internet.MimeMessage;
@Service
public class MailService {
private static final String CLIENT_ID="688417162908-iqvnj4ceb8t1dkbjr70dtcafo27m8kqe.apps.googleusercontent.com";
private static final String CLIENT_SECRET="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";
private static final String REFRESH_TOKEN="1//04_pSivNoGpPUCgYIARAAGAQSNwF-L9IrO0Kx6jSzq_eQNjdl65f0O2iqKSNpFeZ3gtIGMhOk0oiZsnKrPfWs8jvuEic1NhUoZ0g";
private static final String USER_MAIL="baekyangdan@gmail.com";
public void sendTestMail() throws Exception {
UserCredentials credentials =
UserCredentials.newBuilder()
.setClientId(CLIENT_ID)
.setClientSecret(CLIENT_SECRET)
.setRefreshToken(REFRESH_TOKEN)
.build();
AccessToken accessToken = credentials.refreshAccessToken();
Properties props = new Properties();
props.put("mail.smtp.auth", "true");
props.put("mail.smtp.starttls.enable", "true");
props.put("mail.smtp.host", "smtp.gmail.com");
props.put("mail.smtp.port", "587");
props.put("mail.smtp.auth.mechanisms", "XOAUTH2");
Session session = Session.getInstance(props);
Transport transport = session.getTransport("smtp");
transport.connect("smtp.gmail.com", USER_MAIL, accessToken.getTokenValue());
Message message = new MimeMessage(session);
message.setRecipients(Message.RecipientType.TO, InternetAddress.parse("lapinuit966@gmail.com"));
message.setSubject("test Mail");
message.setText("test mail");
message.setFrom(new InternetAddress(USER_MAIL));
transport.sendMessage(message, message.getAllRecipients());
transport.close();
System.out.println("메일 전송 완료");
}
}

View File

@@ -1,5 +0,0 @@
package com.baekyangdan.scheduler.service.schedule;
public class ScheduleService {
}

View File

@@ -1,46 +0,0 @@
package com.baekyangdan.scheduler.service.user;
import com.baekyangdan.scheduler.code.user.UserStatus;
import com.baekyangdan.scheduler.entity.user.UserEntity;
import com.baekyangdan.scheduler.repository.user.UserRepository;
import com.baekyangdan.scheduler.request.user.UserRequest;
import com.baekyangdan.scheduler.utils.converter.PasswordConverter;
import com.baekyangdan.scheduler.utils.validation.UserValidation;
import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
@Service
public class UserService {
private final UserRepository userRepository;
private final PasswordConverter passwordConverter;
public UserService(UserRepository userRepository, PasswordConverter passwordConverter) {
this.userRepository = userRepository;
this.passwordConverter = passwordConverter;
}
// 회원가입 로직
public UserEntity signUp(UserRequest.SignUp data) throws Exception {
// 1. 요청받은 데이터가 회원가입 양식을 준수하는지 검사한다.
// 1-1. 회원가입 양식에 맞지 않는 데이터가 있을 경우, validateSignUpForm 함수 내에서 예외를 던져 함수 동작 중단
UserValidation.validateSignUpForm(data);
// 2. data 안의 평문 비밀번호 암호화
String encodedPassword = passwordConverter.encode(data.getPassword());
// 3. data 를 UserEntity 형식으로 build
UserEntity user = UserEntity
.builder()
.accountId(data.getAccountId())
.email(data.getEmail())
.name(data.getName())
.nickname(data.getNickname())
.password(encodedPassword)
.createdAt(LocalDateTime.now())
.build();
// 4. build 된 entity를 UserRepository.save 로 DB에 저장
return userRepository.save(user);
}
}

View File

@@ -1,21 +0,0 @@
package com.baekyangdan.scheduler.utils.converter;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;
@Component
public class PasswordConverter {
private final PasswordEncoder passwordEncoder;
public PasswordConverter(PasswordEncoder passwordEncoder) {
this.passwordEncoder = passwordEncoder;
}
public String encode(String rawPassword) {
return passwordEncoder.encode(rawPassword);
}
public boolean matches(String rawPassword, String encodedPassword) {
return passwordEncoder.matches(rawPassword, encodedPassword);
}
}

View File

@@ -1,46 +0,0 @@
package com.baekyangdan.scheduler.utils.generator;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class PasswordGenerator {
private static final String DIGITS = "0123456789";
private static final String LOWER = "abcdefghijklmnopqrstuvwxyz";
private static final String UPPER = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
private static final String SPECIAL="!@#$";
private static final String ALL = DIGITS + LOWER + UPPER + SPECIAL;
private static final SecureRandom random = new SecureRandom();
public static String generateRandomPassword() {
int length = 10;
List<Character> passwordCharacters = new ArrayList<>(length);
passwordCharacters.add(randomCharFrom(DIGITS));
passwordCharacters.add(randomCharFrom(LOWER));
passwordCharacters.add(randomCharFrom(UPPER));
passwordCharacters.add(randomCharFrom(SPECIAL));
for (int i = 4; i < length; i++) {
passwordCharacters.add(randomCharFrom(ALL));
}
Collections.shuffle(passwordCharacters, random);
StringBuilder sb = new StringBuilder(length);
for (char c : passwordCharacters) {
sb.append(c);
}
return sb.toString();
}
private static char randomCharFrom(String s) {
int idx = random.nextInt(s.length());
return s.charAt(idx);
}
}

View File

@@ -1,35 +0,0 @@
package com.baekyangdan.scheduler.utils.generator;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class RandomCodeGenerator {
private static final String DIGITS = "0123456789";
private static final SecureRandom random = new SecureRandom();
public static String generateRandomCode(int length) {
List<Character> codeCharacters = new ArrayList<>(length);
for (int i = 0; i < length; i++) {
codeCharacters.add(randomChar());
}
Collections.shuffle(codeCharacters, random);
StringBuilder sb = new StringBuilder(length);
for (char c : codeCharacters) {
sb.append(c);
}
return sb.toString();
}
private static char randomChar() {
int idx = random.nextInt(DIGITS.length());
return DIGITS.charAt(idx);
}
}

View File

@@ -1,32 +0,0 @@
package com.baekyangdan.scheduler.utils.validation;
import java.util.regex.Pattern;
public class BaseValidation {
private final static Pattern emailPattern = Pattern.compile("^[A-Za-z0-9+_.-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{1,}$");
private final static Pattern phoneNumberPattern = Pattern.compile("^010-\\d{4}-\\d{4}$");
protected static boolean matchEmailPattern(String email) {
if (validateStringEmpty(email)) {
return false;
}
return emailPattern.matcher(email).matches();
}
protected static boolean matchPhoneNumberPattern(String phoneNumber) {
if (validateStringEmpty(phoneNumber)) {
return false;
}
return phoneNumberPattern.matcher(phoneNumber).matches();
}
protected static boolean validateStringEmpty(String value) {
if (value == null) {
return true;
}
if (value.trim().isEmpty()) {
return true;
}
return false;
}
}

View File

@@ -1,37 +0,0 @@
package com.baekyangdan.scheduler.utils.validation;
import org.springframework.security.access.method.P;
import com.baekyangdan.scheduler.code.user.SignUpValidationCode;
import com.baekyangdan.scheduler.repository.user.UserRepository;
import com.baekyangdan.scheduler.request.user.UserRequest;
import com.baekyangdan.scheduler.utils.validation.BaseValidation;
public class UserValidation extends BaseValidation {
public static boolean validateSignUpForm(UserRequest.SignUp data) throws Exception {
if (validateStringEmpty(data.getAccountId())) {
throw new Exception(SignUpValidationCode.ID_EMPTY.getMessage());
}
if (validateStringEmpty(data.getEmail())) {
throw new Exception(SignUpValidationCode.EMAIL_EMPTY.getMessage());
}
if (validateStringEmpty(data.getPassword())) {
throw new Exception(SignUpValidationCode.PASSWORD_EMPTY.getMessage());
}
if (validateStringEmpty(data.getName())) {
throw new Exception(SignUpValidationCode.NAME_EMPTY.getMessage());
}
if (validateStringEmpty(data.getNickname())) {
throw new Exception(SignUpValidationCode.NICKNAME_EMPTY.getMessage());
}
return true;
}
}

View File

@@ -1,20 +0,0 @@
spring.datasource.url=jdbc:postgresql://192.168.219.107:5454/scheduler
spring.datasource.username=baekyangdan
spring.datasource.password=qwas745478!
spring.datasource.driver-class-name=org.postgresql.Driver
spring.devtools.restart.enabled=true
spring.devtools.livereload.enabled=true
spring.mail.host=smtp.google.com
spring.mail.port=587
spring.mail.username=bkd.scheduler@gmail.com
spring.mail.protocol=smtp
spring.mail.clientId=688417162908-iqvnj4ceb8t1dkbjr70dtcafo27m8kqe.apps.googleusercontent.com
spring.mail.clientSecret=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
spring.mail.refreshToken=1//04_pSivNoGpPUCgYIARAAGAQSNwF-L9IrO0Kx6jSzq_eQNjdl65f0O2iqKSNpFeZ3gtIGMhOk0oiZsnKrPfWs8jvuEic1NhUoZ0g
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.starttls.enable=true
spring.mail.properties.mail.smtp.starttls.required=true
spring.mail.properties.mail.smtp.auth.mechanisms=XOAUTH2

View File

@@ -1,20 +0,0 @@
spring.datasource.url=jdbc:postgresql://bkdhome.p-e.kr:15454/scheduler
spring.datasource.username=baekyangdan
spring.datasource.password=qwas745478!
spring.datasource.driver-class-name=org.postgresql.Driver
spring.devtools.restart.enabled=true
spring.devtools.livereload.enabled=true
spring.mail.host=smtp.google.com
spring.mail.port=587
spring.mail.username=bkd.scheduler@gmail.com
spring.mail.protocol=smtp
spring.mail.clientId=688417162908-iqvnj4ceb8t1dkbjr70dtcafo27m8kqe.apps.googleusercontent.com
spring.mail.clientSecret=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
spring.mail.refreshToken=1//04_pSivNoGpPUCgYIARAAGAQSNwF-L9IrO0Kx6jSzq_eQNjdl65f0O2iqKSNpFeZ3gtIGMhOk0oiZsnKrPfWs8jvuEic1NhUoZ0g
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.starttls.enable=true
spring.mail.properties.mail.smtp.starttls.required=true
spring.mail.properties.mail.smtp.auth.mechanisms=XOAUTH2

View File

@@ -1,16 +0,0 @@
spring.application.name=scheduler
spring.profiles.active=local
spring.mail.host=smtp.google.com
spring.mail.port=587
spring.mail.username=bkd.scheduler@gmail.com
spring.mail.protocol=smtp
spring.mail.clientId=688417162908-iqvnj4ceb8t1dkbjr70dtcafo27m8kqe.apps.googleusercontent.com
spring.mail.clientSecret=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
spring.mail.refreshToken=1//04_pSivNoGpPUCgYIARAAGAQSNwF-L9IrO0Kx6jSzq_eQNjdl65f0O2iqKSNpFeZ3gtIGMhOk0oiZsnKrPfWs8jvuEic1NhUoZ0g
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.starttls.enable=true
spring.mail.properties.mail.smtp.starttls.required=true
spring.mail.properties.mail.smtp.auth.mechanisms=XOAUTH2

View File

@@ -1,13 +0,0 @@
package com.baekyangdan.scheduler;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class SchedulerApplicationTests {
@Test
void contextLoads() {
}
}