diff --git a/source/app/controllers/main.py b/source/app/controllers/main.py
index 003ea1c..626c330 100644
--- a/source/app/controllers/main.py
+++ b/source/app/controllers/main.py
@@ -1,8 +1,6 @@
#!/usr/bin/env python3
import falcon
-
-from . import util
from middleware import get_template
@@ -19,11 +17,11 @@ class AppLogin(object):
def on_post(self, req, resp):
session = req.env['beaker.session']
values = req.params
- result = self._db.authenticate(values['user'], values['pass'])
- resp.body = util.dumps(result)
+ result = self._db.authenticate(values)
if result['login']:
session.save()
session['user'] = result['user']
+ req.context['result'] = result
resp.status = falcon.HTTP_200
@@ -39,6 +37,17 @@ class AppLogout(object):
raise falcon.HTTPTemporaryRedirect('/')
+class AppAdmin(object):
+ template = 'admin.html'
+
+ def __init__(self, db):
+ self._db = db
+
+ @falcon.after(get_template)
+ def on_get(self, req, resp):
+ resp.status = falcon.HTTP_200
+
+
class AppMain(object):
template = 'main.html'
diff --git a/source/app/main.py b/source/app/main.py
index bc8947e..f526622 100644
--- a/source/app/main.py
+++ b/source/app/main.py
@@ -5,40 +5,36 @@ from beaker.middleware import SessionMiddleware
from middleware import AuthMiddleware, JSONTranslator, static, handle_404
from models.db import StorageEngine
-from controllers.main import AppLogin, AppLogout, AppMain, AppPartners
-from controllers.helper import AppPostalCode
-from settings import DEBUG, WITH_LOGIN
+from controllers.main import (
+ AppLogin, AppLogout, AppAdmin, AppMain,
+)
+from settings import DEBUG
db = StorageEngine()
-pc = AppPostalCode()
-login = AppLogin(db)
-logout = AppLogout(db)
-main = AppMain(db)
-partners = AppPartners(db)
+#~ partners = AppPartners(db)
api = falcon.API(middleware=[AuthMiddleware(), JSONTranslator()])
api.req_options.auto_parse_form_urlencoded = True
api.add_sink(handle_404, '')
-if WITH_LOGIN:
- api.add_route('/', login)
-api.add_route('/logout', logout)
-api.add_route('/main', main)
-api.add_route('/partners', partners)
-api.add_route('/pc', pc)
+
+api.add_route('/', AppLogin(db))
+api.add_route('/logout', AppLogout(db))
+api.add_route('/admin', AppAdmin(db))
+api.add_route('/main', AppMain(db))
+
+#~ api.add_route('/partners', partners)
if DEBUG:
api.add_sink(static, '/static')
-session_opts = {
+session_options = {
'session.type': 'file',
'session.cookie_expires': True,
'session.data_dir': '/tmp/cache/data',
'session.lock_dir': '/tmp/cache/lock',
- #~ 'session.httponly': True,
- #~ 'session.secure': True,
}
-app = SessionMiddleware(api, session_opts)
+app = SessionMiddleware(api, session_options)
diff --git a/source/app/middleware.py b/source/app/middleware.py
index 472f5dd..2ed77a8 100644
--- a/source/app/middleware.py
+++ b/source/app/middleware.py
@@ -31,12 +31,9 @@ def static(req, res):
class AuthMiddleware(object):
- #~ def process_request(self, req, resp):
-
def process_resource(self, req, resp, resource, params):
- paths = ('/main', '/partners', '/cp')
id_session = req.cookies.get('beaker.session.id', '')
- if req.path in paths and not id_session:
+ if not id_session and req.path != '/':
raise falcon.HTTPTemporaryRedirect('/')
@@ -46,5 +43,3 @@ class JSONTranslator(object):
if 'result' not in req.context:
return
resp.body = util.dumps(req.context['result'])
-
-
diff --git a/source/app/models/db.py b/source/app/models/db.py
index 658d543..ca7e420 100644
--- a/source/app/models/db.py
+++ b/source/app/models/db.py
@@ -6,10 +6,10 @@ from . import main
class StorageEngine(object):
def __init__(self):
- main.connect()
+ main.conectar()
- def authenticate(self, username, password):
- return main.authenticate(username, password)
+ def authenticate(self, args):
+ return main.authenticate(args['usuario'], args['contra'])
def get_partners(self, values):
return main.get_partners(values)
diff --git a/source/app/models/main.py b/source/app/models/main.py
index 1a3fdeb..49ba136 100644
--- a/source/app/models/main.py
+++ b/source/app/models/main.py
@@ -3,12 +3,15 @@
import sqlite3
import click
from peewee import *
+from playhouse.fields import PasswordField, ManyToManyField
+
if __name__ == '__main__':
import os, sys
parent_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.insert(0, parent_dir)
+
from controllers import util
from conf import DATABASE, __version__
from settings import log, PATH_CP
@@ -20,50 +23,95 @@ class BaseModel(Model):
database = database
-def connect():
+def conectar():
global database
database.connect()
log.info('Conectado a la BD...')
return
-class Configuration(BaseModel):
- key = FixedCharField(max_length=50)
- value = FixedCharField(max_length=100)
+class Configuracion(BaseModel):
+ clave = TextField()
+ valor = TextField()
class Meta:
- order_by = ('key',)
+ order_by = ('clave',)
indexes = (
- (('key', 'value'), True),
+ (('clave', 'valor'), True),
)
class Tags(BaseModel):
- tag = FixedCharField(max_length=25, index=True)
+ tag = TextField(index=True, unique=True)
class Meta:
order_by = ('tag',)
-class Users(BaseModel):
- username = CharField(max_length=50, unique=True)
- first_name = CharField(max_length=50, default='')
- last_name = CharField(max_length=50, default='')
- email = CharField(max_length=200, default='')
- password = CharField(max_length=100)
- is_superuser = BooleanField(default=False)
- is_admin = BooleanField(default=False)
- is_staff = BooleanField(default=False)
- is_active = BooleanField(default=True)
- date_joined = DateTimeField(default=util.now)
- last_login = DateTimeField(null=True)
+class Usuarios(BaseModel):
+ usuario = TextField(unique=True)
+ nombre = TextField(default='')
+ apellidos = TextField(default='')
+ correo = TextField(default='')
+ contraseña = PasswordField()
+ es_superusuario = BooleanField(default=False)
+ es_admin = BooleanField(default=False)
+ es_activo = BooleanField(default=True)
+ fecha_ingreso = DateTimeField(default=util.now)
+ ultimo_ingreso = DateTimeField(null=True)
def __str__(self):
t = '{} {} ({})'
- return t.format(self.first_name, self.last_name, self.username)
+ return t.format(self.nombre, self.apellidos, self.usuario)
class Meta:
- order_by = ('username',)
+ order_by = ('nombre', 'apellidos')
+
+
+class SATRegimenes(BaseModel):
+ key = TextField(index=True, unique=True)
+ name = TextField(index=True)
+ activo = BooleanField(default=False)
+ default = BooleanField(default=False)
+ fisica = BooleanField(default=False)
+ moral = BooleanField(default=False)
+
+ class Meta:
+ order_by = ('name',)
+ indexes = (
+ (('key', 'name'), True),
+ )
+
+
+class Emisor(BaseModel):
+ rfc = TextField(index=True)
+ nombre = TextField()
+ codigo_postal = TextField(default='')
+ moral = BooleanField(default=False)
+ regimenes = ManyToManyField(SATRegimenes, related_name='emisores')
+
+ def __str__(self):
+ t = '{} ({})'
+ return t.format(self.nombre, self.rfc)
+
+ class Meta:
+ order_by = ('nombre',)
+
+
+class Certificado(BaseModel):
+ key = BlobField()
+ key_enc = TextField(default='')
+ cer = BlobField()
+ cer_pem = TextField(default='')
+ cer_txt = TextField(default='')
+ p12 = BlobField()
+ serie = TextField(default='')
+ rfc = TextField(default='')
+ desde = DateTimeField()
+ hasta = DateTimeField()
+
+ def __str__(self):
+ return self.serie
class Clients(BaseModel):
@@ -114,22 +162,23 @@ class ClientsTags(BaseModel):
)
-def authenticate(username, password):
- data = {'login': False, 'msg': 'No Autorizado', 'user': ''}
+def authenticate(usuario, contraseña):
+ respuesta = {'login': False, 'msg': 'No Autorizado', 'user': ''}
try:
- obj = Users.get(Users.username==username, Users.is_active==True)
- except Users.DoesNotExist:
- return data
+ obj = Usuarios.get(usuario=usuario, es_activo=True)
+ except Usuarios.DoesNotExist:
+ return respuesta
- if not util.validate_password(obj.password, password):
- return data
+ if not obj.contraseña.check_password(contraseña):
+ return respuesta
- obj.last_login = util.now()
+ obj.ultimo_ingreso = util.now()
obj.save()
- data['msg'] = ''
- data['login'] = True
- data['user'] = str(obj)
- return data
+ respuesta['msg'] = ''
+ respuesta['login'] = True
+ respuesta['user'] = str(obj)
+ respuesta['super'] = obj.es_superusuario
+ return respuesta
def get_partners(values):
@@ -199,12 +248,12 @@ def _init_values():
return
-def create_tables():
- connect()
- tables = [Configuration, Tags, Users, Clients, ClientsTags]
- database.create_tables(tables, True)
+def _crear_tablas():
+ conectar()
+ tablas = [Configuracion, Tags, Usuarios,
+ Certificado, Emisor, Emisor.regimenes.get_through_model()]
+ database.create_tables(tablas, True)
log.info('Tablas creadas correctamente...')
- _init_values()
return
@@ -214,19 +263,20 @@ def migrate_tables():
return
-def create_superuser():
- connect()
- username = input('Introduce el nuevo nombre para el superusuario: ').strip()
- if not username:
+def _agregar_superusuario():
+ conectar()
+ usuario = input('Introduce el nuevo nombre para el superusuario: ').strip()
+ if not usuario:
msg = 'El nombre de usuario es requerido'
log.erro(msg)
return
- ok, password = util.get_pass()
+ ok, contraseña = util.get_pass()
if not ok:
- log.error(password)
+ log.error(contraseña)
return
try:
- obj = Users.create(username=username, password=password, is_superuser=True)
+ obj = Usuarios.create(
+ usuario=usuario, contraseña=contraseña, es_superusuario=True)
except IntegrityError:
msg = 'El usuario ya existe'
log.error(msg)
@@ -236,27 +286,27 @@ def create_superuser():
return
-def change_password():
- connect()
- username = input('Introduce el nombre de usuario: ').strip()
- if not username:
+def _cambiar_contraseña():
+ conectar()
+ usuario = input('Introduce el nombre de usuario: ').strip()
+ if not usuario:
msg = 'El nombre de usuario es requerido'
log.error(msg)
return
try:
- obj = Users.get(username=username)
- except Users.DoesNotExist:
+ obj = Usuarios.get(usuario=usuario)
+ except Usuarios.DoesNotExist:
msg = 'El usuario no existe'
log.error(msg)
return
- ok, password = util.get_pass()
+ ok, contraseña = util.get_pass()
if not ok:
- log.error(password)
+ log.error(contraseña)
return
- obj.password = password
+ obj.contraseña = contraseña
obj.save()
log.info('Contraseña cambiada correctamente...')
@@ -282,7 +332,7 @@ def main(iniciar_bd, migrar_bd, nuevo_superusuario, cambiar_contraseña):
opt = locals()
if opt['iniciar_bd']:
- create_tables()
+ _crear_tablas()
sys.exit(0)
if opt['migrar_bd']:
@@ -290,11 +340,11 @@ def main(iniciar_bd, migrar_bd, nuevo_superusuario, cambiar_contraseña):
sys.exit(0)
if opt['nuevo_superusuario']:
- create_superuser()
+ _agregar_superusuario()
sys.exit(0)
if opt['cambiar_contraseña']:
- change_password()
+ _cambiar_contraseña()
return
diff --git a/source/app/settings.py b/source/app/settings.py
index 639709f..7d06624 100644
--- a/source/app/settings.py
+++ b/source/app/settings.py
@@ -5,7 +5,7 @@ import os
import sys
from mako.lookup import TemplateLookup
from logbook import Logger, StreamHandler, RotatingFileHandler
-logbook.set_datetime_format("local")
+logbook.set_datetime_format('local')
from conf import DEBUG
@@ -15,7 +15,7 @@ PATH_STATIC = os.path.abspath(os.path.join(BASE_DIR, '..'))
PATH_TEMPLATES = os.path.abspath(os.path.join(BASE_DIR, '..', 'templates'))
EMAIL_SUPPORT = ('soporte@empresalibre.net',)
-WITH_LOGIN = True
+#~ WITH_LOGIN = True
DB_CP = 'cp.db'
PATH_CP = os.path.abspath(os.path.join(BASE_DIR, '..', 'db', DB_CP))
diff --git a/source/static/js/controller/admin.js b/source/static/js/controller/admin.js
new file mode 100644
index 0000000..def8b71
--- /dev/null
+++ b/source/static/js/controller/admin.js
@@ -0,0 +1,21 @@
+
+
+var controllers = {
+ init: function(){
+ //~ Admin
+ $$('menu_user').attachEvent('onMenuItemClick', menu_user_click)
+ }
+}
+
+
+function menu_user_click(id, e, node){
+ if (id == 1){
+ window.location = '/logout'
+ return
+ }
+}
+
+
+function cmd_home_click(){
+ window.location = '/main'
+}
diff --git a/source/static/js/controller/main.js b/source/static/js/controller/main.js
index 21182d4..a2868e7 100644
--- a/source/static/js/controller/main.js
+++ b/source/static/js/controller/main.js
@@ -29,7 +29,7 @@ var controllers = {
$$("cmd_save_invoice").attachEvent("onItemClick", cmd_save_invoice_click);
$$("cmd_cancel_invoice").attachEvent("onItemClick", cmd_cancel_invoice_click);
- get_partners()
+ //~ get_partners()
}
};
diff --git a/source/static/js/ui/admin.js b/source/static/js/ui/admin.js
new file mode 100644
index 0000000..71f3a8c
--- /dev/null
+++ b/source/static/js/ui/admin.js
@@ -0,0 +1,72 @@
+
+var menu_data = [
+ {id: 'app_home', icon: 'dashboard', value: 'Inicio'},
+ {id: 'app_emisor', icon: 'user-circle', value: 'Emisor'},
+ {id: 'app_cert', icon: 'key', value: 'Certificado'},
+]
+
+
+var sidebar = {
+ view: 'sidebar',
+ data: menu_data,
+ ready: function(){
+ this.select('app_home');
+ this.open(this.getParentId('app_home'));
+ },
+ on:{
+ onAfterSelect: function(id){
+ $$('multi').setValue(id)
+ }
+ }
+};
+
+
+var multi_main = {
+ id: 'multi',
+ animate: true,
+ cells:[
+ {
+ id: 'app_home',
+ view: 'template',
+ template: 'HOME'
+ }
+ //~ app_emisor,
+ ]
+};
+
+
+var menu_user = {
+ view: 'menu',
+ id: 'menu_user',
+ width: 150,
+ autowidth: true,
+ data: [
+ {id: '0', value: 'User...', submenu:[{id:1, value:'Cerrar Sesión'}]},
+ ],
+ type: {
+ subsign: true,
+ },
+};
+
+var ui_admin = {
+ rows: [
+ {view: 'toolbar', padding: 3, elements: [
+ {view: 'button', type: 'icon', icon: 'bars',
+ width: 37, align: 'left', css: 'app_button', click: function(){
+ $$('$sidebar1').toggle()
+ }
+ },
+ {view: 'label', label: 'Empresa Libre - Configuración'},
+ {},
+ {view: 'button', type: 'icon', width: 40, css: 'app_button',
+ icon: 'home', click: 'cmd_home_click'},
+ menu_user
+ ]},
+ {
+ cols:[
+ sidebar,
+ multi_main,
+ ]
+ }
+ ]
+};
diff --git a/source/static/js/ui/login.js b/source/static/js/ui/login.js
index c24ed0a..015e569 100644
--- a/source/static/js/ui/login.js
+++ b/source/static/js/ui/login.js
@@ -1,12 +1,12 @@
-
var msg_user = 'El usuario es requerido'
var msg_pass = 'La contraseña es requerida'
var form_controls = [
- {view: 'text', label: 'Usuario', name: 'user', labelPosition: 'top',
- required: true, invalidMessage: msg_user},
- {view: 'text', label: 'Contraseña', name: 'pass', type: 'password',
- required: true, labelPosition: 'top', invalidMessage: msg_pass},
+ {view: 'text', label: 'Usuario', id: 'txt_usuario', name: 'usuario',
+ labelPosition: 'top', required: true, invalidMessage: msg_user},
+ {view: 'text', label: 'Contraseña', id: 'txt_contra', name: 'contra',
+ type: 'password', required: true, labelPosition: 'top',
+ invalidMessage: msg_pass},
{margin: 10, cols:[{}, {view: 'button', value: 'Iniciar Sesión',
click: 'validate_login', hotkey: 'enter'}, {}]}
]
@@ -28,8 +28,8 @@ var ui_login = {
width: 400,
elements: form_controls,
rules:{
- user:function(value){ return value.trim() != '';},
- pass:function(value){ return value.trim() != '';},
+ usuario:function(value){ return value.trim() != '';},
+ contra:function(value){ return value.trim() != '';},
}
},
]}, {}, ]
diff --git a/source/static/js/ui/main.js b/source/static/js/ui/main.js
index b2e0537..f594323 100644
--- a/source/static/js/ui/main.js
+++ b/source/static/js/ui/main.js
@@ -1,5 +1,4 @@
-
var menu_data = [
{id: 'app_home', icon: 'dashboard', value: 'Inicio'},
{id: 'app_partners', icon: 'users', value: 'Clientes y Proveedores'},
diff --git a/source/templates/admin.html b/source/templates/admin.html
new file mode 100644
index 0000000..cd660d3
--- /dev/null
+++ b/source/templates/admin.html
@@ -0,0 +1,29 @@
+<%inherit file="base.html"/>
+
+<%block name="media">
+
+
+
+
+
+
+
+%block>
+
+<%block name="content">
+
+
+
+
+
+%block>
diff --git a/source/templates/base.html b/source/templates/base.html
index 4441f70..7038ef4 100644
--- a/source/templates/base.html
+++ b/source/templates/base.html
@@ -9,7 +9,6 @@
-
<%block name="media"/>
diff --git a/source/templates/login.html b/source/templates/login.html
index 97ad63b..e1e2fcd 100644
--- a/source/templates/login.html
+++ b/source/templates/login.html
@@ -18,14 +18,18 @@ function validate_login(){
return
}
- var values = form.getValues();
+ var values = form.getValues()
webix.ajax().post("/", values, function(text, data, xhr) {
var values = data.json();
if (values.login) {
- window.location = "/main";
+ if (values.super) {
+ window.location = "/admin"
+ }else{
+ window.location = "/main"
+ }
} else {
- webix.message({ type:"error", text: values.msg });
+ webix.message({ type:"error", text: values.msg })
}
});
};