From 0854439286cc0530de7cc492619aae52d00a3e5a Mon Sep 17 00:00:00 2001 From: rauchy Date: Sat, 2 Mar 2019 23:29:29 +0200 Subject: [PATCH 1/5] return invite link to client if e-mail server is not set up --- redash/handlers/users.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/redash/handlers/users.py b/redash/handlers/users.py index 2d2feab9cb..604d97e3dc 100644 --- a/redash/handlers/users.py +++ b/redash/handlers/users.py @@ -15,6 +15,7 @@ from redash.authentication.account import invite_link_for_user, send_invite_email, send_password_reset_email, send_verify_email from redash.settings import parse_boolean +from redash import settings # Ordering map for relationships @@ -39,6 +40,7 @@ def invite_user(org, inviter, user): invite_url = invite_link_for_user(user) send_invite_email(inviter, user, invite_url, org) + return invite_url class UserListResource(BaseResource): @@ -138,9 +140,15 @@ def post(self): should_send_invitation = 'no_invite' not in request.args if should_send_invitation: - invite_user(self.current_org, self.current_user, user) + invite_url = invite_user(self.current_org, self.current_user, user) + else: + invite_url = invite_link_for_user(user) - return user.to_dict() + d = user.to_dict() + if settings.MAIL_DEFAULT_SENDER is None: + d['invite_link'] = invite_url + + return d class UserInviteResource(BaseResource): From 80a6aee6a4168354f5bf62aa872e4e0e2703d8d6 Mon Sep 17 00:00:00 2001 From: Omer Lachish Date: Sun, 3 Mar 2019 00:19:35 +0200 Subject: [PATCH 2/5] add a couple of tests to make sure invite links are only returned when neccessary --- tests/handlers/test_users.py | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/tests/handlers/test_users.py b/tests/handlers/test_users.py index e00bc55e7b..1541e12e2b 100644 --- a/tests/handlers/test_users.py +++ b/tests/handlers/test_users.py @@ -1,4 +1,4 @@ -from redash import models +from redash import models, settings from tests import BaseTestCase from mock import patch @@ -40,6 +40,34 @@ def test_creates_user(self): self.assertEqual(rv.json['name'], test_user['name']) self.assertEqual(rv.json['email'], test_user['email']) + def test_shows_invite_link_when_email_is_not_configured(self): + previous = settings.MAIL_DEFAULT_SENDER + settings.MAIL_DEFAULT_SENDER = None + + admin = self.factory.create_admin() + + test_user = {'name': 'User', 'email': 'user@example.com'} + rv = self.make_request('post', '/api/users', data=test_user, user=admin) + + self.assertEqual(rv.status_code, 200) + self.assertTrue('invite_link' in rv.json) + + settings.MAIL_DEFAULT_SENDER = previous + + def test_does_not_show_invite_link_when_email_is_configured(self): + previous = settings.MAIL_DEFAULT_SENDER + settings.MAIL_DEFAULT_SENDER = "john@doe.com" + + admin = self.factory.create_admin() + + test_user = {'name': 'User', 'email': 'user@example.com'} + rv = self.make_request('post', '/api/users', data=test_user, user=admin) + + self.assertEqual(rv.status_code, 200) + self.assertFalse('invite_link' in rv.json) + + settings.MAIL_DEFAULT_SENDER = previous + def test_creates_user_case_insensitive_email(self): admin = self.factory.create_admin() From bf5c4c844249a5cc85f06d0fa967c1d4121bd991 Mon Sep 17 00:00:00 2001 From: Omer Lachish Date: Sun, 3 Mar 2019 00:21:24 +0200 Subject: [PATCH 3/5] show invite link when e-mail is not configured --- client/app/pages/users/CreateUser.jsx | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/client/app/pages/users/CreateUser.jsx b/client/app/pages/users/CreateUser.jsx index b05df35b57..18daf0ec86 100644 --- a/client/app/pages/users/CreateUser.jsx +++ b/client/app/pages/users/CreateUser.jsx @@ -37,6 +37,19 @@ class CreateUser extends React.Component { { name: 'email', title: 'Email', type: 'email' }, ].map(field => ({ required: true, readOnly: !!user, ...field })); + const message = ( +
+ The user has been created and should receive an invite email soon. + {user && user.invite_link && ( +
+
+ You can use the following link to invite them yourself: + +
+ )} +
+ ); + return (
@@ -50,7 +63,7 @@ class CreateUser extends React.Component { /> {user && ( From 1317e0976a0e46fb16e71f673d42fe3408dfbfdd Mon Sep 17 00:00:00 2001 From: Omer Lachish Date: Sun, 3 Mar 2019 00:37:31 +0200 Subject: [PATCH 4/5] remove "an e-mail has been sent" when there's no e-mail configured --- client/app/pages/users/CreateUser.jsx | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/client/app/pages/users/CreateUser.jsx b/client/app/pages/users/CreateUser.jsx index 18daf0ec86..2105f9f2a7 100644 --- a/client/app/pages/users/CreateUser.jsx +++ b/client/app/pages/users/CreateUser.jsx @@ -37,18 +37,12 @@ class CreateUser extends React.Component { { name: 'email', title: 'Email', type: 'email' }, ].map(field => ({ required: true, readOnly: !!user, ...field })); - const message = ( + const message = user && user.invite_link ? (
- The user has been created and should receive an invite email soon. - {user && user.invite_link && ( -
-
- You can use the following link to invite them yourself: - -
- )} + The user has been created. You can use the following link to invite them: +
- ); + ) : The user has been created and should receive an invite email soon.; return (
From 2239b72ba9c9a5770a9d90e2c0e920eb0d9fc55a Mon Sep 17 00:00:00 2001 From: Omer Lachish Date: Sun, 3 Mar 2019 09:17:46 +0200 Subject: [PATCH 5/5] return invite_url in re-invites as well. Also refactor to reuse the code. --- redash/handlers/users.py | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/redash/handlers/users.py b/redash/handlers/users.py index 604d97e3dc..cabbe39dc5 100644 --- a/redash/handlers/users.py +++ b/redash/handlers/users.py @@ -37,10 +37,17 @@ ) -def invite_user(org, inviter, user): +def invite_user(org, inviter, user, send_email=True): + email_configured = settings.MAIL_DEFAULT_SENDER is not None + d = user.to_dict() + invite_url = invite_link_for_user(user) - send_invite_email(inviter, user, invite_url, org) - return invite_url + if email_configured and send_email: + send_invite_email(inviter, user, invite_url, org) + else: + d['invite_link'] = invite_url + + return d class UserListResource(BaseResource): @@ -139,25 +146,14 @@ def post(self): }) should_send_invitation = 'no_invite' not in request.args - if should_send_invitation: - invite_url = invite_user(self.current_org, self.current_user, user) - else: - invite_url = invite_link_for_user(user) - - d = user.to_dict() - if settings.MAIL_DEFAULT_SENDER is None: - d['invite_link'] = invite_url - - return d + return invite_user(self.current_org, self.current_user, user, send_email=should_send_invitation) class UserInviteResource(BaseResource): @require_admin def post(self, user_id): user = models.User.get_by_id_and_org(user_id, self.current_org) - invite_url = invite_user(self.current_org, self.current_user, user) - - return user.to_dict() + return invite_user(self.current_org, self.current_user, user) class UserResetPasswordResource(BaseResource):