Show users tree
This commit is contained in:
parent
ba036d26b7
commit
2a1a8d9e94
6 changed files with 111 additions and 75 deletions
130
main.py
130
main.py
|
@ -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__':
|
||||||
|
if "debug" in sys.argv:
|
||||||
|
users_file = "users.dpto2"
|
||||||
app.debug = True
|
app.debug = True
|
||||||
app.run(host="0.0.0.0")
|
app.run(host="0.0.0.0")
|
||||||
|
|
|
@ -17,3 +17,12 @@
|
||||||
#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 |
|
@ -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 %}
|
||||||
|
|
|
@ -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>
|
||||||
|
@ -28,14 +28,10 @@
|
||||||
</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 %}
|
||||||
<!-- Include all compiled plugins (below), or include individual files as needed -->
|
<!-- Include all compiled plugins (below), or include individual files as needed -->
|
||||||
|
|
28
templates/users.html
Normal file
28
templates/users.html
Normal 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 == "" %}
|
||||||
|
<i>Ilúvatar</i>
|
||||||
|
{% else %}
|
||||||
|
<span class="edges">{{ edges|replace(" "," ")|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 %}
|
Loading…
Reference in a new issue