Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -41,5 +41,6 @@ out/

###custom###
application-secret.yml
.env
db_dev.mv.db
db_dev.trace.db
7 changes: 7 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,13 @@ dependencies {
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
implementation("org.springdoc:springdoc-openapi-starter-webmvc-ui:2.8.13")
runtimeOnly("com.mysql:mysql-connector-j")

// JWT 라이브러리
implementation("io.jsonwebtoken:jjwt-api:0.12.6")
runtimeOnly("io.jsonwebtoken:jjwt-impl:0.12.6")
runtimeOnly("io.jsonwebtoken:jjwt-jackson:0.12.6")
implementation("com.fasterxml.jackson.datatype:jackson-datatype-jsr310")
implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
}

tasks.named('test') {
Expand Down
2 changes: 2 additions & 0 deletions src/main/java/back/kalender/KalenderApplication.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.ConfigurationPropertiesScan;
import org.springframework.scheduling.annotation.EnableScheduling;

@SpringBootApplication
@EnableScheduling
@ConfigurationPropertiesScan
public class KalenderApplication {

public static void main(String[] args) {
Expand Down

Large diffs are not rendered by default.

Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package back.kalender.domain.auth.entity;

import back.kalender.global.common.entity.BaseEntity;
import jakarta.persistence.*;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;

import java.time.LocalDateTime;

// 이메일 인증
@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Table(
name = "email_verifications",
indexes = {
@Index(name = "idx_user_id", columnList = "userId"),
@Index(name = "idx_code", columnList = "code")
}
)
public class EmailVerification extends BaseEntity {

private Long userId;

@Column(nullable = false, length = 50)
private String code;

private boolean used;

@Column(nullable = false)
private LocalDateTime expiredAt;

public static EmailVerification create(Long userId, String code) {
EmailVerification ev = new EmailVerification();
ev.userId = userId;
ev.code = code;
ev.used = false;
ev.expiredAt = LocalDateTime.now().plusMinutes(5);
return ev;
}

public void markUsed() {
this.used = true;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package back.kalender.domain.auth.entity;

import back.kalender.global.common.entity.BaseEntity;
import jakarta.persistence.*;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;

import java.time.LocalDateTime;

// 비밀번호 변경
@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Table(
name = "password_reset_tokens",
indexes = {
@Index(name = "idx_password_user_id", columnList = "userId"),
@Index(name = "idx_password_token", columnList = "token")
}
)
public class PasswordResetToken extends BaseEntity {

private Long userId;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nullable=false 명시해주시면 좋을 것 같습니다!


@Column(nullable = false, length = 500)
private String token;

private boolean used;

@Column(nullable = false)
private LocalDateTime expiredAt;

public static PasswordResetToken create(Long userId, String code) {
PasswordResetToken token = new PasswordResetToken();
token.userId = userId;
token.token = code;
token.used = false;
token.expiredAt = LocalDateTime.now().plusMinutes(5);
return token;
}

public void markUsed() {
this.used = true;
}
}
40 changes: 40 additions & 0 deletions src/main/java/back/kalender/domain/auth/entity/RefreshToken.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package back.kalender.domain.auth.entity;

import back.kalender.global.common.entity.BaseEntity;
import jakarta.persistence.*;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;

import java.time.LocalDateTime;

// 리프레시 토큰
@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Table(
name = "refresh_tokens",
indexes = {
@Index(name = "idx_refresh_user_id", columnList = "userId"),
@Index(name = "idx_refresh_token", columnList = "token")
}
)
public class RefreshToken extends BaseEntity {

private Long userId;

@Column(nullable = false, length = 1000)
private String token;

@Column(nullable = false)
private LocalDateTime expiredAt;

public static RefreshToken create(Long userId, String token, long ttlDays) {
RefreshToken rt = new RefreshToken();
rt.userId = userId;
rt.token = token;
rt.expiredAt = LocalDateTime.now().plusDays(ttlDays);
return rt;
}

}
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package back.kalender.domain.auth.repository;

import back.kalender.domain.auth.entity.EmailVerification;
import org.springframework.data.jpa.repository.JpaRepository;

import java.util.Optional;

public interface EmailVerificationRepository extends JpaRepository<EmailVerification, Long> {
Optional<EmailVerification> findTopByUserIdOrderByCreatedAtDesc(Long userId);
Optional<EmailVerification> findByCode(String code);
void deleteByUserId(Long userId);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package back.kalender.domain.auth.repository;

import back.kalender.domain.auth.entity.PasswordResetToken;
import org.springframework.data.jpa.repository.JpaRepository;

import java.util.Optional;

public interface PasswordResetTokenRepository extends JpaRepository<PasswordResetToken, Long> {
Optional<PasswordResetToken> findByToken(String token);
void deleteByUserId(Long userId);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package back.kalender.domain.auth.repository;

import back.kalender.domain.auth.entity.RefreshToken;
import org.springframework.data.jpa.repository.JpaRepository;

import java.util.List;
import java.util.Optional;

public interface RefreshTokenRepository extends JpaRepository<RefreshToken, Long> {
Optional<RefreshToken> findByToken(String token);
List<RefreshToken> findAllByUserId(Long userId);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

refreshToken이 여러개 있는 경우가 있나요? findAll을 써서 다 불러와야 하는지 고려해보면 좋을것 같습니다.

void deleteAllByUserId(Long userId);
}
Empty file.
19 changes: 19 additions & 0 deletions src/main/java/back/kalender/domain/auth/service/AuthService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package back.kalender.domain.auth.service;

import back.kalender.domain.auth.dto.request.*;
import back.kalender.domain.auth.dto.response.EmailStatusResponse;
import back.kalender.domain.auth.dto.response.UserLoginResponse;
import back.kalender.domain.auth.dto.response.VerifyEmailResponse;
import jakarta.servlet.http.HttpServletResponse;

public interface AuthService {
UserLoginResponse login(UserLoginRequest request, HttpServletResponse response);
void logout(String refreshToken);
void refreshToken(String refreshToken, HttpServletResponse response);
void sendPasswordResetEmail(UserPasswordResetSendRequest request);
void resetPassword(UserPasswordResetRequest request);
void sendVerifyEmail(VerifyEmailSendRequest request);
VerifyEmailResponse verifyEmail(VerifyEmailRequest request);
EmailStatusResponse getEmailStatus(Long userId);
}

Loading
Loading