Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Time format fix for last login times #692

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
91aae96
Minor correction to the id prop
Jan 11, 2023
18347a3
Merge remote-tracking branch 'upstream/develop' into fix-id-version-i…
Jan 11, 2023
61b0031
minor refactoring
Jan 11, 2023
dda1b45
Fix missing code in refactoring
Jan 11, 2023
9d08f0f
Merge remote-tracking branch 'upstream/develop' into fix-id-version-i…
Jan 11, 2023
9139aa5
Merge remote-tracking branch 'upstream/develop' into fix-id-version-i…
Jan 12, 2023
e866dd1
Added timezone logger
Jan 12, 2023
7a5ea9c
Merge remote-tracking branch 'upstream/develop' into timeszone-test
Jan 12, 2023
29694a5
Merge remote-tracking branch 'upstream/develop' into timeszone-test
Jan 12, 2023
08f0d9c
Merge remote-tracking branch 'upstream/develop' into timeszone-test
Jan 12, 2023
608982e
Minor correction
Jan 12, 2023
c0c27dd
Pom correction
Jan 12, 2023
58b4d11
Merge remote-tracking branch 'upstream/develop' into timeszone-test
Jan 16, 2023
ba8391c
Added timezone based timestamp responses for related APIs
Jan 18, 2023
b65d768
Code to apply timezone offset in timestamp in filename
Jan 18, 2023
6daf6f2
Test fixes
Jan 18, 2023
90cb108
Merge remote-tracking branch 'upstream/develop' into add-timezone-bas…
Jan 18, 2023
35c10c3
Test fix
Jan 18, 2023
7e0c42c
test gix
Jan 18, 2023
e833f3f
Fix to filename pattern
Jan 18, 2023
da64cc0
Merge remote-tracking branch 'upstream/develop' into add-timezone-bas…
Jan 18, 2023
ecfa1d1
Added missing file
Jan 18, 2023
52dc335
Merge remote-tracking branch 'upstream/develop' into add-timezone-bas…
Jan 18, 2023
84a22a9
Refactored to fix utility class name
Jan 18, 2023
019aee3
Merge remote-tracking branch 'upstream/develop' into refactor-fix-uti…
Jan 18, 2023
c278423
Refactored to fix utility class name
Jan 18, 2023
21cf6ff
Merge remote-tracking branch 'upstream/develop' into refactor-fix-uti…
Jan 19, 2023
c416c3c
Fixed last login time offset; filename timestamp; vid generated on time;
Jan 19, 2023
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 @@ -633,11 +633,11 @@ public ResponseEntity<Object> downLoadServiceHistory(
@ApiResponse(responseCode = "403", description = "Forbidden", content = @Content(schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "404", description = "Not Found", content = @Content(schema = @Schema(hidden = true))) })

public ResponseWrapper<UserInfoDto> userinfo()
public ResponseWrapper<UserInfoDto> userinfo(@RequestHeader(name = "time-zone-offset", required = false, defaultValue = "0") int timeZoneOffset)
throws ResidentServiceCheckedException, ApisResourceAccessException {
logger.debug("ResidentController::getuserinfo()::entry");
String Id = identityServiceImpl.getResidentIdaToken();
ResponseWrapper<UserInfoDto> userInfoDto = residentService.getUserinfo(Id);
ResponseWrapper<UserInfoDto> userInfoDto = residentService.getUserinfo(Id, timeZoneOffset);
logger.debug("ResidentController::getuserinfo()::exit");
return userInfoDto;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package io.mosip.resident.dto;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;

import lombok.Data;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ byte[] downLoadServiceHistory(ResponseWrapper<PageDto<ServiceHistoryResponseDto>
String languageCode, LocalDateTime eventReqDateTime, LocalDate fromDateTime, LocalDate toDateTime,
String serviceType, String statusFilter) throws ResidentServiceCheckedException, IOException;

public ResponseWrapper<UserInfoDto> getUserinfo(String Id) throws ApisResourceAccessException;
public ResponseWrapper<UserInfoDto> getUserinfo(String Id, int timeZoneOffset) throws ApisResourceAccessException;

public String getFileName(String eventId, int timeZoneOffset);
}
Original file line number Diff line number Diff line change
Expand Up @@ -1684,7 +1684,7 @@ public PageDto<ServiceHistoryResponseDto> getServiceHistoryResponse(String sortT
LocalDate toDateTime, String serviceType, String langCode, int timeZoneOffset)
throws ResidentServiceCheckedException {
String nativeQueryString = getDynamicNativeQueryString(sortType, idaToken, pageStart, pageFetch, statusFilter,
searchText, fromDateTime, toDateTime, serviceType);
searchText, fromDateTime, toDateTime, serviceType, timeZoneOffset);
Query nativeQuery = entityManager.createNativeQuery(nativeQueryString, ResidentTransactionEntity.class);
List<ResidentTransactionEntity> residentTransactionEntityList = (List<ResidentTransactionEntity>) nativeQuery
.getResultList();
Expand All @@ -1700,24 +1700,24 @@ public PageDto<ServiceHistoryResponseDto> getServiceHistoryResponse(String sortT

public String getDynamicNativeQueryString(String sortType, String idaToken, Integer pageStart, Integer pageFetch,
String statusFilter, String searchText, LocalDate fromDateTime, LocalDate toDateTime,
String serviceType) {
String serviceType, int timeZoneOffset) {
String query = "SELECT * FROM resident_transaction where token_id = '"
+ idaToken+"'";
String dynamicQuery = "";
if (fromDateTime != null && toDateTime != null && serviceType != null && !serviceType.equalsIgnoreCase("ALL")
&& statusFilter != null && searchText != null) {
dynamicQuery = getDateQuery(fromDateTime, toDateTime) + getServiceQuery(serviceType)
dynamicQuery = getDateQuery(fromDateTime, toDateTime, timeZoneOffset) + getServiceQuery(serviceType)
+ getStatusFilterQuery(statusFilter) + getSearchQuery(searchText);
} else if (fromDateTime != null && toDateTime != null && serviceType != null
&& !serviceType.equalsIgnoreCase("ALL") && statusFilter != null) {
dynamicQuery = getDateQuery(fromDateTime, toDateTime) + getServiceQuery(serviceType )
dynamicQuery = getDateQuery(fromDateTime, toDateTime, timeZoneOffset) + getServiceQuery(serviceType )
+ getStatusFilterQuery(statusFilter );
} else if (fromDateTime != null && toDateTime != null && serviceType != null
&& !serviceType.equalsIgnoreCase("ALL") && searchText != null) {
dynamicQuery = getDateQuery(fromDateTime, toDateTime ) + getServiceQuery(serviceType )
dynamicQuery = getDateQuery(fromDateTime, toDateTime, timeZoneOffset) + getServiceQuery(serviceType )
+ getSearchQuery(searchText );
} else if (fromDateTime != null && toDateTime != null && statusFilter != null && searchText != null) {
dynamicQuery = getDateQuery(fromDateTime, toDateTime ) + getStatusFilterQuery(statusFilter )
dynamicQuery = getDateQuery(fromDateTime, toDateTime, timeZoneOffset) + getStatusFilterQuery(statusFilter )
+ getSearchQuery(searchText );
} else if (serviceType != null && !serviceType.equalsIgnoreCase("ALL") && statusFilter != null
&& searchText != null) {
Expand All @@ -1730,14 +1730,14 @@ public String getDynamicNativeQueryString(String sortType, String idaToken, Inte
} else if (statusFilter != null && searchText != null) {
dynamicQuery = getStatusFilterQuery(statusFilter ) + getSearchQuery(searchText );
} else if (fromDateTime != null && toDateTime != null && searchText != null) {
dynamicQuery = getDateQuery(fromDateTime, toDateTime ) + getSearchQuery(searchText );
dynamicQuery = getDateQuery(fromDateTime, toDateTime, timeZoneOffset) + getSearchQuery(searchText );
} else if (fromDateTime != null && toDateTime != null && statusFilter != null) {
dynamicQuery = getDateQuery(fromDateTime, toDateTime ) + getStatusFilterQuery(statusFilter );
dynamicQuery = getDateQuery(fromDateTime, toDateTime, timeZoneOffset) + getStatusFilterQuery(statusFilter );
} else if (fromDateTime != null && toDateTime != null && serviceType != null
&& !serviceType.equalsIgnoreCase("ALL")) {
dynamicQuery = getDateQuery(fromDateTime, toDateTime ) + getServiceQuery(serviceType );
dynamicQuery = getDateQuery(fromDateTime, toDateTime, timeZoneOffset) + getServiceQuery(serviceType );
} else if (fromDateTime != null && toDateTime != null) {
dynamicQuery = getDateQuery(fromDateTime, toDateTime );
dynamicQuery = getDateQuery(fromDateTime, toDateTime, timeZoneOffset);
} else if (serviceType != null && !serviceType.equalsIgnoreCase("ALL")) {
dynamicQuery = getServiceQuery(serviceType );
} else if (statusFilter != null) {
Expand Down Expand Up @@ -1768,9 +1768,10 @@ private String getServiceQuery(String serviceType) {
return " and request_type_code in (" + serviceTypeListString + ")";
}

private String getDateQuery(LocalDate fromDate, LocalDate toDate) {
LocalDateTime fromDateTime = fromDate.atStartOfDay();
LocalDateTime toDateTime = toDate.plusDays(1).atStartOfDay();
private String getDateQuery(LocalDate fromDate, LocalDate toDate, int timeZoneOffset) {
//Converting local time to UTC before using in db query
LocalDateTime fromDateTime = fromDate.atStartOfDay().plusMinutes(timeZoneOffset);
LocalDateTime toDateTime = toDate.plusDays(1).atStartOfDay().plusMinutes(timeZoneOffset);
return " and cr_dtimes between '" + fromDateTime + "' and '" +
toDateTime+ "'";
}
Expand Down Expand Up @@ -2171,7 +2172,7 @@ public byte[] downLoadServiceHistory(ResponseWrapper<PageDto<ServiceHistoryRespo
if(serviceType == null){
serviceType = ALL;
}
servHistoryMap.put("eventReqTimeStamp", eventReqDateTime);
servHistoryMap.put("eventReqTimeStamp", utility.formatWithOffsetForUI(0, eventReqDateTime));//No change to the offset - keep the incoming timestamp with same offset
servHistoryMap.put("fromDate", fromDate);
servHistoryMap.put("toDate", toDate);
servHistoryMap.put("statusFilter", statusFilter);
Expand All @@ -2187,7 +2188,7 @@ public byte[] downLoadServiceHistory(ResponseWrapper<PageDto<ServiceHistoryRespo
}

@Override
public ResponseWrapper<UserInfoDto> getUserinfo(String Id) throws ApisResourceAccessException {
public ResponseWrapper<UserInfoDto> getUserinfo(String Id, int timeZoneOffset) throws ApisResourceAccessException {
String name = identityServiceImpl.getAvailableclaimValue(env.getProperty(ResidentConstants.NAME_FROM_PROFILE));
String photo = identityServiceImpl.getAvailableclaimValue(env.getProperty(IMAGE));
String email = identityServiceImpl.getAvailableclaimValue(env.getProperty(ResidentConstants.EMAIL_FROM_PROFILE));
Expand All @@ -2207,7 +2208,7 @@ public ResponseWrapper<UserInfoDto> getUserinfo(String Id) throws ApisResourceAc
user.setIp(response.get().getIpAddress());
user.setMachineType(response.get().getMachineType());
user.setHost(response.get().getHost());
user.setLastLogin(response.get().getLastloginDtime());
user.setLastLogin(utility.applyTimeZoneOffsetOnDateTime(timeZoneOffset, response.get().getLastloginDtime()));
user.setPhoto(data);
responseWrapper.setResponse(user);
return responseWrapper;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,8 @@
@Component
public class ResidentVidServiceImpl implements ResidentVidService {

private static final String GENRATED_ON_TIMESTAMP = "genratedOnTimestamp";

private static final String EXPIRY_TIMESTAMP = "expiryTimestamp";

private static final String TRANSACTIONS_LEFT_COUNT = "transactionsLeftCount";
Expand Down Expand Up @@ -735,7 +737,8 @@ public ResponseWrapper<List<Map<String,?>>> retrieveVidsfromUin(String uin, int
LinkedHashMap<String, Object> lhm = new LinkedHashMap<String, Object>(map);
getMaskedVid(lhm);
getRefIdHash(lhm);
normalizeExpiryTime(lhm, timeZoneOffset);
normalizeTime(EXPIRY_TIMESTAMP, lhm, timeZoneOffset);
normalizeTime(GENRATED_ON_TIMESTAMP, lhm, timeZoneOffset);
return lhm;
})
.collect(Collectors.toList());
Expand All @@ -748,16 +751,16 @@ public ResponseWrapper<List<Map<String,?>>> retrieveVidsfromUin(String uin, int

}

private void normalizeExpiryTime(LinkedHashMap<String, Object> lhm, int timeZoneOffset) {
Object expiryTimeObj = lhm.get(EXPIRY_TIMESTAMP);
if(expiryTimeObj instanceof String) {
String expiryTime = String.valueOf(expiryTimeObj);
LocalDateTime expiryLocalDateTime = mapper.convertValue(expiryTime, LocalDateTime.class);
private void normalizeTime(String attributeName, LinkedHashMap<String, Object> lhm, int timeZoneOffset) {
Object timeObject = lhm.get(attributeName);
if(timeObject instanceof String) {
String timeStr = String.valueOf(timeObject);
LocalDateTime localDateTime = mapper.convertValue(timeStr, LocalDateTime.class);
//For the big expiry time, assume no expiry time, so set to null
if(expiryLocalDateTime.getYear() >= 9999) {
lhm.put(EXPIRY_TIMESTAMP, null);
if(localDateTime.getYear() >= 9999) {
lhm.put(attributeName, null);
} else {
lhm.put(EXPIRY_TIMESTAMP, utility.formatWithOffsetForUI(timeZoneOffset, expiryLocalDateTime)) ;
lhm.put(attributeName, utility.formatWithOffsetForUI(timeZoneOffset, localDateTime)) ;
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,58 @@
package io.mosip.resident.util;

import static io.mosip.resident.constant.MappingJsonConstants.EMAIL;
import static io.mosip.resident.constant.MappingJsonConstants.PHONE;
import static io.mosip.resident.constant.RegistrationConstants.DATETIME_PATTERN;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
import java.nio.charset.StandardCharsets;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;

import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletRequest;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.assertj.core.util.Lists;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.mvel2.MVEL;
import org.mvel2.integration.VariableResolverFactory;
import org.mvel2.integration.impl.MapVariableResolverFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.env.Environment;
import org.springframework.core.io.Resource;
import org.springframework.http.MediaType;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.HttpServerErrorException;
import org.springframework.web.client.RestTemplate;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.nimbusds.jose.util.IOUtils;

import io.mosip.kernel.core.exception.ServiceError;
import io.mosip.kernel.core.http.RequestWrapper;
import io.mosip.kernel.core.http.ResponseWrapper;
Expand Down Expand Up @@ -30,55 +81,6 @@
import io.mosip.resident.exception.ResidentServiceException;
import io.mosip.resident.repository.ResidentTransactionRepository;
import io.mosip.resident.service.impl.IdentityServiceImpl;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.assertj.core.util.Lists;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.mvel2.MVEL;
import org.mvel2.integration.VariableResolverFactory;
import org.mvel2.integration.impl.MapVariableResolverFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.env.Environment;
import org.springframework.core.io.Resource;
import org.springframework.http.MediaType;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.HttpServerErrorException;
import org.springframework.web.client.RestTemplate;

import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletRequest;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
import java.nio.charset.StandardCharsets;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;

import static io.mosip.resident.constant.MappingJsonConstants.EMAIL;
import static io.mosip.resident.constant.MappingJsonConstants.PHONE;
import static io.mosip.resident.constant.RegistrationConstants.DATETIME_PATTERN;

/**
* @author Girish Yarru
Expand Down Expand Up @@ -522,16 +524,19 @@ public String getRefIdHash(String individualId) throws NoSuchAlgorithmException
}

private String formatDateTimeForPattern(LocalDateTime localDateTime, String dateTimePattern) {
return localDateTime.format(
DateTimeFormatter.ofPattern(dateTimePattern));
return localDateTime == null ? null : localDateTime.format(DateTimeFormatter.ofPattern(dateTimePattern));
}

public String formatWithOffsetForUI(int timeZoneOffset, LocalDateTime localDateTime) {
return formatDateTimeForPattern(localDateTime.minusMinutes(timeZoneOffset), Objects.requireNonNull(env.getProperty(ResidentConstants.UI_DATE_TIME_PATTERN)));
return formatDateTimeForPattern(applyTimeZoneOffsetOnDateTime(timeZoneOffset, localDateTime), Objects.requireNonNull(env.getProperty(ResidentConstants.UI_DATE_TIME_PATTERN)));
}

public LocalDateTime applyTimeZoneOffsetOnDateTime(int timeZoneOffset, LocalDateTime localDateTime) {
return localDateTime == null ? null : localDateTime.minusMinutes(timeZoneOffset); //Converting UTC to local time zone
}

public String formatWithOffsetForFileName(int timeZoneOffset, LocalDateTime localDateTime) {
return formatDateTimeForPattern(localDateTime.minusMinutes(timeZoneOffset), Objects.requireNonNull(env.getProperty(ResidentConstants.FILENAME_DATETIME_PATTERN)));
return formatDateTimeForPattern(applyTimeZoneOffsetOnDateTime(timeZoneOffset, localDateTime), Objects.requireNonNull(env.getProperty(ResidentConstants.FILENAME_DATETIME_PATTERN)));
}

public String getClientIp(HttpServletRequest req) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -534,8 +534,8 @@ public void testGetUserInfo() throws Exception {
user.setFullName("name");
ResponseWrapper<UserInfoDto> response = new ResponseWrapper<>();
response.setResponse(user);
residentController.userinfo();
Mockito.when(residentService.getUserinfo(Mockito.any())).thenReturn(response);
residentController.userinfo(0);
Mockito.when(residentService.getUserinfo(Mockito.any(), Mockito.anyInt())).thenReturn(response);
this.mockMvc.perform(get("/profile"))
.andExpect(status().isOk());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ public void testGetUserInfo() throws ApisResourceAccessException{
residentUserEntity.setIpAddress("http");
Optional<ResidentUserEntity> response = Optional.of(residentUserEntity);
Mockito.when(residentUserRepository.findById(Mockito.anyString())).thenReturn(response);
ResponseWrapper<UserInfoDto> responseWrapper = residentServiceImpl.getUserinfo("123");
ResponseWrapper<UserInfoDto> responseWrapper = residentServiceImpl.getUserinfo("123", 0);
assertEquals(responseWrapper.getResponse().getFullName(), responseWrapper.getResponse().getFullName());
}

Expand All @@ -204,7 +204,7 @@ public void testGetUserInfoFailed() throws ApisResourceAccessException {
Mockito.when(identityServiceImpl.getClaimFromIdToken(Mockito.anyString())).thenReturn("claim");
Optional<ResidentUserEntity> response = Optional.empty();
Mockito.when(residentUserRepository.findById(Mockito.anyString())).thenReturn(response);
ResponseWrapper<UserInfoDto> responseWrapper = residentServiceImpl.getUserinfo("123");
ResponseWrapper<UserInfoDto> responseWrapper = residentServiceImpl.getUserinfo("123", 0);
assertEquals(responseWrapper.getResponse().getFullName(), responseWrapper.getResponse().getFullName());
}

Expand All @@ -224,7 +224,7 @@ public void testDownloadServiceHistory() throws ResidentServiceCheckedException,
.thenReturn(responseWrapper1);
Mockito.when(templateManager.merge(any(), any())).thenReturn(new ByteArrayInputStream("pdf".getBytes()));
Mockito.when(utility.signPdf(any(), any())).thenReturn("pdf".getBytes(StandardCharsets.UTF_8));
byte[] pdfDocument = residentServiceImpl.downLoadServiceHistory(responseWrapper, "eng",
byte[] pdfDocument = residentServiceImpl.downLoadServiceHistory(responseWrapper, "eng",
LocalDateTime.now(), LocalDate.now(), LocalDate.now(),
String.valueOf(RequestType.DOWNLOAD_PERSONALIZED_CARD), "SUCCESS");
assertNotNull(pdfDocument);
Expand Down