byceps.blueprints.admin.user.views   F
last analyzed

Complexity

Total Complexity 60

Size/Duplication

Total Lines 790
Duplicated Lines 14.43 %

Test Coverage

Coverage 56.1%

Importance

Changes 0
Metric Value
eloc 490
dl 114
loc 790
ccs 184
cts 328
cp 0.561
rs 3.6
c 0
b 0
f 0
wmc 60

28 Functions

Rating   Name   Duplication   Size   Complexity  
A _calculate_days_since() 0 5 2
A delete_account_form() 0 23 3
A unsuspend_account() 35 36 3
A change_email_address() 0 30 2
B create_account() 0 62 5
A view() 0 41 1
A set_password() 0 23 2
A role_deassign() 0 18 1
A change_screen_name_form() 0 14 2
A _get_role_or_404() 0 7 2
A view_events() 0 21 2
A manage_roles() 0 19 1
A invalidate_email_address() 0 32 3
A invalidate_email_address_form() 0 18 3
A change_email_address_form() 0 14 2
A delete_account() 0 34 3
A set_password_form() 0 14 2
A role_assign() 0 18 1
A initialize_account() 0 15 1
A _get_db_user_with_details_or_404() 0 7 2
A unsuspend_account_form() 23 23 3
A suspend_account_form() 23 23 3
A index() 0 35 1
A create_account_form() 0 9 2
A _get_user_or_404() 0 7 2
A view_permissions() 0 18 1
A suspend_account() 33 34 3
A change_screen_name() 0 30 2

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complexity

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like byceps.blueprints.admin.user.views often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
"""
2
byceps.blueprints.admin.user.views
3
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4
5
:Copyright: 2006-2021 Jochen Kupperschmidt
6
:License: Revised BSD (see `LICENSE` file for details)
7
"""
8
9 1
from datetime import datetime
10 1
from typing import Optional
11
12 1
from flask import abort, g, request
13 1
from flask_babel import gettext
14
15 1
from ....services.authentication.password import service as password_service
16 1
from ....services.authentication.session import service as session_service
17 1
from ....services.authorization import service as authorization_service
18 1
from ....services.orga_team import service as orga_team_service
19 1
from ....services.shop.order import service as order_service
20 1
from ....services.shop.shop import service as shop_service
21 1
from ....services.site import service as site_service
22 1
from ....services.user import (
23
    command_service as user_command_service,
24
    creation_service as user_creation_service,
25
    deletion_service as user_deletion_service,
26
    email_address_verification_service,
27
    service as user_service,
28
    stats_service as user_stats_service,
29
)
30 1
from ....services.user_badge import awarding_service as badge_awarding_service
31 1
from ....signals import user as user_signals
32 1
from ....util.authorization import register_permission_enum
33 1
from ....util.framework.blueprint import create_blueprint
34 1
from ....util.framework.flash import flash_error, flash_success
35 1
from ....util.framework.templating import templated
36 1
from ....util.views import permission_required, redirect_to, respond_no_content
37
38 1
from ..authorization.authorization import RolePermission
39
40 1
from .authorization import UserPermission
41 1
from .forms import (
42
    ChangeEmailAddressForm,
43
    ChangeScreenNameForm,
44
    CreateAccountForm,
45
    DeleteAccountForm,
46
    InvalidateEmailAddressForm,
47
    SetPasswordForm,
48
    SuspendAccountForm,
49
)
50 1
from .models import UserStateFilter
51 1
from . import service
52
53
54 1
blueprint = create_blueprint('user_admin', __name__)
55
56
57 1
register_permission_enum(UserPermission)
58
59
60 1
@blueprint.get('/', defaults={'page': 1})
61 1
@blueprint.get('/pages/<int:page>')
62 1
@permission_required(UserPermission.view)
63 1
@templated
64
def index(page):
65
    """List users."""
66 1
    per_page = request.args.get('per_page', type=int, default=20)
67 1
    search_term = request.args.get('search_term', default='').strip()
68 1
    only = request.args.get('only')
69
70 1
    user_state_filter = UserStateFilter.__members__.get(
71
        only, UserStateFilter.none
72
    )
73
74 1
    users = service.get_users_paginated(
75
        page, per_page, search_term=search_term, state_filter=user_state_filter
76
    )
77
78 1
    total_active = user_stats_service.count_active_users()
79 1
    total_uninitialized = user_stats_service.count_uninitialized_users()
80 1
    total_suspended = user_stats_service.count_suspended_users()
81 1
    total_deleted = user_stats_service.count_deleted_users()
82 1
    total_overall = user_stats_service.count_users()
83
84 1
    return {
85
        'users': users,
86
        'total_active': total_active,
87
        'total_uninitialized': total_uninitialized,
88
        'total_suspended': total_suspended,
89
        'total_deleted': total_deleted,
90
        'total_overall': total_overall,
91
        'search_term': search_term,
92
        'only': only,
93
        'UserStateFilter': UserStateFilter,
94
        'user_state_filter': user_state_filter,
95
    }
96
97
98 1
@blueprint.get('/<uuid:user_id>')
99 1
@permission_required(UserPermission.view)
100 1
@templated
101
def view(user_id):
102
    """Show a user's interal profile."""
103 1
    db_user = _get_db_user_with_details_or_404(user_id)
104 1
    user = user_service.get_user(db_user.id, include_avatar=True)
105
106 1
    recent_login = session_service.find_recent_login(user.id)
107 1
    days_since_recent_login = _calculate_days_since(recent_login)
108
109 1
    orga_activities = orga_team_service.get_orga_activities_for_user(user.id)
110
111 1
    newsletter_subscriptions = service.get_newsletter_subscriptions(user.id)
112
113 1
    orders = order_service.get_orders_placed_by_user(user.id)
114
115 1
    order_shop_ids = {order.shop_id for order in orders}
116 1
    shops = shop_service.find_shops(order_shop_ids)
117 1
    shops_by_id = {shop.id: shop for shop in shops}
118
119 1
    parties_and_tickets = service.get_parties_and_tickets(user.id)
120
121 1
    attended_parties = service.get_attended_parties(user.id)
122
123 1
    badges_with_awarding_quantity = (
124
        badge_awarding_service.get_badges_awarded_to_user(user.id)
125
    )
126
127 1
    return {
128
        'user': db_user,
129
        'user_dto': user,
130
        'recent_login': recent_login,
131
        'days_since_recent_login': days_since_recent_login,
132
        'orga_activities': orga_activities,
133
        'newsletter_subscriptions': newsletter_subscriptions,
134
        'orders': orders,
135
        'shops_by_id': shops_by_id,
136
        'parties_and_tickets': parties_and_tickets,
137
        'attended_parties': attended_parties,
138
        'badges_with_awarding_quantity': badges_with_awarding_quantity,
139
    }
140
141
142 1
def _calculate_days_since(dt: Optional[datetime]) -> Optional[int]:
143 1
    if dt is None:
144 1
        return None
145
146
    return (datetime.utcnow().date() - dt.date()).days
147
148
149
# -------------------------------------------------------------------- #
150
# account
151
152
153 1
@blueprint.get('/create')
154 1
@permission_required(UserPermission.create)
155 1
@templated
156 1
def create_account_form(erroneous_form=None):
157
    """Show a form to create a user account."""
158 1
    form = erroneous_form if erroneous_form else CreateAccountForm()
159 1
    form.set_site_choices()
160
161 1
    return {'form': form}
162
163
164 1
@blueprint.post('/')
165 1
@permission_required(UserPermission.create)
166
def create_account():
167
    """Create a user account."""
168
    form = CreateAccountForm(request.form)
169
    form.set_site_choices()
170
171
    if not form.validate():
172
        return create_account_form(form)
173
174
    screen_name = form.screen_name.data.strip()
175
    first_names = form.first_names.data.strip()
176
    last_name = form.last_name.data.strip()
177
    email_address = form.email_address.data.lower()
178
    password = form.password.data
179
    site_id_for_email = form.site_id.data
180
181
    if site_id_for_email:
182
        site_for_email = site_service.get_site(site_id_for_email)
183
    else:
184
        site_for_email = None
185
186
    initiator_id = g.user.id
187
188
    try:
189
        user, event = user_creation_service.create_basic_user(
190
            screen_name,
191
            email_address,
192
            password,
193
            first_names=first_names,
194
            last_name=last_name,
195
            creator_id=initiator_id,
196
            # Do not pass site ID here; the account is not created on a site.
197
        )
198
    except user_creation_service.UserCreationFailed:
199
        flash_error(
200
            gettext(
201
                'User "%(screen_name)s" could not be created.',
202
                screen_name=screen_name,
203
            )
204
        )
205
        return create_account_form(form)
206
207
    flash_success(
208
        gettext(
209
            'User "%(screen_name)s" has been created.',
210
            screen_name=user.screen_name,
211
        )
212
    )
213
214
    if site_for_email:
215
        user_creation_service.request_email_address_confirmation(
216
            user, email_address, site_id_for_email.id
217
        )
218
        flash_success(
219
            gettext('An email has been sent to the corresponding address.'),
220
            icon='email',
221
        )
222
223
    user_signals.account_created.send(None, event=event)
224
225
    return redirect_to('.view', user_id=user.id)
226
227
228 1
@blueprint.post('/<uuid:user_id>/initialize')
229 1
@permission_required(UserPermission.administrate)
230 1
@respond_no_content
231
def initialize_account(user_id):
232
    """Initialize the user account."""
233
    user = _get_user_or_404(user_id)
234
235
    initiator_id = g.user.id
236
237
    user_command_service.initialize_account(user.id, initiator_id=initiator_id)
238
239
    flash_success(
240
        gettext(
241
            "User '%(screen_name)s' has been initialized.",
242
            screen_name=user.screen_name,
243
        )
244
    )
245
246
247 1 View Code Duplication
@blueprint.get('/<uuid:user_id>/suspend')
248 1
@permission_required(UserPermission.administrate)
249 1
@templated
250 1
def suspend_account_form(user_id, erroneous_form=None):
251
    """Show form to suspend the user account."""
252 1
    db_user = _get_db_user_with_details_or_404(user_id)
253 1
    user = user_service.get_user(db_user.id, include_avatar=True)
254
255 1
    if user.suspended:
256 1
        flash_error(
257
            gettext(
258
                "User '%(screen_name)s' is already suspended.",
259
                screen_name=user.screen_name,
260
            )
261
        )
262 1
        return redirect_to('.view', user_id=user.id)
263
264 1
    form = erroneous_form if erroneous_form else SuspendAccountForm()
265
266 1
    return {
267
        'user': db_user,
268
        'user_dto': user,
269
        'form': form,
270
    }
271
272
273 1 View Code Duplication
@blueprint.post('/<uuid:user_id>/suspend')
274 1
@permission_required(UserPermission.administrate)
275
def suspend_account(user_id):
276
    """Suspend the user account."""
277
    user = _get_user_or_404(user_id)
278
279
    if user.suspended:
280
        flash_error(
281
            gettext(
282
                "User '%(screen_name)s' is already suspended.",
283
                screen_name=user.screen_name,
284
            )
285
        )
286
        return redirect_to('.view', user_id=user.id)
287
288
    form = SuspendAccountForm(request.form)
289
    if not form.validate():
290
        return suspend_account_form(user.id, form)
291
292
    initiator_id = g.user.id
293
    reason = form.reason.data.strip()
294
295
    event = user_command_service.suspend_account(user.id, initiator_id, reason)
296
297
    user_signals.account_suspended.send(None, event=event)
298
299
    flash_success(
300
        gettext(
301
            "User '%(screen_name)s' has been suspended.",
302
            screen_name=user.screen_name,
303
        )
304
    )
305
306
    return redirect_to('.view', user_id=user.id)
307
308
309 1 View Code Duplication
@blueprint.get('/<uuid:user_id>/unsuspend')
310 1
@permission_required(UserPermission.administrate)
311 1
@templated
312 1
def unsuspend_account_form(user_id, erroneous_form=None):
313
    """Show form to unsuspend the user account."""
314 1
    db_user = _get_db_user_with_details_or_404(user_id)
315 1
    user = user_service.get_user(db_user.id, include_avatar=True)
316
317 1
    if not user.suspended:
318 1
        flash_error(
319
            gettext(
320
                "User '%(screen_name)s' is not suspended.",
321
                screen_name=user.screen_name,
322
            )
323
        )
324 1
        return redirect_to('.view', user_id=user.id)
325
326 1
    form = erroneous_form if erroneous_form else SuspendAccountForm()
327
328 1
    return {
329
        'user': db_user,
330
        'user_dto': user,
331
        'form': form,
332
    }
333
334
335 1 View Code Duplication
@blueprint.post('/<uuid:user_id>/unsuspend')
336 1
@permission_required(UserPermission.administrate)
337
def unsuspend_account(user_id):
338
    """Unsuspend the user account."""
339
    user = _get_user_or_404(user_id)
340
341
    if not user.suspended:
342
        flash_error(
343
            gettext(
344
                "User '%(screen_name)s' is not suspended.",
345
                screen_name=user.screen_name,
346
            )
347
        )
348
        return redirect_to('.view', user_id=user.id)
349
350
    form = SuspendAccountForm(request.form)
351
    if not form.validate():
352
        return unsuspend_account_form(user.id, form)
353
354
    initiator_id = g.user.id
355
    reason = form.reason.data.strip()
356
357
    event = user_command_service.unsuspend_account(
358
        user.id, initiator_id, reason
359
    )
360
361
    user_signals.account_unsuspended.send(None, event=event)
362
363
    flash_success(
364
        gettext(
365
            "User '%(screen_name)s' has been unsuspended.",
366
            screen_name=user.screen_name,
367
        )
368
    )
369
370
    return redirect_to('.view', user_id=user.id)
371
372
373 1
@blueprint.get('/<uuid:user_id>/delete')
374 1
@permission_required(UserPermission.administrate)
375 1
@templated
376 1
def delete_account_form(user_id, erroneous_form=None):
377
    """Show form to delete the user account."""
378 1
    db_user = _get_db_user_with_details_or_404(user_id)
379 1
    user = user_service.get_user(db_user.id, include_avatar=True)
380
381 1
    if user.deleted:
382 1
        flash_error(
383
            gettext(
384
                "User '%(screen_name)s' has already been deleted.",
385
                screen_name=user.screen_name,
386
            )
387
        )
388 1
        return redirect_to('.view', user_id=user.id)
389
390 1
    form = erroneous_form if erroneous_form else DeleteAccountForm()
391
392 1
    return {
393
        'user': db_user,
394
        'user_dto': user,
395
        'form': form,
396
    }
397
398
399 1
@blueprint.post('/<uuid:user_id>/delete')
400 1
@permission_required(UserPermission.administrate)
401
def delete_account(user_id):
402
    """Delete the user account."""
403
    user = _get_user_or_404(user_id)
404
405
    if user.deleted:
406
        flash_error(
407
            gettext(
408
                "User '%(screen_name)s' has already been deleted.",
409
                screen_name=user.screen_name,
410
            )
411
        )
412
        return redirect_to('.view', user_id=user.id)
413
414
    form = DeleteAccountForm(request.form)
415
    if not form.validate():
416
        return delete_account_form(user.id, form)
417
418
    initiator_id = g.user.id
419
    reason = form.reason.data.strip()
420
421
    event = user_deletion_service.delete_account(user.id, initiator_id, reason)
422
423
    user_signals.account_deleted.send(None, event=event)
424
425
    flash_success(
426
        gettext(
427
            "User '%(screen_name)s' has been deleted.",
428
            screen_name=user.screen_name,
429
        )
430
    )
431
432
    return redirect_to('.view', user_id=user.id)
433
434
435
# -------------------------------------------------------------------- #
436
# screen name
437
438
439 1
@blueprint.get('/<uuid:user_id>/change_screen_name')
440 1
@permission_required(UserPermission.administrate)
441 1
@templated
442 1
def change_screen_name_form(user_id, erroneous_form=None):
443
    """Show form to change the user's screen name."""
444 1
    db_user = _get_db_user_with_details_or_404(user_id)
445 1
    user = user_service.get_user(db_user.id, include_avatar=True)
446
447 1
    form = erroneous_form if erroneous_form else ChangeScreenNameForm()
448
449 1
    return {
450
        'user': db_user,
451
        'user_dto': user,
452
        'form': form,
453
    }
454
455
456 1
@blueprint.post('/<uuid:user_id>/change_screen_name')
457 1
@permission_required(UserPermission.administrate)
458
def change_screen_name(user_id):
459
    """Change the user's screen name."""
460
    user = _get_user_or_404(user_id)
461
462
    form = ChangeScreenNameForm(request.form)
463
    if not form.validate():
464
        return change_screen_name_form(user.id, form)
465
466
    old_screen_name = user.screen_name
467
    new_screen_name = form.screen_name.data.strip()
468
    initiator_id = g.user.id
469
    reason = form.reason.data.strip()
470
471
    event = user_command_service.change_screen_name(
472
        user.id, new_screen_name, initiator_id, reason=reason
473
    )
474
475
    user_signals.screen_name_changed.send(None, event=event)
476
477
    flash_success(
478
        gettext(
479
            "User '%(old_screen_name)s' has been renamed to '%(new_screen_name)s'.",
480
            old_screen_name=old_screen_name,
481
            new_screen_name=new_screen_name,
482
        )
483
    )
484
485
    return redirect_to('.view', user_id=user.id)
486
487
488
# -------------------------------------------------------------------- #
489
# email address
490
491
492 1
@blueprint.get('/<uuid:user_id>/change_email_address')
493 1
@permission_required(UserPermission.administrate)
494 1
@templated
495 1
def change_email_address_form(user_id, erroneous_form=None):
496
    """Show form to change the user's e-mail address."""
497 1
    db_user = _get_db_user_with_details_or_404(user_id)
498 1
    user = user_service.get_user(db_user.id, include_avatar=True)
499
500 1
    form = erroneous_form if erroneous_form else ChangeEmailAddressForm()
501
502 1
    return {
503
        'user': db_user,
504
        'user_dto': user,
505
        'form': form,
506
    }
507
508
509 1
@blueprint.post('/<uuid:user_id>/change_email_address')
510 1
@permission_required(UserPermission.administrate)
511
def change_email_address(user_id):
512
    """Change the user's e-mail address."""
513
    user = _get_user_or_404(user_id)
514
515
    form = ChangeEmailAddressForm(request.form)
516
    if not form.validate():
517
        return change_email_address_form(user.id, form)
518
519
    old_email_address = user_service.find_email_address(user.id)
520
    new_email_address = form.email_address.data.strip()
521
    verified = False
522
    initiator_id = g.user.id
523
    reason = form.reason.data.strip()
524
525
    event = user_command_service.change_email_address(
526
        user.id, new_email_address, verified, initiator_id, reason=reason
527
    )
528
529
    user_signals.email_address_changed.send(None, event=event)
530
531
    flash_success(
532
        gettext(
533
            "Email address for user '%(screen_name)s' has been updated.",
534
            screen_name=user.screen_name,
535
        )
536
    )
537
538
    return redirect_to('.view', user_id=user.id)
539
540
541 1
@blueprint.get('/<uuid:user_id>/invalidate_email_address')
542 1
@permission_required(UserPermission.administrate)
543 1
@templated
544 1
def invalidate_email_address_form(user_id, erroneous_form=None):
545
    """Show form to invalidate the email address assigned with the account."""
546
    db_user = _get_db_user_with_details_or_404(user_id)
547
    user = user_service.get_user(db_user.id, include_avatar=True)
548
549
    if not db_user.email_address_verified:
550
        flash_error(gettext('Email address is already invalidated.'))
551
        return redirect_to('.view', user_id=user.id)
552
553
    form = erroneous_form if erroneous_form else InvalidateEmailAddressForm()
554
555
    return {
556
        'user': db_user,
557
        'user_dto': user,
558
        'form': form,
559
    }
560
561
562 1
@blueprint.post('/<uuid:user_id>/invalidate_email_address')
563 1
@permission_required(UserPermission.administrate)
564
def invalidate_email_address(user_id):
565
    """Invalidate the email address assigned with the account."""
566
    db_user = _get_db_user_with_details_or_404(user_id)
567
    user = user_service.get_user(db_user.id, include_avatar=True)
568
569
    if not db_user.email_address_verified:
570
        flash_error(gettext('Email address is already invalidated.'))
571
        return redirect_to('.view', user_id=user.id)
572
573
    form = InvalidateEmailAddressForm(request.form)
574
    if not form.validate():
575
        return invalidate_email_address_form(user.id, form)
576
577
    initiator_id = g.user.id
578
    reason = form.reason.data.strip()
579
580
    event = email_address_verification_service.invalidate_email_address(
581
        user.id, reason, initiator_id=initiator_id
582
    )
583
584
    user_signals.email_address_invalidated.send(None, event=event)
585
586
    flash_success(
587
        gettext(
588
            "The email address of user '%(screen_name)s' has been invalidated.",
589
            screen_name=user.screen_name,
590
        )
591
    )
592
593
    return redirect_to('.view', user_id=user.id)
594
595
596
# -------------------------------------------------------------------- #
597
# authentication
598
599
600 1
@blueprint.get('/<uuid:user_id>/password')
601 1
@permission_required(UserPermission.set_password)
602 1
@templated
603 1
def set_password_form(user_id, erroneous_form=None):
604
    """Show a form to set a new password for the user."""
605 1
    db_user = _get_db_user_with_details_or_404(user_id)
606 1
    user = user_service.get_user(db_user.id, include_avatar=True)
607
608 1
    form = erroneous_form if erroneous_form else SetPasswordForm()
609
610 1
    return {
611
        'user': db_user,
612
        'user_dto': user,
613
        'form': form,
614
    }
615
616
617 1
@blueprint.post('/<uuid:user_id>/password')
618 1
@permission_required(UserPermission.set_password)
619
def set_password(user_id):
620
    """Set a new password for the user."""
621
    user = _get_user_or_404(user_id)
622
623
    form = SetPasswordForm(request.form)
624
    if not form.validate():
625
        return set_password_form(user.id, form)
626
627
    new_password = form.password.data
628
    initiator_id = g.user.id
629
630
    password_service.update_password_hash(user.id, new_password, initiator_id)
631
632
    flash_success(
633
        gettext(
634
            "New password has been set for user '%(screen_name)s'.",
635
            screen_name=user.screen_name,
636
        )
637
    )
638
639
    return redirect_to('.view', user_id=user.id)
640
641
642
# -------------------------------------------------------------------- #
643
# authorization
644
645
646 1
@blueprint.get('/<uuid:user_id>/permissions')
647 1
@permission_required(UserPermission.view)
648 1
@templated
649
def view_permissions(user_id):
650
    """Show user's permissions."""
651 1
    db_user = _get_db_user_with_details_or_404(user_id)
652 1
    user = user_service.get_user(db_user.id, include_avatar=True)
653
654 1
    permissions_by_role = (
655
        authorization_service.get_permissions_by_roles_for_user_with_titles(
656
            user.id
657
        )
658
    )
659
660 1
    return {
661
        'user': db_user,
662
        'user_dto': user,
663
        'permissions_by_role': permissions_by_role,
664
    }
665
666
667 1
@blueprint.get('/<uuid:user_id>/roles/assignment')
668 1
@permission_required(RolePermission.assign)
669 1
@templated
670
def manage_roles(user_id):
671
    """Manage what roles are assigned to the user."""
672 1
    db_user = _get_db_user_with_details_or_404(user_id)
673 1
    user = user_service.get_user(db_user.id, include_avatar=True)
674
675 1
    permissions_by_role = (
676
        authorization_service.get_permissions_by_roles_with_titles()
677
    )
678
679 1
    user_role_ids = authorization_service.find_role_ids_for_user(user.id)
680
681 1
    return {
682
        'user': db_user,
683
        'user_dto': user,
684
        'permissions_by_role': permissions_by_role,
685
        'user_role_ids': user_role_ids,
686
    }
687
688
689 1
@blueprint.post('/<uuid:user_id>/roles/<role_id>')
690 1
@permission_required(RolePermission.assign)
691 1
@respond_no_content
692
def role_assign(user_id, role_id):
693
    """Assign the role to the user."""
694
    user = _get_user_or_404(user_id)
695
    role = _get_role_or_404(role_id)
696
    initiator_id = g.user.id
697
698
    authorization_service.assign_role_to_user(
699
        role.id, user.id, initiator_id=initiator_id
700
    )
701
702
    flash_success(
703
        gettext(
704
            '%(role_title)s has been assigned to "%(screen_name)s".',
705
            screen_name=user.screen_name,
706
            role_title=role.title,
707
        )
708
    )
709
710
711 1
@blueprint.delete('/<uuid:user_id>/roles/<role_id>')
712 1
@permission_required(RolePermission.assign)
713 1
@respond_no_content
714
def role_deassign(user_id, role_id):
715
    """Deassign the role from the user."""
716
    user = _get_user_or_404(user_id)
717
    role = _get_role_or_404(role_id)
718
    initiator_id = g.user.id
719
720
    authorization_service.deassign_role_from_user(
721
        role.id, user.id, initiator_id=initiator_id
722
    )
723
724
    flash_success(
725
        gettext(
726
            '%(role_title)s has been withdrawn from "%(screen_name)s".',
727
            screen_name=user.screen_name,
728
            role_title=role.title,
729
        )
730
    )
731
732
733
# -------------------------------------------------------------------- #
734
# events
735
736
737 1
@blueprint.get('/<uuid:user_id>/events')
738 1
@permission_required(UserPermission.view)
739 1
@templated
740
def view_events(user_id):
741
    """Show user's events."""
742 1
    db_user = _get_db_user_with_details_or_404(user_id)
743 1
    user = user_service.get_user(db_user.id, include_avatar=True)
744
745 1
    events = list(service.get_events(user.id))
746
747 1
    include_logins = request.args.get('include_logins', default='yes') == 'yes'
748 1
    if not include_logins:
749
        events = [
750
            event for event in events if event['event'] != 'user-logged-in'
751
        ]
752
753 1
    return {
754
        'user': db_user,
755
        'user_dto': user,
756
        'events': events,
757
        'logins_included': include_logins,
758
    }
759
760
761
# -------------------------------------------------------------------- #
762
# helpers
763
764
765 1
def _get_db_user_with_details_or_404(user_id):
766 1
    user = user_service.find_user_with_details(user_id)
767
768 1
    if user is None:
769
        abort(404)
770
771 1
    return user
772
773
774 1
def _get_user_or_404(user_id):
775
    user = user_service.find_user(user_id)
776
777
    if user is None:
778
        abort(404)
779
780
    return user
781
782
783 1
def _get_role_or_404(role_id):
784
    role = authorization_service.find_role(role_id)
785
786
    if role is None:
787
        abort(404)
788
789
    return role
790