branch feature/1_socialauth updated (aa859951 -> d545965b)
This is an automated email from the git hooks/post-receive script. New change to branch feature/1_socialauth in repository pollen. See https://gitlab.nuiton.org/chorem/pollen.git omits aa859951 refs #1 séparaion des langues omits f4cb642f refs #1 gestion de la suppression des credentials omits 6e891e73 refs #1 mise en page des comptes externes dans le profil omits 8e108414 fix build omits 0975e601 refs #1 ajout de credentials depuis le profil omits ef68f13e refs #1 permettre d'ajouter des comptes tiers à un compte existant omits 1a386c04 refs #1 permettre l'ajout d'un mot de passe à des comptes créés à partir de service tiers omits 01639cf5 refs #1 envoi d'un mail à la création d'un compte a partir d'un service tiers omits a32cf352 refs #1 erreur si l'utilisateur veut se connecter via un service tiers et que son email est deja utilisé par un autre compte Pollen omits a63cca0d refs #1 gestion des tiers de connexion + style du login omits 40bb3dc9 refs #1 ajout du socialmanager dans la session en attendant le retour du provider + gestion des tiers de connexion + gestion des comptes sans email omits 9ec9ff65 refs #1 ajout de la conf des providers dans la base (plus simple à modifier) + début de l'admin omits 3d3db40b refs #1 connexion avec google omits c581c872 refs #1 utilisation de la lib socialauth pour se connecter via des services tiers omits 6e63e1c4 refs #1 ajout des credentials sur le user adds 00f2c6af Pour les participant d'un sondage, ne pas proposer d'inporter une list de favoris si l'utilisateur n'en a pas définis (ref #132) new ea9adfde refs #1 ajout des credentials sur le user new 64cc7bbc refs #1 utilisation de la lib socialauth pour se connecter via des services tiers new 253dd540 refs #1 connexion avec google new b5c67229 refs #1 ajout de la conf des providers dans la base (plus simple à modifier) + début de l'admin new 62201ae0 refs #1 ajout du socialmanager dans la session en attendant le retour du provider + gestion des tiers de connexion + gestion des comptes sans email new cfa63ad2 refs #1 gestion des tiers de connexion + style du login new d3f0f3dc refs #1 erreur si l'utilisateur veut se connecter via un service tiers et que son email est deja utilisé par un autre compte Pollen new 1cbe1725 refs #1 envoi d'un mail à la création d'un compte a partir d'un service tiers new 71bf5022 refs #1 permettre l'ajout d'un mot de passe à des comptes créés à partir de service tiers new 160da205 refs #1 permettre d'ajouter des comptes tiers à un compte existant new dee2bf14 refs #1 ajout de credentials depuis le profil new aacfec6e fix build new e36db9ab refs #1 mise en page des comptes externes dans le profil new b34a7a02 refs #1 gestion de la suppression des credentials new d545965b refs #1 séparaion des langues This update added new revisions after undoing existing revisions. That is to say, some revisions that were in the old version of the branch are not in the new version. This situation occurs when a user --force pushes a change and generates a repository containing something like this: * -- * -- B -- O -- O -- O (aa859951) \ N -- N -- N refs/heads/feature/1_socialauth (d545965b) You should already have received notification emails for all of the O revisions, and so the following emails describe only the N revisions from the common base, B. Any revisions marked "omits" are not gone; other references still refer to them. Any revisions marked "discards" are gone forever. The 15 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 d545965b3d120aff578b104343582cd7a955fe8c Author: Kevin Morin <morin@codelutin.com> Date: Thu Sep 7 11:22:15 2017 +0200 refs #1 séparaion des langues commit b34a7a0268cb8d062d8ac3161ea90ece5d7000de Author: Kevin Morin <morin@codelutin.com> Date: Thu Sep 7 11:01:10 2017 +0200 refs #1 gestion de la suppression des credentials commit e36db9ab487847ece02d8a6a3fd4a8e31bf7a2e9 Author: Kevin Morin <morin@codelutin.com> Date: Thu Sep 7 10:48:45 2017 +0200 refs #1 mise en page des comptes externes dans le profil commit aacfec6e28d17fea5a2904b6ce2fbbf6de70246c Author: Kevin Morin <morin@codelutin.com> Date: Tue Sep 5 16:48:06 2017 +0200 fix build commit dee2bf14ea4cd597c5a2979f01c476f1c1180145 Author: Kevin Morin <morin@codelutin.com> Date: Tue Sep 5 16:08:48 2017 +0200 refs #1 ajout de credentials depuis le profil commit 160da205f1bc5ecd8e6bef0ca67eaf3c7ab23c4e Author: Kevin Morin <morin@codelutin.com> Date: Mon Sep 4 15:21:58 2017 +0200 refs #1 permettre d'ajouter des comptes tiers à un compte existant commit 71bf50224f98ada5869279d08ddbaa50f16a178f Author: Kevin Morin <morin@codelutin.com> Date: Thu Aug 31 16:08:45 2017 +0200 refs #1 permettre l'ajout d'un mot de passe à des comptes créés à partir de service tiers commit 1cbe17251adbc04d3e48034963e7eff806d72c7d Author: Kevin Morin <morin@codelutin.com> Date: Thu Aug 31 14:57:45 2017 +0200 refs #1 envoi d'un mail à la création d'un compte a partir d'un service tiers commit d3f0f3dc910239e807543126e0daa63a00dc13f3 Author: Kevin Morin <morin@codelutin.com> Date: Tue Aug 29 17:57:01 2017 +0200 refs #1 erreur si l'utilisateur veut se connecter via un service tiers et que son email est deja utilisé par un autre compte Pollen commit cfa63ad271f28017e49cfbdc491a185ca23ba32b Author: Kevin Morin <morin@codelutin.com> Date: Fri Aug 25 18:04:36 2017 +0200 refs #1 gestion des tiers de connexion + style du login commit 62201ae0f5b3019ed7bd593200a4d24eb1f65556 Author: Kevin Morin <morin@codelutin.com> Date: Fri Aug 25 18:03:46 2017 +0200 refs #1 ajout du socialmanager dans la session en attendant le retour du provider + gestion des tiers de connexion + gestion des comptes sans email commit b5c672295a2136dcaf2dad7c94588eac62996ca7 Author: Kevin Morin <morin@codelutin.com> Date: Thu Aug 24 17:35:35 2017 +0200 refs #1 ajout de la conf des providers dans la base (plus simple à modifier) + début de l'admin commit 253dd540dc6315482fd9cb4a88026b9e36688ef2 Author: Kevin Morin <morin@codelutin.com> Date: Thu Aug 24 11:05:45 2017 +0200 refs #1 connexion avec google commit 64cc7bbcbd6bfec6dfcd278de20295354a9fc43e Author: Kevin Morin <morin@codelutin.com> Date: Fri Aug 11 17:52:32 2017 +0200 refs #1 utilisation de la lib socialauth pour se connecter via des services tiers commit ea9adfdeef6f6b852daeba235c7bd9452691d2dc Author: Kevin Morin <morin@codelutin.com> Date: Fri Aug 11 17:52:10 2017 +0200 refs #1 ajout des credentials sur le user Summary of changes: pollen-ui-riot-js/src/main/web/i18n/en.json | 1 - pollen-ui-riot-js/src/main/web/i18n/fr.json | 1 - .../tag/voterList/ImportFavoritListModal.tag.html | 29 +++++----------------- .../src/main/web/tag/voterList/VoterList.tag.html | 25 ++++++++++++++++--- .../i18n/pollen-votecounting-api_fr_FR.properties | 2 +- 5 files changed, 28 insertions(+), 30 deletions(-) -- 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/1_socialauth in repository pollen. See https://gitlab.nuiton.org/chorem/pollen.git commit b5c672295a2136dcaf2dad7c94588eac62996ca7 Author: Kevin Morin <morin@codelutin.com> Date: Thu Aug 24 17:35:35 2017 +0200 refs #1 ajout de la conf des providers dans la base (plus simple à modifier) + début de l'admin --- .../migration/h2/V3_0_0_9__add_loginproviders.sql | 13 +++ .../postgresql/V3_0_0_9__add_loginproviders.sql | 12 +++ pollen-persistence/src/main/xmi/pollen.properties | 2 +- pollen-persistence/src/main/xmi/pollen.zargo | Bin 27595 -> 28069 bytes .../org/chorem/pollen/rest/api/v1/AuthApi.java | 28 +++++++ .../pollen/services/bean/LoginProviderBean.java | 82 ++++++++++++++++++ .../services/service/PollenServiceSupport.java | 5 ++ .../pollen/services/service/SocialAuthService.java | 63 ++++++++++++++ .../src/main/resources/oauth_consumer.properties | 56 ++++++------- pollen-ui-riot-js/src/main/web/js/AuthService.js | 15 +++- pollen-ui-riot-js/src/main/web/tag/Pollen.tag.html | 8 +- .../src/main/web/tag/PollenHeader.tag.html | 1 + pollen-ui-riot-js/src/main/web/tag/SignIn.tag.html | 12 ++- .../src/main/web/tag/admin/LoginProviders.tag.html | 92 +++++++++++++++++++++ .../src/main/web/tag/{ => admin}/UserCard.tag.html | 6 +- .../web/tag/{ => admin}/UserEditModal.tag.html | 8 +- .../src/main/web/tag/{ => admin}/Users.tag.html | 10 +-- 17 files changed, 367 insertions(+), 46 deletions(-) diff --git a/pollen-persistence/src/main/resources/db/migration/h2/V3_0_0_9__add_loginproviders.sql b/pollen-persistence/src/main/resources/db/migration/h2/V3_0_0_9__add_loginproviders.sql new file mode 100644 index 00000000..1a3adce2 --- /dev/null +++ b/pollen-persistence/src/main/resources/db/migration/h2/V3_0_0_9__add_loginproviders.sql @@ -0,0 +1,13 @@ +-- LOGINPROVIDER + +CREATE TABLE LOGINPROVIDER ( + TOPIAID VARCHAR(255) NOT NULL PRIMARY KEY, + TOPIAVERSION BIGINT NOT NULL, + TOPIACREATEDATE TIMESTAMP, + NAME VARCHAR(255), + KEY VARCHAR(255), + SECRET VARCHAR(255), + PERMISSIONS VARCHAR(255), + ACTIVE BOOLEAN +); + diff --git a/pollen-persistence/src/main/resources/db/migration/postgresql/V3_0_0_9__add_loginproviders.sql b/pollen-persistence/src/main/resources/db/migration/postgresql/V3_0_0_9__add_loginproviders.sql new file mode 100644 index 00000000..75a094ea --- /dev/null +++ b/pollen-persistence/src/main/resources/db/migration/postgresql/V3_0_0_9__add_loginproviders.sql @@ -0,0 +1,12 @@ +-- LOGINPROVIDER + +CREATE TABLE LOGINPROVIDER ( + TOPIAID VARCHAR(255) NOT NULL PRIMARY KEY, + TOPIAVERSION BIGINT NOT NULL, + TOPIACREATEDATE TIMESTAMP, + NAME VARCHAR(255), + KEY VARCHAR(255), + SECRET VARCHAR(255), + PERMISSIONS VARCHAR(255), + ACTIVE BOOLEAN +); diff --git a/pollen-persistence/src/main/xmi/pollen.properties b/pollen-persistence/src/main/xmi/pollen.properties index 16d95ab4..d172fe4c 100644 --- a/pollen-persistence/src/main/xmi/pollen.properties +++ b/pollen-persistence/src/main/xmi/pollen.properties @@ -18,7 +18,7 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. # #L% ###m -model.tagvalue.version=3.0.0.8 +model.tagvalue.version=3.0.0.9 #model.tagValue.notGenerateToString=true #model.tagValue.constantPrefix=PROPERTY_ #model.tagValue.useEnumerationName=true diff --git a/pollen-persistence/src/main/xmi/pollen.zargo b/pollen-persistence/src/main/xmi/pollen.zargo index 72886764..0f29e782 100644 Binary files a/pollen-persistence/src/main/xmi/pollen.zargo and b/pollen-persistence/src/main/xmi/pollen.zargo differ diff --git a/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/AuthApi.java b/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/AuthApi.java index 7a7b74bb..748dc894 100644 --- a/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/AuthApi.java +++ b/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/AuthApi.java @@ -29,6 +29,7 @@ import org.apache.shiro.codec.Base64; import org.chorem.pollen.persistence.entity.PollenUser; import org.chorem.pollen.persistence.entity.SessionToken; import org.chorem.pollen.services.PollenServiceContext; +import org.chorem.pollen.services.bean.LoginProviderBean; import org.chorem.pollen.services.bean.PollenEntityRef; import org.chorem.pollen.services.service.PollenUserService; import org.chorem.pollen.services.service.SocialAuthService; @@ -55,6 +56,7 @@ import javax.ws.rs.core.MediaType; import javax.ws.rs.core.NewCookie; import javax.ws.rs.core.Response; import java.net.URI; +import java.util.List; import java.util.Map; /** @@ -248,4 +250,30 @@ public class AuthApi { } + @Path("/loginproviders") + @GET + public List<LoginProviderBean> getAllLoginProviders(@Context SocialAuthService socialAuthService) { + return socialAuthService.getAllLoginProviders(); + } + + @Path("/loginproviders") + @POST + public LoginProviderBean addLoginProvider(@Context SocialAuthService socialAuthService, + LoginProviderBean loginProvider) { + return socialAuthService.saveLoginProvider(loginProvider, false); + } + + @Path("/loginproviders/{providerId}") + @POST @PUT + public LoginProviderBean saveLoginProvider(@Context SocialAuthService socialAuthService, + LoginProviderBean loginProvider) { + return socialAuthService.saveLoginProvider(loginProvider, true); + } + + @Path("/loginproviders/active") + @GET + public List<String> getAvailableLoginProviders(@Context SocialAuthService socialAuthService) { + return socialAuthService.getAvailableLoginProviders(); + } + } diff --git a/pollen-services/src/main/java/org/chorem/pollen/services/bean/LoginProviderBean.java b/pollen-services/src/main/java/org/chorem/pollen/services/bean/LoginProviderBean.java new file mode 100644 index 00000000..e24d2d19 --- /dev/null +++ b/pollen-services/src/main/java/org/chorem/pollen/services/bean/LoginProviderBean.java @@ -0,0 +1,82 @@ +package org.chorem.pollen.services.bean; + +import org.chorem.pollen.persistence.entity.LoginProvider; +import org.chorem.pollen.persistence.entity.LoginProviderImpl; + +/** + * @author Kevin Morin (Code Lutin) + */ +public class LoginProviderBean extends PollenBean<LoginProvider> { + + protected String name; + protected String key; + protected String secret; + protected String permissions; + protected boolean active; + + public LoginProviderBean() { + super(LoginProvider.class); + } + + @Override + public void fromEntity(LoginProvider entity) { + setEntityId(entity.getTopiaId()); + setName(entity.getName()); + setKey(entity.getKey()); + setSecret(entity.getSecret()); + setPermissions(entity.getPermissions()); + setActive(entity.isActive()); + } + + @Override + public LoginProvider toEntity() { + LoginProvider entity = new LoginProviderImpl(); + entity.setTopiaId(getEntityId()); + entity.setName(getName()); + entity.setKey(getKey()); + entity.setSecret(getSecret()); + entity.setPermissions(getPermissions()); + entity.setActive(isActive()); + return entity; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getKey() { + return key; + } + + public void setKey(String key) { + this.key = key; + } + + public String getSecret() { + return secret; + } + + public void setSecret(String secret) { + this.secret = secret; + } + + public String getPermissions() { + return permissions; + } + + public void setPermissions(String permissions) { + this.permissions = permissions; + } + + public boolean isActive() { + return active; + } + + public void setActive(boolean active) { + this.active = active; + } +} diff --git a/pollen-services/src/main/java/org/chorem/pollen/services/service/PollenServiceSupport.java b/pollen-services/src/main/java/org/chorem/pollen/services/service/PollenServiceSupport.java index c26c5f50..860e0266 100644 --- a/pollen-services/src/main/java/org/chorem/pollen/services/service/PollenServiceSupport.java +++ b/pollen-services/src/main/java/org/chorem/pollen/services/service/PollenServiceSupport.java @@ -33,6 +33,7 @@ import org.chorem.pollen.persistence.entity.ChoiceTopiaDao; import org.chorem.pollen.persistence.entity.CommentTopiaDao; import org.chorem.pollen.persistence.entity.FavoriteListMemberTopiaDao; import org.chorem.pollen.persistence.entity.FavoriteListTopiaDao; +import org.chorem.pollen.persistence.entity.LoginProviderTopiaDao; import org.chorem.pollen.persistence.entity.Poll; import org.chorem.pollen.persistence.entity.PollTopiaDao; import org.chorem.pollen.persistence.entity.PollenPrincipalTopiaDao; @@ -242,6 +243,10 @@ public abstract class PollenServiceSupport implements PollenService { return getPersistenceContext().getVoterListMemberDao(); } + protected LoginProviderTopiaDao getLoginProviderDao() { + return getPersistenceContext().getLoginProviderDao(); + } + public void commit() { getPersistenceContext().commit(); } diff --git a/pollen-services/src/main/java/org/chorem/pollen/services/service/SocialAuthService.java b/pollen-services/src/main/java/org/chorem/pollen/services/service/SocialAuthService.java index 6866b3b5..2d4aa50f 100644 --- a/pollen-services/src/main/java/org/chorem/pollen/services/service/SocialAuthService.java +++ b/pollen-services/src/main/java/org/chorem/pollen/services/service/SocialAuthService.java @@ -1,5 +1,6 @@ package org.chorem.pollen.services.service; +import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.brickred.socialauth.AuthProvider; @@ -7,15 +8,22 @@ import org.brickred.socialauth.Profile; import org.brickred.socialauth.SocialAuthConfig; import org.brickred.socialauth.SocialAuthManager; import org.brickred.socialauth.util.Constants; +import org.brickred.socialauth.util.OAuthConfig; +import org.chorem.pollen.persistence.entity.LoginProvider; +import org.chorem.pollen.persistence.entity.LoginProviderTopiaDao; import org.chorem.pollen.persistence.entity.PollenUser; import org.chorem.pollen.persistence.entity.PollenUserImpl; import org.chorem.pollen.persistence.entity.PollenUserTopiaDao; import org.chorem.pollen.persistence.entity.UserCredential; import org.chorem.pollen.persistence.entity.UserCredentialImpl; +import org.chorem.pollen.services.bean.LoginProviderBean; import org.chorem.pollen.services.bean.PollenEntityRef; +import java.util.Comparator; +import java.util.List; import java.util.Map; import java.util.Optional; +import java.util.stream.Collectors; /** * @author Kevin Morin (Code Lutin) @@ -90,6 +98,22 @@ public class SocialAuthService extends PollenServiceSupport { //Create an instance of SocialAuthConfgi object SocialAuthConfig config = SocialAuthConfig.getDefault(); + List<LoginProvider> allActiveProviders = getLoginProviderDao().forActiveEquals(true).findAll(); + allActiveProviders.forEach(provider -> { + try { + OAuthConfig providerConfig = new OAuthConfig(provider.getKey(), provider.getSecret()); + if (StringUtils.isNotBlank(provider.getPermissions())) { + providerConfig.setCustomPermissions(provider.getPermissions()); + } + config.addProviderConfig(provider.getName(), providerConfig); + + } catch (Exception e) { + if (log.isErrorEnabled()) { + log.error("Error while adding config for provider " + provider.getName(), e); + } + } + }); + //load configuration. By default load the configuration from oauth_consumer.properties. //You can also pass input stream, properties object or properties file name. config.load(); @@ -100,4 +124,43 @@ public class SocialAuthService extends PollenServiceSupport { return manager; } + + public List<LoginProviderBean> getAllLoginProviders() { + checkIsAdmin(); + LoginProviderTopiaDao dao = getLoginProviderDao(); + List<LoginProvider> loginProviders = dao.findAll().stream() + .sorted(Comparator.comparing(LoginProvider::getName)) + .collect(Collectors.toList()); + return toBeanList(LoginProviderBean.class, loginProviders); + } + + public List<String> getAvailableLoginProviders() { + LoginProviderTopiaDao dao = getLoginProviderDao(); + return dao.forActiveEquals(true).findAll().stream() + .map(LoginProvider::getName) + .sorted() + .collect(Collectors.toList()); + } + + public LoginProviderBean saveLoginProvider(LoginProviderBean loginProvider, boolean loginProviderExists) { + checkIsAdmin(); + checkNotNull(loginProvider); + LoginProviderTopiaDao dao = getLoginProviderDao(); + + LoginProvider toSave; + + if (loginProviderExists) { + toSave = dao.forTopiaIdEquals(loginProvider.getEntityId()).findUnique(); + } else { + toSave = dao.create(); + } + toSave.setName(loginProvider.getName()); + toSave.setKey(loginProvider.getKey()); + toSave.setSecret(loginProvider.getSecret()); + toSave.setPermissions(loginProvider.getPermissions()); + toSave.setActive(loginProvider.isActive()); + + commit(); + return toBean(LoginProviderBean.class, toSave); + } } diff --git a/pollen-services/src/main/resources/oauth_consumer.properties b/pollen-services/src/main/resources/oauth_consumer.properties index 6f015cc3..02f55921 100644 --- a/pollen-services/src/main/resources/oauth_consumer.properties +++ b/pollen-services/src/main/resources/oauth_consumer.properties @@ -1,6 +1,6 @@ #google -www.google.com.consumer_key = opensource.brickred.com -www.google.com.consumer_secret = YC06FqhmCLWvtBg/O4W/aJfj +#www.google.com.consumer_key = opensource.brickred.com +#www.google.com.consumer_secret = YC06FqhmCLWvtBg/O4W/aJfj #you can set custom permission by using custom_permissions with provider prefix. #www.google.com.custom_permissions = http://www.google.com/m8/feeds/,http://picasaweb.google.com/data/ @@ -13,44 +13,44 @@ www.google.com.consumer_secret = YC06FqhmCLWvtBg/O4W/aJfj #New registration on google will always provide OAuth2 keys which is supported by GooglePlus provider #google plus -googleapis.com.consumer_key = XXXXXXX -googleapis.com.consumer_secret = XXXXXXXX +#googleapis.com.consumer_key = XXXXXXX +#googleapis.com.consumer_secret = XXXXXXXX #yahoo -api.login.yahoo.com.consumer_key = dj0yJmk9VTdaSUVTU3RrWlRzJmQ9WVdrOWNtSjZNMFpITm1VbWNHbzlNQS0tJnM9Y29uc3VtZXJzZWNyZXQmeD1iMA-- -api.login.yahoo.com.consumer_secret = 1db3d0b897dac60e151aa9e2499fcb2a6b474546 +#api.login.yahoo.com.consumer_key = dj0yJmk9VTdaSUVTU3RrWlRzJmQ9WVdrOWNtSjZNMFpITm1VbWNHbzlNQS0tJnM9Y29uc3VtZXJzZWNyZXQmeD1iMA-- +#api.login.yahoo.com.consumer_secret = 1db3d0b897dac60e151aa9e2499fcb2a6b474546 #twitter -twitter.com.consumer_key = E3hm7J9IQbWLijpiQG7W8Q -twitter.com.consumer_secret = SGKNuXyybt0iDdgsuzVbFHOaemV7V6pr0wKwbaT2MH0 +#twitter.com.consumer_key = E3hm7J9IQbWLijpiQG7W8Q +#twitter.com.consumer_secret = SGKNuXyybt0iDdgsuzVbFHOaemV7V6pr0wKwbaT2MH0 #facebook -graph.facebook.com.consumer_key = 152190004803645 -graph.facebook.com.consumer_secret = 64c94bd02180b0ade85889b44b2ba7c4 +#graph.facebook.com.consumer_key = 152190004803645 +#graph.facebook.com.consumer_secret = 64c94bd02180b0ade85889b44b2ba7c4 #you can set custom permission by using custom_permissions with provider prefix. #graph.facebook.com.custom_permissions = publish_stream,email,user_birthday,user_location,offline_access #hotmail -consent.live.com.consumer_key = 000000004403D60E -consent.live.com.consumer_secret = cYqlii67pTvgPD4pdB7NUVC7L4MIHCcs +#consent.live.com.consumer_key = 000000004403D60E +#consent.live.com.consumer_secret = cYqlii67pTvgPD4pdB7NUVC7L4MIHCcs #Same keys will work for Linkedin OAuth2 provider #LinkedIn -api.linkedin.com.consumer_key = 9-mmqg28fpMocVuAg87exH-RXKs70yms52GSFIqkZN25S3m96kdPGBbuSxdSBIyL -api.linkedin.com.consumer_secret = e6NBqhDYE1fX17RwYGW5vMp25Cvh7Sbw9t-zMYTIW_T5LytY5OwJ12snh_YftgE4 +#api.linkedin.com.consumer_key = 9-mmqg28fpMocVuAg87exH-RXKs70yms52GSFIqkZN25S3m96kdPGBbuSxdSBIyL +#api.linkedin.com.consumer_secret = e6NBqhDYE1fX17RwYGW5vMp25Cvh7Sbw9t-zMYTIW_T5LytY5OwJ12snh_YftgE4 #MySpace -api.myspace.com.consumer_key = 29db395f5ee8426bb90b1db65c91c956 -api.myspace.com.consumer_secret = 0fdccc829c474e42867e16b68cda37a4c4b7b08eda574fe6a959943e3e9be709 +#api.myspace.com.consumer_key = 29db395f5ee8426bb90b1db65c91c956 +#api.myspace.com.consumer_secret = 0fdccc829c474e42867e16b68cda37a4c4b7b08eda574fe6a959943e3e9be709 #FourSquare -foursquare.com.consumer_key = JQKEM1PHWFW4YF2YPEQBRRESXE3SBGNCYJWWDTZKF3IZNJ3V -foursquare.com.consumer_secret = 4IILLDFDVPP2LC554S4KXKETQNTDKPDSEVCKVHA2QEHKYBEQ +#foursquare.com.consumer_key = JQKEM1PHWFW4YF2YPEQBRRESXE3SBGNCYJWWDTZKF3IZNJ3V +#foursquare.com.consumer_secret = 4IILLDFDVPP2LC554S4KXKETQNTDKPDSEVCKVHA2QEHKYBEQ #Yammer -www.yammer.com.consumer_key=5zyIkp12TrkulSRbSegQ -www.yammer.com.consumer_secret=zUcCB9kqWhI1IiTAJbl9QdG2AWcUJMDWp3Qyv5VJJw +#www.yammer.com.consumer_key=5zyIkp12TrkulSRbSegQ +#www.yammer.com.consumer_secret=zUcCB9kqWhI1IiTAJbl9QdG2AWcUJMDWp3Qyv5VJJw #Please use your own keys for mendeley #Mendeley @@ -58,20 +58,20 @@ www.yammer.com.consumer_secret=zUcCB9kqWhI1IiTAJbl9QdG2AWcUJMDWp3Qyv5VJJw #api.mendeley.com.consumer_secret= #Salesforce -login.salesforce.com.consumer_key = 3MVG9Y6d_Btp4xp4yFMR0tPSndkAVu4OBejuYcL2iGFC68tA49PknWKX20XdPl5s1iwWldyuAbSINWHbB2Jcu -login.salesforce.com.consumer_secret = 1993703471433041656 +#login.salesforce.com.consumer_key = 3MVG9Y6d_Btp4xp4yFMR0tPSndkAVu4OBejuYcL2iGFC68tA49PknWKX20XdPl5s1iwWldyuAbSINWHbB2Jcu +#login.salesforce.com.consumer_secret = 1993703471433041656 #Instagram -api.instagram.com.consumer_key=f1e23002a9da49f696d439368624c9fc -api.instagram.com.consumer_secret=f274614621f64d498cb3458b3736827a +#api.instagram.com.consumer_key=f1e23002a9da49f696d439368624c9fc +#api.instagram.com.consumer_secret=f274614621f64d498cb3458b3736827a #Flickr -www.flickr.com.consumer_key=942a1a394b866a30dc9b4ad8db5cb8f8 -www.flickr.com.consumer_secret=f90c5bee8a8de964 +#www.flickr.com.consumer_key=942a1a394b866a30dc9b4ad8db5cb8f8 +#www.flickr.com.consumer_secret=f90c5bee8a8de964 #GITHub -api.github.com.consumer_key=4ffc69764a59dd3ce347 -api.github.com.consumer_secret=dc62937c1d7bb9ce30cb654a26d4a575858f5e1f +#api.github.com.consumer_key=4ffc69764a59dd3ce347 +#api.github.com.consumer_secret=dc62937c1d7bb9ce30cb654a26d4a575858f5e1f #Implementations #you can provide your custom provider here e.g 'myprovider' is your provider id 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 42052f20..5aa63a94 100644 --- a/pollen-ui-riot-js/src/main/web/js/AuthService.js +++ b/pollen-ui-riot-js/src/main/web/js/AuthService.js @@ -69,14 +69,25 @@ class AuthService extends FetchService { } signInProvider(query, providerRedirection) { - console.log(query) - console.log(providerRedirection) return this.fetch( "/v1/login/" + query.loginProvider, "POST", {Authorization: JSON.stringify(query)}, providerRedirection); } + + getAllLoginProviders() { + return this.get("/v1/loginproviders"); + } + + getAvailableLoginProviders() { + console.log("getAvailableLoginProviders") + return this.get("/v1/loginproviders/active"); + } + + saveLoginProvider(loginProvider) { + return this.post("/v1/loginproviders/" + (loginProvider.id || ""), loginProvider); + } } module.exports = singleton(AuthService); diff --git a/pollen-ui-riot-js/src/main/web/tag/Pollen.tag.html b/pollen-ui-riot-js/src/main/web/tag/Pollen.tag.html index 36ca5983..5a4114b6 100644 --- a/pollen-ui-riot-js/src/main/web/tag/Pollen.tag.html +++ b/pollen-ui-riot-js/src/main/web/tag/Pollen.tag.html @@ -30,8 +30,9 @@ require("./poll/EditPoll.tag.html"); require("./poll/Poll.tag.html"); require("./poll/Summary.tag.html"); require("./poll/Polls.tag.html"); -require("./Users.tag.html"); require("./UserProfile.tag.html"); +require("./admin/Users.tag.html"); +require("./admin/LoginProviders.tag.html"); require("./favoriteList/FavoriteLists.tag.html"); require("./favoriteList/FavoriteList.tag.html"); require("./popup/ConfirmPopup.tag.html"); @@ -217,6 +218,11 @@ require("./popup/InformationPopup.tag.html"); riot.mount(this.refs.content, "favoritelist", {favoriteListId: favoriteListId}); }); + route("/loginProviders", () => { + this.bus.trigger("pageChanged", "loginProviders"); + riot.mount(this.refs.content, "loginproviders"); + }); + route(() => { var q = route.query(); if (q.loginProvider != null) { diff --git a/pollen-ui-riot-js/src/main/web/tag/PollenHeader.tag.html b/pollen-ui-riot-js/src/main/web/tag/PollenHeader.tag.html index 9e540e82..7974eccb 100644 --- a/pollen-ui-riot-js/src/main/web/tag/PollenHeader.tag.html +++ b/pollen-ui-riot-js/src/main/web/tag/PollenHeader.tag.html @@ -37,6 +37,7 @@ require("./popup/FeedbackModal.tag.html"); <div class="dropdown-content right"> <a href="#user">{__.users}</a> <a href="#poll">{__.polls}</a> + <a href="#loginProviders">{__.loginProviders}</a> </div> </div> diff --git a/pollen-ui-riot-js/src/main/web/tag/SignIn.tag.html b/pollen-ui-riot-js/src/main/web/tag/SignIn.tag.html index 2ce478c5..c571e63a 100644 --- a/pollen-ui-riot-js/src/main/web/tag/SignIn.tag.html +++ b/pollen-ui-riot-js/src/main/web/tag/SignIn.tag.html @@ -58,8 +58,7 @@ require("./components/HumanInput.tag.html"); <a onclick="{newPassword}">{__.lostpassword}</a> </form> <p>Ou connectez vous avec votre compte : - <a onclick="{signinWithProvider('facebook')}"><i class="fa fa-facebook-official"></i></a> - <a onclick="{signinWithProvider('googleplus')}"><i class="fa fa-google"></i></a> + <a each="{loginProvider in loginProviders}" onclick="{signinWithProvider(loginProvider)}">{loginProvider}</a> </p> </div> @@ -79,6 +78,15 @@ require("./components/HumanInput.tag.html"); this.message = ""; this.openSignIn = false; + let authService = require("../js/AuthService"); + this.loginProviders = []; + this.on("mount", () => { + authService.getAvailableLoginProviders().then((result) => { + this.loginProviders = result; + this.update(); + }); + }); + this.newPassword = () => { this.refs.newPassword.open(this.refs.login.value || ""); }; diff --git a/pollen-ui-riot-js/src/main/web/tag/admin/LoginProviders.tag.html b/pollen-ui-riot-js/src/main/web/tag/admin/LoginProviders.tag.html new file mode 100644 index 00000000..5e23f89e --- /dev/null +++ b/pollen-ui-riot-js/src/main/web/tag/admin/LoginProviders.tag.html @@ -0,0 +1,92 @@ +<LoginProviders> + <div class="container" show="{loaded}"> + <h1>{__.title}</h1> + + <div class="main-content"> + + <table> + <thead> + <tr> + <th>{__.name}</th> + <th>{__.key}</th> + <th>{__.secret}</th> + <th>{__.permission}</th> + <th>{__.active}</th> + </tr> + </thead> + <tbody> + <tr each="{loginprovider, index in loginProviders}"> + <td><input type="text" ref="name{index}" value="{loginprovider.name}" required/></td> + <td><input type="text" ref="key{index}" value="{loginprovider.key}" required/></td> + <td><input type="text" ref="secret{index}" value="{loginprovider.secret}" required/></td> + <td><input type="text" ref="permissions{index}" value="{loginprovider.permissions}"/></td> + <td><input type="checkbox" ref="active{index}" checked="{loginprovider.active}"/></td> + <td> + <button class="c-button" onclick="{saveLoginProvider(index)}"><i class="fa fa-check"></i></button> + <button class="c-button" onclick="{cancelEdition(index)}"><i class="fa fa-remove"></i></button> + </td> + </tr> + </tbody> + </table> + + <button class="c-button" onclick="{addProvider}"><i class="fa fa-plus"></i></button> + </div> + </div> + + <script type="es6"> + this.loaded = false; + let session = require("../../js/Session"); + this.installBundle(session, "loginProviders"); + + let authService = require("../../js/AuthService"); + this.loginProviders = []; + authService.getAllLoginProviders().then((result) => { + if (!this.loaded) { + this.loginProviders = result; + this.loaded = true; + this.update(); + } + return result; + }); + + this.addProvider = (e) => { + e.preventDefault(); + e.stopPropagation(); + this.loginProviders.push({}); + }; + + this.saveLoginProvider = (index) => (e) => { + e.preventDefault(); + e.stopPropagation(); + let loginProvider = this.loginProviders[index]; + loginProvider.name = this.refs["name" + index].value; + loginProvider.key = this.refs["key" + index].value; + loginProvider.secret = this.refs["secret" + index].value; + loginProvider.permissions = this.refs["permissions" + index].value; + loginProvider.active = this.refs["active" + index].checked; + + authService.saveLoginProvider(loginProvider).then((result) => { + loginProvider.id = result.id; + loginProvider.name = result.name; + loginProvider.key = result.key; + loginProvider.secret = result.secret; + loginProvider.permissions = result.permissions; + loginProvider.active = result.active; + }); + }; + + this.cancelEdition = (index) => (e) => { + e.preventDefault(); + e.stopPropagation(); + let loginProvider = this.loginProviders[index]; + this.refs["name" + index].value = loginProvider.name || ""; + this.refs["key" + index].value = loginProvider.key || ""; + this.refs["secret" + index].value = loginProvider.secret || ""; + this.refs["permissions" + index].value = loginProvider.permissions || ""; + this.refs["active" + index].checked = loginProvider.active || false; + }; + + </script> + <style> + </style> +</LoginProviders> diff --git a/pollen-ui-riot-js/src/main/web/tag/UserCard.tag.html b/pollen-ui-riot-js/src/main/web/tag/admin/UserCard.tag.html similarity index 95% rename from pollen-ui-riot-js/src/main/web/tag/UserCard.tag.html rename to pollen-ui-riot-js/src/main/web/tag/admin/UserCard.tag.html index 33ffec79..b2599ea7 100644 --- a/pollen-ui-riot-js/src/main/web/tag/UserCard.tag.html +++ b/pollen-ui-riot-js/src/main/web/tag/admin/UserCard.tag.html @@ -1,4 +1,4 @@ -require("./components/Card.tag.html"); +require("../components/Card.tag.html"); require("./UserEditModal.tag.html"); <UserCard> @@ -50,9 +50,9 @@ require("./UserEditModal.tag.html"); </form> <script type="es6"> - let session = require("../js/Session"); + let session = require("../../js/Session"); this.installBundle(session, "user"); - let userService = require("../js/UserService"); + let userService = require("../../js/UserService"); this.editing = false; this.errors = {}; diff --git a/pollen-ui-riot-js/src/main/web/tag/UserEditModal.tag.html b/pollen-ui-riot-js/src/main/web/tag/admin/UserEditModal.tag.html similarity index 94% rename from pollen-ui-riot-js/src/main/web/tag/UserEditModal.tag.html rename to pollen-ui-riot-js/src/main/web/tag/admin/UserEditModal.tag.html index 5a89e692..a41f5350 100644 --- a/pollen-ui-riot-js/src/main/web/tag/UserEditModal.tag.html +++ b/pollen-ui-riot-js/src/main/web/tag/admin/UserEditModal.tag.html @@ -1,4 +1,4 @@ -require("./popup/Modal.tag.html"); +require("../popup/Modal.tag.html"); <UserEditModal> <Modal ref="modal" @@ -67,10 +67,10 @@ require("./popup/Modal.tag.html"); </Modal> <script type="es6"> - let session = require("../js/Session"); - let Message = require("../js/Message"); + let session = require("../../js/Session"); + let Message = require("../../js/Message"); this.installBundle(session, "user"); - let userService = require("../js/UserService"); + let userService = require("../../js/UserService"); this.errors = {}; diff --git a/pollen-ui-riot-js/src/main/web/tag/Users.tag.html b/pollen-ui-riot-js/src/main/web/tag/admin/Users.tag.html similarity index 88% rename from pollen-ui-riot-js/src/main/web/tag/Users.tag.html rename to pollen-ui-riot-js/src/main/web/tag/admin/Users.tag.html index bb2d4351..286538ad 100644 --- a/pollen-ui-riot-js/src/main/web/tag/Users.tag.html +++ b/pollen-ui-riot-js/src/main/web/tag/admin/Users.tag.html @@ -1,6 +1,6 @@ -require("./components/LazyLoad.tag.html"); -require("./components/LoadingCard.tag.html"); -require("./components/Search.tag.html"); +require("../components/LazyLoad.tag.html"); +require("../components/LoadingCard.tag.html"); +require("../components/Search.tag.html"); require("./UserCard.tag.html"); <Users> <div class="container" show="{loaded}"> @@ -28,7 +28,7 @@ require("./UserCard.tag.html"); <script type="es6"> this.loaded = false; - let session = require("../js/Session"); + let session = require("../../js/Session"); this.installBundle(session, "users"); this.pagination = { @@ -39,7 +39,7 @@ require("./UserCard.tag.html"); }; this.search = {value: ""}; - let userService = require("../js/UserService"); + let userService = require("../../js/UserService"); this.refresh = () => { this.refs.lazyLoad.reload(); -- 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/1_socialauth in repository pollen. See https://gitlab.nuiton.org/chorem/pollen.git commit 62201ae0f5b3019ed7bd593200a4d24eb1f65556 Author: Kevin Morin <morin@codelutin.com> Date: Fri Aug 25 18:03:46 2017 +0200 refs #1 ajout du socialmanager dans la session en attendant le retour du provider + gestion des tiers de connexion + gestion des comptes sans email --- .../org/chorem/pollen/rest/api/v1/AuthApi.java | 41 ++++++++++++--- .../services/service/NotificationService.java | 50 ++++++++++-------- .../pollen/services/service/SocialAuthService.java | 60 ++++++++++++++-------- 3 files changed, 101 insertions(+), 50 deletions(-) diff --git a/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/AuthApi.java b/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/AuthApi.java index 748dc894..fc2ac99b 100644 --- a/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/AuthApi.java +++ b/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/AuthApi.java @@ -26,10 +26,13 @@ import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.shiro.codec.Base64; +import org.brickred.socialauth.SocialAuthManager; +import org.chorem.pollen.persistence.entity.LoginProvider; import org.chorem.pollen.persistence.entity.PollenUser; import org.chorem.pollen.persistence.entity.SessionToken; import org.chorem.pollen.services.PollenServiceContext; import org.chorem.pollen.services.bean.LoginProviderBean; +import org.chorem.pollen.services.bean.PollenEntityId; import org.chorem.pollen.services.bean.PollenEntityRef; import org.chorem.pollen.services.service.PollenUserService; import org.chorem.pollen.services.service.SocialAuthService; @@ -42,7 +45,9 @@ import org.chorem.pollen.services.service.security.PollenSecurityContext; import org.chorem.pollen.services.service.security.PollenUserBannedException; import org.chorem.pollen.services.service.security.SecurityService; +import javax.servlet.http.HttpServletRequest; import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; import javax.ws.rs.GET; import javax.ws.rs.HeaderParam; import javax.ws.rs.POST; @@ -55,7 +60,6 @@ import javax.ws.rs.core.Context; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.NewCookie; import javax.ws.rs.core.Response; -import java.net.URI; import java.util.List; import java.util.Map; @@ -75,7 +79,8 @@ public class AuthApi { public static final String COOKIE_POLLEN_AUTH = "pollen-auth"; private static final String COOKIE_POLLEN_CONNECTED = "pollen-connected"; - private final static int COOKIE_MAX_AGE = 60 * 60 * 24 * 365; // 1 year + private static final int COOKIE_MAX_AGE = 60 * 60 * 24 * 365; // 1 year + private static final String SOCIAL_AUTH_MANAGER_SESSION_KEY = "socialAuthManager"; public static Response.ResponseBuilder removeAuthCookie(Response.ResponseBuilder reponseBuilder) { @@ -191,13 +196,15 @@ public class AuthApi { @Path("/login/{providerId}") @GET - public Response loginProvider(@Context SocialAuthService socialAuthService, + public String getLoginProviderUrl(@Context SocialAuthService socialAuthService, + @Context HttpServletRequest request, @PathParam("providerId") String providerId, @QueryParam("providerRedirection") String providerRedirection) throws Exception { - String providerLoginUrl = socialAuthService.getProviderAuthenticationUrl(providerId, providerRedirection); - return Response.seeOther(URI.create(providerLoginUrl)).build(); + SocialAuthManager socialAuthManager = socialAuthService.getSocialAuthManager(); + request.getSession(true).setAttribute(SOCIAL_AUTH_MANAGER_SESSION_KEY, socialAuthManager); + return socialAuthManager.getAuthenticationUrl(providerId, providerRedirection); } @Path("/login/{providerId}") @@ -206,14 +213,18 @@ public class AuthApi { @Context PollenServiceContext serviceContext, @Context SecurityService securityService, @Context PollenSecurityContext securityContext, - @PathParam("providerId") String providerId, - String providerRedirection, + @Context HttpServletRequest request, @HeaderParam("authorization") String authorization) throws Exception { + SocialAuthManager socialAuthManager = + (SocialAuthManager) request.getSession().getAttribute(SOCIAL_AUTH_MANAGER_SESSION_KEY); + //socialAuthManager + request.getSession().removeAttribute(SOCIAL_AUTH_MANAGER_SESSION_KEY); Gson gson = new Gson(); Map<String, String> paramsMap = gson.fromJson(authorization, Map.class); - PollenEntityRef<PollenUser> userPollenEntityRef = socialAuthService.login(providerId, providerRedirection, paramsMap); + PollenEntityRef<PollenUser> userPollenEntityRef = socialAuthService.login(socialAuthManager, + paramsMap); return getLoginResponseFromPollenUser(serviceContext, securityService, securityContext, userPollenEntityRef); } @@ -270,8 +281,22 @@ public class AuthApi { return socialAuthService.saveLoginProvider(loginProvider, true); } + @Path("/loginproviders/{providerId}") + @DELETE + public void deleteLoginProvider(@Context SocialAuthService socialAuthService, + @PathParam("providerId") PollenEntityId<LoginProvider> providerId) { + socialAuthService.deleteLoginProvider(providerId.getEntityId()); + + } + @Path("/loginproviders/active") @GET + public List<String> getActiveLoginProviders(@Context SocialAuthService socialAuthService) { + return socialAuthService.getActiveLoginProviders(); + } + + @Path("/loginproviders/available") + @GET public List<String> getAvailableLoginProviders(@Context SocialAuthService socialAuthService) { return socialAuthService.getAvailableLoginProviders(); } 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 035fb742..50e62797 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 @@ -73,10 +73,12 @@ import java.util.Set; public class NotificationService extends PollenServiceSupport { public void onUserCreated(PollenUser user) { - EmailService emailService = getEmailService(); - UserAccountCreatedEmail email = emailService.newUserAccountCreatedEmail(user); - email.addTo(user.getEmail()); - emailService.send(email); + if (StringUtils.isNotBlank(user.getEmail())) { + EmailService emailService = getEmailService(); + UserAccountCreatedEmail email = emailService.newUserAccountCreatedEmail(user); + email.addTo(user.getEmail()); + emailService.send(email); + } } public void onResendValidation(PollenUser user) { @@ -87,24 +89,30 @@ public class NotificationService extends PollenServiceSupport { } public void onUserEdited(PollenUser user) { - EmailService emailService = getEmailService(); - UserAccountEditedEmail email = emailService.newUserAccountEditedEmail(user); - email.addTo(user.getEmail()); - emailService.send(email); + if (StringUtils.isNotBlank(user.getEmail())) { + EmailService emailService = getEmailService(); + UserAccountEditedEmail email = emailService.newUserAccountEditedEmail(user); + email.addTo(user.getEmail()); + emailService.send(email); + } } public void onUserDeleted(PollenUser user) { - EmailService emailService = getEmailService(); - UserAccountDeletedEmail email = emailService.newUserAccountDeletedEmail(user); - email.addTo(user.getEmail()); - emailService.send(email); + if (StringUtils.isNotBlank(user.getEmail())) { + EmailService emailService = getEmailService(); + UserAccountDeletedEmail email = emailService.newUserAccountDeletedEmail(user); + email.addTo(user.getEmail()); + emailService.send(email); + } } public void onUserPasswordChanged(PollenUser user) { - EmailService emailService = getEmailService(); - UserAccountPasswordChangedEmail email = emailService.newUserAccountPasswordChangedEmail(user); - email.addTo(user.getEmail()); - emailService.send(email); + if (StringUtils.isNotBlank(user.getEmail())) { + EmailService emailService = getEmailService(); + UserAccountPasswordChangedEmail email = emailService.newUserAccountPasswordChangedEmail(user); + email.addTo(user.getEmail()); + emailService.send(email); + } } public void onUserEmailValidated(PollenUser user) { @@ -115,10 +123,12 @@ public class NotificationService extends PollenServiceSupport { } public void onUserLostPasswordAsked(PollenUser user, String newPassword) { - EmailService emailService = getEmailService(); - LostPasswordEmail email = emailService.newLostPasswordEmail(user, newPassword); - email.addTo(user.getEmail()); - emailService.send(email); + if (StringUtils.isNotBlank(user.getEmail())) { + EmailService emailService = getEmailService(); + LostPasswordEmail email = emailService.newLostPasswordEmail(user, newPassword); + email.addTo(user.getEmail()); + emailService.send(email); + } } public void onFavoriteListAdded(PollenUser user, FavoriteList favoriteList) { diff --git a/pollen-services/src/main/java/org/chorem/pollen/services/service/SocialAuthService.java b/pollen-services/src/main/java/org/chorem/pollen/services/service/SocialAuthService.java index 2d4aa50f..2e136aa7 100644 --- a/pollen-services/src/main/java/org/chorem/pollen/services/service/SocialAuthService.java +++ b/pollen-services/src/main/java/org/chorem/pollen/services/service/SocialAuthService.java @@ -19,7 +19,7 @@ import org.chorem.pollen.persistence.entity.UserCredentialImpl; import org.chorem.pollen.services.bean.LoginProviderBean; import org.chorem.pollen.services.bean.PollenEntityRef; -import java.util.Comparator; +import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Optional; @@ -33,21 +33,9 @@ public class SocialAuthService extends PollenServiceSupport { /** Logger. */ private static final Log log = LogFactory.getLog(SocialAuthService.class); - public String getProviderAuthenticationUrl(String providerId, String redirection) throws Exception { - SocialAuthManager manager = getSocialAuthManager(); - - // get Provider URL to which you should redirect for authentication. - // id can have values "facebook", "twitter", "yahoo" etc. or the OpenID URL - return manager.getAuthenticationUrl(providerId, redirection); - } - - public PollenEntityRef<PollenUser> login(String providerId, - String redirection, + public PollenEntityRef<PollenUser> login(SocialAuthManager manager, Map<String, String> paramsMap) throws Exception { - SocialAuthManager manager = getSocialAuthManager(); - manager.getAuthenticationUrl(providerId, redirection); - paramsMap.remove(Constants.STATE); AuthProvider provider = manager.connect(paramsMap); // get profile @@ -94,7 +82,7 @@ public class SocialAuthService extends PollenServiceSupport { return getSecurityService().getSessionTokenForUser(pollenUser); } - protected SocialAuthManager getSocialAuthManager() throws Exception { + public SocialAuthManager getSocialAuthManager() throws Exception { //Create an instance of SocialAuthConfgi object SocialAuthConfig config = SocialAuthConfig.getDefault(); @@ -128,27 +116,47 @@ public class SocialAuthService extends PollenServiceSupport { public List<LoginProviderBean> getAllLoginProviders() { checkIsAdmin(); LoginProviderTopiaDao dao = getLoginProviderDao(); - List<LoginProvider> loginProviders = dao.findAll().stream() - .sorted(Comparator.comparing(LoginProvider::getName)) - .collect(Collectors.toList()); + List<LoginProvider> loginProviders = dao.findAll(); return toBeanList(LoginProviderBean.class, loginProviders); } - public List<String> getAvailableLoginProviders() { + public List<String> getActiveLoginProviders() { LoginProviderTopiaDao dao = getLoginProviderDao(); return dao.forActiveEquals(true).findAll().stream() .map(LoginProvider::getName) - .sorted() .collect(Collectors.toList()); } + public List<String> getAvailableLoginProviders() { + return new ArrayList<String>() {{ + add(Constants.AMAZON); + add(Constants.FACEBOOK); + add(Constants.FLICKR); + add(Constants.FOURSQUARE); + add(Constants.GITHUB); + add(Constants.GOOGLE_PLUS); + add(Constants.HOTMAIL); + add(Constants.INSTAGRAM); + add(Constants.LINKEDIN); + add(Constants.LINKEDINOAUTH2); + add(Constants.MENDELEY); + add(Constants.MYSPACE); + add(Constants.NIMBLE); + add(Constants.RUNKEEPER); + add(Constants.SALESFORCE); + add(Constants.STACK_EXCHANGE); + add(Constants.TWITTER); + add(Constants.YAHOO); + add(Constants.YAMMER); + }}; + } + public LoginProviderBean saveLoginProvider(LoginProviderBean loginProvider, boolean loginProviderExists) { checkIsAdmin(); checkNotNull(loginProvider); - LoginProviderTopiaDao dao = getLoginProviderDao(); + LoginProviderTopiaDao dao = getLoginProviderDao(); LoginProvider toSave; - if (loginProviderExists) { toSave = dao.forTopiaIdEquals(loginProvider.getEntityId()).findUnique(); } else { @@ -163,4 +171,12 @@ public class SocialAuthService extends PollenServiceSupport { commit(); return toBean(LoginProviderBean.class, toSave); } + + public void deleteLoginProvider(String providerId) { + checkIsAdmin(); + checkNotNull(providerId); + LoginProviderTopiaDao dao = getLoginProviderDao(); + dao.delete(dao.forTopiaIdEquals(providerId).findUnique()); + commit(); + } } -- 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/1_socialauth in repository pollen. See https://gitlab.nuiton.org/chorem/pollen.git commit cfa63ad271f28017e49cfbdc491a185ca23ba32b Author: Kevin Morin <morin@codelutin.com> Date: Fri Aug 25 18:04:36 2017 +0200 refs #1 gestion des tiers de connexion + style du login --- pollen-ui-riot-js/src/main/web/css/main.css | 8 ++ pollen-ui-riot-js/src/main/web/js/AuthService.js | 18 ++- pollen-ui-riot-js/src/main/web/js/FetchService.js | 5 +- pollen-ui-riot-js/src/main/web/js/Session.js | 2 +- pollen-ui-riot-js/src/main/web/tag/SignIn.tag.html | 131 ++++++++++++++------- pollen-ui-riot-js/src/main/web/tag/SignUp.tag.html | 4 +- .../src/main/web/tag/admin/LoginProviders.tag.html | 104 +++++++++++++--- 7 files changed, 205 insertions(+), 67 deletions(-) diff --git a/pollen-ui-riot-js/src/main/web/css/main.css b/pollen-ui-riot-js/src/main/web/css/main.css index 04db9045..59c2433c 100644 --- a/pollen-ui-riot-js/src/main/web/css/main.css +++ b/pollen-ui-riot-js/src/main/web/css/main.css @@ -470,3 +470,11 @@ pollenfooter a:hover { .no-border { border: 0; } + +.align-right { + text-align: right; +} + +.align-center { + text-align: center; + } \ 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 5aa63a94..3fd1d1f1 100644 --- a/pollen-ui-riot-js/src/main/web/js/AuthService.js +++ b/pollen-ui-riot-js/src/main/web/js/AuthService.js @@ -68,12 +68,15 @@ class AuthService extends FetchService { return this.post("/v1/resendValidation", email); } - signInProvider(query, providerRedirection) { + getLoginProviderUrl(providerId, redirection) { + return this.get("/v1/login/" + providerId, { providerRedirection: redirection}); + } + + signInProvider(query) { return this.fetch( "/v1/login/" + query.loginProvider, "POST", - {Authorization: JSON.stringify(query)}, - providerRedirection); + {Authorization: JSON.stringify(query)}); } getAllLoginProviders() { @@ -81,13 +84,20 @@ class AuthService extends FetchService { } getAvailableLoginProviders() { - console.log("getAvailableLoginProviders") + return this.get("/v1/loginproviders/available"); + } + + getActiveLoginProviders() { return this.get("/v1/loginproviders/active"); } saveLoginProvider(loginProvider) { return this.post("/v1/loginproviders/" + (loginProvider.id || ""), loginProvider); } + + deleteLoginProvider(loginProvider) { + return this.doDelete("/v1/loginproviders/" + loginProvider.id); + } } module.exports = singleton(AuthService); diff --git a/pollen-ui-riot-js/src/main/web/js/FetchService.js b/pollen-ui-riot-js/src/main/web/js/FetchService.js index 1426bb72..ae3de5a7 100644 --- a/pollen-ui-riot-js/src/main/web/js/FetchService.js +++ b/pollen-ui-riot-js/src/main/web/js/FetchService.js @@ -50,7 +50,10 @@ class FetchService { return null; } if (response.status === 200) { - return response.json(); + let responseCopy = response.clone(); + return responseCopy.json().catch(err => { + return response.text(); + }); } if (response.status === 400) { return response.json().then(json => Promise.reject(json)); diff --git a/pollen-ui-riot-js/src/main/web/js/Session.js b/pollen-ui-riot-js/src/main/web/js/Session.js index f5f84fdf..77bcd203 100644 --- a/pollen-ui-riot-js/src/main/web/js/Session.js +++ b/pollen-ui-riot-js/src/main/web/js/Session.js @@ -137,7 +137,7 @@ class Session { } signInProvider(query) { - return authService.signInProvider(query, this.getProviderRedirectionUrl(query.loginProvider)) + return authService.signInProvider(query) .then(auth => this.updateConnection(auth, this)); } diff --git a/pollen-ui-riot-js/src/main/web/tag/SignIn.tag.html b/pollen-ui-riot-js/src/main/web/tag/SignIn.tag.html index c571e63a..f58786ac 100644 --- a/pollen-ui-riot-js/src/main/web/tag/SignIn.tag.html +++ b/pollen-ui-riot-js/src/main/web/tag/SignIn.tag.html @@ -24,42 +24,45 @@ require("./components/HumanInput.tag.html"); <SignIn> <div class="body-container colors-default sign-in-layer" show={openSignIn}> <div class="body-content"> - <h1 class="c-heading">{__.title}</h1> + <h1 class="c-heading"><i class="fa fa-sign-in"></i> {__.title}</h1> <form class="signin"> <HumanInput onsubmit={signIn}/> <div class="o-form-element"> - <div class="c-input-group c-input-group--stacked"> - <div class="o-field"> - <input class="c-field {c-field--error : message}" - type="email" - id="login" - name="login" - ref="login" - required - placeholder={__.login_placeholder}> - </div> - <div class="o-field o-field--icon-right"> - <input class="c-field {c-field--error : message}" - type="password" - id="password" - name="password" - ref="password" - required - placeholder={__.password_placeholder}> - <button class="c-icon login-btn" - type="submit" - title={__.connexion}> - <i class="fa fa-fw fa-arrow-right"/> - </button> - </div> - </div> + <label class="c-label" for="login">{__.login}</label> + <input class="c-field {c-field--error : message}" + type="email" + id="login" + name="login" + ref="login" + required + placeholder={__.login_placeholder}/> + </div> + <div class="o-form-element"> + <label class="c-label" for="password">{__.password}</label> + <input class="c-field {c-field--error : message}" + type="password" + id="password" + name="password" + ref="password" + required + placeholder={__.password_placeholder}> + </div> + <div class="o-form-element align-right"> + <p><button class="c-button c-button--info" type="submit"><i class="fa fa-sign-in"></i> {__.title}</button></p> <div class="c-hint--static c-hint--error">{message}</div> + <p><a onclick="{newPassword}">{__.lostpassword}</a></p> + </div> + <div class="o-form-element align-center"> + <p>Ou connectez vous avec votre compte :</p> + <p> + <a each="{loginProvider in loginProviders}" class="provider-link" + onclick="{signinWithProvider(loginProvider)}"> + <i class="fa fa-{providerIcons[loginProvider]}" if="{providerIcons[loginProvider]}"></i> + <span if="{!providerIcons[loginProvider]}">{loginProvider}</span> + </a> + </p> </div> - <a onclick="{newPassword}">{__.lostpassword}</a> </form> - <p>Ou connectez vous avec votre compte : - <a each="{loginProvider in loginProviders}" onclick="{signinWithProvider(loginProvider)}">{loginProvider}</a> - </p> </div> <SignUp/> @@ -78,10 +81,25 @@ require("./components/HumanInput.tag.html"); this.message = ""; this.openSignIn = false; + this.providerIcons = { + "amazon": "amazon", + "facebook": "facebook-official", + "flickr": "flickr", + "foursquare": "foursquare", + "github": "github", + "googleplus": "google", + "instagram": "instagram", + "linkedin": "linkedin", + "linkedin2": "linkedin", + "stackexchange": "stack-exchange", + "twitter": "twitter", + "yahoo": "yahoo" + }; + let authService = require("../js/AuthService"); this.loginProviders = []; this.on("mount", () => { - authService.getAvailableLoginProviders().then((result) => { + authService.getActiveLoginProviders().then((result) => { this.loginProviders = result; this.update(); }); @@ -122,8 +140,11 @@ require("./components/HumanInput.tag.html"); this.signinWithProvider = (provider) => (e) => { let currentPage = location.hash || "#"; localStorage.setItem("currentPage", currentPage); - location.href = this.session.configuration.endPoint + "/v1/login/" + provider - + "?providerRedirection=" + encodeURIComponent(this.session.getProviderRedirectionUrl(provider)); + let authService = require("../js/AuthService"); + let redirection = encodeURIComponent(this.session.getProviderRedirectionUrl(provider)); + authService.getLoginProviderUrl(provider, redirection).then(result => { + location.href = result; + }); }; </script> @@ -143,21 +164,10 @@ require("./components/HumanInput.tag.html"); top: 10px; } - .signin { - width: 250px; - margin: 0 auto; - } - .c-heading { text-align: center; } - .login-btn { - border: none; - background: transparent; - font-size: 1em; - } - .body-content { margin-bottom: 20px; } @@ -168,6 +178,39 @@ require("./components/HumanInput.tag.html"); } } + .signin { + padding: 0 1em; + margin: 0 auto; + max-width: 450px; + } + + .o-form-element p { + padding: 2px 0; + } + + .provider-link { + font-size: 2em; + } + + @media (min-width: 640px) { + .o-form-element .c-label:first-child { + width: 35%; + display: inline-block; + text-align: right; + float: left; + padding-top: 0.5em; + padding-right: 5px; + } + + .o-form-element .c-field { + width: 65%; + display: inline-block; + } + + .signin .c-hint--static { + margin-left: 35%; + } + } </style> </SignIn> 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 eee9115a..1d830d41 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 @@ -95,8 +95,8 @@ require("./components/HumanInput.tag.html"); <div class="actions-right"> <button type="submit" class="c-button c-button--info"> - <i class="fa fa-plus" aria-hidden="true"></i> - {__.validate} + <i class="fa fa-user-plus" aria-hidden="true"></i> + {__.title} </button> </div> </form> diff --git a/pollen-ui-riot-js/src/main/web/tag/admin/LoginProviders.tag.html b/pollen-ui-riot-js/src/main/web/tag/admin/LoginProviders.tag.html index 5e23f89e..49e06b1c 100644 --- a/pollen-ui-riot-js/src/main/web/tag/admin/LoginProviders.tag.html +++ b/pollen-ui-riot-js/src/main/web/tag/admin/LoginProviders.tag.html @@ -1,3 +1,5 @@ +require("../components/HumanInput.tag.html"); + <LoginProviders> <div class="container" show="{loaded}"> <h1>{__.title}</h1> @@ -7,29 +9,38 @@ <table> <thead> <tr> - <th>{__.name}</th> - <th>{__.key}</th> - <th>{__.secret}</th> - <th>{__.permission}</th> + <th>{__.name}*</th> + <th>{__.key}*</th> + <th>{__.secret}*</th> + <th>{__.permissions}</th> <th>{__.active}</th> </tr> </thead> <tbody> <tr each="{loginprovider, index in loginProviders}"> - <td><input type="text" ref="name{index}" value="{loginprovider.name}" required/></td> - <td><input type="text" ref="key{index}" value="{loginprovider.key}" required/></td> - <td><input type="text" ref="secret{index}" value="{loginprovider.secret}" required/></td> - <td><input type="text" ref="permissions{index}" value="{loginprovider.permissions}"/></td> - <td><input type="checkbox" ref="active{index}" checked="{loginprovider.active}"/></td> <td> - <button class="c-button" onclick="{saveLoginProvider(index)}"><i class="fa fa-check"></i></button> - <button class="c-button" onclick="{cancelEdition(index)}"><i class="fa fa-remove"></i></button> + <select class="c-field" ref="name{index}" required disabled="{editingRow != index}"> + <option>{loginprovider.name}</option> + <option each="{availableProvider in availableLoginProviders}">{availableProvider}</option> + </select> + </td> + <td><input class="c-field" type="text" ref="key{index}" value="{loginprovider.key}" required disabled="{editingRow != index}"/></td> + <td><input class="c-field c-field--large" type="text" ref="secret{index}" value="{loginprovider.secret}" required disabled="{editingRow != index}"/></td> + <td><input class="c-field" type="text" ref="permissions{index}" value="{loginprovider.permissions}" disabled="{editingRow != index}"/></td> + <td><input type="checkbox" ref="active{index}" checked="{loginprovider.active}" disabled="{editingRow != index}"/></td> + <td if="{editingRow != index}"> + <button class="c-button c-button--info" onclick="{editLoginProvider(index)}" disabled="{editingRow != null}"><i class="fa fa-edit"></i></button> + <button class="c-button c-button--error" onclick="{deleteLoginProvider(index)}" disabled="{editingRow != null}"><i class="fa fa-trash"></i></button> + </td> + <td if="{editingRow == index}"> + <button class="c-button c-button--success" onclick="{saveLoginProvider(index)}"><i class="fa fa-check"></i></button> + <button class="c-button c-button--error" onclick="{cancelEdition(index)}"><i class="fa fa-remove"></i></button> </td> </tr> </tbody> </table> - <button class="c-button" onclick="{addProvider}"><i class="fa fa-plus"></i></button> + <button class="c-button" onclick="{addProvider}" disabled="{editingRow != null}"><i class="fa fa-plus"></i> {__.newProvider}</button> </div> </div> @@ -38,27 +49,77 @@ let session = require("../../js/Session"); this.installBundle(session, "loginProviders"); + this.editingRow = null; + let authService = require("../../js/AuthService"); this.loginProviders = []; - authService.getAllLoginProviders().then((result) => { + this.availableLoginProviders = []; + Promise.all([authService.getAllLoginProviders(), authService.getAvailableLoginProviders()]).then(results => { if (!this.loaded) { - this.loginProviders = result; + this.loginProviders = results[0]; + let usedLoginProviders = Array.from(this.loginProviders, item => item.name); + this.availableLoginProviders = results[1].filter(item => usedLoginProviders.indexOf(item) === -1); + this.availableLoginProviders.sort(); this.loaded = true; this.update(); } - return result; }); this.addProvider = (e) => { e.preventDefault(); e.stopPropagation(); this.loginProviders.push({}); + this.editingRow = this.loginProviders.length - 1; + }; + + this.editLoginProvider = (index) => (e) => { + e.preventDefault(); + e.stopPropagation(); + this.editingRow = index; + }; + + this.deleteLoginProvider = (index) => (e) => { + e.preventDefault(); + e.stopPropagation(); + let loginProvider = this.loginProviders[index]; + this.confirm(this.__.deleteMessage).then((confirm) => { + if (confirm) { + if (!loginProvider.id) { + this.loginProviders.splice(index, 1); + this.availableLoginProviders.push(loginProvider.name); + this.availableLoginProviders.sort(); + this.update(); + } else { + authService.deleteLoginProvider(loginProvider).then(() => { + this.loginProviders.splice(index, 1); + this.availableLoginProviders.push(loginProvider.name); + this.availableLoginProviders.sort(); + this.update(); + }); + } + } + }); }; this.saveLoginProvider = (index) => (e) => { e.preventDefault(); e.stopPropagation(); let loginProvider = this.loginProviders[index]; + let oldProvider = loginProvider.name; + + if (!this.refs["name" + index].value) { + alert(this.__.emptyName); + return; + } + if (!this.refs["key" + index].value) { + alert(this.__.emptyKey); + return; + } + if (!this.refs["secret" + index].value) { + alert(this.__.emptySecret); + return; + } + loginProvider.name = this.refs["name" + index].value; loginProvider.key = this.refs["key" + index].value; loginProvider.secret = this.refs["secret" + index].value; @@ -72,6 +133,15 @@ loginProvider.secret = result.secret; loginProvider.permissions = result.permissions; loginProvider.active = result.active; + + this.availableLoginProviders.splice(this.availableLoginProviders.indexOf(result.name), 1); + this.availableLoginProviders.push(oldProvider); + this.availableLoginProviders.sort(); + + this.refs["name" + index].value = loginProvider.name; + + this.editingRow = null; + this.update(); }); }; @@ -84,9 +154,13 @@ this.refs["secret" + index].value = loginProvider.secret || ""; this.refs["permissions" + index].value = loginProvider.permissions || ""; this.refs["active" + index].checked = loginProvider.active || false; + this.editingRow = null; }; </script> <style> + td { + text-align: center; + } </style> </LoginProviders> -- 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/1_socialauth in repository pollen. See https://gitlab.nuiton.org/chorem/pollen.git commit d3f0f3dc910239e807543126e0daa63a00dc13f3 Author: Kevin Morin <morin@codelutin.com> Date: Tue Aug 29 17:57:01 2017 +0200 refs #1 erreur si l'utilisateur veut se connecter via un service tiers et que son email est deja utilisé par un autre compte Pollen --- .../pollen/rest/api/PollenRestApiApplication.java | 2 ++ .../PollenEmailAlreadyUsedExceptionMapper.java | 20 ++++++++++++++ .../pollen/services/service/SocialAuthService.java | 4 +++ .../security/PollenEmailAlreadyUsedException.java | 11 ++++++++ pollen-ui-riot-js/src/main/web/img/logo.png | Bin 0 -> 10506 bytes pollen-ui-riot-js/src/main/web/tag/Pollen.tag.html | 18 +++++++++++-- .../src/main/web/tag/PollenMessageManager.tag.html | 2 ++ .../src/main/web/tag/admin/LoginProviders.tag.html | 30 ++++++++++----------- 8 files changed, 69 insertions(+), 18 deletions(-) diff --git a/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/PollenRestApiApplication.java b/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/PollenRestApiApplication.java index 897dfbcf..271b223a 100644 --- a/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/PollenRestApiApplication.java +++ b/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/PollenRestApiApplication.java @@ -7,6 +7,7 @@ import org.chorem.pollen.rest.api.exceptionMappers.FavoriteListImportExceptionMa import org.chorem.pollen.rest.api.exceptionMappers.InvalidEntityLinkExceptionMapper; import org.chorem.pollen.rest.api.exceptionMappers.InvalidFormExceptionMapper; import org.chorem.pollen.rest.api.exceptionMappers.PollenAuthenticationExceptionMapper; +import org.chorem.pollen.rest.api.exceptionMappers.PollenEmailAlreadyUsedExceptionMapper; import org.chorem.pollen.rest.api.exceptionMappers.PollenEmailNotValidatedExceptionMapper; import org.chorem.pollen.rest.api.exceptionMappers.PollenInvalidEmailActivationTokenExceptionMapper; import org.chorem.pollen.rest.api.exceptionMappers.PollenInvalidPermissionExceptionMapper; @@ -61,6 +62,7 @@ public class PollenRestApiApplication extends Application { new PollenInvalidPermissionExceptionMapper(), new PollenInvalidEmailActivationTokenExceptionMapper(), new PollenEmailNotValidatedExceptionMapper(), + new PollenEmailAlreadyUsedExceptionMapper(), new PollenUserBannedExceptionMapper(), new InvalidFormExceptionMapper(), new FavoriteListImportExceptionMapper(), diff --git a/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/exceptionMappers/PollenEmailAlreadyUsedExceptionMapper.java b/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/exceptionMappers/PollenEmailAlreadyUsedExceptionMapper.java new file mode 100644 index 00000000..3b1ec37b --- /dev/null +++ b/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/exceptionMappers/PollenEmailAlreadyUsedExceptionMapper.java @@ -0,0 +1,20 @@ +package org.chorem.pollen.rest.api.exceptionMappers; + +import org.chorem.pollen.services.service.security.PollenEmailAlreadyUsedException; + +import javax.ws.rs.core.Response; + +/** + * @author Sylvain Bavencoff - bavencoff@codelutin.com + */ +public class PollenEmailAlreadyUsedExceptionMapper extends PollenAbstractExceptionMapper<PollenEmailAlreadyUsedException> { + + public PollenEmailAlreadyUsedExceptionMapper() { + super(Response.Status.FORBIDDEN); + } + + @Override + protected Object getEntity(PollenEmailAlreadyUsedException exception) { + return "emailAlreadyUsed"; + } +} diff --git a/pollen-services/src/main/java/org/chorem/pollen/services/service/SocialAuthService.java b/pollen-services/src/main/java/org/chorem/pollen/services/service/SocialAuthService.java index 2e136aa7..8c9f7284 100644 --- a/pollen-services/src/main/java/org/chorem/pollen/services/service/SocialAuthService.java +++ b/pollen-services/src/main/java/org/chorem/pollen/services/service/SocialAuthService.java @@ -18,6 +18,7 @@ import org.chorem.pollen.persistence.entity.UserCredential; import org.chorem.pollen.persistence.entity.UserCredentialImpl; import org.chorem.pollen.services.bean.LoginProviderBean; import org.chorem.pollen.services.bean.PollenEntityRef; +import org.chorem.pollen.services.service.security.PollenEmailAlreadyUsedException; import java.util.ArrayList; import java.util.List; @@ -56,6 +57,9 @@ public class SocialAuthService extends PollenServiceSupport { } pollenUser = pollenUserForCredential.get(); + } else if (userDao.emailExists(p.getEmail())) { + throw new PollenEmailAlreadyUsedException(); + } else { if (log.isInfoEnabled()) { log.info("create new user : " + name); diff --git a/pollen-services/src/main/java/org/chorem/pollen/services/service/security/PollenEmailAlreadyUsedException.java b/pollen-services/src/main/java/org/chorem/pollen/services/service/security/PollenEmailAlreadyUsedException.java new file mode 100644 index 00000000..afd67772 --- /dev/null +++ b/pollen-services/src/main/java/org/chorem/pollen/services/service/security/PollenEmailAlreadyUsedException.java @@ -0,0 +1,11 @@ +package org.chorem.pollen.services.service.security; + +/** + * @author Kevin Morin (Code Lutin) + */ +public class PollenEmailAlreadyUsedException extends Exception { + + public PollenEmailAlreadyUsedException() { + super("emailAlreadyUsed"); + } +} diff --git a/pollen-ui-riot-js/src/main/web/img/logo.png b/pollen-ui-riot-js/src/main/web/img/logo.png new file mode 100644 index 00000000..79c5e328 Binary files /dev/null and b/pollen-ui-riot-js/src/main/web/img/logo.png differ diff --git a/pollen-ui-riot-js/src/main/web/tag/Pollen.tag.html b/pollen-ui-riot-js/src/main/web/tag/Pollen.tag.html index 5a4114b6..a64d7482 100644 --- a/pollen-ui-riot-js/src/main/web/tag/Pollen.tag.html +++ b/pollen-ui-riot-js/src/main/web/tag/Pollen.tag.html @@ -71,15 +71,22 @@ require("./popup/InformationPopup.tag.html"); this.updatePageTitle(); }); + let route = require("riot-route"); + let Message = require("../js/Message"); + this.on("mount", () => { this.listen("locale", this.onLocaleChange); this.listen("unauthorize", this.refs.signIn.open); this.listen("signIn", this.refs.signIn.open); this.listen("closeSignIn", this.refs.signIn.close); + this.listen("messageManagerReady", () => { + let q = route.query(); + if (q.error) { + this.bus.trigger("message", new Message(decodeURIComponent(this._l(q.error)), "error")); + } + }); }); - let route = require("riot-route"); - route("/poll/create", () => { this.bus.trigger("pageChanged", "home"); riot.mount(this.refs.content, "createpoll"); @@ -230,6 +237,13 @@ require("./popup/InformationPopup.tag.html"); let currentPage = localStorage.getItem("currentPage"); localStorage.removeItem("currentPage"); location.href = session.pollenUIContext.uiEndPoint + "/" + currentPage; + }, (e) => { + let currentPage = localStorage.getItem("currentPage"); + localStorage.removeItem("currentPage"); + console.log(e); + e.text().then(label => { + location.href = session.pollenUIContext.uiEndPoint + "/" + currentPage + "?error=" + label; + }); }); } else { diff --git a/pollen-ui-riot-js/src/main/web/tag/PollenMessageManager.tag.html b/pollen-ui-riot-js/src/main/web/tag/PollenMessageManager.tag.html index 6b3854fa..d8fbabdc 100644 --- a/pollen-ui-riot-js/src/main/web/tag/PollenMessageManager.tag.html +++ b/pollen-ui-riot-js/src/main/web/tag/PollenMessageManager.tag.html @@ -31,8 +31,10 @@ }, message.timeout * 1000); }; + this.on("mount", () => { this.listen("message", this.handleMessages); + this.bus.trigger("messageManagerReady"); }); this.closeMessage = (messageId) => (e) => { diff --git a/pollen-ui-riot-js/src/main/web/tag/admin/LoginProviders.tag.html b/pollen-ui-riot-js/src/main/web/tag/admin/LoginProviders.tag.html index 49e06b1c..29e16779 100644 --- a/pollen-ui-riot-js/src/main/web/tag/admin/LoginProviders.tag.html +++ b/pollen-ui-riot-js/src/main/web/tag/admin/LoginProviders.tag.html @@ -82,23 +82,21 @@ require("../components/HumanInput.tag.html"); e.preventDefault(); e.stopPropagation(); let loginProvider = this.loginProviders[index]; - this.confirm(this.__.deleteMessage).then((confirm) => { - if (confirm) { - if (!loginProvider.id) { - this.loginProviders.splice(index, 1); - this.availableLoginProviders.push(loginProvider.name); - this.availableLoginProviders.sort(); - this.update(); - } else { - authService.deleteLoginProvider(loginProvider).then(() => { - this.loginProviders.splice(index, 1); - this.availableLoginProviders.push(loginProvider.name); - this.availableLoginProviders.sort(); - this.update(); - }); + this.confirm(this.__.deleteMessage) + .then((confirm) => { + if (!confirm) { + return Promise.reject(); } - } - }); + if (confirm && loginProvider.id) { + return authService.deleteLoginProvider(loginProvider); + } + }) + .then(() => { + this.loginProviders.splice(index, 1); + this.availableLoginProviders.push(loginProvider.name); + this.availableLoginProviders.sort(); + this.update(); + }); }; this.saveLoginProvider = (index) => (e) => { -- 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/1_socialauth in repository pollen. See https://gitlab.nuiton.org/chorem/pollen.git commit 1cbe17251adbc04d3e48034963e7eff806d72c7d Author: Kevin Morin <morin@codelutin.com> Date: Thu Aug 31 14:57:45 2017 +0200 refs #1 envoi d'un mail à la création d'un compte a partir d'un service tiers --- .../chorem/pollen/services/PollenUIContext.java | 10 +++ .../services/service/NotificationService.java | 11 ++++ .../pollen/services/service/SocialAuthService.java | 2 + .../pollen/services/service/mail/EmailService.java | 35 ++++++++++ .../mail/UserAccountCreatedFromProviderEmail.java | 76 ++++++++++++++++++++++ .../UserAccountCreatedFromProviderEmail.mustache | 10 +++ ...UserAccountCreatedFromProviderEmail_fr.mustache | 11 ++++ .../i18n/pollen-services_en_GB.properties | 20 ++++++ .../i18n/pollen-services_fr_FR.properties | 20 ++++++ .../service/PollenUIUrlRenderServiceTest.java | 1 + pollen-ui-riot-js/src/main/web/js/Session.js | 3 +- pollen-ui-riot-js/src/main/web/tag/SignIn.tag.html | 2 +- 12 files changed, 199 insertions(+), 2 deletions(-) diff --git a/pollen-services/src/main/java/org/chorem/pollen/services/PollenUIContext.java b/pollen-services/src/main/java/org/chorem/pollen/services/PollenUIContext.java index b74ddd3a..c2bdcd61 100644 --- a/pollen-services/src/main/java/org/chorem/pollen/services/PollenUIContext.java +++ b/pollen-services/src/main/java/org/chorem/pollen/services/PollenUIContext.java @@ -21,6 +21,8 @@ public class PollenUIContext implements Serializable { private String resourceDownloadUrl; + private String profileUrl; + public String getUiEndPoint() { return uiEndPoint; } @@ -76,4 +78,12 @@ public class PollenUIContext implements Serializable { public void setResourceDownloadUrl(String resourceDownloadUrl) { this.resourceDownloadUrl = resourceDownloadUrl; } + + public String getProfileUrl() { + return profileUrl; + } + + public void setProfileUrl(String profileUrl) { + this.profileUrl = profileUrl; + } } 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 50e62797..074c6198 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 @@ -29,6 +29,7 @@ import org.chorem.pollen.persistence.entity.Poll; import org.chorem.pollen.persistence.entity.PollType; import org.chorem.pollen.persistence.entity.PollenUser; import org.chorem.pollen.persistence.entity.Report; +import org.chorem.pollen.persistence.entity.UserCredential; import org.chorem.pollen.persistence.entity.Vote; import org.chorem.pollen.persistence.entity.VoterList; import org.chorem.pollen.persistence.entity.VoterListMember; @@ -51,6 +52,7 @@ import org.chorem.pollen.services.service.mail.PollReportForAdminEmail; import org.chorem.pollen.services.service.mail.ResendValidationEmail; import org.chorem.pollen.services.service.mail.RestrictedPollInvitationEmail; import org.chorem.pollen.services.service.mail.UserAccountCreatedEmail; +import org.chorem.pollen.services.service.mail.UserAccountCreatedFromProviderEmail; import org.chorem.pollen.services.service.mail.UserAccountDeletedEmail; import org.chorem.pollen.services.service.mail.UserAccountEditedEmail; import org.chorem.pollen.services.service.mail.UserAccountEmailValidatedEmail; @@ -81,6 +83,15 @@ public class NotificationService extends PollenServiceSupport { } } + public void onUserCreatedFromProvider(PollenUser user, UserCredential credential) { + if (StringUtils.isNotBlank(user.getEmail())) { + EmailService emailService = getEmailService(); + UserAccountCreatedFromProviderEmail email = emailService.newUserAccountCreatedFromProviderEmail(user, credential); + email.addTo(user.getEmail()); + emailService.send(email); + } + } + public void onResendValidation(PollenUser user) { EmailService emailService = getEmailService(); ResendValidationEmail email = emailService.newUserResendValidationEmail(user); diff --git a/pollen-services/src/main/java/org/chorem/pollen/services/service/SocialAuthService.java b/pollen-services/src/main/java/org/chorem/pollen/services/service/SocialAuthService.java index 8c9f7284..0132f818 100644 --- a/pollen-services/src/main/java/org/chorem/pollen/services/service/SocialAuthService.java +++ b/pollen-services/src/main/java/org/chorem/pollen/services/service/SocialAuthService.java @@ -81,6 +81,8 @@ public class SocialAuthService extends PollenServiceSupport { pollenUser = userDao.create(pollenUser); commit(); + + getNotificationService().onUserCreatedFromProvider(pollenUser, credential); } return getSecurityService().getSessionTokenForUser(pollenUser); 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 f1dbe453..eed9fe95 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 @@ -44,6 +44,7 @@ import org.chorem.pollen.persistence.entity.PollenPrincipal; import org.chorem.pollen.persistence.entity.PollenResource; import org.chorem.pollen.persistence.entity.PollenUser; import org.chorem.pollen.persistence.entity.Report; +import org.chorem.pollen.persistence.entity.UserCredential; import org.chorem.pollen.persistence.entity.Vote; import org.chorem.pollen.services.bean.FeedbackBean; import org.chorem.pollen.services.bean.PollenEntityId; @@ -63,6 +64,9 @@ import java.util.Locale; import java.util.Map; import java.util.Set; +import static org.nuiton.i18n.I18n.n; +import static org.nuiton.i18n.I18n.t; + /** * Created on 4/30/14. * @@ -76,6 +80,28 @@ public class EmailService extends PollenServiceSupport { public static final String RECIPIENT_SEPARATOR = ";"; + static { + n("pollen.service.mail.loginProvider.amazon"); + n("pollen.service.mail.loginProvider.facebook"); + n("pollen.service.mail.loginProvider.flickr"); + n("pollen.service.mail.loginProvider.foursquare"); + n("pollen.service.mail.loginProvider.github"); + n("pollen.service.mail.loginProvider.googleplus"); + n("pollen.service.mail.loginProvider.hotmail"); + n("pollen.service.mail.loginProvider.instagram"); + n("pollen.service.mail.loginProvider.linkedin"); + n("pollen.service.mail.loginProvider.linkedin2"); + n("pollen.service.mail.loginProvider.mendeley"); + n("pollen.service.mail.loginProvider.myspace"); + n("pollen.service.mail.loginProvider.nimble"); + n("pollen.service.mail.loginProvider.runkeeper"); + n("pollen.service.mail.loginProvider.salesforce"); + n("pollen.service.mail.loginProvider.stackexchange"); + n("pollen.service.mail.loginProvider.twitter"); + n("pollen.service.mail.loginProvider.yahoo"); + n("pollen.service.mail.loginProvider.yammer"); + } + public ChoiceAddedEmail newChoiceAddedEmail(Poll poll, Choice choice) { ChoiceAddedEmail email = new ChoiceAddedEmail(getLocale()); email.setPoll(poll); @@ -213,6 +239,15 @@ public class EmailService extends PollenServiceSupport { return email; } + public UserAccountCreatedFromProviderEmail newUserAccountCreatedFromProviderEmail(PollenUser user, + UserCredential credential) { + UserAccountCreatedFromProviderEmail email = new UserAccountCreatedFromProviderEmail(getLocale()); + email.setUser(user); + email.setProvider(t("pollen.service.mail.loginProvider." + credential.getProvider())); + email.setProfileUrl(getUIContext().getProfileUrl()); + return email; + } + public UserAccountEditedEmail newUserAccountEditedEmail(PollenUser user) { UserAccountEditedEmail email = new UserAccountEditedEmail(getLocale()); email.setUser(user); diff --git a/pollen-services/src/main/java/org/chorem/pollen/services/service/mail/UserAccountCreatedFromProviderEmail.java b/pollen-services/src/main/java/org/chorem/pollen/services/service/mail/UserAccountCreatedFromProviderEmail.java new file mode 100644 index 00000000..8f7adec3 --- /dev/null +++ b/pollen-services/src/main/java/org/chorem/pollen/services/service/mail/UserAccountCreatedFromProviderEmail.java @@ -0,0 +1,76 @@ +package org.chorem.pollen.services.service.mail; + +/* + * #%L + * Pollen :: Service + * %% + * Copyright (C) 2009 - 2017 Code Lutin, Tony Chemit + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * #L% + */ + +import org.chorem.pollen.persistence.entity.PollenUser; +import org.nuiton.i18n.I18n; + +import java.util.Locale; + +/** + * Created on 4/30/14. + * + * @author Tony Chemit - dev@tchemit.fr + * @since 2.0 + */ +public class UserAccountCreatedFromProviderEmail extends PollenMail { + + private PollenUser user; + private String provider; + private String profileUrl; + + protected UserAccountCreatedFromProviderEmail(Locale locale) { + super(locale); + } + + @Override + public String getSubject() { + if (user.getName() == null) { + return I18n.l(locale, "pollen.service.mail.UserAccountCreatedFromProviderEmail.subject", user.getEmail()); + } + return I18n.l(locale, "pollen.service.mail.UserAccountCreatedFromProviderEmail.subject", user.getName()); + } + + public PollenUser getUser() { + return user; + } + + public void setUser(PollenUser user) { + this.user = user; + } + + public String getProvider() { + return provider; + } + + public void setProvider(String provider) { + this.provider = provider; + } + + public String getProfileUrl() { + return profileUrl; + } + + public void setProfileUrl(String profileUrl) { + this.profileUrl = profileUrl; + } +} diff --git a/pollen-services/src/main/resources/email/UserAccountCreatedFromProviderEmail.mustache b/pollen-services/src/main/resources/email/UserAccountCreatedFromProviderEmail.mustache new file mode 100644 index 00000000..e477bd98 --- /dev/null +++ b/pollen-services/src/main/resources/email/UserAccountCreatedFromProviderEmail.mustache @@ -0,0 +1,10 @@ +Welcome {{user.name}}, + +You have just signed in for the first time with your {{provider}} account. + +A Pollen account has ben automatically created with your profile information: +Name: {{user.name}} +Email: {{user.email}} + +You can edit this information in the following page: {{profileUrl}} +You also can set a password to sign in to Pollen without using {{provider}}. \ No newline at end of file diff --git a/pollen-services/src/main/resources/email/UserAccountCreatedFromProviderEmail_fr.mustache b/pollen-services/src/main/resources/email/UserAccountCreatedFromProviderEmail_fr.mustache new file mode 100644 index 00000000..7619d044 --- /dev/null +++ b/pollen-services/src/main/resources/email/UserAccountCreatedFromProviderEmail_fr.mustache @@ -0,0 +1,11 @@ +Bonjour {{user.name}}, + +Vous venez de vous connecter à Pollen pour la première fois à partir de votre compte {{provider}}. + +Un compte Pollen a été automatiquement créé avec les informations de votre profil : + +Nom : {{user.name}} +Courriel : {{user.email}} + +Vous pouvez modifier ces informations sur la page suivante : {{profileUrl}} +Vous pouvez également renseigner un mot de passe pour pouvoir vous connecter à Pollen sans passer par {{provider}}. \ No newline at end of file diff --git a/pollen-services/src/main/resources/i18n/pollen-services_en_GB.properties b/pollen-services/src/main/resources/i18n/pollen-services_en_GB.properties index aeb42167..b19d9a81 100644 --- a/pollen-services/src/main/resources/i18n/pollen-services_en_GB.properties +++ b/pollen-services/src/main/resources/i18n/pollen-services_en_GB.properties @@ -155,6 +155,7 @@ pollen.service.mail.PollVoteReminderEmail.subject=[Pollen] Reminder to vote on p pollen.service.mail.ResendValidationEmail.subject=[Pollen] Invitation to validate your account %s pollen.service.mail.RestrictedPollInvitationEmail.subject=[Pollen] Invitation to vote on poll %s pollen.service.mail.UserAccountCreatedEmail.subject=[Pollen] Confirmation of account creation %s +pollen.service.mail.UserAccountCreatedFromProviderEmail.subject=[Pollen] Confirmation of account creation %s pollen.service.mail.UserAccountDeletedEmail.subject=[Pollen] Confirmation of deletion of the account %s pollen.service.mail.UserAccountEditedEmail.subject=[Pollen] Update of the account %s pollen.service.mail.UserAccountEmailValidatedEmail.subject=[Pollen] Validation of your account %s @@ -164,3 +165,22 @@ pollen.service.mail.VoteDeletedEmail.subject=[Pollen] A vote was deleted in poll pollen.service.mail.VoteEditedEmail.subject=[Pollen] A vote was edited in poll %s pollen.service.mail.VoteSummaryEmail.subject=[Pollen] Summary of the votes since %s for the poll %s pollen.service.mail.feedbackEmail.subject=[Pollen] feedback - %s +pollen.service.mail.loginProvider.amazon=Amazon +pollen.service.mail.loginProvider.facebook=Facebook +pollen.service.mail.loginProvider.flickr=Flickr +pollen.service.mail.loginProvider.foursquare=Foursquare +pollen.service.mail.loginProvider.github=Github +pollen.service.mail.loginProvider.googleplus=Google +pollen.service.mail.loginProvider.hotmail=Hotmail +pollen.service.mail.loginProvider.instagram=Instagram +pollen.service.mail.loginProvider.linkedin=LinkedIn +pollen.service.mail.loginProvider.linkedin2=LinkedIn +pollen.service.mail.loginProvider.mendeley=Mendeley +pollen.service.mail.loginProvider.myspace=MySpace +pollen.service.mail.loginProvider.nimble=Nimble +pollen.service.mail.loginProvider.runkeeper=Runkeeper +pollen.service.mail.loginProvider.salesforce=Salesforce +pollen.service.mail.loginProvider.stackexchange=Stack Exchange +pollen.service.mail.loginProvider.twitter=Twitter +pollen.service.mail.loginProvider.yahoo=Yahoo +pollen.service.mail.loginProvider.yammer=Yammer diff --git a/pollen-services/src/main/resources/i18n/pollen-services_fr_FR.properties b/pollen-services/src/main/resources/i18n/pollen-services_fr_FR.properties index 5cd63aff..ab2f93c8 100644 --- a/pollen-services/src/main/resources/i18n/pollen-services_fr_FR.properties +++ b/pollen-services/src/main/resources/i18n/pollen-services_fr_FR.properties @@ -154,6 +154,7 @@ pollen.service.mail.PollVoteReminderEmail.subject=[Pollen] Rappel du vote au son pollen.service.mail.ResendValidationEmail.subject=[Pollen] Validez votre compte %s pollen.service.mail.RestrictedPollInvitationEmail.subject=[Pollen] Invitation au sondage %s pollen.service.mail.UserAccountCreatedEmail.subject=[Pollen] Confirmation de création du compte %s +pollen.service.mail.UserAccountCreatedFromProviderEmail.subject=[Pollen] Confirmation de création du compte %s pollen.service.mail.UserAccountDeletedEmail.subject=[Pollen] Confirmation de suppression du compte %s pollen.service.mail.UserAccountEditedEmail.subject=[Pollen] Édition du compte %s pollen.service.mail.UserAccountEmailValidatedEmail.subject=[Pollen] Valiation de votre compte %s @@ -162,3 +163,22 @@ pollen.service.mail.VoteAddedEmail.subject=[Pollen] Un nouveau vote a été ajou pollen.service.mail.VoteDeletedEmail.subject=[Pollen] Un vote a été supprimé sur le sondage %s pollen.service.mail.VoteEditedEmail.subject=[Pollen] Un vote a été modifié du sondage %s pollen.service.mail.feedbackEmail.subject=[Pollen] retour utilisateur - %s +pollen.service.mail.loginProvider.amazon=Amazon +pollen.service.mail.loginProvider.facebook=Facebook +pollen.service.mail.loginProvider.flickr=Flickr +pollen.service.mail.loginProvider.foursquare=Foursquare +pollen.service.mail.loginProvider.github=Github +pollen.service.mail.loginProvider.googleplus=Google +pollen.service.mail.loginProvider.hotmail=Hotmail +pollen.service.mail.loginProvider.instagram=Instagram +pollen.service.mail.loginProvider.linkedin=LinkedIn +pollen.service.mail.loginProvider.linkedin2=LinkedIn +pollen.service.mail.loginProvider.mendeley=Mendeley +pollen.service.mail.loginProvider.myspace=MySpace +pollen.service.mail.loginProvider.nimble=Nimble +pollen.service.mail.loginProvider.runkeeper=Runkeeper +pollen.service.mail.loginProvider.salesforce=Salesforce +pollen.service.mail.loginProvider.stackexchange=Stack Exchange +pollen.service.mail.loginProvider.twitter=Twitter +pollen.service.mail.loginProvider.yahoo=Yahoo +pollen.service.mail.loginProvider.yammer=Yammer diff --git a/pollen-services/src/test/java/org/chorem/pollen/services/service/PollenUIUrlRenderServiceTest.java b/pollen-services/src/test/java/org/chorem/pollen/services/service/PollenUIUrlRenderServiceTest.java index 2081fc10..41517f1e 100644 --- a/pollen-services/src/test/java/org/chorem/pollen/services/service/PollenUIUrlRenderServiceTest.java +++ b/pollen-services/src/test/java/org/chorem/pollen/services/service/PollenUIUrlRenderServiceTest.java @@ -47,6 +47,7 @@ public class PollenUIUrlRenderServiceTest extends AbstractPollenServiceTest { pollenUIContext.setPollEditUrl(UI_END_POINT + "/#poll/edit/{pollId}/{token}"); pollenUIContext.setPollVoteUrl(UI_END_POINT + "/#poll/vote/{pollId}/{token}"); pollenUIContext.setPollVoteEditUrl(UI_END_POINT + "/#poll/vote/{pollId}/{voteId}/{token}"); + pollenUIContext.setProfileUrl(UI_END_POINT + "/#user/profile"); } @Test diff --git a/pollen-ui-riot-js/src/main/web/js/Session.js b/pollen-ui-riot-js/src/main/web/js/Session.js index 77bcd203..57e5396e 100644 --- a/pollen-ui-riot-js/src/main/web/js/Session.js +++ b/pollen-ui-riot-js/src/main/web/js/Session.js @@ -46,7 +46,8 @@ class Session { pollVoteEditUrl: window.location.origin + "/#poll/{pollId}/vote/{voteId}/{token}", pollEditUrl: window.location.origin + "/#poll/{pollId}/edit/{token}", resourceUrl: this.configuration.endPoint + "/v1/resources/{resourceId}", - resourceDownloadUrl: this.configuration.endPoint + "/v1/resources/{resourceId}/download" + resourceDownloadUrl: this.configuration.endPoint + "/v1/resources/{resourceId}/download", + profileUrl: this.configuration.endPoint + "/#user/profile" }; // pour contenir les traductions this.i18n = { diff --git a/pollen-ui-riot-js/src/main/web/tag/SignIn.tag.html b/pollen-ui-riot-js/src/main/web/tag/SignIn.tag.html index f58786ac..10f992e7 100644 --- a/pollen-ui-riot-js/src/main/web/tag/SignIn.tag.html +++ b/pollen-ui-riot-js/src/main/web/tag/SignIn.tag.html @@ -52,7 +52,7 @@ require("./components/HumanInput.tag.html"); <div class="c-hint--static c-hint--error">{message}</div> <p><a onclick="{newPassword}">{__.lostpassword}</a></p> </div> - <div class="o-form-element align-center"> + <div class="o-form-element align-center" if="{loginProviders.length > 0}"> <p>Ou connectez vous avec votre compte :</p> <p> <a each="{loginProvider in loginProviders}" class="provider-link" -- 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/1_socialauth in repository pollen. See https://gitlab.nuiton.org/chorem/pollen.git commit 71bf50224f98ada5869279d08ddbaa50f16a178f Author: Kevin Morin <morin@codelutin.com> Date: Thu Aug 31 16:08:45 2017 +0200 refs #1 permettre l'ajout d'un mot de passe à des comptes créés à partir de service tiers --- .../java/org/chorem/pollen/services/bean/PollenUserBean.java | 12 +++++++++++- .../chorem/pollen/services/service/PollenUserService.java | 8 +++++--- .../service/security/PollenAuthenticationException.java | 4 ++++ .../pollen/services/service/security/SecurityService.java | 10 +++++++++- pollen-ui-riot-js/src/main/web/tag/UserProfile.tag.html | 11 ++++++++--- pollen-ui-riot-js/src/main/web/tag/poll/Polls.tag.html | 2 +- 6 files changed, 38 insertions(+), 9 deletions(-) diff --git a/pollen-services/src/main/java/org/chorem/pollen/services/bean/PollenUserBean.java b/pollen-services/src/main/java/org/chorem/pollen/services/bean/PollenUserBean.java index 9bb64057..42d33279 100644 --- a/pollen-services/src/main/java/org/chorem/pollen/services/bean/PollenUserBean.java +++ b/pollen-services/src/main/java/org/chorem/pollen/services/bean/PollenUserBean.java @@ -46,6 +46,8 @@ public class PollenUserBean extends PollenBean<PollenUser> { protected boolean emailIsValidate; + protected boolean withPassword; + public PollenUserBean() { super(PollenUser.class); } @@ -62,7 +64,7 @@ public class PollenUserBean extends PollenBean<PollenUser> { setEmail(entity.getEmail()); setPassword(entity.getPassword()); setEmailIsValidate(entity.getEmailActivationToken() == null); - + setWithPassword(entity.getPassword() != null); } @Override @@ -136,4 +138,12 @@ public class PollenUserBean extends PollenBean<PollenUser> { public void setBanned(boolean banned) { this.banned = banned; } + + public boolean isWithPassword() { + return withPassword; + } + + public void setWithPassword(boolean withPassword) { + this.withPassword = withPassword; + } } 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 b3cf72ef..5db9468d 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 @@ -82,8 +82,11 @@ public class PollenUserService extends PollenServiceSupport implements PollenSer checkIsConnected(); checkNotNull(userId); - PollenUser pollenUser = getUser0(userId); - + PollenUser pollenUser = getConnectedUser(); + if (!userId.equals(pollenUser.getTopiaId())) { + checkIsAdmin(); + pollenUser = getUser0(userId); + } return toBean(PollenUserBean.class, pollenUser, pollenUserFunction); } @@ -146,7 +149,6 @@ public class PollenUserService extends PollenServiceSupport implements PollenSer String newPassword) throws InvalidFormException { checkNotNull(userId); - checkNotNull(oldPassword); checkNotNull(newPassword); PollenUser user = getUser0(userId); diff --git a/pollen-services/src/main/java/org/chorem/pollen/services/service/security/PollenAuthenticationException.java b/pollen-services/src/main/java/org/chorem/pollen/services/service/security/PollenAuthenticationException.java index f2635c8a..85ac88cd 100644 --- a/pollen-services/src/main/java/org/chorem/pollen/services/service/security/PollenAuthenticationException.java +++ b/pollen-services/src/main/java/org/chorem/pollen/services/service/security/PollenAuthenticationException.java @@ -31,6 +31,10 @@ public class PollenAuthenticationException extends Exception { private static final long serialVersionUID = 1L; + public PollenAuthenticationException() { + super(); + } + public PollenAuthenticationException(Exception e) { super(e); } diff --git a/pollen-services/src/main/java/org/chorem/pollen/services/service/security/SecurityService.java b/pollen-services/src/main/java/org/chorem/pollen/services/service/security/SecurityService.java index 1ccb28bb..f351b350 100644 --- a/pollen-services/src/main/java/org/chorem/pollen/services/service/security/SecurityService.java +++ b/pollen-services/src/main/java/org/chorem/pollen/services/service/security/SecurityService.java @@ -25,6 +25,7 @@ import com.google.common.base.Joiner; import com.google.common.base.Preconditions; import com.google.common.collect.Sets; import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.shiro.authc.AuthenticationException; @@ -125,6 +126,10 @@ public class SecurityService extends PollenServiceSupport { public PollenEntityRef<PollenUser> login(String login, String password, Boolean rememberMe) throws PollenAuthenticationException, PollenEmailNotValidatedException, PollenUserBannedException { + if (StringUtils.isBlank(password)) { + throw new PollenAuthenticationException(); + } + Subject subject = getSubject(); UsernamePasswordToken token = new UsernamePasswordToken(login, password); if (rememberMe != null) { @@ -335,7 +340,10 @@ public class SecurityService extends PollenServiceSupport { public void checkUserPassword(PollenUser user, String password) throws PollenInvalidPasswordException { - String encodedPassword = serviceContext.encodePassword(user.getSalt(), password); + String encodedPassword = null; + if (password != null) { + encodedPassword = serviceContext.encodePassword(user.getSalt(), password); + } boolean valid = Objects.equals(encodedPassword, user.getPassword()); if (user.isBanned() || !valid) { throw new PollenInvalidPasswordException(); diff --git a/pollen-ui-riot-js/src/main/web/tag/UserProfile.tag.html b/pollen-ui-riot-js/src/main/web/tag/UserProfile.tag.html index c06bed10..f7e2eda0 100644 --- a/pollen-ui-riot-js/src/main/web/tag/UserProfile.tag.html +++ b/pollen-ui-riot-js/src/main/web/tag/UserProfile.tag.html @@ -64,7 +64,7 @@ require("./components/HumanInput.tag.html"); <form ref="password-form" class="password-form"> <HumanInput onsubmit={submitPassword}/> <h3 class="c-heading"><i class="fa fa-key"/> {__.passwordChange}</h3> - <div class="o-form-element"> + <div class="o-form-element" if="{user.withPassword}"> <label class="c-label" for="oldPassword">{__.oldPassword}</label> <input class="c-field {c-field--error : errors.oldPassword}" type="password" @@ -131,6 +131,7 @@ require("./components/HumanInput.tag.html"); this.user = session.getUser() || {}; let userService = require("../js/UserService"); let authService = require("../js/AuthService"); + let Message = require("../js/Message"); this.onUserChange = (user) => { this.user = user || {}; @@ -170,13 +171,17 @@ require("./components/HumanInput.tag.html"); this.checkPassword(); if (this.errors.repeatPassword === undefined) { - let oldPassword = this.refs.oldPassword.value; + let oldPassword = this.user.withPassword ? this.refs.oldPassword.value : null; let newPassword = this.refs.newPassword.value; userService.changePassword(this.user.id, oldPassword, newPassword).then(() => { - this.refs.oldPassword.value = ""; + if (this.user.withPassword) { + this.refs.oldPassword.value = ""; + } this.refs.newPassword.value = ""; this.refs.repeatPassword.value = ""; + this.user.withPassword = true; this.update(); + this.bus.trigger("message", new Message(this._l("updatedPassword"), "success")); }) .catch((errors) => { this.errors = errors; diff --git a/pollen-ui-riot-js/src/main/web/tag/poll/Polls.tag.html b/pollen-ui-riot-js/src/main/web/tag/poll/Polls.tag.html index 6f403e32..8fb9e3e7 100644 --- a/pollen-ui-riot-js/src/main/web/tag/poll/Polls.tag.html +++ b/pollen-ui-riot-js/src/main/web/tag/poll/Polls.tag.html @@ -96,7 +96,7 @@ require("../components/Search.tag.html"); return pollService.assignPoll(finds[1], finds[2]).then((result) => { if (result) { this.refresh(); - this.bus.trigger("message", new Message(this._l("assignSuccessMessage", result.title), "succes")); + this.bus.trigger("message", new Message(this._l("assignSuccessMessage", result.title), "success")); } else { this.bus.trigger("message", new Message(this.__.alreadyAssignMessage, "warning")); } -- 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/1_socialauth in repository pollen. See https://gitlab.nuiton.org/chorem/pollen.git commit 160da205f1bc5ecd8e6bef0ca67eaf3c7ab23c4e Author: Kevin Morin <morin@codelutin.com> Date: Mon Sep 4 15:21:58 2017 +0200 refs #1 permettre d'ajouter des comptes tiers à un compte existant --- .../persistence/entity/UserCredentialTopiaDao.java | 30 +++++++ .../db/migration/h2/V3_0_0_8__add_credentials.sql | 1 + .../postgresql/V3_0_0_8__add_credentials.sql | 1 + pollen-persistence/src/main/xmi/pollen.zargo | Bin 28069 -> 28138 bytes .../pollen/rest/api/PollenRestApiApplication.java | 4 +- .../PollenEmailAlreadyUsedExceptionMapper.java | 20 ----- ...rProviderAccountAlreadyUsedExceptionMapper.java | 20 +++++ .../org/chorem/pollen/rest/api/v1/ApiUtils.java | 2 + .../org/chorem/pollen/rest/api/v1/AuthApi.java | 11 ++- .../chorem/pollen/rest/api/v1/PollenUserApi.java | 39 +++++++-- .../pollen/services/bean/PollenUserBean.java | 21 +++++ .../pollen/services/bean/UserCredentialBean.java | 49 +++++++++++ .../pollen/services/service/PollenUserService.java | 1 + .../pollen/services/service/SocialAuthService.java | 90 +++++++++++++++++---- .../security/PollenEmailAlreadyUsedException.java | 11 --- ...EmailOrProviderAccountAlreadyUsedException.java | 11 +++ 16 files changed, 249 insertions(+), 62 deletions(-) diff --git a/pollen-persistence/src/main/java/org/chorem/pollen/persistence/entity/UserCredentialTopiaDao.java b/pollen-persistence/src/main/java/org/chorem/pollen/persistence/entity/UserCredentialTopiaDao.java new file mode 100644 index 00000000..68302fed --- /dev/null +++ b/pollen-persistence/src/main/java/org/chorem/pollen/persistence/entity/UserCredentialTopiaDao.java @@ -0,0 +1,30 @@ +package org.chorem.pollen.persistence.entity; + +import java.util.HashMap; +import java.util.Map; + +public class UserCredentialTopiaDao extends AbstractUserCredentialTopiaDao<UserCredential> { + + public boolean isCredentialValid(String provider, String credentialUserId, String userTopiaId, String email) { + String query = "SELECT COUNT(*)" + + " FROM " + PollenUser.class.getName() + " AS user RIGHT JOIN user." + PollenUser.PROPERTY_USER_CREDENTIAL + " AS credential" + + " WHERE" + + " (credential." + UserCredential.PROPERTY_PROVIDER + " = :provider" + + " AND credential." + UserCredential.PROPERTY_USER_ID + " = :credentialUserId)"; + if (email != null) { + query += " OR (user." + PollenUser.PROPERTY_TOPIA_ID + " = :userTopiaId" + + " AND credential." + UserCredential.PROPERTY_EMAIL + " = :credentialEmail)" + + " OR user." + PollenUser.PROPERTY_EMAIL + " = :userEmail"; + } + + Map<String, Object> params = new HashMap<>(); + params.put("provider", provider); + params.put("credentialUserId", credentialUserId); + if (email != null) { + params.put("userEmail", email); + params.put("userTopiaId", userTopiaId); + params.put("credentialEmail", email); + } + return count(query, params) == 0; + } +} diff --git a/pollen-persistence/src/main/resources/db/migration/h2/V3_0_0_8__add_credentials.sql b/pollen-persistence/src/main/resources/db/migration/h2/V3_0_0_8__add_credentials.sql index 1825b8ae..48fadea4 100644 --- a/pollen-persistence/src/main/resources/db/migration/h2/V3_0_0_8__add_credentials.sql +++ b/pollen-persistence/src/main/resources/db/migration/h2/V3_0_0_8__add_credentials.sql @@ -6,6 +6,7 @@ CREATE TABLE USERCREDENTIAL ( TOPIACREATEDATE TIMESTAMP, PROVIDER VARCHAR(255), USERID VARCHAR(255), + USERNAME VARCHAR(255), EMAIL VARCHAR(255), POLLENUSER VARCHAR(255), FOREIGN KEY (POLLENUSER) references POLLENUSER(TOPIAID) diff --git a/pollen-persistence/src/main/resources/db/migration/postgresql/V3_0_0_8__add_credentials.sql b/pollen-persistence/src/main/resources/db/migration/postgresql/V3_0_0_8__add_credentials.sql index 2280308e..d1f2803d 100644 --- a/pollen-persistence/src/main/resources/db/migration/postgresql/V3_0_0_8__add_credentials.sql +++ b/pollen-persistence/src/main/resources/db/migration/postgresql/V3_0_0_8__add_credentials.sql @@ -6,6 +6,7 @@ CREATE TABLE USERCREDENTIAL ( TOPIACREATEDATE TIMESTAMP, PROVIDER VARCHAR(255), USERID VARCHAR(255), + USERNAME VARCHAR(255), EMAIL VARCHAR(255), POLLENUSER VARCHAR(255), FOREIGN KEY (POLLENUSER) references POLLENUSER(TOPIAID) diff --git a/pollen-persistence/src/main/xmi/pollen.zargo b/pollen-persistence/src/main/xmi/pollen.zargo index 0f29e782..7ce056d6 100644 Binary files a/pollen-persistence/src/main/xmi/pollen.zargo and b/pollen-persistence/src/main/xmi/pollen.zargo differ diff --git a/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/PollenRestApiApplication.java b/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/PollenRestApiApplication.java index 271b223a..687e4f38 100644 --- a/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/PollenRestApiApplication.java +++ b/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/PollenRestApiApplication.java @@ -7,7 +7,7 @@ import org.chorem.pollen.rest.api.exceptionMappers.FavoriteListImportExceptionMa import org.chorem.pollen.rest.api.exceptionMappers.InvalidEntityLinkExceptionMapper; import org.chorem.pollen.rest.api.exceptionMappers.InvalidFormExceptionMapper; import org.chorem.pollen.rest.api.exceptionMappers.PollenAuthenticationExceptionMapper; -import org.chorem.pollen.rest.api.exceptionMappers.PollenEmailAlreadyUsedExceptionMapper; +import org.chorem.pollen.rest.api.exceptionMappers.PollenEmailOrProviderAccountAlreadyUsedExceptionMapper; import org.chorem.pollen.rest.api.exceptionMappers.PollenEmailNotValidatedExceptionMapper; import org.chorem.pollen.rest.api.exceptionMappers.PollenInvalidEmailActivationTokenExceptionMapper; import org.chorem.pollen.rest.api.exceptionMappers.PollenInvalidPermissionExceptionMapper; @@ -62,7 +62,7 @@ public class PollenRestApiApplication extends Application { new PollenInvalidPermissionExceptionMapper(), new PollenInvalidEmailActivationTokenExceptionMapper(), new PollenEmailNotValidatedExceptionMapper(), - new PollenEmailAlreadyUsedExceptionMapper(), + new PollenEmailOrProviderAccountAlreadyUsedExceptionMapper(), new PollenUserBannedExceptionMapper(), new InvalidFormExceptionMapper(), new FavoriteListImportExceptionMapper(), diff --git a/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/exceptionMappers/PollenEmailAlreadyUsedExceptionMapper.java b/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/exceptionMappers/PollenEmailAlreadyUsedExceptionMapper.java deleted file mode 100644 index 3b1ec37b..00000000 --- a/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/exceptionMappers/PollenEmailAlreadyUsedExceptionMapper.java +++ /dev/null @@ -1,20 +0,0 @@ -package org.chorem.pollen.rest.api.exceptionMappers; - -import org.chorem.pollen.services.service.security.PollenEmailAlreadyUsedException; - -import javax.ws.rs.core.Response; - -/** - * @author Sylvain Bavencoff - bavencoff@codelutin.com - */ -public class PollenEmailAlreadyUsedExceptionMapper extends PollenAbstractExceptionMapper<PollenEmailAlreadyUsedException> { - - public PollenEmailAlreadyUsedExceptionMapper() { - super(Response.Status.FORBIDDEN); - } - - @Override - protected Object getEntity(PollenEmailAlreadyUsedException exception) { - return "emailAlreadyUsed"; - } -} diff --git a/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/exceptionMappers/PollenEmailOrProviderAccountAlreadyUsedExceptionMapper.java b/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/exceptionMappers/PollenEmailOrProviderAccountAlreadyUsedExceptionMapper.java new file mode 100644 index 00000000..d6671c68 --- /dev/null +++ b/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/exceptionMappers/PollenEmailOrProviderAccountAlreadyUsedExceptionMapper.java @@ -0,0 +1,20 @@ +package org.chorem.pollen.rest.api.exceptionMappers; + +import org.chorem.pollen.services.service.security.PollenEmailOrProviderAccountAlreadyUsedException; + +import javax.ws.rs.core.Response; + +/** + * @author Sylvain Bavencoff - bavencoff@codelutin.com + */ +public class PollenEmailOrProviderAccountAlreadyUsedExceptionMapper extends PollenAbstractExceptionMapper<PollenEmailOrProviderAccountAlreadyUsedException> { + + public PollenEmailOrProviderAccountAlreadyUsedExceptionMapper() { + super(Response.Status.FORBIDDEN); + } + + @Override + protected Object getEntity(PollenEmailOrProviderAccountAlreadyUsedException exception) { + return "emailOrProviderAccountAlreadyUsed"; + } +} diff --git a/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/ApiUtils.java b/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/ApiUtils.java index cebdb51c..dec31e1b 100644 --- a/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/ApiUtils.java +++ b/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/ApiUtils.java @@ -27,6 +27,8 @@ import java.util.regex.Pattern; */ public class ApiUtils { + public static final String SOCIAL_AUTH_MANAGER_SESSION_KEY = "socialAuthManager"; + public static Response exportBeanToResponse(ExportBean exportBean) { InputStream inputStream = IOUtils.toInputStream(exportBean.getContent(), Charsets.UTF_8); diff --git a/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/AuthApi.java b/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/AuthApi.java index fc2ac99b..776a4f6c 100644 --- a/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/AuthApi.java +++ b/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/AuthApi.java @@ -80,7 +80,6 @@ public class AuthApi { public static final String COOKIE_POLLEN_AUTH = "pollen-auth"; private static final String COOKIE_POLLEN_CONNECTED = "pollen-connected"; private static final int COOKIE_MAX_AGE = 60 * 60 * 24 * 365; // 1 year - private static final String SOCIAL_AUTH_MANAGER_SESSION_KEY = "socialAuthManager"; public static Response.ResponseBuilder removeAuthCookie(Response.ResponseBuilder reponseBuilder) { @@ -203,7 +202,7 @@ public class AuthApi { throws Exception { SocialAuthManager socialAuthManager = socialAuthService.getSocialAuthManager(); - request.getSession(true).setAttribute(SOCIAL_AUTH_MANAGER_SESSION_KEY, socialAuthManager); + request.getSession(true).setAttribute(ApiUtils.SOCIAL_AUTH_MANAGER_SESSION_KEY, socialAuthManager); return socialAuthManager.getAuthenticationUrl(providerId, providerRedirection); } @@ -214,15 +213,15 @@ public class AuthApi { @Context SecurityService securityService, @Context PollenSecurityContext securityContext, @Context HttpServletRequest request, - @HeaderParam("authorization") String authorization) + String providerReturn) throws Exception { SocialAuthManager socialAuthManager = - (SocialAuthManager) request.getSession().getAttribute(SOCIAL_AUTH_MANAGER_SESSION_KEY); + (SocialAuthManager) request.getSession().getAttribute(ApiUtils.SOCIAL_AUTH_MANAGER_SESSION_KEY); //socialAuthManager - request.getSession().removeAttribute(SOCIAL_AUTH_MANAGER_SESSION_KEY); + request.getSession().removeAttribute(ApiUtils.SOCIAL_AUTH_MANAGER_SESSION_KEY); Gson gson = new Gson(); - Map<String, String> paramsMap = gson.fromJson(authorization, Map.class); + Map<String, String> paramsMap = gson.fromJson(providerReturn, Map.class); PollenEntityRef<PollenUser> userPollenEntityRef = socialAuthService.login(socialAuthManager, paramsMap); return getLoginResponseFromPollenUser(serviceContext, securityService, securityContext, userPollenEntityRef); 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 123e13c3..188b9ea7 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 @@ -21,7 +21,10 @@ package org.chorem.pollen.rest.api.v1; * #L% */ +import com.google.gson.Gson; +import org.brickred.socialauth.SocialAuthManager; import org.chorem.pollen.persistence.entity.PollenUser; +import org.chorem.pollen.persistence.entity.UserCredential; import org.chorem.pollen.rest.api.beans.ChangePasswordBean; import org.chorem.pollen.services.bean.PaginationParameterBean; import org.chorem.pollen.services.bean.PaginationResultBean; @@ -30,9 +33,11 @@ import org.chorem.pollen.services.bean.PollenEntityRef; import org.chorem.pollen.services.bean.PollenUserBean; import org.chorem.pollen.services.service.InvalidFormException; import org.chorem.pollen.services.service.PollenUserService; +import org.chorem.pollen.services.service.SocialAuthService; import org.chorem.pollen.services.service.security.PollenInvalidEmailActivationTokenException; import org.chorem.pollen.services.service.security.PollenSecurityContext; +import javax.servlet.http.HttpServletRequest; import javax.ws.rs.BeanParam; import javax.ws.rs.Consumes; import javax.ws.rs.DELETE; @@ -45,6 +50,7 @@ import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; import javax.ws.rs.core.Context; import javax.ws.rs.core.MediaType; +import java.util.Map; import java.util.Objects; /** @@ -65,7 +71,6 @@ public class PollenUserApi { @QueryParam("search") String search) { return pollenUserService.getUsers(paginationParameter, search); - } @Path("/users/connected") @@ -74,7 +79,6 @@ public class PollenUserApi { PollenUser pollenUser = securityContext.getPollenUser(); Objects.requireNonNull(pollenUser,"Could not find connected user"); return pollenUserService.getUser(pollenUser.getTopiaId()); - } @Path("/users/{userId}") @@ -83,7 +87,6 @@ public class PollenUserApi { @PathParam("userId") PollenEntityId<PollenUser> userId) { return pollenUserService.getUser(userId.getEntityId()); - } @Path("/users") @@ -92,7 +95,6 @@ public class PollenUserApi { PollenUserBean user) throws InvalidFormException { return pollenUserService.createUser(user); - } @Path("/users/{userId}") @@ -101,7 +103,6 @@ public class PollenUserApi { PollenUserBean user) throws InvalidFormException { return pollenUserService.editUser(user); - } @Path("/users/{userId}") @@ -111,7 +112,6 @@ public class PollenUserApi { @QueryParam("anonymize") boolean anonymize) { pollenUserService.deleteUser(userId.getEntityId(), anonymize); - } @Path("/users/{userId}") @@ -121,7 +121,6 @@ public class PollenUserApi { @QueryParam("token") String token) throws PollenInvalidEmailActivationTokenException { pollenUserService.validateUserEmail(userId.getEntityId(), token); - } @Path("/users/{userId}/password") @@ -131,6 +130,32 @@ public class PollenUserApi { ChangePasswordBean bean) throws InvalidFormException { pollenUserService.changePassword(userId.getEntityId(), bean.getOldPassword(), bean.getNewPassword()); + } + + @Path("/users/{userId}/credentials/{provider}") + @POST + public String addUserCredential(@Context SocialAuthService socialAuthService, + @Context HttpServletRequest request, + @PathParam("userId") PollenEntityId<PollenUser> userId, + @PathParam("provider") String provider, + String providerReturn) throws Exception { + + SocialAuthManager socialAuthManager = + (SocialAuthManager) request.getSession().getAttribute(ApiUtils.SOCIAL_AUTH_MANAGER_SESSION_KEY); + //socialAuthManager + request.getSession().removeAttribute(ApiUtils.SOCIAL_AUTH_MANAGER_SESSION_KEY); + Gson gson = new Gson(); + Map<String, String> paramsMap = gson.fromJson(providerReturn, Map.class); + return socialAuthService.addCredentialToUser(userId, socialAuthManager, paramsMap); + } + + @Path("/users/{userId}/credentials/{credentialId}") + @DELETE + public void deleteUserCredential(@Context SocialAuthService socialAuthService, + @Context HttpServletRequest request, + @PathParam("userId") PollenEntityId<PollenUser> userId, + @PathParam("credentialId") PollenEntityId<UserCredential> credentialId) throws Exception { + socialAuthService.deleteUserCredential(userId, credentialId); } } diff --git a/pollen-services/src/main/java/org/chorem/pollen/services/bean/PollenUserBean.java b/pollen-services/src/main/java/org/chorem/pollen/services/bean/PollenUserBean.java index 42d33279..d167d9eb 100644 --- a/pollen-services/src/main/java/org/chorem/pollen/services/bean/PollenUserBean.java +++ b/pollen-services/src/main/java/org/chorem/pollen/services/bean/PollenUserBean.java @@ -24,6 +24,10 @@ package org.chorem.pollen.services.bean; import org.chorem.pollen.persistence.entity.PollenUser; import org.chorem.pollen.persistence.entity.PollenUserImpl; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + /** * Created on 5/15/14. * @@ -48,6 +52,8 @@ public class PollenUserBean extends PollenBean<PollenUser> { protected boolean withPassword; + protected List<UserCredentialBean> credentials = new ArrayList<>(); + public PollenUserBean() { super(PollenUser.class); } @@ -65,6 +71,13 @@ public class PollenUserBean extends PollenBean<PollenUser> { setPassword(entity.getPassword()); setEmailIsValidate(entity.getEmailActivationToken() == null); setWithPassword(entity.getPassword() != null); + setCredentials(entity.getUserCredential().stream() + .map(userCredential -> { + UserCredentialBean userCredentialBean = new UserCredentialBean(); + userCredentialBean.fromEntity(userCredential); + return userCredentialBean; + }) + .collect(Collectors.toList())); } @Override @@ -146,4 +159,12 @@ public class PollenUserBean extends PollenBean<PollenUser> { public void setWithPassword(boolean withPassword) { this.withPassword = withPassword; } + + public List<UserCredentialBean> getCredentials() { + return credentials; + } + + public void setCredentials(List<UserCredentialBean> credentials) { + this.credentials = credentials; + } } diff --git a/pollen-services/src/main/java/org/chorem/pollen/services/bean/UserCredentialBean.java b/pollen-services/src/main/java/org/chorem/pollen/services/bean/UserCredentialBean.java new file mode 100644 index 00000000..d88f3444 --- /dev/null +++ b/pollen-services/src/main/java/org/chorem/pollen/services/bean/UserCredentialBean.java @@ -0,0 +1,49 @@ +package org.chorem.pollen.services.bean; + +import org.chorem.pollen.persistence.entity.UserCredential; +import org.chorem.pollen.persistence.entity.UserCredentialImpl; + +/** + * @author Kevin Morin (Code Lutin) + */ +public class UserCredentialBean extends PollenBean<UserCredential> { + + protected String provider; + protected String userName; + + protected UserCredentialBean() { + super(UserCredential.class); + } + + @Override + public void fromEntity(UserCredential entity) { + setEntityId(entity.getTopiaId()); + setProvider(entity.getProvider()); + setUserName(entity.getUserName()); + } + + @Override + public UserCredential toEntity() { + UserCredential entity = new UserCredentialImpl(); + entity.setTopiaId(getEntityId()); + entity.setProvider(getProvider()); + entity.setUserName(getUserName()); + return entity; + } + + public String getProvider() { + return provider; + } + + public void setProvider(String provider) { + this.provider = provider; + } + + public String getUserName() { + return userName; + } + + public void setUserName(String userName) { + this.userName = userName; + } +} 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 5db9468d..ae57949f 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 @@ -137,6 +137,7 @@ public class PollenUserService extends PollenServiceSupport implements PollenSer anonymizeUser(user); } + getUserCredentialDao().deleteAll(user.getUserCredential()); getPollenUserDao().delete(user); commit(); diff --git a/pollen-services/src/main/java/org/chorem/pollen/services/service/SocialAuthService.java b/pollen-services/src/main/java/org/chorem/pollen/services/service/SocialAuthService.java index 0132f818..bfa301af 100644 --- a/pollen-services/src/main/java/org/chorem/pollen/services/service/SocialAuthService.java +++ b/pollen-services/src/main/java/org/chorem/pollen/services/service/SocialAuthService.java @@ -16,9 +16,12 @@ import org.chorem.pollen.persistence.entity.PollenUserImpl; import org.chorem.pollen.persistence.entity.PollenUserTopiaDao; import org.chorem.pollen.persistence.entity.UserCredential; import org.chorem.pollen.persistence.entity.UserCredentialImpl; +import org.chorem.pollen.persistence.entity.UserCredentialTopiaDao; import org.chorem.pollen.services.bean.LoginProviderBean; +import org.chorem.pollen.services.bean.PollenEntityId; import org.chorem.pollen.services.bean.PollenEntityRef; -import org.chorem.pollen.services.service.security.PollenEmailAlreadyUsedException; +import org.chorem.pollen.services.service.security.PollenEmailOrProviderAccountAlreadyUsedException; +import org.chorem.pollen.services.service.security.PollenUnauthorizedException; import java.util.ArrayList; import java.util.List; @@ -46,30 +49,26 @@ public class SocialAuthService extends PollenServiceSupport { PollenUserTopiaDao userDao = getPollenUserDao(); Optional<PollenUser> pollenUserForCredential = userDao.tryFindUserWithCredential(p.getProviderId(), p.getValidatedId()); - String name = p.getDisplayName(); - if (name == null) { - name = p.getFirstName() + " " + p.getLastName(); - } - if (pollenUserForCredential.isPresent()) { - if (log.isInfoEnabled()) { - log.info("credentials found : " + name); + if (log.isDebugEnabled()) { + log.debug("credentials found"); } pollenUser = pollenUserForCredential.get(); } else if (userDao.emailExists(p.getEmail())) { - throw new PollenEmailAlreadyUsedException(); + throw new PollenEmailOrProviderAccountAlreadyUsedException(); } else { - if (log.isInfoEnabled()) { - log.info("create new user : " + name); + String name = p.getFullName(); + if (name == null) { + name = p.getFirstName() + " " + p.getLastName(); + } + + if (log.isDebugEnabled()) { + log.debug("create new user : " + name); } - UserCredential credential = new UserCredentialImpl(); - credential.setProvider(p.getProviderId()); - credential.setUserId(p.getValidatedId()); - credential.setEmail(p.getEmail()); - credential = getUserCredentialDao().create(credential); + UserCredential credential = createUserCredential(p); pollenUser = new PollenUserImpl(); pollenUser.setName(name); @@ -88,6 +87,51 @@ public class SocialAuthService extends PollenServiceSupport { return getSecurityService().getSessionTokenForUser(pollenUser); } + public String addCredentialToUser(PollenEntityId<PollenUser> userId, + SocialAuthManager manager, + Map<String, String> paramsMap) throws Exception { + + checkIsConnected(); + PollenUser connectedUser = getConnectedUser(); + if (!connectedUser.getTopiaId().equals(userId.getEntityId())) { + throw new PollenUnauthorizedException(userId.getReducedId()); + } + + AuthProvider provider = manager.connect(paramsMap); + + // get profile + Profile p = provider.getUserProfile(); + + boolean credentialValid = getUserCredentialDao().isCredentialValid(p.getProviderId(), + p.getValidatedId(), + connectedUser.getTopiaId(), + p.getEmail()); + if (!credentialValid) { + throw new PollenEmailOrProviderAccountAlreadyUsedException(); + } + + UserCredential credential = createUserCredential(p); + connectedUser.addUserCredential(credential); + commit(); + + return credential.getUserName(); + } + + protected UserCredential createUserCredential(Profile p) { + String accountName = p.getDisplayName(); + if (accountName == null) { + accountName = p.getFullName(); + } + + UserCredential credential = new UserCredentialImpl(); + credential.setProvider(p.getProviderId()); + credential.setUserId(p.getValidatedId()); + credential.setUserName(accountName); + credential.setEmail(p.getEmail()); + credential = getUserCredentialDao().create(credential); + return credential; + } + public SocialAuthManager getSocialAuthManager() throws Exception { //Create an instance of SocialAuthConfgi object SocialAuthConfig config = SocialAuthConfig.getDefault(); @@ -185,4 +229,18 @@ public class SocialAuthService extends PollenServiceSupport { dao.delete(dao.forTopiaIdEquals(providerId).findUnique()); commit(); } + + public void deleteUserCredential(PollenEntityId<PollenUser> userId, PollenEntityId<UserCredential> credentialId) { + checkNotNull(credentialId); + + checkIsConnected(); + PollenUser connectedUser = getConnectedUser(); + if (!connectedUser.getTopiaId().equals(userId.getEntityId())) { + throw new PollenUnauthorizedException(userId.getReducedId()); + } + + UserCredentialTopiaDao dao = getUserCredentialDao(); + dao.delete(dao.forTopiaIdEquals(credentialId.getEntityId()).findUnique()); + commit(); + } } diff --git a/pollen-services/src/main/java/org/chorem/pollen/services/service/security/PollenEmailAlreadyUsedException.java b/pollen-services/src/main/java/org/chorem/pollen/services/service/security/PollenEmailAlreadyUsedException.java deleted file mode 100644 index afd67772..00000000 --- a/pollen-services/src/main/java/org/chorem/pollen/services/service/security/PollenEmailAlreadyUsedException.java +++ /dev/null @@ -1,11 +0,0 @@ -package org.chorem.pollen.services.service.security; - -/** - * @author Kevin Morin (Code Lutin) - */ -public class PollenEmailAlreadyUsedException extends Exception { - - public PollenEmailAlreadyUsedException() { - super("emailAlreadyUsed"); - } -} diff --git a/pollen-services/src/main/java/org/chorem/pollen/services/service/security/PollenEmailOrProviderAccountAlreadyUsedException.java b/pollen-services/src/main/java/org/chorem/pollen/services/service/security/PollenEmailOrProviderAccountAlreadyUsedException.java new file mode 100644 index 00000000..cb5bf239 --- /dev/null +++ b/pollen-services/src/main/java/org/chorem/pollen/services/service/security/PollenEmailOrProviderAccountAlreadyUsedException.java @@ -0,0 +1,11 @@ +package org.chorem.pollen.services.service.security; + +/** + * @author Kevin Morin (Code Lutin) + */ +public class PollenEmailOrProviderAccountAlreadyUsedException extends Exception { + + public PollenEmailOrProviderAccountAlreadyUsedException() { + super("emailOrProviderAccountAlreadyUsed"); + } +} -- 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/1_socialauth in repository pollen. See https://gitlab.nuiton.org/chorem/pollen.git commit dee2bf14ea4cd597c5a2979f01c476f1c1180145 Author: Kevin Morin <morin@codelutin.com> Date: Tue Sep 5 16:08:48 2017 +0200 refs #1 ajout de credentials depuis le profil --- .../org/chorem/pollen/rest/api/v1/AuthApi.java | 2 +- pollen-ui-riot-js/src/main/web/js/AuthService.js | 19 ++++++-- pollen-ui-riot-js/src/main/web/js/Session.js | 2 +- pollen-ui-riot-js/src/main/web/js/UserService.js | 11 +++++ pollen-ui-riot-js/src/main/web/tag/Pollen.tag.html | 35 +++++++++++--- pollen-ui-riot-js/src/main/web/tag/SignIn.tag.html | 28 +++-------- .../src/main/web/tag/UserProfile.tag.html | 56 ++++++++++++++++++++-- .../src/main/web/tag/admin/Users.tag.html | 4 +- 8 files changed, 118 insertions(+), 39 deletions(-) diff --git a/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/AuthApi.java b/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/AuthApi.java index 776a4f6c..f7cc206a 100644 --- a/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/AuthApi.java +++ b/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/AuthApi.java @@ -216,7 +216,7 @@ public class AuthApi { String providerReturn) throws Exception { - SocialAuthManager socialAuthManager = + (SocialAuthManager) request.getSession().getAttribute(ApiUtils.SOCIAL_AUTH_MANAGER_SESSION_KEY); //socialAuthManager request.getSession().removeAttribute(ApiUtils.SOCIAL_AUTH_MANAGER_SESSION_KEY); 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 3fd1d1f1..aed4e7c4 100644 --- a/pollen-ui-riot-js/src/main/web/js/AuthService.js +++ b/pollen-ui-riot-js/src/main/web/js/AuthService.js @@ -25,6 +25,20 @@ class AuthService extends FetchService { constructor() { super(); + this.providerIcons = { + "amazon": "amazon", + "facebook": "facebook-official", + "flickr": "flickr", + "foursquare": "foursquare", + "github": "github", + "googleplus": "google", + "instagram": "instagram", + "linkedin": "linkedin", + "linkedin2": "linkedin", + "stackexchange": "stack-exchange", + "twitter": "twitter", + "yahoo": "yahoo" + }; } signIn(login, password) { @@ -73,10 +87,9 @@ class AuthService extends FetchService { } signInProvider(query) { - return this.fetch( + return this.post( "/v1/login/" + query.loginProvider, - "POST", - {Authorization: JSON.stringify(query)}); + JSON.stringify(query)); } getAllLoginProviders() { diff --git a/pollen-ui-riot-js/src/main/web/js/Session.js b/pollen-ui-riot-js/src/main/web/js/Session.js index 57e5396e..83049c93 100644 --- a/pollen-ui-riot-js/src/main/web/js/Session.js +++ b/pollen-ui-riot-js/src/main/web/js/Session.js @@ -174,7 +174,7 @@ class Session { } getProviderRedirectionUrl(provider) { - return this.pollenUIContext.uiEndPoint + "/?loginProvider=" + provider; + return this.pollenUIContext.uiEndPoint + "/?loginProvider=" + provider + "&action=signin"; } } diff --git a/pollen-ui-riot-js/src/main/web/js/UserService.js b/pollen-ui-riot-js/src/main/web/js/UserService.js index 58fe4c6e..32735ae2 100644 --- a/pollen-ui-riot-js/src/main/web/js/UserService.js +++ b/pollen-ui-riot-js/src/main/web/js/UserService.js @@ -62,6 +62,17 @@ class UserService extends FetchService { return this.post(url, body); } + linkProvider(userId, query) { + let url = this._getUrlPrefix(userId) + "/credentials/" + query.loginProvider; + let body = JSON.stringify(query); + return this.post(url, body); + } + + + unlinkProvider(userId, credentialId) { + let url = this._getUrlPrefix(userId) + "/credentials/" + credentialId; + return this.doDelete(url); + } } module.exports = singleton(UserService); diff --git a/pollen-ui-riot-js/src/main/web/tag/Pollen.tag.html b/pollen-ui-riot-js/src/main/web/tag/Pollen.tag.html index a64d7482..dbcddc0d 100644 --- a/pollen-ui-riot-js/src/main/web/tag/Pollen.tag.html +++ b/pollen-ui-riot-js/src/main/web/tag/Pollen.tag.html @@ -53,9 +53,11 @@ require("./popup/InformationPopup.tag.html"); <script type="es6"> let session = require("../js/Session"); - session.start(); this.installBundle(session, "main"); + + session.start(); this.pageTitle = undefined; + let userService = require("../js/UserService"); this.onLocaleChange = () => { this.updatePageTitle(); @@ -135,7 +137,7 @@ require("./popup/InformationPopup.tag.html"); }); route("/poll", () => { - if (!session.isConnected() && !session.getUser.administrator) { + if (!session.isConnected() && !session.getUser().administrator) { route("/signin?url=/poll"); } else { this.bus.trigger("pageChanged", "admin_polls"); @@ -144,7 +146,7 @@ require("./popup/InformationPopup.tag.html"); }); route("/user", () => { - if (!session.isConnected() && !session.getUser.administrator) { + if (!session.isConnected() && !session.getUser().administrator) { route("/signin?url=/user"); } else { this.bus.trigger("pageChanged", "admin_users"); @@ -233,19 +235,40 @@ require("./popup/InformationPopup.tag.html"); route(() => { var q = route.query(); if (q.loginProvider != null) { + if (q.action === "signin") { session.signInProvider(q).then(() => { let currentPage = localStorage.getItem("currentPage"); localStorage.removeItem("currentPage"); - location.href = session.pollenUIContext.uiEndPoint + "/" + currentPage; + location.replace(session.pollenUIContext.uiEndPoint + "/" + currentPage); }, (e) => { let currentPage = localStorage.getItem("currentPage"); localStorage.removeItem("currentPage"); - console.log(e); e.text().then(label => { - location.href = session.pollenUIContext.uiEndPoint + "/" + currentPage + "?error=" + label; + location.replace(session.pollenUIContext.uiEndPoint + "/" + currentPage + "?error=" + label); }); }); + } else if (q.action === "link" && session.isConnected()) { + let callback = (user) => { + userService.linkProvider(user.id, q).then((accountName) => { + location.replace(session.pollenUIContext.uiEndPoint + "/#user/profile"); + }, (e) => { + e.text().then(label => { + location.replace(session.pollenUIContext.uiEndPoint + "/#user/profile?error=" + label); + }); + }); + }; + + if (session.getUser()) { + callback(session.getUser()); + } else { + this.bus.on("user", (user) => { + callback(user); + this.bus.off("user", callback); + }); + } + } + } else { this.bus.trigger("pageChanged", "home"); riot.mount(this.refs.content, "home"); diff --git a/pollen-ui-riot-js/src/main/web/tag/SignIn.tag.html b/pollen-ui-riot-js/src/main/web/tag/SignIn.tag.html index 10f992e7..ada0bdf3 100644 --- a/pollen-ui-riot-js/src/main/web/tag/SignIn.tag.html +++ b/pollen-ui-riot-js/src/main/web/tag/SignIn.tag.html @@ -53,12 +53,12 @@ require("./components/HumanInput.tag.html"); <p><a onclick="{newPassword}">{__.lostpassword}</a></p> </div> <div class="o-form-element align-center" if="{loginProviders.length > 0}"> - <p>Ou connectez vous avec votre compte :</p> + <p>{__.signinWithProvider}</p> <p> <a each="{loginProvider in loginProviders}" class="provider-link" onclick="{signinWithProvider(loginProvider)}"> - <i class="fa fa-{providerIcons[loginProvider]}" if="{providerIcons[loginProvider]}"></i> - <span if="{!providerIcons[loginProvider]}">{loginProvider}</span> + <i class="fa fa-{authService.providerIcons[loginProvider]}" if="{authService.providerIcons[loginProvider]}"></i> + <span if="{!authService.providerIcons[loginProvider]}">{loginProvider}</span> </a> </p> </div> @@ -81,25 +81,10 @@ require("./components/HumanInput.tag.html"); this.message = ""; this.openSignIn = false; - this.providerIcons = { - "amazon": "amazon", - "facebook": "facebook-official", - "flickr": "flickr", - "foursquare": "foursquare", - "github": "github", - "googleplus": "google", - "instagram": "instagram", - "linkedin": "linkedin", - "linkedin2": "linkedin", - "stackexchange": "stack-exchange", - "twitter": "twitter", - "yahoo": "yahoo" - }; - - let authService = require("../js/AuthService"); + this.authService = require("../js/AuthService"); this.loginProviders = []; this.on("mount", () => { - authService.getActiveLoginProviders().then((result) => { + this.authService.getActiveLoginProviders().then((result) => { this.loginProviders = result; this.update(); }); @@ -140,9 +125,8 @@ require("./components/HumanInput.tag.html"); this.signinWithProvider = (provider) => (e) => { let currentPage = location.hash || "#"; localStorage.setItem("currentPage", currentPage); - let authService = require("../js/AuthService"); let redirection = encodeURIComponent(this.session.getProviderRedirectionUrl(provider)); - authService.getLoginProviderUrl(provider, redirection).then(result => { + this.authService.getLoginProviderUrl(provider, redirection).then(result => { location.href = result; }); }; diff --git a/pollen-ui-riot-js/src/main/web/tag/UserProfile.tag.html b/pollen-ui-riot-js/src/main/web/tag/UserProfile.tag.html index f7e2eda0..d036bbe2 100644 --- a/pollen-ui-riot-js/src/main/web/tag/UserProfile.tag.html +++ b/pollen-ui-riot-js/src/main/web/tag/UserProfile.tag.html @@ -59,6 +59,28 @@ require("./components/HumanInput.tag.html"); {__.saveIdentity} </button> </div> + + <div> + <div each="{credential in user.credentials}" class="credential"> + <i if="{authService.providerIcons[credential.provider]}" + class="fa fa-{authService.providerIcons[credential.provider]}"></i> + <span if="{!authService.providerIcons[credential.provider]}">{credential.userName}</span> + <span>{credential.userName}</span> + <a if="{user.withPassword && user.email || user.credentials.length > 1}" + onclick="{unlinkProvider(credential.id)}">X</a> + </div> + </div> + + <div class="o-form-element align-center" if="{loginProviders.length > 0}"> + <p>{__.linkProvider}</p> + <p> + <a each="{loginProvider in loginProviders}" class="provider-link" + onclick="{linkProvider(loginProvider)}"> + <i class="fa fa-{authService.providerIcons[loginProvider]}" if="{authService.providerIcons[loginProvider]}"></i> + <span if="{!authService.providerIcons[loginProvider]}">{loginProvider}</span> + </a> + </p> + </div> </form> <form ref="password-form" class="password-form"> @@ -130,16 +152,22 @@ require("./components/HumanInput.tag.html"); this.errors = {}; this.user = session.getUser() || {}; let userService = require("../js/UserService"); - let authService = require("../js/AuthService"); + this.authService = require("../js/AuthService"); let Message = require("../js/Message"); + this.loginProviders = []; + this.authService.getActiveLoginProviders().then((result) => { + this.loginProviders = result; + this.update(); + }); + this.onUserChange = (user) => { this.user = user || {}; this.update(); }; this.resendValidation = () => { - authService.resendValidation(this.user.email); + this.authService.resendValidation(this.user.email); }; this.submitIdentity = e => { @@ -179,8 +207,8 @@ require("./components/HumanInput.tag.html"); } this.refs.newPassword.value = ""; this.refs.repeatPassword.value = ""; - this.user.withPassword = true; this.update(); + session.updateUser(); this.bus.trigger("message", new Message(this._l("updatedPassword"), "success")); }) .catch((errors) => { @@ -190,6 +218,20 @@ require("./components/HumanInput.tag.html"); } }; + this.linkProvider = (provider) => (e) => { + let redirection = encodeURIComponent(location.origin + location.pathname + + "?loginProvider=" + provider + "&action=link"); + this.authService.getLoginProviderUrl(provider, redirection).then(result => { + location.assign(result); + }); + }; + + this.unlinkProvider = (credentialId) => (e) => { + userService.unlinkProvider(this.user.id, credentialId).then(result => { + console.log("ok"); + }); + }; + this.listen("user", this.onUserChange); </script> @@ -208,6 +250,14 @@ require("./components/HumanInput.tag.html"); padding: 0 5px; } + .credential { + font-size: 1.5em; + } + + .provider-link { + font-size: 2em; + } + </style> </UserProfile> diff --git a/pollen-ui-riot-js/src/main/web/tag/admin/Users.tag.html b/pollen-ui-riot-js/src/main/web/tag/admin/Users.tag.html index 286538ad..fa33c0f6 100644 --- a/pollen-ui-riot-js/src/main/web/tag/admin/Users.tag.html +++ b/pollen-ui-riot-js/src/main/web/tag/admin/Users.tag.html @@ -47,11 +47,9 @@ require("./UserCard.tag.html"); this.lazyLoad = pagination => { return userService.users(pagination, this.search.value).then((result) => { - if (!this.loaded) { + this.loaded = true; this.count = result.pagination.count; - this.loaded = true; this.update(); - } return result; }); }; -- 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/1_socialauth in repository pollen. See https://gitlab.nuiton.org/chorem/pollen.git commit aacfec6e28d17fea5a2904b6ce2fbbf6de70246c Author: Kevin Morin <morin@codelutin.com> Date: Tue Sep 5 16:48:06 2017 +0200 fix build --- .../main/java/org/chorem/pollen/rest/api/v1/AuthApi.java | 2 +- .../org/chorem/pollen/services/bean/PollenUserBean.java | 16 +++++++++------- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/AuthApi.java b/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/AuthApi.java index f7cc206a..776a4f6c 100644 --- a/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/AuthApi.java +++ b/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/AuthApi.java @@ -216,7 +216,7 @@ public class AuthApi { String providerReturn) throws Exception { - + SocialAuthManager socialAuthManager = (SocialAuthManager) request.getSession().getAttribute(ApiUtils.SOCIAL_AUTH_MANAGER_SESSION_KEY); //socialAuthManager request.getSession().removeAttribute(ApiUtils.SOCIAL_AUTH_MANAGER_SESSION_KEY); diff --git a/pollen-services/src/main/java/org/chorem/pollen/services/bean/PollenUserBean.java b/pollen-services/src/main/java/org/chorem/pollen/services/bean/PollenUserBean.java index d167d9eb..e1a28095 100644 --- a/pollen-services/src/main/java/org/chorem/pollen/services/bean/PollenUserBean.java +++ b/pollen-services/src/main/java/org/chorem/pollen/services/bean/PollenUserBean.java @@ -71,13 +71,15 @@ public class PollenUserBean extends PollenBean<PollenUser> { setPassword(entity.getPassword()); setEmailIsValidate(entity.getEmailActivationToken() == null); setWithPassword(entity.getPassword() != null); - setCredentials(entity.getUserCredential().stream() - .map(userCredential -> { - UserCredentialBean userCredentialBean = new UserCredentialBean(); - userCredentialBean.fromEntity(userCredential); - return userCredentialBean; - }) - .collect(Collectors.toList())); + if (entity.getUserCredential() != null) { + setCredentials(entity.getUserCredential().stream() + .map(userCredential -> { + UserCredentialBean userCredentialBean = new UserCredentialBean(); + userCredentialBean.fromEntity(userCredential); + return userCredentialBean; + }) + .collect(Collectors.toList())); + } } @Override -- 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/1_socialauth in repository pollen. See https://gitlab.nuiton.org/chorem/pollen.git commit e36db9ab487847ece02d8a6a3fd4a8e31bf7a2e9 Author: Kevin Morin <morin@codelutin.com> Date: Thu Sep 7 10:48:45 2017 +0200 refs #1 mise en page des comptes externes dans le profil --- .../pollen/services/bean/UserCredentialBean.java | 11 ++++ pollen-ui-riot-js/src/main/web/css/custom.css | 2 + .../src/main/web/tag/UserProfile.tag.html | 73 +++++++++++++++------- 3 files changed, 62 insertions(+), 24 deletions(-) diff --git a/pollen-services/src/main/java/org/chorem/pollen/services/bean/UserCredentialBean.java b/pollen-services/src/main/java/org/chorem/pollen/services/bean/UserCredentialBean.java index d88f3444..85b44ae1 100644 --- a/pollen-services/src/main/java/org/chorem/pollen/services/bean/UserCredentialBean.java +++ b/pollen-services/src/main/java/org/chorem/pollen/services/bean/UserCredentialBean.java @@ -10,6 +10,7 @@ public class UserCredentialBean extends PollenBean<UserCredential> { protected String provider; protected String userName; + protected String emailAddress; protected UserCredentialBean() { super(UserCredential.class); @@ -20,6 +21,7 @@ public class UserCredentialBean extends PollenBean<UserCredential> { setEntityId(entity.getTopiaId()); setProvider(entity.getProvider()); setUserName(entity.getUserName()); + setEmailAddress(entity.getEmail()); } @Override @@ -28,6 +30,7 @@ public class UserCredentialBean extends PollenBean<UserCredential> { entity.setTopiaId(getEntityId()); entity.setProvider(getProvider()); entity.setUserName(getUserName()); + entity.setEmail(getEmailAddress()); return entity; } @@ -46,4 +49,12 @@ public class UserCredentialBean extends PollenBean<UserCredential> { public void setUserName(String userName) { this.userName = userName; } + + public String getEmailAddress() { + return emailAddress; + } + + public void setEmailAddress(String emailAddress) { + this.emailAddress = emailAddress; + } } diff --git a/pollen-ui-riot-js/src/main/web/css/custom.css b/pollen-ui-riot-js/src/main/web/css/custom.css index 5dd7b38c..dbbd4d85 100644 --- a/pollen-ui-riot-js/src/main/web/css/custom.css +++ b/pollen-ui-riot-js/src/main/web/css/custom.css @@ -93,4 +93,6 @@ --report: rgba(0,0,0,0.05); --report-hover: #04c4bb; + + --list-alternate-row: #f3f3f3; } diff --git a/pollen-ui-riot-js/src/main/web/tag/UserProfile.tag.html b/pollen-ui-riot-js/src/main/web/tag/UserProfile.tag.html index d036bbe2..3f30abfd 100644 --- a/pollen-ui-riot-js/src/main/web/tag/UserProfile.tag.html +++ b/pollen-ui-riot-js/src/main/web/tag/UserProfile.tag.html @@ -59,28 +59,6 @@ require("./components/HumanInput.tag.html"); {__.saveIdentity} </button> </div> - - <div> - <div each="{credential in user.credentials}" class="credential"> - <i if="{authService.providerIcons[credential.provider]}" - class="fa fa-{authService.providerIcons[credential.provider]}"></i> - <span if="{!authService.providerIcons[credential.provider]}">{credential.userName}</span> - <span>{credential.userName}</span> - <a if="{user.withPassword && user.email || user.credentials.length > 1}" - onclick="{unlinkProvider(credential.id)}">X</a> - </div> - </div> - - <div class="o-form-element align-center" if="{loginProviders.length > 0}"> - <p>{__.linkProvider}</p> - <p> - <a each="{loginProvider in loginProviders}" class="provider-link" - onclick="{linkProvider(loginProvider)}"> - <i class="fa fa-{authService.providerIcons[loginProvider]}" if="{authService.providerIcons[loginProvider]}"></i> - <span if="{!authService.providerIcons[loginProvider]}">{loginProvider}</span> - </a> - </p> - </div> </form> <form ref="password-form" class="password-form"> @@ -142,6 +120,32 @@ require("./components/HumanInput.tag.html"); </button> </div> </form> + + <div class="providers"> + <h3 class="c-heading"><i class="fa fa-sign-in"/> {__.loginProviders}</h3> + <div class="user-credentials"> + <div each="{credential, index in user.credentials}" class="user-credential {index % 2 == 0 ? 'even' : 'odd'}"> + <i if="{authService.providerIcons[credential.provider]}" + class="fa fa-{authService.providerIcons[credential.provider]}"></i> + <span if="{!authService.providerIcons[credential.provider]}">{credential.userName}</span> + <span class="credential-name">{credential.userName} <em if="{credential.emailAddress}">({credential.emailAddress})</em></span> + <button if="{user.withPassword && user.email || user.credentials.length > 1}" + onclick="{unlinkProvider(credential.id)}" class="c-button u-small c-button--error"><i class="fa fa-trash"></i></button> + </div> + </div> + + <div class="o-form-element align-center" if="{loginProviders.length > 0}"> + <p>{__.linkProvider}</p> + <p> + <a each="{loginProvider in loginProviders}" class="provider-link" + onclick="{linkProvider(loginProvider)}"> + <i class="fa fa-{authService.providerIcons[loginProvider]}" if="{authService.providerIcons[loginProvider]}"></i> + <span if="{!authService.providerIcons[loginProvider]}">{loginProvider}</span> + </a> + </p> + </div> + </div> + </div> </div> @@ -250,8 +254,29 @@ require("./components/HumanInput.tag.html"); padding: 0 5px; } - .credential { - font-size: 1.5em; + .providers { + padding: 0 10px; + } + + .user-credentials { + width: 100%; + } + + .user-credential { + display: flex; + justify-content: space-around; + align-items: center; + margin: 1px 0; + padding: 1px 5px; + } + + .user-credential.odd { + background-color: var(--list-alternate-row); + } + + .credential-name { + flex-grow: 1; + padding: 0 5px; } .provider-link { -- 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/1_socialauth in repository pollen. See https://gitlab.nuiton.org/chorem/pollen.git commit b34a7a0268cb8d062d8ac3161ea90ece5d7000de Author: Kevin Morin <morin@codelutin.com> Date: Thu Sep 7 11:01:10 2017 +0200 refs #1 gestion de la suppression des credentials --- pollen-ui-riot-js/src/main/web/tag/UserProfile.tag.html | 14 ++++++++++---- .../src/main/web/tag/admin/LoginProviders.tag.html | 2 +- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/pollen-ui-riot-js/src/main/web/tag/UserProfile.tag.html b/pollen-ui-riot-js/src/main/web/tag/UserProfile.tag.html index 3f30abfd..19256cf4 100644 --- a/pollen-ui-riot-js/src/main/web/tag/UserProfile.tag.html +++ b/pollen-ui-riot-js/src/main/web/tag/UserProfile.tag.html @@ -130,7 +130,7 @@ require("./components/HumanInput.tag.html"); <span if="{!authService.providerIcons[credential.provider]}">{credential.userName}</span> <span class="credential-name">{credential.userName} <em if="{credential.emailAddress}">({credential.emailAddress})</em></span> <button if="{user.withPassword && user.email || user.credentials.length > 1}" - onclick="{unlinkProvider(credential.id)}" class="c-button u-small c-button--error"><i class="fa fa-trash"></i></button> + onclick="{unlinkProvider(credential.id, index)}" class="c-button u-small c-button--error"><i class="fa fa-trash"></i></button> </div> </div> @@ -230,9 +230,15 @@ require("./components/HumanInput.tag.html"); }); }; - this.unlinkProvider = (credentialId) => (e) => { - userService.unlinkProvider(this.user.id, credentialId).then(result => { - console.log("ok"); + this.unlinkProvider = (credentialId, index) => (e) => { + this.confirm(this.__.unlinkProviderMessage).then((confirm) => { + if (!confirm) { + return Promise.reject(); + } + return userService.unlinkProvider(this.user.id, credentialId) + }).then(result => { + this.user.credentials.splice(index, 1); + this.update(); }); }; diff --git a/pollen-ui-riot-js/src/main/web/tag/admin/LoginProviders.tag.html b/pollen-ui-riot-js/src/main/web/tag/admin/LoginProviders.tag.html index 29e16779..883c0b24 100644 --- a/pollen-ui-riot-js/src/main/web/tag/admin/LoginProviders.tag.html +++ b/pollen-ui-riot-js/src/main/web/tag/admin/LoginProviders.tag.html @@ -87,7 +87,7 @@ require("../components/HumanInput.tag.html"); if (!confirm) { return Promise.reject(); } - if (confirm && loginProvider.id) { + if (loginProvider.id) { return authService.deleteLoginProvider(loginProvider); } }) -- 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/1_socialauth in repository pollen. See https://gitlab.nuiton.org/chorem/pollen.git commit d545965b3d120aff578b104343582cd7a955fe8c Author: Kevin Morin <morin@codelutin.com> Date: Thu Sep 7 11:22:15 2017 +0200 refs #1 séparaion des langues --- pollen-ui-riot-js/src/main/web/i18n/en.json | 20 +++++++++++++++++++- pollen-ui-riot-js/src/main/web/i18n/fr.json | 20 +++++++++++++++++++- 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/pollen-ui-riot-js/src/main/web/i18n/en.json b/pollen-ui-riot-js/src/main/web/i18n/en.json index 26bedde7..7d9b3a81 100644 --- a/pollen-ui-riot-js/src/main/web/i18n/en.json +++ b/pollen-ui-riot-js/src/main/web/i18n/en.json @@ -12,6 +12,7 @@ "main_editPoll" : "Poll edition", "main_userProfile" : "My profile", "main_favoriteLists" : "List of favorites", + "main_emailOrProviderAccountAlreadyUsed": "The email address of the account you are connecting with is already used by another Pollen account.", "pagination_all": "All", "pagination_resultsPerPage": "Results per page", "summary_choices": "Choices", @@ -198,6 +199,7 @@ "signin_password_placeholder": "Enter your password", "signin_lostpassword": "Lost password?", "signin_connexion": "Connect", + "signin_signinWithProvider": "Or sign in with your account:", "signin_error_signin_emailOrPasswordInvalid": "Email or password invalid", "signin_error_signin_banned": "Bloked account", "signin_error_signin_emailNotValidated": "You must validate your account before connecting. Check your emails, we sent you an activation link.", @@ -222,6 +224,7 @@ "header_myParticipatedPolls": "Participated polls", "header_polls": "Polls", "header_users": "Users", + "header_loginProviders": "Login providers", "header_myFavoriteLists": "My favorite lists", "header_createOtherPoll": "New standard poll", "header_createDatePoll": "New date poll", @@ -387,6 +390,10 @@ "userProfile_repeatPassword_placeholder": "Confirm your new password", "userProfile_repeatPassword_error": "The two passwords are not identical.", "userProfile_savePassword": "Save", + "userProfile_updatedPassword": "Your password has been updated", + "userProfile_loginProviders": "External accounts", + "userProfile_linkProvider": "Link an external account to connect to Pollen:", + "userProfile_unlinkProviderMessage": "Unlink this external account? You will not be able to connect to your Pollen account with this external account.", "choice_description_placeholder": "You can enter a description for this choice", "date-picker_today": "Today", "date-picker_dateplaceholder": "Date", @@ -531,5 +538,16 @@ "feedback_description": "Thank to details below your bug report ou your observation", "feedback_descriptionNotBlank": "Observation must be not blank", "feedback_uploadScreenShot": "Screenshot", - "feedback_create_success": "Observation has benn send." + "feedback_create_success": "Observation has been send.", + "loginProviders_title": "Login provider", + "loginProviders_name": "Name", + "loginProviders_key": "Client key", + "loginProviders_secret": "Secret code", + "loginProviders_permissions": "Permissions", + "loginProviders_active": "Active", + "loginProviders_newProvider": "New provider", + "loginProviders_deleteMessage": "Are you sure you want to delete this provider?", + "loginProviders_emptyName": "The name is mandatory", + "loginProviders_emptyKey": "The client key is mandatory", + "loginProviders_emptySecret": "The secret code is mandatory" } diff --git a/pollen-ui-riot-js/src/main/web/i18n/fr.json b/pollen-ui-riot-js/src/main/web/i18n/fr.json index 1893e0eb..9efd0d21 100644 --- a/pollen-ui-riot-js/src/main/web/i18n/fr.json +++ b/pollen-ui-riot-js/src/main/web/i18n/fr.json @@ -12,6 +12,7 @@ "main_editPoll" : "Edition du sondage", "main_userProfile" : "Mon profil", "main_favoriteLists" : "Listes de votants", + "main_emailOrProviderAccountAlreadyUsed": "L'adresse email du compte avec lequel vous essayez de vous connecter, est déjà utilisée par un autre compte Pollen.", "pagination_all": "Tous", "pagination_resultsPerPage": "Résultats par page", "summary_choices": "Choix", @@ -198,6 +199,7 @@ "signin_password_placeholder": "Entrez votre mot de passe", "signin_lostpassword": "Mot de passe perdu ?", "signin_connexion": "Se connecter", + "signin_signinWithProvider": "Ou connectez vous avec votre compte :", "signin_error_signin_emailOrPasswordInvalid": "Courriel ou mot de passe invalide", "signin_error_signin_banned": "Compte bloqué", "signin_error_signin_emailNotValidated": "Vous devez valider votre compte avant de pouvoir vous connecter. Relevez vos emails, nous vous avons envoyé un lien de validation.", @@ -222,6 +224,7 @@ "header_myParticipatedPolls": "Mes participations", "header_polls": "Sondages", "header_users": "Utilisateurs", + "header_loginProviders": "Tiers de connexion", "header_myFavoriteLists": "Mes listes de votants", "header_createOtherPoll": "Nouveau sondage standard", "header_createDatePoll": "Nouveau sondage de dates", @@ -387,6 +390,10 @@ "userProfile_repeatPassword_placeholder": "Répétez votre mot de passe", "userProfile_repeatPassword_error": "Les deux mots de passe ne sont pas identiques.", "userProfile_savePassword": "Enregistrer", + "userProfile_updatedPassword": "Votre mot de passe a été mis à jour", + "userProfile_loginProviders": "Comptes externes", + "userProfile_linkProvider": "Associez un compte externe pour vous connecter à Pollen :", + "userProfile_unlinkProviderMessage": "Désassossier ce compte externe ? Vous ne pourrez plus vous connectez à votre compte Pollen avec ce compte externe.", "choice_description_placeholder": "Vous pouvez saisir une description pour ce choix", "date-picker_today": "Aujourd'hui", "date-picker_dateplaceholder": "Date", @@ -531,5 +538,16 @@ "feedback_description": "Merci de détailler ci-dessous votre rapport de bug ou votre remarque", "feedback_descriptionNotBlank": "La description ne doit pas être blanc", "feedback_uploadScreenShot": "Copie d'écran", - "feedback_create_success": "La remarque est envoyée." + "feedback_create_success": "La remarque est envoyée.", + "loginProviders_title": "Tiers pour la connexion", + "loginProviders_name": "Nom", + "loginProviders_key": "Clé client", + "loginProviders_secret": "Code secret", + "loginProviders_permissions": "Permissions", + "loginProviders_active": "Actif", + "loginProviders_newProvider": "Nouveau tiers", + "loginProviders_deleteMessage": "Êtes-vous sûr de vouloir supprimer ce tier ?", + "loginProviders_emptyName": "Le nom est obligatoire", + "loginProviders_emptyKey": "La clé client est obligatoire", + "loginProviders_emptySecret": "Le code secret est obligatoire" } -- To stop receiving notification emails like this one, please contact chorem.org SCM administrator <admin+scm@chorem.org>.
participants (1)
-
chorem.org scm