1 # frozen_string_literal: true
2
3 require 'json'
4 require_relative 'auth/version'
5 require_relative 'auth/auth'
6
7 module Auth
8 end
9
10 module SmbCloud
11 module Auth
12 class Error < StandardError
13 attr_reader :error_code, :payload
14
15 def initialize(message = nil, error_code: nil, payload: nil)
16 super(message)
17 @error_code = error_code
18 @payload = payload
19 end
20 end
21
22 module Environment
23 DEV = 'dev'
24 PRODUCTION = 'production'
25 end
26
27 class Client
28 attr_reader :environment, :app_id, :app_secret
29
30 def initialize(environment:, app_id:, app_secret:)
31 @environment = environment
32 @app_id = app_id
33 @app_secret = app_secret
34 end
35
36 def signup(email:, password:)
37 Auth.send(:parse_json, Auth.__signup_with_client(environment, app_id, app_secret, email, password))
38 rescue RuntimeError => e
39 raise Auth.send(:normalize_error, e)
40 end
41
42 def login(email:, password:)
43 Auth.send(:parse_json, Auth.__login_with_client(environment, app_id, app_secret, email, password))
44 rescue RuntimeError => e
45 raise Auth.send(:normalize_error, e)
46 end
47
48 # Requests password-reset instructions for the given email. The endpoint
49 # never reveals whether the account exists (no enumeration), and calling
50 # it again re-issues the token, so this also serves the "resend reset
51 # instructions" flow. Returns { code:, message: }.
52 def reset_password(email:)
53 Auth.send(:parse_json, Auth.__reset_password_with_client(environment, app_id, app_secret, email))
54 rescue RuntimeError => e
55 raise Auth.send(:normalize_error, e)
56 end
57
58 def me(access_token:)
59 Auth.send(:parse_json, Auth.__me_with_client(environment, app_id, app_secret, access_token))
60 rescue RuntimeError => e
61 raise Auth.send(:normalize_error, e)
62 end
63
64 def logout(access_token:)
65 Auth.__logout_with_client(environment, app_id, app_secret, access_token)
66 rescue RuntimeError => e
67 raise Auth.send(:normalize_error, e)
68 end
69
70 def remove(access_token:)
71 Auth.__remove_with_client(environment, app_id, app_secret, access_token)
72 rescue RuntimeError => e
73 raise Auth.send(:normalize_error, e)
74 end
75 end
76
77 class << self
78 def client(environment:, app_id:, app_secret:)
79 Client.new(environment:, app_id:, app_secret:)
80 end
81
82 def signup_with_client(environment:, app_id:, app_secret:, email:, password:)
83 client(environment:, app_id:, app_secret:).signup(email:, password:)
84 end
85
86 def login_with_client(environment:, app_id:, app_secret:, email:, password:)
87 client(environment:, app_id:, app_secret:).login(email:, password:)
88 end
89
90 def reset_password_with_client(environment:, app_id:, app_secret:, email:)
91 client(environment:, app_id:, app_secret:).reset_password(email:)
92 end
93
94 def me_with_client(environment:, app_id:, app_secret:, access_token:)
95 client(environment:, app_id:, app_secret:).me(access_token:)
96 end
97
98 def logout_with_client(environment:, app_id:, app_secret:, access_token:)
99 client(environment:, app_id:, app_secret:).logout(access_token:)
100 end
101
102 def remove_with_client(environment:, app_id:, app_secret:, access_token:)
103 client(environment:, app_id:, app_secret:).remove(access_token:)
104 end
105
106 private
107
108 def parse_json(payload)
109 return payload unless payload.is_a?(String)
110
111 JSON.parse(payload, symbolize_names: true)
112 end
113
114 def normalize_error(error)
115 payload = parse_json(error.message)
116 error_hash = payload[:error] || payload
117 message = error_hash[:message] || error.message
118 error_code = error_hash[:error_code]
119 Error.new(message, error_code: error_code, payload: payload)
120 rescue JSON::ParserError, NoMethodError, TypeError
121 Error.new(error.message)
122 end
123 end
124 end
125 end