Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-09-01 15:11:01 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2020-09-01 15:11:01 +0300
commit08b3b98051f56cfc1774db5c92c183cf33ed8bdd (patch)
treed93e764b9ac3fd30eaf827a1017fbb40a7abf40c /app/controllers
parenta928c5170fa58e4aef91ebca6c4fc9ec7cea812e (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app/controllers')
-rw-r--r--app/controllers/groups/settings/integrations_controller.rb6
-rw-r--r--app/controllers/jira_connect/app_descriptor_controller.rb64
-rw-r--r--app/controllers/jira_connect/application_controller.rb57
-rw-r--r--app/controllers/jira_connect/events_controller.rb30
-rw-r--r--app/controllers/jira_connect/subscriptions_controller.rb56
-rw-r--r--app/controllers/oauth/jira/authorizations_controller.rb48
-rw-r--r--app/controllers/passwords_controller.rb6
7 files changed, 265 insertions, 2 deletions
diff --git a/app/controllers/groups/settings/integrations_controller.rb b/app/controllers/groups/settings/integrations_controller.rb
index 103ab860aac..5161b9cb181 100644
--- a/app/controllers/groups/settings/integrations_controller.rb
+++ b/app/controllers/groups/settings/integrations_controller.rb
@@ -11,6 +11,12 @@ module Groups
@integrations = Service.find_or_initialize_all(Service.for_group(group)).sort_by(&:title)
end
+ def edit
+ @admin_integration = Service.instance_for(integration.type)
+
+ super
+ end
+
private
def find_or_initialize_integration(name)
diff --git a/app/controllers/jira_connect/app_descriptor_controller.rb b/app/controllers/jira_connect/app_descriptor_controller.rb
new file mode 100644
index 00000000000..bf53c61601b
--- /dev/null
+++ b/app/controllers/jira_connect/app_descriptor_controller.rb
@@ -0,0 +1,64 @@
+# frozen_string_literal: true
+
+# This returns an app descriptor for use with Jira in development mode
+# For the Atlassian Marketplace, a static copy of this JSON is uploaded to the marketplace
+# https://developer.atlassian.com/cloud/jira/platform/app-descriptor/
+
+class JiraConnect::AppDescriptorController < JiraConnect::ApplicationController
+ skip_before_action :verify_atlassian_jwt!
+
+ def show
+ render json: {
+ name: Atlassian::JiraConnect.app_name,
+ description: 'Integrate commits, branches and merge requests from GitLab into Jira',
+ key: Atlassian::JiraConnect.app_key,
+ baseUrl: jira_connect_base_url(protocol: 'https'),
+ lifecycle: {
+ installed: relative_to_base_path(jira_connect_events_installed_path),
+ uninstalled: relative_to_base_path(jira_connect_events_uninstalled_path)
+ },
+ vendor: {
+ name: 'GitLab',
+ url: 'https://gitlab.com'
+ },
+ links: {
+ documentation: help_page_url('integration/jira_development_panel', anchor: 'gitlabcom-1')
+ },
+ authentication: {
+ type: 'jwt'
+ },
+ scopes: %w(READ WRITE DELETE),
+ apiVersion: 1,
+ modules: {
+ jiraDevelopmentTool: {
+ key: 'gitlab-development-tool',
+ application: {
+ value: 'GitLab'
+ },
+ name: {
+ value: 'GitLab'
+ },
+ url: 'https://gitlab.com',
+ logoUrl: view_context.image_url('gitlab_logo.png'),
+ capabilities: %w(branch commit pull_request)
+ },
+ postInstallPage: {
+ key: 'gitlab-configuration',
+ name: {
+ value: 'GitLab Configuration'
+ },
+ url: relative_to_base_path(jira_connect_subscriptions_path)
+ }
+ },
+ apiMigrations: {
+ gdpr: true
+ }
+ }
+ end
+
+ private
+
+ def relative_to_base_path(full_path)
+ full_path.sub(/^#{jira_connect_base_path}/, '')
+ end
+end
diff --git a/app/controllers/jira_connect/application_controller.rb b/app/controllers/jira_connect/application_controller.rb
new file mode 100644
index 00000000000..a84f25998a6
--- /dev/null
+++ b/app/controllers/jira_connect/application_controller.rb
@@ -0,0 +1,57 @@
+# frozen_string_literal: true
+
+class JiraConnect::ApplicationController < ApplicationController
+ include Gitlab::Utils::StrongMemoize
+
+ skip_before_action :authenticate_user!
+ skip_before_action :verify_authenticity_token
+ before_action :verify_atlassian_jwt!
+
+ attr_reader :current_jira_installation
+
+ private
+
+ def verify_atlassian_jwt!
+ return render_403 unless atlassian_jwt_valid?
+
+ @current_jira_installation = installation_from_jwt
+ end
+
+ def verify_qsh_claim!
+ payload, _ = decode_auth_token!
+
+ # Make sure `qsh` claim matches the current request
+ render_403 unless payload['qsh'] == Atlassian::Jwt.create_query_string_hash(request.url, request.method, jira_connect_base_url)
+ rescue
+ render_403
+ end
+
+ def atlassian_jwt_valid?
+ return false unless installation_from_jwt
+
+ # Verify JWT signature with our stored `shared_secret`
+ decode_auth_token!
+ rescue JWT::DecodeError
+ false
+ end
+
+ def installation_from_jwt
+ return unless auth_token
+
+ strong_memoize(:installation_from_jwt) do
+ # Decode without verification to get `client_key` in `iss`
+ payload, _ = Atlassian::Jwt.decode(auth_token, nil, false)
+ JiraConnectInstallation.find_by_client_key(payload['iss'])
+ end
+ end
+
+ def decode_auth_token!
+ Atlassian::Jwt.decode(auth_token, installation_from_jwt.shared_secret)
+ end
+
+ def auth_token
+ strong_memoize(:auth_token) do
+ params[:jwt] || request.headers['Authorization']&.split(' ', 2)&.last
+ end
+ end
+end
diff --git a/app/controllers/jira_connect/events_controller.rb b/app/controllers/jira_connect/events_controller.rb
new file mode 100644
index 00000000000..8f79c82d847
--- /dev/null
+++ b/app/controllers/jira_connect/events_controller.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+class JiraConnect::EventsController < JiraConnect::ApplicationController
+ skip_before_action :verify_atlassian_jwt!, only: :installed
+ before_action :verify_qsh_claim!, only: :uninstalled
+
+ def installed
+ installation = JiraConnectInstallation.new(install_params)
+
+ if installation.save
+ head :ok
+ else
+ head :unprocessable_entity
+ end
+ end
+
+ def uninstalled
+ if current_jira_installation.destroy
+ head :ok
+ else
+ head :unprocessable_entity
+ end
+ end
+
+ private
+
+ def install_params
+ params.permit(:clientKey, :sharedSecret, :baseUrl).transform_keys(&:underscore)
+ end
+end
diff --git a/app/controllers/jira_connect/subscriptions_controller.rb b/app/controllers/jira_connect/subscriptions_controller.rb
new file mode 100644
index 00000000000..3ff12f29f10
--- /dev/null
+++ b/app/controllers/jira_connect/subscriptions_controller.rb
@@ -0,0 +1,56 @@
+# frozen_string_literal: true
+
+class JiraConnect::SubscriptionsController < JiraConnect::ApplicationController
+ layout 'jira_connect'
+
+ content_security_policy do |p|
+ next if p.directives.blank?
+
+ # rubocop: disable Lint/PercentStringArray
+ script_src_values = Array.wrap(p.directives['script-src']) | %w('self' https://connect-cdn.atl-paas.net https://unpkg.com/jquery@3.3.1/)
+ style_src_values = Array.wrap(p.directives['style-src']) | %w('self' 'unsafe-inline' https://unpkg.com/@atlaskit/)
+ # rubocop: enable Lint/PercentStringArray
+
+ p.frame_ancestors :self, 'https://*.atlassian.net'
+ p.script_src(*script_src_values)
+ p.style_src(*style_src_values)
+ end
+
+ before_action :allow_rendering_in_iframe, only: :index
+ before_action :verify_qsh_claim!, only: :index
+ before_action :authenticate_user!, only: :create
+
+ def index
+ @subscriptions = current_jira_installation.subscriptions.preload_namespace_route
+ end
+
+ def create
+ result = create_service.execute
+
+ if result[:status] == :success
+ render json: { success: true }
+ else
+ render json: { error: result[:message] }, status: result[:http_status]
+ end
+ end
+
+ def destroy
+ subscription = current_jira_installation.subscriptions.find(params[:id])
+
+ if subscription.destroy
+ render json: { success: true }
+ else
+ render json: { error: subscription.errors.full_messages.join(', ') }, status: :unprocessable_entity
+ end
+ end
+
+ private
+
+ def create_service
+ JiraConnectSubscriptions::CreateService.new(current_jira_installation, current_user, namespace_path: params['namespace_path'])
+ end
+
+ def allow_rendering_in_iframe
+ response.headers.delete('X-Frame-Options')
+ end
+end
diff --git a/app/controllers/oauth/jira/authorizations_controller.rb b/app/controllers/oauth/jira/authorizations_controller.rb
new file mode 100644
index 00000000000..a3e30ffc993
--- /dev/null
+++ b/app/controllers/oauth/jira/authorizations_controller.rb
@@ -0,0 +1,48 @@
+# frozen_string_literal: true
+
+# This controller's role is to mimic and rewire the GitLab OAuth
+# flow routes for Jira DVCS integration.
+# See https://gitlab.com/gitlab-org/gitlab/issues/2381
+#
+class Oauth::Jira::AuthorizationsController < ApplicationController
+ skip_before_action :authenticate_user!
+ skip_before_action :verify_authenticity_token
+
+ # 1. Rewire Jira OAuth initial request to our stablished OAuth authorization URL.
+ def new
+ session[:redirect_uri] = params['redirect_uri']
+
+ redirect_to oauth_authorization_path(client_id: params['client_id'],
+ response_type: 'code',
+ redirect_uri: oauth_jira_callback_url)
+ end
+
+ # 2. Handle the callback call as we were a Github Enterprise instance client.
+ def callback
+ # Handling URI query params concatenation.
+ redirect_uri = URI.parse(session['redirect_uri'])
+ new_query = URI.decode_www_form(String(redirect_uri.query)) << ['code', params[:code]]
+ redirect_uri.query = URI.encode_www_form(new_query)
+
+ redirect_to redirect_uri.to_s
+ end
+
+ # 3. Rewire and adjust access_token request accordingly.
+ def access_token
+ # We have to modify request.parameters because Doorkeeper::Server reads params from there
+ request.parameters[:redirect_uri] = oauth_jira_callback_url
+
+ strategy = Doorkeeper::Server.new(self).token_request('authorization_code')
+ response = strategy.authorize
+
+ if response.status == :ok
+ access_token, scope, token_type = response.body.values_at('access_token', 'scope', 'token_type')
+
+ render body: "access_token=#{access_token}&scope=#{scope}&token_type=#{token_type}"
+ else
+ render status: response.status, body: response.body
+ end
+ rescue Doorkeeper::Errors::DoorkeeperError => e
+ render status: :unauthorized, body: e.type
+ end
+end
diff --git a/app/controllers/passwords_controller.rb b/app/controllers/passwords_controller.rb
index af860297358..c27226c3f3f 100644
--- a/app/controllers/passwords_controller.rb
+++ b/app/controllers/passwords_controller.rb
@@ -31,8 +31,10 @@ class PasswordsController < Devise::PasswordsController
def update
super do |resource|
- if resource.valid? && resource.password_automatically_set?
- resource.update_attribute(:password_automatically_set, false)
+ if resource.valid?
+ resource.password_automatically_set = false
+ resource.password_expires_at = nil
+ resource.save(validate: false) if resource.changed?
end
end
end