diaspora_federation 0.0.8 → 0.0.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +3 -1
  3. data/lib/diaspora_federation.rb +66 -1
  4. data/lib/diaspora_federation/discovery/h_card.rb +2 -3
  5. data/lib/diaspora_federation/discovery/web_finger.rb +3 -6
  6. data/lib/diaspora_federation/entities.rb +18 -0
  7. data/lib/diaspora_federation/entities/account_deletion.rb +14 -0
  8. data/lib/diaspora_federation/entities/comment.rb +26 -0
  9. data/lib/diaspora_federation/entities/conversation.rb +38 -0
  10. data/lib/diaspora_federation/entities/like.rb +35 -0
  11. data/lib/diaspora_federation/entities/location.rb +23 -0
  12. data/lib/diaspora_federation/entities/message.rb +38 -0
  13. data/lib/diaspora_federation/entities/participation.rb +28 -0
  14. data/lib/diaspora_federation/entities/person.rb +6 -3
  15. data/lib/diaspora_federation/entities/photo.rb +59 -0
  16. data/lib/diaspora_federation/entities/poll.rb +24 -0
  17. data/lib/diaspora_federation/entities/poll_answer.rb +19 -0
  18. data/lib/diaspora_federation/entities/poll_participation.rb +28 -0
  19. data/lib/diaspora_federation/entities/profile.rb +10 -8
  20. data/lib/diaspora_federation/entities/relayable.rb +101 -0
  21. data/lib/diaspora_federation/entities/relayable_retraction.rb +95 -0
  22. data/lib/diaspora_federation/entities/request.rb +21 -0
  23. data/lib/diaspora_federation/entities/reshare.rb +49 -0
  24. data/lib/diaspora_federation/entities/retraction.rb +24 -0
  25. data/lib/diaspora_federation/entities/signed_retraction.rb +66 -0
  26. data/lib/diaspora_federation/entities/status_message.rb +55 -0
  27. data/lib/diaspora_federation/entity.rb +5 -6
  28. data/lib/diaspora_federation/fetcher.rb +1 -2
  29. data/lib/diaspora_federation/properties_dsl.rb +18 -8
  30. data/lib/diaspora_federation/salmon.rb +17 -0
  31. data/lib/diaspora_federation/salmon/aes.rb +58 -0
  32. data/lib/diaspora_federation/salmon/encrypted_slap.rb +187 -0
  33. data/lib/diaspora_federation/salmon/exceptions.rb +50 -0
  34. data/lib/diaspora_federation/salmon/magic_envelope.rb +191 -0
  35. data/lib/diaspora_federation/salmon/slap.rb +128 -0
  36. data/lib/diaspora_federation/salmon/xml_payload.rb +158 -0
  37. data/lib/diaspora_federation/signing.rb +56 -0
  38. data/lib/diaspora_federation/validators.rb +20 -0
  39. data/lib/diaspora_federation/validators/account_deletion_validator.rb +10 -0
  40. data/lib/diaspora_federation/validators/comment_validator.rb +17 -0
  41. data/lib/diaspora_federation/validators/conversation_validator.rb +14 -0
  42. data/lib/diaspora_federation/validators/like_validator.rb +14 -0
  43. data/lib/diaspora_federation/validators/location_validator.rb +11 -0
  44. data/lib/diaspora_federation/validators/message_validator.rb +16 -0
  45. data/lib/diaspora_federation/validators/participation_validator.rb +16 -0
  46. data/lib/diaspora_federation/validators/photo_validator.rb +24 -0
  47. data/lib/diaspora_federation/validators/poll_answer_validator.rb +11 -0
  48. data/lib/diaspora_federation/validators/poll_participation_validator.rb +16 -0
  49. data/lib/diaspora_federation/validators/poll_validator.rb +11 -0
  50. data/lib/diaspora_federation/validators/relayable_retraction_validator.rb +15 -0
  51. data/lib/diaspora_federation/validators/relayable_validator.rb +14 -0
  52. data/lib/diaspora_federation/validators/request_validator.rb +11 -0
  53. data/lib/diaspora_federation/validators/reshare_validator.rb +18 -0
  54. data/lib/diaspora_federation/validators/retraction_validator.rb +14 -0
  55. data/lib/diaspora_federation/validators/rules/diaspora_id_count.rb +37 -0
  56. data/lib/diaspora_federation/validators/signed_retraction_validator.rb +15 -0
  57. data/lib/diaspora_federation/validators/status_message_validator.rb +14 -0
  58. data/lib/diaspora_federation/version.rb +1 -1
  59. metadata +49 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4c58b6c0d7617af4b0553b67d89ab34de553559b
4
- data.tar.gz: 1954af247aa2309fbf3abb137ef42056f249747b
3
+ metadata.gz: f1cc502235f056676364d5b56b814650f284c8e5
4
+ data.tar.gz: 2b031425ffe4b1b5d83ac789ee674dc0f31f423a
5
5
  SHA512:
6
- metadata.gz: a6d293bb5e33dbce5549eee3b89165e45f4f556825d9dc2cd5366c8e5a616eda8ea80d780e3b273a0cd66348ea8b517e40196612e086ff8f68d65170d8f6028a
7
- data.tar.gz: 9205d8677d54083e4fdc0cb9c988271b97715b01d58453c7c59a139d9cc3e3661e36940b07333c29f88915a3ce7ba8000f3edd6811b5fe3cad2fcb8991643d3f
6
+ metadata.gz: 0f4691907170170b696306f6c65cfc2855e9b95b166850f1c72c5f96fdbe6657c0cf31cb6b8ab3cf55369da424103388d0e24be445e34cf61daaa1b2ad1a187a
7
+ data.tar.gz: 12e1dde41d27bd0ee229a2befd99a6d6329bd7aca49f822e3d29c0a79e6135892238672321cdf1ad64813b78e441552fc318733729415f32c1f0983b42c4a4b8
data/README.md CHANGED
@@ -2,7 +2,9 @@
2
2
 
3
3
  **A library that provides functionalities needed for the diaspora* federation protocol**
4
4
 
5
- [![Build Status](https://travis-ci.org/SuperTux88/diaspora_federation.svg?branch=master)](https://travis-ci.org/SuperTux88/diaspora_federation)
5
+ **master:** [![Build Status master](https://travis-ci.org/SuperTux88/diaspora_federation.svg?branch=master)](https://travis-ci.org/SuperTux88/diaspora_federation)
6
+ **develop:** [![Build Status develop](https://travis-ci.org/SuperTux88/diaspora_federation.svg?branch=develop)](https://travis-ci.org/SuperTux88/diaspora_federation)
7
+
6
8
  [![Code Climate](https://codeclimate.com/github/SuperTux88/diaspora_federation/badges/gpa.svg)](https://codeclimate.com/github/SuperTux88/diaspora_federation)
7
9
  [![Test Coverage](https://codeclimate.com/github/SuperTux88/diaspora_federation/badges/coverage.svg)](https://codeclimate.com/github/SuperTux88/diaspora_federation/coverage)
8
10
  [![Dependency Status](https://gemnasium.com/SuperTux88/diaspora_federation.svg)](https://gemnasium.com/SuperTux88/diaspora_federation)
@@ -7,9 +7,11 @@ require "diaspora_federation/validators"
7
7
 
8
8
  require "diaspora_federation/fetcher"
9
9
 
10
+ require "diaspora_federation/signing"
10
11
  require "diaspora_federation/entities"
11
12
 
12
13
  require "diaspora_federation/discovery"
14
+ require "diaspora_federation/salmon"
13
15
 
14
16
  # diaspora* federation library
15
17
  module DiasporaFederation
@@ -19,13 +21,18 @@ module DiasporaFederation
19
21
  fetch_person_for_webfinger
20
22
  fetch_person_for_hcard
21
23
  save_person_after_webfinger
24
+ fetch_private_key_by_diaspora_id
25
+ fetch_author_private_key_by_entity_guid
26
+ fetch_public_key_by_diaspora_id
27
+ fetch_author_public_key_by_entity_guid
28
+ entity_author_is_local?
29
+ fetch_entity_author_id_by_guid
22
30
  )
23
31
 
24
32
  class << self
25
33
  # {Callbacks} instance with defined callbacks
26
34
  # @see Callbacks#on
27
35
  # @see Callbacks#trigger
28
- #
29
36
  attr_reader :callbacks
30
37
 
31
38
  # the pod url
@@ -58,6 +65,64 @@ module DiasporaFederation
58
65
 
59
66
  # define the callbacks
60
67
  #
68
+ # In order to communicate with the application which uses the diaspora_federation gem
69
+ # callbacks are introduced. The callbacks are used for getting required data from the
70
+ # application or posting data to the application.
71
+ #
72
+ # Callbacks are implemented at the application side and must follow these specifications:
73
+ #
74
+ # fetch_person_for_webfinger
75
+ # Fetches person data from the application to form a WebFinger reply
76
+ # @param [String] Diaspora ID of the person
77
+ # @return [DiasporaFederation::Discovery::WebFinger] person webfinger data
78
+ #
79
+ # fetch_person_for_hcard
80
+ # Fetches person data from the application to reply for an HCard query
81
+ # @param [String] guid of the person
82
+ # @return [DiasporaFederation::Discovery::HCard] person hcard data
83
+ #
84
+ # save_person_after_webfinger
85
+ # After the gem had made a person discovery using WebFinger it calls this callback
86
+ # so the application saves the person data
87
+ # @param [DiasporaFederation::Entities::Person] person data
88
+ #
89
+ # fetch_private_key_by_diaspora_id
90
+ # Fetches a private key of a person by her Diaspora ID from the application
91
+ # @param [String] Diaspora ID of the person
92
+ # @return [OpenSSL::PKey::RSA] key
93
+ #
94
+ # fetch_author_private_key_by_entity_guid
95
+ # Fetches a private key of the person who authored an entity identified by a given guid
96
+ # @param [String] entity type (Post, Comment, Like, etc)
97
+ # @param [String] guid of the entity
98
+ # @return [OpenSSL::PKey::RSA] key
99
+ #
100
+ # fetch_public_key_by_diaspora_id
101
+ # Fetches a public key of a person by her Diaspora ID from the application
102
+ # @param [String] Diaspora ID of the person
103
+ # @return [OpenSSL::PKey::RSA] key
104
+ #
105
+ # fetch_author_public_key_by_entity_guid
106
+ # Fetches a public key of the person who authored an entity identified by a given guid
107
+ # @param [String] entity type (Post, Comment, Like, etc)
108
+ # @param [String] guid of the entity
109
+ # @return [OpenSSL::PKey::RSA] key
110
+ #
111
+ # entity_author_is_local?
112
+ # Reports if the author of the entity identified by a given guid is local on the pod
113
+ # where we operate.
114
+ # @param [String] entity type (Post, Comment, Like, etc)
115
+ # @param [String] guid of the entity
116
+ # @return [Boolean]
117
+ #
118
+ # fetch_entity_author_id_by_guid
119
+ # Fetches Diaspora ID of the person who authored the entity identified by a given guid
120
+ # @param [String] entity type (Post, Comment, Like, etc)
121
+ # @param [String] guid of the entity
122
+ # @return [String] Diaspora ID of the person
123
+ #
124
+ # @see Callbacks#on
125
+ #
61
126
  # @example
62
127
  # config.define_callbacks do
63
128
  # on :some_event do |arg1|
@@ -41,14 +41,13 @@ module DiasporaFederation
41
41
  # @see http://www.ietf.org/rfc/rfc6350.txt "vCard Format Specification"
42
42
  class HCard < Entity
43
43
  # @!attribute [r] guid
44
- # This is just the guid. When a user creates an account on a pod, the pod
45
- # MUST assign them a guid - a random hexadecimal string of at least 8
46
- # hexadecimal digits.
44
+ # @see Entities::Person#guid
47
45
  # @return [String] guid
48
46
  property :guid
49
47
 
50
48
  # @!attribute [r] nickname
51
49
  # the first part of the diaspora ID
50
+ # @see Entities::Person#diaspora_id
52
51
  # @return [String] nickname
53
52
  property :nickname
54
53
 
@@ -81,10 +81,7 @@ module DiasporaFederation
81
81
  # specification (will affect older Diaspora* installations).
82
82
  #
83
83
  # @see HCard#guid
84
- #
85
- # This is just the guid. When a user creates an account on a pod, the pod
86
- # MUST assign them a guid - a random hexadecimal string of at least 8
87
- # hexadecimal digits.
84
+ # @see Entities::Person#guid
88
85
  # @return [String] guid
89
86
  property :guid
90
87
 
@@ -93,7 +90,7 @@ module DiasporaFederation
93
90
  # +hCard+, which actually has fields for an +KEY+ defined in the +vCard+
94
91
  # specification (will affect older Diaspora* installations).
95
92
  #
96
- # @see HCard#pubkey
93
+ # @see HCard#public_key
97
94
  #
98
95
  # When a user is created on the pod, the pod MUST generate a pgp keypair
99
96
  # for them. This key is used for signing messages. The format is a
@@ -152,7 +149,7 @@ module DiasporaFederation
152
149
  links = data[:links]
153
150
 
154
151
  # TODO: remove! public key is deprecated in webfinger
155
- public_key = parse_link(links, REL_PUBKEY)
152
+ public_key = parse_link(links, REL_PUBKEY)
156
153
 
157
154
  new(
158
155
  acct_uri: data[:subject],
@@ -8,5 +8,23 @@ module DiasporaFederation
8
8
  end
9
9
  end
10
10
 
11
+ require "diaspora_federation/entities/relayable"
11
12
  require "diaspora_federation/entities/profile"
12
13
  require "diaspora_federation/entities/person"
14
+ require "diaspora_federation/entities/location"
15
+ require "diaspora_federation/entities/photo"
16
+ require "diaspora_federation/entities/poll_answer"
17
+ require "diaspora_federation/entities/poll"
18
+ require "diaspora_federation/entities/status_message"
19
+ require "diaspora_federation/entities/request"
20
+ require "diaspora_federation/entities/participation"
21
+ require "diaspora_federation/entities/like"
22
+ require "diaspora_federation/entities/comment"
23
+ require "diaspora_federation/entities/account_deletion"
24
+ require "diaspora_federation/entities/message"
25
+ require "diaspora_federation/entities/conversation"
26
+ require "diaspora_federation/entities/relayable_retraction"
27
+ require "diaspora_federation/entities/reshare"
28
+ require "diaspora_federation/entities/retraction"
29
+ require "diaspora_federation/entities/signed_retraction"
30
+ require "diaspora_federation/entities/poll_participation"
@@ -0,0 +1,14 @@
1
+ module DiasporaFederation
2
+ module Entities
3
+ # this entity is sent when account was deleted on a remote pod
4
+ #
5
+ # @see Validators::AccountDeletionValidator
6
+ class AccountDeletion < Entity
7
+ # @!attribute [r] diaspora_id
8
+ # The diaspora ID of the deleted account
9
+ # @see Person#diaspora_id
10
+ # @return [String] diaspora ID
11
+ property :diaspora_id, xml_name: :diaspora_handle
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,26 @@
1
+ module DiasporaFederation
2
+ module Entities
3
+ # this entity represents a comment to some kind of post (e.g. status message)
4
+ #
5
+ # @see Validators::CommentValidator
6
+ class Comment < Entity
7
+ # @!attribute [r] guid
8
+ # a random string of at least 16 chars.
9
+ # @see Validation::Rule::Guid
10
+ # @return [String] comment guid
11
+ property :guid
12
+
13
+ include Relayable
14
+
15
+ # @!attribute [r] text
16
+ # @return [String] the comment text
17
+ property :text
18
+
19
+ # @!attribute [r] diaspora_id
20
+ # The diaspora ID of the author.
21
+ # @see Person#diaspora_id
22
+ # @return [String] diaspora ID
23
+ property :diaspora_id, xml_name: :diaspora_handle
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,38 @@
1
+ module DiasporaFederation
2
+ module Entities
3
+ # this entity represents a private conversation between users
4
+ #
5
+ # @see Validators::ConversationValidator
6
+ class Conversation < Entity
7
+ # @!attribute [r] guid
8
+ # a random string of at least 16 chars.
9
+ # @see Validation::Rule::Guid
10
+ # @return [String] conversation guid
11
+ property :guid
12
+
13
+ # @!attribute [r] subject
14
+ # @return [String] the conversation subject
15
+ property :subject
16
+
17
+ # @!attribute [r] created_at
18
+ # @return [Time] Conversation creation time
19
+ property :created_at, default: -> { Time.now.utc }
20
+
21
+ # @!attribute [r] messages
22
+ # @return [[Entities::Message]] Messages of this conversation
23
+ entity :messages, [Entities::Message]
24
+
25
+ # @!attribute [r] diaspora_id
26
+ # The diaspora ID of the person initiated the conversation.
27
+ # @see Person#diaspora_id
28
+ # @return [String] diaspora ID
29
+ property :diaspora_id, xml_name: :diaspora_handle
30
+
31
+ # @!attribute [r] participant_ids
32
+ # The diaspora IDs of the persons participating the conversation separated by ";".
33
+ # @see Person#diaspora_id
34
+ # @return [String] participants diaspora IDs
35
+ property :participant_ids, xml_name: :participant_handles
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,35 @@
1
+ module DiasporaFederation
2
+ module Entities
3
+ # this entity represents a like to some kind of post (e.g. status message)
4
+ #
5
+ # @see Validators::LikeValidator
6
+ class Like < Entity
7
+ # @!attribute [r] positive
8
+ # If +true+ set a like, if +false+, set a dislike (dislikes are currently not
9
+ # implemented in the Diaspora frontend).
10
+ # @return [Boolean] is it a like or a dislike
11
+ property :positive
12
+
13
+ # @!attribute [r] guid
14
+ # a random string of at least 16 chars.
15
+ # @see Validation::Rule::Guid
16
+ # @return [String] like guid
17
+ property :guid
18
+
19
+ # @!attribute [r] target_type
20
+ # A string describing the type of the target.
21
+ # Can be "Post" or "Comment" (Comments are currently not implemented in the
22
+ # Diaspora Frontend).
23
+ # @return [String] target type
24
+ property :target_type
25
+
26
+ include Relayable
27
+
28
+ # @!attribute [r] diaspora_id
29
+ # The diaspora ID of the person who posts a like
30
+ # @see Person#diaspora_id
31
+ # @return [String] diaspora ID
32
+ property :diaspora_id, xml_name: :diaspora_handle
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,23 @@
1
+ module DiasporaFederation
2
+ module Entities
3
+ # this entity is used to specify a location data and used embedded in a status message
4
+ #
5
+ # @see Validators::LocationValidator
6
+ class Location < Entity
7
+ # @!attribute [r] address
8
+ # A string describing your location, e.g. a city name, a street name, etc
9
+ # @return [String] address
10
+ property :address
11
+
12
+ # @!attribute [r] lat
13
+ # Geographical latitude of your location
14
+ # @return [String] latitude
15
+ property :lat
16
+
17
+ # @!attribute [r] lng
18
+ # Geographical longitude of your location
19
+ # @return [String] longitude
20
+ property :lng
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,38 @@
1
+ module DiasporaFederation
2
+ module Entities
3
+ # this entity represents a private message exchanged in private conversation
4
+ #
5
+ # @see Validators::MessageValidator
6
+ class Message < Entity
7
+ # @!attribute [r] guid
8
+ # a random string of at least 16 chars.
9
+ # @see Validation::Rule::Guid
10
+ # @return [String] message guid
11
+ property :guid
12
+
13
+ include Relayable
14
+
15
+ # @!attribute [r] text
16
+ # text of the message composed by a user
17
+ # @return [String] text
18
+ property :text
19
+
20
+ # @!attribute [r] created_at
21
+ # message creation time
22
+ # @return [Time] creation time
23
+ property :created_at, default: -> { Time.now.utc }
24
+
25
+ # @!attribute [r] diaspora_id
26
+ # The diaspora ID of the message author.
27
+ # @see Person#diaspora_id
28
+ # @return [String] diaspora ID
29
+ property :diaspora_id, xml_name: :diaspora_handle
30
+
31
+ # @!attribute [r] conversation_guid
32
+ # guid of a conversation this message belongs to
33
+ # @see Conversation#guid
34
+ # @return [String] conversation guid
35
+ property :conversation_guid
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,28 @@
1
+ module DiasporaFederation
2
+ module Entities
3
+ # participation is sent to subscribe a user on updates for some post
4
+ #
5
+ # @see Validators::Participation
6
+ class Participation < Entity
7
+ # @!attribute [r] guid
8
+ # a random string of at least 16 chars.
9
+ # @see Validation::Rule::Guid
10
+ # @return [String] participation guid
11
+ property :guid
12
+
13
+ # @!attribute [r] target_type
14
+ # a string describing a type of the target to subscribe on.
15
+ # currently only "Post" is supported.
16
+ # @return [String] target type
17
+ property :target_type
18
+
19
+ include Relayable
20
+
21
+ # @!attribute [r] diaspora_id
22
+ # The diaspora ID of the person who subscribes on a post
23
+ # @see Person#diaspora_id
24
+ # @return [String] diaspora ID
25
+ property :diaspora_id, xml_name: :diaspora_handle
26
+ end
27
+ end
28
+ end
@@ -5,17 +5,20 @@ module DiasporaFederation
5
5
  # @see Validators::PersonValidator
6
6
  class Person < Entity
7
7
  # @!attribute [r] guid
8
- # @see HCard#guid
8
+ # This is just the guid. When a user creates an account on a pod, the pod
9
+ # MUST assign them a guid - a random string of at least 16 chars.
10
+ # @see Validation::Rule::Guid
9
11
  # @return [String] guid
10
12
  property :guid
11
13
 
12
14
  # @!attribute [r] diaspora_id
13
15
  # The diaspora ID of the person
16
+ # @see Validation::Rule::DiasporaId
14
17
  # @return [String] diaspora ID
15
18
  property :diaspora_id, xml_name: :diaspora_handle
16
19
 
17
20
  # @!attribute [r] url
18
- # @see WebFinger#seed_url
21
+ # @see Discovery::WebFinger#seed_url
19
22
  # @return [String] link to the pod
20
23
  property :url
21
24
 
@@ -25,7 +28,7 @@ module DiasporaFederation
25
28
  entity :profile, Entities::Profile
26
29
 
27
30
  # @!attribute [r] exported_key
28
- # @see HCard#public_key
31
+ # @see Discovery::HCard#public_key
29
32
  # @return [String] public key
30
33
  property :exported_key
31
34
  end
@@ -0,0 +1,59 @@
1
+ module DiasporaFederation
2
+ module Entities
3
+ # this entity represents photo and it is federated as a part of a status message
4
+ #
5
+ # @see Validators::PhotoValidator
6
+ class Photo < Entity
7
+ # @!attribute [r] guid
8
+ # a random string of at least 16 chars.
9
+ # @see Validation::Rule::Guid
10
+ # @return [String] guid
11
+ property :guid
12
+
13
+ # @!attribute [r] diaspora_id
14
+ # The diaspora ID of the person who uploaded the photo
15
+ # @see Person#diaspora_id
16
+ # @return [String] author diaspora ID
17
+ property :diaspora_id, xml_name: :diaspora_handle
18
+
19
+ # @!attribute [r] public
20
+ # Points if the photo is visible to everyone or only to some aspects
21
+ # @return [Boolean] is it public
22
+ property :public, default: false
23
+
24
+ # @!attribute [r] created_at
25
+ # photo entity creation time
26
+ # @return [Time] creation time
27
+ property :created_at, default: -> { Time.now.utc }
28
+
29
+ # @!attribute [r] remote_photo_path
30
+ # an url of the photo on a remote server
31
+ # @return [String] remote photo url
32
+ property :remote_photo_path
33
+
34
+ # @!attribute [r] remote_photo_name
35
+ # @return [String] remote photo name
36
+ property :remote_photo_name
37
+
38
+ # @!attribute [r] text
39
+ # @return [String] text
40
+ property :text, default: nil
41
+
42
+ # @!attribute [r] status_message_guid
43
+ # guid of a status message this message belongs to
44
+ # @see StatusMessage#guid
45
+ # @return [String] guid
46
+ property :status_message_guid
47
+
48
+ # @!attribute [r] height
49
+ # photo height
50
+ # @return [String] height
51
+ property :height
52
+
53
+ # @!attribute [r] width
54
+ # photo width
55
+ # @return [String] width
56
+ property :width
57
+ end
58
+ end
59
+ end