├── .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 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/.idea/codeStyles/codeStyleConfig.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
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 |
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 |
--------------------------------------------------------------------------------
/src/view/LoginView.fxml:
--------------------------------------------------------------------------------
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 |
--------------------------------------------------------------------------------
/src/view/MainView.fxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |