package gov.nysenate.openleg.dao.log.data; import com.google.common.collect.Range; import gov.nysenate.openleg.dao.base.*; import gov.nysenate.openleg.model.auth.ApiRequest; import gov.nysenate.openleg.model.auth.ApiResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.dao.DataAccessException; import org.springframework.jdbc.core.RowMapper; import org.springframework.jdbc.core.SingleColumnRowMapper; import org.springframework.jdbc.core.namedparam.MapSqlParameterSource; import org.springframework.stereotype.Repository; import java.net.InetAddress; import java.net.UnknownHostException; import java.time.LocalDateTime; import java.util.List; import static gov.nysenate.openleg.util.DateUtils.*; @Repository public class SqlApiLogDao extends SqlBaseDao implements ApiLogDao { private static final Logger logger = LoggerFactory.getLogger(SqlApiLogDao.class); private static final RowMapper<ApiRequest> apiRequestMapper = (rs, rowNum) -> { ApiRequest request = new ApiRequest(); request.setApiKey(rs.getString("apikey")); request.setRequestId(rs.getInt(("request_id"))); request.setRequestMethod(rs.getString("method")); request.setRequestTime(getLocalDateTimeFromRs(rs, "request_time")); request.setUserAgent(rs.getString("agent")); request.setUrl(rs.getString("url")); String ipAddress = rs.getString("ipaddress"); if (ipAddress != null) { try { request.setIpAddress(InetAddress.getByName(ipAddress)); } catch (UnknownHostException e) { logger.error("Failed to parse IP", e); } } return request; }; private static final RowMapper<ApiResponse> apiResponseMapper = (rs, rowNum) -> { ApiRequest apiRequest = apiRequestMapper.mapRow(rs, rowNum); ApiResponse response = new ApiResponse(apiRequest); response.setContentType(rs.getString("content_type")); response.setStatusCode(rs.getInt("status_code")); response.setProcessTime(rs.getDouble("process_time")); response.setResponseDateTime(getLocalDateTimeFromRs(rs, "response_time")); return response; }; private static ImmutableParams getApiRequestParams(ApiRequest req) { return ImmutableParams.from(new MapSqlParameterSource() .addValue("ipAddress", req.getIpAddress().getHostAddress()) .addValue("requestTime", toDate(req.getRequestTime())) .addValue("url", req.getUrl()) .addValue("userAgent", req.getUserAgent()) .addValue("apikey", req.getApiKey()) .addValue("requestMethod", req.getRequestMethod()) ); } private static ImmutableParams getApiResponseParams(ApiResponse response) { return ImmutableParams.from(new MapSqlParameterSource() .addValue("reqId", response.getBaseRequest().getRequestId()) .addValue("responseTime", toDate(response.getResponseDateTime())) .addValue("status", response.getStatusCode()) .addValue("content", response.getContentType()) .addValue("processTime", response.getProcessTime())); } /** {@inheritDoc} */ @Override public List<ApiResponse> getResponses(LimitOffset limOff, SortOrder order) { OrderBy orderBy = new OrderBy("request_time", order); return jdbcNamed.query( ApiRequestResponseQuery.GET_ALL_RESPONSES.getSql(schema(), orderBy, limOff), apiResponseMapper); } /** {@inheritDoc} */ @Override public List<ApiResponse> getResponses(Range<LocalDateTime> dateTimeRange, LimitOffset limOff, SortOrder order) { OrderBy orderBy = new OrderBy("request_time", order); MapSqlParameterSource params = new MapSqlParameterSource(); params.addValue("startDateTime", startOfDateTimeRange(dateTimeRange)); params.addValue("endDateTime", endOfDateTimeRange(dateTimeRange)); return jdbcNamed.query( ApiRequestResponseQuery.GET_ALL_RESPONSES_BY_DATETIME.getSql(schema(), orderBy, limOff), params, apiResponseMapper); } /** {@inheritDoc} */ @Override public void saveApiResponse(ApiResponse response) throws DataAccessException { if (response != null) { ApiRequest apiRequest = response.getBaseRequest(); Integer requestId = jdbcNamed.queryForObject(ApiRequestResponseQuery.INSERT_REQUEST.getSql(schema()), getApiRequestParams(apiRequest), new SingleColumnRowMapper<>()); apiRequest.setRequestId(requestId); jdbcNamed.update(ApiRequestResponseQuery.INSERT_RESPONSE.getSql(schema()), getApiResponseParams(response)); } } }