From a382f2ff0910143c2bd173983e04c14a693a2c4b Mon Sep 17 00:00:00 2001 From: Melina Gamboa Date: Thu, 3 Jun 2021 10:49:05 +0200 Subject: [PATCH] Admin login --- admin/src/admin/__init__.py | 1 + admin/src/admin/auth/__init__.py | 0 admin/src/admin/auth/authentication.py | 32 +++++++++++++++++++ admin/src/admin/static/templates/login.html | 2 +- .../admin/static/templates/pages/users.html | 2 ++ admin/src/admin/views/AvatarViews.py | 2 ++ admin/src/admin/views/LoginViews.py | 30 +++++++++++++++++ admin/src/admin/views/MenuViews.py | 23 ++++++------- docker/haproxy/haproxy.conf | 10 +++--- 9 files changed, 85 insertions(+), 17 deletions(-) create mode 100644 admin/src/admin/auth/__init__.py create mode 100644 admin/src/admin/auth/authentication.py create mode 100644 admin/src/admin/views/LoginViews.py diff --git a/admin/src/admin/__init__.py b/admin/src/admin/__init__.py index 7aaeb9d..f0ac127 100644 --- a/admin/src/admin/__init__.py +++ b/admin/src/admin/__init__.py @@ -80,6 +80,7 @@ def send_avatars_img(path): ''' Import all views ''' +from .views import LoginViews from .views import MenuViews from .views import AvatarViews diff --git a/admin/src/admin/auth/__init__.py b/admin/src/admin/auth/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/admin/src/admin/auth/authentication.py b/admin/src/admin/auth/authentication.py new file mode 100644 index 0000000..43d21e9 --- /dev/null +++ b/admin/src/admin/auth/authentication.py @@ -0,0 +1,32 @@ +from admin import app +from flask_login import LoginManager, UserMixin + +import os + +login_manager = LoginManager() +login_manager.init_app(app) +login_manager.login_view = "login" + +ram_users={ + os.environ["ADMINAPP"]: { + 'id': os.environ["ADMINAPP"], + 'password': os.environ["ADMINAPP_PASSWORD"], + 'role': 'admin' + }, + os.environ["KEYCLOAK_USER"]: { + 'id': os.environ["KEYCLOAK_USER"], + 'password': os.environ["KEYCLOAK_PASSWORD"], + 'role': 'admin-keycloak', + } +} + +class User(UserMixin): + def __init__(self, dict): + self.id = dict['id'] + self.username = dict['id'] + self.password = dict['password'] + self.role = dict['role'] + +@login_manager.user_loader +def user_loader(username): + return User(ram_users[username]) diff --git a/admin/src/admin/static/templates/login.html b/admin/src/admin/static/templates/login.html index ef1680b..ae4f00c 100644 --- a/admin/src/admin/static/templates/login.html +++ b/admin/src/admin/static/templates/login.html @@ -22,7 +22,7 @@ - +
diff --git a/admin/src/admin/static/templates/pages/users.html b/admin/src/admin/static/templates/pages/users.html index 0fd62fb..6dfd542 100644 --- a/admin/src/admin/static/templates/pages/users.html +++ b/admin/src/admin/static/templates/pages/users.html @@ -27,6 +27,7 @@ + {% if current_user.role =='admin-keycloak' %} @@ -36,6 +37,7 @@ + {% endif %} diff --git a/admin/src/admin/views/AvatarViews.py b/admin/src/admin/views/AvatarViews.py index 52ebb8a..84c180f 100644 --- a/admin/src/admin/views/AvatarViews.py +++ b/admin/src/admin/views/AvatarViews.py @@ -8,6 +8,7 @@ from uuid import uuid4 import time,json import sys,os from flask import render_template, Response, request, redirect, url_for, jsonify, send_file +from flask_login import login_required from pprint import pprint @@ -16,6 +17,7 @@ from ..lib.avatars import Avatars avatars=Avatars() @app.route('/isard-sso-admin/avatar/', methods=['GET']) +@login_required def avatar(username): userid=avatars.username2id(username) if userid: diff --git a/admin/src/admin/views/LoginViews.py b/admin/src/admin/views/LoginViews.py new file mode 100644 index 0000000..e5d4d53 --- /dev/null +++ b/admin/src/admin/views/LoginViews.py @@ -0,0 +1,30 @@ +import os + +from admin import app +from flask import render_template, flash, request, redirect, url_for +from ..auth.authentication import * +from flask_login import login_required, current_user, login_user, logout_user + +@app.route('/isard-sso-admin/login', methods=['GET', 'POST']) +def login(): + if request.method == 'POST': + if request.form['user'] == '' or request.form['password'] == '': + flash("Can't leave it blank",'danger') + elif request.form['user'].startswith(' '): + flash('Username not found or incorrect password.','warning') + else: + ram_user=ram_users.get(request.form['user']) + if ram_user and request.form['password'] == ram_user['password']: + user=User({'id': ram_user['id'], 'password': ram_user['password'], 'role': ram_user['role'], 'active': True}) + login_user(user) + flash('Logged in successfully.','success') + return redirect(url_for('users')) + else: + flash('Username not found or incorrect password.','warning') + return render_template('login.html') + +@app.route('/isard-sso-admin/logout', methods=['GET']) +@login_required +def logout(): + logout_user() + return redirect(url_for('login')) diff --git a/admin/src/admin/views/MenuViews.py b/admin/src/admin/views/MenuViews.py index 088e591..d3f99e6 100644 --- a/admin/src/admin/views/MenuViews.py +++ b/admin/src/admin/views/MenuViews.py @@ -9,6 +9,7 @@ import time,json import sys,os from flask import render_template, Response, request, redirect, url_for, jsonify import concurrent.futures +from flask_login import login_required from pprint import pprint @@ -17,13 +18,13 @@ from pprint import pprint # socketio = SocketIO(app) @app.route('/isard-sso-admin/resync') -# @login_required +@login_required def resync(): return json.dumps(app.admin.resync_data()), 200, {'Content-Type': 'application/json'} @app.route('/isard-sso-admin/users', methods=['GET']) @app.route('/isard-sso-admin/users/', methods=['POST', 'PUT', 'GET', 'DELETE']) -# @login_required +@login_required def users(provider=False): if request.method == 'DELETE': if provider == 'keycloak': @@ -40,25 +41,25 @@ def users(provider=False): return render_template('pages/users.html', title="Users", nav="Users") @app.route('/isard-sso-admin/users_list') -# @login_required +@login_required def users_list(): return json.dumps(app.admin.get_mix_users()), 200, {'Content-Type': 'application/json'} @app.route('/isard-sso-admin/roles') -# @login_required +@login_required def roles(): return render_template('pages/roles.html', title="Roles", nav="Roles") @app.route('/isard-sso-admin/roles_list') -# @login_required +@login_required def roles_list(): return json.dumps(app.admin.get_roles()), 200, {'Content-Type': 'application/json'} @app.route('/isard-sso-admin/groups') @app.route('/isard-sso-admin/groups/', methods=['POST', 'PUT', 'GET', 'DELETE']) -# @login_required +@login_required def groups(provider=False): if request.method == 'DELETE': if provider == 'keycloak': @@ -66,13 +67,13 @@ def groups(provider=False): return render_template('pages/groups.html', title="Groups", nav="Groups") @app.route('/isard-sso-admin/groups_list') -# @login_required +@login_required def groups_list(): return json.dumps(app.admin.get_mix_groups()), 200, {'Content-Type': 'application/json'} @app.route('/isard-sso-admin/external', methods=['POST', 'PUT', 'GET']) -# @login_required +@login_required def external(): if request.method == 'POST': data=request.get_json(force=True) @@ -86,17 +87,17 @@ def external(): return render_template('pages/external.html', title="External", nav="External") @app.route('/isard-sso-admin/external_users_list') -# @login_required +@login_required def external_users_list(): return json.dumps(app.admin.get_external_users()), 200, {'Content-Type': 'application/json'} @app.route('/isard-sso-admin/external_groups_list') -# @login_required +@login_required def external_groups_list(): return json.dumps(app.admin.get_external_groups()), 200, {'Content-Type': 'application/json'} @app.route('/isard-sso-admin/external/roles', methods=['PUT']) -# @login_required +@login_required def external_roles(): if request.method == 'PUT': return json.dumps(app.admin.external_roleassign(request.get_json(force=True))), 200, {'Content-Type': 'application/json'} diff --git a/docker/haproxy/haproxy.conf b/docker/haproxy/haproxy.conf index 7ffdcb0..b846568 100644 --- a/docker/haproxy/haproxy.conf +++ b/docker/haproxy/haproxy.conf @@ -97,8 +97,8 @@ backend be_admin timeout queue 600s timeout server 600s timeout connect 600s - acl authorized http_auth(AuthUsers) - http-request auth realm AuthUsers unless authorized + # acl authorized http_auth(AuthUsers) + # http-request auth realm AuthUsers unless authorized acl existing-x-forwarded-host req.hdr(X-Forwarded-Host) -m found acl existing-x-forwarded-proto req.hdr(X-Forwarded-Proto) -m found http-request add-header X-Forwarded-Host %[req.hdr(Host)] unless existing-x-forwarded-host @@ -107,11 +107,11 @@ backend be_admin backend be_adminer mode http - acl authorized http_auth(AuthUsers) - http-request auth realm AuthUsers unless authorized + # acl authorized http_auth(AuthUsers) + # http-request auth realm AuthUsers unless authorized http-request redirect scheme http drop-query append-slash if { path -m str /isard-sso-adminer } http-request replace-path /isard-sso-adminer/(.*) /\1 - http-request del-header Authorization + # http-request del-header Authorization acl existing-x-forwarded-host req.hdr(X-Forwarded-Host) -m found acl existing-x-forwarded-proto req.hdr(X-Forwarded-Proto) -m found http-request add-header X-Forwarded-Host %[req.hdr(Host)] unless existing-x-forwarded-host