From 685ddeff0038d463959763e85f2f5d017e4781fe Mon Sep 17 00:00:00 2001 From: Maarten de Waard Date: Thu, 21 Jul 2022 10:47:08 +0200 Subject: [PATCH 1/2] send out a recovery email after a new user is created. --- areas/users/user_service.py | 37 ++++++++++++++++++++++++++++++++++++- web/static/base.js | 7 ------- 2 files changed, 36 insertions(+), 8 deletions(-) diff --git a/areas/users/user_service.py b/areas/users/user_service.py index cfec282..bd59f27 100644 --- a/areas/users/user_service.py +++ b/areas/users/user_service.py @@ -1,8 +1,17 @@ +import ory_kratos_client +from ory_kratos_client.model.submit_self_service_recovery_flow_body \ + import SubmitSelfServiceRecoveryFlowBody +from ory_kratos_client.api import v0alpha2_api as kratos_api +from config import KRATOS_ADMIN_URL + from database import db from areas.apps.models import App, AppRole from areas.roles.role_service import RoleService from helpers import KratosApi +tmp = ory_kratos_client.Configuration(host=KRATOS_ADMIN_URL, discard_unknown_keys=True) +KRATOS_ADMIN = kratos_api.V0alpha2Api(ory_kratos_client.ApiClient(tmp)) + class UserService: @staticmethod def get_users(): @@ -22,7 +31,10 @@ class UserService: def post_user(data): kratos_data = { "schema_id": "default", - "traits": {"email": data["email"], "name": data["name"]}, + "traits": { + "name": data["name"], + "email": data["email"], + }, } res = KratosApi.post("/admin/identities", kratos_data).json() @@ -39,8 +51,31 @@ class UserService: db.session.add(app_role) db.session.commit() + UserService.__start_user_recovery_flow(data["email"]) + return UserService.get_user(res["id"]) + + @staticmethod + def __start_user_recovery_flow(email): + """ + Start a Kratos recovery flow for the user's email address. + + This sends out an email to the user that explains to them how they can + set their password. + + :param email: Email to send recovery link to + :type email: str + """ + api_response = KRATOS_ADMIN.initialize_self_service_recovery_flow_without_browser() + flow = api_response['id'] + # Submit the recovery flow to send an email to the new user. + submit_self_service_recovery_flow_body = \ + SubmitSelfServiceRecoveryFlowBody(method="link", email=email) + api_response = KRATOS_ADMIN.submit_self_service_recovery_flow(flow, + submit_self_service_recovery_flow_body= + submit_self_service_recovery_flow_body) + @staticmethod def put_user(id, user_editing_id, data): kratos_data = { diff --git a/web/static/base.js b/web/static/base.js index 6d94cea..4424760 100644 --- a/web/static/base.js +++ b/web/static/base.js @@ -1,5 +1,3 @@ - - /* base.js This is the base JS file to render the user interfaces of kratos and provide the end user with flows for login, recovery etc. @@ -433,8 +431,3 @@ $.urlParam = function(name) { } return decodeURI(results[1]) || 0; }; - - - - - From cc7fc5ab91a9a1a56d5ba8092c8e47420bfe47b8 Mon Sep 17 00:00:00 2001 From: Maarten de Waard Date: Thu, 21 Jul 2022 16:53:08 +0200 Subject: [PATCH 2/2] replace tmp variable name, doc improvements --- areas/users/user_service.py | 13 ++++++++----- cliapp/cliapp/cli.py | 12 ++++++++---- web/login/login.py | 12 ++++++++---- 3 files changed, 24 insertions(+), 13 deletions(-) diff --git a/areas/users/user_service.py b/areas/users/user_service.py index bd59f27..3b7fa68 100644 --- a/areas/users/user_service.py +++ b/areas/users/user_service.py @@ -9,8 +9,10 @@ from areas.apps.models import App, AppRole from areas.roles.role_service import RoleService from helpers import KratosApi -tmp = ory_kratos_client.Configuration(host=KRATOS_ADMIN_URL, discard_unknown_keys=True) -KRATOS_ADMIN = kratos_api.V0alpha2Api(ory_kratos_client.ApiClient(tmp)) +kratos_admin_api_configuration = \ + ory_kratos_client.Configuration(host=KRATOS_ADMIN_URL, discard_unknown_keys=True) +KRATOS_ADMIN = \ + kratos_api.V0alpha2Api(ory_kratos_client.ApiClient(kratos_admin_api_configuration)) class UserService: @staticmethod @@ -51,18 +53,19 @@ class UserService: db.session.add(app_role) db.session.commit() - UserService.__start_user_recovery_flow(data["email"]) + UserService.__start_recovery_flow(data["email"]) return UserService.get_user(res["id"]) @staticmethod - def __start_user_recovery_flow(email): + def __start_recovery_flow(email): """ Start a Kratos recovery flow for the user's email address. This sends out an email to the user that explains to them how they can - set their password. + set their password. Make sure the user exists inside Kratos before you + use this function. :param email: Email to send recovery link to :type email: str diff --git a/cliapp/cliapp/cli.py b/cliapp/cliapp/cli.py index 06e6fb0..6735cb2 100644 --- a/cliapp/cliapp/cli.py +++ b/cliapp/cliapp/cli.py @@ -27,11 +27,15 @@ HYDRA = hydra_client.HydraAdmin(HYDRA_ADMIN_URL) # Kratos has an admin and public end-point. We create an API for them # both. The kratos implementation has bugs, which forces us to set # the discard_unknown_keys to True. -tmp = ory_kratos_client.Configuration(host=KRATOS_ADMIN_URL, discard_unknown_keys=True) -KRATOS_ADMIN = kratos_api.V0alpha2Api(ory_kratos_client.ApiClient(tmp)) +kratos_admin_api_configuration = \ + ory_kratos_client.Configuration(host=KRATOS_ADMIN_URL, discard_unknown_keys=True) +KRATOS_ADMIN = \ + kratos_api.V0alpha2Api(ory_kratos_client.ApiClient(kratos_admin_api_configuration)) -tmp = ory_kratos_client.Configuration(host=KRATOS_PUBLIC_URL, discard_unknown_keys=True) -KRATOS_PUBLIC = kratos_api.V0alpha2Api(ory_kratos_client.ApiClient(tmp)) +kratos_public_api_configuration = \ + ory_kratos_client.Configuration(host=KRATOS_PUBLIC_URL, discard_unknown_keys=True) +KRATOS_PUBLIC = \ + kratos_api.V0alpha2Api(ory_kratos_client.ApiClient(kratos_public_api_configuration)) ############################################################################## # CLI INTERFACE # diff --git a/web/login/login.py b/web/login/login.py index 00cf3af..591acc2 100644 --- a/web/login/login.py +++ b/web/login/login.py @@ -31,11 +31,15 @@ HYDRA = hydra_client.HydraAdmin(HYDRA_ADMIN_URL) # Kratos has an admin and public end-point. We create an API for them # both. The kratos implementation has bugs, which forces us to set # the discard_unknown_keys to True. -tmp = ory_kratos_client.Configuration(host=KRATOS_ADMIN_URL, discard_unknown_keys=True) -KRATOS_ADMIN = kratos_api.V0alpha2Api(ory_kratos_client.ApiClient(tmp)) +kratos_admin_api_configuration = \ + ory_kratos_client.Configuration(host=KRATOS_ADMIN_URL, discard_unknown_keys=True) +KRATOS_ADMIN = \ + kratos_api.V0alpha2Api(ory_kratos_client.ApiClient(kratos_admin_api_configuration)) -tmp = ory_kratos_client.Configuration(host=KRATOS_PUBLIC_URL, discard_unknown_keys=True) -KRATOS_PUBLIC = kratos_api.V0alpha2Api(ory_kratos_client.ApiClient(tmp)) +kratos_public_api_configuration = \ + ory_kratos_client.Configuration(host=KRATOS_PUBLIC_URL, discard_unknown_keys=True) +KRATOS_PUBLIC = \ + kratos_api.V0alpha2Api(ory_kratos_client.ApiClient(kratos_public_api_configuration)) ADMIN_ROLE_ID = 1 NO_ACCESS_ROLE_ID = 3