2 * Copyright (C) 2016 - 2020 Free Software Foundation
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU Affero General Public License as
6 * published by the Free Software Foundation, either version 3 of the
7 * License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU Affero General Public License for more details.
14 * You should have received a copy of the GNU Affero General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 package org.mxchange.jjobs.beans.user;
19 import java.text.MessageFormat;
20 import java.util.Objects;
22 import javax.enterprise.context.RequestScoped;
23 import javax.enterprise.event.Event;
24 import javax.enterprise.event.Observes;
25 import javax.enterprise.inject.Any;
26 import javax.faces.context.FacesContext;
27 import javax.faces.view.facelets.FaceletException;
28 import javax.inject.Inject;
29 import javax.inject.Named;
30 import org.mxchange.jcontacts.model.contact.Contact;
31 import org.mxchange.jcoreee.events.locale.ObservableLocaleChangeEvent;
32 import org.mxchange.jjobs.beans.BaseJobsBean;
33 import org.mxchange.jjobs.beans.contact.JobsContactWebRequestController;
34 import org.mxchange.jjobs.beans.features.JobsFeaturesWebApplicationController;
35 import org.mxchange.jjobs.beans.user.login.JobsUserLoginWebSessionController;
36 import org.mxchange.jusercore.events.user.add.ObservableAdminAddedUserEvent;
37 import org.mxchange.jusercore.events.user.clear.password.ObservableClearUserPasswordEvent;
38 import org.mxchange.jusercore.events.user.clear.username.ObservableClearUserNameEvent;
39 import org.mxchange.jusercore.events.user.created.ObservableCreatedUserEvent;
40 import org.mxchange.jusercore.events.user.linked.ObservableAdminLinkedUserEvent;
41 import org.mxchange.jusercore.events.user.update.ObservableUpdatedUserPersonalDataEvent;
42 import org.mxchange.jusercore.events.user.update.UpdatedUserPersonalDataEvent;
43 import org.mxchange.jusercore.model.user.LoginUser;
44 import org.mxchange.jusercore.model.user.User;
45 import org.mxchange.jusercore.model.user.UserSessionBeanRemote;
46 import org.mxchange.jusercore.model.user.profilemodes.ProfileMode;
47 import org.mxchange.juserlogincore.events.login.ObservableUserLoggedInEvent;
48 import org.mxchange.juserlogincore.events.registration.ObservableUserRegisteredEvent;
49 import org.mxchange.juserlogincore.events.user.password_change.ObservableUpdatedUserPasswordEvent;
50 import org.mxchange.juserlogincore.exceptions.UserPasswordMismatchException;
51 import org.mxchange.juserlogincore.login.UserLoginUtils;
54 * A user controller (bean)
56 * @author Roland Häder<roland@mxchange.org>
58 @Named ("userController")
60 public class JobsUserWebRequestBean extends BaseJobsBean implements JobsUserWebRequestController {
65 private static final long serialVersionUID = 542_145_347_916L;
68 * General contact controller
71 private JobsContactWebRequestController contactController;
77 private JobsFeaturesWebApplicationController featureController;
80 * Localization controller
83 private JobsLocalizationSessionController localizationController;
86 * Event being fired when user updated personal data
90 private Event<ObservableUpdatedUserPersonalDataEvent> updatedPersonalDataEvent;
95 @EJB (lookup = "java:global/jjobs-ejb/user!org.mxchange.jusercore.model.user.UserSessionBeanRemote")
96 private UserSessionBeanRemote userBean;
104 * Login controller (bean)
107 private JobsUserLoginWebSessionController userLoginController;
112 private String userName;
115 * User password (clear-text from web form)
117 private String userPassword;
120 * User password repeated (clear-text from web form)
122 private String userPasswordRepeat;
125 * Whether the user wants a public profile
127 private ProfileMode userProfileMode;
130 * Default constructor
132 public JobsUserWebRequestBean () {
133 // Call super constructor
138 * Event observer for newly added users by administrator
140 * @param event Event being fired
142 public void afterAdminAddedUserEvent (@Observes final ObservableAdminAddedUserEvent event) {
143 // Event and contained entity instance should not be null
146 throw new NullPointerException("event is null"); //NOI18N
147 } else if (event.getAddedUser() == null) {
149 throw new NullPointerException("event.addedUser is null"); //NOI18N
150 } else if (event.getAddedUser().getUserId() == null) {
152 throw new NullPointerException("event.addedUser.userId is null"); //NOI18N
153 } else if (event.getAddedUser().getUserId() < 1) {
155 throw new IllegalArgumentException(MessageFormat.format("userId of user={0} is not valid: {1}", event.getAddedUser(), event.getAddedUser().getUserId())); //NOI18N
159 this.setUserId(event.getAddedUser().getUserId());
163 * Event observer for linked users with existing contact data
165 * @param event Event being fired
167 public void afterAdminLinkedUserEvent (@Observes final ObservableAdminLinkedUserEvent event) {
168 // Event and contained entity instance should not be null
171 throw new NullPointerException("event is null"); //NOI18N
172 } else if (event.getLinkedUser() == null) {
174 throw new NullPointerException("event.linkedUser is null"); //NOI18N
175 } else if (event.getLinkedUser().getUserId() == null) {
177 throw new NullPointerException("event.linkedUser.userId is null"); //NOI18N
178 } else if (event.getLinkedUser().getUserId() < 1) {
180 throw new IllegalArgumentException(MessageFormat.format("userId of user={0} is not valid: {1}", event.getLinkedUser(), event.getLinkedUser().getUserId())); //NOI18N
184 this.setUserId(event.getLinkedUser().getUserId());
188 * Event observer for when a bean helper has successfully created a user
189 * instance, means the user exists. If the user does not exist, this event
190 * should not fire but instead a proper exception must be thrown.
192 * @param event User created event
194 public void afterCreatedUserEvent (@Observes final ObservableCreatedUserEvent event) {
195 // Is the instance valid?
198 throw new NullPointerException("event is null"); //NOI18N
199 } else if (event.getCreatedUser() == null) {
201 throw new NullPointerException("event.createdUser is null"); //NOI18N
202 } else if (event.getCreatedUser().getUserId() == null) {
204 throw new NullPointerException("event.createdUser.userId is null"); //NOI18N
205 } else if (event.getCreatedUser().getUserId() < 1) {
207 throw new NullPointerException(MessageFormat.format("event.createdUser.userId={0} is not valid", event.getCreatedUser().getUserId())); //NOI18N
211 final User user = event.getCreatedUser();
213 // Set all fields here
218 * Event observer for logged-in user
220 * @param event Event instance
222 public void afterUserLoginEvent (@Observes final ObservableUserLoggedInEvent event) {
223 // Event and contained entity instance should not be null
226 throw new NullPointerException("event is null"); //NOI18N
227 } else if (event.getLoggedInUser() == null) {
229 throw new NullPointerException("event.registeredUser is null"); //NOI18N
230 } else if (event.getLoggedInUser().getUserId() == null) {
232 throw new NullPointerException("event.registeredUser.userId is null"); //NOI18N
233 } else if (event.getLoggedInUser().getUserId() < 1) {
235 throw new IllegalArgumentException(MessageFormat.format("userId of user={0} is not valid: {1}", event.getLoggedInUser(), event.getLoggedInUser().getUserId())); //NOI18N
238 // "Cache" user instance
239 final User loggedInUser = event.getLoggedInUser();
241 // Copy all data to this bean
242 this.copyUser(loggedInUser);
246 * Event observer for user password changes
248 * @param event Event being fired
250 public void afterUserPasswordChangedEvent (@Observes final ObservableUpdatedUserPasswordEvent event) {
254 throw new NullPointerException("event is null"); //NOI18N
255 } else if (event.getUserPassword() == null) {
257 throw new NullPointerException("event.userPassword is null"); //NOI18N
258 } else if (event.getUserPassword().isEmpty()) {
260 throw new IllegalArgumentException("event.userPassword is empty"); //NOI18N
264 this.setUserPassword(event.getUserPassword());
265 this.setUserPasswordRepeat(event.getUserPassword());
269 * Event observer for new user registrations
271 * @param event User registration event
273 public void afterUserRegistrationEvent (@Observes final ObservableUserRegisteredEvent event) {
274 // Event and contained entity instance should not be null
277 throw new NullPointerException("event is null"); //NOI18N
278 } else if (event.getRegisteredUser() == null) {
280 throw new NullPointerException("event.registeredUser is null"); //NOI18N
281 } else if (event.getRegisteredUser().getUserId() == null) {
283 throw new NullPointerException("event.registeredUser.userId is null"); //NOI18N
284 } else if (event.getRegisteredUser().getUserId() < 1) {
286 throw new IllegalArgumentException(MessageFormat.format("userId of user={0} is not valid: {1}", event.getRegisteredUser(), event.getRegisteredUser().getUserId())); //NOI18N
290 final User registeredUser = event.getRegisteredUser();
292 // Copy all data from registered->user
293 this.copyUser(registeredUser);
296 this.setUserId(registeredUser.getUserId());
300 * Event observer for when a user name should be cleared
302 * @param event Event being fired
304 public void clearUserNameEvent (@Observes final ObservableClearUserNameEvent event) {
308 throw new NullPointerException("event is null"); //NOI18N
312 this.clearUserName();
316 * Event observer for when both user passwords should be cleared
318 * @param event Event being fired
320 public void clearUserPasswordEvent (@Observes final ObservableClearUserPasswordEvent event) {
324 throw new NullPointerException("event is null"); //NOI18N
328 this.clearUserPasswords();
332 public User createUserInstance (final boolean createContactData) {
333 // Required personal data must be set
334 assert (this.isRequiredPersonalDataSet()) : "not all personal data is set"; //NOI18N
336 // Is user name required?
337 if (!this.isUserNameRequired()) {
338 // Generate pseudo-random user name
339 // @TODO Refacture this to avoid EJB call
340 final String randomName = this.userBean.generateRandomUserName();
342 // Set it and inivisible profile
343 this.setUserName(randomName);
344 this.setUserProfileMode(ProfileMode.INVISIBLE);
346 // Generate random password
347 final String randomPassword = UserLoginUtils.createRandomPassword(JobsUserWebRequestController.MINIMUM_PASSWORD_LENGTH);
349 // Set random password
350 this.setUserPassword(randomPassword);
351 this.setUserPasswordRepeat(randomPassword);
354 // Create new user instance
355 final User user = new LoginUser();
357 // Set user name profile mode and locale
358 user.setUserName(this.getUserName());
359 user.setUserProfileMode(this.getUserProfileMode());
360 user.setUserLocale(this.localizationController.getLocale());
362 // Is multiple registration page
363 if ((createContactData) || (!this.featureController.isFeatureEnabled("user_register_multiple_page"))) { //NOI18N
364 // Create contact instance
365 final Contact contact = this.contactController.createContactInstance();
367 // Set contact in user
368 user.setUserContact(contact);
376 public User createUserLogin () {
378 if (this.getUserName() == null) {
380 throw new NullPointerException("userName is null"); //NOI18N
381 } else if (this.getUserName().isEmpty()) {
383 throw new IllegalStateException("userName is empty."); //NOI18N
386 // Create new user instance
387 final User user = new LoginUser();
389 // Update all data ...
390 user.setUserName(this.getUserName());
392 // Return the new instance
397 public String doChangePersonalData () {
398 // This method shall only be called if the user is logged-in
399 if (!this.userLoginController.isUserLoggedIn()) {
401 throw new IllegalStateException("User is not logged-in"); //NOI18N
402 } else if (!this.isRequiredChangePersonalDataSet()) {
403 // Not all required fields are set
404 throw new FaceletException("Not all required fields are set."); //NOI18N
405 } else if (!this.userLoginController.ifCurrentPasswordMatches()) {
406 // Password not matching
407 throw new FaceletException(new UserPasswordMismatchException(this.userLoginController.getLoggedInUser()));
408 } else if (!this.featureController.isFeatureEnabled("change_user_personal_data")) { //NOI18N
409 // Editing is not allowed
410 throw new IllegalStateException("User tried to edit personal data."); //NOI18N
414 final User user = this.userLoginController.getLoggedInUser();
416 // Copy contact data to contact instance
417 this.contactController.updateContactDataFromController(user.getUserContact());
419 // It should be there, so run some tests on it
420 assert (user instanceof User) : "Instance userLoginController.loggedInUser is null"; //NOI18N
421 assert (user.getUserId() instanceof Long) : "Instance userLoginController.loggedInUser.userId is null"; //NOI18N
422 assert (user.getUserId() > 0) : MessageFormat.format("userLoginController.loggedInUser.userId={0} is invalid", user.getUserId()); //NOI18N
423 assert (user.getUserContact() instanceof Contact) : "Instance userLoginController.loggedInUser.userContact is null"; //NOI18N
424 assert (user.getUserContact().getContactId() instanceof Long) : "Instance userLoginController.userContact.contactId is null"; //NOI18N
425 assert (user.getUserContact().getContactId() > 0) : MessageFormat.format("Instance userLoginController.userContact.contactId={0} is invalid", user.getUserContact().getContactId()); //NOI18N
428 user.setUserProfileMode(this.getUserProfileMode());
430 // Send it to the EJB
431 final User updatedUser = this.userBean.updateUserPersonalData(user);
434 this.updatedPersonalDataEvent.fire(new UpdatedUserPersonalDataEvent(updatedUser));
437 return "user_contact_data_saved"; //NOI18N
445 public Long getUserId () {
452 * @param userId User id
454 public void setUserId (final Long userId) {
455 this.userId = userId;
459 * Getter for user name
463 public String getUserName () {
464 return this.userName;
468 * Setter for user name
470 * @param userName User name
472 public void setUserName (final String userName) {
473 this.userName = userName;
477 public String getUserPassword () {
478 return this.userPassword;
482 * Setter for clear-text user password
484 * @param userPassword Clear-text user password
486 public void setUserPassword (final String userPassword) {
487 this.userPassword = userPassword;
491 * Getter for clear-text user password repeated
493 * @return Clear-text user password repeated
495 public String getUserPasswordRepeat () {
496 return this.userPasswordRepeat;
500 * Setter for clear-text user password repeated
502 * @param userPasswordRepeat Clear-text user password repeated
504 public void setUserPasswordRepeat (final String userPasswordRepeat) {
505 this.userPasswordRepeat = userPasswordRepeat;
509 * Getter for user profile mode
511 * @return User profile mode
513 public ProfileMode getUserProfileMode () {
514 return this.userProfileMode;
518 * Setter for user profile mode
520 * @param userProfileMode User profile mode
522 public void setUserProfileMode (final ProfileMode userProfileMode) {
523 this.userProfileMode = userProfileMode;
527 public boolean ifBothPasswordsEmptyAllowed () {
528 // Check feature first
529 return ((this.featureController.isFeatureEnabled("allow_user_registration_empty_password")) && //NOI18N
530 ((this.getUserPassword() == null) || (this.getUserPassword().isEmpty())) &&
531 ((this.getUserPasswordRepeat() == null) || (this.getUserPasswordRepeat().isEmpty())));
535 public boolean isRequiredChangePersonalDataSet () {
536 return ((this.getUserProfileMode() != null) &&
537 (this.getUserName() != null) && (!this.getUserName().isEmpty()) &&
538 (this.contactController.isRequiredChangePersonalDataSet()));
542 public boolean isRequiredPersonalDataSet () {
543 if (this.featureController.isFeatureEnabled("user_register_multiple_page")) { //NOI18N
544 // Multiple registration page
545 return this.contactController.isRequiredPersonalDataSet();
547 // Single registration page
548 return (((this.getUserName() != null) || (!this.isUserNameRequired())) &&
549 (this.getUserProfileMode() != null) &&
550 (this.contactController.isRequiredPersonalDataSet()) &&
551 (this.getUserPassword() != null) &&
552 (this.getUserPasswordRepeat() != null));
557 public boolean isSamePasswordEntered () {
558 return ((!this.getUserPassword().isEmpty()) && (Objects.equals(this.getUserPassword(), this.getUserPasswordRepeat())));
562 public boolean isUserIdEmpty () {
563 return ((this.getUserId() == null) || (this.getUserId() == 0));
567 public boolean isUserNameRequired () {
568 // Get context parameter
569 final String contextParameter = FacesContext.getCurrentInstance().getExternalContext().getInitParameter("is_user_login_require_user_name"); //NOI18N
572 final boolean isRequired = ((contextParameter instanceof String) && (contextParameter.toLowerCase().equals("true"))); //NOI18N
581 private void clearUserName () {
583 this.setUserName(null);
587 * Clears both user passwords
589 private void clearUserPasswords () {
591 this.setUserPassword(null);
592 this.setUserPasswordRepeat(null);
596 * Copies given user into the controller
598 * @param user User instance
600 private void copyUser (final User user) {
601 // Make sure the instance is valid
604 throw new NullPointerException("user is null"); //NOI18N
605 } else if (user.getUserContact() == null) {
607 throw new NullPointerException("user.userContact is null"); //NOI18N
612 this.setUserId(user.getUserId());
613 this.setUserProfileMode(user.getUserProfileMode());