├── .gitignore ├── .idea ├── .gitignore ├── codeStyles │ ├── Project.xml │ └── codeStyleConfig.xml ├── libraries │ └── lib.xml ├── misc.xml ├── modules.xml ├── uiDesigner.xml └── vcs.xml ├── .settings └── org.eclipse.jdt.core.prefs ├── LICENSE ├── README.md ├── password-manager-java.iml ├── screenshots ├── addPass.png ├── addPassFail.png ├── addPassMain.png ├── login.png ├── main.png └── registerFail.png └── src ├── controller ├── AddPassController.java ├── LoginController.java ├── MainController.java ├── RegisterController.java ├── SmallWindowController.java └── UserHBoxController.java ├── data ├── jerryc.txt ├── jessechen.txt ├── johndoe.txt └── users.txt ├── launcher ├── PasswordManager.java └── PasswordManagerLauncher.java ├── model ├── Colors.java └── PasswordManagerModel.java ├── user ├── Account.java ├── InternetAccount.java └── User.java └── view ├── AddPassView.fxml ├── LoginView.fxml ├── MainView.fxml ├── RegisterView.fxml └── UserHBoxView.fxml /.gitignore: -------------------------------------------------------------------------------- 1 | /bin/ 2 | -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | -------------------------------------------------------------------------------- /.idea/codeStyles/Project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 13 | 14 | -------------------------------------------------------------------------------- /.idea/codeStyles/codeStyleConfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | -------------------------------------------------------------------------------- /.idea/libraries/lib.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/uiDesigner.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.settings/org.eclipse.jdt.core.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled 3 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 4 | org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve 5 | org.eclipse.jdt.core.compiler.compliance=1.8 6 | org.eclipse.jdt.core.compiler.debug.lineNumber=generate 7 | org.eclipse.jdt.core.compiler.debug.localVariable=generate 8 | org.eclipse.jdt.core.compiler.debug.sourceFile=generate 9 | org.eclipse.jdt.core.compiler.problem.assertIdentifier=error 10 | org.eclipse.jdt.core.compiler.problem.enumIdentifier=error 11 | org.eclipse.jdt.core.compiler.source=1.8 12 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 jessechen09 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # password-manager-java 2 | 3 | DISCLAIMER: This is not a true password manager and has ZERO security features. Do NOT use it to store any passwords. 4 | 5 | ## Intro 6 | 7 | This is my first personal project, and I think it's a good starting point for those who are trying to find projects to work on. By working on this project, you also practice reading and understanding someone else's code, which may not necessarily be well written! Hopefully, mine is okay. 8 | 9 | ## Prerequisites 10 | 11 | Java, OOP, MVC architecture, and JavaFX, to list a few. 12 | 13 | ## Task ideas 14 | 15 | Some tasks you can work on include, but are not limited to: 16 | 17 | | Estimated difficulty | Task | 18 | | :------------------- | :--- | 19 | |Easy |Modify the UI.| 20 | |Easy |Investigate how things are handled when we have a multiple InternetAccounts with the same domain and optimize.| 21 | |Easy/Medium |Look around and fix any bugs.| 22 | |Medium |As of now, when we press the close button (the x button the top corners), the parent pane remains disabled. Fix this by adding a "cancel" button| 23 | |Medium |Add a feature that allows users to delete domains from the password manager.| 24 | |Medium |Add a feature that allows users to delete their account from the password manager.| 25 | |Medium |Add a feature that allows users to change their login password.| 26 | |Medium |Add a feature that allows users to change their domains/usernames/passwords for each InternetAccount.| 27 | |Medium |Add a sort feature for the domains, i.e. A-Z and Z-A.| 28 | |Medium |Add a feature that launches the default browser when user clicks on the password domain and open the website.| 29 | |Hard |Add animations to UI.| 30 | |Hard |Instead of using .txt files, use a data base to store all the info.| 31 | |Super Hard |Implement security features.| 32 | 33 | ## How this project works 34 | 35 | This project uses the MVC software design pattern. The FXML files are the views, which are controlled by separate controller classes. There is one main model that stores all the user and account information. The "database" is simulated with .txt files, which the model reads when a user logs in or writes to when new users or internet accounts are added. 36 | 37 | ## Windows 38 | 39 | ### Login window 40 | When you launch the application, you will first see the login window. You can type your username and password to login, or register a new user. 41 |

42 | 43 |

44 | 45 | ### Register window 46 | When you register a new user with a username that already exists, you will get an error. Be sure to choose a unique username! You will also have to type the password twice indentically. 47 |

48 | 49 |

50 | 51 | ### Main window 52 | After logging in, you will reach the main window where all the passwords are stored. You can click on the buttons to copy the username and passwords. Lots of work can be done here, so be creative! 53 |

54 | 55 |

56 | 57 | ### Add new password window 58 | When you want to add a new password, the main window will be disabled until you finish adding a new password. 59 |

60 | 61 |

62 | 63 | Make sure your passwords match! 64 |

65 | 66 |

67 | 68 | Everything is fine now. 69 |

70 | 71 |

72 | 73 | ## The End 74 | -------------------------------------------------------------------------------- /password-manager-java.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /screenshots/addPass.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jessechen09/password-manager-java/508c5e95d232bd72ee8d7765fe297241dac3255a/screenshots/addPass.png -------------------------------------------------------------------------------- /screenshots/addPassFail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jessechen09/password-manager-java/508c5e95d232bd72ee8d7765fe297241dac3255a/screenshots/addPassFail.png -------------------------------------------------------------------------------- /screenshots/addPassMain.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jessechen09/password-manager-java/508c5e95d232bd72ee8d7765fe297241dac3255a/screenshots/addPassMain.png -------------------------------------------------------------------------------- /screenshots/login.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jessechen09/password-manager-java/508c5e95d232bd72ee8d7765fe297241dac3255a/screenshots/login.png -------------------------------------------------------------------------------- /screenshots/main.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jessechen09/password-manager-java/508c5e95d232bd72ee8d7765fe297241dac3255a/screenshots/main.png -------------------------------------------------------------------------------- /screenshots/registerFail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jessechen09/password-manager-java/508c5e95d232bd72ee8d7765fe297241dac3255a/screenshots/registerFail.png -------------------------------------------------------------------------------- /src/controller/AddPassController.java: -------------------------------------------------------------------------------- 1 | package controller; 2 | /** 3 | * Controls the view that allows adding a new password. 4 | * 5 | * @author Jesse Chen 6 | */ 7 | 8 | import javafx.fxml.FXML; 9 | import javafx.scene.control.PasswordField; 10 | import javafx.scene.control.TextField; 11 | import user.InternetAccount; 12 | 13 | public class AddPassController extends SmallWindowController { 14 | 15 | @FXML 16 | private TextField domainTextField; 17 | 18 | @FXML 19 | private PasswordField passwordField2; 20 | 21 | private MainController parentController; 22 | 23 | /** 24 | * Replicates a constructor because FXML only allows default constructors. 25 | * 26 | * @param parentController 27 | */ 28 | public void initialize(MainController parentController) { 29 | this.parentController = parentController; 30 | } 31 | 32 | 33 | /** 34 | * Adds new InternetAccount to current user and displays new password HBox in main window when the finish button 35 | * is pressed. 36 | */ 37 | @Override 38 | public void mainButtonOnAction() { 39 | String domain = domainTextField.getText(); 40 | String username = usernameTextField.getText(); 41 | String password1 = passwordField1.getText(); 42 | String password2 = passwordField2.getText(); 43 | 44 | if (!password1.equals(password2)) { 45 | invalidLabel.setText("Passwords do not match"); 46 | invalidLabel.setVisible(true); 47 | } else { 48 | InternetAccount newInternetAccount = new InternetAccount(domain, username, password1); 49 | parentController.user.addInternetAccount(newInternetAccount); 50 | parentController.borderPane.setDisable(false); 51 | parentController.addPasswordHBox(newInternetAccount); 52 | parentController.addPassStage.close(); 53 | } 54 | } 55 | } 56 | 57 | -------------------------------------------------------------------------------- /src/controller/LoginController.java: -------------------------------------------------------------------------------- 1 | package controller; 2 | 3 | import javafx.fxml.FXML; 4 | import javafx.fxml.FXMLLoader; 5 | import javafx.scene.Parent; 6 | import javafx.scene.Scene; 7 | import javafx.scene.control.Button; 8 | import javafx.scene.layout.BorderPane; 9 | import javafx.stage.Stage; 10 | import model.Colors; 11 | import model.PasswordManagerModel; 12 | 13 | import java.io.IOException; 14 | 15 | /** 16 | * Controls the login window. 17 | * 18 | * @author Jesse Chen 19 | */ 20 | 21 | public class LoginController extends SmallWindowController { 22 | 23 | 24 | @FXML 25 | private Button registerButton; 26 | 27 | @FXML 28 | BorderPane borderPane; 29 | 30 | PasswordManagerModel model; 31 | Stage regStage; 32 | 33 | /** 34 | * Default constructor. 35 | */ 36 | public LoginController() { 37 | model = new PasswordManagerModel(); 38 | System.out.println("New model created"); 39 | } 40 | 41 | //=============== Login button ===================================================================================== 42 | 43 | 44 | /** 45 | * Opens the main password manager window and adds user info to the model. 46 | */ 47 | @Override 48 | public void mainButtonOnAction() { 49 | String username = usernameTextField.getText(); 50 | String password = passwordField1.getText(); 51 | if (model.hasUser(username) && model.isCorrectPassword(username, password)) { 52 | model.setUser(model.getUser(username)); 53 | System.out.println("Logged in: " + model.getCurrentUserName()); 54 | openMainWindow(); 55 | } else { 56 | invalidLabel.setVisible(true); 57 | invalidLabel.setText("Invalid login. Please try again."); 58 | } 59 | } 60 | 61 | /** 62 | * Opens the main password manager window. 63 | */ 64 | private void openMainWindow() { 65 | try { 66 | String viewPath = PasswordManagerModel.VIEW_DIRECTORY + "MainView.fxml"; 67 | FXMLLoader loader = new FXMLLoader(getClass().getResource(viewPath)); 68 | Stage mainStage = new Stage(); 69 | Parent parent = loader.load(); 70 | MainController mainController = loader.getController(); 71 | mainController.initialize(model); 72 | mainStage.setTitle("Password Manager"); 73 | mainStage.setScene(new Scene(parent)); 74 | mainStage.setResizable(false); 75 | mainStage.show(); 76 | mainButton.getScene().getWindow().hide(); 77 | } catch (IOException e) { 78 | e.printStackTrace(); 79 | } 80 | } 81 | 82 | //================ Register button ================================================================================= 83 | 84 | /** 85 | * Opens register window. 86 | */ 87 | public void registerButtonAction() { 88 | System.out.println("Registering new user"); 89 | try { 90 | String viewPath = PasswordManagerModel.VIEW_DIRECTORY + "RegisterView.fxml"; 91 | FXMLLoader loader = new FXMLLoader(getClass().getResource(viewPath)); 92 | regStage = new Stage(); 93 | Parent parent = loader.load(); 94 | RegisterController regController = loader.getController(); 95 | regController.initialize(this); 96 | regStage.setTitle("Register"); 97 | regStage.setScene(new Scene(parent)); 98 | regStage.setResizable(false); 99 | regStage.show(); 100 | borderPane.setDisable(true); 101 | // registerButton.getScene().getWindow().hide(); 102 | } catch (IOException e) { 103 | e.printStackTrace(); 104 | } 105 | } 106 | 107 | /** 108 | * Allows color changes when mouse hovers over button. 109 | */ 110 | public void registerButtonOnEnter() { registerButton.setStyle(Colors.setBackgroundColor(Colors.LIGHT_GREY)); } 111 | 112 | public void registerButtonOnExit() { registerButton.setStyle(Colors.setBackgroundColor(Colors.WHITE)); } 113 | 114 | // https://stackoverflow.com/questions/17014012/how-to-unmask-a-javafx-passwordfield-or-properly-mask-a-textfield 115 | } 116 | -------------------------------------------------------------------------------- /src/controller/MainController.java: -------------------------------------------------------------------------------- 1 | package controller; 2 | 3 | import javafx.fxml.FXML; 4 | import javafx.fxml.FXMLLoader; 5 | import javafx.scene.Parent; 6 | import javafx.scene.Scene; 7 | import javafx.scene.control.Button; 8 | import javafx.scene.control.Label; 9 | import javafx.scene.layout.BorderPane; 10 | import javafx.scene.layout.HBox; 11 | import javafx.scene.layout.VBox; 12 | import javafx.stage.Stage; 13 | import launcher.PasswordManagerLauncher; 14 | import model.PasswordManagerModel; 15 | import user.InternetAccount; 16 | import user.User; 17 | import java.io.IOException; 18 | 19 | /** 20 | * Controls the main password manager window. 21 | * 22 | * @author Jesse Chen 23 | */ 24 | 25 | public class MainController { 26 | Stage addPassStage; 27 | User user; 28 | 29 | @FXML 30 | Button addNewPasswordButton; 31 | 32 | @FXML 33 | VBox passwordsVBox; 34 | 35 | @FXML 36 | private Button logoutButton; 37 | 38 | @FXML 39 | BorderPane borderPane; 40 | 41 | 42 | /** 43 | * FXMl file can only call a default constructor, but we can't do much inside it, so let's just 44 | * remove it. For example, we want to transfer the PasswordManagerModel object from the LoginController class to 45 | * the MainController class. Instead, we use a method that is called by the LoginController class that will do 46 | * this job, along many others. 47 | * 48 | * @param model 49 | */ 50 | public void initialize(PasswordManagerModel model) { 51 | System.out.println("Model transferred from login window to main window"); 52 | System.out.println("This account has these domains stored:"); 53 | 54 | this.user = model.getCurrentUser(); 55 | for (InternetAccount internetAccount : user.getInternetAccounts().values()) { 56 | addPasswordHBox(internetAccount); 57 | } 58 | } 59 | 60 | /** 61 | * Opens the window for adding new passwords. 62 | */ 63 | public void addNewPasswordButtonAction() { 64 | System.out.println("Adding new password..."); 65 | try { 66 | String viewPath = PasswordManagerModel.VIEW_DIRECTORY + "AddPassView.fxml"; 67 | FXMLLoader loader = new FXMLLoader(getClass().getResource(viewPath)); 68 | addPassStage = new Stage(); 69 | Parent parent = loader.load(); 70 | AddPassController addPassController = loader.getController(); 71 | addPassController.initialize(this); 72 | addPassStage.setTitle("Add Password"); 73 | addPassStage.setScene(new Scene(parent)); 74 | addPassStage.setResizable(false); 75 | addPassStage.show(); 76 | borderPane.setDisable(true); 77 | } catch (IOException e) { 78 | e.printStackTrace(); 79 | } 80 | } 81 | 82 | /** 83 | * Logs current user out and returns to login window. 84 | * 85 | * @throws Exception 86 | */ 87 | public void logoutButtonAction() throws Exception { 88 | logoutButton.getScene().getWindow().hide(); 89 | PasswordManagerLauncher pml = new PasswordManagerLauncher(); 90 | pml.start(new Stage()); 91 | } 92 | 93 | /** 94 | * Adds an HBox that displays the domain, username button, and password button. 95 | * 96 | * @param internetAccount 97 | */ 98 | void addPasswordHBox(InternetAccount internetAccount) { 99 | try { 100 | String hboxViewDir = PasswordManagerModel.VIEW_DIRECTORY + "UserHBoxView.fxml"; 101 | FXMLLoader loader = new FXMLLoader(getClass().getResource(hboxViewDir)); 102 | HBox hbox = loader.load(); 103 | UserHBoxController userHBoxController = loader.getController(); 104 | userHBoxController.initialize(internetAccount); 105 | passwordsVBox.getChildren().add(hbox); 106 | ((Label) hbox.getChildren().get(0)).setText(internetAccount.getDomain()); 107 | HBox subHBox = (HBox) hbox.getChildren().get(1); 108 | ((Button) (subHBox.getChildren().get(0))).setText(internetAccount.getUserName()); 109 | } catch (IOException e) { 110 | e.printStackTrace(); 111 | } 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /src/controller/RegisterController.java: -------------------------------------------------------------------------------- 1 | package controller; 2 | 3 | import javafx.fxml.FXML; 4 | import javafx.scene.control.PasswordField; 5 | import model.PasswordManagerModel; 6 | 7 | /** 8 | * Controls the register window. 9 | * 10 | * @author Jesse Chen 11 | */ 12 | 13 | public class RegisterController extends SmallWindowController { 14 | 15 | @FXML 16 | private PasswordField passwordField2; 17 | 18 | private LoginController loginController; 19 | 20 | public void initialize(LoginController loginController) { 21 | this.loginController = loginController; 22 | } 23 | 24 | 25 | /** 26 | * Adds new user to the current model when the finish button is pressed. 27 | */ 28 | @Override 29 | public void mainButtonOnAction() { 30 | String username = usernameTextField.getText(); 31 | String password1 = passwordField1.getText(); 32 | String password2 = passwordField2.getText(); 33 | 34 | if (loginController.model.hasUser(username)) { 35 | invalidLabel.setText("User exists"); 36 | invalidLabel.setVisible(true); 37 | } else if (!password1.equals(password2)) { 38 | invalidLabel.setText("Passwords do not match"); 39 | invalidLabel.setVisible(true); 40 | } else if (password1.length() < PasswordManagerModel.MIN_PASSWORD_LENGTH) { 41 | invalidLabel.setText("Min password length: " + PasswordManagerModel.MIN_PASSWORD_LENGTH); 42 | invalidLabel.setVisible(true); 43 | } else { 44 | loginController.model.addUser(username, password1); 45 | loginController.borderPane.setDisable(false); 46 | loginController.regStage.close(); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/controller/SmallWindowController.java: -------------------------------------------------------------------------------- 1 | package controller; 2 | 3 | import javafx.fxml.FXML; 4 | import javafx.scene.control.Button; 5 | import javafx.scene.control.Label; 6 | import javafx.scene.control.PasswordField; 7 | import javafx.scene.control.TextField; 8 | import javafx.scene.input.KeyCode; 9 | import javafx.scene.input.KeyEvent; 10 | import model.Colors; 11 | 12 | /** 13 | * Abstract class for the small windows, which is basically all windows except the main window. 14 | * 15 | * @author Jesse Chen 16 | */ 17 | 18 | public abstract class SmallWindowController { 19 | 20 | @FXML 21 | protected Button mainButton; 22 | 23 | @FXML 24 | protected TextField usernameTextField; 25 | 26 | @FXML 27 | protected PasswordField passwordField1; 28 | 29 | @FXML 30 | protected Label invalidLabel; 31 | 32 | public abstract void mainButtonOnAction(); 33 | 34 | /** 35 | * These two methods modify the button's color as we move our mouse over it. This can also be converted to 36 | * lambdas if desired. 37 | */ 38 | public void mainButtonOnEnter() { mainButton.setStyle(Colors.setBackgroundColor(Colors.LIGHT_RED)); } 39 | 40 | public void mainButtonOnExit() { mainButton.setStyle(Colors.setBackgroundColor(Colors.MAIN_RED)); } 41 | 42 | /** 43 | * Clicks on main button when user presses return. 44 | * 45 | * @param event 46 | */ 47 | public void fieldOnEnter(KeyEvent event) { 48 | invalidLabel.setVisible(false); 49 | if (event.getCode() == KeyCode.ENTER) mainButtonOnAction(); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/controller/UserHBoxController.java: -------------------------------------------------------------------------------- 1 | package controller; 2 | 3 | import javafx.scene.layout.HBox; 4 | import user.InternetAccount; 5 | import java.awt.*; 6 | import java.awt.datatransfer.Clipboard; 7 | import java.awt.datatransfer.StringSelection; 8 | 9 | /** 10 | * Controls the user HBox. 11 | * 12 | * @author Jesse Chen 13 | */ 14 | 15 | public class UserHBoxController extends HBox { 16 | 17 | private InternetAccount internetAccount; 18 | 19 | public void initialize(InternetAccount internetAccount) { this.internetAccount = internetAccount; } 20 | 21 | /** 22 | * Copy the username to the clipboard. 23 | */ 24 | public void copyUsernameButtonOnAction() { copy(internetAccount.getUserName()); } 25 | 26 | /** 27 | * Copy the user password to the clipboard. 28 | */ 29 | public void copyPasswordButtonOnAction() { copy(internetAccount.getPassword()); } 30 | 31 | /** 32 | * Copy the string to the clipboard. 33 | * 34 | * @param string 35 | */ 36 | private void copy(String string) { 37 | Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); 38 | clipboard.setContents(new StringSelection(string), null); 39 | } 40 | 41 | 42 | /** 43 | * Make button color lighter when mouse hovers over button. 44 | */ 45 | public void buttonOnEnter() { 46 | // TODO: implement this method! 47 | } 48 | 49 | /** 50 | * Make button color normal when mouse leaves button. 51 | */ 52 | public void buttonOnExit() { 53 | // TODO: implement this method! 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /src/data/jerryc.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jessechen09/password-manager-java/508c5e95d232bd72ee8d7765fe297241dac3255a/src/data/jerryc.txt -------------------------------------------------------------------------------- /src/data/jessechen.txt: -------------------------------------------------------------------------------- 1 | www.google.com jc@google passgoogle 2 | www.yahoo.com jc@yahoo passyahoo 3 | www.bing.com jc@bing passbing 4 | www.godogle.com jc@google passgoogle 5 | www.yafahoo.com jc@yahoo passyahoo 6 | www.bifang.com jc@bing passbing 7 | www.goaafdogle.com jc@google passgoogle 8 | www.yahadfoo.com jc@yahoo passyahoo 9 | www.biadfng.com jc@bing passbing 10 | www.googfwefle.com jc@google passgoogle 11 | www.yahovzcxvo.com jc@yahoo passyahoo 12 | www.bineg.com jc@bing passbing 13 | www.goobytgle.com jc@google passgoogle 14 | www.yahfdoo.com jc@yahoo passyahoo 15 | www.bin3g.com jc@bing passbing 16 | www.goodfcr23gle.com jc@google passgoogle 17 | www.yahofwceo.com jc@yahoo passyahoo 18 | www.bingfd2.com jc@bing passbing 19 | www.googfd2le.com jc@google passgoogle 20 | www.yahfc2oo.com jc@yahoo passyahoo 21 | www.bin234fcg.com jc@bing passbing 22 | www.googfc2le.com jc@google passgoogle 23 | www.yahfc2oo.com jc@yahoo passyahoo 24 | www.binfc24g.com jc@bing passbing 25 | www.goog4he56b7hle.com jc@google passgoogle 26 | www.yahorgso.com jc@yahoo passyahoo 27 | www.bin356g.com jc@bing passbing -------------------------------------------------------------------------------- /src/data/johndoe.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jessechen09/password-manager-java/508c5e95d232bd72ee8d7765fe297241dac3255a/src/data/johndoe.txt -------------------------------------------------------------------------------- /src/data/users.txt: -------------------------------------------------------------------------------- 1 | jessechen password4jc 2 | johndoe password4jd 3 | jerryc password4jrc -------------------------------------------------------------------------------- /src/launcher/PasswordManager.java: -------------------------------------------------------------------------------- 1 | package launcher; 2 | 3 | import javafx.application.Application; 4 | 5 | /** 6 | * This class calls the PasswordManagerLauncher class. The main method is not in the launcher class because we did 7 | * not setup a module path. Please see: 8 | * click here. 9 | * 10 | * @author Jesse Chen 11 | */ 12 | 13 | public class PasswordManager { 14 | public static void main(String[] args) { 15 | Application.launch(PasswordManagerLauncher.class); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/launcher/PasswordManagerLauncher.java: -------------------------------------------------------------------------------- 1 | package launcher; 2 | 3 | import javafx.application.Application; 4 | import javafx.fxml.FXMLLoader; 5 | import javafx.scene.Parent; 6 | import javafx.scene.Scene; 7 | import javafx.stage.Stage; 8 | import controller.LoginController; 9 | import model.PasswordManagerModel; 10 | 11 | import java.io.File; 12 | 13 | /** 14 | * This class launches the login page and essentially starts the password manager app. 15 | * 16 | * @author Jesse Chen 17 | */ 18 | 19 | public class PasswordManagerLauncher extends Application { 20 | 21 | @Override 22 | public void start(Stage loginStage) throws Exception { 23 | String loginDirectory = PasswordManagerModel.VIEW_DIRECTORY + "LoginView.fxml"; 24 | FXMLLoader loader = new FXMLLoader((getClass().getResource(loginDirectory))); 25 | Parent parent = loader.load(); 26 | loginStage.setScene(new Scene(parent)); 27 | loginStage.setResizable(false); 28 | loginStage.show(); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/model/Colors.java: -------------------------------------------------------------------------------- 1 | package model; 2 | 3 | /** 4 | * This class stores some color information that can be used for the UI. 5 | */ 6 | 7 | public class Colors { 8 | public static final String MAIN_RED = "#c92d39"; 9 | public static final String LIGHT_RED = "#da6770"; 10 | public static final String MAIN_BLUE = "#001d4c"; 11 | public static final String WHITE = "#ffffff"; 12 | public static final String BLACK = "#000000"; 13 | public static final String LIGHT_GREY = "#eaeaea"; 14 | 15 | /** 16 | * Changes the background color of a Node. 17 | * @param color Color in hex. 18 | * @return 19 | */ 20 | public static String setBackgroundColor(String color) { return "-fx-background-color: " + color + ";"; } 21 | public static String setTextColor(String color) {return "";} 22 | } 23 | -------------------------------------------------------------------------------- /src/model/PasswordManagerModel.java: -------------------------------------------------------------------------------- 1 | package model; 2 | 3 | import user.Account; 4 | import user.User; 5 | 6 | import java.io.File; 7 | import java.io.FileNotFoundException; 8 | import java.io.FileWriter; 9 | import java.io.IOException; 10 | import java.util.*; 11 | 12 | /** 13 | * This class is the model and stores all the information by reading the .txt files. This class also accepts new users. 14 | * 15 | * @author Jesse Chen 16 | */ 17 | 18 | public class PasswordManagerModel { 19 | private Map userMap; 20 | private User currentUser; // the current user, i.e. whoever logged in 21 | private String usersDirectory; 22 | 23 | public static final int MIN_PASSWORD_LENGTH = 6; 24 | public static final String MAIN_DIRECTORY = ".." + File.separator; 25 | public static final String SRC_DIRECTORY = "src" + File.separator; 26 | public static final String VIEW_DIRECTORY = MAIN_DIRECTORY + "view" + File.separator; 27 | public static final String DATA_DIRECTORY = SRC_DIRECTORY + "data" + File.separator; 28 | 29 | public PasswordManagerModel() { 30 | userMap = new HashMap(); 31 | // The following does not work for some reason: 32 | // DATA_DIRECTORY + "users.txt" 33 | usersDirectory = DATA_DIRECTORY + "users.txt"; 34 | try { 35 | Scanner scanner = new Scanner(new File(usersDirectory)); 36 | String username; 37 | String password; 38 | while (scanner.hasNextLine()) { 39 | username = scanner.next(); 40 | password = scanner.next(); 41 | userMap.put(username, new User(new Account(username, password))); 42 | } 43 | } catch (FileNotFoundException e) { 44 | e.printStackTrace(); 45 | } 46 | } 47 | 48 | //=============== Methods ========================================================================================== 49 | 50 | /** 51 | * Sets the current user when you login. 52 | * 53 | * @param user 54 | */ 55 | public void setUser(User user) { 56 | this.currentUser = user; 57 | } 58 | 59 | /** 60 | * @return Returns the current user, i.e. whoever is logged in. 61 | */ 62 | public User getCurrentUser() { 63 | return currentUser; 64 | } 65 | 66 | /** 67 | * @return Returns the current user's username. 68 | */ 69 | public String getCurrentUserName() { return currentUser.getAccount().getUserName(); } 70 | 71 | /** 72 | * @param username 73 | * @return Returns the User that corresponds the input username. 74 | */ 75 | public User getUser(String username) { 76 | return userMap.get(username); 77 | } 78 | 79 | /** 80 | * @param username 81 | * @return Returns true if there is a User with the input username in the database, false otherwise. 82 | */ 83 | public boolean hasUser(String username) { 84 | return userMap.containsKey(username); 85 | } 86 | 87 | /** 88 | * @param username 89 | * @param enteredPassword 90 | * @return Returns true if the input password matches the database password of the input username, false otherwise. 91 | */ 92 | public boolean isCorrectPassword(String username, String enteredPassword) { 93 | if (!hasUser(username)) return false; 94 | return getUser(username).getAccount().getPassword().equals(enteredPassword); 95 | } 96 | 97 | /** 98 | * Adds new user to the map of users 99 | * 100 | * @param username 101 | * @param password 102 | */ 103 | public void addUser(String username, String password) { 104 | try { // add user to database, i.e. "users.txt" 105 | File usersFile = new File(usersDirectory); 106 | FileWriter writer = new FileWriter(usersFile, true); 107 | writer.write("\n" + username + " " + password); 108 | writer.close(); 109 | 110 | // create username.txt file 111 | File userFile = new File(DATA_DIRECTORY + username + ".txt"); 112 | userFile.createNewFile(); 113 | 114 | // add user to userMap 115 | userMap.put(username, new User(new Account(username, password))); 116 | } catch (IOException e) { 117 | e.printStackTrace(); 118 | } 119 | 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /src/user/Account.java: -------------------------------------------------------------------------------- 1 | package user; 2 | 3 | /** 4 | * This is an insecure implementation of the Account object and is up to the 5 | * instructors to choose the modifications that the students should make. 6 | * 7 | * @author Jesse Chen 8 | */ 9 | 10 | public class Account { 11 | 12 | private String username; 13 | private String password; 14 | 15 | public Account(String username, String password) { 16 | this.username = username; 17 | this.password = password; 18 | } 19 | 20 | /** 21 | * @return Returns the username of this Account. 22 | */ 23 | public String getUserName() { 24 | return this.username; 25 | } 26 | 27 | /** 28 | * @return Returns the password of this Account. 29 | */ 30 | public String getPassword() { 31 | return this.password; 32 | } 33 | 34 | /** 35 | * Changes the password for this Account. 36 | * @param password 37 | */ 38 | public void changePassword(String password) { 39 | this.password = password; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/user/InternetAccount.java: -------------------------------------------------------------------------------- 1 | package user; 2 | 3 | /** 4 | * The InternetAccount object holds all the info for the account login and 5 | * passwords that the password manager will save. 6 | * 7 | * @author Jesse Chen 8 | */ 9 | public class InternetAccount extends Account { 10 | 11 | private String domain; 12 | 13 | public InternetAccount(String domain, String username, String password) { 14 | super(username, password); 15 | this.domain = domain; 16 | } 17 | 18 | /** 19 | * @return Returns the domain for this InternetAccount. 20 | */ 21 | public String getDomain() { 22 | return domain; 23 | } 24 | 25 | /** 26 | * Changes this InternetAccount's domain. 27 | * 28 | * @param domain 29 | */ 30 | public void changeDomain(String domain) { this.domain = domain; } 31 | } 32 | -------------------------------------------------------------------------------- /src/user/User.java: -------------------------------------------------------------------------------- 1 | package user; 2 | 3 | import model.PasswordManagerModel; 4 | 5 | import java.io.File; 6 | import java.io.FileNotFoundException; 7 | import java.io.FileWriter; 8 | import java.io.IOException; 9 | import java.util.HashMap; 10 | import java.util.Scanner; 11 | 12 | /** 13 | * The User object holds all account info, including the account info for 14 | * logging into the password manager and all Internet account info. 15 | * 16 | * @author Jesse Chen 17 | */ 18 | 19 | public class User { 20 | private Account account; 21 | private HashMap internetAccounts; 22 | 23 | // take account as parameter because maybe we want to add more info to account in future 24 | public User(Account account) { 25 | this.account = account; 26 | this.internetAccounts = new HashMap(); 27 | 28 | // load in all of user's internet account info 29 | try { 30 | Scanner scanner = new Scanner(new File(PasswordManagerModel.DATA_DIRECTORY + account.getUserName() + 31 | ".txt")); 32 | String domain; 33 | String username; 34 | String password; 35 | while (scanner.hasNextLine()) { 36 | domain = scanner.next(); 37 | username = scanner.next(); 38 | password = scanner.next(); 39 | internetAccounts.put(domain, new InternetAccount(domain, username, password)); 40 | } 41 | } catch (FileNotFoundException e) { 42 | e.printStackTrace(); 43 | } 44 | } 45 | 46 | /** 47 | * @param domain 48 | * @return Returns the InternetAccount corresponding to the input domain. 49 | */ 50 | public InternetAccount getInternetAccount(String domain) { return internetAccounts.get(domain); } 51 | 52 | /** 53 | * @return Returns this User's Acccount. 54 | */ 55 | public Account getAccount() { return account; } 56 | 57 | /** 58 | * @return Returns a HashMap of InternetAccounts. 59 | */ 60 | public HashMap getInternetAccounts() { return internetAccounts; } 61 | 62 | /** 63 | * Adds an InternetAccount to the HashMap and writes the domain, username, and password in the corresponding .txt 64 | * file. 65 | * 66 | * @param internetAccount 67 | */ 68 | public void addInternetAccount(InternetAccount internetAccount) { 69 | try { 70 | String domain = internetAccount.getDomain(); 71 | String username = internetAccount.getUserName(); 72 | String password = internetAccount.getPassword(); 73 | File file = new File(PasswordManagerModel.DATA_DIRECTORY + account.getUserName() + ".txt"); 74 | FileWriter writer = new FileWriter(file, true); 75 | writer.write("\n" + domain + " " + username + " " + password); 76 | writer.close(); 77 | internetAccounts.put(domain, new InternetAccount(domain, username, password)); 78 | } catch (IOException e) { 79 | e.printStackTrace(); 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/view/AddPassView.fxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /src/view/RegisterView.fxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 |