didkit 0.1.0 → 0.2.0
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 +4 -4
- data/CHANGELOG.md +6 -0
- data/lib/didkit/at_handles.rb +14 -0
- data/lib/didkit/document.rb +21 -20
- data/lib/didkit/plc_importer.rb +43 -15
- data/lib/didkit/plc_operation.rb +31 -30
- data/lib/didkit/resolver.rb +4 -0
- data/lib/didkit/service_record.rb +20 -0
- data/lib/didkit/services.rb +15 -0
- data/lib/didkit/version.rb +1 -1
- data/lib/didkit.rb +3 -0
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0170f70f452400a399264cccd61a96a0ef96d570caca53547b2794eb8067d4bd
|
4
|
+
data.tar.gz: 68197fe06b766fbe69d09d6d85b8abf59467f09560cb600b9af34bb900efaf6b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 367f5acd94953397d5ca72edec0a43f2a96e8dfef3615d16210edc203abe14b1875c1e78316efe351e223c881cbc80d2fd6cf7314753c78caea6c9ccb7ed78d0
|
7
|
+
data.tar.gz: 15ade27998fbc1881f28bc07fe7d625f310e686be7f101508460db48df7ca263adfc6731bf9f8bb935363fb23e51f33b1f560183595ba624d1fd7ad4e8dcf00f
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
## [0.2.0] - 2024-03-19
|
2
|
+
|
3
|
+
- added `PLCImporter` class, which lets you import operations from PLC in pages of 1000 through the "export" API
|
4
|
+
- implemented parsing of all services from DID doc & operations, not only `atproto_pds` (specifically labeller endpoints)
|
5
|
+
- allow setting the nameserver in `Resolver` initializer
|
6
|
+
|
1
7
|
## [0.1.0] - 2024-03-12
|
2
8
|
|
3
9
|
- rejecting handles from disallowed domains like `.arpa` or `.test`
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module DIDKit
|
2
|
+
module AtHandles
|
3
|
+
class FormatError < StandardError
|
4
|
+
end
|
5
|
+
|
6
|
+
def parse_also_known_as(aka)
|
7
|
+
raise FormatError, "Invalid alsoKnownAs: #{aka.inspect}" unless aka.is_a?(Array)
|
8
|
+
raise FormatError, "Invalid alsoKnownAs: #{aka.inspect}" unless aka.all? { |x| x.is_a?(String) }
|
9
|
+
raise FormatError, "Invalid alsoKnownAs: #{aka.inspect}" unless aka.all? { |x| x =~ %r(\Aat://[^/]+\z) }
|
10
|
+
|
11
|
+
aka.map { |x| x.gsub('at://', '') }
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
data/lib/didkit/document.rb
CHANGED
@@ -1,11 +1,17 @@
|
|
1
|
+
require_relative 'at_handles'
|
1
2
|
require_relative 'resolver'
|
3
|
+
require_relative 'service_record'
|
4
|
+
require_relative 'services'
|
2
5
|
|
3
6
|
module DIDKit
|
4
7
|
class Document
|
5
8
|
class FormatError < StandardError
|
6
9
|
end
|
7
10
|
|
8
|
-
|
11
|
+
include AtHandles
|
12
|
+
include Services
|
13
|
+
|
14
|
+
attr_reader :json, :did, :handles, :services
|
9
15
|
|
10
16
|
def initialize(did, json)
|
11
17
|
raise FormatError, "Missing id field" if json['id'].nil?
|
@@ -19,25 +25,20 @@ module DIDKit
|
|
19
25
|
raise FormatError, "Missing service key" if service.nil?
|
20
26
|
raise FormatError, "Invalid service data" unless service.is_a?(Array) && service.all? { |x| x.is_a?(Hash) }
|
21
27
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
raise FormatError, "Missing
|
26
|
-
raise FormatError, "Invalid
|
27
|
-
raise FormatError, "
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
@handles = aka.map { |x| x.gsub('at://', '') }
|
38
|
-
else
|
39
|
-
@handles = []
|
40
|
-
end
|
28
|
+
@services = service.map { |x|
|
29
|
+
id, type, endpoint = x.values_at('id', 'type', 'serviceEndpoint')
|
30
|
+
|
31
|
+
raise FormatError, "Missing service id" unless id
|
32
|
+
raise FormatError, "Invalid service id: #{id.inspect}" unless id.is_a?(String) && id.start_with?('#')
|
33
|
+
raise FormatError, "Missing service type" unless type
|
34
|
+
raise FormatError, "Invalid service type: #{type.inspect}" unless type.is_a?(String)
|
35
|
+
raise FormatError, "Missing service endpoint" unless endpoint
|
36
|
+
raise FormatError, "Invalid service endpoint: #{endpoint.inspect}" unless endpoint.is_a?(String)
|
37
|
+
|
38
|
+
ServiceRecord.new(id.gsub(/^#/, ''), type, endpoint)
|
39
|
+
}
|
40
|
+
|
41
|
+
@handles = parse_also_known_as(json['alsoKnownAs'] || [])
|
41
42
|
end
|
42
43
|
|
43
44
|
def get_validated_handle
|
data/lib/didkit/plc_importer.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
require 'json'
|
2
|
-
require 'net/http'
|
3
2
|
require 'open-uri'
|
4
3
|
require 'time'
|
5
4
|
|
@@ -8,21 +7,42 @@ require_relative 'plc_operation'
|
|
8
7
|
module DIDKit
|
9
8
|
class PLCImporter
|
10
9
|
PLC_SERVICE = 'plc.directory'
|
10
|
+
MAX_PAGE = 1000
|
11
11
|
|
12
|
-
attr_accessor :ignore_errors
|
12
|
+
attr_accessor :ignore_errors, :last_date
|
13
|
+
|
14
|
+
def initialize(since: nil)
|
15
|
+
if since.to_s == 'beginning'
|
16
|
+
@last_date = nil
|
17
|
+
elsif since.is_a?(String)
|
18
|
+
@last_date = Time.parse(since)
|
19
|
+
elsif since
|
20
|
+
@last_date = since
|
21
|
+
else
|
22
|
+
@last_date = Time.now
|
23
|
+
@eof = true
|
24
|
+
end
|
13
25
|
|
14
|
-
def initialize(last_date = Time.now)
|
15
|
-
@last_date = last_date
|
16
26
|
@ignore_errors = false
|
17
27
|
end
|
18
28
|
|
19
|
-
def
|
20
|
-
|
21
|
-
|
22
|
-
|
29
|
+
def plc_service
|
30
|
+
PLC_SERVICE
|
31
|
+
end
|
32
|
+
|
33
|
+
def get_export(args = {})
|
34
|
+
url = URI("https://#{plc_service}/export")
|
35
|
+
url.query = URI.encode_www_form(args)
|
23
36
|
|
24
37
|
data = URI.open(url).read
|
25
|
-
|
38
|
+
data.lines.map(&:strip).reject(&:empty?).map { |x| JSON.parse(x) }
|
39
|
+
end
|
40
|
+
|
41
|
+
def fetch_page
|
42
|
+
request_time = Time.now
|
43
|
+
|
44
|
+
query = @last_date ? { :after => @last_date.utc.iso8601(6) } : {}
|
45
|
+
rows = get_export(query)
|
26
46
|
|
27
47
|
operations = rows.filter_map do |json|
|
28
48
|
begin
|
@@ -32,14 +52,22 @@ module DIDKit
|
|
32
52
|
end
|
33
53
|
end
|
34
54
|
|
35
|
-
|
55
|
+
@last_date = operations.last&.created_at || request_time
|
56
|
+
@eof = (rows.length < MAX_PAGE)
|
36
57
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
58
|
+
operations
|
59
|
+
end
|
60
|
+
|
61
|
+
def fetch(&block)
|
62
|
+
loop do
|
63
|
+
operations = fetch_page
|
64
|
+
block.call(operations)
|
65
|
+
break if eof?
|
42
66
|
end
|
43
67
|
end
|
68
|
+
|
69
|
+
def eof?
|
70
|
+
!!@eof
|
71
|
+
end
|
44
72
|
end
|
45
73
|
end
|
data/lib/didkit/plc_operation.rb
CHANGED
@@ -1,56 +1,57 @@
|
|
1
1
|
require 'time'
|
2
2
|
|
3
|
+
require_relative 'at_handles'
|
4
|
+
require_relative 'service_record'
|
5
|
+
require_relative 'services'
|
6
|
+
|
3
7
|
module DIDKit
|
4
8
|
class PLCOperation
|
5
9
|
class FormatError < StandardError
|
6
10
|
end
|
7
11
|
|
8
|
-
|
12
|
+
include AtHandles
|
13
|
+
include Services
|
14
|
+
|
15
|
+
attr_reader :json, :did, :created_at, :type, :handles, :services
|
9
16
|
|
10
17
|
def initialize(json)
|
18
|
+
@json = json
|
11
19
|
@did = json['did']
|
12
|
-
raise FormatError, "Missing DID" if @did.nil?
|
13
|
-
raise FormatError, "Invalid DID" unless @did.is_a?(String) && @did.start_with?('did:')
|
20
|
+
raise FormatError, "Missing DID: #{json}" if @did.nil?
|
21
|
+
raise FormatError, "Invalid DID: #{@did}" unless @did.is_a?(String) && @did.start_with?('did:')
|
14
22
|
|
15
23
|
timestamp = json['createdAt']
|
16
|
-
raise FormatError, "Missing createdAt" if timestamp.nil?
|
17
|
-
raise FormatError, "Invalid createdAt" unless timestamp.is_a?(String)
|
24
|
+
raise FormatError, "Missing createdAt: #{json}" if timestamp.nil?
|
25
|
+
raise FormatError, "Invalid createdAt: #{timestamp.inspect}" unless timestamp.is_a?(String)
|
18
26
|
|
19
27
|
@created_at = Time.parse(timestamp)
|
20
28
|
|
21
29
|
operation = json['operation']
|
22
|
-
raise FormatError, "Missing operation key" if operation.nil?
|
23
|
-
raise FormatError, "Invalid operation data" unless operation.is_a?(Hash)
|
30
|
+
raise FormatError, "Missing operation key: #{json}" if operation.nil?
|
31
|
+
raise FormatError, "Invalid operation data: #{operation.inspect}" unless operation.is_a?(Hash)
|
24
32
|
|
25
33
|
type = operation['type']
|
26
|
-
raise FormatError, "Missing type" if type.nil?
|
34
|
+
raise FormatError, "Missing operation type: #{json}" if type.nil?
|
27
35
|
|
28
36
|
@type = type.to_sym
|
29
37
|
return unless @type == :plc_operation
|
30
38
|
|
31
39
|
services = operation['services']
|
32
|
-
raise FormatError, "Missing services key" if services.nil?
|
33
|
-
raise FormatError, "Invalid services data" unless services.is_a?(Hash)
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
raise FormatError, "
|
39
|
-
raise FormatError, "
|
40
|
-
raise FormatError, "
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
raise FormatError, "Invalid alsoKnownAs" unless aka.all? { |x| x.is_a?(String) }
|
48
|
-
raise FormatError, "Invalid alsoKnownAs" unless aka.all? { |x| x =~ %r(\Aat://[^/]+\z) }
|
49
|
-
|
50
|
-
@handles = aka.map { |x| x.gsub('at://', '') }
|
51
|
-
else
|
52
|
-
@handles = []
|
53
|
-
end
|
40
|
+
raise FormatError, "Missing services key: #{json}" if services.nil?
|
41
|
+
raise FormatError, "Invalid services data: #{services}" unless services.is_a?(Hash)
|
42
|
+
|
43
|
+
@services = services.map { |k, x|
|
44
|
+
type, endpoint = x.values_at('type', 'endpoint')
|
45
|
+
|
46
|
+
raise FormatError, "Missing service type" unless type
|
47
|
+
raise FormatError, "Invalid service type: #{type.inspect}" unless type.is_a?(String)
|
48
|
+
raise FormatError, "Missing service endpoint" unless endpoint
|
49
|
+
raise FormatError, "Invalid service endpoint: #{endpoint.inspect}" unless endpoint.is_a?(String)
|
50
|
+
|
51
|
+
ServiceRecord.new(k, type, endpoint)
|
52
|
+
}
|
53
|
+
|
54
|
+
@handles = parse_also_known_as(operation['alsoKnownAs'] || [])
|
54
55
|
end
|
55
56
|
end
|
56
57
|
end
|
data/lib/didkit/resolver.rb
CHANGED
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'uri'
|
2
|
+
require_relative 'errors'
|
3
|
+
|
4
|
+
module DIDKit
|
5
|
+
class ServiceRecord
|
6
|
+
attr_reader :key, :type, :endpoint
|
7
|
+
|
8
|
+
def initialize(key, type, endpoint)
|
9
|
+
begin
|
10
|
+
uri = URI(endpoint)
|
11
|
+
rescue URI::Error
|
12
|
+
raise FormatError, "Invalid service endpoint: #{endpoint.inspect}"
|
13
|
+
end
|
14
|
+
|
15
|
+
@key = key
|
16
|
+
@type = type
|
17
|
+
@endpoint = endpoint
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module DIDKit
|
2
|
+
module Services
|
3
|
+
def get_service(key, type)
|
4
|
+
@services&.detect { |s| s.key == key && s.type == type }
|
5
|
+
end
|
6
|
+
|
7
|
+
def pds_endpoint
|
8
|
+
@pds_endpoint ||= get_service('atproto_pds', 'AtprotoPersonalDataServer')&.endpoint
|
9
|
+
end
|
10
|
+
|
11
|
+
def labeler_endpoint
|
12
|
+
@labeler_endpoint ||= get_service('atproto_labeler', 'AtprotoLabeler')&.endpoint
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
data/lib/didkit/version.rb
CHANGED
data/lib/didkit.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: didkit
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kuba Suder
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-03-
|
11
|
+
date: 2024-03-19 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description:
|
14
14
|
email:
|
@@ -21,12 +21,15 @@ files:
|
|
21
21
|
- LICENSE.txt
|
22
22
|
- README.md
|
23
23
|
- lib/didkit.rb
|
24
|
+
- lib/didkit/at_handles.rb
|
24
25
|
- lib/didkit/did.rb
|
25
26
|
- lib/didkit/document.rb
|
26
27
|
- lib/didkit/errors.rb
|
27
28
|
- lib/didkit/plc_importer.rb
|
28
29
|
- lib/didkit/plc_operation.rb
|
29
30
|
- lib/didkit/resolver.rb
|
31
|
+
- lib/didkit/service_record.rb
|
32
|
+
- lib/didkit/services.rb
|
30
33
|
- lib/didkit/version.rb
|
31
34
|
- sig/didkit.rbs
|
32
35
|
homepage: https://github.com/mackuba/didkit
|