Minor refactors

This commit is contained in:
Andrew Cantino 2014-08-09 14:06:56 -07:00
parent ae927caa7a
commit 556c45e000
13 changed files with 67 additions and 58 deletions

View file

@ -11,11 +11,11 @@ module Oauthable
true
end
def valid_services(current_user)
def valid_services_for(user)
if valid_oauth_providers == :all
current_user.available_services
user.available_services
else
current_user.available_services.where(provider: valid_oauth_providers)
user.available_services.where(provider: valid_oauth_providers)
end
end

View file

@ -25,11 +25,11 @@ module TwitterConcern
end
def twitter_oauth_token
self.service.token
service.token
end
def twitter_oauth_token_secret
self.service.secret
service.secret
end
def twitter

View file

@ -1,5 +1,4 @@
class ServicesController < ApplicationController
def index
@services = current_user.services.page(params[:page])

View file

@ -44,7 +44,7 @@ class Agent < ActiveRecord::Base
after_save :possibly_update_event_expirations
belongs_to :user, :inverse_of => :agents
belongs_to :service
belongs_to :service, :inverse_of => :agents
has_many :events, -> { order("events.id desc") }, :dependent => :delete_all, :inverse_of => :agent
has_one :most_recent_event, :inverse_of => :agent, :class_name => "Event", :order => "events.id desc"
has_many :logs, -> { order("agent_logs.id desc") }, :dependent => :delete_all, :inverse_of => :agent, :class_name => "AgentLog"

View file

@ -59,7 +59,7 @@ module Agents
end
def check
self.service.prepare_request
service.prepare_request
reponse = HTTParty.get request_url, request_options.merge(query_parameters)
memory[:last_run] = Time.now.utc.iso8601
if last_check_at != nil
@ -72,11 +72,11 @@ module Agents
private
def request_url
"https://basecamp.com/#{URI.encode(self.service.options[:user_id].to_s)}/api/v1/projects/#{URI.encode(interpolated[:project_id].to_s)}/events.json"
"https://basecamp.com/#{URI.encode(service.options[:user_id].to_s)}/api/v1/projects/#{URI.encode(interpolated[:project_id].to_s)}/events.json"
end
def request_options
{:headers => {"User-Agent" => "Huginn (https://github.com/cantino/huginn)", "Authorization" => "Bearer \"#{self.service.token}\""}}
{:headers => {"User-Agent" => "Huginn (https://github.com/cantino/huginn)", "Authorization" => "Bearer \"#{service.token}\""}}
end
def query_parameters

View file

@ -1,17 +1,22 @@
class Service < ActiveRecord::Base
PROVIDER_TO_ENV_MAP = {'37signals' => 'THIRTY_SEVEN_SIGNALS'}
attr_accessible :provider, :name, :token, :secret, :refresh_token, :expires_at, :global, :options
serialize :options, Hash
belongs_to :user
has_many :agents
belongs_to :user, :inverse_of => :services
has_many :agents, :inverse_of => :service
validates_presence_of :user_id, :provider, :name, :token
before_destroy :disable_agents
scope :available_to_user, lambda { |user| where("services.user_id = ? or services.global = true", user.id) }
scope :by_name, lambda { |dir = 'desc'| order("services.name #{dir}") }
def disable_agents
self.agents.each do |agent|
agents.each do |agent|
agent.service_id = nil
agent.disabled = true
agent.save!(validate: false)
@ -24,52 +29,55 @@ class Service < ActiveRecord::Base
end
def prepare_request
if self.expires_at && Time.now > self.expires_at
self.refresh_token!
if expires_at && Time.now > expires_at
refresh_token!
end
end
def refresh_token!
response = HTTParty.post(endpoint, query: {
type: 'refresh',
client_id: ENV["#{provider_to_env}_OAUTH_KEY"],
client_secret: ENV["#{provider_to_env}_OAUTH_SECRET"],
refresh_token: self.refresh_token
client_id: oauth_key,
client_secret: oauth_secret,
refresh_token: refresh_token
})
data = JSON.parse(response.body)
self.update(expires_at: Time.now + data['expires_in'], token: data['access_token'], refresh_token: data['refresh_token'].presence || self.refresh_token)
update(expires_at: Time.now + data['expires_in'], token: data['access_token'], refresh_token: data['refresh_token'].presence || refresh_token)
end
def self.initialize_or_update_via_omniauth(omniauth)
case omniauth['provider']
when 'twitter'
find_or_initialize_by(provider: omniauth['provider'], name: omniauth['info']['nickname']).tap do |service|
service.assign_attributes(token: omniauth['credentials']['token'], secret: omniauth['credentials']['secret'])
end
when 'github'
find_or_initialize_by(provider: omniauth['provider'], name: omniauth['info']['nickname']).tap do |service|
service.assign_attributes(token: omniauth['credentials']['token'])
end
when '37signals'
find_or_initialize_by(provider: omniauth['provider'], name: omniauth['info']['name']).tap do |service|
service.assign_attributes(token: omniauth['credentials']['token'],
refresh_token: omniauth['credentials']['refresh_token'],
expires_at: Time.at(omniauth['credentials']['expires_at']),
options: {user_id: omniauth['extra']['accounts'][0]['id']})
end
else
false
end
end
private
def endpoint
client_options = "OmniAuth::Strategies::#{OmniAuth::Utils.camelize(self.provider)}".constantize.default_options['client_options']
URI.join(client_options['site'], client_options['token_url'])
end
@@provider_to_env_map = {'37signals' => 'THIRTY_SEVEN_SIGNALS'}
def provider_to_env
@@provider_to_env_map[self.provider].presence || self.provider.upcase
PROVIDER_TO_ENV_MAP[provider].presence || provider.upcase
end
def oauth_key
ENV["#{provider_to_env}_OAUTH_KEY"]
end
def oauth_secret
ENV["#{provider_to_env}_OAUTH_SECRET"]
end
def self.provider_specific_options(omniauth)
case omniauth['provider']
when '37signals'
{ user_id: omniauth['extra']['accounts'][0]['id'] }
else
{}
end
end
def self.initialize_or_update_via_omniauth(omniauth)
find_or_initialize_by(provider: omniauth['provider'], name: omniauth['info']['nickname'] || omniauth['info']['name']).tap do |service|
service.assign_attributes token: omniauth['credentials']['token'],
secret: omniauth['credentials']['secret'],
refresh_token: omniauth['credentials']['refresh_token'],
expires_at: omniauth['credentials']['expires_at'] && Time.at(omniauth['credentials']['expires_at']),
options: provider_specific_options(omniauth)
end
end
end

View file

@ -27,10 +27,10 @@ class User < ActiveRecord::Base
has_many :agents, -> { order("agents.created_at desc") }, :dependent => :destroy, :inverse_of => :user
has_many :logs, :through => :agents, :class_name => "AgentLog"
has_many :scenarios, :inverse_of => :user, :dependent => :destroy
has_many :services, -> { order("services.name")}, :dependent => :destroy
has_many :services, -> { by_name('asc') }, :dependent => :destroy
def available_services
Service.where("user_id = ? or global = true", self.id).order("services.name desc")
Service.available_to_user(self).by_name
end
# Allow users to login via either email or username.

View file

@ -34,7 +34,7 @@
<% if @agent.try(:oauthable?) %>
<div class="form-group type-select">
<%= f.label :service %>
<%= f.select :service_id, options_for_select(@agent.valid_services(current_user).collect { |s| ["(#{s.provider}) #{s.name}", s.id]}, @agent.service_id),{}, class: 'form-control' %>
<%= f.select :service_id, options_for_select(@agent.valid_services_for(current_user).collect { |s| ["(#{s.provider}) #{s.name}", s.id]}, @agent.service_id), {}, class: 'form-control' %>
</div>
<% end %>
</div>

View file

@ -120,12 +120,13 @@
</div>
<% end %>
</div>
<% if agent_diff.requires_service? %>
<div class='row'>
<div class='col-md-4'>
<div class="form-group type-select">
<%= label_tag "scenario_import[merges][#{index}][service_id]", 'Service' %>
<%= select_tag "scenario_import[merges][#{index}][service_id]", options_for_select(agent_diff.agent_instance.valid_services(current_user).collect { |s| ["(#{s.provider}) #{s.name}", s.id]}, agent_diff.service_id.try(:current)), class: 'form-control' %>
<%= select_tag "scenario_import[merges][#{index}][service_id]", options_for_select(agent_diff.agent_instance.valid_services_for(current_user).collect { |s| ["(#{s.provider}) #{s.name}", s.id]}, agent_diff.service_id.try(:current)), class: 'form-control' %>
</div>
</div>
</div>

View file

@ -7,7 +7,7 @@
</h2>
</div>
<p>
Before you can authenticate with a service, you need to set it up. Have a look at the
Before you can authenticate with a service, you need to set it up. Have a look at the Huginn
<%= link_to 'wiki', 'https://github.com/cantino/huginn/wiki/Configuring-OAuth-applications', target: :_blank %>
for guidance.
</p>
@ -33,9 +33,9 @@
<td>
<div class="btn-group btn-group-xs">
<% if service.global %>
<%= link_to 'Make private', toggle_availability_service_path(service), method: :post, data: { confirm: 'Are you sure you want to remove the access to this service for every user?'}, class: "btn btn-default" %>
<%= link_to 'Make private', toggle_availability_service_path(service), method: :post, data: { confirm: 'Are you sure you want to remove access to your data on this service for other users?'}, class: "btn btn-default" %>
<% else %>
<%= link_to 'Make global', toggle_availability_service_path(service), method: :post, data: { confirm: 'Are you sure you want to grant every user access to this service?'}, class: "btn btn-default" %>
<%= link_to 'Make global', toggle_availability_service_path(service), method: :post, data: { confirm: 'Are you sure you want to grant every user on this system access to your data on this service?'}, class: "btn btn-default" %>
<% end %>
<%= link_to 'Delete', service_path(service), method: :delete, data: { confirm: 'Are you sure?' }, class: "btn btn-default btn-danger" %>
</div>

View file

@ -40,7 +40,7 @@ class MigrateAgentsToServiceAuthentication < ActiveRecord::Migration
if Agent.where(type: ['Agents::BasecampAgent']).count > 0
puts <<-EOF.strip_heredoc
Your Basecamp agents can not be migrated automatically. You need to manually register an application with 37signals and authenticate huginn to use it.
Your Basecamp agents can not be migrated automatically. You need to manually register an application with 37signals and authenticate Huginn to use it.
Have a look at the wiki (https://github.com/cantino/huginn/wiki/Configuring-OAuth-applications) if you need help.

View file

@ -41,17 +41,18 @@ describe ServicesController do
end
describe "accepting a callback url" do
it "should update the users credentials" do
it "should update the user's credentials" do
expect {
get :callback, provider: 'twitter'
}.to change { users(:bob).services.count }.by(1)
end
it "should not work with an unknown provider" do
it "should work with an unknown provider (for now)" do
request.env["omniauth.auth"]['provider'] = 'unknown'
expect {
get :callback, provider: 'unknown'
}.to change { users(:bob).services.count }.by(0)
}.to change { users(:bob).services.count }.by(1)
users(:bob).services.first.provider.should == 'unknown'
end
end
end

View file

@ -16,14 +16,14 @@ shared_examples_for Oauthable do
@agent.oauthable?.should == true
end
describe "valid_services" do
describe "valid_services_for" do
it "should return all available services without specifying valid_oauth_providers" do
@agent = Agents::OauthableTestAgent.new
@agent.valid_services(users(:bob)).collect(&:id).sort.should == [services(:generic), services(:global)].collect(&:id).sort
@agent.valid_services_for(users(:bob)).collect(&:id).sort.should == [services(:generic), services(:global)].collect(&:id).sort
end
it "should filter the services based on the agent defaults" do
@agent.valid_services(users(:bob)).to_a.should == Service.where(provider: @agent.valid_oauth_providers)
@agent.valid_services_for(users(:bob)).to_a.should == Service.where(provider: @agent.valid_oauth_providers)
end
end
end