1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
|
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
attr_accessor :current_resource_owner
def initialize(uri, current_user)
uri = normalize_uri(uri)
# Sets the base uri for HTTParty, so we can use paths
self.class.base_uri(uri)
@current_resource_owner = current_user
end
def with_session
raise NoSessionError unless create
begin
yield
rescue Errno::ECONNREFUSED
raise NoSessionError
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
private
def create
return unless oauth_uri
return unless token_uri
self.class.headers("Cookie" => "MMAUTHTOKEN=#{request_token}")
self.class.headers("X-Requested-With" => 'XMLHttpRequest')
request_token
end
def destroy
post('/users/logout')
end
def oauth_uri
response = get("/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
@request_token ||= begin
response = get(@token_uri, follow_redirects: false)
response.headers['token'] if 200 <= response.code && response.code < 400
end
end
def get(path, options = {})
self.class.get(path, options)
end
def post(path, options = {})
self.class.post(path, options)
end
def normalize_uri(uri)
uri << '/' unless uri.end_with?('/')
uri << 'api/v3'
end
end
end
|