Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
.formLogin(AbstractHttpConfigurer::disable)
.httpBasic(AbstractHttpConfigurer::disable)
.sessionManagement(session -> session
.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)) // ν•„μš”ν•œ 경우 μ„Έμ…˜ μš”μ²­
.headers((headerConfig) -> headerConfig
.frameOptions(HeadersConfigurer.FrameOptionsConfig::disable));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ public class SecurityPath {

// permitAll
public static final String[] PUBLIC_ENDPOINTS = {
"/api/token/refresh",
"/api/auth/token/refresh",
"/api/auth/oauth/refresh/*",
"/",

Expand All @@ -16,8 +16,11 @@ public class SecurityPath {
"/api/auth/connect/github/state",
"/api/users/me",
"/api/users/me/**",
"/api/logout",
"/api/repos/**"
"/api/auth/logout",
"/api/repos",
"/api/repos/**",
"/api/mindmaps/**",
"/api/history/**"
};

// hasRole("ADMIN")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ public enum ErrorCode {
// λ§ˆμΈλ“œλ§΅ κ΄€λ ¨
MINDMAP_NOT_FOUND(HttpStatus.NOT_FOUND, "MINDMAP-001", "μš”μ²­ν•œ λ§ˆμΈλ“œλ§΅μ„ 찾을 수 μ—†μŠ΅λ‹ˆλ‹€."),

// 멀버 κ΄€λ ¨
MEMBER_NOT_FOUND(HttpStatus.NOT_FOUND, "MEMBER-001", "ν•΄λ‹Ή 멀버λ₯Ό 찾을 수 μ—†μŠ΅λ‹ˆλ‹€."),

// 방문기둝 κ΄€λ ¨
HISTORY_NOT_FOUND(HttpStatus.NOT_FOUND, "VISITHISTORY-001", "λ°©λ¬Έ 기둝을 찾을 수 μ—†μŠ΅λ‹ˆλ‹€."),

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter {
private String secretKey;
private final JwtTokenProvider jwtTokenProvider;
private final ObjectMapper objectMapper;
private static final String BEARER = "Bearer";
private static final String BEARER = "Bearer ";


@Override
Expand Down
30 changes: 19 additions & 11 deletions src/main/java/com/teamEWSN/gitdeun/common/jwt/JwtTokenProvider.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.teamEWSN.gitdeun.common.jwt;

import com.teamEWSN.gitdeun.common.oauth.dto.CustomOAuth2User;
import com.teamEWSN.gitdeun.user.entity.Role;
import com.teamEWSN.gitdeun.user.entity.User;
import com.teamEWSN.gitdeun.user.service.UserService;
Expand All @@ -11,11 +12,13 @@
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.oauth2.core.oidc.user.OidcUser;
import org.springframework.security.oauth2.core.user.OAuth2User;
import org.springframework.stereotype.Component;

import javax.crypto.SecretKey;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.UUID;
Expand Down Expand Up @@ -58,9 +61,15 @@ public JwtToken generateToken(Authentication authentication) {
Role role;

switch (principal) {
case CustomUserPrincipal p -> {
userId = p.getId();
role = Role.valueOf(p.getRole());
// μ†Œμ…œ 둜그인 성곡 ν›„ CustomOAuth2Userλ₯Ό 처리
case CustomOAuth2User customUser -> {
userId = customUser.getUserId();
role = customUser.getRole();
}
// κΈ°μ‘΄ JWT둜 인증된 μ‚¬μš©μžλ₯Ό 처리
case CustomUserDetails userDetails -> {
userId = userDetails.getId();
role = Role.valueOf(userDetails.getRole());
}
case OidcUser oidc -> {
userId = userService.upsertAndGetId(
Expand Down Expand Up @@ -101,17 +110,16 @@ public JwtToken generateToken(Authentication authentication) {
public Authentication getAuthentication(String token) {
Claims claims = jwtTokenParser.parseClaims(token);
Long userId = Long.valueOf(claims.getSubject());
Role role = Role.valueOf(claims.get("role", String.class));

String roleName = claims.get("role", String.class);
Role role = Role.valueOf(roleName);
User user = userService.findById(userId);

CustomUserDetails userDetails =
new CustomUserDetails(user.getId(), user.getEmail(),
user.getNickname(), user.getProfileImage(),
role, user.getName());
CustomUserDetails userDetails = new CustomUserDetails(user.getId(), user.getEmail(),
user.getNickname(), user.getProfileImage(), role, user.getName());

Collection<? extends GrantedAuthority> authorities = Collections.singletonList(role);

return new UsernamePasswordAuthenticationToken(
userDetails, null, Collections.singletonList(role::name));
return new UsernamePasswordAuthenticationToken(userDetails, null, authorities);
}

// // 토큰 생성 - μœ μ € 정보 이용
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.teamEWSN.gitdeun.common.oauth.record;
package com.teamEWSN.gitdeun.common.oauth.dto;

import com.fasterxml.jackson.annotation.JsonProperty;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import org.springframework.security.oauth2.core.user.OAuth2User;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
Expand Down Expand Up @@ -74,7 +75,8 @@ public User processUser(OAuth2User oAuth2User, OAuth2UserRequest userRequest) {
// OAuth2 κ³΅κΈ‰μžλ‘œλΆ€ν„° 받은 μ‚¬μš©μž 정보λ₯Ό 기반으둜 OAuth2ResponseDtoλ₯Ό 생성(μΈμŠ€ν„΄μŠ€ λ©”μ„œλ“œ)
private OAuth2ResponseDto getOAuth2ResponseDto(OAuth2User oAuth2User, OAuth2UserRequest userRequest) {
String registrationId = userRequest.getClientRegistration().getRegistrationId();
Map<String, Object> attr = oAuth2User.getAttributes();

Map<String, Object> attr = new HashMap<>(oAuth2User.getAttributes());

if (registrationId.equalsIgnoreCase("google")) {
return new GoogleResponseDto(attr);
Expand All @@ -90,10 +92,9 @@ private OAuth2ResponseDto getOAuth2ResponseDto(OAuth2User oAuth2User, OAuth2User
.findFirst().map(GitHubEmailDto::getEmail).orElse(null));
}
return new GitHubResponseDto(attr);
} else {
// μ§€μ›ν•˜μ§€ μ•ŠλŠ” μ†Œμ…œ 둜그인 제곡자
throw new GlobalException(ErrorCode.UNSUPPORTED_OAUTH_PROVIDER);
}
// μ§€μ›ν•˜μ§€ μ•ŠλŠ” μ†Œμ…œ 둜그인 제곡자
throw new GlobalException(ErrorCode.UNSUPPORTED_OAUTH_PROVIDER);
}

/**
Expand Down Expand Up @@ -125,11 +126,12 @@ private User createNewUser(OAuth2ResponseDto response, OauthProvider provider, S
.name(response.getName()) // GitHub의 경우 full name, Google의 경우 name
.nickname(nickname)
.profileImage(response.getProfileImageUrl())
.role(Role.ROLE_USER)
.role(Role.USER)
.build();
User savedUser = userRepository.save(newUser);

connectSocialAccount(newUser, provider, providerId, accessToken, refreshToken);
return userRepository.save(newUser);
connectSocialAccount(savedUser, provider, providerId, accessToken, refreshToken);
return savedUser;
}

private void connectSocialAccount(User user, OauthProvider provider, String providerId, String accessToken, String refreshToken) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import com.teamEWSN.gitdeun.common.exception.ErrorCode;
import com.teamEWSN.gitdeun.common.exception.GlobalException;
import com.teamEWSN.gitdeun.common.oauth.record.GoogleTokenResponse;
import com.teamEWSN.gitdeun.common.oauth.dto.GoogleTokenResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import com.teamEWSN.gitdeun.common.exception.ErrorCode;
import com.teamEWSN.gitdeun.common.oauth.entity.OauthProvider;
import com.teamEWSN.gitdeun.common.oauth.entity.SocialConnection;
import com.teamEWSN.gitdeun.common.oauth.record.GoogleTokenResponse;
import com.teamEWSN.gitdeun.common.oauth.dto.GoogleTokenResponse;
import com.teamEWSN.gitdeun.common.oauth.repository.SocialConnectionRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.teamEWSN.gitdeun.mindmap.controller;

import com.teamEWSN.gitdeun.common.jwt.CustomUserDetails;
import com.teamEWSN.gitdeun.mindmap.dto.MindmapCreateRequest;
import com.teamEWSN.gitdeun.mindmap.dto.MindmapCreateRequestDto;
import com.teamEWSN.gitdeun.mindmap.dto.MindmapDetailResponseDto;
import com.teamEWSN.gitdeun.mindmap.dto.MindmapResponseDto;
import com.teamEWSN.gitdeun.mindmap.service.MindmapService;
Expand All @@ -13,24 +13,24 @@
import org.springframework.web.bind.annotation.*;

@Slf4j
@RestController
@RestController("/api/mindmaps")
@RequiredArgsConstructor
public class MindmapController {

private final MindmapService mindmapService;


// λ§ˆμΈλ“œλ§΅ 생성
// λ§ˆμΈλ“œλ§΅ 생성 (λ§ˆμΈλ“œλ§΅μ— ν•œν•΄μ„œ owner κΆŒν•œ μ–»μŒ)
@PostMapping
public ResponseEntity<MindmapResponseDto> createMindmap(
@RequestBody MindmapCreateRequest request,
@RequestBody MindmapCreateRequestDto request,
@AuthenticationPrincipal CustomUserDetails userDetails
) {
MindmapResponseDto responseDto = mindmapService.createMindmap(request, userDetails.getId());
return ResponseEntity.status(HttpStatus.CREATED).body(responseDto);
}

// λ§ˆμΈλ“œλ§΅ 상세 쑰회(μœ μ € 인가 ν™•μΈν•„μš”)
// λ§ˆμΈλ“œλ§΅ 상세 쑰회 (μœ μ € 인가 ν™•μΈν•„μš”?)
@GetMapping("/{mapId}")
public ResponseEntity<MindmapDetailResponseDto> getMindmap(
@PathVariable Long mapId
Expand All @@ -49,7 +49,7 @@ public ResponseEntity<MindmapDetailResponseDto> refreshMindmap(
return ResponseEntity.ok(responseDto);
}

// λ§ˆμΈλ“œλ§΅ μ‚­μ œ
// λ§ˆμΈλ“œλ§΅ μ‚­μ œ (owner만)
@DeleteMapping("/{mapId}")
public ResponseEntity<Void> deleteMindmap(
@PathVariable Long mapId,
Expand All @@ -60,6 +60,4 @@ public ResponseEntity<Void> deleteMindmap(
}


// TODO: λ§ˆμΈλ“œλ§΅ λ°©λ¬Έ μ‹œ / μƒˆλ‘œκ³ μΉ¨ μ‹œ μ—…λŽƒ μžλ™ 확인 + μž¬λ™κΈ°ν™”

}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

@Getter
@NoArgsConstructor
public class MindmapCreateRequest {
public class MindmapCreateRequestDto {
private String repoUrl;
private String prompt;
private MindmapType type;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,19 @@
import com.teamEWSN.gitdeun.common.exception.GlobalException;
import com.teamEWSN.gitdeun.common.fastapi.FastApiClient;
import com.teamEWSN.gitdeun.common.fastapi.dto.AnalysisResultDto;
import com.teamEWSN.gitdeun.mindmap.dto.MindmapCreateRequest;
import com.teamEWSN.gitdeun.mindmap.dto.MindmapCreateRequestDto;
import com.teamEWSN.gitdeun.mindmap.dto.MindmapDetailResponseDto;
import com.teamEWSN.gitdeun.mindmap.dto.MindmapResponseDto;
import com.teamEWSN.gitdeun.mindmap.entity.Mindmap;
import com.teamEWSN.gitdeun.mindmapmember.entity.MindmapMember;
import com.teamEWSN.gitdeun.mindmapmember.entity.MindmapRole;
import com.teamEWSN.gitdeun.mindmap.entity.MindmapType;
import com.teamEWSN.gitdeun.mindmap.mapper.MindmapMapper;
import com.teamEWSN.gitdeun.mindmapmember.repository.MindmapMemberRepository;
import com.teamEWSN.gitdeun.mindmap.repository.MindmapRepository;
import com.teamEWSN.gitdeun.repo.entity.Repo;
import com.teamEWSN.gitdeun.repo.repository.RepoRepository;
import com.teamEWSN.gitdeun.repo.service.RepoService;
import com.teamEWSN.gitdeun.user.entity.User;
import com.teamEWSN.gitdeun.user.repository.UserRepository;
import com.teamEWSN.gitdeun.visithistory.service.VisitHistoryService;
Expand All @@ -29,24 +33,24 @@
@Service
@RequiredArgsConstructor
public class MindmapService {

private final VisitHistoryService visitHistoryService;
private final RepoService repoService;
private final MindmapMapper mindmapMapper;
private final MindmapRepository mindmapRepository;
private final MindmapMemberRepository mindmapMemberRepository;
private final RepoRepository repoRepository;
private final UserRepository userRepository;
private final FastApiClient fastApiClient;

@Transactional
public MindmapResponseDto createMindmap(MindmapCreateRequest req, Long userId) {
public MindmapResponseDto createMindmap(MindmapCreateRequestDto req, Long userId) {
User user = userRepository.findByIdAndDeletedAtIsNull(userId)
.orElseThrow(() -> new GlobalException(ErrorCode.USER_NOT_FOUND_BY_ID));

AnalysisResultDto dto = fastApiClient.analyze(req.getRepoUrl(), req.getPrompt(), req.getType());

Repo repo = repoRepository.findByGithubRepoUrl(req.getRepoUrl())
.orElseGet(() -> Repo.builder().githubRepoUrl(req.getRepoUrl()).build());

repo.updateWithAnalysis(dto);
Repo repo = repoService.createOrUpdate(req.getRepoUrl(), dto);
repoRepository.save(repo);

String field;
Expand Down Expand Up @@ -74,6 +78,11 @@ public MindmapResponseDto createMindmap(MindmapCreateRequest req, Long userId) {

mindmapRepository.save(mindmap);

// λ§ˆμΈλ“œλ§΅ μ†Œμœ μž 등둝
mindmapMemberRepository.save(
MindmapMember.of(mindmap, user, MindmapRole.OWNER)
);

// λ°©λ¬Έ 기둝 생성
visitHistoryService.createVisitHistory(user, mindmap);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package com.teamEWSN.gitdeun.mindmapmember.controller;

import com.teamEWSN.gitdeun.common.jwt.CustomUserDetails;
import com.teamEWSN.gitdeun.mindmapmember.dto.RoleChangeRequestDto;
import com.teamEWSN.gitdeun.mindmapmember.service.MindmapMemberService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.*;

@Slf4j
@RestController("/api/mindmaps/{mapId}/members/{memberId}")
@RequiredArgsConstructor
public class MindmapMemberController {

private final MindmapMemberService memberService;

// λ§ˆμΈλ“œλ§΅ 멀버 κΆŒν•œ λ³€κ²½
@PatchMapping("/role")
public ResponseEntity<Void> updateRole(
@PathVariable Long mapId,
@PathVariable Long memberId,
@RequestBody RoleChangeRequestDto dto,
@AuthenticationPrincipal CustomUserDetails user) {
memberService.changeRole(mapId, memberId, dto.getRole(), user.getId());
return ResponseEntity.ok().build();
}

// λ§ˆμΈλ“œλ§΅ 멀버 μΆ”λ°©
@DeleteMapping
public ResponseEntity<Void> kickMember(
@PathVariable Long mapId,
@PathVariable Long memberId,
@AuthenticationPrincipal CustomUserDetails user) {
memberService.removeMember(mapId, memberId, user.getId());
return ResponseEntity.ok().build();
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.teamEWSN.gitdeun.mindmapmember.dto;

import com.teamEWSN.gitdeun.mindmapmember.entity.MindmapRole;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class RoleChangeRequestDto {
private MindmapRole role; // OWNER, EDITOR, VIEWER
}
Loading