byceps.blueprints.admin.site.views.update()   B
last analyzed

Complexity

Conditions 5

Size

Total Lines 59
Code Lines 46

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 25.3237

Importance

Changes 0
Metric Value
cc 5
eloc 46
nop 1
dl 0
loc 59
ccs 2
cts 30
cp 0.0667
crap 25.3237
rs 8.3006
c 0
b 0
f 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
"""
2
byceps.blueprints.admin.site.views
3
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4
5
:Copyright: 2006-2021 Jochen Kupperschmidt
6
:License: Revised BSD (see `LICENSE` file for details)
7
"""
8
9 1
from __future__ import annotations
10 1
import dataclasses
11 1
from typing import Iterable, Iterator
12
13 1
from flask import abort, request
14 1
from flask_babel import gettext
15
16 1
from ....services.board import board_service
17 1
from ....services.brand import service as brand_service
18 1
from ....services.brand.transfer.models import Brand
19 1
from ....services.news import channel_service as news_channel_service
20 1
from ....services.party import service as party_service
21 1
from ....services.shop.shop import service as shop_service
22 1
from ....services.shop.storefront import service as storefront_service
23 1
from ....services.shop.storefront.transfer.models import (
24
    Storefront,
25
    StorefrontID,
26
)
27 1
from ....services.site import (
28
    service as site_service,
29
    settings_service as site_settings_service,
30
)
31 1
from ....services.site.transfer.models import Site, SiteWithBrand
32 1
from ....util.framework.blueprint import create_blueprint
33 1
from ....util.framework.flash import flash_error, flash_success
34 1
from ....util.framework.templating import templated
35 1
from ....util.views import permission_required, redirect_to, respond_no_content
36
37 1
from .forms import AddNewsChannelForm, CreateForm, UpdateForm
38
39
40 1
blueprint = create_blueprint('site_admin', __name__)
41
42
43 1
@blueprint.get('/')
44 1
@permission_required('site.view')
45 1
@templated
46
def index():
47
    """List all sites."""
48 1
    brands = brand_service.get_all_brands()
49 1
    brands.sort(key=lambda brand: brand.title)
50
51 1
    sites = site_service.get_all_sites()
52 1
    sites = list(_sites_to_sites_with_brand(sites, brands))
53 1
    sites.sort(key=lambda site: (site.title, site.party_id))
54
55 1
    parties = party_service.get_all_parties()
56 1
    party_titles_by_id = {p.id: p.title for p in parties}
57
58 1
    storefronts_by_id = _get_storefronts_by_id(sites)
59
60 1
    return {
61
        'sites': sites,
62
        'brands': brands,
63
        'party_titles_by_id': party_titles_by_id,
64
        'storefronts_by_id': storefronts_by_id,
65
    }
66
67
68 1
@blueprint.get('/for_brand/<brand_id>')
69 1
@permission_required('site.view')
70 1
@templated
71
def index_for_brand(brand_id):
72
    """List sites for this brand."""
73
    brand = brand_service.find_brand(brand_id)
74
    if brand is None:
75
        abort(404)
76
77
    sites = site_service.get_sites_for_brand(brand.id)
78
    sites = [_site_to_site_with_brand(site, brand) for site in sites]
79
    sites.sort(key=lambda site: (site.title, site.party_id))
80
81
    parties = party_service.get_all_parties()
82
    party_titles_by_id = {p.id: p.title for p in parties}
83
84
    storefronts_by_id = _get_storefronts_by_id(sites)
85
86
    return {
87
        'sites': sites,
88
        'brand': brand,
89
        'party_titles_by_id': party_titles_by_id,
90
        'storefronts_by_id': storefronts_by_id,
91
    }
92
93
94 1
def _sites_to_sites_with_brand(
95
    sites: Iterable[Site], brands: Iterable[Brand]
96
) -> Iterator[SiteWithBrand]:
97 1
    brands_by_id = {brand.id: brand for brand in brands}
98
99 1
    for site in sites:
100 1
        brand = brands_by_id[site.brand_id]
101 1
        yield _site_to_site_with_brand(site, brand)
102
103
104 1
def _site_to_site_with_brand(site: Site, brand: Brand) -> SiteWithBrand:
105 1
    site_tuple = dataclasses.astuple(site)
106 1
    brand_tuple = (brand,)
107
108 1
    return SiteWithBrand(*(site_tuple + brand_tuple))
109
110
111 1
def _get_storefronts_by_id(sites) -> dict[StorefrontID, Storefront]:
112 1
    storefront_ids = {
113
        site.storefront_id for site in sites if site.storefront_id is not None
114
    }
115 1
    storefronts = storefront_service.find_storefronts(storefront_ids)
116 1
    return {storefront.id: storefront for storefront in storefronts}
117
118
119 1
@blueprint.get('/sites/<site_id>')
120 1
@permission_required('site.view')
121 1
@templated
122
def view(site_id):
123
    """Show a site's settings."""
124 1
    site = site_service.find_site(site_id)
125 1
    if site is None:
126
        abort(404)
127
128 1
    brand = brand_service.find_brand(site.brand_id)
129
130 1
    news_channels = news_channel_service.get_channels(site.news_channel_ids)
131
132 1
    if site.board_id:
133 1
        board = board_service.find_board(site.board_id)
134
    else:
135
        board = None
136
137 1
    if site.storefront_id:
138
        storefront = storefront_service.get_storefront(site.storefront_id)
139
        shop = shop_service.get_shop(storefront.shop_id)
140
    else:
141 1
        storefront = None
142 1
        shop = None
143
144 1
    settings = site_settings_service.get_settings(site.id)
145
146 1
    return {
147
        'site': site,
148
        'brand': brand,
149
        'news_channels': news_channels,
150
        'board': board,
151
        'shop': shop,
152
        'storefront': storefront,
153
        'settings': settings,
154
    }
155
156
157 1
@blueprint.get('/sites/create/for_brand/<brand_id>')
158 1
@permission_required('site.create')
159 1
@templated
160 1
def create_form(brand_id, erroneous_form=None):
161
    """Show form to create a site."""
162 1
    brand = _get_brand_or_404(brand_id)
163
164 1
    form = erroneous_form if erroneous_form else CreateForm()
165 1
    _fill_in_common_form_choices(form, brand.id)
166
167 1
    return {
168
        'brand': brand,
169
        'form': form,
170
    }
171
172
173 1
@blueprint.post('/sites/for_brand/<brand_id>')
174 1
@permission_required('site.create')
175
def create(brand_id):
176
    """Create a site."""
177 1
    brand = _get_brand_or_404(brand_id)
178
179 1
    form = CreateForm(request.form)
180 1
    _fill_in_common_form_choices(form, brand.id)
181
182 1
    if not form.validate():
183
        return create_form(brand_id, form)
184
185 1
    site_id = form.id.data.strip().lower()
186 1
    title = form.title.data.strip()
187 1
    server_name = form.server_name.data.strip()
188 1
    party_id = form.party_id.data
189 1
    enabled = form.enabled.data
190 1
    user_account_creation_enabled = form.user_account_creation_enabled.data
191 1
    login_enabled = form.login_enabled.data
192 1
    board_id = form.board_id.data.strip() or None
193 1
    storefront_id = form.storefront_id.data.strip() or None
194
195 1
    if party_id:
196
        party = party_service.find_party(party_id)
197
        if not party:
198
            flash_error(
199
                gettext(
200
                    'Party ID "%(party_id)s" is unknown.',
201
                    party_id=party_id,
202
                )
203
            )
204
            return create_form(brand_id, form)
205
    else:
206 1
        party_id = None
207
208 1
    site = site_service.create_site(
209
        site_id,
210
        title,
211
        server_name,
212
        brand.id,
213
        enabled=enabled,
214
        user_account_creation_enabled=user_account_creation_enabled,
215
        login_enabled=login_enabled,
216
        party_id=party_id,
217
        board_id=board_id,
218
        storefront_id=storefront_id,
219
    )
220
221 1
    flash_success(
222
        gettext('Site "%(title)s" has been created.', title=site.title)
223
    )
224
225 1
    return redirect_to('.view', site_id=site.id)
226
227
228 1
@blueprint.get('/sites/<site_id>/update')
229 1
@permission_required('site.update')
230 1
@templated
231 1
def update_form(site_id, erroneous_form=None):
232
    """Show form to update the site."""
233 1
    site = _get_site_or_404(site_id)
234
235 1
    form = erroneous_form if erroneous_form else UpdateForm(obj=site)
236 1
    form.set_brand_choices()
237 1
    _fill_in_common_form_choices(form, site.brand_id)
238
239 1
    return {
240
        'site': site,
241
        'form': form,
242
    }
243
244
245 1
@blueprint.post('/sites/<site_id>')
246 1
@permission_required('site.update')
247
def update(site_id):
248
    """Update the site."""
249
    site = _get_site_or_404(site_id)
250
251
    form = UpdateForm(request.form)
252
    form.set_brand_choices()
253
    _fill_in_common_form_choices(form, site.brand_id)
254
255
    if not form.validate():
256
        return update_form(site.id, form)
257
258
    title = form.title.data.strip()
259
    server_name = form.server_name.data.strip()
260
    brand_id = form.brand_id.data
261
    party_id = form.party_id.data
262
    enabled = form.enabled.data
263
    user_account_creation_enabled = form.user_account_creation_enabled.data
264
    login_enabled = form.login_enabled.data
265
    board_id = form.board_id.data.strip() or None
266
    storefront_id = form.storefront_id.data.strip() or None
267
    archived = form.archived.data
268
269
    if party_id:
270
        party = party_service.find_party(party_id)
271
        if not party:
272
            flash_error(
273
                gettext(
274
                    'Party ID "%(party_id)s" is unknown.',
275
                    party_id=party_id,
276
                )
277
            )
278
            return update_form(site.id, form)
279
    else:
280
        party_id = None
281
282
    try:
283
        site = site_service.update_site(
284
            site.id,
285
            title,
286
            server_name,
287
            brand_id,
288
            party_id,
289
            enabled,
290
            user_account_creation_enabled,
291
            login_enabled,
292
            board_id,
293
            storefront_id,
294
            archived,
295
        )
296
    except site_service.UnknownSiteId:
297
        abort(404, f'Unknown site ID "{site_id}".')
298
299
    flash_success(
300
        gettext('Site "%(title)s" has been updated.', title=site.title)
301
    )
302
303
    return redirect_to('.view', site_id=site.id)
304
305
306 1
def _fill_in_common_form_choices(form, brand_id):
307 1
    form.set_party_choices(brand_id)
308 1
    form.set_board_choices(brand_id)
309 1
    form.set_storefront_choices()
310
311
312
# -------------------------------------------------------------------- #
313
# news channels
314
315
316 1
@blueprint.get('/sites/<site_id>/news_channels/add')
317 1
@permission_required('site.update')
318 1
@templated
319 1
def add_news_channel_form(site_id, erroneous_form=None):
320
    """Show form to add a news channel to the site."""
321
    site = _get_site_or_404(site_id)
322
323
    form = erroneous_form if erroneous_form else AddNewsChannelForm()
324
    form.set_news_channel_choices(site.brand_id)
325
326
    return {
327
        'site': site,
328
        'form': form,
329
    }
330
331
332 1
@blueprint.post('/sites/<site_id>/news_channels')
333 1
@permission_required('site.update')
334
def add_news_channel(site_id):
335
    """Add a news channel to the site."""
336
    site = _get_site_or_404(site_id)
337
338
    form = AddNewsChannelForm(request.form)
339
    form.set_news_channel_choices(site.brand_id)
340
341
    if not form.validate():
342
        return add_news_channel_form(site.id, form)
343
344
    news_channel_id = form.news_channel_id.data
345
    news_channel = news_channel_service.get_channel(news_channel_id)
346
347
    site_service.add_news_channel(site.id, news_channel.id)
348
349
    flash_success(
350
        gettext(
351
            'News channel "%(news_channel_id)s" has been added to site "%(site_title)s".',
352
            news_channel_id=news_channel.id,
353
            site_title=site.title,
354
        )
355
    )
356
357
    return redirect_to('.view', site_id=site.id)
358
359
360 1
@blueprint.delete('/sites/<site_id>/news_channels/<news_channel_id>')
361 1
@permission_required('site.update')
362 1
@respond_no_content
363
def remove_news_channel(site_id, news_channel_id):
364
    """Remove the news channel from the site."""
365
    site = _get_site_or_404(site_id)
366
367
    news_channel = news_channel_service.find_channel(news_channel_id)
368
    if news_channel is None:
369
        abort(404)
370
371
    news_channel_id = news_channel.id
372
373
    site_service.remove_news_channel(site.id, news_channel.id)
374
375
    flash_success(
376
        gettext(
377
            'News channel "%(news_channel_id)s" has been removed from site "%(site_title)s".',
378
            news_channel_id=news_channel.id,
379
            site_title=site.title,
380
        )
381
    )
382
383
384
# -------------------------------------------------------------------- #
385
386
387 1
def _get_site_or_404(site_id):
388 1
    site = site_service.find_site(site_id)
389
390 1
    if site is None:
391
        abort(404)
392
393 1
    return site
394
395
396 1
def _get_brand_or_404(brand_id):
397 1
    brand = brand_service.find_brand(brand_id)
398
399 1
    if brand is None:
400
        abort(404)
401
402
    return brand
403