Changeset - e049a28fbddc
[Not reviewed]
version_5
0 3 1
Dennis Fink - 10 years ago 2015-08-26 18:32:58
dennis.fink@c3l.lu
Add new HTTPAuth feature
4 files changed with 28 insertions and 6 deletions:
0 comments (0 inline, 0 general)
ennstatus/api/auth.py
Show inline comments
 
new file 100644
 
from flask import current_app
 
from flask.ext.httpauth import HTTPDigestAuth
 

	
 
httpauth = HTTPDigestAuth()
 

	
 

	
 
@httpauth.get_password
 
def get_pw(username):
 

	
 
    if username in current_app.config['ENNSTATUS_SERVERS']:
 
        return current_app.confg['ENNSTATUS_SERVERS'][username]['PASSWORD']
 

	
 
    return None
ennstatus/api/views.py
Show inline comments
 
import ipaddress
 
import json
 

	
 
from datetime import datetime
 

	
 
from flask import (Blueprint, request, current_app, jsonify, render_template,
 
                   abort)
 

	
 
import strict_rfc3339
 
import pygeoip
 

	
 
from ennstatus.status.functions import (single_server, all_servers,
 
                                        all_servers_by_type)
 
from .model import Server
 

	
 
from .auth import httpauth
 

	
 
api_page = Blueprint('api', __name__)
 
gi4 = pygeoip.GeoIP('/usr/share/GeoIP/GeoIP.dat', pygeoip.MEMORY_CACHE)
 
gi6 = pygeoip.GeoIP('/usr/share/GeoIP/GeoIPv6.dat', pygeoip.MEMORY_CACHE)
 

	
 

	
 
@api_page.route('/update', methods=('POST',))
 
@httpauth.login_required
 
def update():
 

	
 
    current_app.logger.info('Handling update')
 
    if current_app.debug:
 
        accepted_ips = ['127.0.0.1']
 
    else:
 
        accepted_ips = current_app.config.get('ENNSTATUS_ACCEPTED_IPS', [])
 

	
 
    if request.remote_addr not in accepted_ips:
 
    try:
 
        servers = current_app.config['ENNSTATUS_SERVERS']
 
    except KeyError as e:
 
        current_app.logger.error(str(e))
 
        return abort(500)
 

	
 
    try:
 
        if request.remote_addr not in servers[httpauth.username()]['IPS']:
 
        current_app.logger.warn('Unallowed IP %s tried to update data!'
 
                                % request.remote_addr)
 
        return 'IP not allowed!\n', 403, {'Content-Type': 'text/plain'}
 
    except KeyError as e:
 
        current_app.logger.error(str(e))
 
        return abort(500)
 

	
 
    data = request.get_json()
 

	
 
    if data is None:
 
        current_app.logger.info('No JSON data supplied!')
 
        return 'No JSON data supplied!\n', 400, {'Content-Type': 'text/plain'}
 

	
 
    if 'ip' in data:
 
        ip = data['ip']
 
    elif 'ip6' in data:
 
        ip = data['ip6']
 
    else:
 
        ip = request.remote_addr
 

	
 
    try:
 
        ip = ipaddress.ip_address(ip)
 
    except ipaddress.AddressValueError:
 
        return 'IP not allowed!\n', 403, {'Content-Type': 'text/plain'}
 

	
 
    if ip.version == 4:
 
        data['country'] = gi4.country_name_by_addr(str(ip))
 
    elif ip.version == 6:
 
        data['country'] = gi6.country_name_by_addr(str(ip))
 
    else:
 
        data['country'] = None
 

	
 
    data['last_updated'] = strict_rfc3339.timestamp_to_rfc3339_utcoffset(
 
        datetime.utcnow().timestamp()
 
    )
 

	
 
    try:
 
        server = Server.from_json(json.dumps(data))
 
    except Exception as e:
 
        current_app.logger.warning(' '.join([str(e), str(data)]))
 
        return str(e), 409, {'Content-Type': 'text/plain'}
 

	
 
    if server.type in ('exit', 'relay'):
 
        server.update_weights()
 

	
 
    try:
 
        server.save()
 
    except Exception as e:
 
        current_app.logger.error(str(e))
 
        return str(e), 500, {'Content-Type': 'text/plain'}
 

	
 
    current_app.logger.info('Return result')
 
    return (server.json(), 201,
 
            {'Location': '/api/export/json/single?server_name=%s'
requirements.in
Show inline comments
 
Flask-Bootstrap==3.3.5.6
 
Flask-HTTPAuth==2.6.0
 
Flask-Mail==0.9.1
 
Flask-Moment==0.5.1
 
Flask-WTF==0.12
 
Flask==0.10.1
 
jsonschema==2.5.1
 
pygeoip==0.3.2
 
python-gnupg==0.3.7
 
requests==2.7.0
 
strict-rfc3339==0.5
requirements.txt
Show inline comments
 
#
 
# This file is autogenerated by pip-compile
 
# Make changes in requirements.in, then run this to update:
 
#
 
#    pip-compile requirements.in
 
#
 
blinker==1.4              # via flask-mail
 
dominate==2.1.12          # via flask-bootstrap
 
Flask-Bootstrap==3.3.5.6
 
Flask-HTTPAuth==2.6.0
 
Flask-Mail==0.9.1
 
Flask-Moment==0.5.1
 
Flask-WTF==0.12
 
flask==0.10.1
 
itsdangerous==0.24        # via flask
 
jinja2==2.8               # via flask
 
jsonschema==2.5.1
 
markupsafe==0.23          # via jinja2
 
pygeoip==0.3.2
 
python-gnupg==0.3.7
 
requests==2.7.0
 
strict-rfc3339==0.5
 
werkzeug==0.10.4          # via flask, flask-wtf
 
wtforms==2.0.2            # via flask-wtf
0 comments (0 inline, 0 general)