branch feature/add_password_to_registration created (now 9002c67)
This is an automated email from the git hooks/post-receive script. New change to branch feature/add_password_to_registration in repository pollen. See https://gitlab.nuiton.org/chorem/pollen.git at 9002c67 refs #6 passage des urls du front au back pour l'email d'inscription This branch includes the following new commits: new 089c3c5 refs #6 User account management: ajout du mot de passe dans le formulaire d'inscription new 9002c67 refs #6 passage des urls du front au back pour l'email d'inscription The 2 revisions listed above as "new" are entirely new to this repository and will be described in separate emails. The revisions listed as "adds" were already present in the repository and have only been added to this reference. Detailed log of new commits: commit 089c3c573a030756cebe565569f226c0551d10a8 Author: Kevin Morin <morin@codelutin.com> Date: Tue Feb 28 16:44:56 2017 +0100 refs #6 User account management: ajout du mot de passe dans le formulaire d'inscription commit 9002c6700f143b83ed0409f8e1cc5e4ab7dd601d Author: Kevin Morin <morin@codelutin.com> Date: Tue Feb 28 17:09:25 2017 +0100 refs #6 passage des urls du front au back pour l'email d'inscription -- To stop receiving notification emails like this one, please contact chorem.org SCM administrator <admin+scm@chorem.org>.
This is an automated email from the git hooks/post-receive script. New commit to branch feature/add_password_to_registration in repository pollen. See https://gitlab.nuiton.org/chorem/pollen.git commit 089c3c573a030756cebe565569f226c0551d10a8 Author: Kevin Morin <morin@codelutin.com> Date: Tue Feb 28 16:44:56 2017 +0100 refs #6 User account management: ajout du mot de passe dans le formulaire d'inscription --- .../chorem/pollen/rest/api/v1/PollenUserApi.java | 5 ++-- .../services/service/NotificationService.java | 4 +-- .../pollen/services/service/PollenUserService.java | 32 ++++++---------------- .../pollen/services/service/mail/EmailService.java | 3 +- .../email/UserAccountCreatedEmail.mustache | 1 - .../email/UserAccountCreatedEmail_fr.mustache | 1 - pollen-ui-riot-js/src/main/web/i18n.json | 16 +++++++++-- pollen-ui-riot-js/src/main/web/js/AuthService.js | 2 +- pollen-ui-riot-js/src/main/web/tag/SignUp.tag.html | 28 +++++++++++++++++-- 9 files changed, 52 insertions(+), 40 deletions(-) diff --git a/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/PollenUserApi.java b/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/PollenUserApi.java index 8931c4a..237631d 100644 --- a/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/PollenUserApi.java +++ b/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/PollenUserApi.java @@ -65,10 +65,9 @@ public class PollenUserApi extends WebMotionController { } public PollenEntityRef<PollenUser> createUser(PollenUserService pollenUserService, - PollenUserBean user, - boolean generatePassword) throws InvalidFormException { + PollenUserBean user) throws InvalidFormException { - return pollenUserService.createUser(user, generatePassword); + return pollenUserService.createUser(user); } diff --git a/pollen-services/src/main/java/org/chorem/pollen/services/service/NotificationService.java b/pollen-services/src/main/java/org/chorem/pollen/services/service/NotificationService.java index c2d343e..e53bc32 100644 --- a/pollen-services/src/main/java/org/chorem/pollen/services/service/NotificationService.java +++ b/pollen-services/src/main/java/org/chorem/pollen/services/service/NotificationService.java @@ -42,10 +42,10 @@ import org.chorem.pollen.services.service.mail.UserAccountCreatedEmail; */ public class NotificationService extends PollenServiceSupport { - public void onUserCreated(PollenUser user, String password) { + public void onUserCreated(PollenUser user) { EmailService emailService = getEmailService(); - UserAccountCreatedEmail email = emailService.newUserAccountCreatedEmail(getLocale(), user, password); + UserAccountCreatedEmail email = emailService.newUserAccountCreatedEmail(getLocale(), user); email.addTo(user.getEmail()); diff --git a/pollen-services/src/main/java/org/chorem/pollen/services/service/PollenUserService.java b/pollen-services/src/main/java/org/chorem/pollen/services/service/PollenUserService.java index 9f8c7f0..f62d05f 100644 --- a/pollen-services/src/main/java/org/chorem/pollen/services/service/PollenUserService.java +++ b/pollen-services/src/main/java/org/chorem/pollen/services/service/PollenUserService.java @@ -90,23 +90,19 @@ public class PollenUserService extends PollenServiceSupport implements PollenSer } - public PollenEntityRef<PollenUser> createUser(PollenUserBean user, boolean generatePassword) throws InvalidFormException { + public PollenEntityRef<PollenUser> createUser(PollenUserBean user) throws InvalidFormException { checkNotNull(user); checkIsNotPersisted(user); - if (generatePassword) { - // force not null password - user.setPassword("generate"); - } ErrorMap errorMap = checkPollenUser(user); errorMap.failIfNotEmpty(); - PollenUser result = savePollenUser(user, generatePassword); + PollenUser result = savePollenUser(user); commit(); - getNotificationService().onUserCreated(result, user.getPassword()); + getNotificationService().onUserCreated(result); return PollenEntityRef.of(result); @@ -120,7 +116,7 @@ public class PollenUserService extends PollenServiceSupport implements PollenSer ErrorMap errorMap = checkPollenUser(user); errorMap.failIfNotEmpty(); - PollenUser result = savePollenUser(user, false); + PollenUser result = savePollenUser(user); commit(); getNotificationService().onUserEdited(result); @@ -133,7 +129,7 @@ public class PollenUserService extends PollenServiceSupport implements PollenSer checkNotNull(user); checkIsAdmin(); - PollenUser userSaved = savePollenUser(user, false); + PollenUser userSaved = savePollenUser(user); commit(); getNotificationService().onUserEdited(userSaved); @@ -299,7 +295,7 @@ public class PollenUserService extends PollenServiceSupport implements PollenSer for (PollenUserBean user : listUser) { // create user - PollenEntityRef<PollenUser> newUser = createUser(user, false); + PollenEntityRef<PollenUser> newUser = createUser(user); // validate user PollenUser pollenUser = getPollenUserDao().forTopiaIdEquals(newUser.getEntityId()).findUnique(); @@ -374,7 +370,7 @@ public class PollenUserService extends PollenServiceSupport implements PollenSer } - protected PollenUser savePollenUser(PollenUserBean user, boolean generatePassword) { + protected PollenUser savePollenUser(PollenUserBean user) { boolean userExists = user.isPersisted(); @@ -397,24 +393,12 @@ public class PollenUserService extends PollenServiceSupport implements PollenSer } else { - String password; - - if (generatePassword) { - - password = serviceContext.generatePassword(); - - } else { - - password = user.getPassword(); - - } - PollenToken emailActivation = getSecurityService().generateNewToken(); toSave = getPollenUserDao().create(); toSave.setEmailActivationToken(emailActivation); - getSecurityService().setUserPassword(toSave, password); + getSecurityService().setUserPassword(toSave, user.getPassword()); } diff --git a/pollen-services/src/main/java/org/chorem/pollen/services/service/mail/EmailService.java b/pollen-services/src/main/java/org/chorem/pollen/services/service/mail/EmailService.java index b426262..5549b41 100644 --- a/pollen-services/src/main/java/org/chorem/pollen/services/service/mail/EmailService.java +++ b/pollen-services/src/main/java/org/chorem/pollen/services/service/mail/EmailService.java @@ -177,10 +177,9 @@ public class EmailService extends PollenServiceSupport { return email; } - public UserAccountCreatedEmail newUserAccountCreatedEmail(Locale locale, PollenUser user, String password) { + public UserAccountCreatedEmail newUserAccountCreatedEmail(Locale locale, PollenUser user) { UserAccountCreatedEmail email = new UserAccountCreatedEmail(locale); email.setUser(user); - email.setPassword(password); email.setPollenUrl(getPollenUIUrlRenderService().getPollenUrl()); diff --git a/pollen-services/src/main/resources/email/UserAccountCreatedEmail.mustache b/pollen-services/src/main/resources/email/UserAccountCreatedEmail.mustache index 043c281..c74c09b 100644 --- a/pollen-services/src/main/resources/email/UserAccountCreatedEmail.mustache +++ b/pollen-services/src/main/resources/email/UserAccountCreatedEmail.mustache @@ -3,7 +3,6 @@ Welcome {{user.name}}, You had just created an account on the web application Pollen. Email: {{user.email}} -Password: {{password}} You must validate your email on this url: <a href="{{validateUrl}}">{{vaidateUrl}}</a> diff --git a/pollen-services/src/main/resources/email/UserAccountCreatedEmail_fr.mustache b/pollen-services/src/main/resources/email/UserAccountCreatedEmail_fr.mustache index 85285db..eeb0c7d 100644 --- a/pollen-services/src/main/resources/email/UserAccountCreatedEmail_fr.mustache +++ b/pollen-services/src/main/resources/email/UserAccountCreatedEmail_fr.mustache @@ -3,7 +3,6 @@ Bonjour {{user.name}}, Vous venez de créer un compte sur l'application en ligne Pollen Courriel: {{user.email}} -Password: {{password}} Vous devez valider votre courriel en allant sur cette adresse : <a href="{{validateUrl}}">{{vaidateUrl}}</a> diff --git a/pollen-ui-riot-js/src/main/web/i18n.json b/pollen-ui-riot-js/src/main/web/i18n.json index b515235..59494b2 100644 --- a/pollen-ui-riot-js/src/main/web/i18n.json +++ b/pollen-ui-riot-js/src/main/web/i18n.json @@ -45,9 +45,14 @@ "polls_VOTING": "Vote en cours", "signup_title": "Créer un compte", "signup_email": "Email", - "signup_email_placeholder": "Entrer l'email", + "signup_email_placeholder": "Entrez votre adresse email", "signup_name": "Nom", - "signup_name_placeholder": "Entrer votre nom d'utilisateur", + "signup_name_placeholder": "Entrez votre nom d'utilisateur", + "signup_password": "Mot de passe", + "signup_password_placeholder": "Entrez votre mot de passe", + "signup_repeat_password": "Confirmation du mot de passe", + "signup_repeat_password_placeholder": "Répétez votre mot de passe", + "signup_repeat_password_error": "Les deux mots de passe ne sont pas identiques.", "signup_validate": "Valider", "signup_resendValidation": "Déja inscrit, mais compte non validé ?", "signup_error": "Impossible d'enregister le compte.", @@ -271,6 +276,11 @@ "signup_email_placeholder": "Enter your email", "signup_name": "User name", "signup_name_placeholder": "Entrer your user name", + "signup_password": "Password", + "signup_password_placeholder": "Enter you password", + "signup_repeat_password": "Password confirmation", + "signup_repeat_password_placeholder": "Confirm your password", + "signup_repeat_password_error": "The two passwords are not identical.", "signup_validate": "Create", "signup_resendValidation": "Already member, but account never validated ?", "signup_error": "Could not register account.", @@ -444,4 +454,4 @@ "users_BANNED": "Account banned", "": "" } -} \ No newline at end of file +} diff --git a/pollen-ui-riot-js/src/main/web/js/AuthService.js b/pollen-ui-riot-js/src/main/web/js/AuthService.js index 568f081..bd6502b 100644 --- a/pollen-ui-riot-js/src/main/web/js/AuthService.js +++ b/pollen-ui-riot-js/src/main/web/js/AuthService.js @@ -40,7 +40,7 @@ class AuthService extends FetchService { } signUp(user) { - return this.form("/v1/users", {user: user, generatePassword: true}); + return this.form("/v1/users", {user: user}); } signOut() { diff --git a/pollen-ui-riot-js/src/main/web/tag/SignUp.tag.html b/pollen-ui-riot-js/src/main/web/tag/SignUp.tag.html index def1fae..61c57c4 100644 --- a/pollen-ui-riot-js/src/main/web/tag/SignUp.tag.html +++ b/pollen-ui-riot-js/src/main/web/tag/SignUp.tag.html @@ -32,7 +32,14 @@ require("./popup/AccountCreated.tag.html"); <input class="wide" type="text" name="name" id="name" placeholder="{__.name_placeholder}" required> <label class="wide" for="email">{__.email}</label> <div if="{errors.email}">{errors.email}</div> - <input class="wide" type="text" name="email" id="email" placeholder="{__.email_placeholder}" required> + <input class="wide" type="email" name="email" id="email" placeholder="{__.email_placeholder}" required> + <label class="wide" for="name">{__.password}</label> + <div if="{errors.password}">{errors.password}</div> + <input class="wide" type="password" name="password" id="password" placeholder="{__.password_placeholder}" onblur="{checkPassword}" required> + <label class="wide" for="repeatPassword">{__.repeat_password}</label> + <div if="{errors.repeatPassword}">{errors.repeatPassword}</div> + <input class="wide" type="password" name="repeatPassword" id="repeatPassword" placeholder="{__.repeat_password_placeholder}" + pattern="{refs.user.password.value}" required onblur="{checkPassword}" onkeypress="{clearPasswordError}"> <a onclick="{resendValidation}">{__.resendValidation}</a> <br/> <input type="submit" class="button" value="{__.validate}"> @@ -55,7 +62,7 @@ require("./popup/AccountCreated.tag.html"); }); this.installBundle(session, "signup"); - this.errors = ""; + this.errors = {}; this.resendValidation = () => { this.validate = true; @@ -65,7 +72,7 @@ require("./popup/AccountCreated.tag.html"); e.preventDefault(); e.stopPropagation(); - this.errors = ""; + this.errors = {}; let user = FormHelper.formToMap(this.refs.user); authService.signUp(user) @@ -78,6 +85,21 @@ require("./popup/AccountCreated.tag.html"); }); }; + this.checkPassword = () => { + var password = this.refs.user.password.value; + var repeatPassword = this.refs.user.repeatPassword.value; + + if (repeatPassword && password !== repeatPassword) { + this.errors.repeatPassword = this._l("repeat_password_error"); + } else { + delete this.errors.repeatPassword; + } + }; + + this.clearPasswordError = () => { + delete this.errors.repeatPassword; + }; + if (this.opts.validate) { this.resendValidation(); } -- To stop receiving notification emails like this one, please contact chorem.org SCM administrator <admin+scm@chorem.org>.
This is an automated email from the git hooks/post-receive script. New commit to branch feature/add_password_to_registration in repository pollen. See https://gitlab.nuiton.org/chorem/pollen.git commit 9002c6700f143b83ed0409f8e1cc5e4ab7dd601d Author: Kevin Morin <morin@codelutin.com> Date: Tue Feb 28 17:09:25 2017 +0100 refs #6 passage des urls du front au back pour l'email d'inscription --- .../java/org/chorem/pollen/rest/api/v1/PollenUserApi.java | 6 ++++-- .../pollen/services/service/NotificationService.java | 8 ++++---- .../pollen/services/service/PollenUIUrlRenderService.java | 6 +++--- .../chorem/pollen/services/service/PollenUserService.java | 10 +++++----- .../chorem/pollen/services/service/mail/EmailService.java | 14 +++++++------- pollen-ui-riot-js/src/main/web/conf.js | 3 ++- pollen-ui-riot-js/src/main/web/js/AuthService.js | 6 +++++- 7 files changed, 30 insertions(+), 23 deletions(-) diff --git a/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/PollenUserApi.java b/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/PollenUserApi.java index 237631d..418b0ac 100644 --- a/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/PollenUserApi.java +++ b/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/PollenUserApi.java @@ -65,9 +65,11 @@ public class PollenUserApi extends WebMotionController { } public PollenEntityRef<PollenUser> createUser(PollenUserService pollenUserService, - PollenUserBean user) throws InvalidFormException { + PollenUserBean user, + String pollenUrl, + String validateUrl) throws InvalidFormException { - return pollenUserService.createUser(user); + return pollenUserService.createUser(user, pollenUrl, validateUrl); } diff --git a/pollen-services/src/main/java/org/chorem/pollen/services/service/NotificationService.java b/pollen-services/src/main/java/org/chorem/pollen/services/service/NotificationService.java index e53bc32..170eae1 100644 --- a/pollen-services/src/main/java/org/chorem/pollen/services/service/NotificationService.java +++ b/pollen-services/src/main/java/org/chorem/pollen/services/service/NotificationService.java @@ -42,10 +42,10 @@ import org.chorem.pollen.services.service.mail.UserAccountCreatedEmail; */ public class NotificationService extends PollenServiceSupport { - public void onUserCreated(PollenUser user) { + public void onUserCreated(PollenUser user, String pollenUrl, String validateUrl) { EmailService emailService = getEmailService(); - UserAccountCreatedEmail email = emailService.newUserAccountCreatedEmail(getLocale(), user); + UserAccountCreatedEmail email = emailService.newUserAccountCreatedEmail(user, pollenUrl, validateUrl); email.addTo(user.getEmail()); @@ -53,10 +53,10 @@ public class NotificationService extends PollenServiceSupport { } - public void onResendValidation(PollenUser user) { + public void onResendValidation(PollenUser user, String pollenUrl, String validateUrl) { EmailService emailService = getEmailService(); - ResendValidationEmail email = emailService.newUserResendValidationEmail(user); + ResendValidationEmail email = emailService.newUserResendValidationEmail(user, pollenUrl, validateUrl); email.addTo(user.getEmail()); emailService.send(email); diff --git a/pollen-services/src/main/java/org/chorem/pollen/services/service/PollenUIUrlRenderService.java b/pollen-services/src/main/java/org/chorem/pollen/services/service/PollenUIUrlRenderService.java index 65271ca..a9aae35 100644 --- a/pollen-services/src/main/java/org/chorem/pollen/services/service/PollenUIUrlRenderService.java +++ b/pollen-services/src/main/java/org/chorem/pollen/services/service/PollenUIUrlRenderService.java @@ -81,13 +81,13 @@ public class PollenUIUrlRenderService extends PollenServiceSupport { return url; } - public String getUserValidateUrl(String userId, String token) { + public String getUserValidateUrl(String validateUrl, String userId, String token) { checkNotNull(userId); checkNotNull(token); - String url = serviceContext.getPollenServicesConfig().getUiUrlUserValidate().toString(); +// String url = serviceContext.getPollenServicesConfig().getUiUrlUserValidate().toString(); - url = url.replace("{userId}", userId); + String url = validateUrl.replace("{userId}", userId); url = url.replace("{token}", token); return url; diff --git a/pollen-services/src/main/java/org/chorem/pollen/services/service/PollenUserService.java b/pollen-services/src/main/java/org/chorem/pollen/services/service/PollenUserService.java index f62d05f..9d8aa64 100644 --- a/pollen-services/src/main/java/org/chorem/pollen/services/service/PollenUserService.java +++ b/pollen-services/src/main/java/org/chorem/pollen/services/service/PollenUserService.java @@ -90,7 +90,7 @@ public class PollenUserService extends PollenServiceSupport implements PollenSer } - public PollenEntityRef<PollenUser> createUser(PollenUserBean user) throws InvalidFormException { + public PollenEntityRef<PollenUser> createUser(PollenUserBean user, String pollenUrl, String validateUrl) throws InvalidFormException { checkNotNull(user); checkIsNotPersisted(user); @@ -102,7 +102,7 @@ public class PollenUserService extends PollenServiceSupport implements PollenSer PollenUser result = savePollenUser(user); commit(); - getNotificationService().onUserCreated(result); + getNotificationService().onUserCreated(result, pollenUrl, validateUrl); return PollenEntityRef.of(result); @@ -247,7 +247,7 @@ public class PollenUserService extends PollenServiceSupport implements PollenSer } - public void resendValidation(String email) { + public void resendValidation(String email, String pollenUrl, String validateUrl) { checkNotNull(email); PollenUser user = getPollenUserDao().forEmailEquals(email).findUniqueOrNull(); @@ -260,7 +260,7 @@ public class PollenUserService extends PollenServiceSupport implements PollenSer commit(); } - getNotificationService().onResendValidation(user); + getNotificationService().onResendValidation(user, pollenUrl, validateUrl); } @@ -295,7 +295,7 @@ public class PollenUserService extends PollenServiceSupport implements PollenSer for (PollenUserBean user : listUser) { // create user - PollenEntityRef<PollenUser> newUser = createUser(user); + PollenEntityRef<PollenUser> newUser = createUser(user, "", ""); // validate user PollenUser pollenUser = getPollenUserDao().forTopiaIdEquals(newUser.getEntityId()).findUnique(); diff --git a/pollen-services/src/main/java/org/chorem/pollen/services/service/mail/EmailService.java b/pollen-services/src/main/java/org/chorem/pollen/services/service/mail/EmailService.java index 5549b41..3c4d94a 100644 --- a/pollen-services/src/main/java/org/chorem/pollen/services/service/mail/EmailService.java +++ b/pollen-services/src/main/java/org/chorem/pollen/services/service/mail/EmailService.java @@ -177,31 +177,31 @@ public class EmailService extends PollenServiceSupport { return email; } - public UserAccountCreatedEmail newUserAccountCreatedEmail(Locale locale, PollenUser user) { - UserAccountCreatedEmail email = new UserAccountCreatedEmail(locale); + public UserAccountCreatedEmail newUserAccountCreatedEmail(PollenUser user, String pollenUrl, String validateUrl) { + UserAccountCreatedEmail email = new UserAccountCreatedEmail(getLocale()); email.setUser(user); - email.setPollenUrl(getPollenUIUrlRenderService().getPollenUrl()); + email.setPollenUrl(pollenUrl); PollenEntityId<PollenUser> userId = PollenEntityId.newId(PollenUser.class); userId.setEntityId(user.getTopiaId()); userId.encode(serviceContext.getTopiaApplicationContext().getTopiaIdFactory()); - email.setValidateUrl(getPollenUIUrlRenderService().getUserValidateUrl(userId.getReducedId(), user.getEmailActivationToken().getToken())); + email.setValidateUrl(getPollenUIUrlRenderService().getUserValidateUrl(validateUrl, userId.getReducedId(), user.getEmailActivationToken().getToken())); return email; } - public ResendValidationEmail newUserResendValidationEmail(PollenUser user) { + public ResendValidationEmail newUserResendValidationEmail(PollenUser user, String pollenUrl, String validateUrl) { ResendValidationEmail email = new ResendValidationEmail(getLocale()); email.setUser(user); - email.setPollenUrl(getPollenUIUrlRenderService().getPollenUrl()); + email.setPollenUrl(pollenUrl); PollenEntityId<PollenUser> userId = PollenEntityId.newId(PollenUser.class); userId.setEntityId(user.getTopiaId()); userId.encode(serviceContext.getTopiaApplicationContext().getTopiaIdFactory()); - email.setValidateUrl(getPollenUIUrlRenderService().getUserValidateUrl(userId.getReducedId(), user.getEmailActivationToken().getToken())); + email.setValidateUrl(getPollenUIUrlRenderService().getUserValidateUrl(validateUrl, userId.getReducedId(), user.getEmailActivationToken().getToken())); return email; } diff --git a/pollen-ui-riot-js/src/main/web/conf.js b/pollen-ui-riot-js/src/main/web/conf.js index 1a1424f..c14ef02 100644 --- a/pollen-ui-riot-js/src/main/web/conf.js +++ b/pollen-ui-riot-js/src/main/web/conf.js @@ -11,5 +11,6 @@ window.pollenConf = { defaultDateFormat: "shortDate", defaultTimeFormat: "shortTime", defaultDateTimeFormat: "short", - debugI18n: false + debugI18n: false, + pollenUiUrl: "http://localhost:8080" }; diff --git a/pollen-ui-riot-js/src/main/web/js/AuthService.js b/pollen-ui-riot-js/src/main/web/js/AuthService.js index bd6502b..e20bafb 100644 --- a/pollen-ui-riot-js/src/main/web/js/AuthService.js +++ b/pollen-ui-riot-js/src/main/web/js/AuthService.js @@ -40,7 +40,11 @@ class AuthService extends FetchService { } signUp(user) { - return this.form("/v1/users", {user: user}); + return this.form("/v1/users", { + user: user, + pollenUrl: this.session.configuration.pollenUiUrl, + validateUrl: this.session.configuration.pollenUiUrl + "/#signcheck/{userId}/{token}" + }); } signOut() { -- To stop receiving notification emails like this one, please contact chorem.org SCM administrator <admin+scm@chorem.org>.
participants (1)
-
chorem.org scm