source: trunk/src/org/expeditee/auth/Actions.java@ 1336

Last change on this file since 1336 was 1336, checked in by bln4, 5 years ago

new password reset screen

File size: 22.7 KB
Line 
1package org.expeditee.auth;
2
3import java.io.File;
4import java.io.FileNotFoundException;
5import java.io.IOException;
6import java.nio.file.Files;
7import java.nio.file.Path;
8import java.nio.file.Paths;
9import java.nio.file.StandardCopyOption;
10import java.security.InvalidKeyException;
11import java.security.KeyFactory;
12import java.security.KeyStoreException;
13import java.security.NoSuchAlgorithmException;
14import java.security.PrivateKey;
15import java.security.PublicKey;
16import java.security.cert.CertificateException;
17import java.security.spec.InvalidKeySpecException;
18import java.security.spec.PKCS8EncodedKeySpec;
19import java.sql.SQLException;
20import java.text.ParseException;
21import java.util.Base64;
22import java.util.Collection;
23import java.util.HashMap;
24import java.util.List;
25import java.util.Map;
26import java.util.Optional;
27import java.util.stream.Collectors;
28
29import javax.crypto.BadPaddingException;
30import javax.crypto.IllegalBlockSizeException;
31import javax.crypto.NoSuchPaddingException;
32
33import org.expeditee.agents.ExistingFramesetException;
34import org.expeditee.agents.InvalidFramesetNameException;
35import org.expeditee.auth.Mail.MailEntry;
36import org.expeditee.auth.account.Authenticate;
37import org.expeditee.auth.account.Authenticate.AuthenticationResult;
38import org.expeditee.auth.account.Create;
39import org.expeditee.auth.account.Password;
40import org.expeditee.auth.gui.MailBay;
41import org.expeditee.auth.tags.AuthenticationTag;
42import org.expeditee.core.Colour;
43import org.expeditee.gui.DisplayController;
44import org.expeditee.gui.Frame;
45import org.expeditee.gui.FrameIO;
46import org.expeditee.gui.MessageBay;
47import org.expeditee.items.Item;
48import org.expeditee.items.Text;
49import org.expeditee.settings.UserSettings;
50import org.expeditee.settings.identity.secrets.KeyList;
51import org.expeditee.stats.Formatter;
52import org.ngikm.cryptography.CryptographyConstants;
53
54public class Actions implements CryptographyConstants {
55
56 //Debug Functions
57 public static void SendTestMessage(String colleagueName) throws InvalidKeySpecException, NoSuchAlgorithmException, FileNotFoundException, KeyStoreException, CertificateException, ClassNotFoundException, IOException, SQLException {
58 String time = org.expeditee.stats.Formatter.getDateTime();
59 String sender = UserSettings.UserName.get();
60 String topic = "Test Message";
61 String message = "This is a test message.";
62 Map<String, String> options = new HashMap<String, String>();
63 options.put("Neat", "Beep");
64 MailEntry mail = new MailEntry(time, sender, colleagueName, topic, message, options);
65 Mail.sendMail(mail, colleagueName);
66 MessageBay.displayMessage("Test message sent.");
67 }
68 public static void SendTestMessageHemi(String param) {
69 String time = Formatter.getDateTime();
70 String sender = UserSettings.UserName.get();
71 String recipient = param.split(" ")[0];
72 String message = param.split(" ")[1];
73 Map<String, String> options = new HashMap<String, String>();
74 options.put("Accept", "beep");
75 options.put("Reject", "beep");
76 MailEntry mail = new MailEntry(time, sender, recipient, "Have a key", message, options);
77 Mail.sendMail(mail, recipient);
78 MessageBay.displayMessage("Test message sent.");
79 }
80
81 private static String userbackup = "authadmin";
82 public static void ToggleAuth() {
83 String backup = UserSettings.UserName.get();
84 UserSettings.UserName.set(userbackup);
85 userbackup = backup;
86 }
87
88 /**
89 * Display Expeditee Mail
90 * @throws IOException
91 * @throws SQLException
92 * @throws ClassNotFoundException
93 * @throws CertificateException
94 * @throws NoSuchAlgorithmException
95 * @throws FileNotFoundException
96 * @throws KeyStoreException
97 * @throws ParseException
98 * @throws InvalidKeySpecException
99 * @throws BadPaddingException
100 * @throws IllegalBlockSizeException
101 * @throws NoSuchPaddingException
102 * @throws InvalidKeyException
103 */
104 public static void ToggleBay() throws KeyStoreException, FileNotFoundException, NoSuchAlgorithmException, CertificateException, ClassNotFoundException, SQLException, IOException, ParseException, InvalidKeySpecException, InvalidKeyException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException {
105 if (!AuthenticatorBrowser.isAuthenticated()) return;
106 if (!DisplayController.isMailMode()) {
107 MailBay.ensureLink();
108 Mail.clear();
109 String keyEncoded = KeyList.PrivateKey.get().getData().get(0);
110 byte[] keyBytes = Base64.getDecoder().decode(keyEncoded);
111 PrivateKey key = KeyFactory.getInstance(AsymmetricAlgorithm).generatePrivate(new PKCS8EncodedKeySpec(keyBytes));
112 Mail.checkMail(key);
113 }
114 DisplayController.ToggleMailMode();
115 }
116
117 /**
118 * Action used to navigate the authorised user back to their desktop.
119 */
120 public static void AuthGoToDesktop() {
121 DisplayController.setCurrentFrame(FrameIO.LoadFrame(UserSettings.HomeFrame.get()), true);
122 }
123
124 /**
125 * Action used to created a new user account.
126 * Attempts to use content from text items on frame, will default to java properties if they cannot be found.
127 * Will fail if it cannot find content from text items on frame and all required java properties are not present.
128 * @throws SQLException
129 * @throws IOException
130 * @throws ExistingFramesetException
131 * @throws InvalidFramesetNameException
132 * @throws ClassNotFoundException
133 * @throws FileNotFoundException
134 * @throws CertificateException
135 * @throws NoSuchAlgorithmException
136 * @throws KeyStoreException
137 * @throws BadPaddingException
138 * @throws IllegalBlockSizeException
139 * @throws NoSuchPaddingException
140 * @throws InvalidKeySpecException
141 * @throws InvalidKeyException
142 * @throws ParseException
143 * @throws Exception
144 */
145 public static void AuthCreateAccount() throws KeyStoreException, NoSuchAlgorithmException, CertificateException, FileNotFoundException, ClassNotFoundException, InvalidFramesetNameException, ExistingFramesetException, IOException, SQLException, InvalidKeyException, InvalidKeySpecException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException, ParseException {
146 Collection<Text> textItems = DisplayController.getCurrentFrame().getTextItems();
147 Optional<Map<AuthenticationTag, String>> userdata =
148 AuthenticationTag.fetchUserData(textItems, false,
149 AuthenticationTag.Username,
150 AuthenticationTag.Password,
151 AuthenticationTag.PasswordAgain,
152 AuthenticationTag.Email,
153 AuthenticationTag.EmailAgain);
154
155 if (userdata.isPresent()) {
156 Map<AuthenticationTag, String> userData = userdata.get();
157
158 // A profile already existing with 'username' means an account cannot be created with that username.
159 if (FrameIO.getProfilesList().contains(userData.get(AuthenticationTag.Username))) {
160 MessageBay.errorMessage("A Expeditee profile with this username already exists, please choose another.");
161 return;
162 }
163
164 // The chosen username must be a valid frameset name.
165 if (!FrameIO.isValidFramesetName(userData.get(AuthenticationTag.Username))) {
166 MessageBay.errorMessage("The provided username must begin and end with a letter and contain only letters and numbers inbetween, please choose another.");
167 return;
168 }
169
170 // The passwords provided must match
171 if (userData.get(AuthenticationTag.Password).compareTo(userData.get(AuthenticationTag.PasswordAgain)) != 0) {
172 MessageBay.errorMessage("The provided passwords do not match, please fix this and try again.");
173 return;
174 }
175
176 // The emails provided must match
177 if (userData.get(AuthenticationTag.Email).compareTo(userData.get(AuthenticationTag.EmailAgain)) != 0) {
178 MessageBay.errorMessage("The provided emails do not match, please fix this and try again.");
179 return;
180 }
181
182 Create.createAccount(userData);
183 Authenticate.login(userData);
184 AuthenticatorBrowser.Authenticated = true;
185 } else {
186 MessageBay.errorMessage("Please fill out all the supplied text boxes.");
187 }
188 }
189
190 /**
191 * Action used to start authentication as a specified user.
192 * Attempts to use content from text items on frame, will default to java properties if they cannot be found.
193 * Will fail if it cannot find content from text items on frame and all required java properties are not present.
194 * @throws Exception
195 */
196 public static void AuthLogin() {
197 final Collection<Text> textItems = DisplayController.getCurrentFrame().getTextItems();
198 final Optional<Map<AuthenticationTag, String>> userdata = AuthenticationTag.fetchUserData(textItems, false, AuthenticationTag.Username, AuthenticationTag.Password);
199 if (userdata.isPresent()) {
200 AuthenticationResult result = Authenticate.login(userdata.get());
201 if (result == AuthenticationResult.SuccessLogin) {
202 MessageBay.displayMessage(result.toString());
203 } else {
204 MessageBay.errorMessage(result.toString());
205 }
206 //login(userdata.get());
207 AuthenticatorBrowser.Authenticated = true;
208 } else {
209 MessageBay.errorMessage("Please fill out all the supplied text boxes.");
210 }
211 }
212
213 public static void AuthLogout() {
214 MessageBay.displayMessage(Authenticate.logout().toString());
215 }
216
217 /**
218 * Action used to change the currently authenticated users password.
219 * Attempts to use content from text items on frame, will default to java properties if they cannot be found.
220 * Will fail if it cannot find content from text items on frame and all required java properties are not present.
221 * Will fail if no user is currently logged in.
222 * @throws IOException
223 * @throws CertificateException
224 * @throws FileNotFoundException
225 * @throws KeyStoreException
226 * @throws NoSuchAlgorithmException
227 * @throws SQLException
228 * @throws ClassNotFoundException
229 */
230 public static void AuthChangePassword() throws NoSuchAlgorithmException, KeyStoreException, FileNotFoundException, CertificateException, IOException, ClassNotFoundException, SQLException {
231 final Collection<Text> textItems = DisplayController.getCurrentFrame().getTextItems();
232
233 if (!AuthenticatorBrowser.Authenticated) {
234 MessageBay.errorMessage("You must be logged in to perform this action.");
235 } else {
236 final Optional<Map<AuthenticationTag, String>> userdata = AuthenticationTag.fetchUserData(textItems, false, AuthenticationTag.Password, AuthenticationTag.NewPassword, AuthenticationTag.NewPasswordAgain);
237 if (userdata.isPresent()) {
238 final Map<AuthenticationTag, String> userData = userdata.get();
239 if (userData.get(AuthenticationTag.NewPassword).compareTo(userData.get(AuthenticationTag.NewPasswordAgain)) != 0) {
240 MessageBay.errorMessage("The provided passwords do not match, please fix this and try again.");
241 } else {
242 userData.put(AuthenticationTag.Username, UserSettings.UserName.get());
243 Password.changePassword(userData);
244 }
245 } else {
246 MessageBay.errorMessage("Please fill out all the supplied text boxes.");
247 }
248 }
249 }
250
251 public static void AuthGotoAccountManagement() {
252 if (AuthenticatorBrowser.Authenticated) {
253 DisplayController.setCurrentFrame(FrameIO.LoadFrame("multiuser1"), false);
254 } else {
255 DisplayController.setCurrentFrame(FrameIO.LoadFrame("authentication1"), false);
256 }
257 }
258
259 public static void AuthResetPasswordPt1() {
260 MessageBay.displayMessage("AuthResetPasswordPt1");
261 }
262
263 public static void AuthResetPasswordPt2() {
264 MessageBay.displayMessage("AuthResetPasswordPt2");
265 }
266
267 public static void AuthShareFrameset() throws IOException {
268 Collection<Text> textItems = DisplayController.getCurrentFrame().getTextItems();
269
270 Optional<Map<AuthenticationTag, String>> userdata = AuthenticationTag.fetchUserData(textItems, false, AuthenticationTag.Frameset);
271 if (userdata.isPresent()) {
272 Map<AuthenticationTag, String> userData = userdata.get();
273 FrameIO.SuspendCache();
274 Frame toShare = FrameIO.LoadFrame(userData.get(AuthenticationTag.Frameset) + 1);
275 FrameIO.ResumeCache();
276
277 if (toShare == null) {
278 MessageBay.errorMessage("Insufficient information provided to complete this action.");
279 return;
280 }
281
282 shareFrameset(toShare);
283 }
284 }
285
286 /**
287 * Navigation action for progressing the process of recruiting colleagues to assist in password recovery.
288 * Hides certain content that AuthSubmitPWCollegues goes onto show if it does not fail.
289 */
290 public static void AuthGotoColleagueSubmissionFrame() {
291 Frame destination = FrameIO.LoadFrame("authentication7");
292 DisplayController.setCurrentFrame(destination, true);
293 Collection<Item> toHide = getByData(destination, "ShowOnProgress");
294 for (Item i: toHide) {
295 i.setVisible(false);
296 }
297 }
298
299 /**
300 * Action used to start the process of formalising the password recovery process.
301 * @throws SQLException
302 * @throws IOException
303 * @throws ClassNotFoundException
304 * @throws CertificateException
305 * @throws NoSuchAlgorithmException
306 * @throws FileNotFoundException
307 * @throws KeyStoreException
308 * @throws InvalidKeySpecException
309 */
310 public static void AuthSubmitPWColleagues() throws InvalidKeySpecException, NoSuchAlgorithmException, KeyStoreException, FileNotFoundException, CertificateException, ClassNotFoundException, IOException, SQLException {
311 Frame currentFrame = DisplayController.getCurrentFrame();
312 Collection<Text> textItems = currentFrame.getTextItems();
313
314 if (!AuthenticatorBrowser.Authenticated) {
315 MessageBay.errorMessage("You must be logged in to perform this action.");
316 return;
317 }
318
319 Optional<Map<AuthenticationTag, String>> userdata = AuthenticationTag.fetchUserData(textItems, false, AuthenticationTag.ColleagueOne, AuthenticationTag.ColleagueTwo);
320 if (userdata.isPresent()) {
321 Map<AuthenticationTag, String> userData = userdata.get();
322 String colleagueOne = userData.get(AuthenticationTag.ColleagueOne);
323 Path colleagueOnePath = Paths.get(FrameIO.CONTACTS_PATH).resolve(colleagueOne + "-credentials");
324 String colleagueTwo = userData.get(AuthenticationTag.ColleagueTwo);
325 Path colleagueTwoPath = Paths.get(FrameIO.CONTACTS_PATH).resolve(colleagueTwo + "-credentials");
326 if (!colleagueOnePath.toFile().exists()) {
327 MessageBay.errorMessage("Your nominated colleague: " + colleagueOne + " must exist in your contacts.");
328 } else if (!colleagueTwoPath.toFile().exists()) {
329 MessageBay.errorMessage("Your nominated colleague: " + colleagueTwo + " must exist in your contacts.");
330 } else {
331 userData.put(AuthenticationTag.Username, UserSettings.UserName.get());
332 boolean success = submitPWColleagues(userData);
333 if (success) {
334 Collection<Item> toShow = getByData(currentFrame, "ShowOnProgress");
335 for (Item i: toShow) {
336 i.setVisible(true);
337 }
338 currentFrame.change();
339 MessageBay.displayMessage("-------Messages sent-------");
340 }
341 FrameIO.SaveFrame(currentFrame);
342 DisplayController.requestRefresh(false);
343 }
344 }
345 }
346
347// public static void AuthSetupPasswordRecovery() throws KeyStoreException, FileNotFoundException, NoSuchAlgorithmException, CertificateException, ClassNotFoundException, IOException, SQLException, UnrecoverableEntryException {
348// if (!UserSettings.Authenticated.get()) {
349// MessageBay.errorMessage("You must be logged in to perform this action.");
350// } else if (!Authenticator.getInstance().hasRegisteredEmail(UserSettings.UserName.get())) {
351// Frame registerEmailFrame = FrameIO.LoadFrame("authentication4");
352// DisplayController.setCurrentFrame(registerEmailFrame, true);
353// } else if (!Authenticator.getInstance().hasRequestedColleagues(UserSettings.UserName.get()) && Authenticator.getInstance().getColleagues(UserSettings.UserName.get()) == null) {
354// Frame submitColleaguesFrame = FrameIO.LoadFrame("authentication5");
355// DisplayController.setCurrentFrame(submitColleaguesFrame, true);
356// } else if (Authenticator.getInstance().hasRequestedColleagues(UserSettings.UserName.get()) && Authenticator.getInstance().getColleagues(UserSettings.UserName.get()) == null) {
357// MessageBay.displayMessage("You have already nominated two colleagues to assist you in the process of password recovery and are awaiting their response."
358// + " You will be alerted on Expeditee startup when they have both responded.");
359// } else if (Authenticator.getInstance().getColleagues(UserSettings.UserName.get()) != null) {
360// MessageBay.displayMessage("You have completed the Password Recovery Setup process, there is nothing more to do here.");
361// }
362// }
363
364 public static void AuthConfirmPasswordColleagueRelationship(String colleagueName) {
365
366 }
367
368 public static void AuthDenyPasswordColleagueRelationship(String colleagueName) throws InvalidKeySpecException, NoSuchAlgorithmException,
369 KeyStoreException, FileNotFoundException, CertificateException, ClassNotFoundException, IOException, SQLException {
370 denyPasswordColleagueRelationship(colleagueName);
371 }
372
373 public static void AuthClearPWColleaguesNominated() {
374
375 }
376
377 /*
378 * Function to share a specified frameset.
379 * Currently, this moves the frameset to the 'Shared By Me' directory and then relies on the user to use Google Drive functionality to share it appropriately.
380 */
381 private static void shareFrameset(Frame toShare) throws IOException {
382 File destinationDir = new File(FrameIO.SHARED_FRAMESETS_PATH + File.separator + toShare.getFramesetName());
383 File sourceDir = new File(toShare.getFramesetPath());
384
385 if (destinationDir.exists()) {
386 MessageBay.errorMessage("A frameset by this name already exists.");
387 return;
388 }
389
390 destinationDir.mkdir();
391 List<Path> files = Files.walk(sourceDir.toPath()).collect(Collectors.toList());
392 Files.move(files.get(0), destinationDir.toPath(), StandardCopyOption.ATOMIC_MOVE);
393
394 MessageBay.displayMessage("The frameset " + toShare.getFramesetName() + " has been moved to " + destinationDir + ". Google Drive functionality can now be used to share it with colleagues.");
395 }
396
397 private static void denyPasswordColleagueRelationship(String colleagueName) throws InvalidKeySpecException, NoSuchAlgorithmException, KeyStoreException, FileNotFoundException, CertificateException, ClassNotFoundException, IOException, SQLException {
398 String time = org.expeditee.stats.Formatter.getDateTime();
399 String sender = UserSettings.UserName.get();
400 String message = "You have received a reply from " + sender + " reguarding your request for assistance.";
401 String message2 = "Unfortunately " + sender + " has indicated that they are unable to help you with your potential password recovery.";
402 Map<String, String> options = new HashMap<String, String>();
403 options.put("Clear Preview Colleague Nominations", "AuthClearPWColleaguesNominated");
404 MailEntry mail = new MailEntry(time, sender, colleagueName, message, message2, options);
405 Mail.sendMail(mail, colleagueName);
406 }
407
408 private static boolean submitPWColleagues(Map<AuthenticationTag, String> userData) throws InvalidKeySpecException, NoSuchAlgorithmException, KeyStoreException, FileNotFoundException, CertificateException, ClassNotFoundException, IOException, SQLException {
409 String colleagueOne = userData.get(AuthenticationTag.ColleagueOne);
410 String colleagueTwo = userData.get(AuthenticationTag.ColleagueTwo);
411 PublicKey colleagueOneKey = AuthenticatorBrowser.getInstance().getPublicKey(colleagueOne);
412 PublicKey colleagueTwoKey = AuthenticatorBrowser.getInstance().getPublicKey(colleagueTwo);
413 if (colleagueOneKey == null) {
414 MessageBay.errorMessage("Unable to get public key for colleague: " + colleagueOne);
415 return false;
416 } else if (colleagueTwoKey == null) {
417 MessageBay.errorMessage("Unable to get public key for colleague: " + colleagueTwo);
418 return false;
419 } else {
420 String time = org.expeditee.stats.Formatter.getDateTime();
421 String sender = userData.get(AuthenticationTag.Username);
422 String topic = "You have received a request for cooperation from your colleague " + sender;
423 String message = "Should " + sender + " forget their password, they would like your help recoverying it.";
424 Map<String, String> arguments = new HashMap<String, String>();
425 arguments.put("I agree to assist " + sender + " if they loose access to their account.", "AuthConfirmPasswordColleagueRelationship " + sender);
426 arguments.put("I wish to excuse myself from this responsibility.", "AuthDenyPasswordColleagueRelationship " + sender);
427 MailEntry mail = new MailEntry(time, sender, colleagueOne, topic, message, arguments);
428 Mail.sendMail(mail, colleagueOne);
429 mail = new MailEntry(time, sender, colleagueTwo, topic, message, arguments);
430 Mail.sendMail(mail, colleagueTwo);
431 AuthenticatorBrowser.getInstance().markRequestedColleagues(UserSettings.UserName.get());
432 return true;
433 }
434 }
435
436// // establish properties
437// final String from = "[email protected]";
438// final Properties properties = System.getProperties();
439//
440// properties.setProperty("mail.transport.protocol", "smtp");
441// properties.setProperty("mail.smtp.host", "smtp.gmail.com");
442// properties.setProperty("mail.smtp.port", "465");
443// properties.setProperty("mail.smtp.starttls.enable", "true");
444// properties.setProperty("mail.smtp.auth", "true");
445// properties.setProperty("mail.smtp.debug", "true");
446// properties.setProperty("mail.smtp.auth", "true");
447// properties.setProperty("mail.smtp.socketFactory.port", "465");
448// properties.setProperty("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
449// properties.setProperty("mail.smtp.socketFactory.fallback", "false");
450//
451// final Session session = Session.getDefaultInstance(properties, new javax.mail.Authenticator() {
452// @Override
453// protected PasswordAuthentication getPasswordAuthentication() {
454// return new PasswordAuthentication("noreply.expeditee", "intergalacticnumber");
455// };
456// });
457
458// // construct email message
459// final MimeMessage message = new MimeMessage(session);
460// message.setFrom(new InternetAddress(from));
461// message.addRecipient(Message.RecipientType.TO, new InternetAddress(email));
462// message.setSubject("Expeditee Password Recovery");
463// message.setText(intergalacticNumber);
464//
465// // send email message
466// Transport.send(message);
467
468
469 public static void TickBox(final Text item) {
470 if (item.getBackgroundColor() != Colour.RED) {
471 item.setBackgroundColor(Colour.RED);
472 } else {
473 item.setBackgroundColor(Colour.GREEN);
474 }
475 }
476
477 /*
478 * Gets all items on a specified frame that contain the specified data.
479 */
480 public static Collection<Item> getByData(final Frame frame, final String data) {
481 final Collection<Item> allItems = frame.getAllItems();
482 allItems.removeIf(i -> i.getData() == null || !i.hasData(data));
483 return allItems;
484 }
485
486 public static Collection<Item> getByContent(final Frame frame, final String content) {
487 final Collection<Item> allItems = frame.getAllItems();
488 allItems.removeIf(i -> i.getText().compareTo(content) != 0);
489 return allItems;
490 }
491}
Note: See TracBrowser for help on using the repository browser.