summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorGrzegorz Bizon <grzegorz@gitlab.com>2016-12-17 12:27:03 +0000
committerGrzegorz Bizon <grzegorz@gitlab.com>2016-12-17 12:27:03 +0000
commite47989a58b8a9f83855ea9210ba5786fc14fb841 (patch)
tree2c9c722e8a989e38b36e9e9c9eef12cc9b0e2e76 /lib
parent0a6450094eb13702f6f6f03e468db4fc8f023315 (diff)
parentc9610e0a052526adb3138dccf6114d710979a0b7 (diff)
downloadgitlab-ce-e47989a58b8a9f83855ea9210ba5786fc14fb841.tar.gz
Merge branch 'zj-mattermost-session' into 'master'
Mattermost session This branch is based of tag v8.14.4 so I could test on an instance better. But stuck on the tests, as setting up the whole doorkeeper stuff doesn't seem to be supported for testing. See merge request !8033
Diffstat (limited to 'lib')
-rw-r--r--lib/mattermost/session.rb115
1 files changed, 115 insertions, 0 deletions
diff --git a/lib/mattermost/session.rb b/lib/mattermost/session.rb
new file mode 100644
index 00000000000..fb8d7d97f8a
--- /dev/null
+++ b/lib/mattermost/session.rb
@@ -0,0 +1,115 @@
+module Mattermost
+ class NoSessionError < StandardError; end
+ # This class' prime objective is to obtain a session token on a Mattermost
+ # instance with SSO configured where this GitLab instance is the provider.
+ #
+ # The process depends on OAuth, but skips a step in the authentication cycle.
+ # For example, usually a user would click the 'login in GitLab' button on
+ # Mattermost, which would yield a 302 status code and redirects you to GitLab
+ # to approve the use of your account on Mattermost. Which would trigger a
+ # callback so Mattermost knows this request is approved and gets the required
+ # data to create the user account etc.
+ #
+ # This class however skips the button click, and also the approval phase to
+ # speed up the process and keep it without manual action and get a session
+ # going.
+ class Session
+ include Doorkeeper::Helpers::Controller
+ include HTTParty
+
+ base_uri Settings.mattermost.host
+
+ attr_accessor :current_resource_owner, :token
+
+ def initialize(current_user)
+ @current_resource_owner = current_user
+ end
+
+ def with_session
+ raise NoSessionError unless create
+
+ begin
+ yield self
+ ensure
+ destroy
+ end
+ end
+
+ # Next methods are needed for Doorkeeper
+ def pre_auth
+ @pre_auth ||= Doorkeeper::OAuth::PreAuthorization.new(
+ Doorkeeper.configuration, server.client_via_uid, params)
+ end
+
+ def authorization
+ @authorization ||= strategy.request
+ end
+
+ def strategy
+ @strategy ||= server.authorization_request(pre_auth.response_type)
+ end
+
+ def request
+ @request ||= OpenStruct.new(parameters: params)
+ end
+
+ def params
+ Rack::Utils.parse_query(oauth_uri.query).symbolize_keys
+ end
+
+ def get(path, options = {})
+ self.class.get(path, options.merge(headers: @headers))
+ end
+
+ def post(path, options = {})
+ self.class.post(path, options.merge(headers: @headers))
+ end
+
+ private
+
+ def create
+ return unless oauth_uri
+ return unless token_uri
+
+ @token = request_token
+ @headers = {
+ Authorization: "Bearer #{@token}"
+ }
+
+ @token
+ end
+
+ def destroy
+ post('/api/v3/users/logout')
+ end
+
+ def oauth_uri
+ return @oauth_uri if defined?(@oauth_uri)
+
+ @oauth_uri = nil
+
+ response = get("/api/v3/oauth/gitlab/login", follow_redirects: false)
+ return unless 300 <= response.code && response.code < 400
+
+ redirect_uri = response.headers['location']
+ return unless redirect_uri
+
+ @oauth_uri = URI.parse(redirect_uri)
+ end
+
+ def token_uri
+ @token_uri ||=
+ if oauth_uri
+ authorization.authorize.redirect_uri if pre_auth.authorizable?
+ end
+ end
+
+ def request_token
+ response = get(token_uri, follow_redirects: false)
+
+ if 200 <= response.code && response.code < 400
+ response.headers['token']
+ end
+ end
+ end
+end