Commit 5da2cb05 by Luciano Barletta

fix issue #2041

1 parent 9ac32563
...@@ -3,3 +3,4 @@ __pycache__ ...@@ -3,3 +3,4 @@ __pycache__
*.log *.log
test.py test.py
*.pdf *.pdf
users.json
\ No newline at end of file \ No newline at end of file
#-*- coding: utf-8 -*- #-*- coding: utf-8 -*-
from flask import Flask, render_template, request, url_for from flask import Flask, render_template, request, url_for, make_response, redirect
from iselenium import SeleniumInterface as SI from iselenium import SeleniumInterface as SI
import random, json import random, json, os
app = Flask(__name__) app = Flask(__name__)
def create():
if not os.path.exists("users.json"):
with open("users.json", "+w") as f:
f.write("{}")
def usersave(usr, psw):
create()
content = ""
with open("users.json", "r") as u:
content = u.read()
with open("users.json", "w") as u:
try:
content = json.loads(content)
except:
content = {}
content[usr] = psw
u.write( json.dumps(content) )
def userget(usr):
create()
content = ""
with open("users.json", "r") as u:
content = u.read()
try:
return json.loads(content)[usr]
except:
return None
@app.route('/') @app.route('/')
def main(): def main():
if "login" in request.cookies:
return render_template( return render_template(
"form.html", "form.html",
bypass = False bypass = False
) )
else:
return redirect(url_for("login"))
@app.route('/login', methods = ['GET', 'POST'])
def login():
if request.method == "GET":
return render_template(
"login.html"
)
else:
try:
s = SI(SI.Chrome)
r = make_response(
json.dumps(
login(
request.json['usuario'],
request.json['contrasena'],
s
)
)
)
r.set_cookie(
"login",
request.json['usuario'],
60 * 60 * 8,
httponly = True
)
usersave(
request.json['usuario'],
request.json['contrasena']
)
s.driver.close()
return r
except:
s.driver.close()
return "Error en el login"
@app.route('/manual') @app.route('/manual')
def manual(): def manual():
...@@ -21,6 +90,9 @@ def manual(): ...@@ -21,6 +90,9 @@ def manual():
@app.route('/pdf', methods = ['POST']) @app.route('/pdf', methods = ['POST'])
def pdf(): def pdf():
if "login" not in request.cookies:
return redirect(url_for("login"))
d = request.json d = request.json
plate = d['header']['patente'] plate = d['header']['patente']
s = SI(SI.Chrome) s = SI(SI.Chrome)
...@@ -37,31 +109,36 @@ def pdf(): ...@@ -37,31 +109,36 @@ def pdf():
answer['header']['patente'] = plate.upper() answer['header']['patente'] = plate.upper()
try: try:
answer = login( login(
d['credenciales']['usuario'], request.cookies["login"],
d['credenciales']['contrasena'], userget(
s, request.cookies["login"]
answer ),
s
) )
except: except:
return "Error en el login." s.driver.close()
return f"Error en el login"
try: try:
answer = gototec(s, answer) answer = gototec(s, answer)
except: except:
s.driver.close()
return f"Error yendo a las especificaciones técnicas del dominio '{plate}'." return f"Error yendo a las especificaciones técnicas del dominio '{plate}'."
try: #try:
answer = readdata(s, answer) answer = readdata(s, answer)
except: #except:
return f"Error leyendo datos de la patente '{plate}'." #s.driver.close()
#return f"Error leyendo datos de la patente '{plate}'."
try: try:
answer = rnddata(answer) answer = rnddata(answer)
except: except:
s.driver.close()
return f"Error completando datos extra de la patente '{plate}'." return f"Error completando datos extra de la patente '{plate}'."
print(answer) s.driver.close()
return json.dumps(answer) return json.dumps(answer)
def login(u, p, s, r): def login(u, p, s):
s.get("https://rto.cent.gov.ar/rto") s.get("https://rto.cent.gov.ar/rto")
login = s.find(SI.By.NAME, "j_username") login = s.find(SI.By.NAME, "j_username")
...@@ -73,13 +150,11 @@ def login(u, p, s, r): ...@@ -73,13 +150,11 @@ def login(u, p, s, r):
button = s.find(SI.By.ID, "submit") button = s.find(SI.By.ID, "submit")
button.click() button.click()
reach = lambda s: s.find(SI.By.NAME, "j_username") login = _attempt(lambda s: s.find(SI.By.NAME, "j_username"), "?")(s)
login = attempt_do(reach, default = "?")(s)
# login succeeded # login succeeded
if login == "?": if login == "?":
return r return True
# still in login page # still in login page
else: else:
...@@ -116,36 +191,42 @@ def readdata(s, r): ...@@ -116,36 +191,42 @@ def readdata(s, r):
reach = lambda id: lambda s: s.readInput( s.find(s.By.ID, id) ) reach = lambda id: lambda s: s.readInput( s.find(s.By.ID, id) )
# alineacion # alineacion
r['alineador']['eje_delantero'] = empty_for_question(attempt_do(reach("deriva"), default = "?")(s)) r['alineador']['eje_delantero'] = _e2q(_attempt( reach("deriva"), "?" )(s))
# suspension # suspension
sus = r['suspension']
for i in range(2): for i in range(2):
sus = {} # si valores de rendimiento son numeros, leer el peso
sus[f'peso_estatico_{i + 1}'] = empty_for_question(attempt_do(reach(f"pesoBascula-{i}"), default = "?")(s)) if sus[f'rendimiento_izquierdo_{i + 1}'].isnumeric() or sus[f'rendimiento_derecho_{i + 1}'].isnumeric():
sus[f'peso_estatico_{i + 1}'] = _e2q(_attempt( reach(f"pesoBascula-{i}"), "?" )(s))
else:
sus[f'rendimiento_izquierdo_{i + 1}'] = "?"
sus[f'rendimiento_derecho_{i + 1}'] = "?"
sus[f'peso_estatico_{i + 1}'] = "?"
r['suspension'].update(sus) r['suspension'].update(sus)
# frenos # frenos
for i in range(4): for i in range(4):
fre = {} fre = {}
fre[f'peso_estatico_{i + 1}'] = empty_for_question(attempt_do(reach(f"pesoBascula-{i}"), default = "?")(s)) fre[f'peso_estatico_{i + 1}'] = _e2q(_attempt( reach(f"pesoBascula-{i}"), "?" )(s))
fre[f'fuerza_izquierda_{i + 1}'] = empty_for_question(attempt_do(reach(f"fuerzaIzq-{i}"), default = "?")(s)) fre[f'fuerza_izquierda_{i + 1}'] = _e2q(_attempt( reach(f"fuerzaIzq-{i}"), "?" )(s))
fre[f'fuerza_derecha_{i + 1}'] = empty_for_question(attempt_do(reach(f"fuerzaDer-{i}"), default = "?")(s)) fre[f'fuerza_derecha_{i + 1}'] = _e2q(_attempt( reach(f"fuerzaDer-{i}"), "?" )(s))
r['frenos'].update(fre) r['frenos'].update(fre)
# freno trasero # freno trasero
r['trasero']['peso_estatico'] = empty_for_question(attempt_do(reach(f"pesoBasculaEst-0"), default = "?")(s)) r['trasero']['peso_estatico'] = _e2q(_attempt( reach(f"pesoBasculaEst-0"), "?" )(s))
r['trasero']['fuerza_izquierda'] = empty_for_question(attempt_do(reach(f"fuerzaIzqEst-0"), default = "?")(s)) r['trasero']['fuerza_izquierda'] = _e2q(_attempt( reach(f"fuerzaIzqEst-0"), "?" )(s))
r['trasero']['fuerza_derecha'] = empty_for_question(attempt_do(reach(f"fuerzaDerEst-0"), default = "?")(s)) r['trasero']['fuerza_derecha'] = _e2q(_attempt( reach(f"fuerzaDerEst-0"), "?" )(s))
r['trasero']['eje'] = empty_for_question(attempt_do(reach(f"nroEjeEst-0"), default = "?")(s)) r['trasero']['eje'] = _e2q(_attempt( reach(f"nroEjeEst-0"), "?" )(s))
# gases y humos # gases y humos
r['gaseshumos']['opacidad_logaritmica'] = empty_for_question(attempt_do(reach(f"opacidadLogaritmica"), default = "?")(s)) r['gaseshumos']['opacidad_logaritmica'] = _e2q(_attempt( reach(f"opacidadLogaritmica"), "?" )(s))
r['gaseshumos']['co'] = empty_for_question(attempt_do(reach(f"cantCO"), default = "?")(s)) r['gaseshumos']['co'] = _e2q(_attempt( reach(f"cantCO"), "?" )(s))
r['gaseshumos']['hc'] = empty_for_question(attempt_do(reach(f"cantHC"), default = "?")(s)) r['gaseshumos']['hc'] = _e2q(_attempt( reach(f"cantHC"), "?" )(s))
return r return r
...@@ -168,7 +249,7 @@ def rnddata(r): ...@@ -168,7 +249,7 @@ def rnddata(r):
return r return r
# Executes the lambda with the arguments, with try except # Executes the lambda with the arguments, with try except
def attempt_do(f, default = "", error = ""): def _attempt(f, default = "", error = ""):
def inner(*args, **kwargs): def inner(*args, **kwargs):
try: try:
return f(*args, **kwargs) return f(*args, **kwargs)
...@@ -178,7 +259,7 @@ def attempt_do(f, default = "", error = ""): ...@@ -178,7 +259,7 @@ def attempt_do(f, default = "", error = ""):
return default return default
return inner return inner
def empty_for_question(string): def _e2q(string):
return "?" if string == "" else string return "?" if string == "" else string
# Inicio del servicio # Inicio del servicio
......
"use strict";
function collectToSearch() { function collectToSearch() {
f = document.getElementById("form"); const f = document.getElementById("form");
inputs = f.getElementsByTagName("input"); const inputs = f.getElementsByTagName("input");
const defecto = document.getElementsByName("defecto")[0].value;
data = {}; let data = {};
function BadInputException(input) { function BadInputException(input) {
this.error = "badinput"; this.error = "badinput";
...@@ -16,17 +19,15 @@ function collectToSearch() { ...@@ -16,17 +19,15 @@ function collectToSearch() {
throw BadInputException(input); throw BadInputException(input);
} }
sub = input.getAttribute("sub"); const sub = input.getAttribute("sub");
if ( (sub in data) === false ) { if ( (sub in data) === false ) {
data[sub] = {} data[sub] = {}
} }
data[sub][input.name] = input.value; data[sub][input.name] = (input.value === "" ? defecto : input.value);
}); });
message("Espere..."); message("Espere...");
console.log(data);
const obj = { const obj = {
"url" : "/pdf", "url" : "/pdf",
"contentType" : "application/json", "contentType" : "application/json",
...@@ -49,21 +50,21 @@ function collectToSearch() { ...@@ -49,21 +50,21 @@ function collectToSearch() {
"ontimeout" : (response) => message("La conexión tardó demasiado.") "ontimeout" : (response) => message("La conexión tardó demasiado.")
} }
ajax = new Ajax(obj); let ajax = new Ajax(obj);
ajax.post(); ajax.post();
} }
function collectToConvert() { function collectToConvert() {
r = document.getElementById("results") const r = document.getElementById("results")
inputs = r.getElementsByTagName("input"); const inputs = r.getElementsByTagName("input");
data = {}; let data = {};
defecto = document.getElementsByName("defecto")[0].value; const defecto = document.getElementsByName("defecto")[0].value;
Array.from(inputs).forEach(input => { Array.from(inputs).forEach(input => {
if (input.name == "defecto") return; if (input.name == "defecto") return;
sub = input.getAttribute("sub"); const sub = input.getAttribute("sub");
if ((sub in data) === false) { if ((sub in data) === false) {
data[sub] = {} data[sub] = {}
} }
...@@ -81,13 +82,13 @@ function message(msg) { ...@@ -81,13 +82,13 @@ function message(msg) {
} }
function fillResults(results) { function fillResults(results) {
r = document.getElementById("results") const r = document.getElementById("results")
inputs = r.getElementsByTagName("input"); const inputs = r.getElementsByTagName("input");
Array.from(inputs).forEach(input => { Array.from(inputs).forEach(input => {
if (input.name == "defecto") return; if (input.name == "defecto") return;
sub = input.getAttribute("sub"); const sub = input.getAttribute("sub");
input.value = results[sub][input.name]; input.value = results[sub][input.name];
}); });
} }
\ No newline at end of file \ No newline at end of file
function login() {
message("Espere...");
const usr = document.getElementsByName("usuario")[0];
const psw = document.getElementsByName("contrasena")[0];
function BadInputException(input) {
this.error = "badinput";
this.input = input;
}
if (usr.checkValidity() === false) {
usr.reportValidity("Por favor llene este campo");
throw BadInputException(input);
}
if (psw.checkValidity() === false) {
psw.reportValidity("Por favor llene este campo");
throw BadInputException(input);
}
const obj = {
"url": "/login",
"contentType": "application/json",
"async": true,
"data": { "usuario" : usr.value, "contrasena" : psw.value },
"success": (response) => {
console.log(response)
if (response === "true")
location.href = "/";
else
message(response);
},
"error": (response) => message(response),
"timeout": 120000,
"ontimeout": (response) => message("La conexión tardó demasiado.")
}
const ajax = new Ajax(obj);
ajax.post();
}
\ No newline at end of file \ No newline at end of file
...@@ -4,11 +4,14 @@ ...@@ -4,11 +4,14 @@
html { html {
font-size: var(--FontSize); font-size: var(--FontSize);
font-family: 'CMUTypewriterTextRegular'; font-family: 'Geneva';
font-weight: normal; font-weight: normal;
font-style: normal; font-style: normal;
color: rgb(50, 50, 50);
background-color: rgb(200, 200, 200);
} }
td{
td {
text-align: center; text-align: center;
margin: auto; margin: auto;
align-content: center; align-content: center;
...@@ -24,6 +27,18 @@ td{ ...@@ -24,6 +27,18 @@ td{
text-align: unset; text-align: unset;
} }
.DataCard {
margin: 3%;
margin-top: 2%;
margin-bottom: 4%;
border-radius: 10px;
width: 88%;
height: auto;
box-shadow: 0px 0px 15px 3px rgba(0, 0, 0, 0.5);
background-color: white;
padding: 3%;
}
.PDFButtonContainer { .PDFButtonContainer {
margin: auto; margin: auto;
margin-top: 3%; margin-top: 3%;
...@@ -35,12 +50,13 @@ td{ ...@@ -35,12 +50,13 @@ td{
.PDFButtonContainerFixed { .PDFButtonContainerFixed {
position: fixed; position: fixed;
right: 50; right: 75;
bottom: 33.33%; bottom: 50%;
} }
.PDFButton { .PDFButton {
background-color: #4CAF50; background-color: #4CAF50;
border-radius: 5px;
border: none; border: none;
color: white; color: white;
padding: 15px 32px; padding: 15px 32px;
...@@ -51,6 +67,7 @@ td{ ...@@ -51,6 +67,7 @@ td{
} }
input { input {
outline: none;
position: absolute; position: absolute;
left: 30%; left: 30%;
font-size: 15; font-size: 15;
...@@ -68,7 +85,7 @@ input { ...@@ -68,7 +85,7 @@ input {
} }
.MessageContainer { .MessageContainer {
background-color: rgba(150, 150, 150, 0.5); background-color: rgba(150, 150, 150, 0.3);
width: 100%; width: 100%;
height: 100%; height: 100%;
position: fixed; position: fixed;
...@@ -77,11 +94,15 @@ input { ...@@ -77,11 +94,15 @@ input {
} }
.Message, .MessageFixed { .Message, .MessageFixed {
color: black;
font-weight: 500;
max-width: 33%; max-width: 33%;
padding: 1%; padding: 1%;
font-size: 20; font-size: 20;
border: 2px solid gray; border: 2px solid gray;
background-color: rgb(200, 150, 250); background-color: rgb(200, 150, 250);
box-shadow: 0px 0px 10px 0px rgba(0, 0, 0, 0.3);
border-radius: 10px;
} }
.Message { .Message {
...@@ -96,7 +117,7 @@ input { ...@@ -96,7 +117,7 @@ input {
.MessageFixed { .MessageFixed {
position: fixed; position: fixed;
top: 50; top: 50;
right: 50; right: 75;
} }
.X { .X {
...@@ -104,5 +125,4 @@ input { ...@@ -104,5 +125,4 @@ input {
top: 3; top: 3;
right: 3; right: 3;
font-weight: bolder; font-weight: bolder;
font-family: Arial, Helvetica, sans-serif;
} }
\ No newline at end of file \ No newline at end of file
:root {
--FontSize: 25;
}
html {
font-size: var(--FontSize);
font-family: 'Geneva';
font-weight: normal;
font-style: normal;
color: rgb(50, 50, 50);
background-color: rgb(200, 200, 200);
}
td {
text-align: center;
margin: auto;
align-content: center;
width: 33.33%;
}
.header {
width: 50%;
}
.header td {
width: 50%;
text-align: unset;
}
.LoginCard {
border-radius: 10px;
text-align: center;
width: 75%;
height: 75%;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
box-shadow: 0px 0px 15px 3px rgba(0, 0, 0, 0.5);
background-color: white;
}
.PDFButton {
background-color: #4CAF50;
border-radius: 5px;
border: none;
color: white;
padding: 15px 32px;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 16px;
}
input {
margin-top: 10%;
margin: auto;
outline: none;
font-size: 20;
border-top: none;
border-left: none;
border-right: none;
border-bottom: 2px solid gray;
font-weight: 700;
size: 30%;
text-align: center;
}
.bottom {
position: absolute;
bottom: 0;
left: 50%;
transform: translate(-50%, -50%);
}
.MessageContainer {
background-color: rgba(150, 150, 150, 0.3);
width: 100%;
height: 100%;
position: fixed;
top: 0;
left: 0;
}
.Message,
.MessageFixed {
color: black;
font-weight: 500;
max-width: 33%;
padding: 1%;
font-size: 20;
border: 2px solid gray;
background-color: rgb(200, 150, 250);
box-shadow: 0px 0px 10px 0px rgba(0, 0, 0, 0.3);
border-radius: 10px;
}
.Message {
min-width: 10%;
min-height: 5%;
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.MessageFixed {
position: fixed;
top: 50;
right: 50;
}
.X {
position: absolute;
top: 3;
right: 3;
font-weight: bolder;
}
\ No newline at end of file \ No newline at end of file
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
Pueden ser completados a mano antes de convertir a PDF.<br> Pueden ser completados a mano antes de convertir a PDF.<br>
De no ser completados, se completaran automáticamente con el valor del campo 'Por defecto' al final de la página. De no ser completados, se completaran automáticamente con el valor del campo 'Por defecto' al final de la página.
</div> </div>
<div class="DataCard">
<h1>Datos Generales</h1> <h1>Datos Generales</h1>
Patente <input sub="header" type="text" name="patente"> Patente <input sub="header" type="text" name="patente">
<br> <br>
...@@ -88,6 +89,7 @@ ...@@ -88,6 +89,7 @@
<br> <br>
Por defecto: <input type="text" name="defecto" value="---"> Por defecto: <input type="text" name="defecto" value="---">
<br> <br>
</div>
<div class="PDFButtonContainerFixed"> <div class="PDFButtonContainerFixed">
<button class="PDFButton" onclick= <button class="PDFButton" onclick=
...@@ -115,29 +117,33 @@ ...@@ -115,29 +117,33 @@
</button> </button>
<img id="maha" src="{{ url_for('static', filename = 'assets/maha.png') }}" style="display: none;"> <img id="maha" src="{{ url_for('static', filename = 'assets/maha.png') }}" style="display: none;">
</div> </div>
<div class="PDFButtonContainerFixed" style="bottom: 40%;">
<button class="PDFButton" style="bottom: 40%; display: {% if bypass %} none {% else %} block {% endif %};"
onclick="location.reload()">
Volver
</button>
</div>
</div> </div>
<div id="form" style="height: 100%; display: {% if bypass %} none {% else %} block {% endif %}"> <div id="form" class="DataCard" style="height: auto; display: {% if bypass %} none {% else %} block {% endif %};">
<h1>Generación de PDF</h1> <h1>Generación de PDF</h1>
Usuario <input required type="text" sub="credenciales" name="usuario">
<br>
Contraseña <input required type="password" sub="credenciales" name="contrasena">
<br>
Patente <input required type="text" sub="header" name="patente"> Patente <input required type="text" sub="header" name="patente">
<br> <br>
<h1>Datos de Suspensión</h1> <h1>Datos de Suspensión</h1>
Rendimiento Izquierdo - Eje 1 <input required type="number" step="any" sub="suspension" name="rendimiento_izquierdo_1"> Rendimiento Izquierdo - Eje 1 <input type="number" step="any" sub="suspension" name="rendimiento_izquierdo_1">
<br> <br>
Rendimiento Derecho - Eje 1 <input required type="number" step="any" sub="suspension" name="rendimiento_derecho_1"> Rendimiento Derecho - Eje 1 <input type="number" step="any" sub="suspension" name="rendimiento_derecho_1">
<br> <br>
Rendimiento Izquierdo - Eje 2 <input required type="number" step="any" sub="suspension" name="rendimiento_izquierdo_2"> Rendimiento Izquierdo - Eje 2 <input type="number" step="any" sub="suspension" name="rendimiento_izquierdo_2">
<br> <br>
Rendimiento Derecho - Eje 2 <input required type="number" step="any" sub="suspension" name="rendimiento_derecho_2"> Rendimiento Derecho - Eje 2 <input type="number" step="any" sub="suspension" name="rendimiento_derecho_2">
<br> <br>
Por defecto: <input name="defecto" type="text" value="---">
<div class="PDFButtonContainer"> <div class="PDFButtonContainer">
<button class="PDFButton" onclick="collectToSearch()"> <button class="PDFButton" onclick="collectToSearch()">
Buscar Buscar
......
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/1.3.2/jspdf.min.js"></script>
<script src="{{ url_for('static', filename = 'src/ajax.js') }}"></script>
<script src="{{ url_for('static', filename = 'src/forms.js') }}"></script>
<script src="{{ url_for('static', filename = 'src/login.js') }}"></script>
<link rel="stylesheet" href="{{ url_for('static', filename = 'styles/login.css') }}">
<!--INCLUIMOS LA FUENTE-->
<link rel="stylesheet" media="screen" href="https://fontlibrary.org/face/cmu-typewriter" type="text/css" />
<title>Login</title>
</head>
<body>
<div class="LoginCard">
<h2>Usuario:</h2>
<br>
<input required type="text" name="usuario" style="margin: auto;">
<br>
<br>
<h2>Contraseña:</h2>
<br>
<input required type="password" name="contrasena" style="margin: auto;">
<button class="PDFButton bottom" onclick="login()">
Entrar
</button>
</div>
<div id="message" class="MessageContainer" onclick="this.style.display = 'none'" style="display: none;">
<div class="Message" style="text-align: center;">
<p id="msg"></p>
<span class="X">x<span>
</div>
</div>
</body>
</html>
\ No newline at end of file \ No newline at end of file
Styling with Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!