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