From f452a65da7332ffedc6642446b47fa6b2584484b Mon Sep 17 00:00:00 2001
From: Makhtar DIAGNE <mamakh@users.noreply.github.com>
Date: Tue, 3 Nov 2020 08:40:04 +0000
Subject: [PATCH] =?UTF-8?q?Ajout=20de=20la=20propri=C3=A9t=C3=A9=20siteCod?=
 =?UTF-8?q?e=20=C3=A0=20l'utilisateur=20(#55)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* [FENIX-58] add siteCode to user

* [FENIX-58] add static constant for sitecode

* [FENIX-58] remove println

* [FENIX-58] add siteCode to user creation & update

* [FENIX-58] add a script to init user's siteCode with an empty string if the property does not exist

* [FENIX-86] add siteCode to allowed keys

Co-authored-by: Mounir Nayab <mounir.nayab@xelians.fr>
---
 .../server/service/UserExternalService.java       |  2 +-
 .../server/user/converter/UserConverter.java      |  3 +++
 .../iam/internal/server/user/domain/User.java     |  2 ++
 .../server/user/service/UserInternalService.java  |  4 ++++
 .../service/UserInternalServiceIntegTest.java     |  8 +++++++-
 .../cas/authentication/UserPrincipalResolver.java |  2 ++
 .../gouv/vitamui/commons/api/CommonConstants.java |  2 ++
 .../gouv/vitamui/commons/api/domain/UserDto.java  |  2 ++
 .../commons/security/client/dto/AuthUserDto.java  |  5 +++++
 .../1.0.0/FENIX-58_init_user_sitecode_ref.js      | 15 +++++++++++++++
 .../modules/models/user/auth-user.interface.ts    |  2 +-
 .../src/app/modules/models/user/user.interface.ts |  1 +
 .../user/user-create/user-create.component.html   |  6 ++++++
 .../user/user-create/user-create.component.scss   |  5 +++++
 .../app/user/user-create/user-create.component.ts |  3 ++-
 .../user-information-tab.component.html           |  8 ++++++++
 .../user-information-tab.component.spec.ts        |  6 ++++--
 .../user-information-tab.component.ts             |  6 ++++--
 18 files changed, 74 insertions(+), 8 deletions(-)
 create mode 100644 deployment/scripts/mongod/1.0.0/FENIX-58_init_user_sitecode_ref.js

diff --git a/api/api-iam/iam-external/src/main/java/fr/gouv/vitamui/iam/external/server/service/UserExternalService.java b/api/api-iam/iam-external/src/main/java/fr/gouv/vitamui/iam/external/server/service/UserExternalService.java
index a0983548..ad3ac7b9 100644
--- a/api/api-iam/iam-external/src/main/java/fr/gouv/vitamui/iam/external/server/service/UserExternalService.java
+++ b/api/api-iam/iam-external/src/main/java/fr/gouv/vitamui/iam/external/server/service/UserExternalService.java
@@ -182,7 +182,7 @@ public class UserExternalService extends AbstractResourceClientService<UserDto,
     @Override
     protected Collection<String> getAllowedKeys() {
         return Arrays.asList("id", "lastname", "firstname", "identifier", "groupId", "language", "email", "otp",
-                "subrogeable", "phone", "mobile", "lastConnection", "status", "level", TYPE_KEY, CUSTOMER_ID_KEY);
+                "subrogeable", "phone", "mobile", "lastConnection", "status", "level", TYPE_KEY, CUSTOMER_ID_KEY, "siteCode");
     }
 
     @Override
diff --git a/api/api-iam/iam-internal/src/main/java/fr/gouv/vitamui/iam/internal/server/user/converter/UserConverter.java b/api/api-iam/iam-internal/src/main/java/fr/gouv/vitamui/iam/internal/server/user/converter/UserConverter.java
index 191062d3..ba8efc20 100644
--- a/api/api-iam/iam-internal/src/main/java/fr/gouv/vitamui/iam/internal/server/user/converter/UserConverter.java
+++ b/api/api-iam/iam-internal/src/main/java/fr/gouv/vitamui/iam/internal/server/user/converter/UserConverter.java
@@ -89,6 +89,8 @@ public class UserConverter implements Converter<UserDto, User> {
      */
     public static final String BLOCKED_DURATION = "Durée du blocage";
 
+    public static final String SITE_CODE = "Code du site";
+
     private final GroupRepository groupRepository;
 
     private final AddressConverter addressConverter;
@@ -111,6 +113,7 @@ public class UserConverter implements Converter<UserDto, User> {
         userLogbookData.put(STATUS_KEY, LogbookUtils.getValue(user.getStatus().toString()));
         userLogbookData.put(SUBROGEABLE_KEY, LogbookUtils.getValue(user.isSubrogeable()));
         userLogbookData.put(OTP_KEY, LogbookUtils.getValue(user.isOtp()));
+        userLogbookData.put(SITE_CODE, LogbookUtils.getValue(user.getSiteCode()));
         AddressDto address = user.getAddress() != null ? user.getAddress() : new AddressDto();
         addressConverter.addAddress(address, userLogbookData);
         Optional<Group> group = groupRepository.findById(user.getGroupId());
diff --git a/api/api-iam/iam-internal/src/main/java/fr/gouv/vitamui/iam/internal/server/user/domain/User.java b/api/api-iam/iam-internal/src/main/java/fr/gouv/vitamui/iam/internal/server/user/domain/User.java
index 34aa7718..a4a6c036 100644
--- a/api/api-iam/iam-internal/src/main/java/fr/gouv/vitamui/iam/internal/server/user/domain/User.java
+++ b/api/api-iam/iam-internal/src/main/java/fr/gouv/vitamui/iam/internal/server/user/domain/User.java
@@ -129,4 +129,6 @@ public class User extends CustomerIdDocument implements BaseIdentifierDocument {
     private OffsetDateTime passwordExpirationDate;
 
     private Address address = new Address();
+
+    private String siteCode;
 }
diff --git a/api/api-iam/iam-internal/src/main/java/fr/gouv/vitamui/iam/internal/server/user/service/UserInternalService.java b/api/api-iam/iam-internal/src/main/java/fr/gouv/vitamui/iam/internal/server/user/service/UserInternalService.java
index 47d4be61..8c3cdee1 100644
--- a/api/api-iam/iam-internal/src/main/java/fr/gouv/vitamui/iam/internal/server/user/service/UserInternalService.java
+++ b/api/api-iam/iam-internal/src/main/java/fr/gouv/vitamui/iam/internal/server/user/service/UserInternalService.java
@@ -559,6 +559,10 @@ public class UserInternalService extends VitamUICrudService<UserDto, User> {
                     }
                     addressService.processPatch(user.getAddress(), CastUtils.toMap(entry.getValue()), logbooks);
                     break;
+                case "siteCode" :
+                    logbooks.add(new EventDiffDto(UserConverter.SITE_CODE, user.getSiteCode(), entry.getValue()));
+                    user.setSiteCode(CastUtils.toString(entry.getValue()));
+                    break;
                 default :
                     throw new IllegalArgumentException("Unable to patch group " + user.getId() + ": key " + entry.getKey() + " is not allowed");
             }
diff --git a/api/api-iam/iam-internal/src/test/java/fr/gouv/vitamui/iam/internal/server/user/service/UserInternalServiceIntegTest.java b/api/api-iam/iam-internal/src/test/java/fr/gouv/vitamui/iam/internal/server/user/service/UserInternalServiceIntegTest.java
index 28723d6e..8168f89b 100644
--- a/api/api-iam/iam-internal/src/test/java/fr/gouv/vitamui/iam/internal/server/user/service/UserInternalServiceIntegTest.java
+++ b/api/api-iam/iam-internal/src/test/java/fr/gouv/vitamui/iam/internal/server/user/service/UserInternalServiceIntegTest.java
@@ -307,6 +307,7 @@ public final class UserInternalServiceIntegTest extends AbstractLogbookIntegrati
         final GroupDto group = new GroupDto();
         group.setEnabled(true);
         group.setCustomerId(customerId);
+        user.setSiteCode("001");
         Mockito.when(customerRepository.findById(any())).thenReturn(Optional.of(customer));
         Mockito.when(groupInternalService.getOne(any(), any(), any())).thenReturn(group);
         Mockito.when(internalSecurityService.isLevelAllowed(any())).thenReturn(true);
@@ -338,6 +339,7 @@ public final class UserInternalServiceIntegTest extends AbstractLogbookIntegrati
                 + "\"Statut\":\"ENABLED\","
                 + "\"Subrogeable\":\"false\","
                 + "\"OTP\":\"true\","
+                + "\"Code du site\":\"001\","
                 + "\"Nom de la rue\":\"rue faubourg poissoniére\","
                 + "\"Code postal\":\"75009\","
                 + "\"Ville\":\"paris\","
@@ -400,9 +402,13 @@ public final class UserInternalServiceIntegTest extends AbstractLogbookIntegrati
         internalUserService.patch(partialDto);
         partialDto.remove("otp");
 
+        partialDto.put("siteCode", "001");
+        internalUserService.patch(partialDto);
+        partialDto.remove("siteCode");
+
         final Collection<Event> events = eventRepository
                 .findAll(Query.query(Criteria.where("obId").is(user.getIdentifier()).and("evType").is(EventType.EXT_VITAMUI_UPDATE_USER)));
-        assertThat(events).hasSize(11);
+        assertThat(events).hasSize(12);
 
     }
 
diff --git a/cas/cas-server/src/main/java/fr/gouv/vitamui/cas/authentication/UserPrincipalResolver.java b/cas/cas-server/src/main/java/fr/gouv/vitamui/cas/authentication/UserPrincipalResolver.java
index 2d164516..fb4a093a 100644
--- a/cas/cas-server/src/main/java/fr/gouv/vitamui/cas/authentication/UserPrincipalResolver.java
+++ b/cas/cas-server/src/main/java/fr/gouv/vitamui/cas/authentication/UserPrincipalResolver.java
@@ -66,6 +66,7 @@ import static fr.gouv.vitamui.commons.api.CommonConstants.SUPER_USER_ATTRIBUTE;
 import static fr.gouv.vitamui.commons.api.CommonConstants.SUPER_USER_IDENTIFIER_ATTRIBUTE;
 import static fr.gouv.vitamui.commons.api.CommonConstants.SURROGATION_PARAMETER;
 import static fr.gouv.vitamui.commons.api.CommonConstants.TENANTS_BY_APP_ATTRIBUTE;
+import static fr.gouv.vitamui.commons.api.CommonConstants.SITE_CODE;
 import static fr.gouv.vitamui.commons.api.CommonConstants.TYPE_ATTRIBUTE;
 import static fr.gouv.vitamui.commons.api.CommonConstants.USER_ID_ATTRIBUTE;
 
@@ -217,6 +218,7 @@ public class UserPrincipalResolver implements PrincipalResolver {
             attributes.put(AUTHTOKEN_ATTRIBUTE, Collections.singletonList(authUser.getAuthToken()));
             attributes.put(PROOF_TENANT_ID_ATTRIBUTE, Collections.singletonList(authUser.getProofTenantIdentifier()));
             attributes.put(TENANTS_BY_APP_ATTRIBUTE, Collections.singletonList(new CasJsonWrapper(authUser.getTenantsByApp())));
+            attributes.put(SITE_CODE, Collections.singletonList(user.getSiteCode()));
             final Set<String> roles = new HashSet<>();
             final List<ProfileDto> profiles = authUser.getProfileGroup().getProfiles();
             profiles.forEach(profile -> profile.getRoles().forEach(role -> roles.add(role.getName())));
diff --git a/commons/commons-api/src/main/java/fr/gouv/vitamui/commons/api/CommonConstants.java b/commons/commons-api/src/main/java/fr/gouv/vitamui/commons/api/CommonConstants.java
index 3fb9b198..cd680366 100644
--- a/commons/commons-api/src/main/java/fr/gouv/vitamui/commons/api/CommonConstants.java
+++ b/commons/commons-api/src/main/java/fr/gouv/vitamui/commons/api/CommonConstants.java
@@ -167,6 +167,8 @@ public class CommonConstants {
 
     public static final String TENANTS_BY_APP_ATTRIBUTE = "tenantsByApp";
 
+    public static final String SITE_CODE = "siteCode";
+
     public static final String CUSTOMER_ID_ATTRIBUTE = "customerId";
 
     public static final String CUSTOMER_IDENTIFIER_ATTRIBUTE = "customerIdentifier";
diff --git a/commons/commons-api/src/main/java/fr/gouv/vitamui/commons/api/domain/UserDto.java b/commons/commons-api/src/main/java/fr/gouv/vitamui/commons/api/domain/UserDto.java
index ba968201..4a8b95c1 100644
--- a/commons/commons-api/src/main/java/fr/gouv/vitamui/commons/api/domain/UserDto.java
+++ b/commons/commons-api/src/main/java/fr/gouv/vitamui/commons/api/domain/UserDto.java
@@ -110,4 +110,6 @@ public class UserDto extends CustomerIdDto {
     private OffsetDateTime passwordExpirationDate;
 
     private AddressDto address = new AddressDto();
+
+    private String siteCode;
 }
diff --git a/commons/commons-security/src/main/java/fr/gouv/vitamui/commons/security/client/dto/AuthUserDto.java b/commons/commons-security/src/main/java/fr/gouv/vitamui/commons/security/client/dto/AuthUserDto.java
index b41f184b..2775299a 100644
--- a/commons/commons-security/src/main/java/fr/gouv/vitamui/commons/security/client/dto/AuthUserDto.java
+++ b/commons/commons-security/src/main/java/fr/gouv/vitamui/commons/security/client/dto/AuthUserDto.java
@@ -116,6 +116,7 @@ public class AuthUserDto extends UserDto implements UserDetails {
         setNbFailedAttempts(user.getNbFailedAttempts());
         setPasswordExpirationDate(user.getPasswordExpirationDate());
         setGroupId(user.getGroupId());
+        setSiteCode(user.getSiteCode());
     }
 
     public AuthUserDto(final String username, final Map<String, Object> attributes) {
@@ -244,6 +245,9 @@ public class AuthUserDto extends UserDto implements UserDetails {
                         setTenantsByApp((List<TenantInformationDto>) parseJson(value, new TypeReference<List<TenantInformationDto>>() {
                         }));
                         break;
+                    case SITE_CODE :
+                        setSiteCode((String) value);
+                        break;
                 }
             }
         }
@@ -296,6 +300,7 @@ public class AuthUserDto extends UserDto implements UserDetails {
         user.setNbFailedAttempts(getNbFailedAttempts());
         user.setPasswordExpirationDate(getPasswordExpirationDate());
         user.setGroupId(getGroupId());
+        user.setSiteCode(getSiteCode());
         return user;
     }
 }
diff --git a/deployment/scripts/mongod/1.0.0/FENIX-58_init_user_sitecode_ref.js b/deployment/scripts/mongod/1.0.0/FENIX-58_init_user_sitecode_ref.js
new file mode 100644
index 00000000..5a14176b
--- /dev/null
+++ b/deployment/scripts/mongod/1.0.0/FENIX-58_init_user_sitecode_ref.js
@@ -0,0 +1,15 @@
+db = db.getSiblingDB('iam')
+
+print("START FENIX-58_init_user_sitecode_ref.js");
+
+// Update all users without siteCode : add an empty siteCode
+db.users.updateMany(
+  {"siteCode": {$exists: false}},
+  {
+    $set: {
+      "siteCode": ""
+    }
+  }
+);
+
+print("END FENIX-58_init_user_sitecode_ref.js");
diff --git a/ui/ui-frontend-common/src/app/modules/models/user/auth-user.interface.ts b/ui/ui-frontend-common/src/app/modules/models/user/auth-user.interface.ts
index 4e3a143f..18a47ca3 100644
--- a/ui/ui-frontend-common/src/app/modules/models/user/auth-user.interface.ts
+++ b/ui/ui-frontend-common/src/app/modules/models/user/auth-user.interface.ts
@@ -56,5 +56,5 @@ export interface AuthUser extends User {
   username: string;
   customerIdentifier: string;
   basicCustomer: BasicCustomer;
-
+  siteCode: string;
 }
diff --git a/ui/ui-frontend-common/src/app/modules/models/user/user.interface.ts b/ui/ui-frontend-common/src/app/modules/models/user/user.interface.ts
index 9bb0030c..53229d08 100644
--- a/ui/ui-frontend-common/src/app/modules/models/user/user.interface.ts
+++ b/ui/ui-frontend-common/src/app/modules/models/user/user.interface.ts
@@ -57,5 +57,6 @@ export interface User extends Id {
   lastConnection: string;
   readonly: boolean;
   address: Address;
+  siteCode: string;
 
 }
diff --git a/ui/ui-frontend/projects/identity/src/app/user/user-create/user-create.component.html b/ui/ui-frontend/projects/identity/src/app/user/user-create/user-create.component.html
index 36cd3059..0ef17962 100644
--- a/ui/ui-frontend/projects/identity/src/app/user/user-create/user-create.component.html
+++ b/ui/ui-frontend/projects/identity/src/app/user/user-create/user-create.component.html
@@ -198,6 +198,12 @@
           </div>
         </ng-container>
 
+        <div>
+          <vitamui-common-input class="field-site-code" formControlName="siteCode" placeholder="Code du site"
+                                i18n-placeholder="user create siteCode@@userCreateSiteCode">
+          </vitamui-common-input>
+        </div>
+
         <div class="actions">
           <button type="button" class="btn primary" cdkStepperNext [disabled]="form.get('address').pending || form.get('address').invalid"
             i18n="user create next step otp@@userCreateNextStepOtpButton">
diff --git a/ui/ui-frontend/projects/identity/src/app/user/user-create/user-create.component.scss b/ui/ui-frontend/projects/identity/src/app/user/user-create/user-create.component.scss
index 70c07b7b..f708dbbe 100644
--- a/ui/ui-frontend/projects/identity/src/app/user/user-create/user-create.component.scss
+++ b/ui/ui-frontend/projects/identity/src/app/user/user-create/user-create.component.scss
@@ -68,6 +68,11 @@ h2 {
     margin-right: $field-spacing;
 }
 
+.field-site-code {
+  width: 160px;
+  margin-right: $field-spacing;
+}
+
 .field-city {
     width: 260px;
     margin-right: $field-spacing;
diff --git a/ui/ui-frontend/projects/identity/src/app/user/user-create/user-create.component.ts b/ui/ui-frontend/projects/identity/src/app/user/user-create/user-create.component.ts
index 7a47d721..df9764f8 100644
--- a/ui/ui-frontend/projects/identity/src/app/user/user-create/user-create.component.ts
+++ b/ui/ui-frontend/projects/identity/src/app/user/user-create/user-create.component.ts
@@ -140,7 +140,8 @@ export class UserCreateComponent implements OnInit, OnDestroy {
           zipCode: [null],
           city: [null],
           country: ['FR']
-        })
+        }),
+        siteCode: [null],
       },
       { validator: UserValidators.missingPhoneNumber }
     );
diff --git a/ui/ui-frontend/projects/identity/src/app/user/user-preview/user-information-tab/user-information-tab.component.html b/ui/ui-frontend/projects/identity/src/app/user/user-preview/user-information-tab/user-information-tab.component.html
index 218cf69b..9b225692 100644
--- a/ui/ui-frontend/projects/identity/src/app/user/user-preview/user-information-tab/user-information-tab.component.html
+++ b/ui/ui-frontend/projects/identity/src/app/user/user-preview/user-information-tab/user-information-tab.component.html
@@ -99,6 +99,14 @@
     </div>
   </ng-container>
 
+  <div class="row">
+    <div class="col-6 form-control">
+      <vitamui-common-editable-input formControlName="siteCode" label="Code du site"
+                                     i18n-label="user info tab siteCode@@UserInfoTabSiteCode">
+      </vitamui-common-editable-input>
+    </div>
+  </div>
+
   <div class="row">
     <div class="col-6 form-control">
       <vitamui-common-editable-input formControlName="level" label="Niveau du groupe"
diff --git a/ui/ui-frontend/projects/identity/src/app/user/user-preview/user-information-tab/user-information-tab.component.spec.ts b/ui/ui-frontend/projects/identity/src/app/user/user-preview/user-information-tab/user-information-tab.component.spec.ts
index e38e7e2b..a6b7bd3d 100644
--- a/ui/ui-frontend/projects/identity/src/app/user/user-preview/user-information-tab/user-information-tab.component.spec.ts
+++ b/ui/ui-frontend/projects/identity/src/app/user/user-preview/user-information-tab/user-information-tab.component.spec.ts
@@ -74,7 +74,8 @@ let expectedUser: User = {
       zipCode: '75009',
       city: 'paris',
       country: 'france'
-  }
+  },
+  siteCode: '001'
 };
 
 let expectedCustomer: Customer = {
@@ -182,7 +183,8 @@ describe('UserInfoTabComponent', () => {
           zipCode: '75009',
           city: 'paris',
           country: 'france'
-      }
+      },
+      siteCode: '001'
     };
     expectedCustomer = {
       id: 'idCustomer',
diff --git a/ui/ui-frontend/projects/identity/src/app/user/user-preview/user-information-tab/user-information-tab.component.ts b/ui/ui-frontend/projects/identity/src/app/user/user-preview/user-information-tab/user-information-tab.component.ts
index f858d77b..42585437 100644
--- a/ui/ui-frontend/projects/identity/src/app/user/user-preview/user-information-tab/user-information-tab.component.ts
+++ b/ui/ui-frontend/projects/identity/src/app/user/user-preview/user-information-tab/user-information-tab.component.ts
@@ -85,7 +85,8 @@ export class UserInfoTabComponent implements OnChanges {
       zipCode: string,
       city: string,
       country: string,
-    }
+    },
+    siteCode: string
   };
   clientEmailDomains: string[];
 
@@ -115,7 +116,8 @@ export class UserInfoTabComponent implements OnChanges {
         zipCode: [null, Validators.required],
         city: [null, Validators.required],
         country: [null, Validators.required],
-      })
+      }),
+      siteCode: [null],
     });
 
     this.form.get('mobile').valueChanges.subscribe(() => {
-- 
GitLab