views.py 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412
  1. # -*- coding: utf-8 -*-
  2. '''
  3. Gestor de nodos para LaOtraRed La Paz - El Alto
  4. Copyright (C) 2017 Rodrigo Garcia
  5. This program is free software: you can redistribute it and/or modify
  6. it under the terms of the GNU Affero General Public License as
  7. published by the Free Software Foundation, either version 3 of the
  8. License, or (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU Affero General Public License for more details.
  13. You should have received a copy of the GNU Affero General Public License
  14. along with this program. If not, see <http://www.gnu.org/licenses/>.
  15. '''
  16. import datetime, time
  17. from collections import deque
  18. from flask import render_template, jsonify, abort, Markup, escape, request #, make_response
  19. from flask import Blueprint
  20. from flask import flash, g, session
  21. from flask import redirect, send_from_directory, safe_join, send_file
  22. from flask import url_for
  23. from werkzeug import secure_filename
  24. from werkzeug import secure_filename
  25. from jinja2 import Environment, PackageLoader
  26. from gestor.main import app
  27. from gestor import configs
  28. from database.database import init_db, db_session
  29. from database.database import engine
  30. from sqlalchemy.exc import IntegrityError
  31. from .models import Nodo, Ubicacion
  32. from gestor import utils
  33. from gestor import utils_red
  34. from gestor import utils_firmware
  35. gestor = Blueprint("gestor", __name__, url_prefix='')
  36. @gestor.before_request
  37. def before_request():
  38. g.nodo = None
  39. if 'nodo_id' in session:
  40. g.nodo = Nodo.query.get(session['nodo_id'])
  41. print ("sesion: "+str(g.nodo))
  42. g.estado_construccion = 'No'
  43. @gestor.route('/')
  44. def hello_world():
  45. return render_template("index.html", p_actual="inicio", \
  46. nodo=session.get('nodo_id', None))
  47. #return "DATABASE = "+str(configs.DATABASE_NAME)+"\n"+\
  48. #"DB: "+str(engine)
  49. @gestor.route('/agregar', methods=['GET'])
  50. def get_agregar_nodos(errors=None):
  51. contexto = {}
  52. contexto['modelos_posibles'] = utils.listas_routers()
  53. if errors:
  54. return render_template("agregar_nodo.html", p_actual="agregar",\
  55. contexto=contexto, errors=errors,
  56. nodo=session.get('nodo_id', None))
  57. return render_template("agregar_nodo.html", p_actual="agregar",\
  58. contexto=contexto,\
  59. nodo=session.get('nodo_id', None))
  60. @gestor.route('/nuevo', methods=['POST'])
  61. def post_agregar_nodos():
  62. if request.method == "POST":
  63. errors = utils.comprobar_postAgregarNodo(request, errores_detalle=True)
  64. # comprobando nuevo nodo en la base de datos
  65. #nodo_similar = utils.comprobar_responsableNodo(request)
  66. nodo_similar = utils.comprobar_nodoSimilar(request)
  67. #if nodo_similar is not None:
  68. if nodo_similar != False:
  69. errors['nodo_similar'] = u"Un nodo tiene registrado el email <"+\
  70. str(request.form['email'].lower())+\
  71. "> y el nombre, apellido son distintos a "+\
  72. " los que has introducido."
  73. errors['id_nodo_similar'] = str(nodo_similar)
  74. if len(errors) > 0:
  75. contexto = {}
  76. contexto['modelos_posibles'] = utils.listas_routers()
  77. contexto['errors'] = errors
  78. print ("Errores en formulario: "+str(errors))
  79. return (get_agregar_nodos(errors=errors))
  80. return render_template("agregar_nodo.html", p_actual="agregar",\
  81. contexto=contexto, errors=errors, \
  82. nodo=session.get('nodo_id', None) )
  83. # insertando en la base de datos
  84. db_session.rollback()
  85. compartir_ubicacion = request.form.get("compartir_ubicacion")
  86. # creando nodo con ubicacion dummy
  87. if compartir_ubicacion == "SI":
  88. id_ubicacion_dummy = utils.crear_ubicacionDummy(is_public=True)
  89. elif compartir_ubicacion == "NO":
  90. id_ubicacion_dummy = utils.crear_ubicacionDummy(is_public=False)
  91. # obteniendo bloques de red
  92. cidr_publica = utils_red.get_cidrIpV4(request.form['ips_publicas'])
  93. cidr_privada = utils_red.get_cidrIpV4(request.form['ips_privadas'])
  94. bloque_ipv4_publico = utils_red.\
  95. siguiente_bloqueIpv4Disponible(cidr_publica)
  96. bloque_ipv4_privado = utils_red.\
  97. siguiente_bloqueIpv4Disponible(cidr_privada, publico=False)
  98. bloque_ipv6 = utils_red.siguiente_bloqueIpv6Disponible()
  99. clave_edicion = utils.hash_claveEdicion(request.form['clave'])
  100. nombre_nodo = request.form.get('nombre_nodo', bloque_ipv4_publico)
  101. fecha_actual = datetime.datetime.now().\
  102. strftime("%Y-%m-%d %H:%M:%S")
  103. # creacion de nuevo registro
  104. nodo = Nodo(ubicacion_id = id_ubicacion_dummy,\
  105. nombre = nombre_nodo,\
  106. descripcion = request.form['descripcion'],\
  107. clave_edicion = clave_edicion,\
  108. bloque_ipv4 = bloque_ipv4_publico+"/"+str(cidr_publica) , \
  109. ipv4_network_addr = bloque_ipv4_publico, \
  110. ipv4_cidr = cidr_publica,\
  111. bloque_ipv4_privado = bloque_ipv4_privado, \
  112. ipv4_cidr_privado = cidr_privada, \
  113. bloque_ipv6 = bloque_ipv6,\
  114. ipv6_network_addr = bloque_ipv6.split("/")[0],\
  115. ipv6_cidr = 128,\
  116. url_descarga=utils.get_randomToken(), \
  117. nombres_responsable = request.form['nombres'],\
  118. apellidos_responsable = request.form['apellidos'],\
  119. email = request.form['email'],\
  120. fecha_creacion = fecha_actual
  121. )
  122. try:
  123. db_session.add(nodo)
  124. db_session.commit()
  125. except IntegrityError:
  126. print ('"IntegrityError" con "Nodo" detectado')
  127. return u"Error Interno, datos duplicados en la base de datos"
  128. # generacion de firmware
  129. #TODO: Antes de comenzar a genera la imagen de firmware,
  130. # mostrar en la pagina actual una notificacion (javascript) de que
  131. # se esta procesando la peticion y que se redijira automaticamente
  132. # cuando el proceso termine y tambien se enviara una notificacion
  133. # por email con el directorio para descarga del firmware.
  134. # marcando variable que indica estado de construccion
  135. g.estado_construccion = 'construyendo'
  136. r = utils_firmware.\
  137. crear_imagenFirmware(request.form['modelos'],\
  138. bloque_ipv4_publico,
  139. cidr_publica
  140. )
  141. if r == "Error":
  142. return render_template("generando_firmware.html", error = "1", \
  143. nombre_nodo=nombre_nodo,\
  144. email=request.form['email'],\
  145. bloque_ipv4=bloque_ipv4_publico+"/"+str(cidr_publica),\
  146. modelo_enrutador=request.form["modelos"],\
  147. nombres_responsable = request.form['nombres'],\
  148. apellidos_responsable = request.form['apellidos'],\
  149. #TODO: quitar lo siguiente
  150. resultado = r,\
  151. ##
  152. nodo=session.get('nodo_id', None),\
  153. p_actual="nodos"
  154. )
  155. else:
  156. #TODO: enviar email indicando que el proceso ha terminado
  157. #...
  158. # enviar senyal ajax indicando que el proceso ha terminado
  159. #...
  160. g.estado_construccion = 'terminado'
  161. time.sleep(10)
  162. return render_template("generando_firmware.html",
  163. nombre_nodo=nombre_nodo,\
  164. email=request.form['email'],\
  165. bloque_ipv4=bloque_ipv4_publico+"/"+str(cidr_publica),\
  166. modelo_enrutador=request.form["modelos"],\
  167. nombres_responsable = request.form['nombres'],\
  168. apellidos_responsable = request.form['apellidos'],\
  169. url_descarga = nodo.url_descarga,\
  170. #TODO: quitar lo siguiente
  171. resultado = r, \
  172. ##
  173. nodo=session.get('nodo_id', None)
  174. )
  175. return "no autorizado"
  176. @gestor.route('/nodos', methods=['GET'])
  177. def lista_nodos():
  178. lista_activos = deque([])
  179. lista_proyectados = deque([])
  180. lista = []
  181. for nodo in db_session.query(Nodo).order_by(Nodo.id).all():
  182. dict = {}
  183. dict['id'] = nodo.id
  184. dict['nombre'] = nodo.nombre
  185. dict['bloque_ipv4'] = nodo.bloque_ipv4
  186. dict['bloque_ipv6'] = nodo.bloque_ipv6
  187. dict['descripcion'] = nodo.descripcion
  188. dict['ubicacion_id'] = nodo.ubicacion_id
  189. dict['tupla_ubicacion'] = utils.obtener_ubicacionResumida(nodo.ubicacion_id)
  190. if nodo.is_active == True:
  191. lista_activos.append(dict)
  192. else:
  193. lista_proyectados.append(dict)
  194. for row in db_session.query(Nodo).all():
  195. lista.append(str(row))
  196. for row in db_session.query(Ubicacion).all():
  197. lista.append(str(row))
  198. flash("Obteniendo lista", 'warning')
  199. return render_template("nodos.html", p_actual="nodos",\
  200. rows=lista, \
  201. lista_proyectados=lista_proyectados,\
  202. lista_activos=lista_activos,
  203. num_activos=utils.num_nodosActivos(),\
  204. num_proyectados=utils.num_nodosProyectados(), \
  205. nodo=session.get('nodo_id', None))
  206. @gestor.route('/nodos/<nodo_id>', methods=['GET'])
  207. def info_nodo(nodo_id):
  208. if not nodo_id.isdigit():
  209. return render_template("404.html"), 404
  210. nodo = db_session.query(Nodo).\
  211. filter(Nodo.id == int(nodo_id)).first()
  212. if nodo is None:
  213. return render_template("404.html"), 404
  214. ubicacion = utils.obtener_ubicacionDetallada(nodo.ubicacion_id)
  215. return render_template("nodo.html",\
  216. nombre = nodo.nombre, \
  217. bloque_ipv4 = nodo.bloque_ipv4, \
  218. ipv4_network_addr = nodo.ipv4_network_addr,\
  219. ipv4_cidr = nodo.ipv4_cidr,\
  220. bloque_ipv6 = nodo.bloque_ipv6,\
  221. ipv6_network_addr = nodo.ipv6_network_addr, \
  222. is_active = nodo.is_active,\
  223. is_confirmed = nodo.is_confirmed, \
  224. url_descarga = nodo.url_descarga,\
  225. fecha_creacion = nodo.fecha_creacion, \
  226. descripcion = nodo.descripcion, \
  227. nombres = nodo.nombres_responsable, \
  228. apellidos = nodo.apellidos_responsable, \
  229. email = nodo.email, \
  230. telf = nodo.telf,
  231. ubicacion = ubicacion, \
  232. nodo=session.get('nodo_id', None)
  233. )
  234. @gestor.route('/descargas/<url>', methods = ['GET'])
  235. def descargas_firmware(url):
  236. # probando que exista un nodo con la url asociada
  237. nodo = db_session.query(Nodo).\
  238. filter(Nodo.url_descarga == url).first()
  239. if nodo is None:
  240. return render_template("404.html") , 404
  241. if not g.nodo:
  242. # password de edicion
  243. return render_template("descarga.html",\
  244. nodo=session.get('nodo_id', None),\
  245. nodo_id=nodo.id,\
  246. nombre=nodo.nombre,\
  247. url=url)
  248. else:
  249. # comprobando que la sesion iniciada sea correspondiente a este nodo
  250. if g.nodo.url_descarga != url:
  251. return render_template("descarga.html",\
  252. incorrecto=True,\
  253. nodo=None,\
  254. nodo_id=nodo.id,\
  255. nombre=nodo.nombre,\
  256. url=url)
  257. # retornar template con los archivos para descargar
  258. carpetas = utils_firmware.carpetas_descargaFirmware(nodo.bloque_ipv4)
  259. return render_template("descarga.html",\
  260. nodo=session['nodo_id'],\
  261. nodo_id=nodo.id,\
  262. nombre=nodo.nombre,\
  263. url=url,
  264. carpetas=carpetas)
  265. return "Falta implementar"
  266. @gestor.route('/descargas/<url>/<carpeta>', methods=['GET'])
  267. def descargas_firmwareCarpetas(url, carpeta=None):
  268. nodo = db_session.query(Nodo).\
  269. filter(Nodo.url_descarga == url).first()
  270. if nodo is None:
  271. return render_template("404.html") , 404
  272. if not g.nodo:
  273. # password de edicion
  274. return render_template("descarga.html",\
  275. nodo=session.get('nodo_id', None),\
  276. nodo_id=nodo.id,\
  277. nombre=nodo.nombre,\
  278. url=url)
  279. else:
  280. # comprobando que la sesion iniciada sea correspondiente a este nodo
  281. if g.nodo.url_descarga != url:
  282. return render_template("descarga.html",\
  283. incorrecto=True,\
  284. nodo=None,\
  285. nodo_id=nodo.id,\
  286. nombre=nodo.nombre,\
  287. url=url)
  288. l = utils_firmware.listar_carpetaFirmware(carpeta=carpeta)
  289. dirs = l[0]
  290. archs = l[1]
  291. return render_template("descarga.html",\
  292. nodo=session['nodo_id'],\
  293. nodo_id=nodo.id,\
  294. nombre=nodo.nombre,\
  295. url=url,\
  296. carpeta=carpeta,\
  297. directorios=dirs,\
  298. archivos=archs)
  299. @gestor.route('/descargas/<url>/login', methods=['POST'])
  300. def login_descargas_firmware(url):
  301. nodo = db_session.query(Nodo).\
  302. filter(Nodo.url_descarga == url).first()
  303. if nodo is None:
  304. return render_template("404.html") , 404
  305. if g.nodo and session['nodo_id'] == nodo.id:
  306. print ("ruta:"+url_for('gestor.descargas_firmware', url=url))
  307. return redirect(url_for('gestor.descargas_firmware', url=url))
  308. else:
  309. # comprobando clave de edicion
  310. if utils.hash_claveEdicion(request.form['password']) == \
  311. nodo.clave_edicion:
  312. print ("--- Descarga de firmware ---")
  313. print ("nodo:"+str(nodo))
  314. print ("clave de edicion correcta :)")
  315. print ("ruta:"+url_for('gestor.descargas_firmware',url=url))
  316. print ("----------------------------")
  317. session['nodo_id'] = nodo.id
  318. return redirect(url_for("gestor.descargas_firmware",url=url))
  319. else:
  320. print ("--- Descarga de firmware ---")
  321. print ("nodo:"+str(nodo))
  322. print ("clave de edicion INCORRECTA")
  323. print ("ruta:"+url_for('gestor.descargas_firmware',url=url))
  324. print ("----------------------------")
  325. return redirect(url_for("gestor.descargas_firmware",url=url))
  326. @gestor.route('/logout', methods=['GET'])
  327. def logout_descargas_firmware():
  328. session.pop('nodo_id', None)
  329. return redirect(url_for('gestor.hello_world'))
  330. # respuestas con json
  331. @gestor.route('/nuevo/_construccion')
  332. def estado_construccion():
  333. print
  334. print ("AJAX construccion")
  335. print
  336. return jsonify(estado=g.estado_construccion)
  337. @gestor.route('/_cons')
  338. def prueba_json():
  339. a = 123+321
  340. return jsonify(r=a)
  341. # errores
  342. @gestor.errorhandler(404)
  343. def page_not_found(error):
  344. return render_template( "404.html" ), 404