Completed
Push — main ( 80557c...4ad4e5 )
by Jochen
05:36
created

byceps.blueprints.admin.site.views   A

Complexity

Total Complexity 33

Size/Duplication

Total Lines 332
Duplicated Lines 0 %

Test Coverage

Coverage 69.94%

Importance

Changes 0
Metric Value
eloc 229
dl 0
loc 332
ccs 121
cts 173
cp 0.6994
rs 9.76
c 0
b 0
f 0
wmc 33

13 Functions

Rating   Name   Duplication   Size   Complexity  
B update() 0 56 5
A _sites_to_sites_with_brand() 0 8 2
A index() 0 22 3
A index_for_brand() 0 23 3
A _get_storefronts_by_site_id() 0 10 1
B view() 0 38 5
A _site_to_site_with_brand() 0 5 1
A _fill_in_common_form_choices() 0 6 1
A _get_brand_or_404() 0 7 2
A _get_site_or_404() 0 7 2
A update_form() 0 14 2
A create_form() 0 13 2
B create() 0 49 4
1
"""
2
byceps.blueprints.admin.site.views
3
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4
5
:Copyright: 2006-2020 Jochen Kupperschmidt
6
:License: Modified BSD, see LICENSE for details.
7
"""
8
9 1
import dataclasses
10 1
from typing import Iterable, Iterator
11
12 1
from flask import abort, request
13
14 1
from ....services.board import board_service
15 1
from ....services.brand import service as brand_service
16 1
from ....services.brand.transfer.models import Brand
17 1
from ....services.news import channel_service as news_channel_service
18 1
from ....services.party import service as party_service
19 1
from ....services.shop.shop import service as shop_service
20 1
from ....services.shop.storefront import service as storefront_service
21 1
from ....services.site import (
22
    service as site_service,
23
    settings_service as site_settings_service,
24
)
25 1
from ....services.site.transfer.models import Site, SiteWithBrand
26 1
from ....util.framework.blueprint import create_blueprint
27 1
from ....util.framework.flash import flash_error, flash_success
28 1
from ....util.framework.templating import templated
29 1
from ....util.views import redirect_to
30
31 1
from ...common.authorization.decorators import permission_required
32 1
from ...common.authorization.registry import permission_registry
33
34 1
from .authorization import SitePermission
35 1
from .forms import CreateForm, UpdateForm
36
37
38 1
blueprint = create_blueprint('site_admin', __name__)
39
40
41 1
permission_registry.register_enum(SitePermission)
42
43
44 1
@blueprint.route('/')
45 1
@permission_required(SitePermission.view)
46 1
@templated
47
def index():
48
    """List all sites."""
49 1
    brands = brand_service.get_all_brands()
50 1
    brands.sort(key=lambda brand: brand.title)
51
52 1
    sites = site_service.get_all_sites()
53 1
    sites = list(_sites_to_sites_with_brand(sites, brands))
54 1
    sites.sort(key=lambda site: (site.title, site.party_id))
55
56 1
    parties = party_service.get_all_parties()
57 1
    party_titles_by_id = {p.id: p.title for p in parties}
58
59 1
    storefronts_by_site_id = _get_storefronts_by_site_id(sites)
60
61 1
    return {
62
        'sites': sites,
63
        'brands': brands,
64
        'party_titles_by_id': party_titles_by_id,
65
        'storefronts_by_site_id': storefronts_by_site_id,
66
    }
67
68
69 1
@blueprint.route('/for_brand/<brand_id>')
70 1
@permission_required(SitePermission.view)
71 1
@templated
72
def index_for_brand(brand_id):
73
    """List sites for this brand."""
74
    brand = brand_service.find_brand(brand_id)
75
    if brand is None:
76
        abort(404)
77
78
    sites = site_service.get_sites_for_brand(brand.id)
79
    sites = [_site_to_site_with_brand(site, brand) for site in sites]
80
    sites.sort(key=lambda site: (site.title, site.party_id))
81
82
    parties = party_service.get_all_parties()
83
    party_titles_by_id = {p.id: p.title for p in parties}
84
85
    storefronts_by_site_id = _get_storefronts_by_site_id(sites)
86
87
    return {
88
        'sites': sites,
89
        'brand': brand,
90
        'party_titles_by_id': party_titles_by_id,
91
        'storefronts_by_site_id': storefronts_by_site_id,
92
    }
93
94
95 1
def _sites_to_sites_with_brand(
96
    sites: Iterable[Site], brands: Iterable[Brand]
97
) -> Iterator[SiteWithBrand]:
98 1
    brands_by_id = {brand.id: brand for brand in brands}
99
100 1
    for site in sites:
101 1
        brand = brands_by_id[site.brand_id]
102 1
        yield _site_to_site_with_brand(site, brand)
103
104
105 1
def _site_to_site_with_brand(site: Site, brand: Brand) -> SiteWithBrand:
106 1
    site_tuple = dataclasses.astuple(site)
107 1
    brand_tuple = (brand,)
108
109 1
    return SiteWithBrand(*(site_tuple + brand_tuple))
110
111
112 1
def _get_storefronts_by_site_id(sites):
113 1
    storefront_ids = {
114
        site.storefront_id for site in sites if site.storefront_id is not None
115
    }
116 1
    storefronts = storefront_service.find_storefronts(storefront_ids)
117 1
    storefronts_by_id = {
118
        storefront.id: storefront for storefront in storefronts
119
    }
120 1
    return {
121
        site.id: storefronts_by_id.get(site.storefront_id) for site in sites
122
    }
123
124
125 1
@blueprint.route('/sites/<site_id>')
126 1
@permission_required(SitePermission.view)
127 1
@templated
128
def view(site_id):
129
    """Show a site's settings."""
130 1
    site = site_service.find_site(site_id)
131 1
    if site is None:
132
        abort(404)
133
134 1
    brand = brand_service.find_brand(site.brand_id)
135
136 1
    if site.news_channel_id:
137
        news_channel = news_channel_service.find_channel(site.news_channel_id)
138
    else:
139 1
        news_channel = None
140
141 1
    if site.board_id:
142 1
        board = board_service.find_board(site.board_id)
143
    else:
144
        board = None
145
146 1
    if site.storefront_id:
147
        storefront = storefront_service.get_storefront(site.storefront_id)
148
        shop = shop_service.get_shop(storefront.shop_id)
149
    else:
150 1
        storefront = None
151 1
        shop = None
152
153 1
    settings = site_settings_service.get_settings(site.id)
154
155 1
    return {
156
        'site': site,
157
        'brand': brand,
158
        'news_channel': news_channel,
159
        'board': board,
160
        'shop': shop,
161
        'storefront': storefront,
162
        'settings': settings,
163
    }
164
165
166 1
@blueprint.route('/sites/create/for_brand/<brand_id>')
167 1
@permission_required(SitePermission.create)
168 1
@templated
169 1
def create_form(brand_id, erroneous_form=None):
170
    """Show form to create a site."""
171 1
    brand = _get_brand_or_404(brand_id)
172
173 1
    form = erroneous_form if erroneous_form else CreateForm()
174 1
    _fill_in_common_form_choices(form, brand.id)
175
176 1
    return {
177
        'brand': brand,
178
        'form': form,
179
    }
180
181
182 1
@blueprint.route('/sites/for_brand/<brand_id>', methods=['POST'])
183 1
@permission_required(SitePermission.create)
184
def create(brand_id):
185
    """Create a site."""
186 1
    brand = _get_brand_or_404(brand_id)
187
188 1
    form = CreateForm(request.form)
189 1
    _fill_in_common_form_choices(form, brand.id)
190
191 1
    if not form.validate():
192
        return create_form(brand_id, form)
193
194 1
    site_id = form.id.data.strip().lower()
195 1
    title = form.title.data.strip()
196 1
    server_name = form.server_name.data.strip()
197 1
    email_config_id = form.email_config_id.data
198 1
    party_id = form.party_id.data
199 1
    enabled = form.enabled.data
200 1
    user_account_creation_enabled = form.user_account_creation_enabled.data
201 1
    login_enabled = form.login_enabled.data
202 1
    news_channel_id = form.news_channel_id.data.strip() or None
203 1
    board_id = form.board_id.data.strip() or None
204 1
    storefront_id = form.storefront_id.data.strip() or None
205
206 1
    if party_id:
207
        party = party_service.find_party(party_id)
208
        if not party:
209
            flash_error(f'Die Party-ID "{party_id}" ist unbekannt.')
210
            return create_form(brand_id, form)
211
    else:
212 1
        party_id = None
213
214 1
    site = site_service.create_site(
215
        site_id,
216
        title,
217
        server_name,
218
        brand.id,
219
        email_config_id,
220
        enabled=enabled,
221
        user_account_creation_enabled=user_account_creation_enabled,
222
        login_enabled=login_enabled,
223
        party_id=party_id,
224
        board_id=board_id,
225
        news_channel_id=news_channel_id,
226
        storefront_id=storefront_id,
227
    )
228
229 1
    flash_success(f'Die Site "{site.title}" wurde angelegt.')
230 1
    return redirect_to('.view', site_id=site.id)
231
232
233 1
@blueprint.route('/sites/<site_id>/update')
234 1
@permission_required(SitePermission.update)
235 1
@templated
236 1
def update_form(site_id, erroneous_form=None):
237
    """Show form to update the site."""
238 1
    site = _get_site_or_404(site_id)
239
240 1
    form = erroneous_form if erroneous_form else UpdateForm(obj=site)
241 1
    form.set_brand_choices()
242 1
    _fill_in_common_form_choices(form, site.brand_id)
243
244 1
    return {
245
        'site': site,
246
        'form': form,
247
    }
248
249
250 1
@blueprint.route('/sites/<site_id>', methods=['POST'])
251 1
@permission_required(SitePermission.update)
252
def update(site_id):
253
    """Update the site."""
254
    site = _get_site_or_404(site_id)
255
256
    form = UpdateForm(request.form)
257
    form.set_brand_choices()
258
    _fill_in_common_form_choices(form, site.brand_id)
259
260
    if not form.validate():
261
        return update_form(site.id, form)
262
263
    title = form.title.data.strip()
264
    server_name = form.server_name.data.strip()
265
    brand_id = form.brand_id.data
266
    email_config_id = form.email_config_id.data
267
    party_id = form.party_id.data
268
    enabled = form.enabled.data
269
    user_account_creation_enabled = form.user_account_creation_enabled.data
270
    login_enabled = form.login_enabled.data
271
    news_channel_id = form.news_channel_id.data.strip() or None
272
    board_id = form.board_id.data.strip() or None
273
    storefront_id = form.storefront_id.data.strip() or None
274
    archived = form.archived.data
275
276
    if party_id:
277
        party = party_service.find_party(party_id)
278
        if not party:
279
            flash_error(f'Die Party-ID "{party_id}" ist unbekannt.')
280
            return update_form(site.id, form)
281
    else:
282
        party_id = None
283
284
    try:
285
        site = site_service.update_site(
286
            site.id,
287
            title,
288
            server_name,
289
            brand_id,
290
            email_config_id,
291
            party_id,
292
            enabled,
293
            user_account_creation_enabled,
294
            login_enabled,
295
            news_channel_id,
296
            board_id,
297
            storefront_id,
298
            archived,
299
        )
300
    except site_service.UnknownSiteId:
301
        abort(404, f'Unknown site ID "{site_id}".')
302
303
    flash_success(f'Die Site "{site.title}" wurde aktualisiert.')
304
305
    return redirect_to('.view', site_id=site.id)
306
307
308 1
def _fill_in_common_form_choices(form, brand_id):
309 1
    form.set_email_config_choices()
310 1
    form.set_party_choices(brand_id)
311 1
    form.set_board_choices(brand_id)
312 1
    form.set_news_channel_choices(brand_id)
313 1
    form.set_storefront_choices()
314
315
316 1
def _get_site_or_404(site_id):
317 1
    site = site_service.find_site(site_id)
318
319 1
    if site is None:
320
        abort(404)
321
322 1
    return site
323
324
325 1
def _get_brand_or_404(brand_id):
326 1
    brand = brand_service.find_brand(brand_id)
327
328 1
    if brand is None:
329
        abort(404)
330
331
    return brand
332