phcdevworks_accounts_stytch 0.1.0.pre.1 → 0.2.0.pre.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|