From 870d6564101670d1711e81639b097b54135a5903 Mon Sep 17 00:00:00 2001 From: gaetanbrl Date: Tue, 24 Dec 2024 12:02:20 +0100 Subject: [PATCH] ldap, console : new orgUniqueId #4374 #4372 https://github.com/georchestra/georchestra-gateway/issues/159 Add organizationId object Fix olcAttribute type uniqueOrganizationId Console - new form field - uniqueOrganizationId Custom proconnect tag for docker image ldap management - add new uniqueOrganizationId up attribute and add siret c2c info new uniqueOrganizationId field in orgDao console, ldap - add new orgUniqueId field use organizatioid change jsp new account new code insertion for field uniqueOrganizationId org create form translation Fix app. properties with uniqueOrganizationId translate missing key use standard var name rename new org field according to console rules Fix JSON var name fix getter annotation add missing new file Insert new orgUniqueId field in commons New field Mapping with organization class fix around new orgUniqueId field Changes around new orgUniqueId ldap field Fix JSP error remove useless console log Add new account orgUniqueId field complete code with new org field Control orgUniqId unicity before save, update fix org validation by orgUniqueId field correct makefile btag --- .../security/api/OrganizationsApi.java | 2 + .../security/model/Organization.java | 3 ++ console/package-lock.json | 3 ++ .../ws/backoffice/orgs/OrgsController.java | 31 +++++++++++++ .../EditOrgDetailsFormBean.java | 1 + .../EditOrgDetailsFormController.java | 12 ++++- .../ws/newaccount/AccountFormBean.java | 2 + .../newaccount/NewAccountFormController.java | 9 +++- .../console/ws/utils/Validation.java | 45 +++++++++++++++++++ .../WEB-INF/i18n/application.properties | 3 ++ .../WEB-INF/i18n/application_de.properties | 3 ++ .../WEB-INF/i18n/application_es.properties | 3 ++ .../WEB-INF/i18n/application_fr.properties | 4 ++ .../WEB-INF/i18n/application_nl.properties | 3 ++ .../WEB-INF/views/createAccountForm.jsp | 4 ++ .../WEB-INF/views/editOrgDetailsForm.jsp | 3 ++ .../webapp/manager/app/assets/lang/en.json | 1 + .../webapp/manager/app/assets/lang/fr.json | 1 + .../manager/app/components/orgs/orgs.es6 | 2 +- .../manager/app/templates/orgForm.tpl.html | 7 +++ .../src/main/webapp/manager/brunch-config.js | 6 +++ .../src/main/webapp/manager/package-lock.json | 14 +++--- .../console/integration/OrgsIT.java | 1 + .../resources/testData/createOrgPayload.json | 3 +- .../java/org/georchestra/ds/orgs/Org.java | 10 +++++ .../java/org/georchestra/ds/orgs/OrgExt.java | 1 + .../java/org/georchestra/ds/orgs/OrgsDao.java | 2 + .../org/georchestra/ds/orgs/OrgsDaoImpl.java | 10 +++++ .../ds/security/OrganizationMapper.java | 2 + .../ds/security/OrganizationsApiImpl.java | 7 +++ .../georchestra/ds/orgs/OrgsDaoImplIT.java | 3 ++ ldap/docker-root/georchestra.ldif | 1 + ldap/docker-root/georchestraSchema.ldif | 14 ++++-- 33 files changed, 200 insertions(+), 16 deletions(-) create mode 100644 console/package-lock.json diff --git a/commons/src/main/java/org/georchestra/security/api/OrganizationsApi.java b/commons/src/main/java/org/georchestra/security/api/OrganizationsApi.java index d72481b4b9..a3db739f21 100644 --- a/commons/src/main/java/org/georchestra/security/api/OrganizationsApi.java +++ b/commons/src/main/java/org/georchestra/security/api/OrganizationsApi.java @@ -29,6 +29,8 @@ public interface OrganizationsApi { Optional findById(String id); + Optional findByOrgUniqueId(String id); + Optional findByShortName(String shortName); Optional getLogo(String id); diff --git a/commons/src/main/java/org/georchestra/security/model/Organization.java b/commons/src/main/java/org/georchestra/security/model/Organization.java index fa2e6df7dc..ffd9e481fd 100644 --- a/commons/src/main/java/org/georchestra/security/model/Organization.java +++ b/commons/src/main/java/org/georchestra/security/model/Organization.java @@ -67,6 +67,9 @@ public class Organization implements Serializable { private String mail; + /** Custom field added by georchestra.ldif file */ + private String orgUniqueId; + /** * String that somehow represents the current version, may be a timestamp, a * hash, etc. Provided by request header {@code sec-lastupdated} diff --git a/console/package-lock.json b/console/package-lock.json new file mode 100644 index 0000000000..48e341a095 --- /dev/null +++ b/console/package-lock.json @@ -0,0 +1,3 @@ +{ + "lockfileVersion": 1 +} diff --git a/console/src/main/java/org/georchestra/console/ws/backoffice/orgs/OrgsController.java b/console/src/main/java/org/georchestra/console/ws/backoffice/orgs/OrgsController.java index db2185e942..1a6a165275 100644 --- a/console/src/main/java/org/georchestra/console/ws/backoffice/orgs/OrgsController.java +++ b/console/src/main/java/org/georchestra/console/ws/backoffice/orgs/OrgsController.java @@ -168,6 +168,25 @@ public Org getOrgInfos(@PathVariable String cn) { return this.orgDao.findByCommonName(cn); } + /** + * Retreive full information about one org as JSON document from unique + * organization id number (e.g french SIRET number). Following keys will be + * available : + * + * * 'id' (not used) * 'name' * 'shortName' * 'cities' as json array ex: + * [654,865498,98364,9834534,984984,6978984,98498] * 'status' * 'orgType' * + * 'address' * 'members' as json array ex: ["testadmin", "testuser"] + * + */ + @RequestMapping(value = REQUEST_MAPPING + + "/uoi/{orgUniqueId:.+}", method = RequestMethod.GET, produces = "application/json; charset=utf-8") + @ResponseBody + public Org getOrgInfosFromUniqueOrgId(@PathVariable String orgUniqueId) { + Org orgInfos = this.orgDao.findByOrgUniqueId(orgUniqueId); + this.checkOrgAuthorization(orgInfos.getId()); + return orgInfos; + } + /** * Update information of one org * @@ -185,6 +204,9 @@ public Org getOrgInfos(@PathVariable String cn) { * plante, 73059 Chambrille", "members": [ "testadmin", "testuser" ] } * */ + /** + * TODO: Control orgUniqueId unicity + */ @RequestMapping(value = REQUEST_MAPPING + "/{commonName:.+}", method = RequestMethod.PUT, produces = "application/json; charset=utf-8") @ResponseBody @@ -196,6 +218,10 @@ public Org updateOrgInfos(@PathVariable String commonName, HttpServletRequest re // Parse Json JSONObject json = this.parseRequest(request); + if (!this.validation.validateOrgUnicity(json)) { + throw new IOException("Organization : already exists"); + } + // Validate request against required fields for admin part if (!this.validation.validateOrgField("name", json)) { throw new IOException("required field : name"); @@ -258,6 +284,10 @@ public Org createOrg(HttpServletRequest request) throws IOException, JSONExcepti // Parse Json JSONObject json = this.parseRequest(request); + if (!this.validation.validateOrgUnicity(json)) { + throw new IOException("An organization with this identification number already exists."); + } + // Validate request against required fields for admin part if (!this.validation.validateOrgField("shortName", json)) { throw new IOException("required field : shortName"); @@ -482,6 +512,7 @@ protected void updateFromRequest(Org org, JSONObject json) throws IOException { org.setUrl(json.optString(Org.JSON_URL)); org.setLogo(json.optString(Org.JSON_LOGO)); org.setMail(json.optString(Org.JSON_MAIL)); + org.setOrgUniqueId(json.optString(Org.JSON_ORG_UNIQ_ID)); } /** diff --git a/console/src/main/java/org/georchestra/console/ws/editorgdetails/EditOrgDetailsFormBean.java b/console/src/main/java/org/georchestra/console/ws/editorgdetails/EditOrgDetailsFormBean.java index 4858facfa6..c3eb85e9f6 100644 --- a/console/src/main/java/org/georchestra/console/ws/editorgdetails/EditOrgDetailsFormBean.java +++ b/console/src/main/java/org/georchestra/console/ws/editorgdetails/EditOrgDetailsFormBean.java @@ -12,4 +12,5 @@ private String url; private String orgType; private String mail; + private String orgUniqueId; } diff --git a/console/src/main/java/org/georchestra/console/ws/editorgdetails/EditOrgDetailsFormController.java b/console/src/main/java/org/georchestra/console/ws/editorgdetails/EditOrgDetailsFormController.java index af8ceed65d..abee2b06d8 100644 --- a/console/src/main/java/org/georchestra/console/ws/editorgdetails/EditOrgDetailsFormController.java +++ b/console/src/main/java/org/georchestra/console/ws/editorgdetails/EditOrgDetailsFormController.java @@ -54,7 +54,8 @@ public class EditOrgDetailsFormController { private OrgsDao orgsDao; private Validation validation; - private static final String[] FIELDS = { "id", "url", "description", "logo", "name", "address", "mail" }; + private static final String[] FIELDS = { "id", "url", "description", "logo", "name", "address", "mail", + "orgUniqueId" }; private static final Log LOG = LogFactory.getLog(EditOrgDetailsFormController.class.getName()); @@ -94,6 +95,7 @@ public String setupForm(HttpServletRequest request, Model model) { model.addAttribute("id", org.getId()); model.addAttribute("logo", org.getLogo()); model.addAttribute("mail", org.getMail()); + model.addAttribute("orgUniqueId", org.getOrgUniqueId()); HttpSession session = request.getSession(); for (String f : FIELDS) { if (validation.isOrgFieldRequired(f)) { @@ -110,6 +112,7 @@ public String edit(Model model, @ModelAttribute EditOrgDetailsFormBean formBean, validation.validateOrgField("url", formBean.getUrl(), resultErrors); validation.validateOrgField("address", formBean.getAddress(), resultErrors); validation.validateOrgField("description", formBean.getDescription(), resultErrors); + validation.validateOrgField("orgUniqueId", formBean.getOrgUniqueId(), resultErrors); // TODO validate mail address for the organization ? if (resultErrors.hasErrors()) { @@ -122,6 +125,7 @@ public String edit(Model model, @ModelAttribute EditOrgDetailsFormBean formBean, orgOrigin.setDescription(formBean.getDescription()); orgOrigin.setUrl(formBean.getUrl()); orgOrigin.setAddress(formBean.getAddress()); + orgOrigin.setOrgUniqueId(formBean.getOrgUniqueId()); if (!logo.isEmpty()) { orgOrigin.setLogo(transformLogoFileToBase64(logo)); @@ -154,6 +158,7 @@ private EditOrgDetailsFormBean createForm(Org org) { formBean.setAddress(org.getAddress()); formBean.setOrgType(org.getOrgType()); formBean.setMail(org.getMail()); + formBean.setOrgUniqueId(org.getOrgUniqueId()); return formBean; } @@ -192,6 +197,11 @@ protected void logOrgDetailsChanges(Org org, EditOrgDetailsFormBean formBean, Mu if (StringUtils.isNotEmpty(org.getMail()) && !org.getMail().equals(formBean.getMail())) { logUtils.createAndLogDetails(id, Org.JSON_MAIL, org.getMail(), formBean.getMail(), type); } + + if (!org.getOrgUniqueId().equals(formBean.getOrgUniqueId())) { + logUtils.createAndLogDetails(id, Org.JSON_ORG_UNIQ_ID, org.getOrgUniqueId(), formBean.getAddress(), type); + } + } } \ No newline at end of file diff --git a/console/src/main/java/org/georchestra/console/ws/newaccount/AccountFormBean.java b/console/src/main/java/org/georchestra/console/ws/newaccount/AccountFormBean.java index 7c57c15340..6bf5d5844d 100644 --- a/console/src/main/java/org/georchestra/console/ws/newaccount/AccountFormBean.java +++ b/console/src/main/java/org/georchestra/console/ws/newaccount/AccountFormBean.java @@ -87,6 +87,8 @@ public class AccountFormBean implements Serializable { private @Getter @Setter String orgMail; + private @Getter @Setter String orgUniqueId; + public boolean getPrivacyPolicyAgreed() { return privacyPolicyAgreed; } diff --git a/console/src/main/java/org/georchestra/console/ws/newaccount/NewAccountFormController.java b/console/src/main/java/org/georchestra/console/ws/newaccount/NewAccountFormController.java index 41f68a95ea..c8131165ed 100644 --- a/console/src/main/java/org/georchestra/console/ws/newaccount/NewAccountFormController.java +++ b/console/src/main/java/org/georchestra/console/ws/newaccount/NewAccountFormController.java @@ -179,8 +179,8 @@ public AccountFormBean getAccountFormBean() { public void initForm(WebDataBinder dataBinder) { dataBinder.setAllowedFields("firstName", "surname", "email", "phone", "org", "title", "description", "uid", "password", "confirmPassword", "privacyPolicyAgreed", "consentAgreed", "createOrg", "orgName", - "orgShortName", "orgAddress", "orgType", "orgCities", "orgDescription", "orgUrl", "orgMail", "orgLogo", - "recaptcha_response_field"); + "orgShortName", "orgUniqueId", "orgAddress", "orgType", "orgCities", "orgDescription", "orgUrl", + "orgMail", "orgLogo", "recaptcha_response_field"); } @RequestMapping(value = "/account/new", method = RequestMethod.GET) @@ -258,6 +258,7 @@ public String create(HttpServletRequest request, @ModelAttribute AccountFormBean org.setUrl(formBean.getOrgUrl()); org.setLogo(formBean.getOrgLogo()); org.setMail(formBean.getOrgMail()); + org.setOrgUniqueId(formBean.getOrgUniqueId()); // Parse and store cities orgCities = orgCities.trim(); if (orgCities.length() > 0) @@ -409,6 +410,7 @@ private void validateFields(@ModelAttribute AccountFormBean formBean, BindingRes validation.validateUserField("title", formBean.getTitle(), result); validation.validateUserField("description", formBean.getDescription(), result); + // unique orgUniqueId value if (formBean.getCreateOrg() && !result.hasErrors()) { validation.validateOrgField("name", formBean.getOrgName(), result); validation.validateOrgField("shortName", formBean.getOrgShortName(), result); @@ -417,7 +419,10 @@ private void validateFields(@ModelAttribute AccountFormBean formBean, BindingRes validation.validateOrgField("url", formBean.getOrgUrl(), result); validation.validateOrgField("description", formBean.getOrgDescription(), result); validation.validateOrgField("logo", formBean.getOrgLogo(), result); + validation.validateOrgField("orgUniqueId", formBean.getOrgUniqueId(), result); validation.validateUrlFieldWithSpecificMsg("orgUrl", formBean.getOrgUrl(), result); + + validation.validateOrgUniqueIdField(formBean.getOrgUniqueId(), null, result); } else { validation.validateUserField("org", formBean.getOrg(), result); } diff --git a/console/src/main/java/org/georchestra/console/ws/utils/Validation.java b/console/src/main/java/org/georchestra/console/ws/utils/Validation.java index 3b78143c81..b781df752c 100644 --- a/console/src/main/java/org/georchestra/console/ws/utils/Validation.java +++ b/console/src/main/java/org/georchestra/console/ws/utils/Validation.java @@ -22,12 +22,17 @@ import java.net.MalformedURLException; import java.net.URL; import java.util.HashSet; +import java.util.Objects; import java.util.Set; +import java.util.UUID; import java.util.regex.Matcher; import java.util.regex.Pattern; +import org.georchestra.ds.orgs.Org; +import org.georchestra.ds.orgs.OrgsDao; import org.json.JSONException; import org.json.JSONObject; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.util.StringUtils; import org.springframework.validation.Errors; @@ -45,6 +50,9 @@ */ public class Validation { + @Autowired + private OrgsDao orgDao; + private Set requiredUserFields; private Set requiredOrgFields; @@ -191,4 +199,41 @@ public boolean validateUrlFieldWithSpecificMsg(String fullyQualifiedField, Strin } return true; } + + public boolean validateOrgUnicityByUniqueId(String orgUniqueId, String uuid) { + // case - not value to verify + if (orgUniqueId == null || orgUniqueId.isEmpty()) { + return true; + } + // test if org with same value already exists + Org findByOrgUniqueId = this.orgDao.findByOrgUniqueId(orgUniqueId); + // No org exists with this field value + if (findByOrgUniqueId == null) { + return true; + } + // No uuid to compare means that's an org creation + // and at this step, an org already exists with this orgUniqueId + if (uuid == null) { + // we can't validate this orgUniqueId that already exists + return false; + } + // Control if this is same org update + return Objects.equals(findByOrgUniqueId.getUniqueIdentifier(), UUID.fromString(uuid)); + } + + public boolean validateOrgUniqueIdField(String orgUniqueId, String uniqueId, Errors errors) { + if (!this.validateOrgUnicityByUniqueId(orgUniqueId, uniqueId)) { + errors.rejectValue("orgUniqueId", "error.orgUniqueIdExists", "orgUniqueIdExists"); + return false; + } + return true; + } + + public boolean validateOrgUnicity(JSONObject json) { + boolean isUniqueOrg = true; + if (json.has("orgUniqueId")) { + isUniqueOrg = this.validateOrgUnicityByUniqueId(json.getString("orgUniqueId"), json.getString("uuid")); + } + return isUniqueOrg; + } } diff --git a/console/src/main/webapp/WEB-INF/i18n/application.properties b/console/src/main/webapp/WEB-INF/i18n/application.properties index bdbaead441..284fca9557 100644 --- a/console/src/main/webapp/WEB-INF/i18n/application.properties +++ b/console/src/main/webapp/WEB-INF/i18n/application.properties @@ -94,6 +94,7 @@ confirmPassword.error.pwdNotEquals=These passwords don\'t match confirmPassword.error.pwdNotEquals.tag=Mismatch description.label=Description description.placeholder=Description +orgUniqueId.label=Identification number email.label=E-mail email.placeholder=E-mail email.error.required=Required @@ -101,6 +102,7 @@ email.error.invalidFormat=Invalid format email.error.exist=This e-mail is already in use, you can try to reset your password. error.required=Required error.badUrl=malformed url +error.orgUniqueIdExists=An organisation with this identification number already exists. facsimile.label=Fax facsimile.placeholder=Fax firstName.label=First Name @@ -113,6 +115,7 @@ org.cannot_find_org_in_list=My organization is not present org.required=Required org.creation.label=Organization Name org.creation.shortLabel=Short Name +org.creation.orgUniqueId=Identification number org.creation.address=Address org.creation.orgType=Organization type org.creation.orgDescription=Description diff --git a/console/src/main/webapp/WEB-INF/i18n/application_de.properties b/console/src/main/webapp/WEB-INF/i18n/application_de.properties index 8a71a4e292..49271b785c 100644 --- a/console/src/main/webapp/WEB-INF/i18n/application_de.properties +++ b/console/src/main/webapp/WEB-INF/i18n/application_de.properties @@ -93,12 +93,14 @@ confirmPassword.error.pwdNotEquals.tag=Nicht das gleiche Passwort description.label=Beschreibung description.placeholder=Beschreibung email.label=E-Mail +orgUniqueId.label=Identifikationsnummer email.placeholder=E-Mail email.error.required=Notwendig email.error.invalidFormat=Ungültiges Format email.error.exist=Diese E-Mail Adresse ist bereits in Benutzung, Sie können ihr Passwort zurücksetzen. error.required=Notwendig error.badUrl=malformed url +error.orgUniqueIdExists=Eine Organisation mit dieser Identifikationsnummer existiert bereits. facsimile.label=Fax facsimile.placeholder=Fax firstName.label=Vorname @@ -111,6 +113,7 @@ org.cannot_find_org_in_list=Meine Organisation ist nicht vorhanden org.required=Notwendig org.creation.label=Organisations-Name org.creation.shortLabel=Kurzbezeichnung +org.creation.orgUniqueId=Identifikationsnummer org.creation.address=Adresse org.creation.orgType=Organisationstyp org.creation.orgDescription=Beschreibung diff --git a/console/src/main/webapp/WEB-INF/i18n/application_es.properties b/console/src/main/webapp/WEB-INF/i18n/application_es.properties index 2acb8022cf..dea276008e 100644 --- a/console/src/main/webapp/WEB-INF/i18n/application_es.properties +++ b/console/src/main/webapp/WEB-INF/i18n/application_es.properties @@ -92,12 +92,14 @@ confirmPassword.error.pwdNotEquals.tag=Diferentes description.label=Descripción description.placeholder=Descripción email.label=dirección de correo electrónico +orgUniqueId.label=Identificación email.placeholder=dirección de correo electrónico email.error.required=Requerido email.error.invalidFormat=Formato inválido email.error.exist=Este correo electrónico ya está en uso, puede intentar restablecer su contraseña. error.required=Requerido error.badUrl=malformed url +error.orgUniqueIdExists=Ya existe una organización con este número de identificación. facsimile.label=Fax facsimile.placeholder=Fax firstName.label=Nombre @@ -110,6 +112,7 @@ org.cannot_find_org_in_list=Mi organización no esta presente org.required=Requerida org.creation.label=Nombre de la Organización org.creation.shortLabel=Nombre corto +org.creation.orgUniqueId=Número de identificación org.creation.address=Dirección org.creation.orgType=Tipo de Organización org.creation.orgDescription=Descripción diff --git a/console/src/main/webapp/WEB-INF/i18n/application_fr.properties b/console/src/main/webapp/WEB-INF/i18n/application_fr.properties index fde13ef0ec..b2bfc1fc3e 100644 --- a/console/src/main/webapp/WEB-INF/i18n/application_fr.properties +++ b/console/src/main/webapp/WEB-INF/i18n/application_fr.properties @@ -92,6 +92,7 @@ confirmPassword.error.pwdNotEquals=Les mots de passe sont différents confirmPassword.error.pwdNotEquals.tag=Différents description.label=Description description.placeholder=Description +orgUniqueId.label=Numéro d'identification email.label=Courriel email.placeholder=Courriel email.error.required=Requis @@ -99,6 +100,7 @@ email.error.invalidFormat=Format invalide email.error.exist=Ce courriel est déjà utilisé, vous pouvez tenter de réinitialiser votre mot de passe. error.required=Requis error.badUrl=Format d'url invalide +error.orgUniqueIdExists=Une organisation avec ce numéro d'identification existe déjà. facsimile.label=Fax facsimile.placeholder=Fax firstName.label=Prénom @@ -111,12 +113,14 @@ org.cannot_find_org_in_list=Mon organisme n'apparaît pas dans la liste org.required=Requis org.creation.label=Votre organisme org.creation.shortLabel=Libellé court +org.creation.orgUniqueId=Numéro d'identification org.creation.address=Adresse org.creation.orgType=Type d\'organisme org.creation.orgDescription=Description org.creation.orgUrl=Url org.creation.orgMail=Mail org.creation.orgLogo=Logo +org.creation.orgUniqueId=Numéro d'identification org.shortNameFormat=Le nom court ne doit comporter que des caractères alphanumériques password.label=Mot de passe password.placeholder=Mot de passe diff --git a/console/src/main/webapp/WEB-INF/i18n/application_nl.properties b/console/src/main/webapp/WEB-INF/i18n/application_nl.properties index 70eca33df3..4385cd58d0 100644 --- a/console/src/main/webapp/WEB-INF/i18n/application_nl.properties +++ b/console/src/main/webapp/WEB-INF/i18n/application_nl.properties @@ -93,12 +93,14 @@ confirmPassword.error.pwdNotEquals.tag=Verschillend description.label=Beschrijving description.placeholder=Beschrijving email.label=Email +orgUniqueId.label=Identificatienummer email.placeholder=Email email.error.required=Verplicht email.error.invalidFormat=Ongeldig formaat email.error.exist=Deze e-mail is al in gebruik, u kunt proberen om uw wachtwoord opnieuw in te stellen error.required=Verplicht error.badUrl=malformed url +error.orgUniqueIdExists=Er bestaat al een organisatie met dit identificatienummer. facsimile.label=Fax facsimile.placeholder=Fax firstName.label=Voornaam @@ -111,6 +113,7 @@ org.cannot_find_org_in_list=Mijn organisatie verschijnt niet in de lijst org.required=Verplicht org.creation.label=Uw organisatie org.creation.shortLabel=Kort label +org.creation.orgUniqueId=Identificatienummer org.creation.address=Adres org.creation.orgType=Type organisatie org.creation.orgDescription=Description diff --git a/console/src/main/webapp/WEB-INF/views/createAccountForm.jsp b/console/src/main/webapp/WEB-INF/views/createAccountForm.jsp index c5230397ae..875ad7cccb 100644 --- a/console/src/main/webapp/WEB-INF/views/createAccountForm.jsp +++ b/console/src/main/webapp/WEB-INF/views/createAccountForm.jsp @@ -108,6 +108,10 @@ document.querySelector('#orgShortName').setAttribute('title', '') + + + + diff --git a/console/src/main/webapp/WEB-INF/views/editOrgDetailsForm.jsp b/console/src/main/webapp/WEB-INF/views/editOrgDetailsForm.jsp index e6d1116885..e422c93182 100644 --- a/console/src/main/webapp/WEB-INF/views/editOrgDetailsForm.jsp +++ b/console/src/main/webapp/WEB-INF/views/editOrgDetailsForm.jsp @@ -88,6 +88,9 @@ + + +
diff --git a/console/src/main/webapp/manager/app/assets/lang/en.json b/console/src/main/webapp/manager/app/assets/lang/en.json index 80d33cfb9a..f5b43c85fd 100644 --- a/console/src/main/webapp/manager/app/assets/lang/en.json +++ b/console/src/main/webapp/manager/app/assets/lang/en.json @@ -111,6 +111,7 @@ "org.description" : "Description", "org.url" : "Website", "org.mail" : "Mail", + "org.orgUniqueId": "Identification number", "org.logo" : "Logo", "org.note" : "Internal Notes", "org.cities" : "Area", diff --git a/console/src/main/webapp/manager/app/assets/lang/fr.json b/console/src/main/webapp/manager/app/assets/lang/fr.json index 962182e12f..025bc2e384 100644 --- a/console/src/main/webapp/manager/app/assets/lang/fr.json +++ b/console/src/main/webapp/manager/app/assets/lang/fr.json @@ -111,6 +111,7 @@ "org.description" : "Description", "org.url" : "Site web", "org.mail" : "Mail", + "org.orgUniqueId": "Numéro d'identification", "org.logo" : "Logo", "org.note" : "Notes Internes", "org.cities" : "Aire de compétence", diff --git a/console/src/main/webapp/manager/app/components/orgs/orgs.es6 b/console/src/main/webapp/manager/app/components/orgs/orgs.es6 index c74763ee47..d6d143f0a5 100644 --- a/console/src/main/webapp/manager/app/components/orgs/orgs.es6 +++ b/console/src/main/webapp/manager/app/components/orgs/orgs.es6 @@ -20,7 +20,7 @@ class OrgsController { delete org.members }) this.simplifiedOrgs = this.orgs.map((org) => { - return { id: org.id, name: org.name, shortName: org.shortName, membersCount: org.membersCount, pending: org.pending, status: org.status } + return { id: org.id, name: org.name, shortName: org.shortName, membersCount: org.membersCount, pending: org.pending, status: org.status, orgUniqueId: org.orgUniqueId } }) }) diff --git a/console/src/main/webapp/manager/app/templates/orgForm.tpl.html b/console/src/main/webapp/manager/app/templates/orgForm.tpl.html index 6aaa564793..035db5d099 100644 --- a/console/src/main/webapp/manager/app/templates/orgForm.tpl.html +++ b/console/src/main/webapp/manager/app/templates/orgForm.tpl.html @@ -75,6 +75,13 @@ placeholder="" ng-required="required.mail">
+
+ +
+ +
+
diff --git a/console/src/main/webapp/manager/brunch-config.js b/console/src/main/webapp/manager/brunch-config.js index f052c9ad60..8f50184993 100644 --- a/console/src/main/webapp/manager/brunch-config.js +++ b/console/src/main/webapp/manager/brunch-config.js @@ -1,5 +1,11 @@ module.exports = { config: { + // Changer le port par défaut ici + server: { + port: 4000, // Changer 4000 par le port de votre choix + path: 'http://localhost:4000', + run: true + }, plugins: { ng_templates: { module: 'manager', diff --git a/console/src/main/webapp/manager/package-lock.json b/console/src/main/webapp/manager/package-lock.json index 03ac455958..5a8b18b8b4 100644 --- a/console/src/main/webapp/manager/package-lock.json +++ b/console/src/main/webapp/manager/package-lock.json @@ -809,7 +809,7 @@ } }, "@babel/traverse": { - "version": "7.23.2", + "version": "7.11.0", "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.11.0.tgz", "integrity": "sha512-ZB2V+LskoWKNpMq6E5UUCrjtDUh5IOTAyIl0dTjIEoXum/iKWkoIEKIRDnUucO6f+2FzNkE0oD4RLKoPIufDtg==", "dev": true, @@ -1511,7 +1511,7 @@ } }, "browserify-sign": { - "version": "4.2.2", + "version": "4.2.1", "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.1.tgz", "integrity": "sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg==", "dev": true, @@ -2219,7 +2219,7 @@ "dev": true }, "decode-uri-component": { - "version": "0.2.2", + "version": "0.2.0", "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", "dev": true @@ -4511,7 +4511,7 @@ } }, "minimist": { - "version": "1.2.8", + "version": "1.2.5", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", "dev": true @@ -5395,7 +5395,7 @@ "dev": true }, "qs": { - "version": "6.4.1", + "version": "6.4.0", "resolved": "https://registry.npmjs.org/qs/-/qs-6.4.0.tgz", "integrity": "sha1-E+JtKK1rD/qpExLNO/cI7TUecjM=", "dev": true, @@ -5713,7 +5713,7 @@ } }, "requirejs": { - "version": "2.3.7", + "version": "2.3.6", "resolved": "https://registry.npmjs.org/requirejs/-/requirejs-2.3.6.tgz", "integrity": "sha512-ipEzlWQe6RK3jkzikgCupiTbTvm4S0/CAU5GlgptkN5SO6F3u0UD0K18wy6ErDqiCyP4J4YYe1HuAShvsxePLg==", "dev": true @@ -6986,7 +6986,7 @@ "dev": true }, "word-wrap": { - "version": "1.2.4", + "version": "1.2.3", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", "dev": true diff --git a/console/src/test/java/org/georchestra/console/integration/OrgsIT.java b/console/src/test/java/org/georchestra/console/integration/OrgsIT.java index 207e7e5ac5..aa639a1cbe 100644 --- a/console/src/test/java/org/georchestra/console/integration/OrgsIT.java +++ b/console/src/test/java/org/georchestra/console/integration/OrgsIT.java @@ -71,6 +71,7 @@ public class OrgsIT extends ConsoleIntegrationTest { support.perform(get("/private/orgs/" + orgName.replace(" ", "_"))) .andExpect(jsonPath("$.id").value(orgName.replace(" ", "_").toLowerCase())) .andExpect(jsonPath("$.shortName").value(orgName.toLowerCase())) + .andExpect(jsonPath("$.orgUniqueId").value("80908401500035")) .andExpect(jsonPath("$.name").value("camptocamp")).andExpect(jsonPath("$.cities").isEmpty()) .andExpect(jsonPath("$.members").isEmpty()).andExpect(jsonPath("$.address").value("1, rue du pont")) .andExpect(jsonPath("$.orgType").value("Company")).andExpect(jsonPath("$.pending").value(false)); diff --git a/console/src/test/resources/testData/createOrgPayload.json b/console/src/test/resources/testData/createOrgPayload.json index 6a5d7234bc..55407d762b 100644 --- a/console/src/test/resources/testData/createOrgPayload.json +++ b/console/src/test/resources/testData/createOrgPayload.json @@ -2,5 +2,6 @@ "address": "1, rue du pont", "name": "camptocamp", "orgType": "Company", - "shortName": "{shortName}" + "shortName": "{shortName}", + "orgUniqueId": "80908401500035" } \ No newline at end of file diff --git a/ldap-account-management/src/main/java/org/georchestra/ds/orgs/Org.java b/ldap-account-management/src/main/java/org/georchestra/ds/orgs/Org.java index a28393eca5..aac0829a63 100644 --- a/ldap-account-management/src/main/java/org/georchestra/ds/orgs/Org.java +++ b/ldap-account-management/src/main/java/org/georchestra/ds/orgs/Org.java @@ -59,6 +59,7 @@ public class Org extends ReferenceAware implements Comparable, Cloneable { public static final String JSON_ADDRESS = "address"; public static final String JSON_ORG_TYPE = "orgType"; public static final String JSON_MAIL = "mail"; + public static final String JSON_ORG_UNIQ_ID = "orgUniqueId"; private String id; private String name; @@ -180,4 +181,13 @@ public String getMail() { public void setMail(String mail) { this.ext.setMail(mail); } + + @JsonProperty(JSON_ORG_UNIQ_ID) + public String getOrgUniqueId() { + return this.ext.getOrgUniqueId(); + } + + public void setOrgUniqueId(String orgUniqueId) { + this.ext.setOrgUniqueId(orgUniqueId); + } } diff --git a/ldap-account-management/src/main/java/org/georchestra/ds/orgs/OrgExt.java b/ldap-account-management/src/main/java/org/georchestra/ds/orgs/OrgExt.java index f7aae8321f..a718f28140 100644 --- a/ldap-account-management/src/main/java/org/georchestra/ds/orgs/OrgExt.java +++ b/ldap-account-management/src/main/java/org/georchestra/ds/orgs/OrgExt.java @@ -47,6 +47,7 @@ class OrgExt extends ReferenceAware implements Cloneable { private String logo = ""; private String note = ""; private String mail = ""; + private String orgUniqueId = ""; @Override public OrgExt clone() { diff --git a/ldap-account-management/src/main/java/org/georchestra/ds/orgs/OrgsDao.java b/ldap-account-management/src/main/java/org/georchestra/ds/orgs/OrgsDao.java index b8bca51068..459b2675e7 100644 --- a/ldap-account-management/src/main/java/org/georchestra/ds/orgs/OrgsDao.java +++ b/ldap-account-management/src/main/java/org/georchestra/ds/orgs/OrgsDao.java @@ -56,6 +56,8 @@ public interface OrgsDao { public Org findByUser(Account user); + public Org findByOrgUniqueId(String orgUniqueId); + /** * Search by {@link Org#getUniqueIdentifier()} * diff --git a/ldap-account-management/src/main/java/org/georchestra/ds/orgs/OrgsDaoImpl.java b/ldap-account-management/src/main/java/org/georchestra/ds/orgs/OrgsDaoImpl.java index f1a7567ae2..9b88bbffe2 100644 --- a/ldap-account-management/src/main/java/org/georchestra/ds/orgs/OrgsDaoImpl.java +++ b/ldap-account-management/src/main/java/org/georchestra/ds/orgs/OrgsDaoImpl.java @@ -203,7 +203,9 @@ public Org mapFromAttributes(Attributes attrs) throws NamingException { org.setMembers(asStringStream(attrs, "member").map(LdapNameBuilder::newInstance) .map(LdapNameBuilder::build).map(name -> name.getRdn(name.size() - 1).getValue().toString()) .collect(Collectors.toList())); + org.setOrgUniqueId(asStringStream(attrs, "orgUniqueId").collect(joining(","))); org.setPending(pending); + return org; } }; @@ -227,6 +229,7 @@ public void mapPayloadToContext(OrgExt org, DirContextOperations context) { setOrDeleteField(context, "description", org.getDescription()); setOrDeleteField(context, "labeledURI", org.getUrl()); setOrDeletePhoto(context, "jpegPhoto", org.getLogo()); + setOrDeleteField(context, "orgUniqueId", org.getOrgUniqueId()); } @Override @@ -258,6 +261,7 @@ public OrgExt mapFromAttributes(Attributes attrs) throws NamingException { orgExt.setLogo(asPhoto(attrs.get("jpegPhoto"))); orgExt.setPending(pending); orgExt.setMail(asString(attrs.get("mail"))); + orgExt.setOrgUniqueId(asString(attrs.get("orgUniqueId"))); return orgExt; } @@ -396,6 +400,12 @@ public Org findById(UUID uuid) { return findAllWithExt().filter(o -> uuid.equals(o.getUniqueIdentifier())).findFirst().orElse(null); } + @Override + public Org findByOrgUniqueId(String orgUniqueId) { + return findAllWithExt().filter(o -> orgUniqueId.equals(o.getOrgUniqueId())).findFirst().orElse(null); + + } + private Org addExt(Org org) { if (org == null) { return null; diff --git a/ldap-account-management/src/main/java/org/georchestra/ds/security/OrganizationMapper.java b/ldap-account-management/src/main/java/org/georchestra/ds/security/OrganizationMapper.java index 6cbec19bec..a711eb74a0 100644 --- a/ldap-account-management/src/main/java/org/georchestra/ds/security/OrganizationMapper.java +++ b/ldap-account-management/src/main/java/org/georchestra/ds/security/OrganizationMapper.java @@ -39,6 +39,7 @@ public interface OrganizationMapper { @Mapping(target = "linkage", source = "url") @Mapping(target = "postalAddress", source = "address") @Mapping(target = "category", source = "orgType") + @Mapping(target = "orgUniqueId", source = "orgUniqueId", ignore = true) @Mapping(target = "lastUpdated", ignore = true) @Mapping(target = "withId", ignore = true) @Mapping(target = "withShortName", ignore = true) @@ -51,6 +52,7 @@ public interface OrganizationMapper { @Mapping(target = "withLastUpdated", ignore = true) @Mapping(target = "withMembers", ignore = true) @Mapping(target = "withMail", source = "mail", ignore = true) + @Mapping(target = "withOrgUniqueId", source = "orgUniqueId", ignore = true) Organization map(Org org); @AfterMapping diff --git a/ldap-account-management/src/main/java/org/georchestra/ds/security/OrganizationsApiImpl.java b/ldap-account-management/src/main/java/org/georchestra/ds/security/OrganizationsApiImpl.java index 19ffe6de93..d10d64b260 100644 --- a/ldap-account-management/src/main/java/org/georchestra/ds/security/OrganizationsApiImpl.java +++ b/ldap-account-management/src/main/java/org/georchestra/ds/security/OrganizationsApiImpl.java @@ -66,6 +66,13 @@ public Optional findByShortName(String shortName) { .map(orgMapper::map); } + @Override + public Optional findByOrgUniqueId(String orgUniqueId) { + return Optional.ofNullable(orgsDao.findByOrgUniqueId(orgUniqueId))// + .filter(not(Org::isPending))// + .map(orgMapper::map); + } + @Override public Optional getLogo(String id) { UUID uuid = UUID.fromString(id); diff --git a/ldap-account-management/src/test/java/org/georchestra/ds/orgs/OrgsDaoImplIT.java b/ldap-account-management/src/test/java/org/georchestra/ds/orgs/OrgsDaoImplIT.java index d9769fcc29..cac6733616 100644 --- a/ldap-account-management/src/test/java/org/georchestra/ds/orgs/OrgsDaoImplIT.java +++ b/ldap-account-management/src/test/java/org/georchestra/ds/orgs/OrgsDaoImplIT.java @@ -50,6 +50,7 @@ public void setup() throws Exception { org.setShortName("tEsTOrG"); org.setCities(Lists.newArrayList("Paris")); org.setOrgType("Non Profit"); + org.setOrgUniqueId("5315431354"); dao.insert(org); @@ -59,6 +60,7 @@ public void setup() throws Exception { pendingOrg.setName("Pending Org"); pendingOrg.setPending(true); pendingOrg.setOrgType("For Profit"); + pendingOrg.setOrgUniqueId("6887431324"); dao.insert(pendingOrg); } @@ -223,6 +225,7 @@ public void testOrgAttributeMapperRemovingAllCities() { ncOrg.setShortName("no cities org"); ncOrg.setCities(Lists.newArrayList("Paris")); ncOrg.setOrgType("Non Profit"); + ncOrg.setOrgUniqueId("41134144731"); dao.insert(ncOrg); ncOrg = dao.findByCommonName(ncOrg.getId()); ncOrg.setCities(List.of()); diff --git a/ldap/docker-root/georchestra.ldif b/ldap/docker-root/georchestra.ldif index c985c45839..6d8e199ee4 100644 --- a/ldap/docker-root/georchestra.ldif +++ b/ldap/docker-root/georchestra.ldif @@ -370,6 +370,7 @@ o: C2C mail: georchestra@camptocamp.com businessCategory: Company postalAddress: 18 Rue du lac Saint André, 73000 Chambéry +orgUniqueId: 43369857800054 labeledURI: https://www.camptocamp.com/ description: Camptocamp SAS France knowledgeInformation: Internal CRM notes on Camptocamp diff --git a/ldap/docker-root/georchestraSchema.ldif b/ldap/docker-root/georchestraSchema.ldif index b5c49182b3..2637ff875e 100644 --- a/ldap/docker-root/georchestraSchema.ldif +++ b/ldap/docker-root/georchestraSchema.ldif @@ -20,25 +20,31 @@ olcAttributeTypes: ( 1.3.6.1.4.1.53611.1.2.2 SINGLE-VALUE ) olcAttributeTypes: ( 1.3.6.1.4.1.53611.1.2.3 NAME 'oAuth2Provider' - DESC 'OAuth2 provider for external identity provider users)' + DESC 'OAuth2 provider for external identity provider users' EQUALITY caseIgnoreMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE ) olcAttributeTypes: ( 1.3.6.1.4.1.53611.1.2.4 NAME 'oAuth2Uid' - DESC 'OAuth2 UID for external identity provider users)' + DESC 'OAuth2 UID for external identity provider users' EQUALITY caseIgnoreMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE ) +olcAttributeTypes: ( 1.3.6.1.4.1.53611.1.2.5 + NAME 'orgUniqueId' + DESC 'organization identifier such as SIRET number or other' + EQUALITY caseIgnoreMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 + SINGLE-VALUE) olcObjectClasses: ( 1.3.6.1.4.1.53611.1.1.2 NAME 'georchestraOrg' DESC 'georchestra org' SUP top AUXILIARY - MAY (jpegphoto $ labeledURI $ knowledgeInformation $ georchestraObjectIdentifier)) + MAY (jpegphoto $ labeledURI $ knowledgeInformation $ georchestraObjectIdentifier $ orgUniqueId)) olcObjectClasses: ( 1.3.6.1.4.1.53611.1.1.3 NAME 'georchestraRole' DESC 'Uniquely identifiable georchestra role' SUP top AUXILIARY - MAY (georchestraObjectIdentifier)) + MAY (georchestraObjectIdentifier)) \ No newline at end of file