diff --git a/src/main/java/com/opensource/docgrid/domain/user/entity/McpAccessToken.java b/src/main/java/com/opensource/docgrid/domain/user/entity/McpAccessToken.java new file mode 100644 index 0000000..cabee3c --- /dev/null +++ b/src/main/java/com/opensource/docgrid/domain/user/entity/McpAccessToken.java @@ -0,0 +1,70 @@ +package com.opensource.docgrid.domain.user.entity; + +import java.time.LocalDateTime; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.Index; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.Table; +import lombok.AccessLevel; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@Entity +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@Table( + name = "mcp_access_tokens", + indexes = { + @Index(name = "idx_mcp_access_tokens_user_id", columnList = "user_id") + } +) +public class McpAccessToken { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "user_id", nullable = false) + private User user; + + @Column(name = "token_hash", nullable = false, length = 255) + private String tokenHash; + + // BaseEntity 미사용 — updated_at 없는 스키마에 맞춰 직접 관리 + @Column(name = "created_at", nullable = false, updatable = false) + private LocalDateTime createdAt; + + @Column(name = "last_used_at") + private LocalDateTime lastUsedAt; + + @Column(name = "revoked_at") + private LocalDateTime revokedAt; + + @Builder + public McpAccessToken(User user, String tokenHash) { + this.user = user; + this.tokenHash = tokenHash; + this.createdAt = LocalDateTime.now(); + } + + public void recordUsage(LocalDateTime usedAt) { + this.lastUsedAt = usedAt; + } + + public void revoke(LocalDateTime revokedAt) { + this.revokedAt = revokedAt; + } + + public boolean isRevoked() { + return this.revokedAt != null; + } +} diff --git a/src/main/resources/db/migration/V26__create_mcp_access_tokens.sql b/src/main/resources/db/migration/V26__create_mcp_access_tokens.sql new file mode 100644 index 0000000..1f05b66 --- /dev/null +++ b/src/main/resources/db/migration/V26__create_mcp_access_tokens.sql @@ -0,0 +1,11 @@ +-- mcp_access_tokens: MCP API 접근 토큰 테이블 +CREATE TABLE mcp_access_tokens ( + id BIGSERIAL PRIMARY KEY, + user_id BIGINT NOT NULL REFERENCES users(id), + token_hash VARCHAR(255) NOT NULL, + created_at TIMESTAMP NOT NULL DEFAULT now(), + last_used_at TIMESTAMP, + revoked_at TIMESTAMP +); + +CREATE INDEX idx_mcp_access_tokens_user_id ON mcp_access_tokens (user_id);