From 3b69bbcfe7c04a2a4f63e5672dcd55ea77724fac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Cort=C3=A9s?= Date: Mon, 27 May 2019 12:06:23 -0400 Subject: [PATCH] Agregado sistema de logeo Es bastante bonito, me gusta la logica esta en su propio package ya que no encontraba que estuviera 100% relacionado con el resto de controlardores y vistas, dado que no heredan de las clases BaseController y BasePanel El main obtiene el resultado del logeo a travez de un listener customizado el cual entrega por evento un LoggedEvent, que contiene el usuario que fue logeado, de tal manera que se lo pueda entregar al resto de las vistas. Me costo 2 dias encontrar la combianacion perfecta de cosas para que esto funcionara llegando al final a la solucion de un listener superior. Pareciera que swing al no ejecutarse en el mismo thread no puedo tener un listener que cambie una variable de la instacia, que termine la ejecucion de swing y despues desde la clase superior leer la variable de instancia, ya que no parece que alcance a actualizarse en el thread principal. --- biblioteca.vpp | Bin 898048 -> 898048 bytes script.sql | 20 +++- src/main/java/xyz/danielcortes/App.java | 15 ++- .../controllers/LaunchController.java | 5 +- .../java/xyz/danielcortes/framework/Hash.java | 21 ++++ .../danielcortes/framework/LoggedEvent.java | 31 ++++++ .../framework/LoggedListener.java | 15 +++ .../danielcortes/login/LoginController.java | 66 ++++++++++++ .../xyz/danielcortes/login/LoginPanel.form | 75 +++++++++++++ .../xyz/danielcortes/login/LoginPanel.java | 99 ++++++++++++++++++ .../java/xyz/danielcortes/models/Usuario.java | 67 ++++++++++++ .../repository/UsuarioRepository.java | 22 ++++ 12 files changed, 426 insertions(+), 10 deletions(-) create mode 100644 src/main/java/xyz/danielcortes/framework/Hash.java create mode 100644 src/main/java/xyz/danielcortes/framework/LoggedEvent.java create mode 100644 src/main/java/xyz/danielcortes/framework/LoggedListener.java create mode 100644 src/main/java/xyz/danielcortes/login/LoginController.java create mode 100644 src/main/java/xyz/danielcortes/login/LoginPanel.form create mode 100644 src/main/java/xyz/danielcortes/login/LoginPanel.java create mode 100644 src/main/java/xyz/danielcortes/models/Usuario.java create mode 100644 src/main/java/xyz/danielcortes/repository/UsuarioRepository.java diff --git a/biblioteca.vpp b/biblioteca.vpp index 34f5a522731009550e32b73cf78f917430743567..682d42d17c76d03dbb6f4d174c571ef89ea9107f 100644 GIT binary patch delta 37402 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 { + LaunchController launchController = new LaunchController(e.getUser()); + launchController.run(); + }); } - private static void setupLookAndFeel(){ - System.setProperty("awt.useSystemAAFontSettings","lcd"); + private static void setupLookAndFeel() { + System.setProperty("awt.useSystemAAFontSettings", "lcd"); System.setProperty("swing.aatext", "true"); try { String windows = "com.sun.java.swing.plaf.windows.WindowsLookAndFeel"; - String motif ="com.sun.java.swing.plaf.motif.MotifLookAndFeel"; + String motif = "com.sun.java.swing.plaf.motif.MotifLookAndFeel"; String nimbus = "javax.swing.plaf.nimbus.NimbusLookAndFeel"; String metal = "javax.swing.plaf.metal.MetalLookAndFeel"; String gtk = "com.sun.java.swing.plaf.gtk.GTKLookAndFeel"; diff --git a/src/main/java/xyz/danielcortes/controllers/LaunchController.java b/src/main/java/xyz/danielcortes/controllers/LaunchController.java index 725d5c5..85ed4c8 100644 --- a/src/main/java/xyz/danielcortes/controllers/LaunchController.java +++ b/src/main/java/xyz/danielcortes/controllers/LaunchController.java @@ -29,6 +29,7 @@ import xyz.danielcortes.controllers.libro.LibroUpdateController; import xyz.danielcortes.controllers.libro.LibroViewController; import xyz.danielcortes.framework.BaseController; import xyz.danielcortes.framework.PanelName; +import xyz.danielcortes.models.Usuario; import xyz.danielcortes.views.LaunchFrame; import xyz.danielcortes.views.autor.AutorCreatePanel; import xyz.danielcortes.views.autor.AutorSearchPanel; @@ -55,8 +56,10 @@ public class LaunchController { private LaunchFrame frame; private Map controllers; + private Usuario user; - public LaunchController() { + public LaunchController(Usuario user) { + this.user = user; this.controllers = new HashMap<>(); } diff --git a/src/main/java/xyz/danielcortes/framework/Hash.java b/src/main/java/xyz/danielcortes/framework/Hash.java new file mode 100644 index 0000000..f5394f5 --- /dev/null +++ b/src/main/java/xyz/danielcortes/framework/Hash.java @@ -0,0 +1,21 @@ +package xyz.danielcortes.framework; + +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + +public class Hash { + + private static MessageDigest sha; + + static { + try { + sha = MessageDigest.getInstance("SHA-256"); + } catch (NoSuchAlgorithmException e) { + e.printStackTrace(); + } + } + + public static byte[] sha256(byte[] toHash) { + return sha.digest(toHash); + } +} diff --git a/src/main/java/xyz/danielcortes/framework/LoggedEvent.java b/src/main/java/xyz/danielcortes/framework/LoggedEvent.java new file mode 100644 index 0000000..075e8fb --- /dev/null +++ b/src/main/java/xyz/danielcortes/framework/LoggedEvent.java @@ -0,0 +1,31 @@ +package xyz.danielcortes.framework; + +import java.util.EventObject; +import xyz.danielcortes.models.Usuario; + +/** + * Un evento que indica que un usuario a sido logeado + */ +public class LoggedEvent extends EventObject { + + private Usuario user; + + /** + * Crea el objeto y almacena los datos entregados + * + * El metodo lanza un {@code IllegalArgumentException} en caso que + * {@code source} y {@code user} sean nulos. + * + * @param source El objeto en el que el evento se origino + * @param user El usuario que fue logeado en el sistema + * @throws IllegalArgumentException if source is null + */ + public LoggedEvent(Object source, Usuario user) { + super(source); + this.user = user; + } + + public Usuario getUser() { + return user; + } +} diff --git a/src/main/java/xyz/danielcortes/framework/LoggedListener.java b/src/main/java/xyz/danielcortes/framework/LoggedListener.java new file mode 100644 index 0000000..98766e3 --- /dev/null +++ b/src/main/java/xyz/danielcortes/framework/LoggedListener.java @@ -0,0 +1,15 @@ +package xyz.danielcortes.framework; + +import java.util.EventListener; + +/** + * La interfaz para recibir acciones de logeo de un usuario + */ +public interface LoggedListener extends EventListener { + + /** + * Se invoca cuando un usuario se logra logear al sistema. + * @param e El evento que se ejecutara + */ + public void loginTry(LoggedEvent e); +} diff --git a/src/main/java/xyz/danielcortes/login/LoginController.java b/src/main/java/xyz/danielcortes/login/LoginController.java new file mode 100644 index 0000000..e611689 --- /dev/null +++ b/src/main/java/xyz/danielcortes/login/LoginController.java @@ -0,0 +1,66 @@ +package xyz.danielcortes.login; + +import java.awt.Dimension; +import java.nio.charset.StandardCharsets; +import java.util.Arrays; +import java.util.Optional; +import javax.swing.JFrame; +import javax.swing.WindowConstants; +import xyz.danielcortes.framework.Hash; +import xyz.danielcortes.framework.LoggedEvent; +import xyz.danielcortes.framework.LoggedListener; +import xyz.danielcortes.models.Usuario; +import xyz.danielcortes.repository.UsuarioRepository; + +public class LoginController { + + private JFrame frame; + private LoginPanel view; + private UsuarioRepository repository; + private LoggedListener loggedListener; + + public LoginController(LoginPanel view) { + this.view = view; + this.repository = new UsuarioRepository(); + this.setupListeners(); + this.createFrame(); + } + + private void setupListeners() { + this.view.getUserField().addActionListener(e -> login()); + this.view.getPassField().addActionListener(e -> login()); + this.view.getLoginButton().addActionListener(e -> login()); + } + + private void login() { + String name = this.view.getUserField().getText(); + + Optional optionalUser = this.repository.getByName(name); + if (optionalUser.isEmpty()) + return; + + Usuario user = optionalUser.get(); + byte[] pass = Hash.sha256(new String(this.view.getPassField().getPassword()).getBytes(StandardCharsets.UTF_8)); + if (Arrays.equals(pass, user.getPassword())) { + this.frame.dispose(); + loggedListener.loginTry(new LoggedEvent(this, user)); + } + } + + private void createFrame() { + Dimension dimension = new Dimension(400, 400); + this.frame = new JFrame(); + this.frame.setSize(dimension); + this.frame.setMinimumSize(dimension); + this.frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); + this.frame.setLocationRelativeTo(null); + this.frame.setTitle("Login"); + this.frame.setContentPane(this.view.getContentPane()); + this.frame.setVisible(true); + } + + public void setLoggedListener(LoggedListener listener) { + this.loggedListener = listener; + } + +} diff --git a/src/main/java/xyz/danielcortes/login/LoginPanel.form b/src/main/java/xyz/danielcortes/login/LoginPanel.form new file mode 100644 index 0000000..06f337d --- /dev/null +++ b/src/main/java/xyz/danielcortes/login/LoginPanel.form @@ -0,0 +1,75 @@ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/src/main/java/xyz/danielcortes/login/LoginPanel.java b/src/main/java/xyz/danielcortes/login/LoginPanel.java new file mode 100644 index 0000000..7eb14bc --- /dev/null +++ b/src/main/java/xyz/danielcortes/login/LoginPanel.java @@ -0,0 +1,99 @@ +package xyz.danielcortes.login; + +import com.intellij.uiDesigner.core.GridConstraints; +import com.intellij.uiDesigner.core.GridLayoutManager; +import com.intellij.uiDesigner.core.Spacer; +import java.awt.Dimension; +import java.awt.Insets; +import javax.swing.JButton; +import javax.swing.JComponent; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JPasswordField; +import javax.swing.JTextField; + +public class LoginPanel { + + private JButton loginButton; + private JPanel contentPane; + private JPasswordField passField; + private JTextField userField; + + public JButton getLoginButton() { + return loginButton; + } + + public JPanel getContentPane() { + return contentPane; + } + + public JPasswordField getPassField() { + return passField; + } + + public JTextField getUserField() { + return userField; + } + + { +// GUI initializer generated by IntelliJ IDEA GUI Designer +// >>> IMPORTANT!! <<< +// DO NOT EDIT OR ADD ANY CODE HERE! + $$$setupUI$$$(); + } + + /** + * Method generated by IntelliJ IDEA GUI Designer >>> IMPORTANT!! <<< DO NOT edit this method OR call it in your code! + * + * @noinspection ALL + */ + private void $$$setupUI$$$() { + contentPane = new JPanel(); + contentPane.setLayout(new GridLayoutManager(7, 3, new Insets(20, 20, 20, 20), -1, -1)); + loginButton = new JButton(); + loginButton.setText("Login"); + contentPane.add(loginButton, new GridConstraints(5, 1, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_NONE, + GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, new Dimension(150, -1), + null, 0, false)); + passField = new JPasswordField(); + contentPane.add(passField, new GridConstraints(4, 1, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_HORIZONTAL, + GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED, null, new Dimension(300, -1), + null, 0, false)); + userField = new JTextField(); + contentPane.add(userField, new GridConstraints(2, 1, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_HORIZONTAL, + GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED, null, new Dimension(300, -1), + null, 0, false)); + final JLabel label1 = new JLabel(); + label1.setText("Usuario:"); + contentPane.add(label1, new GridConstraints(1, 1, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, + GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + final JLabel label2 = new JLabel(); + label2.setText("ContraseƱa:"); + contentPane.add(label2, new GridConstraints(3, 1, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, + GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + final Spacer spacer1 = new Spacer(); + contentPane.add(spacer1, + new GridConstraints(6, 1, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_VERTICAL, 1, GridConstraints.SIZEPOLICY_WANT_GROW, null, + null, null, 0, false)); + final Spacer spacer2 = new Spacer(); + contentPane.add(spacer2, + new GridConstraints(6, 2, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, 1, null, + null, null, 0, false)); + final Spacer spacer3 = new Spacer(); + contentPane.add(spacer3, + new GridConstraints(6, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, 1, null, + null, null, 0, false)); + final Spacer spacer4 = new Spacer(); + contentPane.add(spacer4, + new GridConstraints(0, 1, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_VERTICAL, 1, GridConstraints.SIZEPOLICY_WANT_GROW, null, + null, null, 0, false)); + } + + /** + * @noinspection ALL + */ + public JComponent $$$getRootComponent$$$() { + return contentPane; + } + +} diff --git a/src/main/java/xyz/danielcortes/models/Usuario.java b/src/main/java/xyz/danielcortes/models/Usuario.java new file mode 100644 index 0000000..1c491db --- /dev/null +++ b/src/main/java/xyz/danielcortes/models/Usuario.java @@ -0,0 +1,67 @@ +package xyz.danielcortes.models; + +import java.util.Arrays; +import java.util.Objects; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Table; + +@Entity +@Table(name = "usuario") +public class Usuario { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Integer id; + + @Column(name = "nombre") + private String nombre; + + @Column(name = "password", columnDefinition = "varbinary(2000)") + private byte[] password; + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getNombre() { + return nombre; + } + + public void setNombre(String nombre) { + this.nombre = nombre; + } + + public byte[] getPassword() { + return password; + } + + public void setPassword(byte[] password) { + this.password = password; + } + + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (!(o instanceof Usuario)) + return false; + Usuario usuario = (Usuario) o; + return Objects.equals(id, usuario.id) && + Objects.equals(nombre, usuario.nombre) && + Arrays.equals(password, usuario.password); + } + + @Override + public int hashCode() { + int result = Objects.hash(id, nombre); + result = 31 * result + Arrays.hashCode(password); + return result; + } +} diff --git a/src/main/java/xyz/danielcortes/repository/UsuarioRepository.java b/src/main/java/xyz/danielcortes/repository/UsuarioRepository.java new file mode 100644 index 0000000..317243c --- /dev/null +++ b/src/main/java/xyz/danielcortes/repository/UsuarioRepository.java @@ -0,0 +1,22 @@ +package xyz.danielcortes.repository; + +import java.util.Optional; +import javax.persistence.NoResultException; +import javax.persistence.TypedQuery; +import xyz.danielcortes.framework.BaseRepository; +import xyz.danielcortes.models.Usuario; + +public class UsuarioRepository extends BaseRepository { + + public Optional getByName(String name) { + TypedQuery query = em.createQuery("SELECT u FROM Usuario u WHERE nombre = :nombre", Usuario.class); + query.setParameter("nombre", name); + + try{ + Usuario user = query.getSingleResult(); + return Optional.of(user); + }catch (NoResultException e){ + return Optional.empty(); + } + } +}