1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 package fr.paris.lutece.plugins.identitystore.service;
35
36 import static fr.paris.lutece.plugins.identitystore.service.identity.IdentityService.UPDATE_IDENTITY_EVENT_CODE;
37
38 import java.sql.Date;
39 import java.sql.Timestamp;
40 import java.time.Instant;
41 import java.time.ZoneId;
42 import java.time.ZonedDateTime;
43 import java.util.ArrayList;
44 import java.util.Collections;
45 import java.util.List;
46
47 import org.apache.commons.lang3.StringUtils;
48
49 import fr.paris.lutece.plugins.grubusiness.business.demand.DemandType;
50 import fr.paris.lutece.plugins.grubusiness.business.web.rs.DemandDisplay;
51 import fr.paris.lutece.plugins.grubusiness.business.web.rs.DemandResult;
52 import fr.paris.lutece.plugins.grubusiness.business.web.rs.EnumGenericStatus;
53 import fr.paris.lutece.plugins.identitystore.business.contract.ServiceContract;
54 import fr.paris.lutece.plugins.identitystore.business.identity.Identity;
55 import fr.paris.lutece.plugins.identitystore.business.identity.IdentityHome;
56 import fr.paris.lutece.plugins.identitystore.service.contract.ServiceContractService;
57 import fr.paris.lutece.plugins.identitystore.service.identity.IdentityService;
58 import fr.paris.lutece.plugins.identitystore.service.listeners.IdentityStoreNotifyListenerService;
59 import fr.paris.lutece.plugins.identitystore.service.user.InternalUserService;
60 import fr.paris.lutece.plugins.identitystore.v3.web.rs.dto.common.RequestAuthor;
61 import fr.paris.lutece.plugins.identitystore.v3.web.rs.dto.history.IdentityChangeType;
62 import fr.paris.lutece.plugins.notificationstore.v1.web.service.NotificationStoreService;
63 import fr.paris.lutece.portal.service.security.AccessLogService;
64 import fr.paris.lutece.portal.service.security.AccessLoggerConstants;
65 import fr.paris.lutece.portal.service.spring.SpringContextService;
66 import fr.paris.lutece.portal.service.util.AppLogService;
67 import fr.paris.lutece.portal.service.util.AppPropertiesService;
68
69 public final class PurgeIdentityService
70 {
71 private static PurgeIdentityService _instance;
72
73 private final NotificationStoreService _notificationStoreService = SpringContextService.getBean( "notificationStore.notificationStoreService" );
74
75 public static PurgeIdentityService getInstance( )
76 {
77 if ( _instance == null )
78 {
79 _instance = new PurgeIdentityService( );
80 }
81 return _instance;
82 }
83
84
85
86
87
88
89 public String purge( final RequestAuthor daemonAuthor, final String daemonClientCode, final List<String> excludedAppCodes, final int batchLimit )
90 {
91 final StringBuilder msg = new StringBuilder( );
92
93
94 final List<Identity> expiredIdentities = IdentityHome.findExpiredNotMergedAndNotConnectedIdentities(
95 batchLimit, AppPropertiesService.getPropertyBoolean ( "daemon.purgeIdentityDaemon.withGuidOnly", true) );
96 final Timestamp now = Timestamp.from( Instant.now( ) );
97
98 msg.append( expiredIdentities.size( ) ).append( " expired identities found" ).append( "\n" );
99
100 for ( final Identity expiredIdentity : expiredIdentities )
101 {
102 try
103 {
104 final List<Identity> mergedIdentities = IdentityHome.findMergedIdentities( expiredIdentity.getId( ) );
105
106
107 DemandResult demandResult = _notificationStoreService.getListDemand( expiredIdentity.getCustomerId( ), null, null, null, null );
108 final List<DemandDisplay> demandDisplayList = demandResult.getListDemandDisplay() == null ? new ArrayList<>() : new ArrayList<>(demandResult.getListDemandDisplay());
109 for ( final Identity mergedIdentity : mergedIdentities )
110 {
111 demandDisplayList
112 .addAll( _notificationStoreService.getListDemand( mergedIdentity.getCustomerId( ), null, null, null, null ).getListDemandDisplay( ) );
113 }
114
115 boolean isAtLeastOneServiceContractFound = false;
116 boolean isInfosAreMissing = false;
117
118
119 Timestamp demandExpirationDateMAX = expiredIdentity.getExpirationDate( );
120 for ( final DemandDisplay demand : demandDisplayList )
121 {
122
123 if (demand.getDemand().getStatusId() == EnumGenericStatus.CANCELED.getStatusId()) {
124 continue;
125 }
126
127 final String appCode = getAppCodeFromDemandTypeId( demand.getDemand( ).getTypeId( ) );
128 if ( appCode == null )
129 {
130 msg.append( "Unknown AppCode for demand_type_id : ")
131 .append ( (demand.getDemand( ).getTypeId( )!=null?demand.getDemand( ).getTypeId( ):"") )
132 .append ( "\n" );
133 AppLogService.info( "IdentityPurgDaemon / Unknown AppCode for demand_type_id : "
134 + (demand.getDemand( ).getTypeId( )!=null?demand.getDemand( ).getTypeId( ):"") );
135
136 isInfosAreMissing = true;
137 }
138
139 if ( !excludedAppCodes.contains( appCode ) )
140 {
141 final List<String> clientCodeList = ServiceContractService.instance( ).getClientCodesFromAppCode( appCode );
142
143 int nbMonthsCGUsMAX = 0;
144 for ( final String clientCode : clientCodeList )
145 {
146
147 Timestamp tscreate = new Timestamp( demand.getDemand( ).getCreationDate( ) );
148 Date demandCreationDate = Date.valueOf( tscreate.toLocalDateTime( ).toLocalDate( ) );
149
150 ServiceContract sc = ServiceContractService.instance( ).getActiveServiceContractAtSpecificDate( clientCode, demandCreationDate );
151 if ( sc == null )
152 {
153 sc = ServiceContractService.instance( ).getActiveServiceContract( clientCode );
154 }
155
156 if ( sc != null )
157 {
158 isAtLeastOneServiceContractFound = true;
159 if ( sc.getDataRetentionPeriodInMonths( ) > nbMonthsCGUsMAX )
160 {
161 nbMonthsCGUsMAX = sc.getDataRetentionPeriodInMonths( );
162 }
163 }
164 else
165 {
166 isInfosAreMissing = true;
167 }
168 }
169
170 final ZonedDateTime demandDate = ZonedDateTime.ofInstant( Instant.ofEpochMilli( demand.getDemand( ).getModifyDate( ) ),
171 ZoneId.systemDefault( ) );
172 final Timestamp expirationDateFromDemand = Timestamp.from( demandDate.plusMonths( nbMonthsCGUsMAX ).toInstant( ) );
173
174
175 if ( demandExpirationDateMAX.before( expirationDateFromDemand ) )
176 {
177 demandExpirationDateMAX = expirationDateFromDemand;
178 }
179 }
180 }
181
182 if ( !isAtLeastOneServiceContractFound )
183 {
184 msg.append ( "No service contact found for identity [").append( expiredIdentity.getCustomerId( ) ).append ( "]\n");
185
186 continue;
187 }
188
189
190 if ( demandExpirationDateMAX.after( now ) )
191 {
192
193
194 expiredIdentity.setExpirationDate( demandExpirationDateMAX );
195 IdentityHome.update( expiredIdentity );
196
197
198 IdentityStoreNotifyListenerService.instance( ).notifyListenersIdentityChange( IdentityChangeType.UPDATE, expiredIdentity,
199 "EXPIRATION_POSTPONED", StringUtils.EMPTY, daemonAuthor, daemonClientCode, Collections.emptyMap( ) );
200 AccessLogService.getInstance( ).info( AccessLoggerConstants.EVENT_TYPE_MODIFY, UPDATE_IDENTITY_EVENT_CODE,
201 InternalUserService.getInstance( ).getApiUser( daemonAuthor, daemonClientCode ), null, "PURGE_DAEMON" );
202
203 msg.append( "Identity expiration date updated : [" ).append( expiredIdentity.getCustomerId( ) ).append( "]" ).append( "\n" );
204 }
205 else if ( isInfosAreMissing )
206 {
207
208 msg.append( "Unsufficient infos to delete [" ).append( expiredIdentity.getCustomerId( ) ).append( "]" ).append( "\n" );
209 }
210 else
211 {
212
213
214 IdentityService.instance( ).delete( expiredIdentity.getCustomerId( ) );
215 msg.append( "Detete Identity [" ).append( expiredIdentity.getCustomerId( ) ).append( "]" ).append( "\n" );
216
217
218 _notificationStoreService.deleteNotificationByCuid( expiredIdentity.getCustomerId( ) );
219 msg.append( "Notifications deleted for main identity [" ).append( expiredIdentity.getCustomerId( ) ).append( "]" ).append( "\n" );
220 for ( final Identity mergedIdentity : mergedIdentities )
221 {
222 _notificationStoreService.deleteNotificationByCuid( mergedIdentity.getCustomerId( ) );
223 msg.append( "Notifications deleted for merged identity [" ).append( mergedIdentity.getCustomerId( ) ).append( "]" ).append( "\n" );
224 }
225 }
226 }
227 catch( final Exception e )
228 {
229 msg.append( "Daemon execution error for identity : " ).append( expiredIdentity.getCustomerId( ) ).append( " :: " ).append( e.getMessage( ) )
230 .append( "\n" );
231 return msg.toString( );
232 }
233 }
234
235
236 return msg.toString( );
237 }
238
239
240
241
242
243
244
245
246 private String getAppCodeFromDemandTypeId( final String strTypeId )
247 {
248 DemandType demandType = _notificationStoreService.getDemandType( strTypeId );
249
250 if ( demandType != null )
251 {
252 return demandType.getAppCode( );
253 }
254
255 return null;
256 }
257
258 }