Beispiel #1
0
async def show_queues(request):
    """Shows all installed modules"""

    try:
        config.read_config()
    except:
        return PlainTextResponse(
            'Configuration is being updated. Try again in a minute.')

    processing_suspended = False
    processing_halt_file = Path(config.mercure['processing_folder'] + '/' +
                                mercure_names.HALT)
    if processing_halt_file.exists():
        processing_suspended = True

    routing_suspended = False
    routing_halt_file = Path(config.mercure['outgoing_folder'] + '/' +
                             mercure_names.HALT)
    if routing_halt_file.exists():
        routing_suspended = True

    template = "queue.html"
    context = {
        "request": request,
        "mercure_version": mercure_defs.VERSION,
        "page": "queue",
        "processing_suspended": processing_suspended,
        "routing_suspended": routing_suspended
    }
    context.update(get_user_information(request))
    return templates.TemplateResponse(template, context)
Beispiel #2
0
async def show_modules(request):
    """Shows all installed modules"""

    try:
        config.read_config()
    except:
        return PlainTextResponse(
            "Configuration is being updated. Try again in a minute.")

    used_modules = {}
    for rule in config.mercure["rules"]:
        used_module = config.mercure["rules"][rule].get(
            "processing_module", "NONE")
        used_modules[used_module] = rule

    template = "modules.html"
    context = {
        "request": request,
        "mercure_version": mercure_defs.VERSION,
        "page": "modules",
        "modules": config.mercure["modules"],
        "used_modules": used_modules
    }
    context.update(get_user_information(request))
    return templates.TemplateResponse(template, context)
Beispiel #3
0
async def configuration_edit(request):
    """Shows a configuration editor"""

    # Check for existence of lock file
    cfg_file = Path(config.configuration_filename)
    cfg_lock = Path(cfg_file.parent / cfg_file.stem).with_suffix(
        mercure_names.LOCK)
    if cfg_lock.exists():
        return PlainTextResponse(
            'Configuration is being updated. Try again in a minute.')

    try:
        with open(cfg_file, "r") as json_file:
            config_content = json.load(json_file)
    except:
        return PlainTextResponse('Error reading configuration file.')

    config_content = json.dumps(config_content, indent=4, sort_keys=False)

    template = "configuration_edit.html"
    context = {
        "request": request,
        "mercure_version": mercure_defs.VERSION,
        "page": "configuration",
        "config_content": config_content
    }
    context.update(get_user_information(request))
    return templates.TemplateResponse(template, context)
Beispiel #4
0
async def settings_edit(request):
    """Shows the settings for the current user. Renders the same template as the normal user edit, but with parameter own_settings=True."""
    try:
        users.read_users()
    except:
        return PlainTextResponse(
            'Configuration is being updated. Try again in a minute.')

    own_name = request.user.display_name

    template = "users_edit.html"
    context = {
        "request":
        request,
        "mercure_version":
        mercure_defs.VERSION,
        "page":
        "settings",
        "edituser":
        own_name,
        "edituser_info":
        users.users_list[own_name],
        "own_settings":
        "True",
        "change_password":
        users.users_list[own_name].get("change_password", "False")
    }
    context.update(get_user_information(request))
    return templates.TemplateResponse(template, context)
Beispiel #5
0
async def show_users(request):
    """Shows all available users."""
    try:
        users.read_users()
    except:
        return PlainTextResponse("Configuration is being updated. Try again in a minute.")

    template = "users.html"
    context = {"request": request, "mercure_version": mercure_defs.VERSION, "page": "users", "users": users.users_list}
    context.update(get_user_information(request))
    return templates.TemplateResponse(template, context)
Beispiel #6
0
async def show_rules(request):
    """Show all defined routing rules. Can be executed by all logged-in users."""
    try:
        config.read_config()
    except:
        return PlainTextResponse("Configuration is being updated. Try again in a minute.")

    template = "rules.html"
    context = {"request": request, "mercure_version": mercure_defs.VERSION, "page": "rules", "rules": config.mercure["rules"]}
    context.update(get_user_information(request))
    return templates.TemplateResponse(template, context)
Beispiel #7
0
async def homepage(request):
    """Renders the index page that shows information about the system status."""
    used_space = 0
    free_space = 0
    total_space = 0

    try:
        disk_total, disk_used, disk_free = shutil.disk_usage(
            config.mercure["incoming_folder"])

        if (disk_total == 0):
            disk_total = 1

        used_space = 100 * disk_used / disk_total
        free_space = (disk_free // (2**30))
        total_space = (disk_total // (2**30))
    except:
        used_space = -1
        free_space = "N/A"
        disk_total = "N/A"

    service_status = {}
    for service in services.services_list:
        running_status = "False"

        if (services.services_list[service].get("systemd_service", "")):
            if (await async_run("systemctl is-active " +
                                services.services_list[service]
                                ["systemd_service"]))[0] == 0:
                running_status = "True"

        service_status[service] = {
            "id": service,
            "name": services.services_list[service]["name"],
            "running": running_status
        }

    template = "index.html"
    context = {
        "request": request,
        "mercure_version": mercure_defs.VERSION,
        "page": "homepage",
        "used_space": used_space,
        "free_space": free_space,
        "total_space": total_space,
        "service_status": service_status
    }
    context.update(get_user_information(request))
    return templates.TemplateResponse(template, context)
Beispiel #8
0
async def users_edit(request):
    """Shows the settings for a given user."""
    try:
        users.read_users()
    except:
        return PlainTextResponse("Configuration is being updated. Try again in a minute.")

    edituser = request.path_params["user"]

    if not edituser in users.users_list:
        return RedirectResponse(url="/users", status_code=303)

    template = "users_edit.html"
    context = {"request": request, "mercure_version": mercure_defs.VERSION, "page": "users", "edituser": edituser, "edituser_info": users.users_list[edituser]}
    context.update(get_user_information(request))
    return templates.TemplateResponse(template, context)
Beispiel #9
0
async def targets_edit(request):
    """Shows the edit page for the given target."""
    try:
        config.read_config()
    except:
        return PlainTextResponse("Configuration is being updated. Try again in a minute.")

    edittarget = request.path_params["target"]

    if not edittarget in config.mercure["targets"]:
        return RedirectResponse(url="/targets", status_code=303)

    template = "targets_edit.html"
    context = {"request": request, "mercure_version": mercure_defs.VERSION, "page": "targets", "targets": config.mercure["targets"], "edittarget": edittarget}
    context.update(get_user_information(request))
    return templates.TemplateResponse(template, context)
Beispiel #10
0
async def show_targets(request):
    """Shows all configured targets."""
    try:
        config.read_config()
    except:
        return PlainTextResponse("Configuration is being updated. Try again in a minute.")

    used_targets = {}
    for rule in config.mercure["rules"]:
        used_target = config.mercure["rules"][rule].get("target", "NONE")
        used_targets[used_target] = rule

    template = "targets.html"
    context = {"request": request, "mercure_version": mercure_defs.VERSION, "page": "targets", "targets": config.mercure["targets"], "used_targets": used_targets}
    context.update(get_user_information(request))
    return templates.TemplateResponse(template, context)
Beispiel #11
0
async def edit_module(request):
    """Shows all installed modules"""
    module = request.path_params["module"]
    try:
        config.read_config()
    except:
        return PlainTextResponse(
            "Configuration is being updated. Try again in a minute.")

    template = "modules_edit.html"
    context = {
        "request": request,
        "mercure_version": mercure_defs.VERSION,
        "page": "modules",
        "module": config.mercure["modules"][module],
        "module_name": module
    }
    context.update(get_user_information(request))
    return templates.TemplateResponse(template, context)
Beispiel #12
0
async def configuration(request):
    """Shows the current configuration of the mercure appliance."""
    try:
        config.read_config()
    except:
        return PlainTextResponse('Error reading configuration file.')
    template = "configuration.html"
    config_edited = int(request.query_params.get("edited", 0))
    os_info = distro.linux_distribution()
    os_string = f"{os_info[0]} Version {os_info[1]} ({os_info[2]})"
    context = {
        "request": request,
        "mercure_version": mercure_defs.VERSION,
        "page": "configuration",
        "config": config.mercure,
        "os_string": os_string,
        "config_edited": config_edited
    }
    context.update(get_user_information(request))
    return templates.TemplateResponse(template, context)
Beispiel #13
0
async def rules_edit(request):
    """Shows the edit page for the given routing rule."""
    try:
        config.read_config()
    except:
        return PlainTextResponse("Configuration is being updated. Try again in a minute.")

    rule = request.path_params["rule"]
    template = "rules_edit.html"
    context = {
        "request": request,
        "mercure_version": mercure_defs.VERSION,
        "page": "rules",
        "rules": config.mercure["rules"],
        "targets": config.mercure["targets"],
        "modules": config.mercure["modules"],
        "rule": rule,
        "alltags": tagslist.alltags,
        "sortedtags": tagslist.sortedtags,
    }
    context.update(get_user_information(request))
    return templates.TemplateResponse(template, context)
Beispiel #14
0
async def show_log(request):
    """Render the log for the given service. The time range can be specified via URL parameters."""
    requested_service = request.path_params["service"]

    # Get optional start and end dates from the URL. Make sure
    # that the date format is clean
    try:
        start_date = request.query_params.get("from", "")
        start_time = request.query_params.get("from_time", "")
        datetime.datetime.strptime(start_date, '%Y-%m-%d')
        start_date_cmd = ' --since "' + start_date
        if start_date and start_time:
            datetime.datetime.strptime(start_time, '%H:%M')
            start_date_cmd = start_date_cmd + " " + start_time
        start_date_cmd = start_date_cmd + '"'
    except:
        start_date = ""
        start_time = ""
        start_date_cmd = ""

    try:
        end_date = request.query_params.get("to", "")
        end_time = request.query_params.get("to_time", "")
        datetime.datetime.strptime(end_date, '%Y-%m-%d')
        end_date_cmd = ' --until "' + end_date
        if end_date and end_time:
            datetime.datetime.strptime(end_time, '%H:%M')
            end_date_cmd = end_date_cmd + " " + end_time
        end_date_cmd = end_date_cmd + '"'
    except:
        end_date = ""
        end_time = ""
        end_date_cmd = ""

    service_logs = {}
    for service in services.services_list:
        service_logs[service] = {
            "id": service,
            "name": services.services_list[service]["name"],
            "systemd": services.services_list[service]["systemd_service"]
        }

    if (not requested_service in service_logs) or (
            not services.services_list[requested_service]["systemd_service"]):
        return PlainTextResponse(
            'Service does not exist or is incorrectly configured.')

    run_result = await async_run(
        'journalctl -n 1000 -u ' +
        services.services_list[requested_service]["systemd_service"] +
        start_date_cmd + end_date_cmd)

    log_content = ""

    if run_result[0] == 0:
        log_content = html.escape(str(run_result[1].decode()))
        line_list = log_content.split('\n')
        if len(line_list) and (not line_list[-1]):
            del line_list[-1]

        log_content = '<br />'.join(line_list)
    else:
        log_content = "Error reading log information."
        if start_date or end_date:
            log_content = log_content + "<br /><br />Are the From/To settings valid?"

    template = "logs.html"
    context = {
        "request": request,
        "mercure_version": mercure_defs.VERSION,
        "page": "logs",
        "service_logs": service_logs,
        "log_id": requested_service,
        "log_content": log_content,
        "start_date": start_date,
        "start_time": start_time,
        "end_date": end_date,
        "end_time": end_time
    }
    context.update(get_user_information(request))
    return templates.TemplateResponse(template, context)
Beispiel #15
0
async def show_log(request):
    """Render the log for the given service. The time range can be specified via URL parameters."""
    requested_service = request.path_params["service"]

    # Get optional start and end dates from the URL. Make sure
    # that the date format is clean.
    try:
        start_date = request.query_params.get("from", "")
        start_time = request.query_params.get("from_time", "00:00")
        start_timestamp = f"{start_date} {start_time}"
        start_obj = datetime.datetime.strptime(start_timestamp,
                                               "%Y-%m-%d %H:%M")
    except ValueError:
        start_obj = None
        start_timestamp = ""

    try:
        end_date = request.query_params.get("to", "")
        # Make sure end time includes the day-of, unless otherwise specified
        end_time = request.query_params.get("to_time", "23:59")
        end_timestamp = f"{end_date} {end_time}"
        datetime.datetime.strptime(end_timestamp, "%Y-%m-%d %H:%M")
    except ValueError:
        end_timestamp = ""

    service_logs = {}
    for service in services.services_list:
        service_logs[service] = {
            "id": service,
            "name": services.services_list[service]["name"],
            "systemd":
            services.services_list[service].get("systemd_service", ""),
            "docker":
            services.services_list[service].get("docker_service", "")
        }

    if requested_service not in service_logs:
        return PlainTextResponse("Service does not exist.")

    if "systemd_service" not in services.services_list[requested_service] and \
            "docker_service" not in services.services_list[requested_service]:
        return PlainTextResponse("Service incorrectly configured.")

    return_code = -1
    raw_logs = ""

    if "systemd_service" in services.services_list[requested_service]:
        start_date_cmd = ""
        end_date_cmd = ""
        if start_timestamp:
            start_date_cmd = f'--since {start_timestamp}'
        if end_timestamp:
            end_date_cmd = f'--until {end_timestamp}'

        run_result = await async_run(
            f'journalctl -n 1000 -u '
            f'{services.services_list[requested_service]["systemd_service"]} '
            f'{start_date_cmd} {end_date_cmd}')
        return_code = run_result[0]
        raw_logs = run_result[1]

    elif "docker_service" in services.services_list[requested_service]:
        client = docker.from_env()
        try:
            container = client.containers.get(
                services.services_list[requested_service]["docker_service"])
            container.reload()
            raw_logs = container.logs(since=start_obj)
            return_code = 0
        except (docker.errors.NotFound, docker.errors.APIError):
            return_code = 1

    if return_code == 0:
        log_content = html.escape(str(raw_logs.decode()))
        line_list = log_content.split("\n")
        if len(line_list) and (not line_list[-1]):
            del line_list[-1]

        log_content = "<br />".join(line_list)
    else:
        log_content = "Error reading log information."
        if start_date or end_date:
            log_content = log_content + "<br /><br />Are the From/To settings valid?"

    template = "logs.html"
    context = {
        "request": request,
        "mercure_version": mercure_defs.VERSION,
        "page": "logs",
        "service_logs": service_logs,
        "log_id": requested_service,
        "log_content": log_content,
        "start_date": start_date,
        "start_time": start_time,
        "end_date": end_date,
        "end_time": end_time,
    }
    context.update(get_user_information(request))
    return templates.TemplateResponse(template, context)
Beispiel #16
0
async def homepage(request):
    """Renders the index page that shows information about the system status."""
    used_space = 0
    free_space = 0
    total_space = 0

    try:
        disk_total, disk_used, disk_free = shutil.disk_usage(
            config.mercure["incoming_folder"])

        if disk_total == 0:
            disk_total = 1

        used_space = 100 * disk_used / disk_total
        free_space = disk_free // (2**30)
        total_space = disk_total // (2**30)
    except:
        used_space = -1
        free_space = "N/A"
        disk_total = "N/A"

    service_status = {}
    for service in services.services_list:
        running_status = "False"

        if services.services_list[service].get("systemd_service", ""):
            if (await async_run("systemctl is-active " +
                                services.services_list[service]
                                ["systemd_service"]))[0] == 0:
                running_status = "True"

        elif services.services_list[service].get("docker_service", ""):
            client = docker.from_env()
            try:
                container = client.containers.get(
                    services.services_list[service]["docker_service"])
                container.reload()
                status = container.status
                """restarting, running, paused, exited"""
                if status == "running":
                    running_status = "True"

            except (docker.errors.NotFound, docker.errors.APIError):
                running_status = "False"

        service_status[service] = {
            "id": service,
            "name": services.services_list[service]["name"],
            "running": running_status
        }

    template = "index.html"
    context = {
        "request": request,
        "mercure_version": mercure_defs.VERSION,
        "page": "homepage",
        "used_space": used_space,
        "free_space": free_space,
        "total_space": total_space,
        "service_status": service_status,
    }
    context.update(get_user_information(request))
    return templates.TemplateResponse(template, context)