Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
74 commits
Select commit Hold shift + click to select a range
01f15d3
feat: 스페이스멤버 초대 구현중
juykoung Sep 18, 2025
aea1da3
Merge branch 'main' of https://github.com/Kernel180-BE12/Final-1team-…
juykoung Sep 18, 2025
9f0ba3a
feat: 스페이스id, 유저id로 스페이스 멤버조회 구현
juykoung Sep 18, 2025
5e5b6c9
refactor: 스페이스멤버 추가 구현 중(2)
juykoung Sep 18, 2025
dea8dce
refactor: findByEmailAndSpaceId 제거
juykoung Sep 18, 2025
bcfefbc
Merge branch 'develop' of https://github.com/Kernel180-BE12/Final-1te…
juykoung Sep 19, 2025
bbd05db
refactor: SpaceMember email 제거
juykoung Sep 19, 2025
e6ae714
Merge branch 'develop' into feature/spaceMember-invite
juykoung Sep 19, 2025
b2f7535
feat: 멤버초대 구현
juykoung Sep 19, 2025
9948f3c
docs: 불필요한 부분 삭제
juykoung Sep 19, 2025
bc2de9e
feat: 스페이스 멤버 추가 구현
juykoung Sep 22, 2025
e8636c9
Merge branch 'develop' of https://github.com/Kernel180-BE12/Final-1te…
juykoung Sep 22, 2025
b2a63b3
feat: findByEmail 추가
juykoung Sep 22, 2025
5a96e2e
Merge remote-tracking branch 'origin/feature/spaceMember-invite' into…
juykoung Sep 22, 2025
d402cc4
docs: swagger 추가
juykoung Sep 22, 2025
de7d737
fix: findByUserEmailAndSpaceIdAndStatus 쿼리수정
juykoung Sep 22, 2025
294a21c
feat: 필드 및 메서드 추가
juykoung Sep 22, 2025
e92f559
refactor: 불필요 메서드 삭제
juykoung Sep 22, 2025
1ca635e
fix: @AuthenticationPrincipal 추가
juykoung Sep 22, 2025
873e856
refactor: 스페이스 멤버 리스트 조회 시, sm.isDeleted 추가
juykoung Sep 22, 2025
be657e7
refactor: 초대메일 발송 후 InviteStatus 테이블에 저장되도록 로직 수정
juykoung Sep 22, 2025
6efe9c8
docs: 스페이스멤버 초대 메일 템플릿 구현
juykoung Sep 22, 2025
df8547e
feat: InviteStatusRepository 구현
juykoung Sep 22, 2025
72d6988
chore: 불필요 import 삭제
juykoung Sep 22, 2025
6c30654
fix: 비회원 inviteStatus에 insert되지 않는 부분 수정
juykoung Sep 23, 2025
afbc20c
Merge branch 'main' of https://github.com/Kernel180-BE12/Final-1team-…
juykoung Sep 24, 2025
4a8dbd1
fix: ${restUrl} 수정
juykoung Sep 24, 2025
4ba051d
refactor: 스페이스 멤버로 등록될 때, 논리삭제값 자동세팅
juykoung Sep 24, 2025
1619e0e
fix: 메일url 수정
juykoung Sep 24, 2025
611c6d6
refactor: 안쓰는 메서드 삭제
juykoung Sep 24, 2025
dc87f87
refactor: acceptInvitation 리턴타입 변경
juykoung Sep 24, 2025
63a378b
refactor: EXPIRED(초대 유효일 만료) 상태추가
juykoung Sep 24, 2025
ea8dd37
Merge branch 'main' of https://github.com/Kernel180-BE12/Final-1team-…
juykoung Sep 24, 2025
a619f62
Merge remote-tracking branch 'origin/feature/spaceMember-invite' into…
juykoung Sep 24, 2025
a99dc9d
fix: 이전 머지에 누락된sendInviteEmailToUser 파라미터 email 추가
juykoung Sep 24, 2025
ab3d890
rename : dto로 경로이동
juykoung Sep 24, 2025
e01a8c2
feat : findByEmailAndSpaceIdAndStatus 메서드 추가
juykoung Sep 24, 2025
ab4fc8c
refactor : 멤버초대/메일수락 수정
juykoung Sep 24, 2025
b044969
feat: 스페이스 멤버 초대 결과를 담는 InviteResult DTO 추가
juykoung Sep 24, 2025
2bce383
Merge branch 'develop' of https://github.com/Kernel180-BE12/Final-1te…
juykoung Sep 25, 2025
94f9ecc
Merge branch 'main' of https://github.com/Kernel180-BE12/Final-1team-…
juykoung Sep 25, 2025
d7f6406
feat: 스페이스멤버로 초대받아 회원가입하는 기능 구현
juykoung Sep 25, 2025
67627f4
Merge branch 'develop' into feature/spaceMember-register
juykoung Sep 25, 2025
122cf4b
feat: 스페이스멤버 논리삭제 및 수정 구현
juykoung Sep 26, 2025
fefc9a4
refactor: 초대메일 url 변경
juykoung Sep 26, 2025
b17722e
refactor: 초대메일 회원가입 수정
juykoung Sep 26, 2025
7b11bc5
Merge remote-tracking branch 'origin/feature/spaceMember-register' in…
juykoung Sep 26, 2025
2c1057c
Merge branch 'develop' into feature/spaceMember-register
juykoung Sep 26, 2025
3b750e1
Update UserService.java
juykoung Sep 26, 2025
6be4a30
refactor: sendInviteEmailToSingUp - email 파라미터 삭제누락
juykoung Sep 26, 2025
113963a
Merge branch 'main' of https://github.com/Kernel180-BE12/Final-1team-…
juykoung Sep 26, 2025
d699e0e
refactor: 스페이스멤버 다중삭제로 수정
juykoung Sep 26, 2025
aeee87c
Merge remote-tracking branch 'origin/feature/spaceMember-register' in…
juykoung Sep 26, 2025
68907f1
docs: 스웨거 수정
juykoung Sep 26, 2025
4a3488d
refactor: 없는멤버 삭제 시 에러추가
juykoung Sep 26, 2025
c617fc0
Merge branch 'develop' into feature/spaceMember-register
juykoung Sep 26, 2025
f312bfd
feat: 스페이스 멤버 태그조회 구현
juykoung Sep 27, 2025
8708d13
Merge branch 'develop' into feature/spaceMember-register
juykoung Sep 27, 2025
e607514
refactor: 멤버리스트 조회 내역 변경
juykoung Sep 30, 2025
773cf19
Merge remote-tracking branch 'origin/feature/spaceMember-register' in…
juykoung Sep 30, 2025
8161ef9
Merge branch 'develop' into feature/spaceMember-register
juykoung Sep 30, 2025
0c15b31
refactor: 멤버리스트 조회 내역 변경
juykoung Sep 30, 2025
b8e1e88
Merge remote-tracking branch 'origin/feature/spaceMember-register' in…
juykoung Sep 30, 2025
13b7f41
스페이스멤버 리스트 조회내역 변경 (#102)
juykoung Sep 30, 2025
68b4548
refactor: 멤버 논리삭제 @Builder.Default 설정
juykoung Sep 30, 2025
15a607d
Merge branch 'main' of https://github.com/Kernel180-BE12/Final-1team-…
juykoung Sep 30, 2025
c2b9257
refactor: 멤버만 멤버리스트 조회 가능하게 변경
juykoung Sep 30, 2025
5e717a8
refactor: @DynamicUpdate 추가
juykoung Sep 30, 2025
7d2efb8
Merge remote-tracking branch 'origin/feature/spaceMember-register' in…
juykoung Sep 30, 2025
4ca114d
refactor: 태그별/멤버조회는 해당 스페이스 멤버만 가능하도록 조건 추가
juykoung Sep 30, 2025
21313ce
refactor: 로그인 유저는 회원가입 접근 못하게 수정
juykoung Oct 1, 2025
241ff91
refactor: 멤버 초대 시 '멤버'만 가능하게, 삭제 시 관리자는 삭제 금지
juykoung Oct 1, 2025
8f8d9e5
Merge remote-tracking branch 'origin/feature/spaceMember-register' in…
juykoung Oct 1, 2025
c321e70
Merge branch 'develop' into feature/spaceMember-register
juykoung Oct 1, 2025
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 @@ -15,6 +15,7 @@
import org.springframework.core.Ordered;
import org.springframework.security.authentication.*;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.authorization.AuthorizationDecision;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.annotation.web.configurers.HeadersConfigurer;
Expand Down Expand Up @@ -132,7 +133,13 @@ public SecurityFilterChain securityFilterChain(
.headers(headers -> headers.frameOptions(HeadersConfigurer.FrameOptionsConfig::sameOrigin))
.authorizeHttpRequests(
auth ->
auth.requestMatchers(props.getPermitAll().toArray(String[]::new))
auth
.requestMatchers("/register", "/user/register")
.access((authentication, context) -> {
boolean noSession = authentication.get().getPrincipal().equals("anonymousUser");
return new AuthorizationDecision(noSession);
})
.requestMatchers(props.getPermitAll().toArray(String[]::new))
.permitAll()
.requestMatchers(props.getPermitUser().toArray(String[]::new))
.permitAll()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,17 +66,14 @@ public ResponseEntity<Void> acceptInvitation(
return ResponseEntity.ok().build();
}

/**
* 특정 스페이스의 모든 멤버를 조회합니다.
*
* @param spaceId 멤버를 조회할 스페이스 ID
* @return 스페이스 멤버 목록과 HTTP 상태 코드
*/
@Operation(summary = "스페이스 멤버 조회", description = "특정 spaceId에 속한 모든 멤버 정보를 가져옵니다.")
@Parameter(name = "spaceId", description = "멤버를 조회할 스페이스의 ID", required = true)
@Operation(summary = "스페이스 멤버 조회", description = "특정 스페이스에 속한 모든 멤버 정보를 조회합니다. 해당 스페이스의 멤버만 조회할 수 있습니다.")
@Parameter(name = "spaceId", description = "멤버를 조회할 스페이스의 ID", required = true)
@ApiResponse(responseCode = "200", description = "멤버 조회 성공")
@ApiResponse(responseCode = "403", description = "해당 스페이스 멤버가 아닌 경우")
@GetMapping("/{spaceId}/members")
public ResponseEntity<List<SpaceMemberListResponseDto>> getSpaceMembers(@PathVariable Long spaceId) {
List<SpaceMemberListResponseDto> result = spaceMemberService.getSpaceMembers(spaceId);
public ResponseEntity<List<SpaceMemberListResponseDto>> getSpaceMembers(@PathVariable Long spaceId,
@AuthenticationPrincipal CustomUserDetails principal) {
List<SpaceMemberListResponseDto> result = spaceMemberService.getSpaceMembers(spaceId, principal);
return ResponseEntity.ok(result);
}

Expand Down Expand Up @@ -161,7 +158,7 @@ public ResponseEntity<List<SpaceMemberListResponseDto>> getMemberByTag(
@Parameter(hidden = true)
@AuthenticationPrincipal CustomUserDetails principal
) {
List<SpaceMemberListResponseDto> result = spaceMemberService.getMemberByTag(spaceId, tag, principal.getUserId());
List<SpaceMemberListResponseDto> result = spaceMemberService.getMemberByTag(spaceId, tag, principal);

return ResponseEntity.ok(result);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import org.fastcampus.jober.space.entity.Space;
import org.fastcampus.jober.space.entity.SpaceMember;
import org.fastcampus.jober.user.entity.Users;
import org.hibernate.annotations.DynamicUpdate;

import java.time.LocalDateTime;

Expand All @@ -19,6 +20,7 @@
@Getter
@NoArgsConstructor
@AllArgsConstructor
@DynamicUpdate
public class InviteStatus extends BaseEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
Expand Down Expand Up @@ -48,13 +50,17 @@ public void updateStatus(InviteStatusType status) {
this.status = status;
}

/**
* 얘를 SpaceMemberMapper로 옮기면 this.tag, this.authority를 그대로 가져오지 못하는데
* SpaceMember toSpaceMember(InviteStatus inviteStatus, Space space, Users user); 처럼 파라미터를 늘리는게 나은지
* 아님 지금처럼 이 파일에 두는게 나은지?
*/
public SpaceMember toSpaceMember(Space space, Users user) {
return SpaceMember.builder()
.space(space)
.user(user)
.tag(this.tag)
.authority(this.authority)
.isDeleted(false)
.build();
}
}
2 changes: 2 additions & 0 deletions src/main/java/org/fastcampus/jober/space/entity/Space.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,14 @@
import org.fastcampus.jober.error.ErrorCode;
import org.fastcampus.jober.space.dto.request.SpaceUpdateRequestDto;
import org.fastcampus.jober.user.entity.Users;
import org.hibernate.annotations.DynamicUpdate;

@Entity
@Getter
@NoArgsConstructor
@AllArgsConstructor
@Builder
@DynamicUpdate
public class Space extends BaseEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,14 @@
import org.fastcampus.jober.common.entity.BaseEntity;
import org.fastcampus.jober.space.dto.request.MemberUpdateRequestDto;
import org.fastcampus.jober.user.entity.Users;
import org.hibernate.annotations.DynamicUpdate;

@Entity
@Getter
@AllArgsConstructor
@NoArgsConstructor
@Builder
@DynamicUpdate
public class SpaceMember extends BaseEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
Expand All @@ -33,8 +35,8 @@ public class SpaceMember extends BaseEntity {
@JoinColumn(name = "userId")
private Users user;

@Column(nullable = false)
@Builder.Default
@Column(nullable = false) // DB 스키마의 제약조건
@Builder.Default // 애플리케이션 레벨 기본값
private Boolean isDeleted = false; // 멤버 논리삭제 유무

public void softDelete() {isDeleted = true;}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ public InviteResult inviteSpaceMember(Long spaceId, List<SpaceMemberAddRequestDt
successEmails.add(dto.getEmail());

InviteStatus inviteMember = InviteStatus.builder()
.authority(dto.getAuthority())
.authority(Authority.MEMBER) // 일단 멤버로만 추가 가능하게 수정
.tag(dto.getTag())
.email(dto.getEmail())
.status(InviteStatusType.PENDING)
Expand Down Expand Up @@ -140,7 +140,10 @@ public void processSpaceInvitation(Long spaceId, String email, Users user) {
spaceMemberRepository.save(spaceMember);
}

public List<SpaceMemberListResponseDto> getSpaceMembers(Long spaceId) {
public List<SpaceMemberListResponseDto> getSpaceMembers(Long spaceId, CustomUserDetails principal) {
spaceMemberRepository.findBySpaceIdAndUserId(spaceId, principal.getUserId())
.orElseThrow(() -> new BusinessException(ErrorCode.FORBIDDEN, "해당 스페이스 멤버만 조회할 수 있습니다."));

List<SpaceMember> spaceMembers = spaceMemberRepository.findBySpaceId(spaceId);
return spaceMemberMapper.toMemberResponseDtoList(spaceMembers);
}
Expand All @@ -155,6 +158,13 @@ public void deleteSpaceMember(List<Long> memberIds, Long spaceId, CustomUserDeta
if (members.size() != memberIds.size()) {
throw new BusinessException(ErrorCode.NOT_FOUND, "해당하는 멤버가 없습니다.");}

boolean containsAdmin = members.stream()
.anyMatch(m -> m.getAuthority() == Authority.ADMIN);

if (containsAdmin) {
throw new BusinessException(ErrorCode.BAD_REQUEST, "관리자는 삭제할 수 없습니다.");
}

members.forEach(SpaceMember::softDelete);

// 3. 명시적 저장 (혹시 모를 Dirty Checking 문제 방지)
Expand All @@ -172,15 +182,12 @@ public MemberUpdateResponseDto updateMember(Long memberId, Long spaceId, MemberU
return spaceMemberMapper.toMemberUpdateResponseDto(member);
}

public List<SpaceMemberListResponseDto> getMemberByTag(Long spaceId, String tag, Long userId) {

spaceRepository.findByIdOrThrow(spaceId);

spaceMemberRepository.findBySpaceIdAndUserId(spaceId, userId)
public List<SpaceMemberListResponseDto> getMemberByTag(Long spaceId, String tag, CustomUserDetails principal) {
spaceMemberRepository.findBySpaceIdAndUserId(spaceId, principal.getUserId())
.orElseThrow(() -> new BusinessException(ErrorCode.FORBIDDEN, "해당 스페이스 멤버만 조회할 수 있습니다."));

spaceRepository.findByIdOrThrow(spaceId);
List<SpaceMember> members = spaceMemberRepository.findBySpaceIdAndTag(spaceId, tag);

return spaceMemberMapper.toMemberResponseDtoList(members);

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ public void createSpace(SpaceCreateRequestDto dto, CustomUserDetails principal)
.spaceId(savedSpace.getSpaceId())
.userId(principal.getUserId())
.authority(Authority.ADMIN)
.isDeleted(false)
.build();

SpaceMember spaceMember = spaceMemberMapper.toEntity(adminUser);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@ public Long getUserId(String username) throws UsernameNotFoundException {
return userRepository.findByUsernameAndIsDeletedFalse(username).orElseThrow().getUserId();
}

/**
* 이메일로 초대받아 진행되는 회원가입
* @param req
* @param spaceId
*/
@Transactional
public void register(RegisterRequestDto req, Long spaceId) {
register(req);
Expand All @@ -47,9 +52,6 @@ public void register(RegisterRequestDto req, Long spaceId) {
}


/**
* 이메일로 초대받아 진행되는 회원가입
*/
@Transactional
public void register(RegisterRequestDto req) {
// 입력값 형식 검증
Expand Down
1 change: 0 additions & 1 deletion src/main/resources/application-develop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ security:
- /h2-console/**
- /admin/sessions/**
permit-user:
- /user/register
- /user/login
- /user/id/check
- /user/email/check
Expand Down
1 change: 0 additions & 1 deletion src/main/resources/application-production.yml
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ security:
- /swagger-ui.html
- /admin/sessions/**
permit-user:
- /user/register
- /user/login
- /user/id/check
- /user/email/check
Expand Down