]> git.mxchange.org Git - pizzaservice-war.git/blob - src/java/org/mxchange/pizzaapplication/beans/login/PizzaUserLoginWebSessionBean.java
Please cherry-pick:
[pizzaservice-war.git] / src / java / org / mxchange / pizzaapplication / beans / login / PizzaUserLoginWebSessionBean.java
1 /*
2  * Copyright (C) 2016 Roland Häder
3  *
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.
8  *
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.
13  *
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/>.
16  */
17 package org.mxchange.pizzaapplication.beans.login;
18
19 import java.text.MessageFormat;
20 import java.util.Collections;
21 import java.util.List;
22 import java.util.Objects;
23 import javax.enterprise.context.SessionScoped;
24 import javax.enterprise.event.Event;
25 import javax.enterprise.event.Observes;
26 import javax.enterprise.inject.Any;
27 import javax.faces.context.FacesContext;
28 import javax.faces.view.facelets.FaceletException;
29 import javax.inject.Inject;
30 import javax.inject.Named;
31 import javax.naming.Context;
32 import javax.naming.InitialContext;
33 import javax.naming.NamingException;
34 import org.mxchange.jusercore.container.login.LoginContainer;
35 import org.mxchange.jusercore.container.login.UserLoginContainer;
36 import org.mxchange.jusercore.events.login.ObservableUserLoggedInEvent;
37 import org.mxchange.jusercore.events.login.UserLoggedInEvent;
38 import org.mxchange.jusercore.events.logout.ObservableUserLogoutEvent;
39 import org.mxchange.jusercore.events.logout.UserLogoutEvent;
40 import org.mxchange.jusercore.events.user.password_change.ObservableUpdatedUserPasswordEvent;
41 import org.mxchange.jusercore.exceptions.UserNotFoundException;
42 import org.mxchange.jusercore.exceptions.UserPasswordMismatchException;
43 import org.mxchange.jusercore.exceptions.UserStatusLockedException;
44 import org.mxchange.jusercore.exceptions.UserStatusUnconfirmedException;
45 import org.mxchange.jusercore.model.login.UserLoginSessionBeanRemote;
46 import org.mxchange.jusercore.model.user.User;
47 import org.mxchange.jusercore.model.user.UserUtils;
48 import org.mxchange.jusercore.model.user.password_history.PasswordHistory;
49 import org.mxchange.jusercore.model.user.password_history.UserPasswordHistorySessionBeanRemote;
50 import org.mxchange.jusercore.model.user.profilemodes.ProfileMode;
51 import org.mxchange.jusercore.model.user.status.UserAccountStatus;
52 import org.mxchange.pizzaapplication.beans.BasePizzaController;
53 import org.mxchange.pizzaapplication.beans.user.PizzaUserWebSessionController;
54
55 /**
56  * A web bean for user registration
57  * <p>
58  * @author Roland Häder<roland@mxchange.org>
59  */
60 @Named ("userLoginController")
61 @SessionScoped
62 public class PizzaUserLoginWebSessionBean extends BasePizzaController implements PizzaUserLoginWebSessionController {
63
64         /**
65          * Path name for guest base template
66          */
67         private static final String GUEST_BASE_TEMPLATE_NAME = "guest/guest";
68
69         /**
70          * Path name for logged-in user base template
71          */
72         private static final String USER_BASE_TEMPLATE_NAME = "login/user/user";
73
74         /**
75          * Serial number
76          */
77         private static final long serialVersionUID = 47_828_986_719_691_592L;
78
79         /**
80          * Template type for pages that might be displayed in guest area and login
81          * area.
82          */
83         private String baseTemplatePathName;
84
85         /**
86          * Logged-in user instance
87          */
88         private User loggedInUser;
89
90         /**
91          * Remote register session bean
92          */
93         private UserLoginSessionBeanRemote loginBean;
94
95         /**
96          * Event fired when user has logged in
97          */
98         @Inject
99         @Any
100         private Event<ObservableUserLoggedInEvent> loginEvent;
101
102         /**
103          * User controller
104          */
105         @Inject
106         private PizzaUserWebSessionController userController;
107
108         /**
109          * Current password
110          */
111         private String userCurrentPassword;
112
113         /**
114          * Flag whether the user has logged-in, set only from inside
115          */
116         private boolean userLoggedIn;
117
118         /**
119          * Event fired when user has logged in
120          */
121         @Inject
122         @Any
123         private Event<ObservableUserLoggedInEvent> userLoginEvent;
124
125         /**
126          * Event fired when user has logged out
127          */
128         @Inject
129         @Any
130         private Event<ObservableUserLogoutEvent> userLogoutEvent;
131
132         /**
133          * User's password history
134          */
135         private List<PasswordHistory> userPasswordHistory;
136
137         /**
138          * EJB for user's password history
139          */
140         private UserPasswordHistorySessionBeanRemote userPasswordHistoryBean;
141
142         /**
143          * Default constructor
144          */
145         public PizzaUserLoginWebSessionBean () {
146                 try {
147                         // Get initial context
148                         Context context = new InitialContext();
149
150                         // Try to lookup
151                         this.loginBean = (UserLoginSessionBeanRemote) context.lookup("java:global/jjobs-ejb/login!org.mxchange.jusercore.model.login.UserLoginSessionBeanRemote"); //NOI18N
152
153                         // Also find this
154                         this.userPasswordHistoryBean = (UserPasswordHistorySessionBeanRemote) context.lookup("java:global/jjobs-ejb/userPasswordHistory!org.mxchange.jusercore.model.user.password_history.UserPasswordHistorySessionBeanRemote"); //NOI18N
155
156                         // Defaul template is guest
157                         this.baseTemplatePathName = GUEST_BASE_TEMPLATE_NAME;
158                 } catch (final NamingException ex) {
159                         // Continue to throw
160                         throw new FaceletException(ex);
161                 }
162         }
163
164         /**
165          * Method being call after user's password has been updated (and history
166          * entry has been created).
167          * <p>
168          * @param event Event being observed
169          */
170         public void afterUserUpdatedPasswordEvent (@Observes final ObservableUpdatedUserPasswordEvent event) {
171                 // Check parameter
172                 if (null == event) {
173                         // Throw NPE
174                         throw new NullPointerException("event is null"); //NOI18N
175                 } else if (event.getPasswordHistory() == null) {
176                         // Throw NPE again
177                         throw new NullPointerException("event.passwordHistory is null"); //NOI18N
178                 } else if (event.getPasswordHistory().getUserPasswordHistoryId() == null) {
179                         // ... and again
180                         throw new NullPointerException("event.passwordHistory.userPasswordHistoryId is null"); //NOI18N
181                 } else if (event.getPasswordHistory().getUserPasswordHistoryId() < 1) {
182                         // Invalid value
183                         throw new IllegalArgumentException(MessageFormat.format("event.passwordHistory.userPasswordHistoryId={0} is in valid", event.getPasswordHistory().getUserPasswordHistoryId())); //NOI18N
184                 }
185
186                 // All fine, so update list
187                 this.updatePasswordHistory(event.getPasswordHistory());
188         }
189
190         @Override
191         public String doAdminLogout () {
192                 // Is a user logged-in?
193                 if (this.isUserLoggedIn()) {
194                         // Call other logout
195                         return this.doUserLogout();
196                 }
197
198                 // Invalidate session
199                 FacesContext.getCurrentInstance().getExternalContext().invalidateSession();
200
201                 // Set template type to guest
202                 this.setBaseTemplatePathName(GUEST_BASE_TEMPLATE_NAME); //NOI18N
203
204                 // Redirect to index
205                 return "index?faces-redirect=true"; //NOI18N
206         }
207
208         @Override
209         public String doUserLogin () {
210                 // Get user instance
211                 User user = this.userController.createUserLogin();
212
213                 // Create login container
214                 LoginContainer container = new UserLoginContainer(user, this.userController.getUserPassword());
215
216                 try {
217                         // Call bean
218                         User confirmedUser = this.loginBean.validateUserAccountStatus(container);
219
220                         // All fine here so set it here
221                         this.setLoggedInUser(confirmedUser);
222
223                         // Retrieve user's password list
224                         this.userPasswordHistory = this.userPasswordHistoryBean.getUserPasswordHistory(confirmedUser);
225
226                         // Set template to "login"
227                         this.setBaseTemplatePathName(USER_BASE_TEMPLATE_NAME); //NOI18N
228
229                         // Fire event away. Keep this last before return statement.
230                         this.userLoginEvent.fire(new UserLoggedInEvent(confirmedUser));
231
232                         // Clear this bean
233                         this.clear();
234
235                         // All fine
236                         return "login_user"; //NOI18N
237                 } catch (final UserNotFoundException ex) {
238                         // Show JSF message
239                         this.showFacesMessage("form_user_login:userName", "ERROR_USER_NOT_FOUND"); //NOI18N
240                         return ""; //NOI18N
241                 } catch (final UserStatusLockedException ex) {
242                         this.showFacesMessage("form_user_login:userName", "ERROR_USER_STATUS_LOCKED"); //NOI18N
243                         return ""; //NOI18N
244                 } catch (final UserStatusUnconfirmedException ex) {
245                         this.showFacesMessage("form_user_login:userName", "ERROR_USER_STATUS_UNCONFIRMED"); //NOI18N
246                         return ""; //NOI18N
247                 } catch (final UserPasswordMismatchException ex) {
248                         // Show JSF message
249                         this.showFacesMessage("form_user_login:userPassword", "ERROR_USER_PASSWORD_MISMATCH"); //NOI18N
250                         return ""; //NOI18N
251                 }
252         }
253
254         @Override
255         public String doUserLogout () {
256                 // Is loggedInUser set?
257                 if (this.getLoggedInUser() == null) {
258                         // Throw NPE
259                         throw new NullPointerException("this.loggedInUser is null"); //NOI18N
260                 } else if (this.getLoggedInUser().getUserId() == null) {
261                         // Throw again
262                         throw new NullPointerException("this.loggedInUser.userId is null"); //NOI18N
263                 } else if (this.getLoggedInUser().getUserId() < 1) {
264                         // Invalid user id
265                         throw new IllegalStateException(MessageFormat.format("this.loggedInUser.userId={0} is not valid.", this.getLoggedInUser().getUserId())); //NOI18N
266                 }
267
268                 // Fire event
269                 this.userLogoutEvent.fire(new UserLogoutEvent(this.getLoggedInUser()));
270
271                 // Invalidate session
272                 FacesContext.getCurrentInstance().getExternalContext().invalidateSession();
273
274                 // Unset any user instances
275                 this.setLoggedInUser(null);
276                 this.setBaseTemplatePathName(GUEST_BASE_TEMPLATE_NAME); //NOI18N
277
278                 // Redirect to index
279                 return "index"; //NOI18N
280         }
281
282         @Override
283         public String getBaseTemplatePathName () {
284                 return this.baseTemplatePathName;
285         }
286
287         @Override
288         public void setBaseTemplatePathName (final String baseTemplatePathName) {
289                 this.baseTemplatePathName = baseTemplatePathName;
290         }
291
292         @Override
293         public User getLoggedInUser () {
294                 return this.loggedInUser;
295         }
296
297         @Override
298         public void setLoggedInUser (final User loggedInUser) {
299                 this.loggedInUser = loggedInUser;
300         }
301
302         @Override
303         public String getUserCurrentPassword () {
304                 return this.userCurrentPassword;
305         }
306
307         @Override
308         public void setUserCurrentPassword (final String userCurrentPassword) {
309                 this.userCurrentPassword = userCurrentPassword;
310         }
311
312         @Override
313         public List<PasswordHistory> getUserPasswordHistory () {
314                 return Collections.unmodifiableList(this.userPasswordHistory);
315         }
316
317         @Override
318         public boolean ifCurrentPasswordMatches () {
319                 // The current password must be set and not empty
320                 if (this.getUserCurrentPassword() == null) {
321                         // Is not set
322                         throw new NullPointerException("this.userCurrentPassword is null"); //NOI18N
323                 } else if (this.getUserCurrentPassword().isEmpty()) {
324                         // Is set empty
325                         throw new IllegalStateException("this.userCurrentPassword is empty."); //NOI18N
326                 }
327
328                 // Create "container"
329                 LoginContainer container = new UserLoginContainer(this.getLoggedInUser(), this.getUserCurrentPassword());
330
331                 // Now check if it matches
332                 return UserUtils.ifPasswordMatches(container, this.getLoggedInUser());
333         }
334
335         @Override
336         public boolean ifUserMustChangePassword () {
337                 return ((this.isUserLoggedIn()) && (Objects.equals(this.getLoggedInUser().getUserMustChangePassword(), Boolean.TRUE)));
338         }
339
340         @Override
341         public boolean isInvisible () {
342                 // Check on login
343                 if (!this.isUserLoggedIn()) {
344                         // Not logged in!
345                         throw new IllegalStateException("isInvisible() has been invoked for a guest."); //NOI18N
346                 }
347
348                 // Check logged-in first, then invisibility
349                 return Objects.equals(this.getLoggedInUser().getUserProfileMode(), ProfileMode.INVISIBLE);
350         }
351
352         @Override
353         public boolean isPasswordInHistory (final String userPassword) {
354                 // Default is not found
355                 boolean isPasswordInHistory = false;
356
357                 // Init variables
358                 int count = 1;
359                 int maxEntries = this.getIntegerContextParameter("max_user_password_history"); //NOI18N
360
361                 // Check all passwords
362                 for (final PasswordHistory entry : this.getUserPasswordHistory()) {
363                         // Is password the same?
364                         if (UserUtils.ifPasswordMatches(userPassword, entry.getUserPasswordHistoryUser())) {
365                                 // Yes, found it
366                                 isPasswordInHistory = true;
367                                 break;
368                         } else if (count == maxEntries) {
369                                 // Maximum reached
370                                 break;
371                         }
372
373                         // Count up
374                         count++;
375                 }
376
377                 // Return status
378                 return isPasswordInHistory;
379         }
380
381         @Override
382         public boolean isUserLoggedIn () {
383                 // Compare instance
384                 this.userLoggedIn = ((this.getLoggedInUser() instanceof User) && (Objects.equals(this.getLoggedInUser().getUserAccountStatus(), UserAccountStatus.CONFIRMED)));
385
386                 // Return it
387                 return this.userLoggedIn;
388         }
389
390         /**
391          * Clears this bean
392          */
393         private void clear () {
394                 // Clear all fields
395                 this.setUserCurrentPassword(null);
396         }
397
398         /**
399          * Updates password history by adding given entry to it as long as it is not
400          * there.
401          * <p>
402          * @param passwordHistory Password history entry
403          */
404         private void updatePasswordHistory (final PasswordHistory passwordHistory) {
405                 if (null == passwordHistory) {
406                         // Throw NPE
407                         throw new NullPointerException("passwordHistory is null"); //NOI18N
408                 } else if (passwordHistory.getUserPasswordHistoryId() == null) {
409                         // Throw NPE again
410                         throw new NullPointerException("passwordHistory.userPasswordHistoryId is null"); //NOI18N
411                 } else if (passwordHistory.getUserPasswordHistoryId() < 1) {
412                         // Invalid id
413                         throw new IllegalArgumentException(MessageFormat.format("passwordHistory.userPasswordHistoryId={0} is not valid.", passwordHistory.getUserPasswordHistoryId())); //NOI18N
414                 }
415
416                 // Is it there?
417                 if (this.userPasswordHistory.contains(passwordHistory)) {
418                         // Excact copy found
419                         return;
420                 }
421
422                 // Check all entries
423                 for (final PasswordHistory entry : this.userPasswordHistory) {
424                         // Is same id number?
425                         if (Objects.equals(entry.getUserPasswordHistoryId(), passwordHistory.getUserPasswordHistoryId())) {
426                                 // Found it
427                                 return;
428                         }
429                 }
430
431                 // Not found, so add it
432                 this.userPasswordHistory.add(passwordHistory);
433         }
434
435 }