improvement: API Key 마스킹 및 전체 조회 엔드포인트 추가 (#220)
All checks were successful
SPMS_API/pipeline/head This commit looks good
All checks were successful
SPMS_API/pipeline/head This commit looks good
Reviewed-on: https://git.ipstein.myds.me/SPMS/SPMS_API/pulls/221
This commit is contained in:
commit
fecd322763
|
|
@ -116,7 +116,7 @@ public class ServiceController : ControllerBase
|
||||||
[HttpPost("{serviceCode}")]
|
[HttpPost("{serviceCode}")]
|
||||||
[SwaggerOperation(
|
[SwaggerOperation(
|
||||||
Summary = "서비스 상세 조회",
|
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(200, "조회 성공", typeof(ApiResponse<ServiceResponseDto>))]
|
||||||
[SwaggerResponse(401, "인증되지 않은 요청")]
|
[SwaggerResponse(401, "인증되지 않은 요청")]
|
||||||
[SwaggerResponse(403, "권한 없음")]
|
[SwaggerResponse(403, "권한 없음")]
|
||||||
|
|
@ -144,6 +144,20 @@ public class ServiceController : ControllerBase
|
||||||
return Ok(ApiResponse<ServiceResponseDto>.Success(result));
|
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")]
|
[HttpPost("{serviceCode}/apikey/refresh")]
|
||||||
[SwaggerOperation(
|
[SwaggerOperation(
|
||||||
Summary = "API Key 재발급",
|
Summary = "API Key 재발급",
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ public interface IServiceManagementService
|
||||||
Task<ServiceResponseDto> GetByServiceCodeAsync(string serviceCode);
|
Task<ServiceResponseDto> GetByServiceCodeAsync(string serviceCode);
|
||||||
Task DeleteAsync(DeleteServiceRequestDto request);
|
Task DeleteAsync(DeleteServiceRequestDto request);
|
||||||
Task<ServiceResponseDto> ChangeStatusAsync(string serviceCode, ChangeServiceStatusRequestDto request);
|
Task<ServiceResponseDto> ChangeStatusAsync(string serviceCode, ChangeServiceStatusRequestDto request);
|
||||||
|
Task<ApiKeyRefreshResponseDto> ViewApiKeyAsync(string serviceCode);
|
||||||
Task<ApiKeyRefreshResponseDto> RefreshApiKeyAsync(string serviceCode);
|
Task<ApiKeyRefreshResponseDto> RefreshApiKeyAsync(string serviceCode);
|
||||||
Task RegisterApnsCredentialsAsync(string serviceCode, ApnsCredentialsRequestDto request);
|
Task RegisterApnsCredentialsAsync(string serviceCode, ApnsCredentialsRequestDto request);
|
||||||
Task RegisterFcmCredentialsAsync(string serviceCode, FcmCredentialsRequestDto request);
|
Task RegisterFcmCredentialsAsync(string serviceCode, FcmCredentialsRequestDto request);
|
||||||
|
|
|
||||||
|
|
@ -314,6 +314,25 @@ public class ServiceManagementService : IServiceManagementService
|
||||||
return MapToDto(service);
|
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)
|
public async Task<ApiKeyRefreshResponseDto> RefreshApiKeyAsync(string serviceCode)
|
||||||
{
|
{
|
||||||
var service = await _serviceRepository.GetByServiceCodeAsync(serviceCode);
|
var service = await _serviceRepository.GetByServiceCodeAsync(serviceCode);
|
||||||
|
|
@ -981,7 +1000,7 @@ public class ServiceManagementService : IServiceManagementService
|
||||||
ServiceCode = service.ServiceCode,
|
ServiceCode = service.ServiceCode,
|
||||||
ServiceName = service.ServiceName,
|
ServiceName = service.ServiceName,
|
||||||
Description = service.Description,
|
Description = service.Description,
|
||||||
ApiKey = service.ApiKey,
|
ApiKey = MaskApiKey(service.ApiKey),
|
||||||
ApiKeyCreatedAt = service.ApiKeyCreatedAt,
|
ApiKeyCreatedAt = service.ApiKeyCreatedAt,
|
||||||
ApnsBundleId = service.ApnsBundleId,
|
ApnsBundleId = service.ApnsBundleId,
|
||||||
ApnsKeyId = service.ApnsKeyId,
|
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>
|
/// <summary>
|
||||||
/// 서비스의 플랫폼 자격증명 상태를 판정하여 PlatformSummaryDto를 반환합니다.
|
/// 서비스의 플랫폼 자격증명 상태를 판정하여 PlatformSummaryDto를 반환합니다.
|
||||||
/// Android: FcmCredentials 유무로 판정
|
/// Android: FcmCredentials 유무로 판정
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user