sistema_web/login-mecanics/content/main.py

189 lines
6.7 KiB
Python

# -*- coding: utf-8 -*-
import os
from flask import Flask, Blueprint, abort, session, g, current_app, request, render_template, send_from_directory, jsonify, flash, redirect
from flask_login import login_user, current_user, logout_user, login_required
from user_agents import parse
from webinterface import db, bcrypt
from sqlalchemy import func
from datetime import datetime, date
from webinterface.models.system import Persona, Ipaddr, Dispositivo, Identidad, Sesion, Registro, Conexion, Ruta, Sitio, Correo
from webinterface.content.forms import mMiCuenta, LoginForm, RequestResetForm, ResetPasswordForm
from webinterface.content.utils import clean_str, es_local
main = Blueprint('main', __name__)
if os.environ.get('COOKIE_DOMAIN'):
systemuri = "https://app.{}/".format(os.environ.get('COOKIE_DOMAIN'))
else:
systemuri = 'https://app.tpmc.ilab.cl/'
@main.route("/system/login", methods=['GET', 'POST'])
def login():
if current_user.is_authenticated:
return redirect(systemuri)
form = LoginForm()
if form.validate_on_submit():
form.login.data = clean_str(form.login.data.lower().strip())
user = Persona.query.filter(Persona.rut==form.login.data).first()
if user and bcrypt.check_password_hash(user.clave, form.clave.data):
login_user(user, remember=form.remember.data)
g.user = user
g.sesion.identidad = user
db.session.commit()
next_page = request.args.get('next')
current_app.logger.info('Acceso exitoso: IP({}), USER({}), UA({})'.format(g.ip.ipaddr,form.login.data, g.dispositivo.parsed_ua))
return redirect(next_page) if next_page else redirect(systemuri)
else:
flash(u'El nombre de usuario o la contraseña son incorrectos.', 'danger')
current_app.logger.warning('Intento de ingreso fallido: IP({}), USER({}), UA({})'.format(g.ip.ipaddr,form.login.data, g.dispositivo.parsed_ua))
return render_template('system/login.html', title='Ingreso de Usuarios del Sistema', form=form)
@main.route("/system/logout")
def logout():
logout_user()
session.pop('sid', None)
return redirect('https://tpmc.ilab.cl/')
@main.route("/system/me", methods=['GET', 'POST'])
@login_required
def micuenta():
form = mMiCuenta()
if form.validate_on_submit():
if form.clave.data:
hashed_password = bcrypt.generate_password_hash(form.clave.data).decode('utf-8')
current_user.clave = hashed_password
trimmed = form.correo.data.strip().lower()
correo = Correo.query.filter_by(correo=trimmed).first()
if correo is None:
correo = Correo(correo=trimmed, cuenta=current_user)
current_user.correodefecto=correo
current_user.telefono = form.fono.data.replace(" ", "")
db.session.commit()
flash(u'Los datos de tu cuenta han sido actualizados.', 'success')
return redirect(url_for('main.micuenta'))
elif request.method == 'GET':
if current_user.correodefecto is not None:
form.correo.data = current_user.correodefecto.correo
form.id.data = current_user.id
form.login.data = current_user.rut
form.nombrecompleto.data = current_user.nombrecompleto
form.fono.data = current_user.telefono
return render_template('system/me.html', title='Mi Cuenta', form=form)
@main.before_app_request
def registra_sesion():
if request.headers.getlist("X-Forwarded-For"):
remote_ip = request.headers.getlist("X-Forwarded-For")[0]
else:
remote_ip = request.environ['REMOTE_ADDR']
uadata = parse(request.user_agent.string)
ip = Ipaddr.query.filter_by(ipaddr=remote_ip).one_or_none()
if ip is None:
ip = Ipaddr(ipaddr=remote_ip)
db.session.add(ip)
db.session.commit()
if 'sid' in session:
sesion = Sesion.query.filter_by(id=session['sid']).one_or_none()
if sesion is None:
session.pop('sid', None)
else:
dispositivo = Dispositivo.query.filter_by(id=sesion.dispositivoid, parsed_ua=str(uadata)).one_or_none()
if dispositivo is None:
session.pop('sid', None)
else:
conexion = Conexion.query.filter_by(ipaddrid=ip.id, sesionid=sesion.id).one_or_none()
Ident = sesion.identidad
if conexion is None:
conexion = Conexion(ipaddr=ip, sesion=sesion)
db.session.add(conexion)
db.session.commit()
if 'sid' not in session:
dispositivo = Dispositivo.query.filter_by(useragent=request.user_agent.string).one_or_none()
if dispositivo is None:
dev = uadata.is_pc and "PC" or uadata.device.family
os = ("%s %s" % (uadata.os.family, uadata.os.version_string)).strip()
browser = ("%s %s" % (uadata.browser.family, uadata.browser.version_string)).strip()
dispositivo = Dispositivo(useragent=request.user_agent.string, dev=dev , os=os , browser=browser, parsed_ua=str(uadata))
db.session.add(dispositivo)
db.session.commit()
if uadata.is_bot:
Ident = Identidad.query.filter_by(login='Buscador').one()
elif es_local(remote_ip):
Ident = Identidad.query.filter_by(login='Intranet').one()
else:
Ident = Identidad.query.filter_by(login='Internet').one()
sesion = Sesion(identidad=Ident, dispositivo=dispositivo)
db.session.add(sesion)
db.session.commit()
conexion = Conexion(ipaddr=ip, sesion=sesion)
db.session.add(conexion)
db.session.commit()
# agregamos el registro asociado a la solicitud actual
# a la sesion que esta actualmente cargada. Dejamos la sesion guardada en
# la variable global g.
if '/reset_password' in str(request.path):
rpth = '/reset_password'
else:
rpth = str(request.path)
solicitud = Ruta.query.filter_by(ruta=rpth).first()
if solicitud is None:
solicitud = Ruta(ruta=str(request.path))
db.session.add(solicitud)
db.session.commit()
host = Sitio.query.filter_by(sitio=request.host).first()
if host is None:
host = Sitio(sitio=request.host)
db.session.add(host)
db.session.commit()
tamano = int(request.headers.get('Content-Length') or 0)
now = datetime.now()
registro = Registro(sitio=host, ruta=solicitud, sesion=sesion, ipaddr=ip, tamano=tamano)
db.session.add(registro)
db.session.commit()
conexion.ultimo = now
sesion.ultimo = now
db.session.commit()
g.ip = ip
g.user = Ident
g.sesion = sesion
g.conexion = conexion
g.registro = registro
g.dispositivo = dispositivo
session['sid'] = g.sesion.id