phcdevworks_accounts_stytch 0.1.0.pre.1 → 0.2.0.pre.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +43 -4
- data/app/controllers/concerns/error_handler.rb +19 -0
- data/app/controllers/concerns/handle_service_action.rb +17 -0
- data/app/controllers/concerns/organization_setter.rb +11 -0
- data/app/controllers/phcdevworks_accounts_stytch/b2b/authenticate_controller.rb +81 -0
- data/app/controllers/phcdevworks_accounts_stytch/b2b/magic_links_controller.rb +57 -0
- data/app/controllers/phcdevworks_accounts_stytch/b2b/passwords_controller.rb +95 -0
- data/app/controllers/phcdevworks_accounts_stytch/b2c/authenticate_controller.rb +99 -0
- data/app/controllers/phcdevworks_accounts_stytch/b2c/magic_links_controller.rb +90 -0
- data/app/controllers/phcdevworks_accounts_stytch/b2c/passwords_controller.rb +94 -0
- data/app/views/layouts/phcdevworks_accounts_stytch/application.html.erb +2 -0
- data/app/views/phcdevworks_accounts_stytch/b2b/magic_links/invite.html.erb +12 -0
- data/app/views/phcdevworks_accounts_stytch/b2b/magic_links/login_or_signup.html.erb +12 -0
- data/app/views/phcdevworks_accounts_stytch/b2b/passwords/reset_existing_password.html.erb +22 -0
- data/app/views/phcdevworks_accounts_stytch/b2b/passwords/reset_password.html.erb +17 -0
- data/app/views/phcdevworks_accounts_stytch/b2b/passwords/reset_start.html.erb +12 -0
- data/app/views/phcdevworks_accounts_stytch/b2b/passwords/reset_with_session.html.erb +17 -0
- data/app/views/phcdevworks_accounts_stytch/b2c/magic_links/invite.html.erb +12 -0
- data/app/views/phcdevworks_accounts_stytch/b2c/magic_links/login_or_signup.html.erb +12 -0
- data/app/views/phcdevworks_accounts_stytch/b2c/passwords/reset_existing_password.html.erb +22 -0
- data/app/views/phcdevworks_accounts_stytch/b2c/passwords/reset_password.html.erb +17 -0
- data/app/views/phcdevworks_accounts_stytch/b2c/passwords/reset_start.html.erb +12 -0
- data/app/views/phcdevworks_accounts_stytch/b2c/passwords/reset_with_session.html.erb +17 -0
- data/config/routes/b2b.rb +30 -0
- data/config/routes/b2c.rb +27 -0
- data/config/routes.rb +2 -4
- data/lib/phcdevworks_accounts_stytch/authentication/b2b/magic_link_service.rb +63 -0
- data/lib/phcdevworks_accounts_stytch/authentication/b2b/password_service.rb +80 -0
- data/lib/phcdevworks_accounts_stytch/authentication/b2c/magic_link_service.rb +55 -0
- data/lib/phcdevworks_accounts_stytch/authentication/b2c/password_service.rb +76 -0
- data/lib/phcdevworks_accounts_stytch/engine.rb +6 -0
- data/lib/phcdevworks_accounts_stytch/stytch/client.rb +45 -0
- data/lib/phcdevworks_accounts_stytch/stytch/error.rb +26 -0
- data/lib/phcdevworks_accounts_stytch/stytch/method_options.rb +21 -0
- data/lib/phcdevworks_accounts_stytch/stytch/organization.rb +51 -0
- data/lib/phcdevworks_accounts_stytch/stytch/response.rb +44 -0
- data/lib/phcdevworks_accounts_stytch/stytch/success.rb +19 -0
- data/lib/phcdevworks_accounts_stytch/version.rb +1 -1
- data/lib/phcdevworks_accounts_stytch.rb +3 -4
- metadata +37 -13
- data/app/controllers/phcdevworks_accounts_stytch/authentication/login_controller.rb +0 -26
- data/app/controllers/phcdevworks_accounts_stytch/authentication/processor_controller.rb +0 -36
- data/lib/phcdevworks_accounts_stytch/stytch_client.rb +0 -10
@@ -0,0 +1,22 @@
|
|
1
|
+
<h1>Reset Your Password Using Existing Password</h1>
|
2
|
+
|
3
|
+
<%= form_with url: phcdevworks_accounts_stytch.b2b_process_reset_existing_password_path(organization_slug: params[:organization_slug] || 'example-slug'), method: :post do |form| %>
|
4
|
+
<div>
|
5
|
+
<%= form.label :email, "Email" %>
|
6
|
+
<%= form.email_field :email, required: true %>
|
7
|
+
</div>
|
8
|
+
|
9
|
+
<div>
|
10
|
+
<%= form.label :old_password, "Old Password" %>
|
11
|
+
<%= form.password_field :old_password, required: true %>
|
12
|
+
</div>
|
13
|
+
|
14
|
+
<div>
|
15
|
+
<%= form.label :new_password, "New Password" %>
|
16
|
+
<%= form.password_field :new_password, required: true %>
|
17
|
+
</div>
|
18
|
+
|
19
|
+
<div>
|
20
|
+
<%= form.submit "Reset Password" %>
|
21
|
+
</div>
|
22
|
+
<% end %>
|
@@ -0,0 +1,17 @@
|
|
1
|
+
<h1>Reset Your Password</h1>
|
2
|
+
|
3
|
+
<%= form_with url: phcdevworks_accounts_stytch.b2b_process_password_reset_path(organization_slug: params[:organization_slug]), method: :post do |form| %>
|
4
|
+
<div>
|
5
|
+
<%= form.label :token, "Reset Token" %>
|
6
|
+
<%= form.text_field :token, required: true %>
|
7
|
+
</div>
|
8
|
+
|
9
|
+
<div>
|
10
|
+
<%= form.label :password, "New Password" %>
|
11
|
+
<%= form.password_field :password, required: true %>
|
12
|
+
</div>
|
13
|
+
|
14
|
+
<div>
|
15
|
+
<%= form.submit "Reset Password" %>
|
16
|
+
</div>
|
17
|
+
<% end %>
|
@@ -0,0 +1,12 @@
|
|
1
|
+
<h1>Reset Password</h1>
|
2
|
+
|
3
|
+
<%= form_with url: phcdevworks_accounts_stytch.b2b_process_reset_start_path(organization_slug: params[:organization_slug]), method: :post do |form| %>
|
4
|
+
<div>
|
5
|
+
<%= form.label :email, "Email" %>
|
6
|
+
<%= form.email_field :email, required: true %>
|
7
|
+
</div>
|
8
|
+
|
9
|
+
<div>
|
10
|
+
<%= form.submit "Send Reset Instructions" %>
|
11
|
+
</div>
|
12
|
+
<% end %>
|
@@ -0,0 +1,17 @@
|
|
1
|
+
<h1>Reset Your Password Using Session</h1>
|
2
|
+
|
3
|
+
<%= form_with url: phcdevworks_accounts_stytch.b2b_process_reset_session_path(organization_slug: params[:organization_slug]), method: :post do |form| %>
|
4
|
+
<div>
|
5
|
+
<%= form.label :session_token, "Session Token" %>
|
6
|
+
<%= form.text_field :session_token, required: true %>
|
7
|
+
</div>
|
8
|
+
|
9
|
+
<div>
|
10
|
+
<%= form.label :password, "New Password" %>
|
11
|
+
<%= form.password_field :password, required: true %>
|
12
|
+
</div>
|
13
|
+
|
14
|
+
<div>
|
15
|
+
<%= form.submit "Reset Password" %>
|
16
|
+
</div>
|
17
|
+
<% end %>
|
@@ -0,0 +1,12 @@
|
|
1
|
+
<h1>Invite User via Magic Link</h1>
|
2
|
+
|
3
|
+
<%= form_with url: phcdevworks_accounts_stytch.b2c_magic_links_process_invite_path, local: true do |form| %>
|
4
|
+
<div class="field">
|
5
|
+
<%= form.label :email, "Invitee's Email" %><br>
|
6
|
+
<%= form.email_field :email, required: true %>
|
7
|
+
</div>
|
8
|
+
|
9
|
+
<div class="actions">
|
10
|
+
<%= form.submit "Send Invite" %>
|
11
|
+
</div>
|
12
|
+
<% end %>
|
@@ -0,0 +1,12 @@
|
|
1
|
+
<h1>Login or Sign Up with Magic Link</h1>
|
2
|
+
|
3
|
+
<%= form_with url: phcdevworks_accounts_stytch.b2c_magic_links_process_login_or_signup_path, local: true do |form| %>
|
4
|
+
<div class="field">
|
5
|
+
<%= form.label :email, "Your Email" %><br>
|
6
|
+
<%= form.email_field :email, required: true %>
|
7
|
+
</div>
|
8
|
+
|
9
|
+
<div class="actions">
|
10
|
+
<%= form.submit "Send Magic Link" %>
|
11
|
+
</div>
|
12
|
+
<% end %>
|
@@ -0,0 +1,22 @@
|
|
1
|
+
<h1>Reset Your Password Using Existing Password</h1>
|
2
|
+
|
3
|
+
<%= form_with url: phcdevworks_accounts_stytch.b2c_process_reset_existing_password_path, method: :post do |form| %>
|
4
|
+
<div>
|
5
|
+
<%= form.label :email, "Email" %>
|
6
|
+
<%= form.email_field :email, required: true %>
|
7
|
+
</div>
|
8
|
+
|
9
|
+
<div>
|
10
|
+
<%= form.label :old_password, "Old Password" %>
|
11
|
+
<%= form.password_field :old_password, required: true %>
|
12
|
+
</div>
|
13
|
+
|
14
|
+
<div>
|
15
|
+
<%= form.label :new_password, "New Password" %>
|
16
|
+
<%= form.password_field :new_password, required: true %>
|
17
|
+
</div>
|
18
|
+
|
19
|
+
<div>
|
20
|
+
<%= form.submit "Reset Password" %>
|
21
|
+
</div>
|
22
|
+
<% end %>
|
@@ -0,0 +1,17 @@
|
|
1
|
+
<h1>Reset Your Password</h1>
|
2
|
+
|
3
|
+
<%= form_with url: phcdevworks_accounts_stytch.b2c_process_password_reset_path, method: :post do |form| %>
|
4
|
+
<div>
|
5
|
+
<%= form.label :token, "Reset Token" %>
|
6
|
+
<%= form.text_field :token, required: true %>
|
7
|
+
</div>
|
8
|
+
|
9
|
+
<div>
|
10
|
+
<%= form.label :password, "New Password" %>
|
11
|
+
<%= form.password_field :password, required: true %>
|
12
|
+
</div>
|
13
|
+
|
14
|
+
<div>
|
15
|
+
<%= form.submit "Reset Password" %>
|
16
|
+
</div>
|
17
|
+
<% end %>
|
@@ -0,0 +1,12 @@
|
|
1
|
+
<h1>Reset Password</h1>
|
2
|
+
|
3
|
+
<%= form_with url: phcdevworks_accounts_stytch.b2c_process_reset_start_path, method: :post do |form| %>
|
4
|
+
<div>
|
5
|
+
<%= form.label :email, "Email" %>
|
6
|
+
<%= form.email_field :email, required: true %>
|
7
|
+
</div>
|
8
|
+
|
9
|
+
<div>
|
10
|
+
<%= form.submit "Send Reset Instructions" %>
|
11
|
+
</div>
|
12
|
+
<% end %>
|
@@ -0,0 +1,17 @@
|
|
1
|
+
<h1>Reset Your Password Using Session</h1>
|
2
|
+
|
3
|
+
<%= form_with url: phcdevworks_accounts_stytch.b2c_process_reset_session_path, method: :post do |form| %>
|
4
|
+
<div>
|
5
|
+
<%= form.label :session_token, "Session Token" %>
|
6
|
+
<%= form.text_field :session_token, required: true %>
|
7
|
+
</div>
|
8
|
+
|
9
|
+
<div>
|
10
|
+
<%= form.label :password, "New Password" %>
|
11
|
+
<%= form.password_field :password, required: true %>
|
12
|
+
</div>
|
13
|
+
|
14
|
+
<div>
|
15
|
+
<%= form.submit "Reset Password" %>
|
16
|
+
</div>
|
17
|
+
<% end %>
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
namespace :b2b do
|
4
|
+
# PHCDEVWORKS - B2B Routes for Magic Links
|
5
|
+
get 'magic_links/invite/:organization_slug', to: 'magic_links#invite', as: 'magic_links_invite'
|
6
|
+
get 'magic_links/login/:organization_slug', to: 'magic_links#login_or_signup', as: 'magic_links_login'
|
7
|
+
get 'magic_links/signup/:organization_slug', to: 'magic_links#login_or_signup', as: 'magic_links_signup'
|
8
|
+
|
9
|
+
post 'magic_links/process_invite/:organization_slug', to: 'magic_links#process_invite', as: 'magic_links_process_invite'
|
10
|
+
post 'magic_links/process_login_or_signup/:organization_slug', to: 'magic_links#process_login_or_signup',
|
11
|
+
as: 'magic_links_process_login_or_signup'
|
12
|
+
|
13
|
+
# PHCDEVWORKS - B2B Routes for Passwords
|
14
|
+
get 'passwords/reset/:organization_slug', to: 'passwords#reset_password', as: 'password_reset'
|
15
|
+
get 'passwords/reset/existing/:organization_slug', to: 'passwords#reset_existing_password', as: 'password_reset_existing'
|
16
|
+
get 'passwords/reset/session/:organization_slug', to: 'passwords#reset_with_session', as: 'password_reset_session'
|
17
|
+
get 'passwords/reset/start/:organization_slug', to: 'passwords#reset_start', as: 'password_reset_start'
|
18
|
+
|
19
|
+
post 'passwords/reset/:organization_slug', to: 'passwords#process_reset_password', as: 'process_password_reset'
|
20
|
+
post 'passwords/reset/existing/:organization_slug', to: 'passwords#process_reset_existing_password',
|
21
|
+
as: 'process_reset_existing_password'
|
22
|
+
post 'passwords/reset/session/:organization_slug',
|
23
|
+
to: 'passwords#process_reset_with_session', as: 'process_reset_session'
|
24
|
+
|
25
|
+
post 'passwords/reset/start/:organization_slug', to: 'passwords#process_reset_start', as: 'process_reset_start'
|
26
|
+
|
27
|
+
# PHCDEVWORKS - B2B Authentication Routes for both Passwords and Magic Links
|
28
|
+
get 'authenticate', to: 'authenticate#authenticate', as: 'authenticate'
|
29
|
+
match 'process_authenticate', to: 'authenticate#process_authenticate', via: %i[get post], as: 'process_authenticate'
|
30
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
namespace :b2c do
|
4
|
+
# PHCDEVWORKS - B2C Routes for Magic Links
|
5
|
+
get 'magic_links/invite', to: 'magic_links#invite', as: 'magic_links_invite'
|
6
|
+
get 'magic_links/login', to: 'magic_links#login_or_signup', as: 'magic_links_login'
|
7
|
+
get 'magic_links/signup', to: 'magic_links#login_or_signup', as: 'magic_links_signup'
|
8
|
+
|
9
|
+
post 'magic_links/process_invite', to: 'magic_links#process_invite', as: 'magic_links_process_invite'
|
10
|
+
post 'magic_links/process_revoke_invite', to: 'magic_links#process_revoke_invite', as: 'magic_links_process_revoke_invite'
|
11
|
+
post 'magic_links/process_login_or_signup', to: 'magic_links#process_login_or_signup', as: 'magic_links_process_login_or_signup'
|
12
|
+
|
13
|
+
# PHCDEVWORKS - B2C Routes for Passwords
|
14
|
+
get 'passwords/reset', to: 'passwords#reset_password', as: 'password_reset'
|
15
|
+
get 'passwords/reset/existing', to: 'passwords#reset_existing_password', as: 'password_reset_existing'
|
16
|
+
get 'passwords/reset/session', to: 'passwords#reset_with_session', as: 'password_reset_session'
|
17
|
+
get 'passwords/reset/start', to: 'passwords#reset_start', as: 'password_reset_start'
|
18
|
+
|
19
|
+
post 'passwords/reset', to: 'passwords#process_reset_password', as: 'process_password_reset'
|
20
|
+
post 'passwords/reset/existing', to: 'passwords#process_reset_existing_password', as: 'process_reset_existing_password'
|
21
|
+
post 'passwords/reset/session', to: 'passwords#process_reset_with_session', as: 'process_reset_session'
|
22
|
+
post 'passwords/reset/start', to: 'passwords#process_reset_start', as: 'process_reset_start'
|
23
|
+
|
24
|
+
# PHCDEVWORKS - B2C Authentication Routes for both Passwords and Magic Links
|
25
|
+
get 'authenticate', to: 'authenticate#authenticate', as: 'authenticate'
|
26
|
+
match 'process_authenticate', to: 'authenticate#process_authenticate', via: %i[get post], as: 'process_authenticate'
|
27
|
+
end
|
data/config/routes.rb
CHANGED
@@ -0,0 +1,63 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PhcdevworksAccountsStytch
|
4
|
+
module Authentication
|
5
|
+
module B2b
|
6
|
+
class MagicLinkService
|
7
|
+
def initialize
|
8
|
+
@client = PhcdevworksAccountsStytch::Stytch::Client.b2b_client
|
9
|
+
end
|
10
|
+
|
11
|
+
def process_login_or_signup(email, organization_id)
|
12
|
+
log_action('Login or Signup', email: email, organization_id: organization_id)
|
13
|
+
response = @client.magic_links.email.login_or_signup(
|
14
|
+
organization_id: organization_id,
|
15
|
+
email_address: email
|
16
|
+
)
|
17
|
+
handle_response(response)
|
18
|
+
end
|
19
|
+
|
20
|
+
def process_invite(email, organization_id, session_token)
|
21
|
+
log_action('Invite', email: email, organization_id: organization_id)
|
22
|
+
options = build_method_options(session_token)
|
23
|
+
response = @client.magic_links.email.invite(
|
24
|
+
organization_id: organization_id,
|
25
|
+
email_address: email,
|
26
|
+
method_options: options
|
27
|
+
)
|
28
|
+
handle_response(response)
|
29
|
+
end
|
30
|
+
|
31
|
+
def process_authenticate(magic_links_token)
|
32
|
+
log_action('Authenticate', magic_links_token: magic_links_token)
|
33
|
+
response = @client.magic_links.authenticate(magic_links_token: magic_links_token)
|
34
|
+
handle_response(response)
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def handle_response(response)
|
40
|
+
PhcdevworksAccountsStytch::Stytch::Response.handle_response(response)
|
41
|
+
rescue PhcdevworksAccountsStytch::Stytch::Error => e
|
42
|
+
log_error(e)
|
43
|
+
raise
|
44
|
+
end
|
45
|
+
|
46
|
+
def build_method_options(session_token)
|
47
|
+
PhcdevworksAccountsStytch::Stytch::MethodOptions.new(
|
48
|
+
authorization: { session_token: session_token }
|
49
|
+
)
|
50
|
+
end
|
51
|
+
|
52
|
+
def log_action(action_name, details = {})
|
53
|
+
Rails.logger.info "Starting #{action_name} with details: #{details.inspect}"
|
54
|
+
end
|
55
|
+
|
56
|
+
def log_error(error)
|
57
|
+
Rails.logger.error "Error occurred: #{error.message}"
|
58
|
+
Rails.logger.error error.backtrace.join("\n")
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PhcdevworksAccountsStytch
|
4
|
+
module Authentication
|
5
|
+
module B2b
|
6
|
+
class PasswordService
|
7
|
+
def initialize
|
8
|
+
@client = PhcdevworksAccountsStytch::Stytch::Client.b2b_client
|
9
|
+
end
|
10
|
+
|
11
|
+
def reset_start(email, organization_id)
|
12
|
+
log_action('Password Reset Start', email: email, organization_id: organization_id)
|
13
|
+
response = @client.passwords.email.reset_start(
|
14
|
+
organization_id: organization_id,
|
15
|
+
email_address: email
|
16
|
+
)
|
17
|
+
handle_response(response)
|
18
|
+
end
|
19
|
+
|
20
|
+
def reset(password_reset_token, new_password)
|
21
|
+
log_action('Password Reset', token: password_reset_token)
|
22
|
+
response = @client.passwords.email.reset(
|
23
|
+
password_reset_token: password_reset_token,
|
24
|
+
password: new_password
|
25
|
+
)
|
26
|
+
handle_response(response)
|
27
|
+
end
|
28
|
+
|
29
|
+
def reset_existing(email, old_password, new_password, organization_id)
|
30
|
+
log_action('Existing Password Reset', email: email, organization_id: organization_id)
|
31
|
+
response = @client.passwords.existing_password.reset(
|
32
|
+
email_address: email,
|
33
|
+
existing_password: old_password,
|
34
|
+
new_password: new_password,
|
35
|
+
organization_id: organization_id
|
36
|
+
)
|
37
|
+
handle_response(response)
|
38
|
+
end
|
39
|
+
|
40
|
+
def reset_with_session(session_token, new_password, organization_id)
|
41
|
+
log_action('Session-based Password Reset', session_token: session_token, organization_id: organization_id)
|
42
|
+
response = @client.passwords.sessions.reset(
|
43
|
+
session_token: session_token,
|
44
|
+
password: new_password,
|
45
|
+
organization_id: organization_id
|
46
|
+
)
|
47
|
+
handle_response(response)
|
48
|
+
end
|
49
|
+
|
50
|
+
def authenticate_password(email, password, organization_id)
|
51
|
+
log_action('Password Authentication', email: email, organization_id: organization_id)
|
52
|
+
response = @client.passwords.authenticate(
|
53
|
+
email_address: email,
|
54
|
+
password: password,
|
55
|
+
organization_id: organization_id
|
56
|
+
)
|
57
|
+
handle_response(response)
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
|
62
|
+
def handle_response(response)
|
63
|
+
PhcdevworksAccountsStytch::Stytch::Response.handle_response(response)
|
64
|
+
rescue PhcdevworksAccountsStytch::Stytch::Error => e
|
65
|
+
log_error(e)
|
66
|
+
raise
|
67
|
+
end
|
68
|
+
|
69
|
+
def log_action(action_name, details = {})
|
70
|
+
Rails.logger.info "Starting #{action_name} with details: #{details.inspect}"
|
71
|
+
end
|
72
|
+
|
73
|
+
def log_error(error)
|
74
|
+
Rails.logger.error "Error occurred: #{error.message}"
|
75
|
+
Rails.logger.error error.backtrace.join("\n")
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PhcdevworksAccountsStytch
|
4
|
+
module Authentication
|
5
|
+
module B2c
|
6
|
+
class MagicLinkService
|
7
|
+
def initialize
|
8
|
+
@client = PhcdevworksAccountsStytch::Stytch::Client.b2c_client
|
9
|
+
end
|
10
|
+
|
11
|
+
def process_login_or_signup(email)
|
12
|
+
log_action('Login or Signup', email: email)
|
13
|
+
response = @client.magic_links.email.login_or_create(email: email)
|
14
|
+
handle_response(response)
|
15
|
+
end
|
16
|
+
|
17
|
+
def process_invite(email)
|
18
|
+
log_action('Invite', email: email)
|
19
|
+
response = @client.magic_links.email.invite(email: email)
|
20
|
+
handle_response(response)
|
21
|
+
end
|
22
|
+
|
23
|
+
def process_revoke_invite(email)
|
24
|
+
log_action('Revoke Invite', email: email)
|
25
|
+
response = @client.magic_links.email.revoke_invite(email: email)
|
26
|
+
handle_response(response)
|
27
|
+
end
|
28
|
+
|
29
|
+
def process_authenticate(token)
|
30
|
+
log_action('Authenticate', token: token)
|
31
|
+
response = @client.magic_links.authenticate(token: token)
|
32
|
+
handle_response(response)
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def handle_response(response)
|
38
|
+
PhcdevworksAccountsStytch::Stytch::Response.handle_response(response)
|
39
|
+
rescue PhcdevworksAccountsStytch::Stytch::Error => e
|
40
|
+
log_error(e)
|
41
|
+
raise
|
42
|
+
end
|
43
|
+
|
44
|
+
def log_action(action_name, details = {})
|
45
|
+
Rails.logger.info "Starting #{action_name} with details: #{details.inspect}"
|
46
|
+
end
|
47
|
+
|
48
|
+
def log_error(error)
|
49
|
+
Rails.logger.error "Error occurred: #{error.message}"
|
50
|
+
Rails.logger.error error.backtrace.join("\n")
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PhcdevworksAccountsStytch
|
4
|
+
module Authentication
|
5
|
+
module B2c
|
6
|
+
class PasswordService
|
7
|
+
def initialize
|
8
|
+
@client = PhcdevworksAccountsStytch::Stytch::Client.b2c_client
|
9
|
+
end
|
10
|
+
|
11
|
+
def reset_start(email)
|
12
|
+
log_action('Password Reset Start', email: email)
|
13
|
+
response = @client.passwords.email.reset_start(
|
14
|
+
email: email
|
15
|
+
)
|
16
|
+
handle_response(response)
|
17
|
+
end
|
18
|
+
|
19
|
+
def reset(password_reset_token, new_password)
|
20
|
+
log_action('Password Reset', token: password_reset_token)
|
21
|
+
response = @client.passwords.email.reset(
|
22
|
+
token: password_reset_token,
|
23
|
+
password: new_password
|
24
|
+
)
|
25
|
+
handle_response(response)
|
26
|
+
end
|
27
|
+
|
28
|
+
def reset_existing(email, old_password, new_password)
|
29
|
+
log_action('Existing Password Reset', email: email)
|
30
|
+
response = @client.passwords.existing_password.reset(
|
31
|
+
email: email,
|
32
|
+
existing_password: old_password,
|
33
|
+
new_password: new_password
|
34
|
+
)
|
35
|
+
handle_response(response)
|
36
|
+
end
|
37
|
+
|
38
|
+
def reset_with_session(session_token, new_password)
|
39
|
+
log_action('Session-based Password Reset', session_token: session_token)
|
40
|
+
response = @client.passwords.sessions.reset(
|
41
|
+
session_token: session_token,
|
42
|
+
password: new_password
|
43
|
+
)
|
44
|
+
handle_response(response)
|
45
|
+
end
|
46
|
+
|
47
|
+
def authenticate_password(email, password)
|
48
|
+
log_action('Password Authentication', email: email)
|
49
|
+
response = @client.passwords.authenticate(
|
50
|
+
email: email,
|
51
|
+
password: password
|
52
|
+
)
|
53
|
+
handle_response(response)
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
|
58
|
+
def handle_response(response)
|
59
|
+
PhcdevworksAccountsStytch::Stytch::Response.handle_response(response)
|
60
|
+
rescue PhcdevworksAccountsStytch::Stytch::Error => e
|
61
|
+
log_error(e)
|
62
|
+
raise
|
63
|
+
end
|
64
|
+
|
65
|
+
def log_action(action_name, details = {})
|
66
|
+
Rails.logger.info "Starting #{action_name} with details: #{details.inspect}"
|
67
|
+
end
|
68
|
+
|
69
|
+
def log_error(error)
|
70
|
+
Rails.logger.error "Error occurred: #{error.message}"
|
71
|
+
Rails.logger.error error.backtrace.join("\n")
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -3,5 +3,11 @@
|
|
3
3
|
module PhcdevworksAccountsStytch
|
4
4
|
class Engine < ::Rails::Engine
|
5
5
|
isolate_namespace PhcdevworksAccountsStytch
|
6
|
+
|
7
|
+
initializer 'phcdevworks_accounts_stytch.configure_stytch' do
|
8
|
+
PhcdevworksAccountsStytch::Stytch::Client.b2b_client
|
9
|
+
PhcdevworksAccountsStytch::Stytch::Client.b2c_client
|
10
|
+
end
|
11
|
+
config.autoload_paths += %W[#{config.root}/lib]
|
6
12
|
end
|
7
13
|
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PhcdevworksAccountsStytch
|
4
|
+
module Stytch
|
5
|
+
class Client
|
6
|
+
class << self
|
7
|
+
def b2b_client
|
8
|
+
@b2b_client ||= create_b2b_client
|
9
|
+
end
|
10
|
+
|
11
|
+
def b2c_client
|
12
|
+
@b2c_client ||= create_b2c_client
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def create_b2b_client
|
18
|
+
project_id = Rails.application.credentials.dig(:stytch, :b2b, :project_id)
|
19
|
+
secret = Rails.application.credentials.dig(:stytch, :b2b, :secret)
|
20
|
+
unless project_id && secret
|
21
|
+
raise PhcdevworksAccountsStytch::Stytch::Error.new(error_message: 'Stytch B2B credentials are missing')
|
22
|
+
end
|
23
|
+
|
24
|
+
StytchB2B::Client.new(
|
25
|
+
project_id: project_id,
|
26
|
+
secret: secret
|
27
|
+
)
|
28
|
+
end
|
29
|
+
|
30
|
+
def create_b2c_client
|
31
|
+
project_id = Rails.application.credentials.dig(:stytch, :b2c, :project_id)
|
32
|
+
secret = Rails.application.credentials.dig(:stytch, :b2c, :secret)
|
33
|
+
unless project_id && secret
|
34
|
+
raise PhcdevworksAccountsStytch::Stytch::Error.new(error_message: 'Stytch B2C credentials are missing')
|
35
|
+
end
|
36
|
+
|
37
|
+
::Stytch::Client.new(
|
38
|
+
project_id: project_id,
|
39
|
+
secret: secret
|
40
|
+
)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PhcdevworksAccountsStytch
|
4
|
+
module Stytch
|
5
|
+
class Error < StandardError
|
6
|
+
attr_reader :status_code, :error_code, :error_message
|
7
|
+
|
8
|
+
def initialize(status_code: nil, error_code: nil, error_message: nil)
|
9
|
+
@status_code = status_code
|
10
|
+
@error_code = error_code
|
11
|
+
@error_message = error_message || 'An error occurred with Stytch'
|
12
|
+
super(build_message)
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def build_message
|
18
|
+
message = 'Stytch Error'
|
19
|
+
message += " (Status Code: #{@status_code})" if @status_code
|
20
|
+
message += " - Code: #{@error_code}" if @error_code
|
21
|
+
message += " - Message: #{@error_message}" if @error_message
|
22
|
+
message
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PhcdevworksAccountsStytch
|
4
|
+
module Stytch
|
5
|
+
class MethodOptions
|
6
|
+
attr_reader :options
|
7
|
+
|
8
|
+
def initialize(options = {})
|
9
|
+
@options = options
|
10
|
+
end
|
11
|
+
|
12
|
+
def to_headers
|
13
|
+
headers = {}
|
14
|
+
if (authorization = options[:authorization]) && authorization[:session_token]
|
15
|
+
headers['Authorization'] = "Bearer #{authorization[:session_token]}"
|
16
|
+
end
|
17
|
+
headers
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|