diff --git a/.vscode/launch.json b/.vscode/launch.json index 2f15ef6..e3066b1 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -13,7 +13,7 @@ "request": "launch", "mainClass": "com.timesheet.Main", "projectName": "server", - "vmArgs": "-DXms512m -DXmx512m -DKEYSTORE_PATH=./arquivos/certs/keystore.jks -DROOT_PATH=. -DDB_URL=jdbc:h2:./timesheet -DDB_USER=sa -DDB_PASS=sa -DSERVICE_PORT=8000 -DSERVICE_BIND=localhost" + "vmArgs": "-DXms512m -DXmx512m -DKEYSTORE_PATH=./arquivos/certs/keystore.jks -DROOT_PATH=. -DDB_URL=jdbc:h2:./timesheet -DDB_USER=sa -DDB_PASS=sa -DSERVICE_PORT=443 -DSERVICE_BIND=localhost" } ] } \ No newline at end of file diff --git a/app.css b/app.css index bc0be23..2994a0c 100644 --- a/app.css +++ b/app.css @@ -13,10 +13,18 @@ border-color: red; } -.vis-nested-group.toBreak { +.vis-nested-group.toBreak90 { background-color: lightgreen; } +.vis-nested-group.toBreak120 { + background-color: lightyellow; +} + +.vis-nested-group.toBreak150 { + background-color: lightcoral; +} + .vis-item.blue { background-color: blue; border-color: blue; diff --git a/app.js b/app.js index f264ca0..42f8ccd 100644 --- a/app.js +++ b/app.js @@ -98,6 +98,7 @@ var app = new Vue({ removerSheets: function (idSubGroup, event) { this.items.forEach(function (i) { if (i.selecionado) { + removerAvisoVisual(idSubGroup); items.remove(i.id); removeItem(i, 'I'); } @@ -160,8 +161,6 @@ var app = new Vue({ var items = new vis.DataSet([]); var groups = new vis.DataSet([]); -// items.on('*', itemsOn); -// groups.on('*', groupsOn); var timeline = null; var container = document.getElementById("TimeLine"); @@ -255,13 +254,19 @@ function actionFired(properties) { item.end = getMoment(); group = getGroupById(item.group); var diffMinutes = item.end.diff(item.start, 'minutes'); - if (group.className != 'toBreak' && item.typeOfWork === 'Work' && diffMinutes >= 90) { - group.className = 'toBreak'; + if (group.className != 'toBreak90' && item.typeOfWork === 'Work' && diffMinutes >= 90 && diffMinutes < 120) { + group.className = 'toBreak90'; groups.update(group); - } else if (group.className === 'toBreak' && item.typeOfWork === 'Work' && diffMinutes < 90) { + } else if (group.className != 'toBreak120' && item.typeOfWork === 'Work' && diffMinutes >= 120 && diffMinutes < 150) { + group.className = 'toBreak120'; + groups.update(group); + } else if (group.className != 'toBreak150' && item.typeOfWork === 'Work' && diffMinutes >= 150) { + group.className = 'toBreak150'; + groups.update(group); + } else if (group.className != 'p' && item.typeOfWork === 'Work' && diffMinutes < 90) { group.className = 'p'; groups.update(group); - } else if (group.className === 'toBreak' && item.typeOfWork != 'Work') { + } else if (group.className === 'p' && item.typeOfWork != 'Work') { group.className = 'p'; groups.update(group); } @@ -319,9 +324,16 @@ function checkme(component, idSubGroup) { var c = montarNome(subGrupo.id, subGrupo.employeeName, component.checked); groups.update({ id: idSubGroup, content: c, checked: !subGrupo.checked }); } +function removerAvisoVisual(idSubGroup) { + var g = groups.get(idSubGroup); + g.className = 'p'; + groups.update(g); + persistItem(g, 'G'); +} function closeLastItem(idSubGroup, hora, minuto) { if (typeof hora == 'undefined') hora = getHora(hora); if (typeof minuto == 'undefined') minuto = getMinuto(minuto); + removerAvisoVisual(idSubGroup); var item = getLastOpenItemBySubGroup(idSubGroup); if (item) { item.end = getMoment().hours(hora).minutes(minuto).seconds(0).milliseconds(0); @@ -407,7 +419,7 @@ function adicionar(name, sector, horaInicial, minutoInicial, horaFinal, minutoFi if (typeof name === 'undefined' || name == null || name.length <= 0) { return; } - var idSubGroup = groups.add({ employeeName: name, order: 0, checked: false })[0]; + var idSubGroup = groups.add({ employeeName: name, order: 0, checked: false, className: 'p' })[0]; var c = montarNome(idSubGroup, name, false); groups.update({ id: idSubGroup, content: c }); if (!horaInicial) horaInicial = 9; @@ -560,7 +572,7 @@ function updateDateItem(item) { var socket; if (window.WebSocket) { - var url = "wss://" + location.hostname + ":444/"; + var url = "wss://" + location.hostname + "/ws"; socket = new WebSocket(url); socket.onmessage = function (event) { var action = JSON.parse(event.data); diff --git a/compare-complete.json b/compare-complete.json deleted file mode 100644 index cbf2e3f..0000000 --- a/compare-complete.json +++ /dev/null @@ -1,98 +0,0 @@ -[ - { - "id": "Detail", - "content": "Detail", - "nestedGroups": [ - "1b0bcc37-0c30-46f0-a1f5-890bb08155d8", - "6e508516-3175-410a-a5a8-6242a94527de" - ] - }, - { - "id": "Wipedown", - "content": "Wipedown", - "nestedGroups": [ - "cbc0f40a-d5eb-4ed7-975f-6c647d843186", - "297c02ae-8421-42e1-8c52-3da8f702f004" - ] - }, - { - "id": "Prep", - "content": "Prep", - "nestedGroups": [ - "d881f26a-3a51-45d0-98d5-02e162714027", - "771a30a6-323f-49f6-a9a9-354d5253b9eb" - ] - }, - { - "id": "Cash and Sale", - "content": "Cash and Sale", - "nestedGroups": [ - "4b0747a3-be8a-4a9c-81a2-dd8ff561d4f5", - "06f4d22b-85d6-45c2-b02b-cfb52c5ad7b1" - ] - }, - { - "employeeName": "employee 01", - "order": 0, - "checked": false, - "id": "4b0747a3-be8a-4a9c-81a2-dd8ff561d4f5", - "content": "employee 01", - "nestedInGroup": "Cash and Sale" - }, - { - "employeeName": "employee 02", - "order": 0, - "checked": false, - "id": "d881f26a-3a51-45d0-98d5-02e162714027", - "content": "employee 02", - "nestedInGroup": "Prep" - }, - { - "employeeName": "employee 03", - "order": 0, - "checked": false, - "id": "1b0bcc37-0c30-46f0-a1f5-890bb08155d8", - "content": "employee 03", - "nestedInGroup": "Detail" - }, - { - "employeeName": "employee 04", - "order": 0, - "checked": false, - "id": "cbc0f40a-d5eb-4ed7-975f-6c647d843186", - "content": "employee 04", - "nestedInGroup": "Wipedown" - }, - { - "employeeName": "employee 05", - "order": 0, - "checked": false, - "id": "297c02ae-8421-42e1-8c52-3da8f702f004", - "content": "employee 05", - "nestedInGroup": "Wipedown" - }, - { - "employeeName": "employee 06", - "order": 0, - "checked": false, - "id": "6e508516-3175-410a-a5a8-6242a94527de", - "content": "employee 06", - "nestedInGroup": "Detail" - }, - { - "employeeName": "employee 07", - "order": 0, - "checked": false, - "id": "771a30a6-323f-49f6-a9a9-354d5253b9eb", - "content": "employee 07", - "nestedInGroup": "Prep" - }, - { - "employeeName": "employee 08", - "order": 0, - "checked": false, - "id": "06f4d22b-85d6-45c2-b02b-cfb52c5ad7b1", - "content": "employee 08", - "nestedInGroup": "Cash and Sale" - } -] \ No newline at end of file diff --git a/compare-unity.json b/compare-unity.json deleted file mode 100644 index cbf2e3f..0000000 --- a/compare-unity.json +++ /dev/null @@ -1,98 +0,0 @@ -[ - { - "id": "Detail", - "content": "Detail", - "nestedGroups": [ - "1b0bcc37-0c30-46f0-a1f5-890bb08155d8", - "6e508516-3175-410a-a5a8-6242a94527de" - ] - }, - { - "id": "Wipedown", - "content": "Wipedown", - "nestedGroups": [ - "cbc0f40a-d5eb-4ed7-975f-6c647d843186", - "297c02ae-8421-42e1-8c52-3da8f702f004" - ] - }, - { - "id": "Prep", - "content": "Prep", - "nestedGroups": [ - "d881f26a-3a51-45d0-98d5-02e162714027", - "771a30a6-323f-49f6-a9a9-354d5253b9eb" - ] - }, - { - "id": "Cash and Sale", - "content": "Cash and Sale", - "nestedGroups": [ - "4b0747a3-be8a-4a9c-81a2-dd8ff561d4f5", - "06f4d22b-85d6-45c2-b02b-cfb52c5ad7b1" - ] - }, - { - "employeeName": "employee 01", - "order": 0, - "checked": false, - "id": "4b0747a3-be8a-4a9c-81a2-dd8ff561d4f5", - "content": "employee 01", - "nestedInGroup": "Cash and Sale" - }, - { - "employeeName": "employee 02", - "order": 0, - "checked": false, - "id": "d881f26a-3a51-45d0-98d5-02e162714027", - "content": "employee 02", - "nestedInGroup": "Prep" - }, - { - "employeeName": "employee 03", - "order": 0, - "checked": false, - "id": "1b0bcc37-0c30-46f0-a1f5-890bb08155d8", - "content": "employee 03", - "nestedInGroup": "Detail" - }, - { - "employeeName": "employee 04", - "order": 0, - "checked": false, - "id": "cbc0f40a-d5eb-4ed7-975f-6c647d843186", - "content": "employee 04", - "nestedInGroup": "Wipedown" - }, - { - "employeeName": "employee 05", - "order": 0, - "checked": false, - "id": "297c02ae-8421-42e1-8c52-3da8f702f004", - "content": "employee 05", - "nestedInGroup": "Wipedown" - }, - { - "employeeName": "employee 06", - "order": 0, - "checked": false, - "id": "6e508516-3175-410a-a5a8-6242a94527de", - "content": "employee 06", - "nestedInGroup": "Detail" - }, - { - "employeeName": "employee 07", - "order": 0, - "checked": false, - "id": "771a30a6-323f-49f6-a9a9-354d5253b9eb", - "content": "employee 07", - "nestedInGroup": "Prep" - }, - { - "employeeName": "employee 08", - "order": 0, - "checked": false, - "id": "06f4d22b-85d6-45c2-b02b-cfb52c5ad7b1", - "content": "employee 08", - "nestedInGroup": "Cash and Sale" - } -] \ No newline at end of file diff --git a/index.html b/index.html index 81312e2..68348fc 100644 --- a/index.html +++ b/index.html @@ -79,7 +79,7 @@
- Versao 3.0 WebSocket + Versao 3.1 Cores
diff --git a/login.html b/login.html deleted file mode 100644 index cd9e743..0000000 --- a/login.html +++ /dev/null @@ -1,133 +0,0 @@ - - - - - - - - - - Campanario's System - - - -
- - -
-
-
- -
-
- -
-
- -
-
- Versao 2.2 toBreak -
-
-
-
- - - - - - -
-
-
-
-
-
-
- - -
-
- -
-
- - -
- -
- - - - - - - - - - - \ No newline at end of file diff --git a/service/server/pom.xml b/service/server/pom.xml index 76c08a0..b3cbf17 100644 --- a/service/server/pom.xml +++ b/service/server/pom.xml @@ -28,13 +28,13 @@ io.undertow undertow-core - 1.4.0.Final + 2.0.27.Final io.undertow undertow-servlet - 1.4.0.Final + 2.0.27.Final diff --git a/service/server/src/main/java/com/timesheet/Main.java b/service/server/src/main/java/com/timesheet/Main.java index 19e96a8..6a0a31b 100644 --- a/service/server/src/main/java/com/timesheet/Main.java +++ b/service/server/src/main/java/com/timesheet/Main.java @@ -11,13 +11,17 @@ import java.io.InputStream; import java.nio.file.Paths; import java.security.KeyStore; +import java.security.Principal; import java.security.SecureRandom; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; +import java.util.Arrays; +import java.util.Collections; import java.util.HashSet; +import java.util.List; import java.util.Set; import javax.net.ssl.HostnameVerifier; @@ -33,6 +37,17 @@ import org.h2.server.web.DbStarter; import io.undertow.Undertow; +import io.undertow.security.api.AuthenticationMechanism; +import io.undertow.security.api.AuthenticationMode; +import io.undertow.security.handlers.AuthenticationCallHandler; +import io.undertow.security.handlers.AuthenticationConstraintHandler; +import io.undertow.security.handlers.AuthenticationMechanismsHandler; +import io.undertow.security.handlers.SecurityInitialHandler; +import io.undertow.security.idm.Account; +import io.undertow.security.idm.Credential; +import io.undertow.security.idm.IdentityManager; +import io.undertow.security.idm.PasswordCredential; +import io.undertow.security.impl.BasicAuthenticationMechanism; import io.undertow.server.HttpHandler; import io.undertow.server.handlers.resource.PathResourceManager; import io.undertow.servlet.api.DeploymentInfo; @@ -63,14 +78,14 @@ public static void main(String[] args) throws Throwable { initializeServers(); } - private static void initializeServers() throws Throwable { + private static void initializeServers() throws Throwable { ServletInfo timeSheetServlet = servlet("TimeSheetServlet", TimeSheetServlet.class).addMapping("/ts"); ListenerInfo databaseListener = listener(DbStarter.class); DeploymentInfo servletBuilder = deployment().setClassLoader(Main.class.getClassLoader()).setContextPath("/") - .setDeploymentName("timesheet.war").setResourceManager(new PathResourceManager(Paths.get(Main.ROOT_PATH), 100)) + .setDeploymentName("timesheet.war") + .setResourceManager(new PathResourceManager(Paths.get(Main.ROOT_PATH), 100)) .addListener(databaseListener).addInitParameter("db.url", DB_URL).addInitParameter("db.user", DB_USER) - .addInitParameter("db.password", DB_PASS).addWelcomePage("index.html") - .addServlets(timeSheetServlet); + .addInitParameter("db.password", DB_PASS).addWelcomePage("index.html").addServlets(timeSheetServlet); DeploymentManager manager = defaultContainer().addDeployment(servletBuilder); manager.deploy(); HttpHandler servletHandler = null; @@ -78,16 +93,58 @@ private static void initializeServers() throws Throwable { servletHandler = manager.start(); } catch (ServletException e) { } + + IdentityManager identityManager = new IdentityManager() { + public Account verify(String id, Credential credential) { + if ("tsbro-admin".equals(id)) { + if (credential instanceof PasswordCredential) { + char[] password = ((PasswordCredential) credential).getPassword(); + char[] expectedPassword = "tsbro-admin".toCharArray(); + if (Arrays.equals(password, expectedPassword)) { + return new Account() { + HashSet roles = new HashSet(1); + public Set getRoles() { + if (roles.isEmpty()) { + roles.add("admin"); + } + return roles; + } + public Principal getPrincipal() { + return new Principal() { + public String getName() { + return "tsbro-admin"; + } + }; + } + }; + } + } + } + return null; + } + public Account verify(Credential credential) { + return null; + } + public Account verify(Account account) { + return account; + } + }; + + HttpHandler securityHandler = servletHandler; + securityHandler = new AuthenticationCallHandler(securityHandler); + securityHandler = new AuthenticationConstraintHandler(securityHandler); + final List mechanisms = Collections + .singletonList(new BasicAuthenticationMechanism("TimeSheet Brothers' System")); + securityHandler = new AuthenticationMechanismsHandler(securityHandler, mechanisms); + securityHandler = new SecurityInitialHandler(AuthenticationMode.PRO_ACTIVE, identityManager, securityHandler); + int port = Integer.parseInt(SERVICE_PORT); String host = SERVICE_BIND; Undertow httpServer = Undertow.builder().addHttpsListener(port, host, Main.getSSLContext()) - .setHandler(servletHandler).build(); - httpServer.start(); - - Undertow webSockerServer = Undertow.builder().addHttpsListener(Integer.parseInt(SERVICE_PORT) + 1, SERVICE_BIND, Main.getSSLContext()) - .setHandler(path().addPrefixPath("/", + .setHandler(path().addPrefixPath("/", servletHandler).addPrefixPath("/ws", new WebSocketProtocolHandshakeHandler(new WebSocketConnectionCallback() { Set channels = new HashSet(); + @Override public void onConnect(WebSocketHttpExchange exchange, WebSocketChannel channel) { channels.add(channel); @@ -108,8 +165,7 @@ protected void onFullTextMessage(WebSocketChannel channel, } }))) .build(); - webSockerServer.start(); - + httpServer.start(); } private static void initializeDatabase() { @@ -158,44 +214,43 @@ private static String initializeVariables(String variable) { return result; } - private static SSLContext getSSLContext() throws Throwable { - SSLContext sslContext = SSLContext.getDefault(); - sslContext = SSLContext.getInstance("TLSv1.2"); - String defaultAlgorithm = KeyManagerFactory.getDefaultAlgorithm(); + private static SSLContext getSSLContext() throws Throwable { + SSLContext sslContext = SSLContext.getDefault(); + sslContext = SSLContext.getInstance("TLSv1.2"); + String defaultAlgorithm = KeyManagerFactory.getDefaultAlgorithm(); KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(defaultAlgorithm); - + KeyStore localKeyStore = KeyStore.getInstance("JKS"); InputStream is = new FileInputStream(new File(Main.KEYSTORE_PATH)); localKeyStore.load(is, "".toCharArray()); - keyManagerFactory.init(localKeyStore, "".toCharArray()); - - KeyManager[] km = keyManagerFactory.getKeyManagers(); + keyManagerFactory.init(localKeyStore, "".toCharArray()); - TrustManager[] tm = new TrustManager[] { new X509TrustManager() { - public X509Certificate[] getAcceptedIssuers() { - return null; - } + KeyManager[] km = keyManagerFactory.getKeyManagers(); - public void checkClientTrusted(X509Certificate[] c, String a) throws CertificateException { - } + TrustManager[] tm = new TrustManager[] { new X509TrustManager() { + public X509Certificate[] getAcceptedIssuers() { + return null; + } - public void checkServerTrusted(X509Certificate[] c, String a) throws CertificateException { - } - } }; - SecureRandom sr = new SecureRandom(); - sslContext.init(km, tm, sr); - HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() { - public boolean verify(String h, SSLSession s) { - return true; - } - }); + public void checkClientTrusted(X509Certificate[] c, String a) throws CertificateException { + } - return sslContext; - } + public void checkServerTrusted(X509Certificate[] c, String a) throws CertificateException { + } + } }; + SecureRandom sr = new SecureRandom(); + sslContext.init(km, tm, sr); + HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() { + public boolean verify(String h, SSLSession s) { + return true; + } + }); + return sslContext; + } private static void initializeVariables() { Main.DB_URL = initializeVariables("DB_URL"); diff --git a/service/server/src/main/java/com/timesheet/example1.json b/service/server/src/main/java/com/timesheet/example1.json deleted file mode 100644 index 4c99517..0000000 --- a/service/server/src/main/java/com/timesheet/example1.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "group": "8b3c8569-9ec8-45b7-8dad-34c5701d4d98", - "start": "2019-09-22T13:00:00.000Z", - "end": "2019-09-22T20:30:00.000Z", - "persist": true, - "type": "background", - "id": "bad60ff4-a85f-44b9-ac61-8f64ea45e156", - "typeOfWork": "Scheduled" -} \ No newline at end of file diff --git a/service/server/src/main/java/com/timesheet/example2.json b/service/server/src/main/java/com/timesheet/example2.json deleted file mode 100644 index 9ec9b92..0000000 --- a/service/server/src/main/java/com/timesheet/example2.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "id" : "Wipedown", - "content" : "Wipedown", - "nestedGroups" : [ "252eb1ec-3880-4240-b00f-a427195df97e", "220a060e-ee4b-421c-8403-fb572a816a3a", "7b548986-5b3e-460a-b61b-dc59f0881c8c", "7149c624-58a7-4f0d-86e6-434369877655", "816fbe98-b7d9-41a9-8504-5e808a69545a", "3ea1b484-85c4-4257-b115-bbb9095df700", "cb08a551-04ac-4fe2-be94-733f9da26601", "07602673-80da-431b-a4c1-f433b95648ea", "e4977da6-fb4c-4e6f-b7d8-06d8afd6ef78", "a12f22d4-10df-49c2-a21c-849f44259585", "7e7fa9cc-9bb4-459f-9e77-8b3a3f40567b", "2752aa2b-289f-411d-a01c-f7f1826148ee", "6e65412a-a158-4232-831b-5dab90ec8689", "07b5bd10-a053-4ef5-b290-d6efc1787322" ], - "subgroupStack" : true, - "order" : 0, - "showNested" : true - } \ No newline at end of file diff --git a/service/server/src/main/java/com/timesheet/example3.json b/service/server/src/main/java/com/timesheet/example3.json deleted file mode 100644 index 8b44fcb..0000000 --- a/service/server/src/main/java/com/timesheet/example3.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "employeeName" : "Dillon F.", - "order" : -38418868, - "checked" : false, - "id" : "8b3c8569-9ec8-45b7-8dad-34c5701d4d98", - "content" : "Dillon F.", - "nestedInGroup" : "Prep", - "visible" : false, - "className" : "toBreak" - } \ No newline at end of file