podio 0.6.0 → 0.7.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.
Files changed (37) hide show
  1. data/.travis.yml +4 -0
  2. data/LICENSE +1 -1
  3. data/lib/podio.rb +7 -3
  4. data/lib/podio/active_podio/base.rb +121 -54
  5. data/lib/podio/client.rb +15 -2
  6. data/lib/podio/error.rb +1 -0
  7. data/lib/podio/middleware/error_response.rb +2 -0
  8. data/lib/podio/models/app_store_share.rb +8 -4
  9. data/lib/podio/models/application.rb +4 -0
  10. data/lib/podio/models/{calendar.rb → calendar_event.rb} +13 -1
  11. data/lib/podio/models/contact.rb +1 -0
  12. data/lib/podio/models/contract.rb +17 -1
  13. data/lib/podio/models/email_subscription_setting.rb +1 -0
  14. data/lib/podio/models/external_file.rb +30 -0
  15. data/lib/podio/models/file_attachment.rb +30 -12
  16. data/lib/podio/models/filter.rb +33 -2
  17. data/lib/podio/models/item.rb +23 -0
  18. data/lib/podio/models/item_field.rb +1 -1
  19. data/lib/podio/models/linked_account.rb +32 -0
  20. data/lib/podio/models/meeting.rb +55 -30
  21. data/lib/podio/models/meeting_participiant.rb +10 -4
  22. data/lib/podio/models/notification_group.rb +3 -4
  23. data/lib/podio/models/organization.rb +11 -9
  24. data/lib/podio/models/organization_member.rb +2 -1
  25. data/lib/podio/models/organization_profile.rb +1 -0
  26. data/lib/podio/models/question_answer.rb +3 -2
  27. data/lib/podio/models/referral.rb +25 -0
  28. data/lib/podio/models/reminder.rb +2 -2
  29. data/lib/podio/models/search.rb +34 -5
  30. data/lib/podio/models/space_invitation.rb +9 -4
  31. data/lib/podio/models/space_member.rb +8 -0
  32. data/lib/podio/models/subscription.rb +7 -3
  33. data/lib/podio/models/user_status.rb +2 -1
  34. data/lib/podio/models/widget.rb +2 -0
  35. data/lib/podio/version.rb +1 -1
  36. data/test/active_podio_test.rb +2 -2
  37. metadata +14 -11
@@ -72,10 +72,23 @@ module Podio
72
72
  @oauth_token
73
73
  end
74
74
 
75
+ # Sign in with SSO
76
+ def authenticate_with_sso(attributes)
77
+ response = @oauth_connection.post do |req|
78
+ req.url '/oauth/token', :grant_type => 'sso', :client_id => api_key, :client_secret => api_secret
79
+ req.body = attributes
80
+ end
81
+
82
+ @oauth_token = OAuthToken.new(response.body)
83
+ configure_oauth
84
+
85
+ [@oauth_token, response['new_user_created']]
86
+ end
87
+
75
88
  # Sign in with an OpenID, only available for Podio
76
- def authenticate_with_openid(identifier)
89
+ def authenticate_with_openid(identifier, type)
77
90
  response = @oauth_connection.post do |req|
78
- req.url '/oauth/token_by_openid', :grant_type => 'openid', :client_id => api_key, :client_secret => api_secret, :identifier => identifier
91
+ req.url '/oauth/token_by_openid', :grant_type => type, :client_id => api_key, :client_secret => api_secret, :identifier => identifier
79
92
  end
80
93
 
81
94
  @oauth_token = OAuthToken.new(response.body)
@@ -17,5 +17,6 @@ module Podio
17
17
  class NotFoundError < PodioError; end
18
18
  class ConflictError < PodioError; end
19
19
  class GoneError < PodioError; end
20
+ class RateLimitError < PodioError; end
20
21
  class UnavailableError < PodioError; end
21
22
  end
@@ -27,6 +27,8 @@ module Podio
27
27
  raise ConflictError.new(env[:body], env[:status], env[:url])
28
28
  when 410
29
29
  raise GoneError.new(env[:body], env[:status], env[:url])
30
+ when 420
31
+ raise RateLimitError.new(env[:body], env[:status], env[:url])
30
32
  when 500
31
33
  raise ServerError.new(env[:body], env[:status], env[:url])
32
34
  when 502, 503
@@ -21,11 +21,11 @@ class Podio::AppStoreShare < ActivePodio::Base
21
21
  property :ratings, :hash
22
22
  property :user_rating, :array
23
23
  property :screenshots, :array
24
- property :info, :hash
25
-
24
+ property :video, :string
25
+
26
26
  has_many :children, :class => 'AppStoreShare'
27
27
  has_one :author, :class => 'ByLine'
28
-
28
+
29
29
  alias_method :id, :share_id
30
30
 
31
31
  def create
@@ -37,7 +37,11 @@ class Podio::AppStoreShare < ActivePodio::Base
37
37
  end
38
38
 
39
39
  handle_api_errors_for :create, :install # Call must be made after the methods to handle have been defined
40
-
40
+
41
+ def api_friendly_ref_type
42
+ 'share'
43
+ end
44
+
41
45
  class << self
42
46
  def create(attributes)
43
47
  response = Podio.connection.post do |req|
@@ -107,5 +107,9 @@ class Podio::Application < ActivePodio::Base
107
107
  def delete(id)
108
108
  Podio.connection.delete("/app/#{id}").body
109
109
  end
110
+
111
+ def install_on_mobile(id)
112
+ Podio.connection.post("/mobile/install_app/#{id}").body
113
+ end
110
114
  end
111
115
  end
@@ -1,4 +1,4 @@
1
- class Podio::Calendar < ActivePodio::Base
1
+ class Podio::CalendarEvent < ActivePodio::Base
2
2
  property :type, :string
3
3
  property :id, :integer
4
4
  property :group, :string
@@ -13,6 +13,18 @@ class Podio::Calendar < ActivePodio::Base
13
13
 
14
14
  class << self
15
15
 
16
+ def find_all(options = {})
17
+ list Podio.connection.get { |req|
18
+ req.url('/calendar/', options)
19
+ }.body
20
+ end
21
+
22
+ def find_all_for_space(space_id, options={})
23
+ list Podio.connection.get { |req|
24
+ req.url("/calendar/space/#{space_id}/", options)
25
+ }.body
26
+ end
27
+
16
28
  def find_summary
17
29
  response = Podio.connection.get("/calendar/summary").body
18
30
  response['today']['events'] = list(response['today']['events'])
@@ -8,6 +8,7 @@ class Podio::Contact < Podio::Profile
8
8
  property :type, :string # user, space, connection - blank probably means it's a real user / Podio member
9
9
  property :link, :string
10
10
  property :last_seen_on, :datetime
11
+ property :rights, :array
11
12
 
12
13
  alias_method :id, :user_id
13
14
 
@@ -19,6 +19,8 @@ class Podio::Contract < ActivePodio::Base
19
19
  property :next_period_end, :datetime, :convert_timezone => false
20
20
  property :invoice_interval, :integer
21
21
  property :invoicing_mode, :string
22
+ property :ended_reason, :string
23
+ property :ended_comment, :string
22
24
 
23
25
  has_one :org, :class => 'Organization'
24
26
  has_one :user, :class => 'User'
@@ -37,6 +39,7 @@ class Podio::Contract < ActivePodio::Base
37
39
 
38
40
  def calculate_price
39
41
  pricing = self.class.calculate_price(self.contract_id, self.attributes.slice(:full, :premium_emp_network, :premium_space_ids))
42
+ self.clear_price
40
43
  self["price"] = pricing
41
44
  end
42
45
 
@@ -48,7 +51,11 @@ class Podio::Contract < ActivePodio::Base
48
51
  self.class.delete(self.id)
49
52
  end
50
53
 
51
- handle_api_errors_for :update, :delete, :create_payment # Call must be made after the methods to handle have been defined
54
+ def end(attributes)
55
+ self.class.end(self.id, attributes)
56
+ end
57
+
58
+ handle_api_errors_for :update, :delete, :create_payment, :end # Call must be made after the methods to handle have been defined
52
59
 
53
60
  class << self
54
61
  def find(contract_id)
@@ -88,6 +95,15 @@ class Podio::Contract < ActivePodio::Base
88
95
  Podio.connection.post("/contract/#{contract_id}/start").body
89
96
  end
90
97
 
98
+ def end(contract_id, attributes)
99
+ response = Podio.connection.post do |req|
100
+ req.url "/contract/#{contract_id}/end"
101
+ req.body = attributes
102
+ end
103
+
104
+ response.body
105
+ end
106
+
91
107
  def delete(id)
92
108
  Podio.connection.delete("/contract/#{id}").body
93
109
  end
@@ -5,6 +5,7 @@ class Podio::EmailSubscriptionSetting < ActivePodio::Base
5
5
  property :bulletin, :boolean
6
6
  property :reference, :boolean
7
7
  property :message, :boolean
8
+ property :reminder, :boolean
8
9
  property :space, :boolean
9
10
  property :subscription, :boolean
10
11
  property :push_notification, :boolean
@@ -0,0 +1,30 @@
1
+ class Podio::ExternalFile < ActivePodio::Base
2
+ property :external_file_id, :string
3
+ property :name, :string
4
+ property :mimetype, :string
5
+
6
+ property :created_on, :datetime
7
+ property :updated_on, :datetime
8
+
9
+ alias_method :id, :external_file_id
10
+
11
+
12
+ class << self
13
+
14
+ def find_all_for_linked_account(linked_account_id, options={})
15
+ list Podio.connection.get { |req|
16
+ req.url("/file/linked_account/#{linked_account_id}/", options)
17
+ }.body
18
+ end
19
+
20
+ def create_from_external_file_id(linked_account_id, external_file_id)
21
+ response = Podio.client.connection.post do |req|
22
+ req.url "/file/linked_account/#{linked_account_id}/"
23
+ req.body = { :external_file_id => external_file_id }
24
+ end
25
+
26
+ member response.body
27
+ end
28
+
29
+ end
30
+ end
@@ -1,23 +1,35 @@
1
1
  class Podio::FileAttachment < ActivePodio::Base
2
2
  property :file_id, :integer
3
3
  property :link, :string
4
+ property :perma_link, :string
5
+ property :thumbnail_link, :string
6
+ property :hosted_by, :string
4
7
  property :name, :string
5
8
  property :description, :string
6
9
  property :mimetype, :string
7
10
  property :size, :integer
8
11
  property :context, :hash
9
12
  property :created_on, :datetime
10
-
13
+ property :rights, :array
14
+
11
15
  has_one :created_by, :class => 'ByLine'
12
16
  has_one :created_via, :class => 'Via'
13
17
  has_many :replaces, :class => 'FileAttachment'
14
-
18
+
15
19
  alias_method :id, :file_id
16
20
 
21
+ def has_thumbnail?
22
+ self.thumbnail_link.present?
23
+ end
24
+
17
25
  def image?
18
26
  ['image/png', 'image/jpeg', 'image/gif', 'image/bmp'].include?(self.mimetype)
19
27
  end
20
-
28
+
29
+ def api_friendly_ref_type
30
+ 'file'
31
+ end
32
+
21
33
  class << self
22
34
  # Accepts an open file stream along with a file name and uploads the file to Podio
23
35
  def upload(file_stream, file_name)
@@ -50,11 +62,11 @@ class Podio::FileAttachment < ActivePodio::Base
50
62
  def copy(id)
51
63
  Podio.connection.post("/file/#{id}/copy").body['file_id']
52
64
  end
53
-
65
+
54
66
  def delete(id)
55
67
  Podio.connection.delete("/file/#{id}")
56
68
  end
57
-
69
+
58
70
  def find(id)
59
71
  member Podio.connection.get("/file/#{id}").body
60
72
  end
@@ -86,7 +98,13 @@ class Podio::FileAttachment < ActivePodio::Base
86
98
  req.url("/file/space/#{space_id}/latest/", options)
87
99
  }.body
88
100
  end
89
-
101
+
102
+ def find_for_google(linked_account_id, options={})
103
+ list Podio.connection.get { |req|
104
+ req.url("/file/google/#{linked_account_id}/", options)
105
+ }.body
106
+ end
107
+
90
108
  def replace(old_file_id, new_file_id)
91
109
  Podio.connection.post { |req|
92
110
  req.url "/file/#{new_file_id}/replace"
@@ -100,12 +118,12 @@ class Podio::FileAttachment < ActivePodio::Base
100
118
  req.body = { :description => description }
101
119
  }.body
102
120
  end
103
-
104
-
121
+
122
+
105
123
  #
106
124
  # Obsolete way of uploading files, use upload method instead
107
125
  #
108
-
126
+
109
127
  # Uploading a file is a two-step operation
110
128
  # First, the file must be created to get a file id and the path to move it to
111
129
  def create(name, content_type)
@@ -116,11 +134,11 @@ class Podio::FileAttachment < ActivePodio::Base
116
134
 
117
135
  response.body
118
136
  end
119
-
137
+
120
138
  # Then, when the file has been moved, it must be marked as available
121
139
  def set_available(id)
122
140
  Podio.connection.post "/file/#{id}/available"
123
141
  end
124
-
142
+
125
143
  end
126
- end
144
+ end
@@ -1,11 +1,42 @@
1
1
  class Podio::Filter < ActivePodio::Base
2
+ property :filter_id, :integer
3
+ property :name, :string
4
+ property :created_on, :datetime
5
+ property :items, :integer
2
6
  property :sort_by, :string
3
- property :sort_desc, :boolean
4
- property :filters, :array
7
+ property :sort_desc, :string
8
+ property :filters, :hash
9
+
10
+ alias_method :id, :filter_id
11
+
12
+ has_one :created_by, :class => 'User'
5
13
 
6
14
  class << self
7
15
  def find_last(app_id)
8
16
  member Podio.connection.get("/filter/app/#{app_id}/last").body
9
17
  end
18
+
19
+ def find_all(app_id)
20
+ list Podio.connection.get { |req|
21
+ req.url("/filter/app/#{app_id}/")
22
+ }.body
23
+ end
24
+
25
+ def find(id)
26
+ member Podio.connection.get("/filter/#{id}").body
27
+ end
28
+
29
+ def delete(filter_id)
30
+ Podio.connection.delete("/filter/#{filter_id}").status
31
+ end
32
+
33
+ def create(app_id, attributes)
34
+ response = Podio.connection.post do |req|
35
+ req.url "/filter/app/#{app_id}/"
36
+ req.body = attributes
37
+ end
38
+
39
+ response.body['filter_id']
40
+ end
10
41
  end
11
42
  end
@@ -22,6 +22,7 @@ class Podio::Item < ActivePodio::Base
22
22
  property :subscribed, :boolean
23
23
  property :user_ratings, :hash
24
24
  property :link, :string
25
+ property :invite, :hash
25
26
 
26
27
  has_many :revisions, :class => 'ItemRevision'
27
28
  has_many :files, :class => 'FileAttachment'
@@ -79,6 +80,21 @@ class Podio::Item < ActivePodio::Base
79
80
  req.url("/item/app/#{app_id}/", options)
80
81
  }.body
81
82
  end
83
+
84
+ def find_by_filter_id(app_id, filter_id, attributes)
85
+ collection Podio.connection.post { |req|
86
+ req.url "/item/app/#{app_id}/filter/#{filter_id}/"
87
+ req.body = attributes
88
+ }.body
89
+ end
90
+
91
+ def find_by_filter_values(app_id, filter_values, attributes={})
92
+ attributes[:filters] = filter_values
93
+ collection Podio.connection.post { |req|
94
+ req.url "/item/app/#{app_id}/filter/"
95
+ req.body = attributes
96
+ }.body
97
+ end
82
98
 
83
99
  def find_next(current_item_id, time = nil)
84
100
  find_next_or_previous(:next, current_item_id, time)
@@ -87,6 +103,13 @@ class Podio::Item < ActivePodio::Base
87
103
  def find_previous(current_item_id, time = nil)
88
104
  find_next_or_previous(:previous, current_item_id, time)
89
105
  end
106
+
107
+ def find_app_values(app_id)
108
+ response = Podio.connection.get { |req|
109
+ req.url("/item/app/#{app_id}/values")
110
+ }
111
+ response.body
112
+ end
90
113
 
91
114
  def find_field_top(field_id, options={:limit => 8})
92
115
  list Podio.connection.get { |req|
@@ -13,7 +13,7 @@ class Podio::ItemField < ActivePodio::Base
13
13
  req.url "/item/#{item_id}/value/#{field_id}"
14
14
  req.body = values
15
15
  end
16
- response.status
16
+ response.body
17
17
  end
18
18
  end
19
19
  end
@@ -0,0 +1,32 @@
1
+ class Podio::LinkedAccount < ActivePodio::Base
2
+ property :linked_account_id, :integer
3
+ property :label, :string
4
+ property :provider, :string
5
+
6
+ alias_method :id, :linked_account_id
7
+
8
+ class << self
9
+
10
+ def find_all(provider, capability = nil)
11
+ options = { :provider => provider }
12
+ options[:capability] = capability if capability.present?
13
+ list Podio.connection.get { |req|
14
+ req.url("/linked_account/", options)
15
+ }.body
16
+ end
17
+
18
+ def create(attributes)
19
+ response = Podio.connection.post do |req|
20
+ req.url '/linked_account/'
21
+ req.body = attributes
22
+ end
23
+
24
+ member response.body
25
+ end
26
+
27
+ def delete(id)
28
+ Podio.connection.delete("/linked_account/#{id}").status
29
+ end
30
+
31
+ end
32
+ end
@@ -2,16 +2,19 @@ class Podio::Meeting < ActivePodio::Base
2
2
  include ActivePodio::Updatable, HasReference
3
3
 
4
4
  property :meeting_id, :integer
5
+ property :rights, :array
5
6
  property :title, :string
7
+ property :start_date, :date
6
8
  property :starts_on, :datetime, :convert_incoming_local_datetime_to_utc => true
7
9
  property :ends_on, :datetime, :convert_incoming_local_datetime_to_utc => true
8
10
  property :participant_ids, :array
9
- property :is_remote, :boolean
10
- property :status, :string
11
+ property :plugin, :string
12
+ property :plugin_data, :hash
11
13
  property :location, :string
12
14
  property :agenda, :string
13
15
  property :notes, :string
14
- property :transcript, :string
16
+ property :subscribed, :bool
17
+ property :liked, :integer
15
18
  property :external_id, :string
16
19
  property :external_url, :string
17
20
  property :external_phone, :string
@@ -22,7 +25,7 @@ class Podio::Meeting < ActivePodio::Base
22
25
  property :link, :string
23
26
  property :ref, :hash
24
27
  property :space_id, :integer
25
-
28
+
26
29
  # For creation only
27
30
  property :ref_id, :integer
28
31
  property :ref_type, :string
@@ -30,14 +33,14 @@ class Podio::Meeting < ActivePodio::Base
30
33
 
31
34
  has_one :created_by, :class => 'User'
32
35
  has_one :created_via, :class => 'Via'
33
- has_one :deleted_by, :class => 'User'
34
- has_one :deleted_via, :class => 'Via'
35
36
  has_many :participants, :class => 'MeetingParticipant'
36
37
  has_many :files, :class => 'FileAttachment'
37
38
  has_many :comments, :class => 'Comment'
39
+ has_one :reminder, :class => 'Reminder'
40
+ has_one :recurrence, :class => 'Recurrence'
38
41
 
39
42
  alias_method :id, :meeting_id
40
-
43
+
41
44
  def create
42
45
  compacted_attributes = remove_nil_values(self.attributes)
43
46
  created_model = if(self.ref_type.present? && self.ref_id.present?)
@@ -45,29 +48,23 @@ class Podio::Meeting < ActivePodio::Base
45
48
  else
46
49
  self.class.create(compacted_attributes)
47
50
  end
48
-
51
+
49
52
  self.attributes = created_model.attributes
50
53
  end
51
54
 
52
55
  def update
53
- compacted_attributes = remove_nil_values(self.attributes)
54
- updated_model = self.class.update(self.id, compacted_attributes)
56
+ # compacted_attributes = remove_nil_values(self.attributes)
57
+ # updated_model = self.class.update(self.id, compacted_attributes)
58
+ # self.attributes = updated_model.attributes
59
+ updated_model = self.class.update(self.id, self.attributes)
55
60
  self.attributes = updated_model.attributes
56
61
  end
57
-
62
+
58
63
  def destroy
59
64
  self.class.delete(self.id)
60
65
  end
61
66
 
62
- def start
63
- self.class.start(self.id)
64
- end
65
-
66
- def stop
67
- self.class.stop(self.id)
68
- end
69
-
70
- handle_api_errors_for :create, :destroy, :start, :stop # Call must be made after the methods to handle have been defined
67
+ handle_api_errors_for :create, :destroy # Call must be made after the methods to handle have been defined
71
68
 
72
69
  class << self
73
70
  def create(attributes)
@@ -101,20 +98,14 @@ class Podio::Meeting < ActivePodio::Base
101
98
  Podio.connection.delete("/meeting/#{id}").status
102
99
  end
103
100
 
104
- def start(id)
105
- Podio.connection.post("/meeting/#{id}/start").body
106
- end
107
-
108
- def stop(id)
109
- Podio.connection.post("/meeting/#{id}/stop").body
110
- end
111
-
112
101
  def find(id)
113
102
  member Podio.connection.get("/meeting/#{id}").body
114
103
  end
115
104
 
116
- def find_for_reference(ref_type, ref_id)
117
- list Podio.connection.get("/meeting/#{ref_type}/#{ref_id}/").body
105
+ def find_for_reference(ref_type, ref_id, options={})
106
+ list Podio.connection.get { |req|
107
+ req.url("/meeting/#{ref_type}/#{ref_id}/", options)
108
+ }.body
118
109
  end
119
110
 
120
111
  def find_all(options={})
@@ -122,5 +113,39 @@ class Podio::Meeting < ActivePodio::Base
122
113
  req.url('/meeting/', options)
123
114
  }.body
124
115
  end
116
+
117
+ def find_summary
118
+ response = Podio.connection.get("/meeting/summary").body
119
+ response['past']['tasks'] = list(response['past']['meetings'])
120
+ response['today']['tasks'] = list(response['today']['meetings'])
121
+ response['future']['tasks'] = list(response['future']['meetings'])
122
+ response
123
+ end
124
+
125
+ def find_summary_for_reference(ref_type, ref_id)
126
+ response = Podio.connection.get("/meeting/#{ref_type}/#{ref_id}/summary").body
127
+ response['past']['tasks'] = list(response['past']['meetings'])
128
+ response['today']['tasks'] = list(response['today']['meetings'])
129
+ response['future']['tasks'] = list(response['future']['meetings'])
130
+ response
131
+ end
132
+
133
+ def find_personal_summary
134
+ response = Podio.connection.get("/meeting/personal/summary").body
135
+ response['past']['tasks'] = list(response['past']['meetings'])
136
+ response['today']['tasks'] = list(response['today']['meetings'])
137
+ response['future']['tasks'] = list(response['future']['meetings'])
138
+ response
139
+ end
140
+
141
+ def set_participation_status(id, status)
142
+ response = Podio.connection.post do |req|
143
+ req.url "/meeting/#{id}/status"
144
+ req.body = { :status => status }
145
+ end
146
+
147
+ response.status
148
+ end
149
+
125
150
  end
126
151
  end