Show users tree

This commit is contained in:
Andy Teijelo Pérez 2015-11-04 12:46:20 -05:00
parent ba036d26b7
commit 2a1a8d9e94
6 changed files with 111 additions and 75 deletions

132
main.py
View file

@ -3,14 +3,11 @@
from flask import Flask, request, abort, make_response, \ from flask import Flask, request, abort, make_response, \
render_template, redirect, url_for, \ render_template, redirect, url_for, \
json, jsonify, session, flash json, jsonify, session, flash
from werkzeug import secure_filename
from multiprocessing import Process
from urllib.parse import unquote
import hashlib import hashlib
import random import random
import shutil import shutil
import time import time
import sys
import re import re
import os import os
@ -38,10 +35,12 @@ def delete_user(deluser):
f.close() f.close()
reload_freeradius() reload_freeradius()
def create_user(username, password): def nthash(password):
nthash = hashlib.new('md4',password.encode('utf-16le')).hexdigest().upper() return hashlib.new('md4',password.encode('utf-16le')).hexdigest().upper()
def create_user(username, password, creator):
f = open(users_file,"a") f = open(users_file,"a")
f.write('{} NT-Password := "{}"\n'.format(username, nthash)) f.write('{} NT-Password := "{}" # created by {} \n'.format(username, nthash(password), creator))
f.close() f.close()
reload_freeradius() reload_freeradius()
@ -58,6 +57,22 @@ def index():
return render_template("index.html", guestpass=guestpass) return render_template("index.html", guestpass=guestpass)
def load_users():
users = []
with open(users_file) as f:
for l in f:
if l.strip().startswith("#"):
continue
m = re.match("(^\S+).*-Password\s+:=\s+\"(\S+)\"(?:\s+#.*created.by\s+(\S+))?", l)
if m:
users.append(m.groups())
return users
def check_login(username, password):
for u,p,c in load_users():
if u == username and p == nthash(password):
return True
raise ValueError("Invalid username or password")
@app.route("/login",methods=['GET','POST']) @app.route("/login",methods=['GET','POST'])
def login(): def login():
@ -68,18 +83,20 @@ def login():
if request.method == 'POST': if request.method == 'POST':
username = request.form.get("username",None) username = request.form.get("username",None)
password = request.form.get("password",None) password = request.form.get("password",None)
if username is None or password is None:
return render_template("login.html",error=True,errormsg="invalid username or password")
try: if username is None or password is None:
check_call(["radtest",username,password,"localhost","0","testing123"])
except:
return render_template("login.html",error=True,errormsg="invalid username or password") return render_template("login.html",error=True,errormsg="invalid username or password")
if username == 'guest': if username == 'guest':
return render_template("login.html",error=True,errormsg="guest user has no admin privileges") return render_template("login.html",error=True,errormsg="guest user has no admin privileges")
try:
check_login(username, password)
except Exception as e:
return render_template("login.html",error=True,errormsg=str(e))
session['logged_in'] = True session['logged_in'] = True
session['username'] = username
return redirect(url_for('admin')) return redirect(url_for('admin'))
@app.route("/admin",methods=['GET','POST']) @app.route("/admin",methods=['GET','POST'])
@ -97,6 +114,7 @@ def admin():
username = request.form.get('username',None) username = request.form.get('username',None)
pass1 = request.form.get('password1',None) pass1 = request.form.get('password1',None)
pass2 = request.form.get('password2',None) pass2 = request.form.get('password2',None)
creator = session['username']
if username is not None: if username is not None:
if username == 'guest': if username == 'guest':
return render_template("admin.html", create_error=True, errormsg="Cannot create guest user") return render_template("admin.html", create_error=True, errormsg="Cannot create guest user")
@ -104,67 +122,53 @@ def admin():
pass2 is None or \ pass2 is None or \
pass1 != pass2: pass1 != pass2:
return render_template("admin.html", create_error=True, errormsg="Password do not match") return render_template("admin.html", create_error=True, errormsg="Password do not match")
create_user(username,pass1) create_user(username,pass1,creator)
flash("User created successfully") flash("User created successfully")
return render_template("admin.html") return render_template("admin.html")
def render_users_tree(tree):
lines = []
def _render(user, edges, is_last):
lines.append((edges + (" └─" if is_last else " ├─"), user))
n = len(tree[user])
for i,u in enumerate(tree[user]):
_render(u, edges + (" " if is_last else ""), i == n - 1)
return lines
# root = tree(""); n = len(root)
# for i,u in enumerate(root):
_render("", "", True)
return lines
@app.route("/users")
def list_users():
if not session.get('logged_in', False):
return redirect(url_for('login'))
users = load_users()
users_set = set(x[0] for x in users)
tree = { "": [] }
for user,passwd,creator in users:
if user == "guest":
continue
tree[user] = []
if creator is None:
tree[""].append(user)
else:
if creator not in users_set:
creator += " (invalid username)"
tree[""].append(creator)
tree[creator] = tree.get(creator,[]) + [user]
lines = render_users_tree(tree)
return render_template("users.html", users=lines)
@app.route("/logout") @app.route("/logout")
def logout(): def logout():
session.pop("logged_in",None) session.pop("logged_in",None)
return redirect(url_for("index")) return redirect(url_for("index"))
#@app.route("/upload",methods=['GET','POST'])
#def upload():
# if request.method == 'POST':
# f = request.files['circuit']
# if len(f.filename) == 0:
# return render_template("emptyupload.html")
# if f and len(f.filename) > 0:
# sid = new_id()
# session_dir = os.path.join('sessions',sid)
# shutil.copytree('skel',session_dir)
# old_dir = os.getcwd()
# os.chdir(session_dir)
# try:
# skipcookie = unquote(request.cookies.get('skip_tests',''))
# skip = set(int(n) for n in skipcookie.split(','))
# except:
# skip = set()
# options = {'skip_tests': skip}
# try:
# filename = secure_filename(f.filename)
# f.save(filename)
# p = Process(target=Verifier, args=(filename, ), kwargs={'options': options})
# p.start()
# except:
# os.chdir(old_dir)
# raise
# os.chdir(old_dir)
# return redirect(url_for('tests',sid=sid))
# return "Ocurrió algún error haciendo upload"
#@app.route("/details")
#def details():
# sid = request.args.get('sid','')
# filename = request.args.get('file','')
# if len(sid) == 0:
# return ''
# if len(filename) == 0:
# return ''
# filename = secure_filename(filename)
# session_dir = os.path.join('sessions',sid)
# try:
# f = open(os.path.join(session_dir,filename), encoding="utf8")
# s = f.read()
# f.close()
# except FileNotFoundError:
# s = ""
# resp = make_response(s)
# resp.mimetype = 'text/plain'
# return resp
if __name__ == '__main__': if __name__ == '__main__':
app.debug = True if "debug" in sys.argv:
users_file = "users.dpto2"
app.debug = True
app.run(host="0.0.0.0") app.run(host="0.0.0.0")

View file

@ -16,4 +16,13 @@
#selected-tests span { #selected-tests span {
margin-left: 0.5em; margin-left: 0.5em;
} }
div.users-tree {
line-height: initial;
}
.edges {
font-family: monospace;
line-height: initial;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 7.4 KiB

View file

@ -6,7 +6,7 @@
{% endblock %} {% endblock %}
{% block content %} {% block content %}
<center><h1>Usuarios de <code>dpto2</code></h1></center> <center><h2>Usuarios de <code>dpto2</code></h2></center>
{% with messages = get_flashed_messages() %} {% with messages = get_flashed_messages() %}
{% if messages %} {% if messages %}
@ -18,7 +18,6 @@
{% endif %} {% endif %}
{% endwith %} {% endwith %}
<div class="container" style="width: 601px;">
<div class="row"><h3>Crear usuario nuevo:</h3></div> <div class="row"><h3>Crear usuario nuevo:</h3></div>
<div class="row"> <div class="row">
@ -76,7 +75,7 @@
</div> </div>
</form> </form>
</div> </div>
<div class="row"><a href="{{ url_for('list_users') }}">Lista de usuarios</a></div>
<div class="row"><a href="{{ url_for('logout') }}">Cerrar sesión</a></div> <div class="row"><a href="{{ url_for('logout') }}">Cerrar sesión</a></div>
</div>
{% endblock %} {% endblock %}

View file

@ -10,7 +10,7 @@
<link href="{{ static('css/bootstrap.min.css') }}" rel="stylesheet"> <link href="{{ static('css/bootstrap.min.css') }}" rel="stylesheet">
<link href="{{ static('css/font-awesome.min.css') }}" rel="stylesheet"> <link href="{{ static('css/font-awesome.min.css') }}" rel="stylesheet">
<link href="{{ static('css/isabel.css') }}" rel="stylesheet"> <link href="{{ static('css/isabel.css') }}" rel="stylesheet">
<!-- <link href="{{ static('img/icon.png') }}" rel="icon"/> --> <link href="{{ static('img/icon.png') }}" rel="icon"/>
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) --> <!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
<script src="{{ static('js/cookies.js')}}"></script> <script src="{{ static('js/cookies.js')}}"></script>
@ -27,14 +27,10 @@
{% endblock %} {% endblock %}
</head> </head>
<body> <body>
<div class="container"> <div class="container" style="width: 600px;">
<div class="row">
<div class="col-md-12">
{% block content %} {% block content %}
{% endblock %} {% endblock %}
</div>
</div>
</div> </div>
{% block body_scripts %} {% block body_scripts %}

28
templates/users.html Normal file
View file

@ -0,0 +1,28 @@
{% extends "base.html" %}
{% block title %}Usuarios{% endblock %}
{% block head %}
{{ super() }}
{% endblock %}
{% block content %}
<div class="row"><h3>Usuarios de <code>dpto2</code>:</h3></div>
<div class="well well-lg">
<div class="users-tree">
{% for edges, username in users %}
<span>
{% if username == "" %}
&nbsp;&nbsp;<i>Ilúvatar</i>
{% else %}
<span class="edges">{{ edges|replace(" ","&nbsp;")|safe }}</span>
{{ username }}
{% endif %}
</span><br>
{% endfor %}
</div>
</div>
<div class="row"><a href="{{ url_for('admin') }}">Administrar usuarios</a></div>
<div class="row"><a href="{{ url_for('logout') }}">Cerrar sesión</a></div>
{% endblock %}