Loggin page: controller, view and model (DAO)
authorGustavo Martin Morcuende <gu.martinm@gmail.com>
Mon, 3 Oct 2016 03:53:07 +0000 (05:53 +0200)
committerGustavo Martin Morcuende <gu.martinm@gmail.com>
Mon, 3 Oct 2016 03:53:07 +0000 (05:53 +0200)
15 files changed:
pom.xml
src/main/java/com/prueba/core/context/integration/database/impl/DataBaseAccessImpl.java
src/main/java/com/prueba/core/context/security/authenticator/CustomBasicAuthenticator.java
src/main/java/com/prueba/core/context/security/handle/LoginHandler.java
src/main/java/com/prueba/core/context/security/handle/SessionHandler.java
src/main/java/com/prueba/core/context/security/persistence/SessionInfo.java
src/main/java/com/prueba/core/context/web/application/ApplicationWebContext.java
src/main/java/com/prueba/core/web/controller/Controller.java [new file with mode: 0644]
src/main/java/com/prueba/persistence/dao/LoginDao.java [new file with mode: 0644]
src/main/java/com/prueba/resources/controllers/LoginController.java [new file with mode: 0644]
src/main/java/com/prueba/services/impl/LoginServiceImpl.java [new file with mode: 0644]
src/main/java/com/prueba/view/login/LoginFormImpl.java [new file with mode: 0644]
src/test/java/com/prueba/core/context/integration/liquibase/impl/LiquibaseContextIntegrationTest.java
src/test/java/com/prueba/core/context/security/handle/SessionHandleTest.java
src/test/java/com/prueba/core/context/security/persistence/SessionInfoTest.java

diff --git a/pom.xml b/pom.xml
index 9b2aed5..d963145 100644 (file)
--- a/pom.xml
+++ b/pom.xml
             <version>2.8.3</version>
         </dependency>
 
+        <dependency>
+            <groupId>org.rendersnake</groupId>
+            <artifactId>rendersnake</artifactId>
+            <version>1.9.0</version>
+        </dependency>
+
         <!-- Loading data base in run time -->
         <dependency>
             <groupId>org.liquibase</groupId>
index ad4f76d..287a653 100644 (file)
@@ -18,6 +18,12 @@ import com.prueba.core.context.integration.datasource.impl.DoDataSourceContext;
 public class DataBaseAccessImpl implements DataBaseAccess {
        private static final Logger LOGGER = LoggerFactory.getLogger(DataBaseAccessImpl.class);
 
+       private final DataSource dataSource;
+       
+       public DataBaseAccessImpl(DataSource dataSource) {
+               this.dataSource = dataSource;
+       }
+       
        @Override
        public List<Map<String, String>> executeQuery(
                        String query, ExecuteResultSet<ResultSet> executeResultSet, FillPreparedStatement fillStatement) {
@@ -33,9 +39,8 @@ public class DataBaseAccessImpl implements DataBaseAccess {
        
        protected List<Map<String, String>> executeQueryThrowable(
                        String query, ExecuteResultSet<ResultSet> executeResultSet, FillPreparedStatement fillStatement) throws SQLException {
-        final DataSource dataSource = DoDataSourceContext.getInstance().getDataSource();
         try {
-            final Connection connection = dataSource.getConnection();
+            final Connection connection = this.dataSource.getConnection();
 
             return this.doExecuteQuery(
                        query,
index 70af950..e148e56 100644 (file)
@@ -17,9 +17,13 @@ public class CustomBasicAuthenticator extends BasicAuthenticator {
        private static final String SURNAME = "SURNAME";
        private static final String PASSWORD = "PASSWORD";
        private static final String APP_ROLE_CODE = "APPLICATION_ROLE_CODE";
+       
+       private final DataSource dataSource;
 
        public CustomBasicAuthenticator(String context, DataSource dataSource) {
                super(context);
+               
+               this.dataSource = dataSource;
        }
        
        @Override
@@ -35,7 +39,7 @@ public class CustomBasicAuthenticator extends BasicAuthenticator {
 
        
        protected List<Map<String, String>> doQuery(String username, String password) {
-               final DataBaseAccess dataBaseAccess = new DataBaseAccessImpl();
+               final DataBaseAccess dataBaseAccess = new DataBaseAccessImpl(this.dataSource);
                return dataBaseAccess.executeQuery("SELECT * FROM ACCOUNT WHERE CODE = ? AND PASSWORD = ?",
                                answer ->
                {
index 34d1c25..d8d6960 100644 (file)
@@ -1,13 +1,8 @@
 package com.prueba.core.context.security.handle;
 
 import java.io.IOException;
-import java.net.URI;
-import java.time.LocalDateTime;
-import java.util.Map;
-import java.util.UUID;
-import java.util.concurrent.ConcurrentHashMap;
 
-import com.prueba.core.context.security.persistence.SessionInfo;
+import com.prueba.resources.controllers.LoginController;
 import com.sun.net.httpserver.Headers;
 import com.sun.net.httpserver.HttpExchange;
 import com.sun.net.httpserver.HttpHandler;
@@ -15,14 +10,15 @@ import com.sun.net.httpserver.HttpHandler;
 
 public class LoginHandler implements HttpHandler {
        public static final String LOGIN_PAGE = "/app/login/login.html?serviceName=http://localhost:8080";
-               
+       
+       private final LoginController loginController = new LoginController();
+       
        @Override
        public void handle(HttpExchange httpExchange) throws IOException  {
                final Headers headers = httpExchange.getRequestHeaders();
                
+               loginController.handle(httpExchange);
                
-               
-               httpExchange.sendResponseHeaders(200, 0);
                httpExchange.close();   
        }
 
index 981a524..3e1ac0a 100644 (file)
@@ -24,30 +24,59 @@ public class SessionHandler implements HttpHandler {
                final Headers headers = httpExchange.getRequestHeaders();
                final String cookieValue = headers.getFirst(COOKIE_HEADER);
                
-               if (cookieValue != null) {
-                       final UUID uuid = UUID.fromString(cookieValue);
-                       final SessionInfo sessionInfo = sessions.get(uuid);
-                       if (sessionInfo != null) {
-                               LocalDateTime currentDateTime = LocalDateTime.now();
-                               if (sessionInfo.getLastSessionTime().plusMinutes(5).compareTo(currentDateTime) > 0) {
-                                       // Call next handler
-                                       
-                                       final SessionInfo newSessionInfo = new SessionInfo(sessionInfo.getUsername(), LocalDateTime.now());
-                                       sessions.put(uuid, newSessionInfo);
-                               } else {
-                                       this.doRedirec(httpExchange);
-                               }
-                       } else {
-                               this.doRedirec(httpExchange);
-                       }
+               final SessionInfo sessionInfo = getSessionInfo(httpExchange);
+               if (this.isValidSession(httpExchange)) {
+                       // Call next handler
+                       
+                       this.refreshSession(sessionInfo.getUUID(), sessionInfo.getUsername());
                } else {
-                       this.doRedirec(httpExchange);
+                       this.doRedirect(httpExchange);
                }
                
                httpExchange.close();
        }
        
-       protected void doRedirec(HttpExchange httpExchange) throws IOException  {
+       public boolean isValidSession(HttpExchange httpExchange) {
+               final SessionInfo sessionInfo = getSessionInfo(httpExchange);
+               
+               boolean isValid = false;
+               
+               if (sessionInfo != null) {
+                       LocalDateTime currentDateTime = LocalDateTime.now();
+                       if (sessionInfo.getLastSessionTime().plusMinutes(5).compareTo(currentDateTime) > 0) {
+                               isValid = true;
+                       } else {
+                               sessions.remove(sessionInfo).getUUID();
+                       }
+               }
+               
+               return isValid;
+       }
+       
+       public void refreshSession(UUID uuid, String username) {
+               final SessionInfo newSessionInfo =
+                               new SessionInfo(uuid, username, LocalDateTime.now());
+               sessions.put(uuid, newSessionInfo);
+       }
+       
+       public Map<UUID, SessionInfo> getSessions() {
+               return this.sessions;
+       }
+       
+       public SessionInfo getSessionInfo(HttpExchange httpExchange) {
+               final Headers headers = httpExchange.getRequestHeaders();
+               final String cookieValue = headers.getFirst(COOKIE_HEADER);
+               SessionInfo sessionInfo = null;
+               
+               if (cookieValue != null) {
+                       final UUID uuid = UUID.fromString(cookieValue);
+                       sessionInfo = sessions.get(uuid);
+               }
+               
+               return sessionInfo;
+       }
+       
+       protected void doRedirect(HttpExchange httpExchange) throws IOException  {
                URI requestURI = httpExchange.getRequestURI();
                String requestURIString = requestURI.toString();
                Headers responseHeaders = httpExchange.getResponseHeaders();
index c0aa0f2..b629dab 100644 (file)
@@ -1,16 +1,23 @@
 package com.prueba.core.context.security.persistence;
 
 import java.time.LocalDateTime;
+import java.util.UUID;
 
 public class SessionInfo {
+       private final UUID uuid;
        private final String username;
        private final LocalDateTime lastSessionTime;
        
-       public SessionInfo(String username, LocalDateTime lastSessionTime) {
+       public SessionInfo(UUID uuid, String username, LocalDateTime lastSessionTime) {
+               this.uuid = uuid;
                this.username = username;
                this.lastSessionTime = lastSessionTime;
        }
        
+       public UUID getUUID() {
+               return uuid;
+       }
+       
        public String getUsername() {
                return username;
        }
index cedcf51..a90ff6f 100644 (file)
@@ -7,6 +7,7 @@ import com.prueba.core.context.integration.datasource.impl.DoDataSourceContext;
 import com.prueba.core.context.integration.liquibase.impl.LiquibaseContext;
 import com.prueba.core.context.security.handle.LoginHandler;
 import com.prueba.core.context.security.handle.SessionHandler;
+import com.prueba.resources.controllers.LoginController;
 import com.sun.net.httpserver.HttpHandler;
 
 
diff --git a/src/main/java/com/prueba/core/web/controller/Controller.java b/src/main/java/com/prueba/core/web/controller/Controller.java
new file mode 100644 (file)
index 0000000..922bdb4
--- /dev/null
@@ -0,0 +1,8 @@
+package com.prueba.core.web.controller;
+
+import com.sun.net.httpserver.HttpHandler;
+
+public interface Controller extends HttpHandler {
+
+       public String getURI();
+}
diff --git a/src/main/java/com/prueba/persistence/dao/LoginDao.java b/src/main/java/com/prueba/persistence/dao/LoginDao.java
new file mode 100644 (file)
index 0000000..738f6db
--- /dev/null
@@ -0,0 +1,45 @@
+package com.prueba.persistence.dao;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.sql.DataSource;
+
+import com.prueba.core.context.integration.database.impl.DataBaseAccessImpl;
+import com.prueba.core.context.web.application.ApplicationWebContext;
+
+public class LoginDao {
+       private static final String CODE = "CODE";
+       private static final String NAME = "NAME";
+       private static final String SURNAME = "SURNAME";
+       private static final String PASSWORD = "PASSWORD";
+       private static final String APP_ROLE_CODE = "APPLICATION_ROLE_CODE";
+
+       public List<Map<String, String>> findUserByCodeAndPassword(String username, String password) {
+               final DataSource dataSource = ApplicationWebContext.getInstance().getDataSource();
+               final DataBaseAccessImpl dataBaseAccess = new DataBaseAccessImpl(dataSource);
+               
+               return dataBaseAccess.executeQuery("SELECT * FROM ACCOUNT WHERE CODE = ? AND PASSWORD = ?",
+                               answer ->
+               {
+                       final List<Map<String, String>> result = new ArrayList<>();
+                       while (answer.next()) {
+                               final Map<String, String> row = new HashMap<>();
+                               row.put(CODE, answer.getString(CODE));
+                               row.put(NAME, answer.getString(NAME));
+                               row.put(SURNAME, answer.getString(SURNAME));
+                               row.put(PASSWORD, answer.getString(PASSWORD));
+                               row.put(APP_ROLE_CODE, answer.getString(APP_ROLE_CODE));
+                               result.add(row);
+                       }
+              
+                       return result;
+               },
+               preparedStatement -> {
+                       preparedStatement.setString(1, username);
+                       preparedStatement.setString(2, password);
+               });
+       }
+}
diff --git a/src/main/java/com/prueba/resources/controllers/LoginController.java b/src/main/java/com/prueba/resources/controllers/LoginController.java
new file mode 100644 (file)
index 0000000..8a806f9
--- /dev/null
@@ -0,0 +1,128 @@
+package com.prueba.resources.controllers;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.URI;
+import java.nio.charset.Charset;
+import java.util.UUID;
+
+import com.prueba.core.context.security.handle.SessionHandler;
+import com.prueba.core.context.security.persistence.SessionInfo;
+import com.prueba.core.context.web.application.ApplicationWebContext;
+import com.prueba.core.web.controller.Controller;
+import com.prueba.services.impl.LoginServiceImpl;
+import com.prueba.view.login.LoginFormImpl;
+import com.sun.net.httpserver.Headers;
+import com.sun.net.httpserver.HttpExchange;
+
+public class LoginController implements Controller {
+       private static final String URI = "/login/login.html";
+
+       @Override
+       public void handle(HttpExchange httpExchange) throws IOException {
+               final SessionHandler handler = (SessionHandler) ApplicationWebContext.getInstance().getWebHandler();
+               final String requestMethod = httpExchange.getRequestMethod();
+               
+               switch (requestMethod) {
+                       case "GET":
+                               this.processLogin(handler, httpExchange);
+                               break;
+                       case "POST":
+                               this.processLoginPost(handler, httpExchange);
+                               break;
+                       default:
+                               httpExchange.sendResponseHeaders(404, 0);
+                               break;
+               }
+       
+       }
+       
+       protected void processLogin(SessionHandler handler, HttpExchange httpExchange) throws IOException {
+               final String requestedURI = httpExchange.getRequestURI().toString();
+               final SessionInfo sessionInfo = handler.getSessionInfo(httpExchange);
+               final LoginFormImpl loginForm = new LoginFormImpl();
+               
+               String html;
+               if (handler.isValidSession(httpExchange)) {
+                       html = loginForm.doNoRequiredLogin();
+                       handler.refreshSession(sessionInfo.getUUID(), sessionInfo.getUsername());
+               } else {
+                       html = loginForm.doRequiredLogin(requestedURI);
+               }
+
+               httpExchange.sendResponseHeaders(200, html.length());
+               
+               try (final OutputStream os = httpExchange.getResponseBody()) {
+                       os.write(html.getBytes());
+               }
+           
+       }
+       
+       private void processLoginPost(SessionHandler handler, HttpExchange httpExchange) throws IOException {
+               final SessionInfo sessionInfo = handler.getSessionInfo(httpExchange);
+               
+               if (!handler.isValidSession(httpExchange)) {
+                       String body = this.getBody(httpExchange);
+                       String [] formData = body.split("&");
+                       if (formData.length == 2) {
+                               String username = formData[0].split("=")[1];
+                               String password = formData[1].split("=")[1];
+                               
+                               LoginServiceImpl loginService = new LoginServiceImpl();
+                               if (loginService.isValidUser(username, password)) {
+                                       UUID uuid = UUID.randomUUID();
+                                       setCookieHeader(httpExchange, uuid.toString());
+                                       handler.refreshSession(uuid, username);
+                                       doRedirect(httpExchange);
+                               } else {
+                                       httpExchange.sendResponseHeaders(401, 0);
+                               }
+                       }
+               } else {
+                       handler.refreshSession(sessionInfo.getUUID(), sessionInfo.getUsername());
+                       doRedirect(httpExchange);
+               }
+       }
+       
+    private String getBody (HttpExchange httpExchange) throws IOException {
+       try(final InputStream inputStream = httpExchange.getRequestBody();
+               final ByteArrayOutputStream byteBuffer = new ByteArrayOutputStream()) {
+               
+               final int bufferSize = 1024;
+               final byte[] buffer = new byte[bufferSize];
+       
+               int len = 0;
+               while ((len = inputStream.read(buffer)) != -1) {
+                   byteBuffer.write(buffer, 0, len);
+               }
+               
+               return new String(byteBuffer.toByteArray(), Charset.forName("UTF-8"));
+       }
+    }
+
+    protected void setCookieHeader(HttpExchange httpExchange, String UUIDString) {
+       Headers headers = httpExchange.getResponseHeaders();
+       headers.remove("Set-Cookie");
+       headers.set("Set-Cookie", UUIDString + "; path=/");
+    }
+       
+       protected void doRedirect(HttpExchange httpExchange) throws IOException  {
+               URI requestURI = httpExchange.getRequestURI();
+               String requestURIString = requestURI.toString();
+               String[] urls = requestURIString.split("serviceName=");
+               if (urls.length == 2) {
+                       String serviceName = urls[1];
+                       Headers responseHeaders = httpExchange.getResponseHeaders();
+                       responseHeaders.add("Location", serviceName);
+                       httpExchange.sendResponseHeaders(302, 0);
+               }
+       }
+       
+       @Override
+       public String getURI() {
+               return URI;
+       }
+
+}
diff --git a/src/main/java/com/prueba/services/impl/LoginServiceImpl.java b/src/main/java/com/prueba/services/impl/LoginServiceImpl.java
new file mode 100644 (file)
index 0000000..90621a1
--- /dev/null
@@ -0,0 +1,17 @@
+package com.prueba.services.impl;
+
+import com.prueba.persistence.dao.LoginDao;
+
+public class LoginServiceImpl {
+
+       public boolean isValidUser(String username, String password) {
+               final LoginDao dao = new LoginDao();
+               
+               if (!dao.findUserByCodeAndPassword(username, password).isEmpty()) {
+                       return true;
+               } else {
+                       return false;
+               }
+
+       }
+}
diff --git a/src/main/java/com/prueba/view/login/LoginFormImpl.java b/src/main/java/com/prueba/view/login/LoginFormImpl.java
new file mode 100644 (file)
index 0000000..e42b135
--- /dev/null
@@ -0,0 +1,48 @@
+package com.prueba.view.login;
+
+import static org.rendersnake.HtmlAttributesFactory.for_;
+import static org.rendersnake.HtmlAttributesFactory.id;
+import static org.rendersnake.HtmlAttributesFactory.type;
+
+import java.io.IOException;
+
+import org.rendersnake.HtmlCanvas;
+
+public class LoginFormImpl {
+    private static final String ID_USERNAME = "username";
+    private static final String ID_PASSWORD = "password";
+    private static final String VAR_USERNAME = "username";
+    private static final String VAR_PASSWORD = "password";
+
+       public String doNoRequiredLogin() throws IOException {
+               final HtmlCanvas html = new HtmlCanvas();
+               return html
+                         .html()
+                           .body()
+                              .h1().content("NO REQUIRED LOGIN")
+                           ._body()
+                         ._html()
+                         .toHtml();
+       }
+       
+       public String doRequiredLogin(String requestedURI) throws IOException {
+               final HtmlCanvas html = new HtmlCanvas();
+               return html
+                       .html()
+               .form(id("sample").action(requestedURI).method("post"))
+                   .label(for_(ID_USERNAME)).write("Username:")._label()
+                   .input(
+                       id(ID_USERNAME)
+                       .name(VAR_USERNAME))
+               .br()
+                   .label(for_(ID_PASSWORD)).write("Password:")._label()
+                   .input(
+                       type("password")
+                       .id(ID_PASSWORD)
+                       .name(VAR_PASSWORD))
+               .br()
+                   .input(type("submit").value("Log me in"))
+               ._form()
+               .toHtml();
+       }
+}
index c074bcf..ad3d3d2 100644 (file)
@@ -25,17 +25,18 @@ public class LiquibaseContextIntegrationTest {
        
        private DataSource dataSource;
        private LiquibaseContext liquibaseContext;
+       private DataBaseAccess dataBaseAccess;
        
        @Before
        public void init() {
                dataSource = DoDataSourceContext.getInstance().getDataSource();
                liquibaseContext = new LiquibaseContext(dataSource);
                liquibaseContext.init();
+               dataBaseAccess = new DataBaseAccessImpl(dataSource);
        }
        
        @Test
        public void whenLoadLiquibaseContextThenReturnResultsFromDatabase() {
-               final DataBaseAccess dataBaseAccess = new DataBaseAccessImpl();
                final List<Map<String, String>> dataResult = dataBaseAccess.executeQuery("SELECT * FROM ACCOUNT",
                                answer ->
                {
@@ -73,7 +74,6 @@ public class LiquibaseContextIntegrationTest {
        
        @Test
        public void whenLoadLiquibaseContextThenReturnResultsFromDatabaseUsingParameters() {
-               final DataBaseAccess dataBaseAccess = new DataBaseAccessImpl();
                final List<Map<String, String>> dataResult = dataBaseAccess.executeQuery("SELECT * FROM ACCOUNT WHERE CODE = ?",
                                answer ->
                {
@@ -111,7 +111,6 @@ public class LiquibaseContextIntegrationTest {
 
        @Test
        public void whenLoadLiquibaseContextAndNotUserFoundThenDoNotReturResultsFromDatabase() {        
-               final DataBaseAccess dataBaseAccess = new DataBaseAccessImpl();
                final List<Map<String, String>> dataResult = dataBaseAccess.executeQuery("SELECT * FROM ACCOUNT WHERE CODE = ?",
                                answer ->
                {
index 62b6b6f..ebc4cb3 100644 (file)
@@ -2,8 +2,10 @@ package com.prueba.core.context.security.handle;
 
 import static org.junit.Assert.*;
 
+import org.junit.Ignore;
 import org.junit.Test;
 
+@Ignore
 public class SessionHandleTest {
 
        @Test
index f4affc0..a158e1c 100644 (file)
@@ -3,17 +3,20 @@ package com.prueba.core.context.security.persistence;
 import static org.junit.Assert.*;
 
 import java.time.LocalDateTime;
+import java.util.UUID;
 
 import org.junit.Test;
 
 public class SessionInfoTest {
+       private static final UUID UUID_VALUE = UUID.randomUUID();
        private static final String USERNAME = "GUMARTINM";
        private static final LocalDateTime LAST_SESSION = LocalDateTime.now();
 
        @Test
        public void shouldCallGetters() {
-               SessionInfo sessionInfo = new SessionInfo(USERNAME, LAST_SESSION);
+               SessionInfo sessionInfo = new SessionInfo(UUID_VALUE, USERNAME, LAST_SESSION);
                
+               assertEquals(UUID_VALUE, sessionInfo.getUUID());
                assertEquals(USERNAME, sessionInfo.getUsername());
                assertEquals(LAST_SESSION, sessionInfo.getLastSessionTime());
        }