Skip to content

Commit

Permalink
Merge pull request #438 from cedarcode/sr--add-json-serializer
Browse files Browse the repository at this point in the history
Extract shared logic for serializing credential options into a new `JSONSerializer` module
  • Loading branch information
brauliomartinezlm authored Nov 12, 2024
2 parents 6fe25bf + 78ddf37 commit ae3f1fe
Show file tree
Hide file tree
Showing 7 changed files with 84 additions and 69 deletions.
2 changes: 1 addition & 1 deletion lib/webauthn.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# frozen_string_literal: true

require "webauthn/camelize_helper"
require "webauthn/json_serializer"
require "webauthn/configuration"
require "webauthn/credential"
require "webauthn/credential_creation_options"
Expand Down
21 changes: 0 additions & 21 deletions lib/webauthn/camelize_helper.rb

This file was deleted.

43 changes: 43 additions & 0 deletions lib/webauthn/json_serializer.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# frozen_string_literal: true

module WebAuthn
module JSONSerializer
# Argument wildcard for Ruby on Rails controller automatic object JSON serialization
def as_json(*)
to_hash_with_camelized_keys
end

private

def to_hash_with_camelized_keys
attributes.each_with_object({}) do |attribute_name, hash|
value = send(attribute_name)

if value.respond_to?(:as_json)
hash[camelize(attribute_name)] = value.as_json
elsif value
hash[camelize(attribute_name)] = deep_camelize_keys(value)
end
end
end

def deep_camelize_keys(object)
case object
when Hash
object.each_with_object({}) do |(key, value), result|
result[camelize(key)] = deep_camelize_keys(value)
end
when Array
object.map { |element| deep_camelize_keys(element) }
else
object
end
end

def camelize(term)
first_term, *rest = term.to_s.split('_')

[first_term, *rest.map(&:capitalize)].join.to_sym
end
end
end
24 changes: 1 addition & 23 deletions lib/webauthn/public_key_credential/entity.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,38 +3,16 @@
module WebAuthn
class PublicKeyCredential
class Entity
include CamelizeHelper
include JSONSerializer

attr_reader :name

def initialize(name:)
@name = name
end

def as_json
deep_camelize_keys(to_hash)
end

private

def to_hash
hash = {}

attributes.each do |attribute_name|
value = send(attribute_name)

if value.respond_to?(:as_json)
value = value.as_json
end

if value
hash[attribute_name] = value
end
end

hash
end

def attributes
[:name]
end
Expand Down
25 changes: 1 addition & 24 deletions lib/webauthn/public_key_credential/options.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
module WebAuthn
class PublicKeyCredential
class Options
include CamelizeHelper
include JSONSerializer

CHALLENGE_LENGTH = 32

Expand All @@ -21,31 +21,8 @@ def challenge
encoder.encode(raw_challenge)
end

# Argument wildcard for Ruby on Rails controller automatic object JSON serialization
def as_json(*)
deep_camelize_keys(to_hash)
end

private

def to_hash
hash = {}

attributes.each do |attribute_name|
value = send(attribute_name)

if value.respond_to?(:as_json)
value = value.as_json
end

if value
hash[attribute_name] = value
end
end

hash
end

def attributes
[:challenge, :timeout, :extensions]
end
Expand Down
25 changes: 25 additions & 0 deletions spec/webauthn/public_key_credential/creation_options_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,31 @@
expect(hash[:challenge]).to be_truthy
end

it "has minimum required" do
options = WebAuthn::PublicKeyCredential::CreationOptions.new(
user: {
id: "user-id",
name: "user-name",
}
)

hash = options.as_json

expect(hash[:rp]).to eq({})
expect(hash[:user]).to eq(
id: "user-id", name: "user-name", displayName: 'user-name'
)
expect(hash[:pubKeyCredParams]).to eq(
[{ type: "public-key", alg: -7 }, { type: "public-key", alg: -37 }, { type: "public-key", alg: -257 }]
)
expect(hash[:timeout]).to eq(120_000)
expect(hash[:excludeCredentials]).to be_nil
expect(hash[:authenticatorSelection]).to be_nil
expect(hash[:attestation]).to be_nil
expect(hash[:extensions]).to eq({})
expect(hash[:challenge]).to be_truthy
end

it "accepts shorthand for exclude_credentials" do
options = WebAuthn::PublicKeyCredential::CreationOptions.new(user: { id: "id", name: "name" }, exclude: "id")

Expand Down
13 changes: 13 additions & 0 deletions spec/webauthn/public_key_credential/request_options_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,19 @@
expect(hash[:challenge]).to be_truthy
end

it "has minimum required" do
options = WebAuthn::PublicKeyCredential::RequestOptions.new

hash = options.as_json

expect(hash[:rpId]).to be_nil
expect(hash[:timeout]).to eq(120_000)
expect(hash[:allowCredentials]).to eq([])
expect(hash[:userVerification]).to be_nil
expect(hash[:extensions]).to eq({})
expect(hash[:challenge]).to be_truthy
end

it "accepts shorthand for allow_credentials" do
options = WebAuthn::PublicKeyCredential::RequestOptions.new(allow: "id")

Expand Down

0 comments on commit ae3f1fe

Please sign in to comment.