diff --git a/powerdnsadmin/__init__.py b/powerdnsadmin/__init__.py index c70b273..3f68a58 100755 --- a/powerdnsadmin/__init__.py +++ b/powerdnsadmin/__init__.py @@ -100,8 +100,6 @@ def create_app(config=None): app.jinja_env.filters['display_record_name'] = utils.display_record_name app.jinja_env.filters['display_master_name'] = utils.display_master_name app.jinja_env.filters['display_second_to_time'] = utils.display_time - app.jinja_env.filters[ - 'email_to_gravatar_url'] = utils.email_to_gravatar_url app.jinja_env.filters[ 'display_setting_state'] = utils.display_setting_state app.jinja_env.filters['pretty_domain_name'] = utils.pretty_domain_name diff --git a/powerdnsadmin/lib/utils.py b/powerdnsadmin/lib/utils.py index 9e7cf20..4ef5759 100644 --- a/powerdnsadmin/lib/utils.py +++ b/powerdnsadmin/lib/utils.py @@ -2,14 +2,12 @@ import logging import re import json import requests -import hashlib import ipaddress import idna from collections.abc import Iterable from distutils.version import StrictVersion from urllib.parse import urlparse -from datetime import datetime, timedelta def auth_from_url(url): @@ -186,17 +184,6 @@ def pdns_api_extended_uri(version): return "" -def email_to_gravatar_url(email="", size=100): - """ - AD doesn't necessarily have email - """ - if email is None: - email = "" - - hash_string = hashlib.md5(email.encode('utf-8')).hexdigest() - return "https://s.gravatar.com/avatar/{0}?s={1}".format(hash_string, size) - - def display_setting_state(value): if value == 1: return "ON" diff --git a/powerdnsadmin/models/setting.py b/powerdnsadmin/models/setting.py index 51e78e5..a4016bf 100644 --- a/powerdnsadmin/models/setting.py +++ b/powerdnsadmin/models/setting.py @@ -193,7 +193,8 @@ class Setting(db.Model): 'otp_force': False, 'max_history_records': 1000, 'deny_domain_override': False, - 'account_name_extra_chars': False + 'account_name_extra_chars': False, + 'gravatar_enabled': False, } def __init__(self, id=None, name=None, value=None): diff --git a/powerdnsadmin/routes/admin.py b/powerdnsadmin/routes/admin.py index c5f28d1..9474503 100644 --- a/powerdnsadmin/routes/admin.py +++ b/powerdnsadmin/routes/admin.py @@ -1259,20 +1259,41 @@ def history_table(): # ajax call data @login_required @operator_role_required def setting_basic(): - if request.method == 'GET': - settings = [ - 'maintenance', 'fullscreen_layout', 'record_helper', - 'login_ldap_first', 'default_record_table_size', - 'default_domain_table_size', 'auto_ptr', 'record_quick_edit', - 'pretty_ipv6_ptr', 'dnssec_admins_only', - 'allow_user_create_domain', 'allow_user_remove_domain', 'allow_user_view_history', 'bg_domain_updates', 'site_name', - 'session_timeout', 'warn_session_timeout', 'ttl_options', - 'pdns_api_timeout', 'verify_ssl_connections', 'verify_user_email', - 'delete_sso_accounts', 'otp_field_enabled', 'custom_css', 'enable_api_rr_history', 'max_history_records', 'otp_force', - 'deny_domain_override', 'enforce_api_ttl', 'account_name_extra_chars' - ] + settings = [ + 'account_name_extra_chars', + 'allow_user_create_domain', + 'allow_user_remove_domain', + 'allow_user_view_history', + 'auto_ptr', + 'bg_domain_updates', + 'custom_css', + 'default_domain_table_size', + 'default_record_table_size', + 'delete_sso_accounts', + 'deny_domain_override', + 'dnssec_admins_only', + 'enable_api_rr_history', + 'enforce_api_ttl', + 'fullscreen_layout', + 'gravatar_enabled', + 'login_ldap_first', + 'maintenance', + 'max_history_records', + 'otp_field_enabled', + 'otp_force', + 'pdns_api_timeout', + 'pretty_ipv6_ptr', + 'record_helper', + 'record_quick_edit', + 'session_timeout', + 'site_name', + 'ttl_options', + 'verify_ssl_connections', + 'verify_user_email', + 'warn_session_timeout', + ] - return render_template('admin_setting_basic.html', settings=settings) + return render_template('admin_setting_basic.html', settings=settings) @admin_bp.route('/setting/basic//edit', methods=['POST']) diff --git a/powerdnsadmin/routes/user.py b/powerdnsadmin/routes/user.py index f411c29..709156f 100644 --- a/powerdnsadmin/routes/user.py +++ b/powerdnsadmin/routes/user.py @@ -1,5 +1,8 @@ import datetime -from flask import Blueprint, request, render_template, make_response, jsonify, redirect, url_for, g, session, current_app +import hashlib + +from flask import Blueprint, request, render_template, make_response, jsonify, redirect, url_for, g, session, \ + current_app, after_this_request, abort from flask_login import current_user, login_required, login_manager from ..models.user import User, Anonymous @@ -96,4 +99,34 @@ def qrcode(): 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0' - } \ No newline at end of file + } + + +@user_bp.route('/image', methods=['GET']) +@login_required +def image(): + """Returns the user profile image or avatar.""" + + @after_this_request + def add_cache_headers(response_): + """When the response is ok, add cache headers.""" + if 200 <= response_.status_code <= 399: + response_.cache_control.private = True + response_.cache_control.max_age = int(datetime.timedelta(days=1).total_seconds()) + return response_ + + # To prevent "cache poisoning", the username query parameter is required + if request.args.get('username', None) != current_user.username: + abort(400) + + setting = Setting() + + email = current_user.email + if email and setting.get('gravatar_enabled'): + hash_ = hashlib.md5(email.encode('utf-8')).hexdigest() + url = f'https://s.gravatar.com/avatar/{hash_}?s=100' + current_app.logger.debug('Redirect user image request to gravatar') + return redirect(url, 307) + + # Fallback to the local default image + return current_app.send_static_file('img/user_image.png') diff --git a/powerdnsadmin/static/custom/css/custom.css b/powerdnsadmin/static/custom/css/custom.css index f5dcb34..1cd3728 100644 --- a/powerdnsadmin/static/custom/css/custom.css +++ b/powerdnsadmin/static/custom/css/custom.css @@ -42,15 +42,6 @@ table td { background-position: center; } -.navbar-nav>.user-menu>.dropdown-menu>li.user-header>img.img-circle.offline { - filter: brightness(0); - border-color: black; -} - -.navbar-nav>.user-menu .user-image.offline { - filter: brightness(0); -} - .search-input { width: 100%; } \ No newline at end of file diff --git a/powerdnsadmin/static/img/gravatar.png b/powerdnsadmin/static/img/gravatar.png deleted file mode 100644 index 8360286..0000000 Binary files a/powerdnsadmin/static/img/gravatar.png and /dev/null differ diff --git a/powerdnsadmin/static/img/user_image.png b/powerdnsadmin/static/img/user_image.png new file mode 100644 index 0000000..325b0ef Binary files /dev/null and b/powerdnsadmin/static/img/user_image.png differ diff --git a/powerdnsadmin/templates/base.html b/powerdnsadmin/templates/base.html index 92e3a1c..85b2f82 100644 --- a/powerdnsadmin/templates/base.html +++ b/powerdnsadmin/templates/base.html @@ -23,11 +23,7 @@ {% endblock %} - {% if OFFLINE_MODE %} - {% set gravatar_url = url_for('static', filename='img/gravatar.png') %} - {% elif current_user.email is defined %} - {% set gravatar_url = current_user.email|email_to_gravatar_url(size=80) %} - {% endif %} +{% set user_image_url = url_for('user.image', username=current_user.username) %}
{% block pageheader %}
@@ -51,14 +47,14 @@