Skip to content

Instantly share code, notes, and snippets.

@m5rk
Last active April 30, 2020 07:37
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save m5rk/0321caa67436711ae47e70480c0a0b32 to your computer and use it in GitHub Desktop.
Save m5rk/0321caa67436711ae47e70480c0a0b32 to your computer and use it in GitHub Desktop.
Slack Sessions Controller
# app/controllers/slack/sessions_controller.rb
module Slack
class SessionsController < ApplicationController
before_action :ensure_no_error!
before_action :ensure_ok!
before_action :ensure_slack_token_valid!
before_action :ensure_account!
before_action :ensure_user!
expose(:slack_client) { Slack::Web::Client.new }
expose(:oauth_token) do
slack_client.oauth_access(
client_id: Chamber.slack.client_id,
client_secret: Chamber.slack.secret,
redirect_uri: slack_login_url,
code: params[:code])
end
expose(:slack_team_from_token) { oauth_token.team }
expose(:slack_user_from_token) { oauth_token.user }
expose(:team_id) { slack_team_from_token.id }
expose(:account) { Account.for_slack_team_id(team_id).first }
expose(:user) { account.users.where(email: slack_user_from_token.email).first }
def create
sign_in_and_redirect(user)
end
private
def ensure_no_error!
return unless params[:error]
message = if params[:error] == 'access_denied'
'You canceled sign in with Slack'
else
'An error occurred when signing in with Slack'
end
redirect_to new_user_session_path, alert: message
end
def ensure_ok!
return if oauth_token['ok']
message = 'An error occurred when signing in with Slack'
redirect_to new_user_session_path, alert: message
end
def ensure_slack_token_valid!
return unless account
return if account.slack_token.auth_test?
message = "No account found for Slack Team: #{slack_team_from_token.name}"
redirect_to new_user_session_path, alert: message
end
def ensure_account!
return if account
message = "No account found for Slack Team: #{slack_team_from_token.name}"
redirect_to new_user_session_path, alert: message
end
def ensure_user!
return if user
message = "No user found in the Manifestly Account #{account.name} for email #{slack_user_from_token.email}"
redirect_to new_user_session_path, alert: message
end
end
end
# spec/controllers/slack/sessions_controller_spec.rb
require 'rails_helper'
RSpec.describe Slack::SessionsController do
before { allow(SlackUser).to receive(:fetch_all) }
describe 'GET #create' do
let(:action) { get :create, params }
context 'when there is an access_denied error' do
let(:params) do
{
error: 'access_denied'
}
end
it_behaves_like 'a slack sign in error', 'You canceled sign in with Slack'
end
context 'when there is any other error' do
let(:params) do
{
error: 'some other error'
}
end
it_behaves_like 'a slack sign in error', 'An error occurred when signing in with Slack'
end
context 'when there is an oauth token' do
let(:mock_slack_client) { instance_double(Slack::Web::Client) }
let(:mock_oauth_access) { Slack::Messages::Message.new(json) }
let(:params) do
{
code: 'the code'
}
end
let(:ok) { Slack::Messages::Message.new(ok: true) }
before do
allow(Slack::Web::Client).to receive(:new).and_return(mock_slack_client)
allow(mock_slack_client).to receive(:auth_test).and_return(ok)
allow(mock_slack_client).to receive(:oauth_access).with(
client_id: Chamber.slack.client_id,
client_secret: Chamber.slack.secret,
redirect_uri: slack_login_url,
code: params[:code]
).and_return(mock_oauth_access)
end
context 'when the token is not ok' do
let(:json) do
{
ok: false
}
end
it_behaves_like 'a slack sign in error', 'An error occurred when signing in with Slack'
end
context 'when there is no account for the Slack team' do
let(:json) do
{
ok: true,
team: { id: 'foo', name: 'team alpha' }
}
end
it_behaves_like 'a slack sign in error', 'No account found for Slack Team: team alpha'
end
context 'when the token is no longer valid for the Slack team' do
let(:account) { create :account }
let(:slack_token) { create :slack_token, :enabled, account: account }
let(:json) do
{
ok: true,
team: { id: slack_token.team_id, name: 'team alpha' }
}
end
before do
expect(mock_slack_client).to receive(:auth_test).and_raise(Slack::Web::Api::Error.new('token_revoked'))
end
it_behaves_like 'a slack sign in error', 'No account found for Slack Team: team alpha'
it 'deletes the token' do
expect { action }.to change { SlackToken.where(account_id: account.id).count }.to(0)
end
end
context 'when there is no user in the account for the specified email' do
let(:account) { create :account, name: 'Acme, Inc.' }
let(:slack_token) { create :slack_token, :enabled, account: account }
let(:json) do
{
ok: true,
team: { id: slack_token.team_id },
user: { email: 'foo@bar.com' }
}
end
it_behaves_like 'a slack sign in error', 'No user found in the Manifestly Account Acme, Inc. for email foo@bar.com'
end
context 'when the account and user exist' do
let(:user) { create :user, current_account: account, email: 'foo@bar.com', sign_in_count: 2 }
let(:account) { create :account, name: 'Acme, Inc.' }
let(:slack_token) { create :slack_token, :enabled, account: account }
let(:json) do
{
ok: true,
team: { id: slack_token.team_id },
user: { email: user.email }
}
end
it 'redirects to the dashboard' do
action
expect(response).to redirect_to(dashboard_path)
end
end
end
end
end
# spec/support/examples/slack_sign_in_error.rb
RSpec.shared_examples 'a slack sign in error' do |message|
before { action }
it 'redirects to sign in' do
expect(response).to redirect_to(new_user_session_path)
end
it 'sets the flash' do
is_expected.to set_flash[:alert].to message
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment