added login finally
This commit is contained in:
parent
80ca3240f1
commit
a659e1217c
2
.idea/misc.xml
generated
2
.idea/misc.xml
generated
@ -4,7 +4,7 @@
|
||||
<component name="FrameworkDetectionExcludesConfiguration">
|
||||
<file type="web" url="file://$PROJECT_DIR$" />
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_25" default="true" project-jdk-name="openjdk-25" project-jdk-type="JavaSDK">
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_X" default="true" project-jdk-name="openjdk-25" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/out" />
|
||||
</component>
|
||||
</project>
|
||||
@ -3,6 +3,7 @@ package dev.ksan.CASystem;
|
||||
import javax.crypto.SecretKeyFactory;
|
||||
import javax.crypto.spec.PBEKeySpec;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.InputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
@ -18,7 +19,7 @@ public class KeystoreService {
|
||||
|
||||
private static String KEYSTORE_TYPE = "PKCS12";
|
||||
private static String KEY_ALIAS = "key";
|
||||
private static final Path USER_KEYSORE_DIR = Path.of("keystores/users");
|
||||
private static final Path USER_KEYSTORE_DIR = Path.of("keystores/users");
|
||||
private static final Path CA_KEYSTORE_DIR = Path.of("keystores/ca");
|
||||
|
||||
|
||||
@ -35,7 +36,7 @@ public class KeystoreService {
|
||||
|
||||
keyStore.setKeyEntry(KEY_ALIAS, privateKey, keystorePassword, chain);
|
||||
|
||||
Path path = USER_KEYSORE_DIR.resolve(username + ".p12");
|
||||
Path path = USER_KEYSTORE_DIR.resolve(username + ".p12");
|
||||
|
||||
Files.createDirectories(path.getParent());
|
||||
|
||||
@ -46,14 +47,14 @@ public class KeystoreService {
|
||||
}
|
||||
|
||||
public static PrivateKey getPrivateKey(String username, char[] keystorePassword) throws Exception {
|
||||
KeyStore keystore = loadKeyStore(USER_KEYSORE_DIR.resolve(username+".p12"), keystorePassword);
|
||||
KeyStore keystore = loadKeyStore(USER_KEYSTORE_DIR.resolve(username+".p12"), keystorePassword);
|
||||
|
||||
return (PrivateKey) keystore.getKey(KEY_ALIAS, keystorePassword);
|
||||
|
||||
}
|
||||
|
||||
public static X509Certificate getCertificate(String username, char[] keystorePassword) throws Exception {
|
||||
KeyStore keyStore = loadKeyStore(USER_KEYSORE_DIR.resolve(username+".p12"), keystorePassword);
|
||||
KeyStore keyStore = loadKeyStore(USER_KEYSTORE_DIR.resolve(username+".p12"), keystorePassword);
|
||||
return (X509Certificate) keyStore.getCertificate(KEY_ALIAS);
|
||||
}
|
||||
|
||||
@ -122,6 +123,7 @@ public class KeystoreService {
|
||||
KeyStore ks = loadKeystore(CA_KEYSTORE_DIR.resolve(caName + ".p12"), caPassword);
|
||||
return (PrivateKey) ks.getKey(KEY_ALIAS, caPassword);
|
||||
}
|
||||
|
||||
private static KeyStore loadKeystore(Path path, char[] password) throws Exception {
|
||||
KeyStore ks = KeyStore.getInstance(KEYSTORE_TYPE);
|
||||
try (InputStream is = Files.newInputStream(path)) {
|
||||
@ -129,4 +131,5 @@ public class KeystoreService {
|
||||
}
|
||||
return ks;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -108,6 +108,7 @@ public class LoginService {
|
||||
|
||||
user.setFailedLoginAttempts(user.getFailedLoginAttempts() + 1);
|
||||
|
||||
System.out.println("Attempt failed: " + user.getFailedLoginAttempts());
|
||||
if (user.getFailedLoginAttempts() >= 3) {
|
||||
|
||||
user.setRevoked(true);
|
||||
|
||||
@ -17,7 +17,6 @@ public abstract class User implements Serializable {
|
||||
|
||||
public User(){
|
||||
|
||||
//generate key
|
||||
}
|
||||
|
||||
public PublicKey getPublicKey() {
|
||||
|
||||
@ -136,20 +136,35 @@ public class UserRepository {
|
||||
StandardCopyOption.REPLACE_EXISTING);
|
||||
}
|
||||
|
||||
//this was annoying i dont wannt look at java.nio.channels.ClosedChannelException again
|
||||
private static Object deserialize(Path path) throws Exception {
|
||||
if (!Files.exists(path)) return null;
|
||||
|
||||
try (FileInputStream fis = new FileInputStream(path.toFile());
|
||||
FileLock fileLock = fis.getChannel().tryLock(0, Long.MAX_VALUE, true); // shared read lock
|
||||
ObjectInputStream ois = new ObjectInputStream(fis)) {
|
||||
FileInputStream fis = new FileInputStream(path.toFile());
|
||||
FileLock fileLock = null;
|
||||
|
||||
try {
|
||||
fileLock = fis.getChannel().tryLock(0, Long.MAX_VALUE, true);
|
||||
|
||||
if (fileLock == null) {
|
||||
throw new IllegalStateException("Could not acquire read lock on: " + path);
|
||||
}
|
||||
return ois.readObject();
|
||||
|
||||
ObjectInputStream ois = new ObjectInputStream(fis);
|
||||
Object obj = ois.readObject();
|
||||
ois.close(); // close stream AFTER reading
|
||||
|
||||
return obj;
|
||||
|
||||
} finally {
|
||||
if (fileLock != null && fileLock.isValid()) {
|
||||
fileLock.release(); // release FIRST
|
||||
}
|
||||
fis.close(); // then close channel
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static <T extends User> List<T> findAll(
|
||||
Path dir, Class<T> type, String lockPrefix) throws Exception {
|
||||
|
||||
|
||||
@ -9,7 +9,7 @@ public class Voter extends User {
|
||||
private String lastName;
|
||||
private String username;
|
||||
|
||||
public Voter(String name, String username, String lastName){
|
||||
public Voter(String name, String lastName, String username){
|
||||
super();
|
||||
this.name = name;
|
||||
this.username = username;
|
||||
|
||||
@ -23,7 +23,7 @@ public class HomeController {
|
||||
|
||||
@FXML
|
||||
public void initialize() {
|
||||
loginButton.setOnAction(e -> System.out.println("Go to login"));
|
||||
loginButton.setOnAction(e -> goToLogin());
|
||||
registerButton.setOnAction(e -> goToRegister());
|
||||
}
|
||||
|
||||
@ -47,4 +47,23 @@ public class HomeController {
|
||||
}
|
||||
}
|
||||
|
||||
private void goToLogin() {
|
||||
try {
|
||||
FXMLLoader loader = new FXMLLoader(getClass().getResource("/fxml/LoginView.fxml"));
|
||||
Scene oldScene = stage.getScene();
|
||||
Scene scene = new Scene(loader.load(),
|
||||
oldScene.getWidth(),
|
||||
oldScene.getHeight()
|
||||
);
|
||||
|
||||
LoginController controller = loader.getController();
|
||||
controller.setStage(stage);
|
||||
|
||||
stage.setScene(scene);
|
||||
stage.setTitle("Register");
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
313
src/main/java/dev/ksan/ui/LoginController.java
Normal file
313
src/main/java/dev/ksan/ui/LoginController.java
Normal file
@ -0,0 +1,313 @@
|
||||
package dev.ksan.ui;
|
||||
|
||||
import dev.ksan.CASystem.CAType;
|
||||
import dev.ksan.CASystem.KeystoreService;
|
||||
import dev.ksan.CASystem.LoginService;
|
||||
import dev.ksan.Users.Organizer;
|
||||
import dev.ksan.Users.User;
|
||||
import dev.ksan.Users.Voter;
|
||||
import javafx.application.Platform;
|
||||
import javafx.concurrent.Task;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.fxml.FXMLLoader;
|
||||
import javafx.scene.Parent;
|
||||
import javafx.scene.Scene;
|
||||
import javafx.scene.control.*;
|
||||
import javafx.scene.input.Dragboard;
|
||||
import javafx.scene.input.TransferMode;
|
||||
import javafx.scene.layout.StackPane;
|
||||
import javafx.scene.layout.VBox;
|
||||
import javafx.stage.FileChooser;
|
||||
import javafx.stage.Stage;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.InputStream;
|
||||
import java.security.KeyStore;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.Arrays;
|
||||
|
||||
public class LoginController {
|
||||
|
||||
@FXML private StackPane dropZone;
|
||||
//currently everything is saved as .p12? so we also need to insert password here???? maybe??
|
||||
// or change it so that the user just has the plain cert and we hand that in? and we get
|
||||
// the private only key then after they login finally
|
||||
// this is the password field for the p12 keystore
|
||||
@FXML private PasswordField passwordField;
|
||||
@FXML private Label dropZoneLabel;
|
||||
@FXML private Label errorLabel;
|
||||
@FXML private Button loginButton;
|
||||
|
||||
@FXML private VBox form1;
|
||||
@FXML private VBox form2;
|
||||
@FXML
|
||||
private Button finishLoginButton;
|
||||
|
||||
@FXML
|
||||
private TextField usernameField;
|
||||
|
||||
@FXML
|
||||
private PasswordField userPasswordField;
|
||||
|
||||
|
||||
private User certUser;
|
||||
|
||||
private Stage stage;
|
||||
private File droppedFile;
|
||||
private X509Certificate loadedCert;
|
||||
private CAType detectedCAType;
|
||||
|
||||
public void setStage(Stage stage) {
|
||||
this.stage = stage;
|
||||
}
|
||||
|
||||
@FXML
|
||||
public void initialize() {
|
||||
showForm1();
|
||||
dropZone.setStyle(
|
||||
"-fx-border-color: #888;" +
|
||||
"-fx-border-width: 2;" +
|
||||
"-fx-border-radius: 8;" +
|
||||
"-fx-background-radius: 8;" +
|
||||
"-fx-background-color: #f9f9f9;"
|
||||
);
|
||||
|
||||
errorLabel.setVisible(false);
|
||||
loginButton.setDisable(true); // disabled until cert + password are provided
|
||||
|
||||
setupDropZone();
|
||||
|
||||
passwordField.textProperty().addListener((obs, oldVal, newVal) -> {
|
||||
loginButton.setDisable(droppedFile == null || newVal.trim().isEmpty());
|
||||
});
|
||||
userPasswordField.textProperty().addListener((obs, oldVal, newVal) -> {
|
||||
finishLoginButton.setDisable( newVal.trim().isEmpty());
|
||||
});
|
||||
}
|
||||
|
||||
private void setupDropZone() {
|
||||
dropZone.setOnDragEntered(e -> {
|
||||
if (e.getDragboard().hasFiles())
|
||||
dropZone.setStyle(dropZone.getStyle() + "-fx-border-color: #4A90D9;");
|
||||
});
|
||||
|
||||
dropZone.setOnDragExited(e -> {
|
||||
dropZone.setStyle(dropZone.getStyle().replace("-fx-border-color: #4A90D9;", "-fx-border-color: #888;"));
|
||||
});
|
||||
|
||||
dropZone.setOnDragOver(event -> {
|
||||
if (event.getGestureSource() != dropZone && event.getDragboard().hasFiles()) {
|
||||
event.acceptTransferModes(TransferMode.COPY);
|
||||
}
|
||||
event.consume();
|
||||
});
|
||||
|
||||
dropZone.setOnDragDropped(event -> {
|
||||
Dragboard db = event.getDragboard();
|
||||
boolean success = false;
|
||||
|
||||
if (db.hasFiles()) {
|
||||
File file = db.getFiles().get(0);
|
||||
if (file.getName().endsWith(".p12")) {
|
||||
droppedFile = file;
|
||||
dropZoneLabel.setText("📄 " + file.getName());
|
||||
success = true;
|
||||
showError("Certificate loaded. Enter your password and click Login.");
|
||||
} else {
|
||||
showError("Please drop a .p12 keystore file.");
|
||||
}
|
||||
}
|
||||
|
||||
event.setDropCompleted(success);
|
||||
event.consume();
|
||||
});
|
||||
|
||||
dropZone.setOnMouseClicked(e -> browseForKeystore());
|
||||
}
|
||||
|
||||
private void browseForKeystore() {
|
||||
FileChooser fileChooser = new FileChooser();
|
||||
fileChooser.setTitle("Select your keystore (.p12)");
|
||||
fileChooser.getExtensionFilters().add(
|
||||
new FileChooser.ExtensionFilter("PKCS12 Keystore", "*.p12"));
|
||||
|
||||
File file = fileChooser.showOpenDialog(stage);
|
||||
if (file != null) {
|
||||
droppedFile = file;
|
||||
dropZoneLabel.setText("📄 " + file.getName());
|
||||
}
|
||||
}
|
||||
|
||||
@FXML
|
||||
public void onLoginClicked() {
|
||||
clearError();
|
||||
|
||||
if (droppedFile == null) {
|
||||
showError("Please provide your keystore (.p12) file.");
|
||||
return;
|
||||
}
|
||||
|
||||
String password = passwordField.getText();
|
||||
if (password.isBlank()) {
|
||||
showError("Please enter your password.");
|
||||
return;
|
||||
}
|
||||
|
||||
String identity = droppedFile.getName().replace(".p12", "");
|
||||
|
||||
loginButton.setDisable(true);
|
||||
|
||||
Task<User> loginTask = new Task<>() {
|
||||
@Override
|
||||
protected User call() throws Exception {
|
||||
|
||||
char[] ksPassword = KeystoreService.deriveKeystorePassword(password, identity);
|
||||
KeyStore ks = KeyStore.getInstance("PKCS12");
|
||||
|
||||
try (InputStream is = new FileInputStream(droppedFile)) {
|
||||
ks.load(is, Arrays.copyOf(ksPassword, ksPassword.length));
|
||||
} catch (Exception e) {
|
||||
// TODO
|
||||
// if this also counts as unsuccessful attempt then we need
|
||||
// to add handle failed attempt here too
|
||||
}
|
||||
|
||||
|
||||
X509Certificate cert = (X509Certificate) ks.getCertificate("key");
|
||||
if (cert == null)
|
||||
throw new SecurityException("No certificate found in keystore.");
|
||||
|
||||
CAType caType = LoginService.validateCertificate(cert);
|
||||
|
||||
|
||||
showForm2();
|
||||
loadedCert = cert;
|
||||
detectedCAType = caType;
|
||||
return LoginService.validateCredentials(identity, password, cert, caType);
|
||||
}
|
||||
};
|
||||
|
||||
loginTask.setOnSucceeded(e -> {
|
||||
User user = loginTask.getValue();
|
||||
certUser=user;
|
||||
});
|
||||
|
||||
loginTask.setOnFailed(e -> {
|
||||
certUser=null;
|
||||
Throwable ex = loginTask.getException();
|
||||
showError(ex.getMessage());
|
||||
loginButton.setDisable(false);
|
||||
});
|
||||
|
||||
new Thread(loginTask).start();
|
||||
}
|
||||
@FXML
|
||||
public void onFinalLoginClicked() {
|
||||
clearError();
|
||||
|
||||
|
||||
String password = userPasswordField.getText();
|
||||
if (password.isBlank()) {
|
||||
showError("Please enter your password.");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
finishLoginButton.setDisable(true);
|
||||
|
||||
Task<Boolean> loginTask = new Task<>() {
|
||||
@Override
|
||||
protected Boolean call() throws Exception {
|
||||
|
||||
|
||||
return userLogin();
|
||||
}
|
||||
};
|
||||
|
||||
loginTask.setOnSucceeded(e -> {
|
||||
navigateToUserUI(certUser);
|
||||
});
|
||||
|
||||
loginTask.setOnFailed(e -> {
|
||||
certUser = null;
|
||||
loadedCert = null;
|
||||
detectedCAType = null;
|
||||
Throwable ex = loginTask.getException();
|
||||
showError(ex.getMessage());
|
||||
finishLoginButton.setDisable(true);
|
||||
});
|
||||
|
||||
new Thread(loginTask).start();
|
||||
}
|
||||
|
||||
private boolean userLogin() {
|
||||
|
||||
try{
|
||||
|
||||
User user = LoginService.validateCredentials(usernameField.getText().trim(),
|
||||
userPasswordField.getText().trim(), loadedCert, detectedCAType);
|
||||
return user == certUser;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
|
||||
// TODO maybe pass in the certificate and/or keypair?
|
||||
private void navigateToUserUI(User user) {
|
||||
try {
|
||||
|
||||
if (user instanceof Organizer organizer) {
|
||||
FXMLLoader loader = new FXMLLoader(
|
||||
getClass().getResource("/fxml/OrganizerView.fxml"));
|
||||
Parent root = loader.load();
|
||||
OrganizerController controller = loader.getController();
|
||||
controller.setOrganizer(organizer);
|
||||
controller.setStage(stage);
|
||||
stage.setScene(new Scene(root));
|
||||
|
||||
} else if (user instanceof Voter voter) {
|
||||
FXMLLoader loader = new FXMLLoader(
|
||||
getClass().getResource("/fxml/VoterView.fxml"));
|
||||
Parent root = loader.load();
|
||||
VoterController controller = loader.getController();
|
||||
controller.setVoter(voter);
|
||||
controller.setStage(stage);
|
||||
stage.setScene(new Scene(root));
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
showError("Failed to load UI: " + e.getMessage());
|
||||
loginButton.setDisable(false);
|
||||
}
|
||||
}
|
||||
|
||||
private void showError(String message) {
|
||||
Platform.runLater(() -> {
|
||||
errorLabel.setText(message);
|
||||
errorLabel.setVisible(true);
|
||||
});
|
||||
}
|
||||
|
||||
private void clearError() {
|
||||
errorLabel.setText("");
|
||||
errorLabel.setVisible(false);
|
||||
}
|
||||
|
||||
|
||||
@FXML
|
||||
private void showForm2() {
|
||||
form1.setVisible(false);
|
||||
form2.setVisible(true);
|
||||
}
|
||||
|
||||
@FXML
|
||||
private void showForm1() {
|
||||
form1.setVisible(true);
|
||||
form2.setVisible(false);
|
||||
}
|
||||
}
|
||||
18
src/main/java/dev/ksan/ui/OrganizerController.java
Normal file
18
src/main/java/dev/ksan/ui/OrganizerController.java
Normal file
@ -0,0 +1,18 @@
|
||||
package dev.ksan.ui;
|
||||
|
||||
import dev.ksan.Users.Organizer;
|
||||
import javafx.stage.Stage;
|
||||
|
||||
public class OrganizerController {
|
||||
private Organizer organizer;
|
||||
|
||||
private Stage stage;
|
||||
public void setOrganizer(Organizer organizer) {
|
||||
this.organizer = organizer;
|
||||
}
|
||||
|
||||
public void setStage(Stage stage) {
|
||||
this.stage = stage;
|
||||
|
||||
}
|
||||
}
|
||||
@ -1,5 +1,8 @@
|
||||
package dev.ksan.ui;
|
||||
|
||||
import dev.ksan.CASystem.RegistrationService;
|
||||
import dev.ksan.Users.Organizer;
|
||||
import dev.ksan.Users.Voter;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.scene.control.Button;
|
||||
import javafx.scene.control.PasswordField;
|
||||
@ -31,4 +34,69 @@ public class RegisterOrganizerController {
|
||||
public void setStage(Stage stage) {
|
||||
this.stage = stage;
|
||||
}
|
||||
|
||||
@FXML
|
||||
public void initialize() {
|
||||
registerButton.setOnAction(event -> tryRegisterVoter());
|
||||
}
|
||||
|
||||
private void tryRegisterVoter() {
|
||||
|
||||
try {
|
||||
if (!checkAndHighlightFields()) return;
|
||||
|
||||
Organizer organizer = new Organizer(nameField.getText().trim(),idField.getText().trim());
|
||||
|
||||
|
||||
|
||||
|
||||
RegistrationService.registerOrganizer(organizer, passwordField.getText());
|
||||
|
||||
}catch (Exception e) {
|
||||
displayError("Username already Taken");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//TODO
|
||||
private void loginUser(Voter voter) {
|
||||
}
|
||||
|
||||
|
||||
//TODO
|
||||
private void displayError(String usernameAlreadyTaken) {
|
||||
}
|
||||
|
||||
// return true if everything is filled
|
||||
private boolean checkAndHighlightFields() {
|
||||
if (nameField.getText().trim().isEmpty()) {
|
||||
nameField.setStyle("-fx-text-fill: red");
|
||||
return false;
|
||||
}else{
|
||||
nameField.setStyle("-fx-text-fill: white");
|
||||
}
|
||||
if (idField.getText().isEmpty()) {
|
||||
idField.setStyle("-fx-text-fill: red");
|
||||
return false;
|
||||
}else{
|
||||
idField.setStyle("-fx-text-fill: white");
|
||||
}
|
||||
if (passwordField.getText().isEmpty()) {
|
||||
passwordField.setStyle("-fx-text-fill: red");
|
||||
return false;
|
||||
}else{
|
||||
passwordField.setStyle("-fx-text-fill: white");
|
||||
}
|
||||
if (confirmPasswordField.getText().isEmpty() || !confirmPasswordField.getText().equals(passwordField.getText())) {
|
||||
confirmPasswordField.setStyle("-fx-text-fill: red");
|
||||
displayError("Passwords do not match");
|
||||
return false;
|
||||
}else{
|
||||
confirmPasswordField.setStyle("-fx-text-fill: white");
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,5 +1,8 @@
|
||||
package dev.ksan.ui;
|
||||
|
||||
import dev.ksan.CASystem.RegistrationService;
|
||||
import dev.ksan.Users.UserRepository;
|
||||
import dev.ksan.Users.Voter;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.scene.control.Button;
|
||||
import javafx.scene.control.PasswordField;
|
||||
@ -38,6 +41,79 @@ public class RegisterVoterController {
|
||||
}
|
||||
@FXML
|
||||
public void initialize() {
|
||||
registerButton.setOnAction(event -> tryRegisterVoter());
|
||||
}
|
||||
|
||||
private void tryRegisterVoter() {
|
||||
|
||||
System.out.println("Registering voter");
|
||||
try {
|
||||
if (!checkAndHighlightFields()) return;
|
||||
|
||||
Voter voter = new Voter(nameField.getText().trim(), surnameField.getText().trim(),
|
||||
usernameField.getText().trim());
|
||||
|
||||
|
||||
|
||||
RegistrationService.registerVoter(voter, passwordField.getText());
|
||||
|
||||
loginUser(voter);
|
||||
}catch (Exception e) {
|
||||
displayError("Username already Taken");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//TODO
|
||||
private void loginUser(Voter voter) {
|
||||
System.out.println("registered: " + voter);
|
||||
}
|
||||
|
||||
|
||||
//TODO
|
||||
private void displayError(String usernameAlreadyTaken) {
|
||||
}
|
||||
|
||||
// return true if everything is filled
|
||||
private boolean checkAndHighlightFields() {
|
||||
if (nameField.getText().isEmpty()) {
|
||||
nameField.setStyle("-fx-text-fill: red");
|
||||
return false;
|
||||
}else{
|
||||
nameField.setStyle("-fx-text-fill: black");
|
||||
}
|
||||
if (surnameField.getText().isEmpty()) {
|
||||
surnameField.setStyle("-fx-text-fill: red");
|
||||
return false;
|
||||
}else{
|
||||
surnameField.setStyle("-fx-text-fill: black");
|
||||
}
|
||||
if (usernameField.getText().isEmpty()) {
|
||||
usernameField.setStyle("-fx-text-fill: red");
|
||||
return false;
|
||||
}else{
|
||||
usernameField.setStyle("-fx-text-fill: black");
|
||||
}
|
||||
if (passwordField.getText().isEmpty()) {
|
||||
passwordField.setStyle("-fx-text-fill: red");
|
||||
return false;
|
||||
}else{
|
||||
passwordField.setStyle("-fx-text-fill: black");
|
||||
}
|
||||
if (confirmPasswordField.getText().isEmpty() || !confirmPasswordField.getText().equals(passwordField.getText())) {
|
||||
confirmPasswordField.setStyle("-fx-text-fill: red");
|
||||
displayError("Passwords do not match");
|
||||
return false;
|
||||
}else{
|
||||
confirmPasswordField.setStyle("-fx-text-fill: black");
|
||||
}
|
||||
|
||||
if(UserRepository.voterExists(usernameField.getText().trim())){
|
||||
displayError("Username already Taken");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
17
src/main/java/dev/ksan/ui/VoterController.java
Normal file
17
src/main/java/dev/ksan/ui/VoterController.java
Normal file
@ -0,0 +1,17 @@
|
||||
package dev.ksan.ui;
|
||||
|
||||
import dev.ksan.Users.Voter;
|
||||
import javafx.stage.Stage;
|
||||
|
||||
public class VoterController {
|
||||
private Voter voter;
|
||||
private Stage stage;
|
||||
|
||||
public void setVoter(Voter voter) {
|
||||
this.voter = voter;
|
||||
}
|
||||
|
||||
public void setStage(Stage stage) {
|
||||
this.stage = stage;
|
||||
}
|
||||
}
|
||||
@ -1,14 +1,88 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<?import java.lang.*?>
|
||||
<?import java.util.*?>
|
||||
<?import javafx.scene.*?>
|
||||
<?import javafx.scene.control.*?>
|
||||
<?import javafx.scene.layout.*?>
|
||||
<?import javafx.geometry.Insets?>
|
||||
<?import javafx.scene.control.Button?>
|
||||
<?import javafx.scene.control.Label?>
|
||||
<?import javafx.scene.control.PasswordField?>
|
||||
<?import javafx.scene.control.TextField?>
|
||||
<?import javafx.scene.layout.BorderPane?>
|
||||
<?import javafx.scene.layout.ColumnConstraints?>
|
||||
<?import javafx.scene.layout.GridPane?>
|
||||
<?import javafx.scene.layout.RowConstraints?>
|
||||
<?import javafx.scene.layout.StackPane?>
|
||||
<?import javafx.scene.layout.VBox?>
|
||||
<?import javafx.scene.text.Text?>
|
||||
|
||||
<AnchorPane xmlns="http://javafx.com/javafx"
|
||||
xmlns:fx="http://javafx.com/fxml"
|
||||
fx:controller="fxml.LoginView"
|
||||
prefHeight="400.0" prefWidth="600.0">
|
||||
|
||||
</AnchorPane>
|
||||
<BorderPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/23.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="dev.ksan.ui.LoginController">
|
||||
<center>
|
||||
<VBox alignment="CENTER" prefHeight="200.0" prefWidth="100.0" BorderPane.alignment="CENTER">
|
||||
<children>
|
||||
<StackPane fx:id="rootStack" prefHeight="150.0" prefWidth="200.0">
|
||||
<children>
|
||||
<VBox fx:id="form1" alignment="CENTER" prefHeight="200.0" prefWidth="100.0">
|
||||
<children>
|
||||
<Text strokeType="OUTSIDE" strokeWidth="0.0" text="E-Voting">
|
||||
<VBox.margin>
|
||||
<Insets bottom="75.0" />
|
||||
</VBox.margin>
|
||||
</Text>
|
||||
<StackPane fx:id="dropZone" prefHeight="150.0" prefWidth="200.0">
|
||||
<children>
|
||||
<Label fx:id="dropZoneLabel" text="dropZoneLabel">
|
||||
<padding>
|
||||
<Insets bottom="50.0" left="50.0" right="50.0" top="50.0" />
|
||||
</padding>
|
||||
</Label>
|
||||
</children>
|
||||
<VBox.margin>
|
||||
<Insets left="100.0" right="100.0" />
|
||||
</VBox.margin>
|
||||
</StackPane>
|
||||
<PasswordField fx:id="passwordField">
|
||||
<VBox.margin>
|
||||
<Insets left="150.0" right="150.0" top="15.0" />
|
||||
</VBox.margin>
|
||||
</PasswordField>
|
||||
<Label fx:id="errorLabel" text="ErrorLabel">
|
||||
<VBox.margin>
|
||||
<Insets bottom="4.0" top="4.0" />
|
||||
</VBox.margin>
|
||||
</Label>
|
||||
<Button fx:id="loginButton" mnemonicParsing="false" onAction="#onLoginClicked" text="login" />
|
||||
</children>
|
||||
</VBox>
|
||||
<VBox fx:id="form2" alignment="CENTER" prefHeight="200.0" prefWidth="100.0">
|
||||
<children>
|
||||
<Text strokeType="OUTSIDE" strokeWidth="0.0" text="E-Voting" />
|
||||
<GridPane alignment="CENTER">
|
||||
<columnConstraints>
|
||||
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
|
||||
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
|
||||
</columnConstraints>
|
||||
<rowConstraints>
|
||||
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
|
||||
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
|
||||
</rowConstraints>
|
||||
<VBox.margin>
|
||||
<Insets left="100.0" right="100.0" />
|
||||
</VBox.margin>
|
||||
<children>
|
||||
<Text strokeType="OUTSIDE" strokeWidth="0.0" text="Username:" textAlignment="CENTER" />
|
||||
<Text strokeType="OUTSIDE" strokeWidth="0.0" text="Password:" GridPane.rowIndex="1" />
|
||||
<TextField fx:id="usernameField" GridPane.columnIndex="1" />
|
||||
<PasswordField fx:id="userPasswordField" GridPane.columnIndex="1" GridPane.rowIndex="1" />
|
||||
</children>
|
||||
</GridPane>
|
||||
<Button fx:id="finishLoginButton" mnemonicParsing="false" onAction="#onFinalLoginClicked" text="login">
|
||||
<VBox.margin>
|
||||
<Insets top="50.0" />
|
||||
</VBox.margin>
|
||||
</Button>
|
||||
</children>
|
||||
</VBox>
|
||||
</children>
|
||||
</StackPane>
|
||||
</children>
|
||||
</VBox>
|
||||
</center>
|
||||
</BorderPane>
|
||||
|
||||
@ -12,7 +12,6 @@
|
||||
<?import javafx.scene.text.Font?>
|
||||
<?import javafx.scene.text.Text?>
|
||||
|
||||
|
||||
<BorderPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/23.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="dev.ksan.ui.RegisterVoterController">
|
||||
<center>
|
||||
<VBox alignment="CENTER" prefHeight="200.0" prefWidth="100.0" BorderPane.alignment="CENTER">
|
||||
@ -83,7 +82,7 @@
|
||||
<Insets right="100.0" />
|
||||
</GridPane.margin>
|
||||
</PasswordField>
|
||||
<PasswordField fx:id="passwordConfirmField" GridPane.columnIndex="1" GridPane.rowIndex="4">
|
||||
<PasswordField fx:id="confirmPasswordField" GridPane.columnIndex="1" GridPane.rowIndex="4">
|
||||
<GridPane.margin>
|
||||
<Insets right="100.0" />
|
||||
</GridPane.margin>
|
||||
|
||||
@ -0,0 +1,43 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<?import com.gluonhq.charm.glisten.control.Avatar?>
|
||||
<?import com.gluonhq.charm.glisten.control.DropdownButton?>
|
||||
<?import com.gluonhq.charm.glisten.control.ExpansionPanel?>
|
||||
<?import javafx.geometry.Insets?>
|
||||
<?import javafx.scene.control.MenuItem?>
|
||||
<?import javafx.scene.layout.BorderPane?>
|
||||
<?import javafx.scene.layout.HBox?>
|
||||
<?import javafx.scene.layout.VBox?>
|
||||
<?import javafx.scene.text.Text?>
|
||||
|
||||
|
||||
<BorderPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/23.0.1" xmlns:fx="http://javafx.com/fxml/1">
|
||||
<left>
|
||||
<VBox prefHeight="200.0" prefWidth="100.0" BorderPane.alignment="CENTER">
|
||||
<children>
|
||||
<HBox alignment="CENTER" prefHeight="100.0" prefWidth="200.0">
|
||||
<children>
|
||||
<Avatar>
|
||||
<HBox.margin>
|
||||
<Insets left="5.0" right="5.0" />
|
||||
</HBox.margin>
|
||||
</Avatar>
|
||||
<Text strokeType="OUTSIDE" strokeWidth="0.0" text="Text" />
|
||||
</children>
|
||||
</HBox>
|
||||
<VBox alignment="CENTER" prefHeight="200.0" prefWidth="100.0">
|
||||
<children>
|
||||
<DropdownButton>
|
||||
<items>
|
||||
<MenuItem text="Choice 1" />
|
||||
<MenuItem text="Choice 2" />
|
||||
<MenuItem text="Choice 3" />
|
||||
</items>
|
||||
</DropdownButton>
|
||||
<ExpansionPanel />
|
||||
</children>
|
||||
</VBox>
|
||||
</children>
|
||||
</VBox>
|
||||
</left>
|
||||
</BorderPane>
|
||||
Loading…
x
Reference in New Issue
Block a user