service.rb 2.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. class Service < ActiveRecord::Base
  2. PROVIDER_TO_ENV_MAP = {'37signals' => 'THIRTY_SEVEN_SIGNALS'}
  3. attr_accessible :provider, :name, :token, :secret, :refresh_token, :expires_at, :global, :options, :uid
  4. serialize :options, Hash
  5. belongs_to :user, :inverse_of => :services
  6. has_many :agents, :inverse_of => :service
  7. validates_presence_of :user_id, :provider, :name, :token
  8. before_destroy :disable_agents
  9. scope :available_to_user, lambda { |user| where("services.user_id = ? or services.global = true", user.id) }
  10. scope :by_name, lambda { |dir = 'desc'| order("services.name #{dir}") }
  11. def disable_agents(conditions = {})
  12. agents.where.not(conditions[:where_not] || {}).each do |agent|
  13. agent.service_id = nil
  14. agent.disabled = true
  15. agent.save!(validate: false)
  16. end
  17. end
  18. def toggle_availability!
  19. disable_agents(where_not: {user_id: self.user_id}) if global
  20. self.global = !self.global
  21. self.save!
  22. end
  23. def prepare_request
  24. if expires_at && Time.now > expires_at
  25. refresh_token!
  26. end
  27. end
  28. def refresh_token!
  29. response = HTTParty.post(endpoint, query: {
  30. type: 'refresh',
  31. client_id: oauth_key,
  32. client_secret: oauth_secret,
  33. refresh_token: refresh_token
  34. })
  35. data = JSON.parse(response.body)
  36. update(expires_at: Time.now + data['expires_in'], token: data['access_token'], refresh_token: data['refresh_token'].presence || refresh_token)
  37. end
  38. def endpoint
  39. client_options = "OmniAuth::Strategies::#{OmniAuth::Utils.camelize(self.provider)}".constantize.default_options['client_options']
  40. URI.join(client_options['site'], client_options['token_url'])
  41. end
  42. def provider_to_env
  43. PROVIDER_TO_ENV_MAP[provider].presence || provider.upcase
  44. end
  45. def oauth_key
  46. ENV["#{provider_to_env}_OAUTH_KEY"]
  47. end
  48. def oauth_secret
  49. ENV["#{provider_to_env}_OAUTH_SECRET"]
  50. end
  51. def self.provider_specific_options(omniauth)
  52. case omniauth['provider']
  53. when 'twitter', 'github'
  54. { name: omniauth['info']['nickname'] }
  55. when '37signals'
  56. { user_id: omniauth['extra']['accounts'][0]['id'], name: omniauth['info']['name'] }
  57. else
  58. { name: omniauth['info']['nickname'] }
  59. end
  60. end
  61. def self.initialize_or_update_via_omniauth(omniauth)
  62. options = provider_specific_options(omniauth)
  63. find_or_initialize_by(provider: omniauth['provider'], uid: omniauth['uid'].to_s).tap do |service|
  64. service.assign_attributes token: omniauth['credentials']['token'],
  65. secret: omniauth['credentials']['secret'],
  66. name: options[:name],
  67. refresh_token: omniauth['credentials']['refresh_token'],
  68. expires_at: omniauth['credentials']['expires_at'] && Time.at(omniauth['credentials']['expires_at']),
  69. options: options
  70. end
  71. end
  72. end