hsman/app/views/main.py

155 lines
4.9 KiB
Python

import logging
import datetime
import os
from flask import current_app
from flask import render_template, Blueprint
from flask import redirect, session, url_for
from app import auth
# from ..lib import username
from flask import jsonify, make_response
from flask_pyoidc.user_session import UserSession
from hsapi_client import Node, User, Route, PreAuthKey, Policy
from hsapi_client.preauthkeys import v1ListPreAuthKeyRequest
log = logging.getLogger()
main_blueprint = Blueprint(
'main', __name__, url_prefix=os.getenv('APPLICATION_ROOT', '/'))
@main_blueprint.route('/health', methods=['GET'])
def health():
return jsonify(dict(status="OK", version=current_app.config['APP_VERSION']))
@main_blueprint.route('/token', methods=['GET', 'POST'])
@auth.authorize_admins('default')
def token():
user_session = UserSession(session)
return jsonify(access_token=user_session.access_token,
id_token=user_session.id_token,
userinfo=user_session.userinfo)
@main_blueprint.route('/', methods=['GET', 'POST'])
@auth.access_control('default')
def index():
hs_user = auth.username
userNodeList = [n for n in Node().list().nodes if n.user.name == hs_user]
return render_template('index.html',
userNodeList=userNodeList)
@main_blueprint.route('/logout')
@auth.oidc_logout
def logout():
return redirect(url_for('main.index'))
@main_blueprint.route('/nodes', methods=['GET'])
@auth.authorize_admins('default')
def nodes():
nodelist = Node().list()
return render_template('nodes.html',
nodes=nodelist.nodes)
@main_blueprint.route('/node/<int:nodeId>', methods=['GET'])
@auth.access_control('default')
def node(nodeId):
# There is a bug in HS api with retrieving a single node
# and we added a workaround to hsapi, so node.get() returns a
# v1Node object instead of v1NodeResponse, so we access directly
# `node`, instead of `node.node`
if not auth.userOrAdmin(auth.username):
return auth.unathorized
node = Node().get(nodeId)
routes = Node().routes(nodeId)
isExitNode = any(
(r for r in routes.routes if r.prefix.endswith('0/0') and r.enabled))
return render_template("node.html",
routes=routes.routes,
isExitNode=isExitNode,
node=node)
@main_blueprint.route('/users', methods=['GET'])
@auth.authorize_admins('default')
def users():
userList = User().list()
# Get online status of devices of the user
online = {}
nodeList = Node().list()
for user in userList.users:
userNodeList = [n for n in nodeList.nodes if n.user.name == user.name]
online[user.name] = any(map(lambda x: x.online, userNodeList))
return render_template('users.html',
users=userList.users,
online=online)
@main_blueprint.route('/user/<userName>', methods=['GET'])
@auth.authorize_admins('default')
def user(userName):
user = User().get(userName)
userNodeList = [n for n in Node().list().nodes if n.user.name == userName]
preauthkeyreq = v1ListPreAuthKeyRequest(user=userName)
preauthKeys = PreAuthKey().list(preauthkeyreq)
defaultExpiry = datetime.datetime.now() + datetime.timedelta(days=7)
expStr = defaultExpiry.strftime('%Y-%m-%dT%H:%M')
return render_template("user.html",
user=user.user,
defaultExpiry=expStr,
preauthKeys=preauthKeys.preAuthKeys,
userNodeList=userNodeList)
@main_blueprint.route('/routes', methods=['GET'])
@auth.authorize_admins('default')
def routes():
routes = Route().list()
prefixes = sorted(set(
(r.prefix for r in routes.routes if not r.prefix.endswith('/0'))))
exitNodes = [r.node for r in routes.routes if r.prefix.endswith(
'0/0') and r.enabled]
final = {}
for prefix in prefixes:
rrp = [x for x in routes.routes if x.prefix == prefix]
final[prefix] = sorted(rrp, key=lambda x: x.isPrimary, reverse=True)
return render_template("routes.html",
exitNodes=exitNodes,
routes=final)
@main_blueprint.route('/policy', defaults={'action': None}, methods=['GET'])
@main_blueprint.route('/policy/<action>', methods=['GET'])
@auth.authorize_admins('default')
def policy(action):
policy = Policy().get()
if action == "view":
return policy.json
elif action == "download":
updateStr = policy.updatedAt.strftime(format='%Y%m%d-%H%M')
log.debug(updateStr)
filename = f"acl-{updateStr}.json"
response = make_response(policy.json)
response.headers['Content-Disposition'] = f'attachment; filename={
filename}'
return response
else:
return render_template("policy.html",
policy=policy)