Ignore:
Timestamp:
05/17/19 14:37:12 (5 years ago)
Author:
bln4
Message:

It is now possible to complete the process of recovering access to a Expeditee account. Further work, in the form of frames in the authentication frameset, are to follow.
A refactoring/tidy up has also been completed.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/expeditee/auth/Actions.java

    r1362 r1363  
    2323import java.util.Collection;
    2424import java.util.HashMap;
    25 import java.util.Iterator;
    2625import java.util.List;
    2726import java.util.Map;
     
    3938import org.expeditee.agents.ExistingFramesetException;
    4039import org.expeditee.agents.InvalidFramesetNameException;
    41 import org.expeditee.auth.Mail.MailEntry;
    4240import org.expeditee.auth.account.Authenticate;
    4341import org.expeditee.auth.account.Authenticate.AuthenticationResult;
     
    4543import org.expeditee.auth.account.Create.CreateResult;
    4644import org.expeditee.auth.account.Password;
    47 import org.expeditee.auth.gui.MailBay;
     45import org.expeditee.auth.mail.Mail;
     46import org.expeditee.auth.mail.Mail.MailEntry;
     47import org.expeditee.auth.mail.gui.MailBay;
    4848import org.expeditee.auth.tags.AuthenticationTag;
    49 import org.expeditee.core.Colour;
    5049import org.expeditee.gio.gesture.StandardGestureActions;
    5150import org.expeditee.gui.DisplayController;
     
    5655import org.expeditee.items.Text;
    5756import org.expeditee.settings.UserSettings;
    58 import org.expeditee.settings.identity.passwordrecovery.Colleagues;
    5957import org.expeditee.settings.identity.secrets.KeyList;
    6058import org.expeditee.stats.Formatter;
     
    6361public class Actions implements CryptographyConstants {
    6462       
    65         //Debug Functions
     63        //      Start Debug Actions
    6664        public static void SendTestMessage(String colleagueName) throws InvalidKeySpecException, NoSuchAlgorithmException, FileNotFoundException, KeyStoreException, CertificateException, ClassNotFoundException, IOException, SQLException {
    6765                String time = org.expeditee.stats.Formatter.getDateTime();
     
    7573                MessageBay.displayMessage("Test message sent.");
    7674        }
     75       
    7776        public static void SendTestMessageHemi(String param) {
    7877                String time = Formatter.getDateTime();
     
    8786                MessageBay.displayMessage("Test message sent.");
    8887        }
     88       
    8989        public static void SendTestOneOffMessage(String colleagueName) {
    9090                String time = Formatter.getDateTime();
     
    101101                Mail.sendOneOffMail(mail, colleagueName, key);
    102102        }
    103         public static void AuthOneOffSecureMessage(Text cursor, Text actionItem) {
    104                 byte[] keyBytes = Base64.getDecoder().decode(cursor.getText());
    105                 SecretKey key = new SecretKeySpec(keyBytes, SymmetricAlgorithm);
    106                 List<String> data = actionItem.getData();
    107                 String topic = new String(org.expeditee.auth.sharing.Actions.DecryptSymmetric(Base64.getDecoder().decode(data.get(3)), key));
    108                 String message = new String(org.expeditee.auth.sharing.Actions.DecryptSymmetric(Base64.getDecoder().decode(data.get(4)), key));
    109                 Map<String, String> options = new HashMap<String, String>();
    110                 for (int i = 5; i < data.size(); i+=2) {
    111                         String k = new String(org.expeditee.auth.sharing.Actions.DecryptSymmetric(Base64.getDecoder().decode(data.get(i)), key));
    112                         String v = new String(org.expeditee.auth.sharing.Actions.DecryptSymmetric(Base64.getDecoder().decode(data.get(i + 1)), key));
    113                         options.put(k, v);
    114                 }
    115                 MailBay.addMessage(data.get(0), topic, message, options);
    116                 StandardGestureActions.Refresh();
    117         }
    118         public static void SetPWColleagues(String colleagueOne, String colleagueTwo) {
    119                 Colleagues.Colleague_One.set(colleagueOne);
    120                 Colleagues.Colleague_Two.set(colleagueTwo);
    121                 Colleagues.Colleague_One_Email.set("[email protected]");
    122                 Colleagues.Colleague_Two_Email.set("[email protected]");
    123         }
    124103       
    125104        private static String userbackup = "authadmin";
     
    128107                UserSettings.UserName.set(userbackup);
    129108                userbackup = backup;
     109        }
     110        //      End Debug Actions
     111       
     112        //      Start Misc Auth Actions
     113        /**
     114         * Action ran by user to read a message using a single use distributed Symmetric key
     115         * @param cursor The content on the cursor should be a text item whose content is the
     116         * Symmetric key to use, represented as a Base64 encoded string.
     117         * @param actionItem The action item will contain the encrypted message in its data.
     118         */
     119        public static void AuthOneOffSecureMessage(Text cursor, Text actionItem) {
     120                byte[] keyBytes = Base64.getDecoder().decode(cursor.getText());
     121                SecretKey key = new SecretKeySpec(keyBytes, SymmetricAlgorithm);
     122                List<String> data = actionItem.getData();
     123                Mail.decryptOneOffSecureMessage(key, data);
     124                StandardGestureActions.Refresh();
    130125        }
    131126       
     
    166161        }
    167162       
     163        /**
     164         * Action used to navigate to multiuser1 (multiuser abilities) if authenticated and authentication1 (login) is not so.
     165         */
     166        public static void AuthGotoAccountManagement() {
     167                if (AuthenticatorBrowser.Authenticated) {
     168                        DisplayController.setCurrentFrame(FrameIO.LoadFrame("multiuser1"), false);
     169                } else {
     170                        DisplayController.setCurrentFrame(FrameIO.LoadFrame("authentication1"), false);
     171                }
     172        }
     173       
     174        /**
     175         * Gets all items on a specified frame that contain the specified data.
     176         */
     177        public static Collection<Item> getByData(Frame frame, String data) {
     178                Collection<Item> allItems = frame.getAllItems();
     179                allItems.removeIf(i -> i.getData() == null || !i.hasData(data));
     180                return allItems;
     181        }
     182       
     183        /**
     184         * Gets all items on a specified frame that contains the specified content.
     185         */
     186        public static Collection<Item> getByContent(Frame frame, String content) {
     187                Collection<Item> allItems = frame.getAllItems();
     188                allItems.removeIf(i -> i.getText().compareTo(content) != 0);
     189                return allItems;
     190        }
     191        //      End Misc Auth Actions
     192       
     193        //      Start Regain Account Access Actions
     194        /**
     195         * Action ran by user to specify who their password colleagues are.  These are the
     196         * individuals who will be consulted if and when the user needs to regain access
     197         * to their account. 
     198         * @param colleagueOne
     199         * @param colleagueTwo
     200         */
     201        public static void AuthSetPWColleagues(String colleagueOne, String colleagueTwo) {
     202                Password.setPWColleagues(colleagueOne, colleagueTwo);
     203        }
     204       
     205        /**
     206         * Action ran by user to oblige with a request from colleague who has nominated the
     207         * user as a pw colleague.  Will email (not Expeditee mail) the colleague the password
     208         * share that the user has stored on their secrets frame.
     209         * @param colleagueName
     210         */
     211        public static void AuthEmailPasswordShare(String colleagueName) {
     212                Password.emailPasswordShare(colleagueName);
     213        }
     214       
     215        /**
     216         * Action ran by user to regain access to their account by providing:
     217         *      their username
     218         *      two password shares obtained from pw colleagues
     219         *      their desired new password
     220         */
     221        public static void AuthRegainAccountAccess() {
     222                Collection<Text> textItems = DisplayController.getCurrentFrame().getTextItems();
     223                Optional<Map<AuthenticationTag, String>> userdata = AuthenticationTag.fetchUserData(textItems, false,
     224                                AuthenticationTag.Username, AuthenticationTag.NewPassword, AuthenticationTag.NewPasswordAgain,
     225                                AuthenticationTag.PasswordSliceOne, AuthenticationTag.PasswordSliceTwo);
     226                if (userdata.isPresent()) {
     227                        // Confirm new requested passwords match
     228                        Map<AuthenticationTag, String> userData = userdata.get();
     229                        if (!userData.get(AuthenticationTag.NewPassword).equals(userData.get(AuthenticationTag.NewPasswordAgain))) {
     230                                return;
     231                        }
     232                       
     233                        Password.regainAccountAccess(userData);
     234                }
     235        }
     236               
     237        /**
     238         * Actions used to generate and deliver an intergalactic number to a users public email
     239         * address after they have began the password recovery process.
     240         */
     241        public static void AuthDistributeIntergalacticNumber() {
     242                Collection<Text> textItems = DisplayController.getCurrentFrame().getTextItems();
     243                Optional<Map<AuthenticationTag, String>> userdata =
     244                                AuthenticationTag.fetchUserData(textItems, false, AuthenticationTag.Username);
     245                if (userdata.isPresent()) {
     246                        Map<AuthenticationTag, String> userData = userdata.get();
     247                        String username = userData.get(AuthenticationTag.Username);
     248                        String email = getEmailFromUsername(username);
     249                        userData.put(AuthenticationTag.Email, email);
     250                        Password.generateAndDeliverIntergalacticNumber(userData);
     251                        MessageBay.displayMessage("A identity number has been sent to the email "
     252                                        + "associated with your account.  Enter it below to proceed.");
     253                }
     254        }
     255       
     256        /**
     257         * Action used by user to submit their intergalactic number along with their username
     258         * in order to confirm that they own the public email address registered to their account.
     259         * This is part of the process of recoverying access to an account.
     260         */
     261        public static void AuthSubmitIntergalacticNumber() {
     262                Collection<Text> textItems = DisplayController.getCurrentFrame().getTextItems();
     263                Optional<Map<AuthenticationTag, String>> userdata =
     264                                AuthenticationTag.fetchUserData(textItems, false, AuthenticationTag.Username,
     265                                                AuthenticationTag.IntergalacticNumber);
     266                if (userdata.isPresent()) {
     267                        Password.confirmIntergalacticNumberAndAlertColleagues(userdata.get());
     268                }
     269        }
     270        //      End Regain Account Access Actions
     271       
     272        //      Start Create Account Actions
    168273        /**
    169274         * Action used to created a new user account.
     
    235340                }
    236341        }
    237        
     342        //      End Create Account Actions
     343       
     344        //      Start Account Login Actions
    238345        /**
    239346         * Action used to start authentication as a specified user. 
     
    258365        }
    259366       
     367        /**
     368         * Action used by the user to log out of their account.
     369         */
    260370        public static void AuthLogout() {
    261371                MessageBay.displayMessage(Authenticate.logout().toString());
    262372        }
    263        
     373        //      End Account Login Actions
     374       
     375        //      Start Change Access Actions
    264376        /**
    265377         * Action used to change the currently authenticated users password.
     
    295407                }
    296408        }
    297        
    298         public static void AuthGotoAccountManagement() {
    299                 if (AuthenticatorBrowser.Authenticated) {
    300                         DisplayController.setCurrentFrame(FrameIO.LoadFrame("multiuser1"), false);
    301                 } else {
    302                         DisplayController.setCurrentFrame(FrameIO.LoadFrame("authentication1"), false);
    303                 }
    304         }
    305        
    306         public static void AuthDistributeIntergalacticNumber() {
    307                 Collection<Text> textItems = DisplayController.getCurrentFrame().getTextItems();
    308                 Optional<Map<AuthenticationTag, String>> userdata =
    309                                 AuthenticationTag.fetchUserData(textItems, false, AuthenticationTag.Username);
    310                 if (userdata.isPresent()) {
    311                         Map<AuthenticationTag, String> userData = userdata.get();
    312                         String username = userData.get(AuthenticationTag.Username);
    313                         String email = getEmailFromUsername(username);
    314                         userData.put(AuthenticationTag.Email, email);
    315                         Password.generateAndDeliverIntergalacticNumber(userData);
    316                         MessageBay.displayMessage("A identity number has been sent to the email "
    317                                         + "associated with your account.  Enter it below to proceed.");
    318                 }
    319         }
    320        
    321         public static void AuthSubmitIntergalacticNumber() {
    322                 Collection<Text> textItems = DisplayController.getCurrentFrame().getTextItems();
    323                 Optional<Map<AuthenticationTag, String>> userdata =
    324                                 AuthenticationTag.fetchUserData(textItems, false, AuthenticationTag.Username,
    325                                                 AuthenticationTag.IntergalacticNumber);
    326                 if (userdata.isPresent()) {
    327                         Map<AuthenticationTag, String> tags = userdata.get();
    328                         String username = tags.get(AuthenticationTag.Username);
    329                         String intergalacticNumber = tags.get(AuthenticationTag.IntergalacticNumber);
    330                         boolean match = false;
    331                         try {
    332                                 match = AuthenticatorBrowser.getInstance().confirmIntergalaticNumber(username, intergalacticNumber);
    333                         } catch (NoSuchAlgorithmException | KeyStoreException | CertificateException | ClassNotFoundException
    334                                         | IOException | SQLException e) {
    335                                 e.printStackTrace();
    336                                 return;
    337                         }
    338                         if (!match) {
    339                                 MessageBay.errorMessage("The provided identity number does not match the one stored on file.");
    340                                 return;
    341                         }
    342                         String[] colleagues = getPasswordColleaguesFromUsername(username);
    343                         Password.confirmIntergalacticNumberAndAlertColleagues(userdata.get(), colleagues);
    344                 }
    345         }
    346        
     409        // End Change Access Actions
     410       
     411        // Start Private Helper Functions. 
     412        /**
     413         * Gets the public email address associated with the specified username.
     414         * @param username
     415         * @return
     416         */
    347417        private static String getEmailFromUsername(String username) {
    348418                Path credentialsDirPath = Paths.get(FrameIO.PROFILE_PATH).resolve(username).resolve(username + "-credentials");
     
    374444                }
    375445        }
    376        
    377         private static String[] getPasswordColleaguesFromUsername(String username) {
    378                 Path credentialsDirPath = Paths.get(FrameIO.PROFILE_PATH).resolve(username).resolve(username + "-credentials");
    379                 Path credentialsFilePath = credentialsDirPath.resolve("pwcolleagues.inf");
    380                 String fileName = null;
    381                 if (credentialsFilePath.toFile().exists()) {
    382                         try (Scanner in = new Scanner(credentialsFilePath)) {
    383                                 fileName = in.nextLine();
    384                         } catch (IOException e) {
    385                                 MessageBay.errorMessage("Unable to password colleague frame for specified user, are they registered on this computer?");
    386                                 return null;
    387                         }
    388                 } else {
    389                         MessageBay.errorMessage("Unable to password colleague frame for specified user, are they registered on this computer?");
    390                         return null;
    391                 }
    392                
    393                 int number = Integer.parseInt(fileName.replace(".exp", ""));
    394                 Frame pwColleagueFrame = FrameIO.LoadFrame(username + number, FrameIO.PROFILE_PATH);
    395                 Collection<Text> textItems = pwColleagueFrame.getTextItems();
    396                 textItems.removeIf(text -> !text.getText().startsWith("Colleague"));
    397                
    398                 String[] ret = new String[4];
    399                 Iterator<Text> it = textItems.iterator();
    400                 while(it.hasNext()) {
    401                         String content = it.next().getText().toLowerCase().trim();
    402                         if (content.contains("colleague_one:")) {
    403                                 ret[0] = content.replace("colleague_one:", "").trim();
    404                         } else if (content.contains("colleague_two:")) {
    405                                 ret[1] = content.replace("colleague_two:", "").trim();
    406                         } else if (content.contains("colleague_one_email:")) {
    407                                 ret[2] = content.replace("colleague_one_email:", "").trim();
    408                         } else if (content.contains("colleague_two_email:")) {
    409                                 ret[3] = content.replace("colleague_two_email:", "").trim();
    410                         }
    411                 }
    412                 return ret;
    413         }
    414        
     446        //      End Private Helper Functions.
     447       
     448        //      Start Future Functionality
    415449        public static void AuthShareFrameset() throws IOException {
    416450                Collection<Text> textItems = DisplayController.getCurrentFrame().getTextItems();
     
    431465                }
    432466        }
    433 
    434         /**
    435          * Navigation action for progressing the process of recruiting colleagues to assist in password recovery.
    436          * Hides certain content that AuthSubmitPWCollegues goes onto show if it does not fail.
    437          */
    438         public static void AuthGotoColleagueSubmissionFrame() {
    439                 Frame destination = FrameIO.LoadFrame("authentication7");
    440                 DisplayController.setCurrentFrame(destination, true);
    441                 Collection<Item> toHide = getByData(destination, "ShowOnProgress");
    442                 for (Item i: toHide) {
    443                         i.setVisible(false);
    444                 }
     467       
     468        /*
     469         * Function to share a specified frameset.
     470         * 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.
     471         */
     472        private static void shareFrameset(Frame toShare) throws IOException {   
     473                File destinationDir = new File(FrameIO.SHARED_FRAMESETS_PATH + File.separator + toShare.getFramesetName());
     474                File sourceDir = new File(toShare.getFramesetPath());
     475               
     476                if (destinationDir.exists()) {
     477                        MessageBay.errorMessage("A frameset by this name already exists.");
     478                        return;
     479                }
     480               
     481                destinationDir.mkdir();
     482                List<Path> files = Files.walk(sourceDir.toPath()).collect(Collectors.toList());
     483                Files.move(files.get(0), destinationDir.toPath(), StandardCopyOption.ATOMIC_MOVE);
     484               
     485                MessageBay.displayMessage("The frameset " + toShare.getFramesetName() + " has been moved to " + destinationDir + ".  Google Drive functionality can now be used to share it with colleagues.");
    445486        }
    446487       
     
    493534        }
    494535       
    495 //      public static void AuthSetupPasswordRecovery() throws KeyStoreException, FileNotFoundException, NoSuchAlgorithmException, CertificateException, ClassNotFoundException, IOException, SQLException, UnrecoverableEntryException {
    496 //              if (!UserSettings.Authenticated.get()) {
    497 //                      MessageBay.errorMessage("You must be logged in to perform this action.");
    498 //              } else if (!Authenticator.getInstance().hasRegisteredEmail(UserSettings.UserName.get())) {
    499 //                      Frame registerEmailFrame = FrameIO.LoadFrame("authentication4");
    500 //                      DisplayController.setCurrentFrame(registerEmailFrame, true);
    501 //              } else if (!Authenticator.getInstance().hasRequestedColleagues(UserSettings.UserName.get()) && Authenticator.getInstance().getColleagues(UserSettings.UserName.get()) == null) {
    502 //                      Frame submitColleaguesFrame = FrameIO.LoadFrame("authentication5");
    503 //                      DisplayController.setCurrentFrame(submitColleaguesFrame, true);
    504 //              } else if (Authenticator.getInstance().hasRequestedColleagues(UserSettings.UserName.get()) && Authenticator.getInstance().getColleagues(UserSettings.UserName.get()) == null) {
    505 //                      MessageBay.displayMessage("You have already nominated two colleagues to assist you in the process of password recovery and are awaiting their response."
    506 //                                      + "  You will be alerted on Expeditee startup when they have both responded.");
    507 //              } else if (Authenticator.getInstance().getColleagues(UserSettings.UserName.get()) != null) {
    508 //                      MessageBay.displayMessage("You have completed the Password Recovery Setup process, there is nothing more to do here.");
    509 //              }
    510 //      }
    511        
    512         public static void AuthConfirmPasswordColleagueRelationship(String colleagueName) {
    513                
    514         }
    515        
    516         public static void AuthDenyPasswordColleagueRelationship(String colleagueName) throws InvalidKeySpecException, NoSuchAlgorithmException,
    517                 KeyStoreException, FileNotFoundException, CertificateException, ClassNotFoundException, IOException, SQLException {
    518                 denyPasswordColleagueRelationship(colleagueName);
    519         }
    520        
    521         public static void AuthClearPWColleaguesNominated() {
    522                
    523         }
    524        
    525536        /*
    526          * Function to share a specified frameset.
    527          * 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.
    528          */
    529         private static void shareFrameset(Frame toShare) throws IOException {   
    530                 File destinationDir = new File(FrameIO.SHARED_FRAMESETS_PATH + File.separator + toShare.getFramesetName());
    531                 File sourceDir = new File(toShare.getFramesetPath());
    532                
    533                 if (destinationDir.exists()) {
    534                         MessageBay.errorMessage("A frameset by this name already exists.");
    535                         return;
    536                 }
    537                
    538                 destinationDir.mkdir();
    539                 List<Path> files = Files.walk(sourceDir.toPath()).collect(Collectors.toList());
    540                 Files.move(files.get(0), destinationDir.toPath(), StandardCopyOption.ATOMIC_MOVE);
    541                
    542                 MessageBay.displayMessage("The frameset " + toShare.getFramesetName() + " has been moved to " + destinationDir + ".  Google Drive functionality can now be used to share it with colleagues.");
    543         }
    544        
    545         private static void denyPasswordColleagueRelationship(String colleagueName) throws InvalidKeySpecException, NoSuchAlgorithmException, KeyStoreException, FileNotFoundException, CertificateException, ClassNotFoundException, IOException, SQLException {
    546                 String time = org.expeditee.stats.Formatter.getDateTime();
    547                 String sender = UserSettings.UserName.get();
    548                 String message = "You have received a reply from " + sender + " reguarding your request for assistance.";
    549                 String message2 = "Unfortunately " + sender + " has indicated that they are unable to help you with your potential password recovery.";
    550                 Map<String, String> options = new HashMap<String, String>();
    551                 options.put("Clear Preview Colleague Nominations", "AuthClearPWColleaguesNominated");
    552                 MailEntry mail = new MailEntry(time, sender, colleagueName, message, message2, options);
    553                 Mail.sendMail(mail, colleagueName);
    554         }
    555        
     537         * Function to submit a request to specified contacts to be the current users pw colleagues.
     538         */
    556539        private static boolean submitPWColleagues(Map<AuthenticationTag, String> userData) throws InvalidKeySpecException, NoSuchAlgorithmException, KeyStoreException, FileNotFoundException, CertificateException, ClassNotFoundException, IOException, SQLException {
    557540                String colleagueOne = userData.get(AuthenticationTag.ColleagueOne);
     
    581564                }
    582565        }
    583        
    584         public static void TickBox(final Text item) {
    585                 if (item.getBackgroundColor() != Colour.RED) {
    586                         item.setBackgroundColor(Colour.RED);
    587                 } else {
    588                         item.setBackgroundColor(Colour.GREEN);
    589                 }
    590         }
    591        
    592         /*
    593          * Gets all items on a specified frame that contain the specified data.
    594          */
    595         public static Collection<Item> getByData(final Frame frame, final String data) {
    596                 final Collection<Item> allItems = frame.getAllItems();
    597                 allItems.removeIf(i -> i.getData() == null || !i.hasData(data));
    598                 return allItems;
    599         }
    600        
    601         public static Collection<Item> getByContent(final Frame frame, final String content) {
    602                 final Collection<Item> allItems = frame.getAllItems();
    603                 allItems.removeIf(i -> i.getText().compareTo(content) != 0);
    604                 return allItems;
    605         }
     566        // End Future Functionality
    606567}
Note: See TracChangeset for help on using the changeset viewer.