wowsql-sdk 3.9.0 → 3.9.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: dda55e2b1cbe73aabfaffa2aaadb6690c8a8978e89f712284cf9507a640004cf
4
- data.tar.gz: c88299d7c4be38e8a121865f292d0cac3d489b5de358ea002d24afc6a6715fe6
3
+ metadata.gz: d95459a8c529ff5a62a4dc8c370041f1c77827bfc55069e562efeb5dcb9ba00a
4
+ data.tar.gz: 6f05ecb7c8da142eab17f92dd449fbc1761e3e4cb1c33c15028b6e00b8733762
5
5
  SHA512:
6
- metadata.gz: f8d0524196573928f5c92b8cac0df6a0bd6789a9fa18d1cf4c16d87ffb76fb547d51365ca2dc8bca996469584497a249ae3be7fb3fdc1b06c50a2d4c083c8ee4
7
- data.tar.gz: 1ee24eb2e9e535fdaa3ca6478ac77407e693a68914f26466b66eeb04ca92f2c561bb9a2154f9705d1eaa7ed793da1ea89e30b267a51f20a4bab91516b1e8c8a2
6
+ metadata.gz: 398dc67a4528c3699f110e5371395896734fb97eb6ef78aa9cef63ea810150e07a77980e63011af8c5c4b04a55551caf1688972c888f71be08e6a9f322723f83
7
+ data.tar.gz: 8c2e796cdcea0191470e0277201b91222f6fbe51d796698bbff6f50dd2a22a2371fef0e4fcc9d7dfaf07b4170f532d381560a431d1dec67a0d44267b1ee52b3b
data/CHANGELOG.md CHANGED
@@ -5,6 +5,19 @@ All notable changes to the WowSQL Ruby SDK will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [3.9.2] - 2026-10-10
9
+
10
+ ### Added - Optional Turnstile captcha
11
+ - Optional captcha token on signup, login, forgot password, OTP send, magic link, and resend verification
12
+ - Existing calls without a token remain unchanged
13
+
14
+ ## [3.9.1] - 2026-10-07
15
+
16
+ ### Added - Phone OTP (SMS)
17
+ - `sendOtp` / `verifyOtp` (and language equivalents) accept either **email** or **phone** (exactly one)
18
+ - Existing email OTP call sites remain backward compatible
19
+
20
+
8
21
  ## [3.9.0] - 2026-08-20
9
22
 
10
23
  ### Added - Realtime
@@ -12,7 +25,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
12
25
  - `client.realtime.subscribe` for Postgres `INSERT` / `UPDATE` / `DELETE` (and `*`)
13
26
  - WebSocket auth: `wss://<project>/realtime/v1/websocket?apikey=<anon or service_role key>`
14
27
  - Auto-reconnect after disconnect; unsubscribe / disconnect clean local and server state
15
- - `client.realtime.channel(name)` — ephemeral broadcast (`send`) and presence (`track` / `presence_state`)
28
+ - `client.realtime.channel(name)` — ephemeral broadcast (`send`) and presence (`track` / `presence_state`)
16
29
  - `websocket-client-simple` dependency
17
30
 
18
31
  ### Documentation
data/README.md CHANGED
@@ -406,6 +406,22 @@ puts response.session.access_token
406
406
  puts response.session.refresh_token
407
407
  ```
408
408
 
409
+ ### CAPTCHA (Turnstile)
410
+
411
+ Optional. Only required when Attack Protection → Turnstile is enabled. Existing calls without `captcha_token` are unchanged.
412
+
413
+ ```ruby
414
+ # 1. GET /auth/v1/settings → captcha.site_key
415
+ # 2. Render Cloudflare Turnstile with that site key
416
+ # 3. Pass the token:
417
+ auth.sign_up(email: "alice@example.com", password: "SecurePass123!", captcha_token: turnstile_token)
418
+ auth.sign_in(email: "alice@example.com", password: "SecurePass123!", captcha_token: turnstile_token)
419
+ auth.forgot_password(email: "alice@example.com", captcha_token: turnstile_token)
420
+ auth.send_otp(email: "alice@example.com", captcha_token: turnstile_token)
421
+ auth.send_magic_link(email: "alice@example.com", captcha_token: turnstile_token)
422
+ auth.resend_verification(email: "alice@example.com", captcha_token: turnstile_token)
423
+ ```
424
+
409
425
  ### get_user
410
426
 
411
427
  ```ruby
data/lib/wowsql/auth.rb CHANGED
@@ -126,10 +126,11 @@ module WOWSQL
126
126
  # @param full_name [String, nil] Optional full name
127
127
  # @param user_metadata [Hash, nil] Optional user metadata
128
128
  # @return [AuthResponse]
129
- def sign_up(email:, password:, full_name: nil, user_metadata: nil)
129
+ def sign_up(email:, password:, full_name: nil, user_metadata: nil, captcha_token: nil)
130
130
  payload = { email: email, password: password }
131
131
  payload[:full_name] = full_name if full_name
132
132
  payload[:user_metadata] = user_metadata if user_metadata
133
+ payload[:captcha_token] = captcha_token if captcha_token && !captcha_token.to_s.empty?
133
134
 
134
135
  data = request('POST', '/signup', nil, payload)
135
136
  session = persist_session(data)
@@ -142,8 +143,9 @@ module WOWSQL
142
143
  # @param email [String] User email
143
144
  # @param password [String] User password
144
145
  # @return [AuthResponse]
145
- def sign_in(email:, password:)
146
+ def sign_in(email:, password:, captcha_token: nil)
146
147
  payload = { email: email, password: password }
148
+ payload[:captcha_token] = captcha_token if captcha_token && !captcha_token.to_s.empty?
147
149
  data = request('POST', '/login', nil, payload)
148
150
  session = persist_session(data)
149
151
  AuthResponse.new(session: session, user: nil)
@@ -219,8 +221,9 @@ module WOWSQL
219
221
  #
220
222
  # @param email [String] User's email address
221
223
  # @return [Hash]
222
- def forgot_password(email:)
224
+ def forgot_password(email:, captcha_token: nil)
223
225
  payload = { email: email }
226
+ payload[:captcha_token] = captcha_token if captcha_token && !captcha_token.to_s.empty?
224
227
  data = request('POST', '/forgot-password', nil, payload)
225
228
  {
226
229
  'success' => data['success'] != false,
@@ -242,41 +245,55 @@ module WOWSQL
242
245
  }
243
246
  end
244
247
 
245
- # Send OTP code to user's email.
248
+ # Send OTP via email or phone (SMS). Provide exactly one of email or phone.
246
249
  #
247
- # @param email [String] User's email address
250
+ # @param email [String, nil] User's email address
251
+ # @param phone [String, nil] E.164 phone number
248
252
  # @param purpose [String] 'login', 'signup', or 'password_reset'
249
253
  # @return [Hash]
250
- def send_otp(email:, purpose: 'login')
254
+ def send_otp(email: nil, phone: nil, purpose: 'login', captcha_token: nil)
251
255
  unless %w[login signup password_reset].include?(purpose)
252
256
  raise WOWSQLError.new("Purpose must be 'login', 'signup', or 'password_reset'")
253
257
  end
258
+ if email.to_s.empty? == phone.to_s.empty?
259
+ raise WOWSQLError.new('Provide exactly one of email or phone')
260
+ end
261
+
262
+ payload = { purpose: purpose }
263
+ payload[:email] = email unless email.to_s.empty?
264
+ payload[:phone] = phone unless phone.to_s.empty?
265
+ payload[:captcha_token] = captcha_token if captcha_token && !captcha_token.to_s.empty?
254
266
 
255
- payload = { email: email, purpose: purpose }
256
267
  data = request('POST', '/otp/send', nil, payload)
257
268
  {
258
269
  'success' => data['success'] != false,
259
- 'message' => data['message'] || 'If that email exists, an OTP code has been sent'
270
+ 'message' => data['message'] || (phone.to_s.empty? ? 'If that email exists, an OTP code has been sent' : 'If that phone exists, an OTP code has been sent')
260
271
  }
261
272
  end
262
273
 
263
- # Verify OTP and complete authentication.
274
+ # Verify OTP via email or phone. Provide exactly one of email or phone.
264
275
  #
265
- # @param email [String] User's email address
266
- # @param otp [String] 6-digit OTP code
276
+ # @param email [String, nil] User's email address
277
+ # @param phone [String, nil] E.164 phone number
278
+ # @param otp [String] OTP code
267
279
  # @param purpose [String] 'login', 'signup', or 'password_reset'
268
280
  # @param new_password [String, nil] Required for password_reset purpose
269
281
  # @return [AuthResponse, Hash]
270
- def verify_otp(email:, otp:, purpose: 'login', new_password: nil)
282
+ def verify_otp(email: nil, phone: nil, otp:, purpose: 'login', new_password: nil)
271
283
  unless %w[login signup password_reset].include?(purpose)
272
284
  raise WOWSQLError.new("Purpose must be 'login', 'signup', or 'password_reset'")
273
285
  end
286
+ if email.to_s.empty? == phone.to_s.empty?
287
+ raise WOWSQLError.new('Provide exactly one of email or phone')
288
+ end
274
289
 
275
290
  if purpose == 'password_reset' && new_password.nil?
276
291
  raise WOWSQLError.new('new_password is required for password_reset purpose')
277
292
  end
278
293
 
279
- payload = { email: email, otp: otp, purpose: purpose }
294
+ payload = { otp: otp, purpose: purpose }
295
+ payload[:email] = email unless email.to_s.empty?
296
+ payload[:phone] = phone unless phone.to_s.empty?
280
297
  payload[:new_password] = new_password if new_password
281
298
 
282
299
  data = request('POST', '/otp/verify', nil, payload)
@@ -298,12 +315,13 @@ module WOWSQL
298
315
  # @param email [String] User's email address
299
316
  # @param purpose [String] 'login', 'signup', or 'email_verification'
300
317
  # @return [Hash]
301
- def send_magic_link(email:, purpose: 'login')
318
+ def send_magic_link(email:, purpose: 'login', captcha_token: nil)
302
319
  unless %w[login signup email_verification].include?(purpose)
303
320
  raise WOWSQLError.new("Purpose must be 'login', 'signup', or 'email_verification'")
304
321
  end
305
322
 
306
323
  payload = { email: email, purpose: purpose }
324
+ payload[:captcha_token] = captcha_token if captcha_token && !captcha_token.to_s.empty?
307
325
  data = request('POST', '/magic-link/send', nil, payload)
308
326
  {
309
327
  'success' => data['success'] != false,
@@ -329,8 +347,9 @@ module WOWSQL
329
347
  #
330
348
  # @param email [String] User's email address
331
349
  # @return [Hash]
332
- def resend_verification(email:)
350
+ def resend_verification(email:, captcha_token: nil)
333
351
  payload = { email: email }
352
+ payload[:captcha_token] = captcha_token if captcha_token && !captcha_token.to_s.empty?
334
353
  data = request('POST', '/resend-verification', nil, payload)
335
354
  {
336
355
  'success' => data['success'] != false,
@@ -1,4 +1,4 @@
1
1
  module WOWSQL
2
- VERSION = "3.9.0"
2
+ VERSION = "3.9.2"
3
3
  end
4
4
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: wowsql-sdk
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.9.0
4
+ version: 3.9.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - WOWSQL Team