Browse Source

Merge pull request #10 from tracim/fix/611_reenable_email_new_user_notification_with_password

Bastien Sevajol 6 years ago
parent
commit
1e73e4afc0
No account linked to committer's email

+ 67 - 0
backend/tests_configs.ini View File

@@ -63,3 +63,70 @@ email.notification.smtp.server = 127.0.0.1
63 63
 email.notification.smtp.port = 1025
64 64
 email.notification.smtp.user = test_user
65 65
 email.notification.smtp.password = just_a_password
66
+
67
+[functional_test]
68
+sqlalchemy.url = sqlite:///tracim_test.sqlite
69
+depot_storage_name = test
70
+depot_storage_dir = /tmp/test/depot
71
+user.auth_token.validity = 604800
72
+preview_cache_dir = /tmp/test/preview_cache
73
+preview.jpg.restricted_dims = True
74
+email.notification.activated = false
75
+
76
+[functional_test_no_db]
77
+sqlalchemy.url = sqlite://
78
+depot_storage_name = test
79
+depot_storage_dir = /tmp/test/depot
80
+user.auth_token.validity = 604800
81
+preview_cache_dir = /tmp/test/preview_cache
82
+preview.jpg.restricted_dims = True
83
+email.notification.activated = false
84
+
85
+[functional_test_with_mail_test_sync]
86
+sqlalchemy.url = sqlite:///tracim_test.sqlite
87
+depot_storage_name = test
88
+depot_storage_dir = /tmp/test/depot
89
+user.auth_token.validity = 604800
90
+preview_cache_dir = /tmp/test/preview_cache
91
+preview.jpg.restricted_dims = True
92
+email.notification.activated = true
93
+email.notification.from.email = test_user_from+{user_id}@localhost
94
+email.notification.from.default_label = Tracim Notifications
95
+email.notification.reply_to.email = test_user_reply+{content_id}@localhost
96
+email.notification.references.email = test_user_refs+{content_id}@localhost
97
+email.notification.content_update.template.html = %(here)s/tracim_backend/templates/mail/content_update_body_html.mak
98
+email.notification.content_update.template.text = %(here)s/tracim_backend/templates/mail/content_update_body_text.mak
99
+email.notification.created_account.template.html = %(here)s/tracim_backend/templates/mail/created_account_body_html.mak
100
+email.notification.created_account.template.text = %(here)s/tracim_backend/templates/mail/created_account_body_text.mak
101
+email.notification.content_update.subject = [{website_title}] [{workspace_label}] {content_label} ({content_status_label})
102
+email.notification.created_account.subject = [{website_title}] Created account
103
+email.notification.processing_mode = sync
104
+email.notification.smtp.server = 127.0.0.1
105
+email.notification.smtp.port = 1025
106
+email.notification.smtp.user = test_user
107
+email.notification.smtp.password = just_a_password
108
+
109
+
110
+[functional_test_with_mail_test_async]
111
+sqlalchemy.url = sqlite:///tracim_test.sqlite
112
+depot_storage_name = test
113
+depot_storage_dir = /tmp/test/depot
114
+user.auth_token.validity = 604800
115
+preview_cache_dir = /tmp/test/preview_cache
116
+preview.jpg.restricted_dims = True
117
+email.notification.activated = true
118
+email.notification.from.email = test_user_from+{user_id}@localhost
119
+email.notification.from.default_label = Tracim Notifications
120
+email.notification.reply_to.email = test_user_reply+{content_id}@localhost
121
+email.notification.references.email = test_user_refs+{content_id}@localhost
122
+email.notification.content_update.template.html = %(here)s/tracim_backend/templates/mail/content_update_body_html.mak
123
+email.notification.content_update.template.text = %(here)s/tracim_backend/templates/mail/content_update_body_text.mak
124
+email.notification.created_account.template.html = %(here)s/tracim_backend/templates/mail/created_account_body_html.mak
125
+email.notification.created_account.template.text = %(here)s/tracim_backend/templates/mail/created_account_body_text.mak
126
+email.notification.content_update.subject = [{website_title}] [{workspace_label}] {content_label} ({content_status_label})
127
+email.notification.created_account.subject = [{website_title}] Created account
128
+email.notification.processing_mode = async
129
+email.notification.smtp.server = 127.0.0.1
130
+email.notification.smtp.port = 1025
131
+email.notification.smtp.user = test_user
132
+email.notification.smtp.password = just_a_password

+ 3 - 1
backend/tracim_backend/config.py View File

@@ -161,9 +161,11 @@ class CFG(object):
161 161
 
162 162
         self.EMAIL_NOTIFICATION_FROM_EMAIL = settings.get(
163 163
             'email.notification.from.email',
164
+            'noreply+{user_id}@trac.im'
164 165
         )
165 166
         self.EMAIL_NOTIFICATION_FROM_DEFAULT_LABEL = settings.get(
166
-            'email.notification.from.default_label'
167
+            'email.notification.from.default_label',
168
+            'Tracim Notifications'
167 169
         )
168 170
         self.EMAIL_NOTIFICATION_REPLY_TO_EMAIL = settings.get(
169 171
             'email.notification.reply_to.email',

+ 24 - 0
backend/tracim_backend/lib/utils/utils.py View File

@@ -1,5 +1,7 @@
1 1
 # -*- coding: utf-8 -*-
2 2
 import datetime
3
+import random
4
+import string
3 5
 from redis import Redis
4 6
 from rq import Queue
5 7
 
@@ -72,3 +74,25 @@ def current_date_for_filename() -> str:
72 74
     # webdav utils, it may cause trouble. So, it should be replaced to
73 75
     # a character which will not change in bdd.
74 76
     return datetime.datetime.now().isoformat().replace(':', '.')
77
+
78
+# INFO - G.M - 2018-08-02 - Simple password generator, inspired by
79
+# https://gist.github.com/23maverick23/4131896
80
+
81
+
82
+ALLOWED_AUTOGEN_PASSWORD_CHAR = string.ascii_letters + \
83
+                                string.digits + \
84
+                                string.punctuation
85
+
86
+DEFAULT_PASSWORD_GEN_CHAR_LENGTH = 12
87
+
88
+
89
+def password_generator(
90
+        length: int=DEFAULT_PASSWORD_GEN_CHAR_LENGTH,
91
+        chars: str=ALLOWED_AUTOGEN_PASSWORD_CHAR
92
+) -> str:
93
+    """
94
+    :param length: length of the new password
95
+    :param chars: characters allowed
96
+    :return: password as string
97
+    """
98
+    return ''.join(random.choice(chars) for char_number in range(length))

+ 8 - 11
backend/tracim_backend/tests/__init__.py View File

@@ -68,20 +68,17 @@ def create_1000px_png_test_image():
68 68
 class FunctionalTest(unittest.TestCase):
69 69
 
70 70
     fixtures = [BaseFixture]
71
-    sqlalchemy_url = 'sqlite:///tracim_test.sqlite'
71
+    config_uri = 'tests_configs.ini'
72
+    config_section = 'functional_test'
72 73
 
73 74
     def setUp(self):
74 75
         logger._logger.setLevel('WARNING')
76
+
75 77
         DepotManager._clear()
76
-        self.settings = {
77
-            'sqlalchemy.url': self.sqlalchemy_url,
78
-            'user.auth_token.validity': '604800',
79
-            'depot_storage_dir': '/tmp/test/depot',
80
-            'depot_storage_name': 'test',
81
-            'preview_cache_dir': '/tmp/test/preview_cache',
82
-            'preview.jpg.restricted_dims': True,
83
-            'email.notification.activated': 'false',
84
-        }
78
+        self.settings = plaster.get_settings(
79
+            self.config_uri,
80
+            self.config_section
81
+        )
85 82
         hapic.reset_context()
86 83
         self.engine = get_engine(self.settings)
87 84
         DeclarativeBase.metadata.create_all(self.engine)
@@ -127,7 +124,7 @@ class FunctionalTestEmptyDB(FunctionalTest):
127 124
 
128 125
 
129 126
 class FunctionalTestNoDB(FunctionalTest):
130
-    sqlalchemy_url = 'sqlite://'
127
+    config_section = 'functional_test_no_db'
131 128
 
132 129
     def init_database(self, settings):
133 130
         self.engine = get_engine(settings)

+ 84 - 1
backend/tracim_backend/tests/functional/test_workspaces.py View File

@@ -2,7 +2,7 @@
2 2
 """
3 3
 Tests for /api/v2/workspaces subpath endpoints.
4 4
 """
5
-
5
+import requests
6 6
 import transaction
7 7
 from depot.io.utils import FileIntent
8 8
 
@@ -600,6 +600,89 @@ class TestWorkspaceMembersEndpoint(FunctionalTest):
600 600
         assert user_role['workspace_id'] == 1
601 601
 
602 602
 
603
+class TestUserInvitationWithMailActivatedSync(FunctionalTest):
604
+
605
+    fixtures = [BaseFixture, ContentFixtures]
606
+    config_section = 'functional_test_with_mail_test_sync'
607
+
608
+    def test_api__create_workspace_member_role__ok_200__new_user(self):  # nopep8
609
+        """
610
+        Create workspace member role
611
+        :return:
612
+        """
613
+        requests.delete('http://127.0.0.1:8025/api/v1/messages')
614
+        self.testapp.authorization = (
615
+            'Basic',
616
+            (
617
+                'admin@admin.admin',
618
+                'admin@admin.admin'
619
+            )
620
+        )
621
+        # create workspace role
622
+        params = {
623
+            'user_id': None,
624
+            'user_email_or_public_name': 'bob@bob.bob',
625
+            'role': 'content-manager',
626
+        }
627
+        res = self.testapp.post_json(
628
+            '/api/v2/workspaces/1/members',
629
+            status=200,
630
+            params=params,
631
+        )
632
+        user_role_found = res.json_body
633
+        assert user_role_found['role'] == 'content-manager'
634
+        assert user_role_found['user_id']
635
+        user_id = user_role_found['user_id']
636
+        assert user_role_found['workspace_id'] == 1
637
+        assert user_role_found['newly_created'] is True
638
+        assert user_role_found['email_sent'] is True
639
+
640
+        # check mail received
641
+        response = requests.get('http://127.0.0.1:8025/api/v1/messages')
642
+        response = response.json()
643
+        assert len(response) == 1
644
+        headers = response[0]['Content']['Headers']
645
+        assert headers['From'][0] == 'Tracim Notifications <test_user_from+0@localhost>'  # nopep8
646
+        assert headers['To'][0] == 'bob <bob@bob.bob>'
647
+        assert headers['Subject'][0] == '[TRACIM] Created account'
648
+
649
+        # TODO - G.M - 2018-08-02 - Place cleanup outside of the test
650
+        requests.delete('http://127.0.0.1:8025/api/v1/messages')
651
+
652
+
653
+class TestUserInvitationWithMailActivatedASync(FunctionalTest):
654
+
655
+    fixtures = [BaseFixture, ContentFixtures]
656
+    config_section = 'functional_test_with_mail_test_async'
657
+
658
+    def test_api__create_workspace_member_role__ok_200__new_user(self):  # nopep8
659
+        """
660
+        Create workspace member role
661
+        :return:
662
+        """
663
+        self.testapp.authorization = (
664
+            'Basic',
665
+            (
666
+                'admin@admin.admin',
667
+                'admin@admin.admin'
668
+            )
669
+        )
670
+        # create workspace role
671
+        params = {
672
+            'user_id': None,
673
+            'user_email_or_public_name': 'bob@bob.bob',
674
+            'role': 'content-manager',
675
+        }
676
+        res = self.testapp.post_json(
677
+            '/api/v2/workspaces/1/members',
678
+            status=200,
679
+            params=params,
680
+        )
681
+        user_role_found = res.json_body
682
+        assert user_role_found['newly_created'] is True
683
+        assert user_role_found['email_sent'] is False
684
+
685
+
603 686
 class TestWorkspaceContents(FunctionalTest):
604 687
     """
605 688
     Tests for /api/v2/workspaces/{workspace_id}/contents endpoint

+ 14 - 0
backend/tracim_backend/tests/library/tests_utils.py View File

@@ -0,0 +1,14 @@
1
+import string
2
+
3
+from tracim_backend.lib.utils.utils import password_generator
4
+from tracim_backend.lib.utils.utils import ALLOWED_AUTOGEN_PASSWORD_CHAR
5
+from tracim_backend.lib.utils.utils import DEFAULT_PASSWORD_GEN_CHAR_LENGTH
6
+
7
+
8
+class TestPasswordGenerator(object):
9
+
10
+    def test_password_generator_ok_nominal_case(self):
11
+        password = password_generator()
12
+        assert len(password) == DEFAULT_PASSWORD_GEN_CHAR_LENGTH
13
+        for char in password:
14
+            assert char in ALLOWED_AUTOGEN_PASSWORD_CHAR

+ 9 - 2
backend/tracim_backend/views/core_api/workspace_controller.py View File

@@ -31,6 +31,7 @@ from tracim_backend.exceptions import ContentNotFound
31 31
 from tracim_backend.exceptions import WorkspacesDoNotMatch
32 32
 from tracim_backend.exceptions import ParentNotFound
33 33
 from tracim_backend.views.controllers import Controller
34
+from tracim_backend.lib.utils.utils import password_generator
34 35
 from tracim_backend.views.core_api.schemas import FilterContentQuerySchema
35 36
 from tracim_backend.views.core_api.schemas import WorkspaceMemberCreationSchema
36 37
 from tracim_backend.views.core_api.schemas import WorkspaceMemberInviteSchema
@@ -213,12 +214,18 @@ class WorkspaceController(Controller):
213 214
                 # TODO - G.M - 2018-07-05 - [UserCreation] Reenable email
214 215
                 # notification for creation
215 216
                 user = uapi.create_user(
216
-                    hapic_data.body.user_email_or_public_name,
217
-                    do_notify=False
217
+                    email=hapic_data.body.user_email_or_public_name,
218
+                    password= password_generator(),
219
+                    do_notify=True
218 220
                 )  # nopep8
219 221
                 newly_created = True
222
+                if app_config.EMAIL_NOTIFICATION_ACTIVATED and \
223
+                        app_config.EMAIL_NOTIFICATION_PROCESSING_MODE.lower() == 'sync':
224
+                    email_sent = True
225
+
220 226
             except EmailValidationFailed:
221 227
                 raise UserCreationFailed('no valid mail given')
228
+
222 229
         role = rapi.create_one(
223 230
             user=user,
224 231
             workspace=request.current_workspace,