gc-guide-api/src/main/java/com/gcsc/guide/service/RoleService.java
htlee 9db7b8bfb4 feat: 관리자/활동/이슈 API 전체 구현
- Entity: LoginHistory, PageView, Issue, IssueComment 추가
- Repository: 각 엔티티별 JpaRepository 추가
- Service: UserService, RoleService, ActivityService, IssueService
- Admin API: 사용자 관리 7개, 롤/권한 관리 7개, 통계 1개 엔드포인트
- Activity API: 페이지뷰 기록, 로그인 이력 조회
- Issue API: CRUD + 코멘트, 프로젝트/위치/Gitea 링크 지원
- Exception: GlobalExceptionHandler, ResourceNotFoundException, BusinessException
- AuthController: 로그인 시 LoginHistory 기록 추가
- Dockerfile 추가

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-14 21:13:14 +09:00

89 lines
3.2 KiB
Java

package com.gcsc.guide.service;
import com.gcsc.guide.dto.RoleResponse;
import com.gcsc.guide.entity.Role;
import com.gcsc.guide.entity.RoleUrlPattern;
import com.gcsc.guide.exception.BusinessException;
import com.gcsc.guide.exception.ResourceNotFoundException;
import com.gcsc.guide.repository.RoleRepository;
import com.gcsc.guide.repository.RoleUrlPatternRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
@Service
@RequiredArgsConstructor
public class RoleService {
private final RoleRepository roleRepository;
private final RoleUrlPatternRepository roleUrlPatternRepository;
@Transactional(readOnly = true)
public List<RoleResponse> getRoles() {
return roleRepository.findAllWithUrlPatterns().stream()
.map(RoleResponse::from)
.toList();
}
@Transactional
public RoleResponse createRole(String name, String description) {
roleRepository.findByName(name).ifPresent(r -> {
throw new BusinessException("이미 존재하는 롤 이름입니다: " + name);
});
Role role = new Role(name, description);
return RoleResponse.from(roleRepository.save(role));
}
@Transactional
public RoleResponse updateRole(Long roleId, String name, String description) {
Role role = findRoleById(roleId);
roleRepository.findByName(name)
.filter(r -> !r.getId().equals(roleId))
.ifPresent(r -> {
throw new BusinessException("이미 존재하는 롤 이름입니다: " + name);
});
role.update(name, description);
return RoleResponse.from(roleRepository.save(role));
}
@Transactional
public void deleteRole(Long roleId) {
if (!roleRepository.existsById(roleId)) {
throw new ResourceNotFoundException("", roleId);
}
roleRepository.deleteById(roleId);
}
@Transactional(readOnly = true)
public List<String> getPermissions(Long roleId) {
Role role = roleRepository.findByIdWithUrlPatterns(roleId)
.orElseThrow(() -> new ResourceNotFoundException("", roleId));
return role.getUrlPatterns().stream()
.map(RoleUrlPattern::getUrlPattern)
.toList();
}
@Transactional
public RoleResponse addPermission(Long roleId, String urlPattern) {
Role role = roleRepository.findByIdWithUrlPatterns(roleId)
.orElseThrow(() -> new ResourceNotFoundException("", roleId));
role.getUrlPatterns().add(new RoleUrlPattern(role, urlPattern));
return RoleResponse.from(roleRepository.save(role));
}
@Transactional
public void deletePermission(Long permissionId) {
if (!roleUrlPatternRepository.existsById(permissionId)) {
throw new ResourceNotFoundException("권한", permissionId);
}
roleUrlPatternRepository.deleteById(permissionId);
}
private Role findRoleById(Long roleId) {
return roleRepository.findById(roleId)
.orElseThrow(() -> new ResourceNotFoundException("", roleId));
}
}