about summary refs log tree commit diff
path: root/uploader/route_utils.py
blob: 63b2852a766db919c2dd3e1a6f1a56c44032f5c4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
"""Generic routing utilities."""
import json
from json.decoder import JSONDecodeError

from flask import (flash,
                   url_for,
                   request,
                   redirect,
                   render_template,
                   current_app as app)

from gn_libs.mysqldb import database_connection

from uploader.datautils import base64_encode_dict, base64_decode_to_dict
from uploader.population.models import (populations_by_species,
                                        population_by_species_and_id)

def generic_select_population(
        # pylint: disable=[too-many-arguments, too-many-positional-arguments]
        species: dict,
        template: str,
        population_id: str,
        back_to: str,
        forward_to: str,
        activelink: str,
        error_message: str = "No such population found!"
):
    """Handles common flow for 'select population' step."""
    with database_connection(app.config["SQL_URI"]) as conn:
        if not bool(population_id):
            return render_template(
                template,
                species=species,
                populations=populations_by_species(conn, species["SpeciesId"]),
                activelink=activelink)

        if population_id == "CREATE-POPULATION":
            return redirect(url_for(
                "species.populations.create_population",
                species_id=species["SpeciesId"],
                return_to=forward_to))

        population = population_by_species_and_id(
            conn, species["SpeciesId"], int(population_id))
        if not bool(population):
            flash(error_message, "alert-danger")
            return redirect(url_for(back_to, species_id=species["SpeciesId"]))

        return redirect(url_for(forward_to,
                                species_id=species["SpeciesId"],
                                population_id=population["Id"]))


def redirect_to_next(default: dict):
    """Redirect to the next uri if specified, else redirect to default."""
    assert "uri" in default, "You must provide at least the 'uri' value."
    try:
        next_page = base64_decode_to_dict(request.args.get("next"))
        return redirect(url_for(
            next_page["uri"],
            **{key:value for key,value in next_page.items()}))
    except (TypeError, JSONDecodeError) as _err:
        logger.debug("We could not decode the next value '%s'",
                     next_page,
                     exc_info=True)

    return redirect(url_for(
        default["uri"],
        **{key:value for key,value in default.items()}))


def build_next_argument(uri: str, **kwargs) -> str:
    """Build the `next` URI argument from provided details."""
    dumps_keywords = (
        "skipkeys", "ensure_ascii", "check_circular", "allow_nan", "cls",
        "indent", "separators", "default", "sort_keys")
    return base64_encode_dict(
        {
            "uri": uri,
            **{
                key: val for key,val in kwargs.items()
                if key not in dumps_keywords
            }
        },
        **{
            key: val for key,val in kwargs.items()
            if key in dumps_keywords
        })