From bf775e658ea5966ce70c17decabcfaef8424af33 Mon Sep 17 00:00:00 2001 From: deflax Date: Sun, 4 Jun 2017 17:10:38 +0300 Subject: [PATCH] adding admin page --- README.md | 3 + app/__init__.py | 5 +- app/admin/__init__.py | 3 + app/admin/routes.py | 94 ++++++++++ app/models.py | 17 +- app/templates/admin/dashboard.html | 255 ++++++++++++++++++++++++++ app/templates/admin/users.html | 8 + app/templates/footer_index.html | 9 +- app/templates/vmanager/dashboard.html | 86 +++++++-- app/vmanager/routes.py | 48 ++--- 10 files changed, 475 insertions(+), 53 deletions(-) create mode 100644 app/admin/__init__.py create mode 100644 app/admin/routes.py create mode 100644 app/templates/admin/dashboard.html create mode 100644 app/templates/admin/users.html diff --git a/README.md b/README.md index 3862749..3bdaee0 100644 --- a/README.md +++ b/README.md @@ -68,3 +68,6 @@ server { 1. crontab -e 2. @reboot /usr/bin/screen -dmS proxadmin /home/proxadmin/appserver/proxmaster-panel/start.sh + +### backup the database: +1. python3 manage.py dump create diff --git a/app/__init__.py b/app/__init__.py index 573e32b..b7478bd 100644 --- a/app/__init__.py +++ b/app/__init__.py @@ -44,6 +44,9 @@ app.register_blueprint(news_blueprint, url_prefix='/news') from .auth import auth as auth_blueprint app.register_blueprint(auth_blueprint, url_prefix='/auth') +from .admin import admin as admin_blueprint +app.register_blueprint(admin_blueprint, url_prefix='/' + app.config['ADMIN_PREFIX']) + from .settings import settings as settings_blueprint app.register_blueprint(settings_blueprint, url_prefix='/settings') @@ -85,7 +88,7 @@ def forbidden(e): response = jsonify({'error': 'forbidden'}) response.status_code = 403 return response - return render_template('errors/403.html'), 403 + return render_template('errors/403.html'), 403 @app.errorhandler(404) def page_not_found(e): diff --git a/app/admin/__init__.py b/app/admin/__init__.py new file mode 100644 index 0000000..f933ea1 --- /dev/null +++ b/app/admin/__init__.py @@ -0,0 +1,3 @@ +from flask import Blueprint +admin = Blueprint('admin', __name__) +from . import routes diff --git a/app/admin/routes.py b/app/admin/routes.py new file mode 100644 index 0000000..3ee9907 --- /dev/null +++ b/app/admin/routes.py @@ -0,0 +1,94 @@ +from flask import render_template, abort, redirect, url_for, abort, flash, request, current_app, make_response, g +from flask_login import login_required, login_user, logout_user +from flask_sqlalchemy import get_debug_queries + +from . import admin +from .. import db +from ..email import send_email +from ..models import User, Role, Deployment, Service, Region, Address, Domain, contact_proxmaster +from ..decorators import admin_required, permission_required + +import base64 +import string +import random +from datetime import datetime, timedelta, date, time +import ast + +#@admin.before_app_request +#def before_request(): +# g.user = current_user +# print('current_user: %s, g.user: %s, leaving bef_req' % (current_user, g.user)) + +@admin.after_app_request +def after_request(response): + for query in get_debug_queries(): + if query.duration >= current_app.config['SLOW_DB_QUERY_TIME']: + current_app.logger.warning('Slow query: %s\nParameters: %s\nDuration: %fs\nContext: %s\n' % (query.statement, query.parameters, query.duration, query.context)) + return response + +@admin.route("/", methods=['GET']) +@login_required +@admin_required +def index(): + allusers = User.query.all() + return render_template('admin/users.html', users=allusers) + +@admin.route("/dashboard/", methods=['GET', 'POST']) +@login_required +@admin_required +def dashboard(user_pid=0): + cuser = User.query.filter_by(pid=user_pid).first() + + deployments = cuser.inv_deployments.order_by(Deployment.date_created.desc()).all() + inv_deploycubeids = [] + inv_deploynames = [] + for invcls in deployments: + if invcls.user_id == cuser.pid and invcls.enabled == True: + inv_deploycubeids.extend([invcls.machine_id]) + inv_deploynames.extend([invcls.machine_alias]) + + services = cuser.inv_services.order_by(Service.date_created.desc()).all() + inv_services = [] + for invcls in services: + if invcls.user_id == cuser.pid and invcls.enabled == True: + inv_services.extend([invcls.description]) + + domains = cuser.inv_domains.order_by(Domain.date_created.desc()).all() + inv_domains = [] + for invcls in domains: + if invcls.user_id == cuser.pid and invcls.enabled == True: + inv_domains.extend([invcls.fqdn]) + + addresses = cuser.inv_addresses.order_by(Address.date_assigned.desc()).all() + inv_addresses = [] + for invcls in addresses: + if invcls.user_id == cuser.pid and invcls.enabled == True: + inv_addresses.extend([invcls.ip]) + + #extract rrd and status from the deployments + rrd = {} + statuses = {} + for cubeid in inv_deploycubeids: + rrd[cubeid] = {} + try: + query = contact_proxmaster({}, 'vmrrd', cubeid) + except: + flash('Deploy #{} unreachable.'.format(str(cubeid))) + + graphs_list = ['net', 'cpu', 'mem', 'hdd'] + try: + for graph in graphs_list: + raw = query[graph]['image'].encode('raw_unicode_escape') + rrd[cubeid][graph] = base64.b64encode(raw).decode() + status = { cubeid : query['status'] } + statuses.update(status) + except Exception as e: + print(e) + flash('Deploy #{} unreachable. Support is notified'.format(str(cubeid))) + send_email(current_app.config['MAIL_USERNAME'], 'Cube {} is unreachable'.format(cubeid), + 'vmanager/email/adm_unreachable', user=cuser, cubeid=cubeid ) + + current_app.logger.info('[{}] deployments: {}, domains: {}, services: {}'.format(cuser.email, inv_deploynames, inv_services, inv_domains, inv_addresses )) + return render_template('admin/dashboard.html', rrd=rrd, status=statuses, inv_deployments=deployments, inv_services=services, inv_domains=domains, inv_addresses=addresses) + + diff --git a/app/models.py b/app/models.py index f44a88d..29d796b 100644 --- a/app/models.py +++ b/app/models.py @@ -86,7 +86,7 @@ class User(db.Model, UserMixin): inv_deployments = db.relationship('Deployment', backref='owner', lazy='dynamic') inv_services = db.relationship('Service', backref='owner', lazy='dynamic') inv_domains = db.relationship('Domain', backref='owner', lazy='dynamic') - inv_address = db.relationship('Address', backref='owner', lazy='dynamic') + inv_addresses = db.relationship('Address', backref='owner', lazy='dynamic') def __init__(self, **kwargs): super(User, self).__init__(**kwargs) @@ -223,12 +223,15 @@ class Service(db.Model): __tablename__ = 'services' pid = db.Column(db.Integer, primary_key=True) #PK user_id = db.Column(db.Integer, db.ForeignKey('users.pid')) #FK + date_created = db.Column(db.DateTime, index=True, default=datetime.utcnow) + date_expire = db.Column(db.DateTime) + enabled = db.Column(db.Boolean) + name = db.Column(db.String(64)) image = db.Column(db.String(128)) description = db.Column(db.Unicode(128)) unit = db.Column(db.Integer) unitprice = db.Column(db.Float) - enabled = db.Column(db.Boolean) class Deployment(db.Model): __tablename__ = 'deployments' @@ -243,7 +246,6 @@ class Deployment(db.Model): machine_cpu = db.Column(db.Integer) machine_mem = db.Column(db.Integer) machine_hdd = db.Column(db.Integer) - machine_ipv4list = db.Column(db.String) def charge(): result = Deployment.query.all() @@ -269,6 +271,8 @@ class Deployment(db.Model): class Region(db.Model): __tablename__ = 'regions' pid = db.Column(db.Integer, primary_key=True) + enabled = db.Column(db.Boolean) + name = db.Column(db.String(64)) description = db.Column(db.String(128)) extraprice = db.Column(db.Float) @@ -276,17 +280,20 @@ class Region(db.Model): class Address(db.Model): __tablename__ = 'address' pid = db.Column(db.Integer, primary_key=True) + enabled = db.Column(db.Boolean) + date_assigned = db.Column(db.DateTime, index=True, default=datetime.utcnow) user_id = db.Column(db.Integer, db.ForeignKey('users.pid')) #FK region_id = db.Column(db.Integer, db.ForeignKey('regions.pid')) #FK - ipv4 = db.Column(db.String(64)) - ipv6 = db.Column(db.String(256)) + ip = db.Column(db.String(64)) rdns = db.Column(db.String(256)) macaddr = db.Column(db.String(128)) class Domain(db.Model): __tablename__ = 'domains' pid = db.Column(db.Integer, primary_key=True) + enabled = db.Column(db.Boolean) + user_id = db.Column(db.Integer, db.ForeignKey('users.pid')) #FK date_created = db.Column(db.DateTime, index=True, default=datetime.utcnow) date_expire = db.Column(db.DateTime) diff --git a/app/templates/admin/dashboard.html b/app/templates/admin/dashboard.html new file mode 100644 index 0000000..02e8a7f --- /dev/null +++ b/app/templates/admin/dashboard.html @@ -0,0 +1,255 @@ +{% extends "base.html" %} + +{% block styles %} +{{ super() }} + + + +{% endblock %} + +{% block scripts %} +{{ super() }} + + +{% endblock %} + +{% block page_content %} +
+
+
+ +
+
+
Deployments
+

+ + + + + + + + + + + + + {% for deploy in inv_deployments %} + + + + + + + + + + {% endfor %} + +
NameCPUMemHDDIPv4Control
+ {% if status[deploy.machine_id] == 'running' %}{% else %}{% endif %}{{ deploy.machine_alias }}{{ deploy.machine_cpu }} Cores{{ deploy.machine_mem }} MB{{ deploy.machine_hdd }} GB0.0.0.0{% if status[deploy.machine_id] == 'running' %} + + + {% else %} + + {% endif %}{% if status[deploy.machine_id] == 'running' %} + + {% endif %}
+ +

+
+
+ +
+
+
Domains
+

+ + + + + + + + + {% for domain in inv_domains %} + + + + + + {% endfor %} + +
NameExpiry DateControl
{{ domain.fqdn }}{{ domain.date_expire }}soon...
+ +

+
+
+ +
+
+
Addresses
+

+ + + + + + + + + + {% for address in inv_addresses %} + + + + + + {% endfor %} + + +
IPReverse DNSMAC Addr.Control
{{ address.ip }}{{ address.rdns }}{{ address.macaddr }}soon...
+ +

+
+
+ +
+
+
Services
+

+ + + + + + + + + + {% for service in inv_services %} + + + + + + + {% endfor %} + +
NameDescriptionUnitPrice
{{ service.name }}{{ service.description }}{{ service.unit }}{{ service.unitprice }}
+ + +

+
+
+ +
+ + +
+
+
+ +{% endblock %} + diff --git a/app/templates/admin/users.html b/app/templates/admin/users.html new file mode 100644 index 0000000..7d0ebfd --- /dev/null +++ b/app/templates/admin/users.html @@ -0,0 +1,8 @@ +{% extends "base.html" %} + +{% block page_content %} +
+
+
+ +{% endblock %} diff --git a/app/templates/footer_index.html b/app/templates/footer_index.html index bb55f71..592eb48 100644 --- a/app/templates/footer_index.html +++ b/app/templates/footer_index.html @@ -14,14 +14,7 @@
-

Newsletter Signup

-

Join our newsletter to stay informed on our latest updates and sales.

-
-
- - -
-
+

diff --git a/app/templates/vmanager/dashboard.html b/app/templates/vmanager/dashboard.html index 6c86b91..8866374 100644 --- a/app/templates/vmanager/dashboard.html +++ b/app/templates/vmanager/dashboard.html @@ -106,6 +106,7 @@ addEventListener("DOMContentLoaded", function() { // and then we send it off request.send(); //alert("command " + command + " executed."); + window.location.reload(); } }); } @@ -119,10 +120,9 @@ addEventListener("DOMContentLoaded", function() {
-
+
Deployments

- {% if inv_deploymens == None %} @@ -142,7 +142,7 @@ addEventListener("DOMContentLoaded", function() { - +
{{ deploy.machine_cpu }} Cores {{ deploy.machine_mem }} MB {{ deploy.machine_hdd }} GB{% for ip in deploy.machine_ipv4list %}{{ ip }}{% endfor %}0.0.0.0 {% if status[deploy.machine_id] == 'running' %} @@ -156,38 +156,89 @@ addEventListener("DOMContentLoaded", function() { {% endfor %}
- {% endif %}

-
-
+
+
Domains

+ + + + + + + + {% for domain in inv_domains %} - {{ fqdn }} + + + + + {% endfor %} - + +
NameExpiry DateControl
{{ domain.fqdn }}{{ domain.date_expire }}soon...
+

+
+
+
Addresses
+

+ + + + + + + + + + {% for address in inv_addresses %} + + + + + + {% endfor %} + + +
IPReverse DNSMAC Addr.Control
{{ address.ip }}{{ address.rdns }}{{ address.macaddr }}soon...
+ +

+
+
-
+
Services

- {% for contract in inv_contracts %} - {{ contract.description }}
- {{ contract.units }}
- {% if not contract.discount == 0 %} - Discount %{{ contract.discount }}
- Credit: {{ contract.credit }}
- {% endif %} + + + + + + + + + + {% for service in inv_services %} + + + + + + {% endfor %} - + +
NameDescriptionUnitPrice
{{ service.name }}{{ service.description }}{{ service.unit }}{{ service.unitprice }}
+

@@ -202,4 +253,3 @@ addEventListener("DOMContentLoaded", function() { {% endblock %} - diff --git a/app/vmanager/routes.py b/app/vmanager/routes.py index 1449d32..0e4972f 100644 --- a/app/vmanager/routes.py +++ b/app/vmanager/routes.py @@ -122,25 +122,31 @@ def deploy(product_id=None): @vmanager.route("/dashboard", methods=['GET', 'POST']) @login_required def dashboard(): - deployments = current_user.inv_deployments.order_by(Deployment.date_created.desc()).all() - inv_deploycubeids = [] - inv_deploynames = [] - for invcls in deployments: - if invcls.enabled == True: - inv_deploycubeids.extend([invcls.machine_id]) - inv_deploynames.extend([invcls.machine_alias]) - - services = current_user.inv_services.order_by(Service.date_created.desc()).all() - inv_services = [] - for invcls in services: - if invcls.enabled == True: - inv_services.extend([invcls.description]) - - domains = current_user.inv_domains.order_by(Domain.date_created.desc()).all() - inv_domains = [] - for invcls in domains: - if invcls.enabled == True: - inv_domains.extend([invcls.fqdn]) + deployments = cuser.inv_deployments.order_by(Deployment.date_created.desc()).all() + inv_deploycubeids = [] + inv_deploynames = [] + for invcls in deployments: + if invcls.user_id == cuser.pid and invcls.enabled == True: + inv_deploycubeids.extend([invcls.machine_id]) + inv_deploynames.extend([invcls.machine_alias]) + + services = cuser.inv_services.order_by(Service.date_created.desc()).all() + inv_services = [] + for invcls in services: + if invcls.user_id == cuser.pid and invcls.enabled == True: + inv_services.extend([invcls.description]) + + domains = cuser.inv_domains.order_by(Domain.date_created.desc()).all() + inv_domains = [] + for invcls in domains: + if invcls.user_id == cuser.pid and invcls.enabled == True: + inv_domains.extend([invcls.fqdn]) + + addresses = cuser.inv_addresses.order_by(Address.date_assigned.desc()).all() + inv_addresses = [] + for invcls in addresses: + if invcls.user_id == cuser.pid and invcls.enabled == True: + inv_addresses.extend([invcls.ip]) #extract rrd and status from the deployments rrd = {} @@ -167,8 +173,8 @@ def dashboard(): send_email(current_app.config['MAIL_USERNAME'], 'Cube {} is unreachable'.format(cubeid), 'vmanager/email/adm_unreachable', user=current_user, cubeid=cubeid ) - current_app.logger.info('[{}] deployments: {}, domains: {}, services: {}'.format(current_user.email, inv_deploynames, inv_contracts, inv_domains )) - return render_template('vmanager/dashboard.html', rrd=rrd, status=statuses, inv_deployments=deployments, inv_contracts=contracts, inv_domains=domains) + current_app.logger.info('[{}] deployments: {}, domains: {}, services: {}'.format(current_user.email, inv_deploynames, inv_services, inv_domains, inv_addresses )) + return render_template('vmanager/dashboard.html', rrd=rrd, status=statuses, inv_deployments=deployments, inv_services=services, inv_domains=domains, inv_addresses=addresses) @vmanager.route('/vmvnc/') @login_required