Completed
Push — main ( 79af2c...5d8ea8 )
by Jochen
03:35
created

terms_consent_subject_id()   A

Complexity

Conditions 1

Size

Total Lines 34
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 21
nop 2
dl 0
loc 34
rs 9.376
c 0
b 0
f 0
1
"""
2
:Copyright: 2006-2020 Jochen Kupperschmidt
3
:License: Modified BSD, see LICENSE for details.
4
"""
5
6
from unittest.mock import patch
7
8
import pytest
9
10
from byceps.services.authentication.password.models import Credential
11
from byceps.services.authentication.session import service as session_service
12
from byceps.services.authorization import service as authorization_service
13
from byceps.services.brand import settings_service as brand_settings_service
14
from byceps.services.consent import (
15
    consent_service,
16
    subject_service as consent_subject_service,
17
)
18
from byceps.services.newsletter import (
19
    command_service as newsletter_command_service,
20
    service as newsletter_service,
21
)
22
from byceps.services.snippet import service as snippet_service
23
from byceps.services.snippet.transfer.models import Scope
24
from byceps.services.terms import document_service as terms_document_service
25
from byceps.services.terms import version_service as terms_version_service
26
from byceps.services.user import event_service, service as user_service
27
from byceps.services.user.models.user import User
28
from byceps.services.verification_token.models import (
29
    Purpose as TokenPurpose,
30
    Token,
31
)
32
33
from tests.helpers import http_client
34
35
36
@pytest.fixture(scope='module')
37
def user_admin(make_user):
38
    return make_user('UserAdmin')
39
40
41
@pytest.fixture(scope='module')
42
def terms_consent_subject_id(user_admin, brand):
43
    scope = Scope.for_brand(brand.id)
44
45
    snippet, _ = snippet_service.create_fragment(
46
        scope, 'terms_of_service', user_admin.id, 'Don\'t do anything stupid!'
47
    )
48
49
    consent_subject = consent_subject_service.create_subject(
50
        f'{brand.id}_terms-of-service_v1',
51
        f'Terms of service for {brand.title} / v1',
52
        'Ich akzeptiere die <a href="{url}" target="_blank">Allgemeinen Geschäftsbedingungen</a>.',
53
        '/terms/',
54
    )
55
56
    terms_document_id = brand.id
57
    terms_document = terms_document_service.create_document(
58
        terms_document_id, terms_document_id
59
    )
60
61
    terms_version = terms_version_service.create_version(
62
        terms_document.id, '01-Jan-2016', snippet.id, consent_subject.id
63
    )
64
65
    consent_subject_id = terms_version.consent_subject_id
66
67
    consent_subject_service.create_brand_requirement(
68
        brand.id, consent_subject_id
69
    )
70
71
    yield consent_subject_id
72
73
    consent_subject_service.delete_brand_requirement(
74
        brand.id, consent_subject_id
75
    )
76
77
78
@pytest.fixture(scope='module')
79
def privacy_policy_consent_subject_id(brand):
80
    consent_subject = consent_subject_service.create_subject(
81
        f'{brand.id}_privacy_policy_v1',
82
        f'Privacy policy for {brand.title} / v1',
83
        'Ich akzeptiere die <a href="{url}" target="_blank">Datenschutzbestimmungen</a>.',
84
        '/privacy',
85
    )
86
87
    consent_subject_service.create_brand_requirement(
88
        brand.id, consent_subject.id
89
    )
90
91
    yield consent_subject.id
92
93
    consent_subject_service.delete_brand_requirement(
94
        brand.id, consent_subject.id
95
    )
96
97
98
@pytest.fixture(scope='module')
99
def newsletter_list(brand):
100
    list_ = newsletter_command_service.create_list(brand.id, brand.title)
101
102
    brand_settings_service.create_setting(
103
        brand.id, 'newsletter_list_id', str(list_.id)
104
    )
105
106
107
@patch('byceps.email.send')
108
def test_create(
109
    send_email_mock,
110
    site_app,
111
    brand,
112
    site,
113
    terms_consent_subject_id,
114
    privacy_policy_consent_subject_id,
115
    newsletter_list,
116
):
117
    screen_name = 'Hiro'
118
119
    user_count_before = get_user_count()
120
    assert find_user(screen_name) is None
121
122
    form_data = {
123
        'screen_name': screen_name,
124
        'first_names': 'Hiroaki',
125
        'last_name': 'Protagonist',
126
        'email_address': '[email protected]',
127
        'password': 'Snow_Crash',
128
        f'consent_to_subject_{terms_consent_subject_id.hex}': 'y',
129
        f'consent_to_subject_{privacy_policy_consent_subject_id.hex}': 'y',
130
        'subscribe_to_newsletter': 'y',
131
    }
132
133
    response = send_request(site_app, form_data)
134
    assert response.status_code == 302
135
136
    user_count_afterwards = get_user_count()
137
    assert user_count_afterwards == user_count_before + 1
138
139
    user = find_user(screen_name)
140
    assert user is not None
141
142
    assert user.created_at is not None
143
    assert user.screen_name == 'Hiro'
144
    assert user.email_address == '[email protected]'
145
    assert not user.initialized
146
    assert not user.deleted
147
148
    # events
149
    assert_creation_event_created(user.id)
150
151
    # password
152
    assert_password_credentials_created(user.id)
153
154
    # Session token should not have been created at this point.
155
    session_token = session_service.find_session_token_for_user(user.id)
156
    assert session_token is None
157
158
    # avatar
159
    assert user.avatar is None
160
161
    # details
162
    assert user.detail.first_names == 'Hiroaki'
163
    assert user.detail.last_name == 'Protagonist'
164
165
    # authorization
166
    role_ids = authorization_service.find_role_ids_for_user(user.id)
167
    assert role_ids == set()
168
169
    # consents
170
    assert_consent(user.id, terms_consent_subject_id)
171
    assert_consent(user.id, privacy_policy_consent_subject_id)
172
173
    # newsletter subscription
174
    assert is_subscribed_to_newsletter(user.id, brand.id)
175
176
    # confirmation e-mail
177
178
    verification_token = find_verification_token(user.id)
179
    assert verification_token is not None
180
181
    expected_sender = '[email protected]'
182
    expected_recipients = ['[email protected]']
183
    expected_subject = 'Hiro, bitte bestätige deine E-Mail-Adresse'
184
    expected_body = f'''
185
Hallo Hiro,
186
187
bitte bestätige deine E-Mail-Adresse, indem du diese URL abrufst: https://www.acmecon.test/users/email_address/confirmation/{verification_token.token}
188
    '''.strip()
189
190
    send_email_mock.assert_called_once_with(
191
        expected_sender, expected_recipients, expected_subject, expected_body
192
    )
193
194
195
@patch('byceps.email.send')
196
def test_create_without_newsletter_subscription(
197
    send_email_mock,
198
    site_app,
199
    brand,
200
    site,
201
    terms_consent_subject_id,
202
    privacy_policy_consent_subject_id,
203
    newsletter_list,
204
):
205
    screen_name = 'Hiro2'
206
207
    form_data = {
208
        'screen_name': screen_name,
209
        'first_names': 'Hiroaki',
210
        'last_name': 'Protagonist',
211
        'email_address': '[email protected]',
212
        'password': 'Snow_Crash',
213
        f'consent_to_subject_{terms_consent_subject_id.hex}': 'y',
214
        f'consent_to_subject_{privacy_policy_consent_subject_id.hex}': 'y',
215
        'subscribe_to_newsletter': '',
216
    }
217
218
    response = send_request(site_app, form_data)
219
    assert response.status_code == 302
220
221
    user = find_user(screen_name)
222
    assert user is not None
223
224
    # newsletter subscription
225
    assert not is_subscribed_to_newsletter(user.id, brand.id)
226
227
228
# helpers
229
230
231
def send_request(app, form_data):
232
    url = '/users/'
233
234
    with http_client(app) as client:
235
        return client.post(url, data=form_data)
236
237
238
def find_user(screen_name):
239
    return user_service.find_user_by_screen_name(screen_name)
240
241
242
def get_user_count():
243
    return User.query.count()
244
245
246
def find_verification_token(user_id):
247
    return Token.query \
248
        .filter_by(user_id=user_id) \
249
        .for_purpose(TokenPurpose.email_address_confirmation) \
250
        .first()
251
252
253
def is_subscribed_to_newsletter(user_id, brand_id):
254
    return newsletter_service.is_subscribed(user_id, brand_id)
255
256
257
def assert_creation_event_created(user_id):
258
    events = event_service.get_events_of_type_for_user('user-created', user_id)
259
    assert len(events) == 1
260
261
    first_event = events[0]
262
    assert first_event.event_type == 'user-created'
263
    assert first_event.data == {}
264
265
266
def assert_password_credentials_created(user_id):
267
    credential = Credential.query.get(user_id)
268
269
    assert credential is not None
270
    assert credential.password_hash.startswith('pbkdf2:sha256:150000$')
271
    assert credential.updated_at is not None
272
273
274
def assert_consent(user_id, subject_id):
275
    assert consent_service.has_user_consented_to_subject(user_id, subject_id)
276