aboutsummaryrefslogtreecommitdiffstats
path: root/pysite/views/staff/tables/edit.py
blob: b70bc20e551ac27810a37272bd3a0d9aa8945574 (plain) (blame)
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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
import json

from flask import redirect, request, url_for
from werkzeug.exceptions import BadRequest, NotFound

from pysite.base_route import RouteView
from pysite.constants import TABLE_MANAGER_ROLES
from pysite.decorators import csrf, require_roles
from pysite.mixins import DBMixin
from pysite.tables import TABLES


class TableEditView(RouteView, DBMixin):
    path = "/tables/<table>/edit"
    name = "tables.edit"

    @require_roles(*TABLE_MANAGER_ROLES)
    def get(self, table):
        obj = TABLES.get(table)

        if not obj:
            # Unknown table
            raise NotFound()

        if obj.locked:
            return redirect(url_for("staff.tables.table", table=table, page=1), code=303)

        key = request.args.get("key")

        old_primary = None

        if key:
            db_obj = self.db.get(table, key)
            old_primary = key  # Provide the current document's primary key, in case it's modified

            document = json.dumps(  # Editor uses JSON
                db_obj,
                indent=4
            )
        else:
            document = json.dumps(  # Generate default document from key schema
                {k: "" for k in obj.keys},
                indent=4
            )

        return self.render(
            "staff/tables/edit.html", table=table, primary_key=obj.primary_key,
            document=document, old_primary=old_primary
        )

    @require_roles(*TABLE_MANAGER_ROLES)
    @csrf
    def post(self, table):
        obj = TABLES.get(TABLES)

        if not obj:
            # Unknown table
            raise NotFound()

        if obj.locked:
            raise BadRequest()

        data = request.form.get("json")
        old_primary = request.form.get("old_primary")

        if not data:
            # No data given (for some reason)
            document = json.dumps(
                {k: "" for k in obj.keys},
                indent=4
            )

            return self.render(
                "staff/tables/edit.html", table=table, primary_key=obj.primary_key, document=document,
                message="Please provide some data to save", old_primary=old_primary
            )

        try:
            data = json.loads(data)
        except json.JSONDecodeError as e:
            # Invalid JSON
            return self.render(
                "staff/tables/edit.html", table=table, primary_key=obj.primary_key, document=data,
                message=f"Invalid JSON, please try again: {e}", old_primary=old_primary
            )

        if not data[obj.primary_key]:
            # No primary key value provided
            return self.render(
                "staff/tables/edit.html", table=table, primary_key=obj.primary_key, document=data,
                message=f"Please provide a value for the primary key: {obj.primary_key}", old_primary=old_primary
            )

        if old_primary is None:
            self.db.insert(  # This is a new object, so just insert it
                table, data
            )
        elif old_primary == data[obj.primary_key]:
            self.db.insert(  # This is an update without a primary key change, replace the whole document
                table, data, conflict="replace"
            )
        else:
            self.db.delete(  # This is a primary key change, so we need to remove the old object
                table, old_primary
            )
            self.db.insert(
                table, data,
            )

        return redirect(url_for("staff.tables.table", table=table, page=1), code=303)