Files @ d55a3fc29e0b
Branch filter:

Location: FVDE/ennstatus/ennstatus/api/views.py - annotation

Dennis Fink
Renamed disclaimer to about ennstatus
9dd5a0479455
1585155d7c8a
1585155d7c8a
9dd5a0479455
9bfee64f690e
9bfee64f690e
9bfee64f690e
3ec5be85acb4
3ec5be85acb4
1585155d7c8a
1585155d7c8a
d1494001db7c
1585155d7c8a
9bfee64f690e
9bfee64f690e
1585155d7c8a
e049a28fbddc
9bfee64f690e
9bfee64f690e
1585155d7c8a
1585155d7c8a
9bfee64f690e
9bfee64f690e
9bfee64f690e
e049a28fbddc
9bfee64f690e
9bfee64f690e
9bfee64f690e
e049a28fbddc
e049a28fbddc
e049a28fbddc
e049a28fbddc
e049a28fbddc
e049a28fbddc
9bfee64f690e
270279ad054e
270279ad054e
e049a28fbddc
270279ad054e
270279ad054e
270279ad054e
270279ad054e
270279ad054e
270279ad054e
e049a28fbddc
e049a28fbddc
e049a28fbddc
e049a28fbddc
1585155d7c8a
3ec5be85acb4
3ec5be85acb4
3ec5be85acb4
9bfee64f690e
9bfee64f690e
9bfee64f690e
270279ad054e
270279ad054e
270279ad054e
270279ad054e
270279ad054e
270279ad054e
270279ad054e
270279ad054e
270279ad054e
270279ad054e
270279ad054e
270279ad054e
1585155d7c8a
1585155d7c8a
1585155d7c8a
1585155d7c8a
9bfee64f690e
9bfee64f690e
6d5132a446e9
6d5132a446e9
6d5132a446e9
6d5132a446e9
6d5132a446e9
6d5132a446e9
6d5132a446e9
6d5132a446e9
6d5132a446e9
9bfee64f690e
9dd5a0479455
6d5132a446e9
6d5132a446e9
6d5132a446e9
9dd5a0479455
6d5132a446e9
1585155d7c8a
1585155d7c8a
1585155d7c8a
9bfee64f690e
1585155d7c8a
bfe920603761
1585155d7c8a
1585155d7c8a
1585155d7c8a
1585155d7c8a
b38ffa9fbcfc
1585155d7c8a
b38ffa9fbcfc
b38ffa9fbcfc
b38ffa9fbcfc
b38ffa9fbcfc
b38ffa9fbcfc
9bfee64f690e
1585155d7c8a
1585155d7c8a
1585155d7c8a
1585155d7c8a
1585155d7c8a
1585155d7c8a
1585155d7c8a
86c43281b1b4
86c43281b1b4
86c43281b1b4
86c43281b1b4
86c43281b1b4
86c43281b1b4
86c43281b1b4
86c43281b1b4
9bfee64f690e
9bfee64f690e
9bfee64f690e
9bfee64f690e
9bfee64f690e
9bfee64f690e
9bfee64f690e
9bfee64f690e
9bfee64f690e
9bfee64f690e
9bfee64f690e
9bfee64f690e
9bfee64f690e
9bfee64f690e
9bfee64f690e
9bfee64f690e
9bfee64f690e
9bfee64f690e
9bfee64f690e
1585155d7c8a
1585155d7c8a
9bfee64f690e
9bfee64f690e
9bfee64f690e
9bfee64f690e
eebcc143d129
9bfee64f690e
9bfee64f690e
9bfee64f690e
9bfee64f690e
9bfee64f690e
9bfee64f690e
9bfee64f690e
9bfee64f690e
9bfee64f690e
9bfee64f690e
9bfee64f690e
9bfee64f690e
9bfee64f690e
9bfee64f690e
1585155d7c8a
9bfee64f690e
86c43281b1b4
1585155d7c8a
9bfee64f690e
9bfee64f690e
9bfee64f690e
1585155d7c8a
9bfee64f690e
9bfee64f690e
eebcc143d129
9bfee64f690e
9bfee64f690e
import ipaddress

from datetime import datetime

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

from werkzeug.exceptions import BadRequest

import strict_rfc3339
import pygeoip
import requests

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')

    try:
        servers = current_app.config['ENNSTATUS_SERVERS']
    except KeyError as e:
        current_app.logger.error(str(e))
        return abort(500)

    username = httpauth.username()

    try:
        if request.remote_addr not in servers[username]['IPS']:
            current_app.logger.warn(
                'Unallowed IP {} tried to update data!'.format(
                    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)

    try:
        data = request.get_json()
    except BadRequest:
        current_app.logger.info('No JSON data supplied!')
        return 'No JSON data supplied!\n', 400, {'Content-Type': 'text/plain'}

    try:
        if username != data['name'].lower():
            current_app.logger.warn(
                'Unallowed user {} tried to update {}!'.format(
                    username, data['name']
                )
            )
            return ('You are not allowed to update this server\n',
                    403, {'Content-Type': 'text/plain'})
    except KeyError:
        return abort(409)

    if 'ip' in data:
        ip = data['ip']
    elif 'ip6' in data:
        ip = data['ip6']
    else:
        ip = request.remote_addr
        try:
            temp_ip = ipaddress.ip_address(ip)
        except ipaddress.AddressValueError:
            return 'IP not allowed!\n', 403, {'Content-Type': 'text/plain'}
        else:
            if temp_ip.version == 4:
                data['ip'] = ip
            elif temp_ip.verison == 6:
                data['ip6'] = ip

    try:
        country = gi4.country_name_by_addr(ip)
    except pygeoip.GeoIPError:
        country = gi6.country_name_by_addr(ip)

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

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

    try:
        server.update_weights()
    except NotImplementedError:
        pass
    except requests.HTTPError as e:
        current_app.logger.error(str(e), exc_info=True)
        pass

    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={}'.format(
                server.name
            )
        }
    )


@api_page.route('/export', defaults={'server_type': 'all',
                                     'export_format': 'json'})
@api_page.route('/export/<any("json", "xml"):export_format>',
                defaults={'server_type': 'all'})
@api_page.route(('/export/<any("json", "xml"):export_format>'
                 '/<any("all", "exit", "bridge", "relay", "single")'
                 ':server_type>'))
def export(export_format, server_type):

    current_app.logger.info('Handling export')
    if server_type == 'single':
        server_name = request.args.get('server_name', None)
        if server_name is not None:
            server = single_server(server_name)
            if server:
                if export_format == 'json':
                    current_app.logger.info('Returning server as json!')
                    return (server.json(), 200,
                            {'Content-Type': 'application/json'})
                else:
                    current_app.logger.info('Returning server as xml!')
                    return (
                        render_template(
                            'api/export/xml/single_server.xml',
                            server=server),
                        200, {'Content-Type': 'text/xml'})
            else:
                current_app.logger.warning('Server not found!')
                return ('Server not found!\n',
                        404, {'Content-Type': 'text/plain'})
        else:
            current_app.logger.warning('No server_name specified!')
            return ('No server_name specified!\n',
                    400, {'Content-Type': 'text/plain'})

    else:
        if server_type == 'all':
            current_app.logger.info('Getting all servers!')
            servers = [server.json() for server in all_servers()]
        else:
            current_app.logger.info('Getting all {}!'.format(server_type))
            servers = list(all_servers_by_type(server_type.lower()))

        if export_format == 'json':
            current_app.logger.info('Returning as json!')
            return str(servers)
        else:
            current_app.logger.info('Returning as xml!')
            return (render_template('api/export/xml/network.xml',
                                    servers=servers),
                    200, {'Content-Type': 'text/xml'})