#8 story/pfleger-module-login-pfleger #50

Merged
SZUT-Dominik merged 7 commits from story/pfleger-module-login-pfleger into main 2024-05-22 09:46:02 +00:00
10 changed files with 126 additions and 19 deletions
Showing only changes of commit 0df409e775 - Show all commits

View file

@ -37,10 +37,18 @@ public class Main extends Application {
@Override @Override
public void start(Stage primaryStage) { public void start(Stage primaryStage) {
this.primaryStage = primaryStage; this.primaryStage = primaryStage;
executePassword(); User user = executeLogin();
if(user != null){
executeMainApplication(user);
}
} }
private void executePassword() { /**
* Executes the login.
* @return User The {@link User} object for the logged-in {@link User}.
* Is {@code null}, if the login was not successful,
*/
private User executeLogin() {
try { try {
FXMLLoader loader = new FXMLLoader(Main.class.getResource("/de/hitec/nhplus/login/LoginView.fxml")); FXMLLoader loader = new FXMLLoader(Main.class.getResource("/de/hitec/nhplus/login/LoginView.fxml"));
@ -55,12 +63,10 @@ public class Main extends Application {
controller.initialize(loginStage); controller.initialize(loginStage);
loginStage.showAndWait(); loginStage.showAndWait();
return controller.user;
if(controller.user != null){
executeMainApplication(controller.user);
}
} catch (IOException exception) { } catch (IOException exception) {
exception.printStackTrace(); exception.printStackTrace();
return null;
} }
} }

View file

@ -13,7 +13,12 @@ import java.sql.Connection;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.*; import java.util.*;
public class UserFixture implements Fixture<User>{ /**
* {@link Fixture} for {@link User}.
*
* @author Dominik Säume
*/
public class UserFixture implements Fixture<User> {
private static final String SCHEMA = "/de/hitec/nhplus/login/database/User.sql"; private static final String SCHEMA = "/de/hitec/nhplus/login/database/User.sql";
private static final String PERMISSION_SCHEMA = "/de/hitec/nhplus/login/database/UserPermission.sql"; private static final String PERMISSION_SCHEMA = "/de/hitec/nhplus/login/database/UserPermission.sql";
private static final String TO_NURSE_SCHEMA = "/de/hitec/nhplus/login/database/UserToNurse.sql"; private static final String TO_NURSE_SCHEMA = "/de/hitec/nhplus/login/database/UserToNurse.sql";
@ -94,7 +99,7 @@ public class UserFixture implements Fixture<User>{
UserDao dao = DaoFactory.getInstance().createUserDAO(); UserDao dao = DaoFactory.getInstance().createUserDAO();
Map<String, User> usersByUsername = new HashMap<>(); Map<String, User> usersByUsername = new HashMap<>();
for (User user : users){ for (User user : users) {
dao.create(user); dao.create(user);
usersByUsername.put(user.getUsername(), user); usersByUsername.put(user.getUsername(), user);
} }

View file

@ -17,6 +17,11 @@ import java.security.NoSuchAlgorithmException;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.Arrays; import java.util.Arrays;
/**
* Controller for handling the login of {@link User}s.
*
* @author Dominik Säume
*/
public class LoginController { public class LoginController {
public User user; public User user;
@ -29,11 +34,18 @@ public class LoginController {
private Stage stage; private Stage stage;
private int loginTries = 0; private int loginTries = 0;
/**
* JavaFX Initialization method that is called after the binding of all the fields.
*
* @param stage The {@link Stage}, so the modal can close itself, when finished.
*/
public void initialize(Stage stage) { public void initialize(Stage stage) {
this.stage = stage; this.stage = stage;
} }
/**
* Internal method to handle actions on wrong logins, like a shake, timout and total tries.
*/
private void handleWrongPasswordOrUsername() { private void handleWrongPasswordOrUsername() {
loginTries++; loginTries++;

View file

@ -1,5 +1,11 @@
package de.hitec.nhplus.login; package de.hitec.nhplus.login;
/**
* A simple class holding the bitmasks for all permissions.
* This is a class instead of an enum, for ease of use.
*
* @author Dominiok Säume
*/
public class Permissions { public class Permissions {
public final static int EVERYBODY = 0b0; public final static int EVERYBODY = 0b0;
public final static int NURSE = 0b1; public final static int NURSE = 0b1;

View file

@ -7,8 +7,13 @@ import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom; import java.security.SecureRandom;
public class User {
/**
* The model for a {@link User}.
*
* @author Dominik Säume
*/
public class User {
private int id; private int id;
private String username; private String username;
@ -17,6 +22,10 @@ public class User {
private int permissions = 0; private int permissions = 0;
private Nurse nurse; private Nurse nurse;
/**
* This constructor allows instantiating a {@link User} object with all existing fields.
*/
public User( public User(
int id, int id,
String username, String username,
@ -33,6 +42,9 @@ public class User {
this.nurse = nurse; this.nurse = nurse;
} }
/**
* This constructor allows instantiating a {@link User} object.
*/
public User( public User(
String username, String username,
int permissions, int permissions,
@ -42,6 +54,12 @@ public class User {
this.permissions = permissions; this.permissions = permissions;
this.nurse = nurse; this.nurse = nurse;
} }
/**
* Sets the {@link User} password. The {@link User} will need to be manually stored with the
* {@link de.hitec.nhplus.login.database.UserDao UserDao}, for changes to persists.
* @param password The new Password
*/
public void setPassword(String password) { public void setPassword(String password) {
try { try {
SecureRandom random = new SecureRandom(); SecureRandom random = new SecureRandom();
@ -59,6 +77,7 @@ public class User {
public boolean hasNursePermissions(){ public boolean hasNursePermissions(){
return (permissions & Permissions.NURSE) != 0; return (permissions & Permissions.NURSE) != 0;
} }
public boolean hasAdminPermissions(){ public boolean hasAdminPermissions(){
return (permissions & Permissions.MANAGEMENT) != 0; return (permissions & Permissions.MANAGEMENT) != 0;
} }

View file

@ -12,6 +12,12 @@ import java.sql.SQLException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
/**
* The {@link UserDao} is an implementation of the{@link de.hitec.nhplus.datastorage.Dao Dao}
* for the {@link User} model.
*
* @author Dominik Säume
*/
public class UserDao implements Dao<User> { public class UserDao implements Dao<User> {
protected final Connection connection; protected final Connection connection;
@ -19,6 +25,11 @@ public class UserDao implements Dao<User> {
this.connection = connection; this.connection = connection;
} }
/**
* Try reading a {@link User#id} by its {@link User#username}.
* @param username The {@link User#username username} to try reading the {@link User#id id} of.
* @return The {@link User#id}. {@code 0} if the {@link User} doesn't exist.
*/
public int readUserId(String username) throws SQLException { public int readUserId(String username) throws SQLException {
final String SQL = "SELECT id FROM user WHERE username = ?"; final String SQL = "SELECT id FROM user WHERE username = ?";
PreparedStatement statement = this.connection.prepareStatement(SQL); PreparedStatement statement = this.connection.prepareStatement(SQL);
@ -26,6 +37,11 @@ public class UserDao implements Dao<User> {
return statement.executeQuery().getInt(1); return statement.executeQuery().getInt(1);
} }
/**
* Read a {@link User}s {@link User#passwordSalt password salt}.
* @param id The {@link User#id} of which the {@link User#passwordSalt password salt} should be read.
* @return The {@link User#passwordSalt password salt} as a{@code byte[]}.
*/
public byte[] readPasswordSalt(int id) throws SQLException { public byte[] readPasswordSalt(int id) throws SQLException {
final String SQL = "SELECT passwordSalt FROM user WHERE id = ?"; final String SQL = "SELECT passwordSalt FROM user WHERE id = ?";
PreparedStatement statement = this.connection.prepareStatement(SQL); PreparedStatement statement = this.connection.prepareStatement(SQL);
@ -33,6 +49,11 @@ public class UserDao implements Dao<User> {
return statement.executeQuery().getBytes(1); return statement.executeQuery().getBytes(1);
} }
/**
* Read a {@link User}s {@link User#passwordHash password hash} for authentication purposes.
* @param id The {@link User#id} of which the {@link User#passwordHash password hash} should be read.
* @return The {@link User#passwordHash password hash} as a{@code byte[]}.
*/
public byte[] readPasswordHash(int id) throws SQLException { public byte[] readPasswordHash(int id) throws SQLException {
final String SQL = "SELECT passwordHash FROM user WHERE id = ?"; final String SQL = "SELECT passwordHash FROM user WHERE id = ?";
PreparedStatement statement = this.connection.prepareStatement(SQL); PreparedStatement statement = this.connection.prepareStatement(SQL);

View file

@ -14,10 +14,7 @@ import java.util.List;
/** /**
* Controller for the main window of the application, which holds all tabs. * Controller for the main window of the application, which holds all tabs.
* *
* @author Bernd Heidemann
* @author Dominik Säume * @author Dominik Säume
* @author Armin Ribic
* @author Dorian Nemec
*/ */
public class MainWindowController { public class MainWindowController {
private static MainWindowController instace; private static MainWindowController instace;
@ -30,14 +27,13 @@ public class MainWindowController {
instace = this; instace = this;
} }
/**
* Method copying the idea of a singleton, to allow getting the current {@link User}.
*/
public static MainWindowController getInstance() { public static MainWindowController getInstance() {
return instace; return instace;
} }
public User getUser() {
return user;
}
/** /**
* JavaFX Initialization method that is called after the binding of all the fields. * JavaFX Initialization method that is called after the binding of all the fields.
* *
@ -95,4 +91,8 @@ public class MainWindowController {
mainTabPane.getSelectionModel().select(defaultTab); mainTabPane.getSelectionModel().select(defaultTab);
defaultTab.getOnSelectionChanged().handle(new Event(Event.ANY)); defaultTab.getOnSelectionChanged().handle(new Event(Event.ANY));
} }
public User getUser() {
return user;
}
} }

View file

@ -44,7 +44,7 @@ public class Nurse extends Person {
/** /**
* This constructor allows instantiating a {@link Nurse} object with * This constructor allows instantiating a {@link Nurse} object with
* specifying if the nurse is locked or not. * specifying whether the {@link Nurse} is locked or not.
*/ */
public Nurse( public Nurse(
String firstName, String firstName,

View file

@ -15,6 +15,12 @@ import java.io.IOException;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
/**
* A utility class to construct {@link Tab}s from views. This also supports sub {@link Tab}s.
*
* @author Dominiok Säume
* @see TabManager
*/
public class TabManager { public class TabManager {
private final User user; private final User user;
@ -22,11 +28,21 @@ public class TabManager {
this.user = user; this.user = user;
} }
/**
* Internal method to check permissions
* @param requiredPermissions The permissions the {@link User} requires.
* @param permissions The permissions the {@link User} has.
*/
private boolean hasPermissions(int requiredPermissions, int permissions) { private boolean hasPermissions(int requiredPermissions, int permissions) {
return requiredPermissions == Permissions.EVERYBODY return requiredPermissions == Permissions.EVERYBODY
|| (permissions & requiredPermissions) != 0; || (permissions & requiredPermissions) != 0;
} }
/**
* Method to set up a single tab and register it to its {@link TabPane}.
* @param tabPane The {@link TabPane} to register to.
* @param tabStruct The data needed to construct the new tab.
*/
public void setupTab(TabPane tabPane, TabStruct tabStruct) { public void setupTab(TabPane tabPane, TabStruct tabStruct) {
if (!hasPermissions(tabStruct.requiredPermissions, user.getPermissions())) { if (!hasPermissions(tabStruct.requiredPermissions, user.getPermissions())) {
return; return;
@ -39,6 +55,11 @@ public class TabManager {
tabPane.getTabs().add(tab); tabPane.getTabs().add(tab);
} }
/**
* {@link EventHandler} to handle the loading of a {@link Tab}.
* @param tabStruct The {@link TabStruct} holding the path of the view.
* @param pane The main pane of the {@link Tab}.
*/
private EventHandler<Event> loadTabEventHandler(TabStruct tabStruct, AnchorPane pane) { private EventHandler<Event> loadTabEventHandler(TabStruct tabStruct, AnchorPane pane) {
return event -> { return event -> {
try { try {
@ -56,6 +77,13 @@ public class TabManager {
}; };
} }
/**
* Method to set up a sub tab and register it to its parent {@link TabPane}.
* @param parentTabPane The {@link TabPane} to register to.
* @param title The title of the {@link Tab}.
* @param requiredPermissions The permissions required to see the sub {@link Tab}.
* @param subTabs A {@link List} of {@link TabStruct}s to create in the sub {@link Tab}.
*/
public void setupSubTabPane(TabPane parentTabPane, String title, int requiredPermissions, List<TabStruct> subTabs) { public void setupSubTabPane(TabPane parentTabPane, String title, int requiredPermissions, List<TabStruct> subTabs) {
if (!hasPermissions(requiredPermissions, user.getPermissions())) { if (!hasPermissions(requiredPermissions, user.getPermissions())) {
return; return;
@ -73,6 +101,10 @@ public class TabManager {
parentTabPane.getTabs().add(tab); parentTabPane.getTabs().add(tab);
} }
/**
* {@link EventHandler} to handle the loading of a sub {@link TabPane}.
* @param tabPane The {@link TabPane} of the sub {@link Tab} to handle loading.
*/
private EventHandler<Event> loadSubTabPaneEventHandler(TabPane tabPane) { private EventHandler<Event> loadSubTabPaneEventHandler(TabPane tabPane) {
return event -> { return event -> {
Tab tab = tabPane.getSelectionModel().getSelectedItem(); Tab tab = tabPane.getSelectionModel().getSelectedItem();

View file

@ -1,5 +1,11 @@
package de.hitec.nhplus.utils.tab; package de.hitec.nhplus.utils.tab;
/**
* A simple class holding the data needed for constructing a {@link javafx.scene.control.Tab Tab}.
*
* @author Dominiok Säume
* @see TabManager
*/
public class TabStruct { public class TabStruct {
public String title; public String title;
public String view; public String view;