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.web;
35
36 import com.fasterxml.jackson.databind.DeserializationFeature;
37 import com.fasterxml.jackson.databind.ObjectMapper;
38 import com.fasterxml.jackson.databind.SerializationFeature;
39 import fr.paris.lutece.plugins.identitystore.business.duplicates.suspicions.SuspiciousIdentityHome;
40 import fr.paris.lutece.plugins.identitystore.business.identity.Identity;
41 import fr.paris.lutece.plugins.identitystore.business.identity.IdentityAttribute;
42 import fr.paris.lutece.plugins.identitystore.business.identity.IdentityAttributeHome;
43 import fr.paris.lutece.plugins.identitystore.business.identity.IdentityConstants;
44 import fr.paris.lutece.plugins.identitystore.business.identity.IdentityHome;
45 import fr.paris.lutece.plugins.identitystore.service.IdentityManagementResourceIdService;
46 import fr.paris.lutece.plugins.identitystore.service.identity.IdentityService;
47 import fr.paris.lutece.plugins.identitystore.service.search.ISearchIdentityService;
48 import fr.paris.lutece.plugins.identitystore.utils.Batch;
49 import fr.paris.lutece.plugins.identitystore.v3.csv.CsvIdentityService;
50 import fr.paris.lutece.plugins.identitystore.v3.web.rs.DtoConverter;
51 import fr.paris.lutece.plugins.identitystore.v3.web.rs.dto.common.AttributeTreatmentType;
52 import fr.paris.lutece.plugins.identitystore.v3.web.rs.dto.common.BatchDto;
53 import fr.paris.lutece.plugins.identitystore.v3.web.rs.dto.common.IdentityDto;
54 import fr.paris.lutece.plugins.identitystore.v3.web.rs.dto.history.AttributeChange;
55 import fr.paris.lutece.plugins.identitystore.v3.web.rs.dto.history.IdentityChange;
56 import fr.paris.lutece.plugins.identitystore.v3.web.rs.dto.importing.BatchImportRequest;
57 import fr.paris.lutece.plugins.identitystore.v3.web.rs.dto.search.SearchAttribute;
58 import fr.paris.lutece.plugins.identitystore.v3.web.rs.util.Constants;
59 import fr.paris.lutece.plugins.identitystore.web.exception.IdentityStoreException;
60 import fr.paris.lutece.portal.service.admin.AccessDeniedException;
61 import fr.paris.lutece.portal.service.security.AccessLogService;
62 import fr.paris.lutece.portal.service.security.AccessLoggerConstants;
63 import fr.paris.lutece.portal.service.spring.SpringContextService;
64 import fr.paris.lutece.portal.service.util.AppPropertiesService;
65 import fr.paris.lutece.portal.util.mvc.admin.annotations.Controller;
66 import fr.paris.lutece.portal.util.mvc.commons.annotations.Action;
67 import fr.paris.lutece.portal.util.mvc.commons.annotations.View;
68 import fr.paris.lutece.util.http.SecurityUtil;
69 import org.apache.commons.collections.CollectionUtils;
70 import org.apache.commons.collections.MapUtils;
71 import org.apache.commons.lang3.StringUtils;
72
73 import javax.servlet.http.HttpServletRequest;
74 import java.io.ByteArrayOutputStream;
75 import java.sql.Date;
76 import java.sql.Timestamp;
77 import java.time.Instant;
78 import java.time.LocalDate;
79 import java.util.ArrayList;
80 import java.util.Arrays;
81 import java.util.Collections;
82 import java.util.List;
83 import java.util.Map;
84 import java.util.Objects;
85 import java.util.Optional;
86 import java.util.UUID;
87 import java.util.stream.Collectors;
88 import java.util.zip.ZipEntry;
89 import java.util.zip.ZipOutputStream;
90
91
92
93
94 @Controller( controllerJsp = "ManageIdentities.jsp", controllerPath = "jsp/admin/plugins/identitystore/", right = "IDENTITYSTORE_MANAGEMENT" )
95 public class IdentityJspBean extends ManageIdentitiesJspBean
96 {
97
98
99
100 private static final long serialVersionUID = 6053504380426222888L;
101
102 private static final String TEMPLATE_SEARCH_IDENTITIES = "/admin/plugins/identitystore/search_identities.html";
103 private static final String TEMPLATE_VIEW_IDENTITY = "/admin/plugins/identitystore/view_identity.html";
104 private static final String TEMPLATE_VIEW_IDENTITY_HISTORY = "/admin/plugins/identitystore/view_identity_change_history.html";
105
106
107 private static final String PARAMETER_ID_IDENTITY = "id";
108
109
110 private static final String PROPERTY_PAGE_TITLE_MANAGE_IDENTITIES = "identitystore.manage_identities.pageTitle";
111 private static final String PROPERTY_PAGE_TITLE_VIEW_IDENTITY = "identitystore.create_identity.pageTitle";
112 private static final String PROPERTY_PAGE_TITLE_VIEW_CHANGE_HISTORY = "identitystore.view_change_history.pageTitle";
113
114
115 private static final String MARK_IDENTITY_LIST = "identity_list";
116 private static final String MARK_IDENTITY = "identity";
117 private static final String MARK_ATTRIBUTES = "attributes";
118 private static final String MARK_MERGED_IDENTITIES = "merged_identities";
119 private static final String MARK_IDENTITY_IS_SUSPICIOUS = "identity_is_suspicious";
120 private static final String MARK_IDENTITY_CHANGE_LIST = "identity_change_list";
121 private static final String MARK_ATTRIBUTES_CHANGE_LIST = "attributes_change_list";
122 private static final String MARK_HAS_CREATE_ROLE = "createIdentityRole";
123 private static final String MARK_HAS_MODIFY_ROLE = "modifyIdentityRole";
124 private static final String MARK_HAS_DELETE_ROLE = "deleteIdentityRole";
125 private static final String MARK_HAS_VIEW_ROLE = "viewIdentityRole";
126 private static final String MARK_HAS_ATTRIBUTS_HISTO_ROLE = "histoAttributsRole";
127 private static final String JSP_MANAGE_IDENTITIES = "jsp/admin/plugins/identitystore/ManageIdentities.jsp";
128
129
130 private static final String VIEW_MANAGE_IDENTITIES = "manageIdentitys";
131 private static final String VIEW_IDENTITY = "viewIdentity";
132 private static final String VIEW_IDENTITY_HISTORY = "viewIdentityHistory";
133
134
135 private static final String ACTION_EXPORT_IDENTITIES = "exportIdentities";
136 private static final String ACTION_BATCH_GENERATE_REQUESTS = "exportRequestIdentities";
137
138
139 private static final String DISPLAY_IDENTITY_EVENT_CODE = "DISPLAY_IDENTITY";
140 private static final String DISPLAY_IDENTITY_HISTORY_EVENT_CODE = "DISPLAY_HISTORY_IDENTITY";
141
142
143 private static final String DATASOURCE_DB = "db";
144 private static final String DATASOURCE_ES = "es";
145 private static final int BATCH_PARTITION_SIZE = AppPropertiesService.getPropertyInt( "identitystore.export.batch.size", 100 );
146 private static final int PROPERTY_MAX_NB_IDENTITY_RETURNED = AppPropertiesService.getPropertyInt("identitystore.search.maxNbIdentityReturned", 0);
147 private static final String RESOURCE_SEARCH_LINK = AppPropertiesService.getProperty("identitystore.search.resource.link", "");
148
149
150 private Identity _identity;
151
152 private final List<IdentityDto> _identities = new ArrayList<>( );
153
154 private final ISearchIdentityService _searchIdentityServiceDB = SpringContextService.getBean( "identitystore.searchIdentityService.database" );
155 private final ISearchIdentityService _searchIdentityServiceES = SpringContextService.getBean( "identitystore.searchIdentityService.elasticsearch" );
156
157 @View( value = VIEW_MANAGE_IDENTITIES, defaultView = true )
158 public String getManageIdentitys( HttpServletRequest request )
159 {
160 _identity = null;
161 _identities.clear( );
162 final Map<String, String> queryParameters = this.getQueryParameters( request );
163
164 final List<SearchAttribute> atttributes = new ArrayList<>( );
165 final String cuid = queryParameters.get( QUERY_PARAM_CUID );
166 final String guid = queryParameters.get( QUERY_PARAM_GUID );
167 final String insee_city = queryParameters.get( QUERY_PARAM_INSEE_CITY );
168 final String insee_country = queryParameters.get( QUERY_PARAM_INSEE_COUNTRY );
169 final String email = queryParameters.get( QUERY_PARAM_EMAIL );
170 final String gender = queryParameters.get( QUERY_PARAM_GENDER );
171 final String common_name = queryParameters.get(QUERY_PARAM_COMMON_LASTNAME);
172 final String first_name = queryParameters.get( QUERY_PARAM_FIRST_NAME );
173 final String birthdate = queryParameters.get( QUERY_PARAM_BIRTHDATE );
174 final String birthplace = queryParameters.get( QUERY_PARAM_INSEE_BIRTHPLACE_LABEL );
175 final String birthcountry = queryParameters.get( QUERY_PARAM_INSEE_BIRTHCOUNTRY_LABEL );
176 final String phone = queryParameters.get( QUERY_PARAM_PHONE );
177 final String datasource = Optional.ofNullable( queryParameters.get( QUERY_PARAM_DATASOURCE ) ).orElse( DATASOURCE_DB );
178
179 try
180 {
181 if ( StringUtils.isNotEmpty( cuid ) )
182 {
183 if ( datasource.equals( DATASOURCE_DB ) )
184 {
185 final Identity identity = IdentityHome.findMasterIdentityByCustomerId( cuid );
186 if ( identity != null )
187 {
188 final IdentityDto qualifiedIdentity = DtoConverter.convertIdentityToDto( identity );
189 _identities.add( qualifiedIdentity );
190 }
191 }
192 else
193 if ( datasource.equals( DATASOURCE_ES ) )
194 {
195 _identities.addAll( _searchIdentityServiceES.getQualifiedIdentities( cuid, Collections.emptyList() )
196 .getQualifiedIdentities( ) );
197 }
198 }
199 else
200 {
201 if ( StringUtils.isNotEmpty( guid ) )
202 {
203 if ( datasource.equals( DATASOURCE_DB ) )
204 {
205 final Identity identity = IdentityHome.findMasterIdentityByConnectionId( guid );
206 if ( identity != null )
207 {
208 final IdentityDto qualifiedIdentity = DtoConverter.convertIdentityToDto( identity );
209 _identities.add( qualifiedIdentity );
210 }
211 }
212 else
213 if ( datasource.equals( DATASOURCE_ES ) )
214 {
215 _identities.addAll( _searchIdentityServiceES.getQualifiedIdentitiesByConnectionId( guid, Collections.emptyList() )
216 .getQualifiedIdentities( ) );
217 }
218 }
219 else
220 {
221 if ( StringUtils.isNotEmpty( insee_city ) )
222 {
223 atttributes.add( new SearchAttribute( Constants.PARAM_BIRTH_PLACE_CODE, insee_city, AttributeTreatmentType.STRICT ) );
224 }
225 if ( StringUtils.isNotEmpty( insee_country ) )
226 {
227 atttributes.add( new SearchAttribute( Constants.PARAM_BIRTH_COUNTRY_CODE, insee_country, AttributeTreatmentType.STRICT ) );
228 }
229 if ( StringUtils.isNotEmpty( email ) )
230 {
231 atttributes.add( new SearchAttribute( Constants.PARAM_COMMON_EMAIL, email, AttributeTreatmentType.STRICT ) );
232 }
233 if ( StringUtils.isNotEmpty( gender ) )
234 {
235 atttributes.add( new SearchAttribute( Constants.PARAM_GENDER, gender, AttributeTreatmentType.STRICT ) );
236 }
237 if ( StringUtils.isNotEmpty( common_name ) )
238 {
239 atttributes.add( new SearchAttribute( Constants.PARAM_COMMON_LASTNAME, common_name, AttributeTreatmentType.APPROXIMATED ) );
240 }
241 if ( StringUtils.isNotEmpty( first_name ) )
242 {
243 atttributes.add( new SearchAttribute( Constants.PARAM_FIRST_NAME, first_name, AttributeTreatmentType.APPROXIMATED ) );
244 }
245 if ( StringUtils.isNotEmpty( birthdate ) )
246 {
247 atttributes.add( new SearchAttribute( Constants.PARAM_BIRTH_DATE, birthdate, AttributeTreatmentType.STRICT ) );
248 }
249 if ( StringUtils.isNotEmpty( birthplace ) )
250 {
251 atttributes.add( new SearchAttribute( Constants.PARAM_BIRTH_PLACE, birthplace, AttributeTreatmentType.APPROXIMATED ) );
252 }
253 if ( StringUtils.isNotEmpty( birthcountry ) )
254 {
255 atttributes.add( new SearchAttribute( Constants.PARAM_BIRTH_COUNTRY, birthcountry, AttributeTreatmentType.APPROXIMATED ) );
256 }
257 if ( StringUtils.isNotEmpty( phone ) )
258 {
259 atttributes.add( new SearchAttribute( Constants.PARAM_COMMON_PHONE, phone, AttributeTreatmentType.STRICT ) );
260 }
261 if ( CollectionUtils.isNotEmpty( atttributes ) )
262 {
263 if ( datasource.equals( DATASOURCE_DB ) )
264 {
265 _identities.addAll( _searchIdentityServiceDB.getQualifiedIdentities( atttributes, PROPERTY_MAX_NB_IDENTITY_RETURNED, false, Collections.emptyList( ) )
266 .getQualifiedIdentities( ) );
267 }
268 else
269 if ( datasource.equals( DATASOURCE_ES ) )
270 {
271 _identities.addAll( _searchIdentityServiceES.getQualifiedIdentities( atttributes, PROPERTY_MAX_NB_IDENTITY_RETURNED, false, Collections.emptyList( ) )
272 .getQualifiedIdentities( ) );
273 }
274 }
275 }
276 }
277 }
278 catch( Exception e )
279 {
280 addError( e.getMessage( ) );
281 this.clearParameters( request );
282 return redirectView( request, VIEW_MANAGE_IDENTITIES );
283 }
284
285 _identities.forEach(
286 qualifiedIdentity -> AccessLogService.getInstance( ).info( AccessLoggerConstants.EVENT_TYPE_READ, IdentityService.SEARCH_IDENTITY_EVENT_CODE,
287 getUser( ), SecurityUtil.logForgingProtect( qualifiedIdentity.getCustomerId( ) ), IdentityService.SPECIFIC_ORIGIN ) );
288
289 final Map<String, Object> model = getPaginatedListModel( request, MARK_IDENTITY_LIST, _identities, JSP_MANAGE_IDENTITIES );
290 model.put( MARK_HAS_CREATE_ROLE,
291 IdentityManagementResourceIdService.isAuthorized( IdentityManagementResourceIdService.PERMISSION_CREATE_IDENTITY, getUser( ) ) );
292 model.put( MARK_HAS_MODIFY_ROLE,
293 IdentityManagementResourceIdService.isAuthorized( IdentityManagementResourceIdService.PERMISSION_MODIFY_IDENTITY, getUser( ) ) );
294 model.put( MARK_HAS_DELETE_ROLE,
295 IdentityManagementResourceIdService.isAuthorized( IdentityManagementResourceIdService.PERMISSION_DELETE_IDENTITY, getUser( ) ) );
296 model.put( MARK_HAS_VIEW_ROLE,
297 IdentityManagementResourceIdService.isAuthorized( IdentityManagementResourceIdService.PERMISSION_VIEW_IDENTITY, getUser( ) ) );
298
299 model.put( QUERY_PARAM_CUID, cuid );
300 model.put( QUERY_PARAM_GUID, guid );
301 model.put( QUERY_PARAM_INSEE_CITY, insee_city );
302 model.put( QUERY_PARAM_INSEE_COUNTRY, insee_country );
303 model.put( QUERY_PARAM_COMMON_LASTNAME, common_name );
304 model.put( QUERY_PARAM_FIRST_NAME, first_name );
305 model.put( QUERY_PARAM_EMAIL, email );
306 model.put( QUERY_PARAM_INSEE_BIRTHPLACE_LABEL, birthplace );
307 model.put( QUERY_PARAM_INSEE_BIRTHCOUNTRY_LABEL, birthcountry );
308 model.put( QUERY_PARAM_PHONE, phone );
309 model.put( QUERY_PARAM_BIRTHDATE, birthdate );
310 model.put( QUERY_PARAM_GENDER, gender );
311 model.put( QUERY_PARAM_DATASOURCE, datasource );
312
313 return getPage( PROPERTY_PAGE_TITLE_MANAGE_IDENTITIES, TEMPLATE_SEARCH_IDENTITIES, model );
314 }
315
316
317
318
319
320
321
322
323 @View( VIEW_IDENTITY )
324 public String getViewIdentity( HttpServletRequest request )
325 {
326 final String nId = request.getParameter( PARAMETER_ID_IDENTITY );
327
328 _identity = IdentityHome.findByCustomerId( nId );
329
330 List<Identity> mergedIdentities = IdentityHome.findMergedIdentities(_identity.getId());
331 _identity.setMerged(mergedIdentities != null && !mergedIdentities.isEmpty());
332
333 final String filteredCustomerId = SecurityUtil.logForgingProtect( _identity.getCustomerId( ) );
334 AccessLogService.getInstance( ).info( AccessLoggerConstants.EVENT_TYPE_READ, DISPLAY_IDENTITY_EVENT_CODE, getUser( ), filteredCustomerId,
335 IdentityService.SPECIFIC_ORIGIN );
336
337 List<IdentityAttribute> attributes = sortIdentityttributes( );
338
339 final Map<String, Object> model = getModel( );
340 model.put( MARK_IDENTITY, _identity );
341 model.put( MARK_ATTRIBUTES, attributes );
342 model.put( MARK_MERGED_IDENTITIES, mergedIdentities );
343 model.put( MARK_IDENTITY_IS_SUSPICIOUS, SuspiciousIdentityHome.hasSuspicious( Collections.singletonList( _identity.getCustomerId( ) ) ) );
344 model.put( MARK_HAS_ATTRIBUTS_HISTO_ROLE,
345 IdentityManagementResourceIdService.isAuthorized( IdentityManagementResourceIdService.PERMISSION_ATTRIBUTS_HISTO, getUser( ) ) );
346 model.put( QUERY_PARAM_CUID_LINK, RESOURCE_SEARCH_LINK );
347
348 return getPage( PROPERTY_PAGE_TITLE_VIEW_IDENTITY, TEMPLATE_VIEW_IDENTITY, model );
349 }
350
351
352
353
354
355
356
357
358 @View( value = VIEW_IDENTITY_HISTORY )
359 public String getIdentityHistoryView( HttpServletRequest request )
360 {
361
362 final List<AttributeChange> attributeChangeList = new ArrayList<>( );
363 final List<IdentityChange> identityChangeList = new ArrayList<>( );
364
365 if ( _identity != null && MapUtils.isNotEmpty( _identity.getAttributes( ) ) )
366 {
367 try
368 {
369 attributeChangeList.addAll( IdentityAttributeHome.getAttributeChangeHistory( _identity.getId( ) ) );
370 identityChangeList.addAll( IdentityHome.findHistoryByCustomerId( _identity.getCustomerId( ) ) );
371 }
372 catch( IdentityStoreException e )
373 {
374 addError( e.getMessage( ) );
375 return getViewIdentity( request );
376 }
377 }
378 if ( _identity != null )
379 {
380 final String filteredCustomerId = SecurityUtil.logForgingProtect( _identity.getCustomerId( ) );
381 AccessLogService.getInstance( ).info( AccessLoggerConstants.EVENT_TYPE_READ, DISPLAY_IDENTITY_HISTORY_EVENT_CODE, getUser( ), filteredCustomerId,
382 IdentityService.SPECIFIC_ORIGIN );
383 }
384
385 final Map<String, Object> model = getModel( );
386 model.put( MARK_IDENTITY_CHANGE_LIST, identityChangeList );
387 model.put( MARK_ATTRIBUTES_CHANGE_LIST, attributeChangeList );
388
389 return getPage( PROPERTY_PAGE_TITLE_VIEW_CHANGE_HISTORY, TEMPLATE_VIEW_IDENTITY_HISTORY, model );
390 }
391
392
393
394
395
396
397
398
399
400 @Action( ACTION_EXPORT_IDENTITIES )
401 public void doExportIdentities( HttpServletRequest request )
402 {
403 try
404 {
405 final List<IdentityDto> identitiesToProcess = _identities.stream( ).filter( this::validateMinimumAttributes )
406 .peek( identityDto -> identityDto.setExternalCustomerId( UUID.randomUUID( ).toString( ) ) ).collect( Collectors.toList( ) );
407 final Batch<IdentityDto> batches = Batch.ofSize( identitiesToProcess, BATCH_PARTITION_SIZE );
408
409 final ByteArrayOutputStream outputStream = new ByteArrayOutputStream( );
410 final ZipOutputStream zipOut = new ZipOutputStream( outputStream );
411
412 int i = 0;
413 for ( final List<IdentityDto> batch : batches )
414 {
415 final byte [ ] bytes = CsvIdentityService.instance( ).write( batch );
416 final ZipEntry zipEntry = new ZipEntry( "identities-" + ++i + ".csv" );
417 zipEntry.setSize( bytes.length );
418 zipOut.putNextEntry( zipEntry );
419 zipOut.write( bytes );
420 }
421 zipOut.closeEntry( );
422 zipOut.close( );
423 this.download( outputStream.toByteArray( ), "identities.zip", "application/zip" );
424 }
425 catch( Exception e )
426 {
427 addError( e.getMessage( ) );
428 redirectView( request, VIEW_MANAGE_IDENTITIES );
429 }
430 }
431
432 private boolean validateMinimumAttributes( final IdentityDto identity )
433 {
434 return this.checkAttributeExists( identity, Constants.PARAM_FAMILY_NAME ) && this.checkAttributeExists( identity, Constants.PARAM_FIRST_NAME )
435 && this.checkAttributeExists( identity, Constants.PARAM_BIRTH_DATE );
436 }
437
438 private boolean checkAttributeExists( final IdentityDto identity, final String attributeKey )
439 {
440 return identity.getAttributes( ).stream( )
441 .anyMatch( attributeDto -> Objects.equals( attributeDto.getKey( ), attributeKey ) && StringUtils.isNotBlank( attributeDto.getValue( ) ) );
442 }
443
444
445
446
447
448
449
450
451
452 @Action( ACTION_BATCH_GENERATE_REQUESTS )
453 public void doGenerateBatchIdentities( HttpServletRequest request )
454 {
455 try
456 {
457
458 _identities.forEach( identityDto -> {
459 identityDto.setExternalCustomerId( UUID.randomUUID( ).toString( ) );
460 identityDto.setCustomerId( null );
461 identityDto.setQuality( null );
462 identityDto.setExpiration( null );
463 identityDto.setMerge( null );
464 identityDto.setLastUpdateDate( null );
465 identityDto.setConnectionId( null );
466 identityDto.setMonParisActive( null );
467 identityDto.setCreationDate( null );
468 identityDto.setDuplicateDefinition( null );
469 identityDto.setSuspicious( null );
470 } );
471 final Batch<IdentityDto> batches = Batch.ofSize( _identities, BATCH_PARTITION_SIZE );
472
473 final ByteArrayOutputStream outputStream = new ByteArrayOutputStream( );
474 final ZipOutputStream zipOut = new ZipOutputStream( outputStream );
475
476 int i = 0;
477 final String reference = UUID.randomUUID( ).toString( );
478
479 final ObjectMapper mapper = new ObjectMapper( );
480 mapper.enable( SerializationFeature.INDENT_OUTPUT );
481 mapper.disable( DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES );
482
483 for ( final List<IdentityDto> batch : batches )
484 {
485 final BatchImportRequest batchImportRequest = new BatchImportRequest( );
486 batchImportRequest.setBatch( new BatchDto( ) );
487 batchImportRequest.getBatch( ).setReference( reference );
488 batchImportRequest.getBatch( ).setComment( "Batch exporté depuis identity store" );
489 batchImportRequest.getBatch( ).setCreationDate( Timestamp.from( Instant.now( ) ) );
490 batchImportRequest.getBatch( ).setUser( getUser( ).getEmail( ) );
491 batchImportRequest.getBatch( ).setAppCode( "TEST" );
492 batchImportRequest.getBatch( ).setIdentities( batch );
493 final ZipEntry zipEntry = new ZipEntry( "identities-" + ++i + ".json" );
494 final byte [ ] bytes = mapper.writeValueAsBytes( batchImportRequest );
495 zipEntry.setSize( bytes.length );
496 zipOut.putNextEntry( zipEntry );
497 zipOut.write( bytes );
498 }
499 zipOut.closeEntry( );
500 zipOut.close( );
501 this.download( outputStream.toByteArray( ), "identity_requests.zip", "application/zip" );
502 }
503 catch( Exception e )
504 {
505 addError( e.getMessage( ) );
506 redirectView( request, VIEW_MANAGE_IDENTITIES );
507 }
508 }
509
510 private List<IdentityAttribute> sortIdentityttributes( )
511 {
512 if ( _identity != null )
513 {
514 final List<String> _sortedAttributeKeyList = Arrays.asList( AppPropertiesService.getProperty(IdentityConstants.PROPERTY_IDENTITY_ATTRIBUTE_ORDER, "" ).split( "," ) );
515 List<IdentityAttribute> valueList = new ArrayList<>(_identity.getAttributes( ).values());
516 valueList.sort( ( a1, a2 ) -> {
517 final int index1 = _sortedAttributeKeyList.indexOf( a1.getAttributeKey( ).getKeyName() );
518 final int index2 = _sortedAttributeKeyList.indexOf( a2.getAttributeKey( ).getKeyName() );
519 final int i1 = index1 == -1 ? 999 : index1;
520 final int i2 = index2 == -1 ? 999 : index2;
521 if ( i1 == i2 )
522 {
523 return a1.getAttributeKey( ).getKeyName().compareTo( a2.getAttributeKey( ).getKeyName() );
524 }
525 return Integer.compare( i1, i2 );
526 } );
527 return valueList;
528 }
529 return null;
530 }
531 }