1 package fr.ifremer.quadrige2.ui.swing.common.content.login;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 import com.google.common.base.Objects;
28 import fr.ifremer.quadrige2.core.exception.Quadrige2TechnicalException;
29 import fr.ifremer.quadrige2.core.security.AuthenticationInfo;
30 import fr.ifremer.quadrige2.core.security.SecurityContextHelper;
31 import fr.ifremer.quadrige2.core.security.remote.AuthenticationRemoteException;
32 import fr.ifremer.quadrige2.core.security.remote.AuthenticationRemoteService;
33 import fr.ifremer.quadrige2.core.service.ClientServiceLocator;
34 import fr.ifremer.quadrige2.core.service.administration.user.UserService;
35 import fr.ifremer.quadrige2.core.vo.administration.user.QuserVO;
36 import fr.ifremer.quadrige2.synchro.service.client.SynchroRestClientService;
37 import fr.ifremer.quadrige2.ui.swing.common.action.AbstractMainUIAction;
38 import fr.ifremer.quadrige2.ui.swing.common.action.CloseApplicationAction;
39 import fr.ifremer.quadrige2.ui.swing.common.content.AbstractMainUIHandler;
40 import org.apache.commons.lang3.StringUtils;
41 import org.apache.commons.lang3.builder.ToStringBuilder;
42 import org.apache.commons.lang3.builder.ToStringStyle;
43 import org.apache.commons.logging.Log;
44 import org.apache.commons.logging.LogFactory;
45 import org.nuiton.jaxx.application.swing.action.AbstractApplicationAction;
46
47 import javax.swing.SwingUtilities;
48
49 import static org.nuiton.i18n.I18n.t;
50
51
52
53
54
55
56
57 public class AuthenticationAction extends AbstractMainUIAction {
58
59 private static final Log LOG = LogFactory.getLog(AuthenticationAction.class);
60
61
62
63
64
65
66
67
68
69
70
71
72 private AbstractApplicationAction callbackAction;
73 private boolean authenticated;
74 private boolean authenticationCanceled;
75
76
77
78
79
80
81 public AuthenticationAction(AbstractMainUIHandler handler) {
82 this(handler, null);
83 }
84
85
86
87
88
89
90
91 public AuthenticationAction(AbstractMainUIHandler handler, AbstractApplicationAction callbackAction) {
92 super(handler, true);
93 this.callbackAction = callbackAction;
94 setActionDescription(t("quadrige2.action.authenticate.title"));
95 }
96
97
98 @Override
99 public void doAction() throws Exception {
100
101
102 authenticated = false;
103 authenticationCanceled = false;
104 UserService userService = ClientServiceLocator.instance().getUserService();
105
106
107 String message = null;
108 if (callbackAction != null) {
109 message = callbackAction.getActionDescription();
110 }
111
112 while (!authenticated) {
113
114
115 AuthenticationInfo authenticationInfo = getHandler().askAuthenticationInfo(message);
116
117 if (authenticationInfo == null
118 || StringUtils.isBlank(authenticationInfo.getLogin())) {
119
120 if (LOG.isDebugEnabled()) {
121 LOG.debug("insufficient authentication information, cancelling action");
122 }
123 callbackAction = null;
124 authenticationCanceled = true;
125
126 if (getConfig().isAuthenticationForced() && !getContext().isAuthenticated()) {
127
128 getContext().getErrorHelper().showErrorDialog(t("quadrige2.action.authenticate.forced.message", getConfig().getApplicationName()));
129 getActionEngine().runInternalAction(handler, CloseApplicationAction.class);
130 }
131
132 return;
133 }
134
135 String login = authenticationInfo.getLogin();
136 boolean isLocalUserWithEmptyPassword = userService.isLocalUserWithNoPassword(login);
137
138 try {
139
140
141 if (isLocalUserWithEmptyPassword) {
142
143
144 if (StringUtils.isNotEmpty(authenticationInfo.getPassword())) {
145 getContext().getErrorHelper().showErrorDialog(t("quadrige2.error.authenticate.badCredential"));
146
147
148 if (!getConfig().isAuthenticationForced()) {
149 return;
150 }
151 }
152 else {
153 authenticated = SecurityContextHelper.authenticate(login, null);
154 }
155 }
156
157 else {
158
159 if (StringUtils.isBlank(authenticationInfo.getPassword())) {
160 throw new AuthenticationRemoteException(t("quadrige2.error.authenticate.badCredential"));
161 }
162
163 boolean hasPasswordInDatabase;
164 if (getConfig().isAuthenticationDisabled()) {
165
166
167 hasPasswordInDatabase = true;
168 } else {
169
170
171 hasPasswordInDatabase = userService.hasPassword(login);
172 }
173
174
175 if (hasPasswordInDatabase) {
176
177
178 authenticated = SecurityContextHelper.authenticate(login, authenticationInfo.getPassword());
179
180 }
181
182
183 if (!authenticated) {
184
185
186 AuthenticationRemoteService authRemoteService = ClientServiceLocator.instance().getAuthenticationRemoteService();
187 boolean remoteAuthenticated = authRemoteService.canAuthenticate(authenticationInfo);
188
189 if (remoteAuthenticated) {
190
191
192 userService.resetPassword(login);
193 hasPasswordInDatabase = false;
194
195
196 authenticated = SecurityContextHelper.authenticate(login, null);
197
198
199 if (!authenticated) {
200
201 if (tryUpdatePersonFromServer(authenticationInfo)) {
202
203 userService.resetPassword(login);
204 authenticated = SecurityContextHelper.authenticate(login, null);
205 } else {
206 throw new AuthenticationRemoteException(t("quadrige2.error.authenticate.badCredential"));
207 }
208 }
209 }
210 }
211
212 if (!authenticated) {
213 throw new AuthenticationRemoteException(t("quadrige2.error.authenticate.notFound", login));
214 }
215
216 if (LOG.isDebugEnabled()) {
217 LOG.debug("user '" + login + "' authenticated");
218 }
219
220 if (!hasPasswordInDatabase) {
221
222 userService.updatePasswordByUserId(
223 SecurityContextHelper.getQuadrige2UserId(),
224 authenticationInfo.getPassword());
225 }
226 }
227 } catch (AuthenticationRemoteException ae) {
228
229 getContext().getErrorHelper().showErrorDialog(ae.getLocalizedMessage());
230
231
232 if (!getConfig().isAuthenticationForced()) {
233 return;
234 }
235 }
236 }
237 }
238
239
240 @Override
241 public void postSuccessAction() {
242 super.postSuccessAction();
243
244
245 if (authenticationCanceled) {
246 return;
247 }
248
249 getContext().setAuthenticated(authenticated);
250
251
252 if (authenticated && callbackAction != null) {
253 if (LOG.isDebugEnabled()) {
254 LOG.debug("run callback action " + callbackAction.getClass().getSimpleName());
255 }
256 SwingUtilities.invokeLater(new Runnable() {
257
258 @Override
259 public void run() {
260 getActionEngine().runAction(callbackAction);
261 }
262 });
263 }
264
265 }
266
267
268 @Override
269 public void postFailedAction(Throwable error) {
270 super.postFailedAction(error);
271
272 getContext().setAuthenticated(false);
273
274 }
275
276
277
278
279
280
281
282
283
284 protected boolean tryUpdatePersonFromServer(AuthenticationInfo authenticationInfo) {
285 if (!getConfig().isSynchronizationEnabled()) {
286 return false;
287 }
288
289
290 SynchroRestClientService synchroRestClientService = ClientServiceLocator.instance().getSynchroRestClientService();
291 QuserVO user;
292 try {
293 user = synchroRestClientService.getUser(authenticationInfo);
294 } catch (Quadrige2TechnicalException e) {
295 return false;
296 }
297
298 if (user == null) {
299 return false;
300 }
301
302
303 if (!Objects.equal(user.getQuserIntranetLg(), authenticationInfo.getLogin())
304 && !Objects.equal(user.getQuserExtranetLg(), authenticationInfo.getLogin())) {
305 LOG.warn(String.format("Synchronization server send a bad person, with wrong login: expected [%s] but found [username=%s] and [usernameExtranet=%s]. Check configuration on synchro server.",
306 authenticationInfo.getLogin(),
307 user.getQuserIntranetLg(),
308 user.getQuserExtranetLg()));
309 return false;
310 }
311
312 if (LOG.isDebugEnabled()) {
313 LOG.debug("Will save person, retrieve from synchro server: " + ToStringBuilder.reflectionToString(user, ToStringStyle.SHORT_PREFIX_STYLE));
314 }
315 UserService personService = ClientServiceLocator.instance().getUserService();
316 personService.save(user, true);
317
318 return true;
319 }
320
321 }