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

Last change on this file since 1504 was 1504, checked in by bnemhaus, 4 years ago

Revised implementation of authenticated Expeditee mail. Motivated by bugs relating to messages not being marked as read and incorrect counting of new messages for users, the Expeditee mail system has been rewritten. The new code not only does not exhibit the previous bugs but is also better engineered. Whilst the MailBay is static (which is in line with the MessageBay), the Mail class is no longer static and must be initialised for each user as they log in.

File size: 25.3 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.KeyStoreException;
12import java.security.NoSuchAlgorithmException;
13import java.security.PublicKey;
14import java.security.SecureRandom;
15import java.security.cert.CertificateException;
16import java.security.spec.InvalidKeySpecException;
17import java.sql.SQLException;
18import java.text.ParseException;
19import java.util.Base64;
20import java.util.Collection;
21import java.util.Date;
22import java.util.HashMap;
23import java.util.List;
24import java.util.Map;
25import java.util.Optional;
26import java.util.Random;
27import java.util.Scanner;
28import java.util.stream.Collectors;
29
30import javax.crypto.BadPaddingException;
31import javax.crypto.IllegalBlockSizeException;
32import javax.crypto.NoSuchPaddingException;
33import javax.crypto.SecretKey;
34import javax.crypto.spec.SecretKeySpec;
35
36import org.expeditee.agents.ExistingFramesetException;
37import org.expeditee.agents.InvalidFramesetNameException;
38import org.expeditee.auth.account.Authenticate;
39import org.expeditee.auth.account.Authenticate.AuthenticationResult;
40import org.expeditee.auth.account.Contacts;
41import org.expeditee.auth.account.Create;
42import org.expeditee.auth.account.Create.CreateResult;
43import org.expeditee.auth.account.Password;
44import org.expeditee.auth.mail.Mail;
45import org.expeditee.auth.mail.Mail.MailEntry;
46import org.expeditee.auth.mail.gui.MailBay;
47import org.expeditee.auth.tags.AuthenticationTag;
48import org.expeditee.encryption.CryptographyConstants;
49import org.expeditee.gio.gesture.StandardGestureActions;
50import org.expeditee.gui.DisplayController;
51import org.expeditee.gui.Frame;
52import org.expeditee.gui.FrameIO;
53import org.expeditee.gui.MessageBay;
54import org.expeditee.items.Item;
55import org.expeditee.items.Text;
56import org.expeditee.settings.UserSettings;
57
58public class Actions implements CryptographyConstants {
59
60 // Start Debug Actions
61 public static void SendTestMessage(String recipient) {
62 String time = Mail.FORMAT.format(new Date());
63 String sender = UserSettings.UserName.get();
64 String topic = "Test Message";
65 String message = "This is a test message.";
66 Map<String, String> options = new HashMap<String, String>();
67 options.put("Neat", "Beep");
68 Mail mailClient = MailBay.getMailClient();
69 Mail.MailEntry mail = mailClient.new MailEntry(time, sender, recipient, topic, message, options);
70 mailClient.sendMail(mail, recipient);
71 MessageBay.displayMessage("Test message sent.");
72 }
73
74 public static void CheckMailTest() {
75 List<Mail.MailEntry> mail = MailBay.getMailClient().checkMail();
76 for (Mail.MailEntry entry: mail) {
77 MessageBay.displayMessage(entry.toString());
78 }
79 MessageBay.displayMessage(mail.size() + " new mail since last run.");
80 }
81
82 public static void SendTestOneOffMessage(String recipient) {
83 String time = Mail.FORMAT.format(new Date());
84 String sender = UserSettings.UserName.get();
85 String topic = "Test Message";
86 String message = "This is a test message.";
87 Map<String, String> options = new HashMap<String, String>();
88 options.put("Neat", "Beep");
89
90 Random rand = new SecureRandom();
91 byte[] keyBytes = new byte[16];
92 rand.nextBytes(keyBytes);
93 SecretKey key = new SecretKeySpec(keyBytes, SymmetricAlgorithm);
94 System.out.println(Base64.getEncoder().encodeToString(keyBytes));
95
96 Mail mailClient = MailBay.getMailClient();
97 Mail.MailEntry mail = mailClient.new MailEntry(time, sender, recipient, topic, message, options);
98 mailClient.sendOneOffMail(mail, recipient, key);
99 MessageBay.displayMessage("Test message sent.");
100 }
101
102 private static String userbackup = "authadmin";
103 public static void ToggleAuth() {
104 String backup = UserSettings.UserName.get();
105 System.setProperty("user.name", userbackup);
106 UserSettings.UserName.set(userbackup);
107 userbackup = backup;
108 }
109 // End Debug Actions
110
111 // Start Misc Auth Actions
112 public static void CheckForNewMail() {
113 MailBay.checkMail();
114 }
115
116 /**
117 * Action ran by user to read a message using a single use distributed Symmetric key
118 * @param cursor The content on the cursor should be a text item whose content is the
119 * Symmetric key to use, represented as a Base64 encoded string.
120 * @param actionItem The action item will contain the encrypted message in its data.
121 */
122 public static void AuthOneOffSecureMessage(Text cursor, Text actionItem) {
123 byte[] keyBytes = Base64.getDecoder().decode(cursor.getText());
124 SecretKey key = new SecretKeySpec(keyBytes, SymmetricAlgorithm);
125 List<String> data = actionItem.getData();
126 MailBay.decryptOneOffSecureMessage(key, data);
127 StandardGestureActions.Refresh();
128 }
129
130 /**
131 * Display Expeditee Mail
132 * @throws IOException
133 * @throws SQLException
134 * @throws ClassNotFoundException
135 * @throws CertificateException
136 * @throws NoSuchAlgorithmException
137 * @throws FileNotFoundException
138 * @throws KeyStoreException
139 * @throws ParseException
140 * @throws InvalidKeySpecException
141 * @throws BadPaddingException
142 * @throws IllegalBlockSizeException
143 * @throws NoSuchPaddingException
144 * @throws InvalidKeyException
145 */
146 public static void ToggleBay() throws KeyStoreException, FileNotFoundException, NoSuchAlgorithmException, CertificateException, ClassNotFoundException, SQLException, IOException, ParseException, InvalidKeySpecException, InvalidKeyException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException {
147 if (!AuthenticatorBrowser.isAuthenticated()) return;
148 //if (!DisplayController.isMailMode()) {
149 // MailBayV2.checkMail();
150 //}
151 DisplayController.ToggleMailMode();
152 }
153
154 /**
155 * Action used to navigate the authorised user back to their desktop.
156 */
157 public static void AuthGoToDesktop() {
158 if (AuthenticatorBrowser.Authenticated) {
159 DisplayController.setCurrentFrame(FrameIO.LoadFrame(UserSettings.HomeFrame.get()), true);
160 } else {
161 MessageBay.displayMessage("Please Login to proceed to your home frame.");
162 DisplayController.setCurrentFrame(FrameIO.LoadFrame("authentication1"), true);
163 }
164 }
165
166 /**
167 * Action used to navigate to multiuser1 (multiuser abilities) if authenticated and authentication1 (login) is not so.
168 */
169 public static void AuthGotoAccountManagement() {
170 if (AuthenticatorBrowser.Authenticated) {
171 DisplayController.setCurrentFrame(FrameIO.LoadFrame("multiuser1"), true);
172 } else {
173 MessageBay.displayMessage("Please Login to proceed to account managment.");
174 DisplayController.setCurrentFrame(FrameIO.LoadFrame("authentication1"), true);
175 }
176 }
177
178 /**
179 * Gets all items on a specified frame that contain the specified data.
180 */
181 public static Collection<Item> getByData(Frame frame, String data) {
182 Collection<Item> allItems = frame.getAllItems();
183 allItems.removeIf(i -> i.getData() == null || !i.hasData(data));
184 return allItems;
185 }
186
187 /**
188 * Gets all items on a specified frame that contains the specified content.
189 */
190 public static Collection<Item> getByContent(Frame frame, String content) {
191 Collection<Item> allItems = frame.getAllItems();
192 allItems.removeIf(i -> i.getText().compareTo(content) != 0);
193 return allItems;
194 }
195 // End Misc Auth Actions
196
197 // Start Making Contacts Actions
198 public static void AuthDistributeContactDetails() {
199 MessageBay.displayMessage(
200 "To receive directions on distributing your contact details to someone, attach their username to your cursor and run this action again."
201 );
202 }
203 public static String AuthDistributeContactDetails(String username) {
204 return Contacts.distributeContactDetails(username);
205 }
206 public static void AuthAddContactDetails() {
207 MessageBay.displayMessage("If a user has sent their contact details to you, running this action again with their username attached to your cursor will display instructions to adding those details to your contacts directory.");
208 }
209 public static String AuthAddContactDetails(String username) {
210 return Contacts.addContactDetails(username);
211 }
212 // End Making Contacts Actions
213
214 // Start Regain Account Access Actions
215 /**
216 * Action used to start the process of formalising the password recovery process.
217 * @throws SQLException
218 * @throws IOException
219 * @throws ClassNotFoundException
220 * @throws CertificateException
221 * @throws NoSuchAlgorithmException
222 * @throws FileNotFoundException
223 * @throws KeyStoreException
224 * @throws InvalidKeySpecException
225 */
226 public static void AuthSubmitTrustedUsersPasswordRecovery() throws InvalidKeySpecException, NoSuchAlgorithmException, KeyStoreException, FileNotFoundException, CertificateException, ClassNotFoundException, IOException, SQLException {
227 Frame currentFrame = DisplayController.getCurrentFrame();
228 Collection<Text> textItems = currentFrame.getTextItems();
229
230 if (!AuthenticatorBrowser.Authenticated) {
231 MessageBay.errorMessage("You must be logged in to perform this action.");
232 return;
233 }
234
235 Optional<Map<AuthenticationTag, String>> userdata = AuthenticationTag.fetchUserData(textItems, false, AuthenticationTag.TrustedUserOne, AuthenticationTag.TrustedUserTwo);
236 if (userdata.isPresent()) {
237 Map<AuthenticationTag, String> userData = userdata.get();
238 String colleagueOne = userData.get(AuthenticationTag.TrustedUserOne);
239 String colleagueTwo = userData.get(AuthenticationTag.TrustedUserTwo);
240 String username = UserSettings.UserName.get().toLowerCase();
241 if (colleagueOne.toLowerCase().equals(username) || colleagueTwo.toLowerCase().equals(username)) {
242 MessageBay.displayMessage("You cannot nominate yourself as one of your trusted colleagues.");
243 } else {
244 AuthSubmitTrustedUsersPasswordRecovery(colleagueOne, colleagueTwo);
245 }
246 }
247 }
248
249 /**
250 * Action ran by user to specify who their password colleagues are. These are the
251 * individuals who will be consulted if and when the user needs to regain access
252 * to their account.
253 * @param colleagueOne
254 * @param colleagueTwo
255 */
256 public static void AuthSubmitTrustedUsersPasswordRecovery(String colleagueOne, String colleagueTwo) {
257 Password.setPWColleagues(colleagueOne, colleagueTwo);
258 }
259
260 /**
261 * Action ran by user to oblige with a request from colleague who has nominated the
262 * user as a pw colleague. Will email (not Expeditee mail) the colleague the password
263 * share that the user has stored on their secrets frame.
264 * @param colleagueName
265 */
266 public static void AuthEmailPasswordShare(String colleagueName) {
267 Password.emailPasswordShare(colleagueName);
268 }
269
270 /**
271 * Action ran by user to regain access to their account by providing:
272 * their username
273 * two password shares obtained from pw colleagues
274 * their desired new password
275 */
276 public static void AuthRegainAccountAccess() {
277 Collection<Text> textItems = DisplayController.getCurrentFrame().getTextItems();
278 Optional<Map<AuthenticationTag, String>> userdata = AuthenticationTag.fetchUserData(textItems, false,
279 AuthenticationTag.Username, AuthenticationTag.NewPassword, AuthenticationTag.NewPasswordAgain,
280 AuthenticationTag.PasswordSliceOne, AuthenticationTag.PasswordSliceTwo);
281 if (userdata.isPresent()) {
282 // Confirm new requested passwords match
283 Map<AuthenticationTag, String> userData = userdata.get();
284 String username = userData.get(AuthenticationTag.Username).trim();
285 if (username.length() == 0) {
286 MessageBay.errorMessage("Please fill out the username box.");
287 } else if (!userData.get(AuthenticationTag.NewPassword).equals(userData.get(AuthenticationTag.NewPasswordAgain))) {
288 MessageBay.errorMessage("The passwords you have provided do not match.");
289 } else {
290 Password.regainAccountAccess(userData);
291 }
292 }
293 }
294
295 /**
296 * Actions used to generate and deliver an intergalactic number to a users public email
297 * address after they have began the password recovery process.
298 */
299 public static void AuthDistributeIntergalacticNumber() {
300 Text displayMessage = MessageBay.displayMessage("Action processing....");
301 Collection<Text> textItems = DisplayController.getCurrentFrame().getTextItems();
302 Optional<Map<AuthenticationTag, String>> userdata =
303 AuthenticationTag.fetchUserData(textItems, false, AuthenticationTag.Username);
304 if (userdata.isPresent()) {
305 Map<AuthenticationTag, String> userData = userdata.get();
306 String username = userData.get(AuthenticationTag.Username);
307 String email = getEmailFromUsername(username);
308 userData.put(AuthenticationTag.Email, email);
309 Password.generateAndDeliverIntergalacticNumber(userData);
310 MessageBay.displayMessage("An identity number has been sent to the email "
311 + "associated with your account. Enter it below to proceed.");
312 }
313 displayMessage.setText(displayMessage.getText() + "..Done");
314 }
315
316 /**
317 * Action used by user to submit their intergalactic number along with their username
318 * in order to confirm that they own the public email address registered to their account.
319 * This is part of the process of recoverying access to an account.
320 */
321 public static void AuthSubmitIntergalacticNumber() {
322 Text displayMessage = MessageBay.displayMessage("Action processing....");
323 Collection<Text> textItems = DisplayController.getCurrentFrame().getTextItems();
324 Optional<Map<AuthenticationTag, String>> userdata =
325 AuthenticationTag.fetchUserData(textItems, false, AuthenticationTag.Username,
326 AuthenticationTag.IntergalacticNumber);
327 if (userdata.isPresent()) {
328 Password.confirmIntergalacticNumberAndAlertTrustedUsers(userdata.get());
329 }
330 displayMessage.setText(displayMessage.getText() + "..Done");
331 }
332 // End Regain Account Access Actions
333
334 // Start Create Account Actions
335 /**
336 * Action used to created a new user account.
337 * Attempts to use content from text items on frame, will default to java properties if they cannot be found.
338 * Will fail if it cannot find content from text items on frame and all required java properties are not present.
339 * @throws SQLException
340 * @throws IOException
341 * @throws ExistingFramesetException
342 * @throws InvalidFramesetNameException
343 * @throws ClassNotFoundException
344 * @throws FileNotFoundException
345 * @throws CertificateException
346 * @throws NoSuchAlgorithmException
347 * @throws KeyStoreException
348 * @throws BadPaddingException
349 * @throws IllegalBlockSizeException
350 * @throws NoSuchPaddingException
351 * @throws InvalidKeySpecException
352 * @throws InvalidKeyException
353 * @throws ParseException
354 * @throws Exception
355 */
356 public static void AuthCreateAccount() throws KeyStoreException, NoSuchAlgorithmException, CertificateException, FileNotFoundException, ClassNotFoundException, InvalidFramesetNameException, ExistingFramesetException, IOException, SQLException, InvalidKeyException, InvalidKeySpecException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException, ParseException {
357 Collection<Text> textItems = DisplayController.getCurrentFrame().getTextItems();
358 Optional<Map<AuthenticationTag, String>> userdata =
359 AuthenticationTag.fetchUserData(textItems, false,
360 AuthenticationTag.Username,
361 AuthenticationTag.Password,
362 AuthenticationTag.PasswordAgain,
363 AuthenticationTag.Email,
364 AuthenticationTag.EmailAgain);
365
366 if (userdata.isPresent()) {
367 Map<AuthenticationTag, String> userData = userdata.get();
368
369 // A profile already existing with 'username' means an account cannot be created with that username.
370 if (FrameIO.getProfilesList().contains(userData.get(AuthenticationTag.Username))) {
371 MessageBay.errorMessage("A Expeditee profile with this username already exists, please choose another.");
372 return;
373 }
374
375 // The chosen username must be a valid frameset name.
376 if (!FrameIO.isValidFramesetName(userData.get(AuthenticationTag.Username))) {
377 MessageBay.errorMessage("The provided username must begin and end with a letter and contain only letters and numbers inbetween, please choose another.");
378 return;
379 }
380
381 // The passwords provided must match
382 if (userData.get(AuthenticationTag.Password).compareTo(userData.get(AuthenticationTag.PasswordAgain)) != 0) {
383 MessageBay.errorMessage("The provided passwords do not match, please fix this and try again.");
384 return;
385 }
386
387 // The emails provided must match
388 if (userData.get(AuthenticationTag.Email).compareTo(userData.get(AuthenticationTag.EmailAgain)) != 0) {
389 MessageBay.errorMessage("The provided emails do not match, please fix this and try again.");
390 return;
391 }
392
393 CreateResult result = Create.createAccount(userData);
394 if (result == CreateResult.SuccessCreateAccount) {
395 Authenticate.login(userData);
396 AuthenticatorBrowser.Authenticated = true;
397 } else {
398 MessageBay.errorMessage(result.toString());
399 }
400 } else {
401 MessageBay.errorMessage("Please fill out all the supplied text boxes.");
402 }
403 }
404 // End Create Account Actions
405
406 // Start Account Login Actions
407 /**
408 * Action used to start authentication as a specified user.
409 * Attempts to use content from text items on frame, will default to java properties if they cannot be found.
410 * Will fail if it cannot find content from text items on frame and all required java properties are not present.
411 * @throws Exception
412 */
413 public static void AuthLogin() {
414 Collection<Text> textItems = DisplayController.getCurrentFrame().getTextItems();
415 Optional<Map<AuthenticationTag, String>> userdata = AuthenticationTag.fetchUserData(textItems, false, AuthenticationTag.Username, AuthenticationTag.Password);
416 if (userdata.isPresent()) {
417 AuthenticationResult result = Authenticate.login(userdata.get());
418 if (result == AuthenticationResult.SuccessLogin) {
419 MessageBay.displayMessage(result.toString());
420 AuthenticatorBrowser.Authenticated = true;
421 } else {
422 MessageBay.errorMessage(result.toString());
423 }
424 } else {
425 MessageBay.errorMessage("Please fill out all the supplied text boxes.");
426 }
427 }
428
429 /**
430 * Action used by the user to log out of their account.
431 */
432 public static void AuthLogout() {
433 MessageBay.displayMessage(Authenticate.logout().toString());
434 }
435 // End Account Login Actions
436
437 // Start Change Access Actions
438 /**
439 * Action used to change the currently authenticated users password.
440 * Attempts to use content from text items on frame, will default to java properties if they cannot be found.
441 * Will fail if it cannot find content from text items on frame and all required java properties are not present.
442 * Will fail if no user is currently logged in.
443 * @throws IOException
444 * @throws CertificateException
445 * @throws FileNotFoundException
446 * @throws KeyStoreException
447 * @throws NoSuchAlgorithmException
448 * @throws SQLException
449 * @throws ClassNotFoundException
450 */
451 public static void AuthChangePassword() throws NoSuchAlgorithmException, KeyStoreException, FileNotFoundException, CertificateException, IOException, ClassNotFoundException, SQLException {
452 final Collection<Text> textItems = DisplayController.getCurrentFrame().getTextItems();
453
454 if (!AuthenticatorBrowser.Authenticated) {
455 MessageBay.errorMessage("You must be logged in to perform this action.");
456 } else {
457 final Optional<Map<AuthenticationTag, String>> userdata = AuthenticationTag.fetchUserData(textItems, false, AuthenticationTag.Password, AuthenticationTag.NewPassword, AuthenticationTag.NewPasswordAgain);
458 if (userdata.isPresent()) {
459 final Map<AuthenticationTag, String> userData = userdata.get();
460 if (userData.get(AuthenticationTag.NewPassword).compareTo(userData.get(AuthenticationTag.NewPasswordAgain)) != 0) {
461 MessageBay.errorMessage("The provided passwords do not match, please fix this and try again.");
462 } else {
463 userData.put(AuthenticationTag.Username, UserSettings.UserName.get());
464 Password.changePassword(userData);
465 }
466 } else {
467 MessageBay.errorMessage("Please fill out all the supplied text boxes.");
468 }
469 }
470 }
471 // End Change Access Actions
472
473 // Start Private Helper Functions.
474 /**
475 * Gets the public email address associated with the specified username.
476 * @param username
477 * @return
478 */
479 private static String getEmailFromUsername(String username) {
480 Path credentialsDirPath = Paths.get(FrameIO.PROFILE_PATH).resolve(username).resolve(username + "-credentials");
481 Path credentialsFilePath = credentialsDirPath.resolve("credentials.inf");
482 String fileName = null;
483 if (credentialsFilePath.toFile().exists()) {
484 try (Scanner in = new Scanner(credentialsFilePath)) {
485 fileName = in.nextLine();
486 } catch (IOException e) {
487 MessageBay.errorMessage("Unable to locate public email for specified user, are they registered on this computer?");
488 return null;
489 }
490 } else {
491 MessageBay.errorMessage("Unable to locate public email for specified user, are they registered on this computer?");
492 return null;
493 }
494
495 int number = Integer.parseInt(fileName.replace(".exp", ""));
496 Frame credentialsFrame = FrameIO.LoadFrame(username + number, FrameIO.PROFILE_PATH);
497 Collection<Text> textItems = credentialsFrame.getTextItems();
498 textItems.removeIf(text -> !text.getText().startsWith("Email: "));
499 if (textItems.isEmpty()) {
500 MessageBay.errorMessage("Unable to locate public email for specified user, are they registered on this computer?");
501 return null;
502 } else {
503 Text emailText = textItems.iterator().next();
504 String email = emailText.getText().replace("Email: ", "");
505 return email;
506 }
507 }
508 // End Private Helper Functions.
509
510 // Start Future Functionality
511 public static void AuthShareFrameset() throws IOException {
512 Collection<Text> textItems = DisplayController.getCurrentFrame().getTextItems();
513
514 Optional<Map<AuthenticationTag, String>> userdata = AuthenticationTag.fetchUserData(textItems, false, AuthenticationTag.Frameset);
515 if (userdata.isPresent()) {
516 Map<AuthenticationTag, String> userData = userdata.get();
517 FrameIO.SuspendCache();
518 Frame toShare = FrameIO.LoadFrame(userData.get(AuthenticationTag.Frameset) + 1);
519 FrameIO.ResumeCache();
520
521 if (toShare == null) {
522 MessageBay.errorMessage("Insufficient information provided to complete this action.");
523 return;
524 }
525
526 shareFrameset(toShare);
527 }
528 }
529
530 /*
531 * Function to share a specified frameset.
532 * 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.
533 */
534 private static void shareFrameset(Frame toShare) throws IOException {
535 File destinationDir = new File(FrameIO.SHARED_FRAMESETS_PATH + File.separator + toShare.getFramesetName());
536 File sourceDir = new File(toShare.getFramesetPath());
537
538 if (destinationDir.exists()) {
539 MessageBay.errorMessage("A frameset by this name already exists.");
540 return;
541 }
542
543 destinationDir.mkdir();
544 List<Path> files = Files.walk(sourceDir.toPath()).collect(Collectors.toList());
545 Files.move(files.get(0), destinationDir.toPath(), StandardCopyOption.ATOMIC_MOVE);
546
547 MessageBay.displayMessage("The frameset " + toShare.getFramesetName() + " has been moved to " + destinationDir + ". Google Drive functionality can now be used to share it with colleagues.");
548 }
549
550 /*
551 * Function to submit a request to specified contacts to be the current users pw colleagues.
552 */
553 @SuppressWarnings("unused")
554 private static boolean submitTrustedUsersPasswordRecovery(Map<AuthenticationTag, String> userData) throws InvalidKeySpecException, NoSuchAlgorithmException, KeyStoreException, FileNotFoundException, CertificateException, ClassNotFoundException, IOException, SQLException {
555 String trustedUserOne = userData.get(AuthenticationTag.TrustedUserOne);
556 String trustedUserTwo = userData.get(AuthenticationTag.TrustedUserTwo);
557 PublicKey colleagueOneKey = AuthenticatorBrowser.getInstance().getPublicKey(trustedUserOne);
558 PublicKey colleagueTwoKey = AuthenticatorBrowser.getInstance().getPublicKey(trustedUserTwo);
559 if (colleagueOneKey == null) {
560 MessageBay.errorMessage("Unable to get public key for colleague: " + trustedUserOne);
561 return false;
562 } else if (colleagueTwoKey == null) {
563 MessageBay.errorMessage("Unable to get public key for colleague: " + trustedUserTwo);
564 return false;
565 } else {
566 String time = Mail.FORMAT.format(new Date());
567 String sender = userData.get(AuthenticationTag.Username);
568 String topic = "You have received a request for cooperation from your colleague " + sender;
569 String message = "Should " + sender + " forget their password, they would like your help recoverying it.";
570 Map<String, String> arguments = new HashMap<String, String>();
571 arguments.put("I agree to assist " + sender + " if they loose access to their account.", "AuthConfirmPasswordColleagueRelationship " + sender);
572 arguments.put("I wish to excuse myself from this responsibility.", "AuthDenyPasswordColleagueRelationship " + sender);
573 Mail outbox = MailBay.getMailClient();
574 MailEntry mail = outbox.new MailEntry(time, sender, trustedUserOne, topic, message, arguments);
575 outbox.sendMail(mail, trustedUserOne);
576 mail = outbox.new MailEntry(time, sender, trustedUserTwo, topic, message, arguments);
577 outbox.sendMail(mail, trustedUserTwo);
578 AuthenticatorBrowser.getInstance().markRequestedColleagues(UserSettings.UserName.get());
579 return true;
580 }
581 }
582 // End Future Functionality
583}
Note: See TracBrowser for help on using the repository browser.