]> git.argeo.org Git - lgpl/argeo-commons.git/blob - auth/CmsLogin.java
Prepare next development cycle
[lgpl/argeo-commons.git] / auth / CmsLogin.java
1 package org.argeo.cms.swt.auth;
2
3 import static org.argeo.cms.CmsMsg.password;
4 import static org.argeo.cms.CmsMsg.username;
5
6 import java.io.IOException;
7 import java.util.Collections;
8 import java.util.List;
9 import java.util.Locale;
10
11 import javax.security.auth.Subject;
12 import javax.security.auth.callback.Callback;
13 import javax.security.auth.callback.CallbackHandler;
14 import javax.security.auth.callback.LanguageCallback;
15 import javax.security.auth.callback.NameCallback;
16 import javax.security.auth.callback.PasswordCallback;
17 import javax.security.auth.callback.UnsupportedCallbackException;
18 import javax.security.auth.login.LoginContext;
19 import javax.security.auth.login.LoginException;
20
21 import org.argeo.api.cms.CmsAuth;
22 import org.argeo.api.cms.CmsContext;
23 import org.argeo.api.cms.CmsLog;
24 import org.argeo.api.cms.ux.CmsView;
25 import org.argeo.cms.CmsMsg;
26 import org.argeo.cms.LocaleUtils;
27 import org.argeo.cms.auth.RemoteAuthCallback;
28 import org.argeo.cms.servlet.ServletHttpRequest;
29 import org.argeo.cms.servlet.ServletHttpResponse;
30 import org.argeo.cms.swt.CmsStyles;
31 import org.argeo.cms.swt.CmsSwtUtils;
32 import org.argeo.eclipse.ui.specific.UiContext;
33 import org.eclipse.swt.SWT;
34 import org.eclipse.swt.events.MouseAdapter;
35 import org.eclipse.swt.events.MouseEvent;
36 import org.eclipse.swt.events.SelectionAdapter;
37 import org.eclipse.swt.events.SelectionEvent;
38 import org.eclipse.swt.events.SelectionListener;
39 import org.eclipse.swt.events.TraverseEvent;
40 import org.eclipse.swt.events.TraverseListener;
41 import org.eclipse.swt.layout.GridData;
42 import org.eclipse.swt.layout.GridLayout;
43 import org.eclipse.swt.widgets.Button;
44 import org.eclipse.swt.widgets.Composite;
45 import org.eclipse.swt.widgets.Control;
46 import org.eclipse.swt.widgets.Label;
47 import org.eclipse.swt.widgets.Shell;
48 import org.eclipse.swt.widgets.Text;
49
50 public class CmsLogin implements CmsStyles, CallbackHandler {
51 private final static CmsLog log = CmsLog.getLog(CmsLogin.class);
52
53 private Composite parent;
54 private Text usernameT, passwordT;
55 private Composite credentialsBlock;
56 private final SelectionListener loginSelectionListener;
57
58 private final Locale defaultLocale;
59 private LocaleChoice localeChoice = null;
60
61 private final CmsView cmsView;
62
63 // optional subject to be set explicitly
64 private Subject subject = null;
65
66 private CmsContext cmsContext;
67
68 public CmsLogin(CmsView cmsView, CmsContext cmsContext) {
69 this.cmsView = cmsView;
70 this.cmsContext = cmsContext;
71 if (this.cmsContext != null) {
72 defaultLocale = this.cmsContext.getDefaultLocale();
73 List<Locale> locales = this.cmsContext.getLocales();
74 if (locales != null)
75 localeChoice = new LocaleChoice(locales, defaultLocale);
76 } else {
77 defaultLocale = Locale.getDefault();
78 }
79 loginSelectionListener = new SelectionListener() {
80 private static final long serialVersionUID = -8832133363830973578L;
81
82 @Override
83 public void widgetSelected(SelectionEvent e) {
84 login();
85 }
86
87 @Override
88 public void widgetDefaultSelected(SelectionEvent e) {
89 }
90 };
91 }
92
93 protected boolean isAnonymous() {
94 return cmsView.isAnonymous();
95 }
96
97 public final void createUi(Composite parent) {
98 this.parent = parent;
99 createContents(parent);
100 }
101
102 protected void createContents(Composite parent) {
103 defaultCreateContents(parent);
104 }
105
106 public final void defaultCreateContents(Composite parent) {
107 parent.setLayout(CmsSwtUtils.noSpaceGridLayout());
108 Composite credentialsBlock = createCredentialsBlock(parent);
109 if (parent instanceof Shell) {
110 credentialsBlock.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, true, true));
111 }
112 }
113
114 public final Composite createCredentialsBlock(Composite parent) {
115 if (isAnonymous()) {
116 return anonymousUi(parent);
117 } else {
118 return userUi(parent);
119 }
120 }
121
122 public Composite getCredentialsBlock() {
123 return credentialsBlock;
124 }
125
126 protected Composite userUi(Composite parent) {
127 Locale locale = localeChoice == null ? this.defaultLocale : localeChoice.getSelectedLocale();
128 credentialsBlock = new Composite(parent, SWT.NONE);
129 credentialsBlock.setLayout(new GridLayout());
130 // credentialsBlock.setLayoutData(CmsUiUtils.fillAll());
131
132 specificUserUi(credentialsBlock);
133
134 Label l = new Label(credentialsBlock, SWT.NONE);
135 CmsSwtUtils.style(l, CMS_USER_MENU_ITEM);
136 l.setText(CmsMsg.logout.lead(locale));
137 GridData lData = CmsSwtUtils.fillWidth();
138 lData.widthHint = 120;
139 l.setLayoutData(lData);
140
141 l.addMouseListener(new MouseAdapter() {
142 private static final long serialVersionUID = 6444395812777413116L;
143
144 public void mouseDown(MouseEvent e) {
145 logout();
146 }
147 });
148 return credentialsBlock;
149 }
150
151 /** To be overridden */
152 protected void specificUserUi(Composite parent) {
153
154 }
155
156 protected Composite anonymousUi(Composite parent) {
157 Locale locale = localeChoice == null ? this.defaultLocale : localeChoice.getSelectedLocale();
158 // We need a composite for the traversal
159 credentialsBlock = new Composite(parent, SWT.NONE);
160 credentialsBlock.setLayout(new GridLayout());
161 // credentialsBlock.setLayoutData(CmsUiUtils.fillAll());
162 CmsSwtUtils.style(credentialsBlock, CMS_LOGIN_DIALOG);
163
164 Integer textWidth = 120;
165 if (parent instanceof Shell)
166 CmsSwtUtils.style(parent, CMS_USER_MENU);
167 // new Label(this, SWT.NONE).setText(CmsMsg.username.lead());
168 usernameT = new Text(credentialsBlock, SWT.BORDER);
169 usernameT.setMessage(username.lead(locale));
170 CmsSwtUtils.style(usernameT, CMS_LOGIN_DIALOG_USERNAME);
171 GridData gd = CmsSwtUtils.fillWidth();
172 gd.widthHint = textWidth;
173 usernameT.setLayoutData(gd);
174
175 // new Label(this, SWT.NONE).setText(CmsMsg.password.lead());
176 passwordT = new Text(credentialsBlock, SWT.BORDER | SWT.PASSWORD);
177 passwordT.setMessage(password.lead(locale));
178 CmsSwtUtils.style(passwordT, CMS_LOGIN_DIALOG_PASSWORD);
179 gd = CmsSwtUtils.fillWidth();
180 gd.widthHint = textWidth;
181 passwordT.setLayoutData(gd);
182
183 TraverseListener tl = new TraverseListener() {
184 private static final long serialVersionUID = -1158892811534971856L;
185
186 public void keyTraversed(TraverseEvent e) {
187 if (e.detail == SWT.TRAVERSE_RETURN)
188 login();
189 }
190 };
191 credentialsBlock.addTraverseListener(tl);
192 usernameT.addTraverseListener(tl);
193 passwordT.addTraverseListener(tl);
194 parent.setTabList(new Control[] { credentialsBlock });
195 credentialsBlock.setTabList(new Control[] { usernameT, passwordT });
196
197 // Button
198 Button loginButton = new Button(credentialsBlock, SWT.PUSH);
199 loginButton.setText(CmsMsg.login.lead(locale));
200 loginButton.setLayoutData(CmsSwtUtils.fillWidth());
201 loginButton.addSelectionListener(loginSelectionListener);
202
203 extendsCredentialsBlock(credentialsBlock, locale, loginSelectionListener);
204 if (localeChoice != null)
205 createLocalesBlock(credentialsBlock);
206 return credentialsBlock;
207 }
208
209 /**
210 * To be overridden in order to provide custom login button and other links.
211 */
212 protected void extendsCredentialsBlock(Composite credentialsBlock, Locale selectedLocale,
213 SelectionListener loginSelectionListener) {
214
215 }
216
217 protected void updateLocale(Locale selectedLocale) {
218 // save already entered values
219 String usernameStr = usernameT.getText();
220 char[] pwd = passwordT.getTextChars();
221
222 for (Control child : parent.getChildren())
223 child.dispose();
224 createContents(parent);
225 if (parent.getParent() != null)
226 parent.getParent().layout(true, true);
227 else
228 parent.layout();
229 usernameT.setText(usernameStr);
230 passwordT.setTextChars(pwd);
231 }
232
233 protected Composite createLocalesBlock(final Composite parent) {
234 Composite c = new Composite(parent, SWT.NONE);
235 CmsSwtUtils.style(c, CMS_USER_MENU_ITEM);
236 c.setLayout(CmsSwtUtils.noSpaceGridLayout());
237 c.setLayoutData(CmsSwtUtils.fillAll());
238
239 SelectionListener selectionListener = new SelectionAdapter() {
240 private static final long serialVersionUID = 4891637813567806762L;
241
242 public void widgetSelected(SelectionEvent event) {
243 Button button = (Button) event.widget;
244 if (button.getSelection()) {
245 localeChoice.setSelectedIndex((Integer) event.widget.getData());
246 updateLocale(localeChoice.getSelectedLocale());
247 }
248 };
249 };
250
251 List<Locale> locales = localeChoice.getLocales();
252 for (Integer i = 0; i < locales.size(); i++) {
253 Locale locale = locales.get(i);
254 Button button = new Button(c, SWT.RADIO);
255 CmsSwtUtils.style(button, CMS_USER_MENU_ITEM);
256 button.setData(i);
257 button.setText(LocaleUtils.toLead(locale.getDisplayName(locale), locale) + " (" + locale + ")");
258 // button.addListener(SWT.Selection, listener);
259 button.addSelectionListener(selectionListener);
260 if (i == localeChoice.getSelectedIndex())
261 button.setSelection(true);
262 }
263 return c;
264 }
265
266 protected boolean login() {
267 // TODO use CmsVie in order to retrieve subject?
268 // Subject subject = cmsView.getLoginContext().getSubject();
269 // LoginContext loginContext = cmsView.getLoginContext();
270 try {
271 //
272 // LOGIN
273 //
274 // loginContext.logout();
275 LoginContext loginContext;
276 if (subject == null)
277 loginContext = new LoginContext(CmsAuth.LOGIN_CONTEXT_USER, this);
278 else
279 loginContext = new LoginContext(CmsAuth.LOGIN_CONTEXT_USER, subject, this);
280 loginContext.login();
281 cmsView.authChange(loginContext);
282 cmsContext.sendEvent("cms", Collections.singletonMap("msg", "New login"));
283 return true;
284 } catch (LoginException e) {
285 if (log.isTraceEnabled())
286 log.warn("Login failed: " + e.getMessage(), e);
287 else
288 log.warn("Login failed: " + e.getMessage());
289
290 try {
291 Thread.sleep(3000);
292 } catch (InterruptedException e2) {
293 // silent
294 }
295 // ErrorFeedback.show("Login failed", e);
296 return false;
297 }
298 // catch (LoginException e) {
299 // log.error("Cannot login", e);
300 // return false;
301 // }
302 }
303
304 protected void logout() {
305 cmsView.logout();
306 cmsView.navigateTo("~");
307 }
308
309 @Override
310 public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
311 for (Callback callback : callbacks) {
312 if (callback instanceof NameCallback && usernameT != null)
313 ((NameCallback) callback).setName(usernameT.getText());
314 else if (callback instanceof PasswordCallback && passwordT != null)
315 ((PasswordCallback) callback).setPassword(passwordT.getTextChars());
316 else if (callback instanceof RemoteAuthCallback) {
317 ((RemoteAuthCallback) callback).setRequest(new ServletHttpRequest(UiContext.getHttpRequest()));
318 ((RemoteAuthCallback) callback).setResponse(new ServletHttpResponse(UiContext.getHttpResponse()));
319 } else if (callback instanceof LanguageCallback) {
320 Locale toUse = null;
321 if (localeChoice != null)
322 toUse = localeChoice.getSelectedLocale();
323 else if (defaultLocale != null)
324 toUse = defaultLocale;
325
326 if (toUse != null) {
327 ((LanguageCallback) callback).setLocale(toUse);
328 UiContext.setLocale(toUse);
329 }
330
331 }
332 }
333 }
334
335 public void setSubject(Subject subject) {
336 this.subject = subject;
337 }
338
339 }