Skip to content

Commit

Permalink
add slack basic oauth flow
Browse files Browse the repository at this point in the history
  • Loading branch information
kaiomagalhaes committed Aug 30, 2020
1 parent 731460d commit 752643e
Show file tree
Hide file tree
Showing 9 changed files with 118 additions and 13 deletions.
5 changes: 4 additions & 1 deletion .env.example
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
SLACK_API_KEY=
AUTHENTICATION_KEY=
AUTHENTICATION_KEY=
SLACK_CLIENT_ID=
SLACK_CLIENT_SECRET=
DATABASE_URL=
2 changes: 2 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@ source "https://rubygems.org"
gem "sinatra"
gem 'slack-ruby-client'
gem 'gelf'
gem 'mongo'

group :development, :test do
gem "rerun"
gem "dotenv"
gem 'pry'
end
10 changes: 10 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ GEM
minitest (~> 5.1)
tzinfo (~> 1.1)
zeitwerk (~> 2.2, >= 2.2.2)
bson (4.10.0)
coderay (1.1.3)
concurrent-ruby (1.1.6)
dotenv (2.7.5)
faraday (1.0.1)
Expand All @@ -24,10 +26,16 @@ GEM
listen (3.2.1)
rb-fsevent (~> 0.10, >= 0.10.3)
rb-inotify (~> 0.9, >= 0.9.10)
method_source (1.0.0)
minitest (5.14.1)
mongo (2.13.0)
bson (>= 4.8.2, < 5.0.0)
multipart-post (2.1.1)
mustermann (1.1.1)
ruby2_keywords (~> 0.0.1)
pry (0.13.1)
coderay (~> 1.1)
method_source (~> 1.0)
rack (2.2.3)
rack-protection (2.0.8.1)
rack
Expand Down Expand Up @@ -64,6 +72,8 @@ PLATFORMS
DEPENDENCIES
dotenv
gelf
mongo
pry
rerun
sinatra
slack-ruby-client
Expand Down
48 changes: 38 additions & 10 deletions app.rb
Original file line number Diff line number Diff line change
@@ -1,28 +1,37 @@
require 'dotenv/load' if ENV["RACK_ENV"] != "production"

require 'sinatra'
require 'gelf'
require './controllers/channel_messages_controller'
require './controllers/direct_messages_controller'
require './controllers/direct_ephemeral_messages_controller'
require './controllers/reactions_controller'
require './controllers/users_controller'
require './models/access_tokens'
require './services/slack_oauth'

configure do
set :show_exceptions, false
end

before do
content_type :json
body = request.body.read

def authenticate!
key = env['HTTP_AUTHORIZATION']
clean_key = key&.gsub(/Bearer /, '')

if clean_key != ENV['AUTHENTICATION_KEY']
halt 401
end
end

before do
content_type :json
body = request.body.read

@body = JSON.parse body if !body.empty?

if (@body && @body["team"])
@slack_team_key = AccessTokens.new.by_team_id(@body["team"])[:value]
end
end

def render_json json
Expand All @@ -34,27 +43,46 @@ def render_json json
end

post '/channel-messages' do
ChannelMessagesController.new(@body, response).create!
authenticate!
ChannelMessagesController.new(@body, response, @slack_team_key).create!
end

patch '/channel-messages' do
ChannelMessagesController.new(@body, response).update!
authenticate!
ChannelMessagesController.new(@body, response, @slack_team_key).update!
end

post '/direct-messages' do
DirectMessagesController.new(@body, response).create!
authenticate!
DirectMessagesController.new(@body, response, @slack_team_key).create!
end

post '/direct-ephemeral-messages' do
DirecEphemeraltMessagesController.new(@body, response).create!
authenticate!
DirecEphemeraltMessagesController.new(@body, response, @slack_team_key).create!
end

post '/reactions' do
ReactionsController.new(@body, response).create!
authenticate!
ReactionsController.new(@body, response, @slack_team_key).create!
end

get '/users' do
UsersController.new(@body, response).index
authenticate!
UsersController.new(@body, response, @slack_key).index
end

get '/oauth' do
code = params[:code]
data = SlackOauth.new(code).authenticate!
access_token = data.with_indifferent_access[:access_token]
team_id = data.with_indifferent_access[:team][:id]

AccessTokens.new.create!(access_token, team_id)

response.body = JSON.dump({
status: 'success'
})
end

error do
Expand Down
5 changes: 3 additions & 2 deletions controllers/application_controller.rb
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
class ApplicationController
def initialize(params, response)
def initialize(params, response, slack_team_key = nil)
Slack.configure do |config|
config.token = ENV['SLACK_API_KEY']
config.token = slack_team_key || ENV['SLACK_API_KEY']
end

@params = params&.with_indifferent_access
@response = response
end
Expand Down
18 changes: 18 additions & 0 deletions models/access_tokens.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
require './models/base_model'

class AccessTokens < BaseModel
# @TODO: do not create a new one if there is a team id in the database already
def create!(access_token, team_id)
collection = @client[:access_tokens]
doc = {
value: access_token,
team_id: team_id
}
collection.insert_one(doc)
end

def by_team_id(team_id)
collection = @client[:access_tokens]
collection.find("team_id": team_id ).first
end
end
7 changes: 7 additions & 0 deletions models/base_model.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
require './services/database'

class BaseModel
def initialize
@client = Database.instance.client
end
end
10 changes: 10 additions & 0 deletions services/Database.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
require 'mongo'
require 'singleton'

class Database
include Singleton

def client
@client ||= client = Mongo::Client.new(ENV['DATABASE_URL'])
end
end
26 changes: 26 additions & 0 deletions services/slack_oauth.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
require 'uri'
require 'net/http'

class SlackOauth
SLACK_AUTHENTICATE_URL = 'https://slack.com/api/oauth.v2.access'

def initialize(code)
@code = code
end

def authenticate!
data = {
:code => @code,
:client_id => ENV['SLACK_CLIENT_ID'],
:client_secret => ENV['SLACK_CLIENT_SECRET'],
}

encoded_data = URI.encode_www_form(data)

url = URI.parse("#{SLACK_AUTHENTICATE_URL}?#{encoded_data}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
req = Net::HTTP::Get.new(url.request_uri)
JSON.parse(http.request(req).body)
end
end

0 comments on commit 752643e

Please sign in to comment.