improvement: API Key 마스킹 및 전체 조회 엔드포인트 추가 (#220) #221
|
|
@ -116,7 +116,7 @@ public class ServiceController : ControllerBase
|
|||
[HttpPost("{serviceCode}")]
|
||||
[SwaggerOperation(
|
||||
Summary = "서비스 상세 조회",
|
||||
Description = "특정 서비스의 상세 정보를 조회합니다. apnsAuthType(p8/p12)과 platforms 필드로 각 플랫폼의 자격증명 상태(credentialStatus: ok/warn/error), 만료일(expiresAt) 정보를 포함합니다.")]
|
||||
Description = "특정 서비스의 상세 정보를 조회합니다. API Key는 마스킹(앞 8자+********)되어 반환되며, 전체 키 조회는 apikey/view 엔드포인트를 사용합니다. apnsAuthType(p8/p12)과 platforms 필드로 각 플랫폼의 자격증명 상태(credentialStatus: ok/warn/error), 만료일(expiresAt) 정보를 포함합니다.")]
|
||||
[SwaggerResponse(200, "조회 성공", typeof(ApiResponse<ServiceResponseDto>))]
|
||||
[SwaggerResponse(401, "인증되지 않은 요청")]
|
||||
[SwaggerResponse(403, "권한 없음")]
|
||||
|
|
@ -144,6 +144,20 @@ public class ServiceController : ControllerBase
|
|||
return Ok(ApiResponse<ServiceResponseDto>.Success(result));
|
||||
}
|
||||
|
||||
[HttpPost("{serviceCode}/apikey/view")]
|
||||
[SwaggerOperation(
|
||||
Summary = "API Key 전체 조회",
|
||||
Description = "서비스의 API Key 전체 값을 조회합니다. 상세 조회 시 마스킹된 키 대신 전체 키를 확인할 때 사용합니다. 키 회전(재발급) 없이 현재 키를 반환합니다.")]
|
||||
[SwaggerResponse(200, "조회 성공", typeof(ApiResponse<ApiKeyRefreshResponseDto>))]
|
||||
[SwaggerResponse(401, "인증되지 않은 요청")]
|
||||
[SwaggerResponse(403, "권한 없음")]
|
||||
[SwaggerResponse(404, "서비스를 찾을 수 없음")]
|
||||
public async Task<IActionResult> ViewApiKeyAsync([FromRoute] string serviceCode)
|
||||
{
|
||||
var result = await _serviceManagementService.ViewApiKeyAsync(serviceCode);
|
||||
return Ok(ApiResponse<ApiKeyRefreshResponseDto>.Success(result));
|
||||
}
|
||||
|
||||
[HttpPost("{serviceCode}/apikey/refresh")]
|
||||
[SwaggerOperation(
|
||||
Summary = "API Key 재발급",
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ public interface IServiceManagementService
|
|||
Task<ServiceResponseDto> GetByServiceCodeAsync(string serviceCode);
|
||||
Task DeleteAsync(DeleteServiceRequestDto request);
|
||||
Task<ServiceResponseDto> ChangeStatusAsync(string serviceCode, ChangeServiceStatusRequestDto request);
|
||||
Task<ApiKeyRefreshResponseDto> ViewApiKeyAsync(string serviceCode);
|
||||
Task<ApiKeyRefreshResponseDto> RefreshApiKeyAsync(string serviceCode);
|
||||
Task RegisterApnsCredentialsAsync(string serviceCode, ApnsCredentialsRequestDto request);
|
||||
Task RegisterFcmCredentialsAsync(string serviceCode, FcmCredentialsRequestDto request);
|
||||
|
|
|
|||
|
|
@ -314,6 +314,25 @@ public class ServiceManagementService : IServiceManagementService
|
|||
return MapToDto(service);
|
||||
}
|
||||
|
||||
public async Task<ApiKeyRefreshResponseDto> ViewApiKeyAsync(string serviceCode)
|
||||
{
|
||||
var service = await _serviceRepository.GetByServiceCodeAsync(serviceCode);
|
||||
if (service is null)
|
||||
{
|
||||
throw new SpmsException(
|
||||
ErrorCodes.NotFound,
|
||||
"서비스를 찾을 수 없습니다.",
|
||||
404);
|
||||
}
|
||||
|
||||
return new ApiKeyRefreshResponseDto
|
||||
{
|
||||
ServiceCode = service.ServiceCode,
|
||||
ApiKey = service.ApiKey,
|
||||
ApiKeyCreatedAt = service.ApiKeyCreatedAt
|
||||
};
|
||||
}
|
||||
|
||||
public async Task<ApiKeyRefreshResponseDto> RefreshApiKeyAsync(string serviceCode)
|
||||
{
|
||||
var service = await _serviceRepository.GetByServiceCodeAsync(serviceCode);
|
||||
|
|
@ -981,7 +1000,7 @@ public class ServiceManagementService : IServiceManagementService
|
|||
ServiceCode = service.ServiceCode,
|
||||
ServiceName = service.ServiceName,
|
||||
Description = service.Description,
|
||||
ApiKey = service.ApiKey,
|
||||
ApiKey = MaskApiKey(service.ApiKey),
|
||||
ApiKeyCreatedAt = service.ApiKeyCreatedAt,
|
||||
ApnsBundleId = service.ApnsBundleId,
|
||||
ApnsKeyId = service.ApnsKeyId,
|
||||
|
|
@ -1003,6 +1022,20 @@ public class ServiceManagementService : IServiceManagementService
|
|||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// API Key를 마스킹합니다 (앞 8자 노출 + ********).
|
||||
/// </summary>
|
||||
private static string MaskApiKey(string apiKey)
|
||||
{
|
||||
if (string.IsNullOrEmpty(apiKey))
|
||||
return string.Empty;
|
||||
|
||||
if (apiKey.Length <= 8)
|
||||
return new string('*', apiKey.Length);
|
||||
|
||||
return apiKey[..8] + "********";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 서비스의 플랫폼 자격증명 상태를 판정하여 PlatformSummaryDto를 반환합니다.
|
||||
/// Android: FcmCredentials 유무로 판정
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user