diff --git a/entries/1/1password.com.json b/entries/1/1password.com.json index ce44ec1..72c5d5c 100644 --- a/entries/1/1password.com.json +++ b/entries/1/1password.com.json @@ -4,7 +4,7 @@ "1password.ca", "1password.eu" ], - "passkeys": "allowed", + "mfa": "allowed", "documentation": "https://support.1password.com/security-key/", "categories": "identity" } diff --git a/entries/i/icloud.com.json b/entries/i/icloud.com.json new file mode 100644 index 0000000..c5ade3e --- /dev/null +++ b/entries/i/icloud.com.json @@ -0,0 +1,8 @@ +{ + "Apple iCloud": { + "passwordless": "allowed", + "documentation": "https://support.apple.com/guide/iphone/use-passkeys-to-sign-in-to-apps-and-websites-iphf538ea8d0/ios", + "notes": "Passwordless authentication only works on Apple devices.", + "categories": "backup" + } +} diff --git a/img/i/icloud.com.svg b/img/i/icloud.com.svg new file mode 100644 index 0000000..ef3599c --- /dev/null +++ b/img/i/icloud.com.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/scripts/APIv1.rb b/scripts/APIv1.rb index c6019bf..1c322a6 100755 --- a/scripts/APIv1.rb +++ b/scripts/APIv1.rb @@ -8,7 +8,8 @@ # @return [Integer] Returns exit code def public_api all = {} - passkeys = {} + passwordless = {} + mfa = {} path = 'public/api/v1' Dir.glob(@entries) { |file| all[File.basename(file, '.*')] = JSON.parse(File.read(file)).values[0] } @@ -18,24 +19,20 @@ def public_api end entry.delete('additional-domains') entry.delete('img') + entry.delete('categories') end all.to_h.each do |k, v| - pk = Array(v['passkeys']) - next if pk.empty? - - pk.each do |option| - passkeys[option] ||= {} - passkeys[option][k] = v - end + mfa[k] = v if v['mfa'] + passwordless[k] = v if v['passwordless'] end - { 'all' => all }.merge(passkeys).each do |k, v| + { 'all' => all, 'mfa' => mfa, 'passwordless' => passwordless }.each do |k, v| File.open("#{path}/#{k}.json", 'w') { |file| file.write v.sort_by { |a, _| a.downcase }.to_h.to_json } end File.open("#{path}/supported.json", 'w') do |file| - file.write all.select { |_, v| v.key? 'passkeys' }.sort_by { |k, _| k.downcase }.to_h.to_json + file.write all.select { |_, v| v.keys.any? { |k| k.match(/mfa|passwordless/) } }.sort_by { |k, _| k.downcase }.to_h.to_json end end @@ -55,7 +52,6 @@ def private_api regions[region] = {} unless regions.key? region regions[region]['count'] = 1 + regions[region]['count'].to_i end - entry['passkeys'] = Array(entry['passkeys']) if entry.key?('passkeys') entry['categories'] = Array(entry['categories']) if entry.key?('categories') entry.delete 'additional-domains' end diff --git a/tests/schema.json b/tests/schema.json index 8014038..1d2522c 100644 --- a/tests/schema.json +++ b/tests/schema.json @@ -20,22 +20,13 @@ "type": "string", "pattern": "^[a-z0-9_\\-+.]+\\.(png|svg)$" }, - "passkeys": { - "oneOf": [ - { - "type": "array", - "uniqueItems": true, - "minItems": 2, - "items": { - "type": "string", - "pattern": "^(allowed|required|mfa)" - } - }, - { - "type": "string", - "pattern": "^(allowed|required|mfa)" - } - ] + "mfa": { + "type": "string", + "pattern": "^(allowed|required)$" + }, + "passwordless": { + "type": "string", + "pattern": "^(allowed|required)$" }, "documentation": { "type": "string", @@ -131,14 +122,60 @@ }, "oneOf": [ { - "required": [ - "passkeys" - ] + "required": ["contact"], + "not": { + "anyOf": [ + { "required": ["mfa"] }, + { "required": ["passwordless"] } + ] + } }, { - "required": [ - "contact" - ] + "type": "object", + "properties": { + "mfa": { + "type": "string", + "pattern": "^(allowed|required)$" + }, + "passwordless": { + "type": "string", + "pattern": "^(allowed|required)$" + } + }, + "required": ["mfa", "passwordless"], + "not": { "required": ["contact"] } + }, + { + "type": "object", + "properties": { + "mfa": { + "type": "string", + "pattern": "^(allowed|required)$" + } + }, + "required": ["mfa"], + "not": { + "anyOf": [ + { "required": ["passwordless"] }, + { "required": ["contact"] } + ] + } + }, + { + "type": "object", + "properties": { + "passwordless": { + "type": "string", + "pattern": "^(allowed|required)$" + } + }, + "required": ["passwordless"], + "not": { + "anyOf": [ + { "required": ["mfa"] }, + { "required": ["contact"] } + ] + } } ] }