diff options
author | Lin Jen-Shin <godfat@godfat.org> | 2016-12-20 20:54:40 +0800 |
---|---|---|
committer | Lin Jen-Shin <godfat@godfat.org> | 2016-12-20 20:54:40 +0800 |
commit | 0f0738e78867f6822dd15cb26da1f17628acde77 (patch) | |
tree | 0813c71b448d149afad6802e25c56a219efb0523 /lib/mattermost/session.rb | |
parent | eb839b9af51d411a6a35786a1c1c58954da1a650 (diff) | |
parent | ad1a1d976c877eca16858368db0c5b3ef800db8b (diff) | |
download | gitlab-ce-0f0738e78867f6822dd15cb26da1f17628acde77.tar.gz |
Merge remote-tracking branch 'upstream/master' into feature/1376-allow-write-access-deploy-keys
* upstream/master: (538 commits)
Reject blank environment vcariables in Gitlab::Git::RevList
Add online terminal documentation
Add changelog entry
Add terminal UI and controller actions
Fix specs
Even out padding on plus button in breadcrumb menu
Update font size of detail page header to 14px
Update CHANGELOG.md for 8.13.10
Update CHANGELOG.md for 8.14.5
Fix Route#rename_children behavior
Remove inline-block styling from status
Add terminals to the Kubernetes deployment service
Add a ReactiveCaching concern for use in the KubernetesService
Add xterm.js 2.1.0 and a wrapper class to the asset pipeline
Remove unnecessary hidden svg elements for icons.
Fix consistent typo in environment.js
Use a block to insert extra check for authenticate_build!
Align milestone column header with count number
Add Wiki import to BB importer
Make CI badge hitboxes better match container
...
Diffstat (limited to 'lib/mattermost/session.rb')
-rw-r--r-- | lib/mattermost/session.rb | 115 |
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 |