diff --git a/main.py b/main.py index f37c872..8478ef0 100755 --- a/main.py +++ b/main.py @@ -3,14 +3,11 @@ from flask import Flask, request, abort, make_response, \ render_template, redirect, url_for, \ json, jsonify, session, flash -from werkzeug import secure_filename -from multiprocessing import Process -from urllib.parse import unquote - import hashlib import random import shutil import time +import sys import re import os @@ -38,10 +35,12 @@ def delete_user(deluser): f.close() reload_freeradius() -def create_user(username, password): - nthash = hashlib.new('md4',password.encode('utf-16le')).hexdigest().upper() +def nthash(password): + return hashlib.new('md4',password.encode('utf-16le')).hexdigest().upper() + +def create_user(username, password, creator): 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() reload_freeradius() @@ -58,6 +57,22 @@ def index(): 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']) def login(): @@ -68,18 +83,20 @@ def login(): if request.method == 'POST': username = request.form.get("username",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: - check_call(["radtest",username,password,"localhost","0","testing123"]) - except: + if username is None or password is None: return render_template("login.html",error=True,errormsg="invalid username or password") if username == 'guest': 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['username'] = username return redirect(url_for('admin')) @app.route("/admin",methods=['GET','POST']) @@ -97,6 +114,7 @@ def admin(): username = request.form.get('username',None) pass1 = request.form.get('password1',None) pass2 = request.form.get('password2',None) + creator = session['username'] if username is not None: if username == 'guest': return render_template("admin.html", create_error=True, errormsg="Cannot create guest user") @@ -104,67 +122,53 @@ def admin(): pass2 is None or \ pass1 != pass2: 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") 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") def logout(): session.pop("logged_in",None) 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__': - app.debug = True + if "debug" in sys.argv: + users_file = "users.dpto2" + app.debug = True app.run(host="0.0.0.0") diff --git a/static/css/isabel.css b/static/css/isabel.css index 6383587..12cb83c 100644 --- a/static/css/isabel.css +++ b/static/css/isabel.css @@ -16,4 +16,13 @@ #selected-tests span { margin-left: 0.5em; -} \ No newline at end of file +} + +div.users-tree { + line-height: initial; +} + +.edges { + font-family: monospace; + line-height: initial; +} diff --git a/static/img/icon.png b/static/img/icon.png index 7472f85..10436b5 100644 Binary files a/static/img/icon.png and b/static/img/icon.png differ diff --git a/templates/admin.html b/templates/admin.html index ae09838..2109779 100644 --- a/templates/admin.html +++ b/templates/admin.html @@ -6,7 +6,7 @@ {% endblock %} {% block content %} -

Usuarios de dpto2

+

Usuarios de dpto2

{% with messages = get_flashed_messages() %} {% if messages %} @@ -18,7 +18,6 @@ {% endif %} {% endwith %} -

Crear usuario nuevo:

@@ -76,7 +75,7 @@
+
Lista de usuarios
Cerrar sesión
- {% endblock %} diff --git a/templates/base.html b/templates/base.html index edec241..fa69b6d 100644 --- a/templates/base.html +++ b/templates/base.html @@ -10,7 +10,7 @@ - + @@ -27,14 +27,10 @@ {% endblock %} - -
-
-
+ +
{% block content %} {% endblock %} -
-
{% block body_scripts %} diff --git a/templates/users.html b/templates/users.html new file mode 100644 index 0000000..16046b7 --- /dev/null +++ b/templates/users.html @@ -0,0 +1,28 @@ +{% extends "base.html" %} +{% block title %}Usuarios{% endblock %} + +{% block head %} + {{ super() }} +{% endblock %} + +{% block content %} +

Usuarios de dpto2:

+ +
+
+ {% for edges, username in users %} + + {% if username == "" %} +   Ilúvatar + {% else %} + {{ edges|replace(" "," ")|safe }} + {{ username }} + {% endif %} +
+ {% endfor %} +
+
+ +
Administrar usuarios
+
Cerrar sesión
+{% endblock %}