podio 0.6.0 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
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