Make chat authorization to work [ci skip]
This commit is contained in:
		
							parent
							
								
									4762198959
								
							
						
					
					
						commit
						53271b486d
					
				| 
						 | 
				
			
			@ -28,6 +28,8 @@ class Projects::ServicesController < Projects::ApplicationController
 | 
			
		|||
  end
 | 
			
		||||
 | 
			
		||||
  def test
 | 
			
		||||
    return render_404 unless @service.can_test?
 | 
			
		||||
 | 
			
		||||
    data = @service.test_data(project, current_user)
 | 
			
		||||
    outcome = @service.test(data)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,4 +6,8 @@ module TriggersHelper
 | 
			
		|||
      "#{Settings.gitlab.url}/api/v3/projects/#{project_id}/ref/#{ref}/trigger/builds"
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def service_trigger_url(service)
 | 
			
		||||
    "#{Settings.gitlab.url}/api/v3/projects/#{service.project_id}/services/#{service.to_param}/trigger"
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -23,8 +23,8 @@ class Project < ActiveRecord::Base
 | 
			
		|||
 | 
			
		||||
  cache_markdown_field :description, pipeline: :description
 | 
			
		||||
 | 
			
		||||
  delegate :feature_available?, :builds_enabled?, :wiki_enabled?, 
 | 
			
		||||
           :merge_requests_enabled?, :issues_enabled?, to: :project_feature, 
 | 
			
		||||
  delegate :feature_available?, :builds_enabled?, :wiki_enabled?,
 | 
			
		||||
           :merge_requests_enabled?, :issues_enabled?, to: :project_feature,
 | 
			
		||||
                                                       allow_nil: true
 | 
			
		||||
 | 
			
		||||
  default_value_for :archived, false
 | 
			
		||||
| 
						 | 
				
			
			@ -91,6 +91,7 @@ class Project < ActiveRecord::Base
 | 
			
		|||
  has_one :assembla_service, dependent: :destroy
 | 
			
		||||
  has_one :asana_service, dependent: :destroy
 | 
			
		||||
  has_one :gemnasium_service, dependent: :destroy
 | 
			
		||||
  has_one :mattermost_chat_service, dependent: :destroy
 | 
			
		||||
  has_one :slack_service, dependent: :destroy
 | 
			
		||||
  has_one :buildkite_service, dependent: :destroy
 | 
			
		||||
  has_one :bamboo_service, dependent: :destroy
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,13 +3,16 @@
 | 
			
		|||
class ChatService < Service
 | 
			
		||||
  default_value_for :category, 'chat'
 | 
			
		||||
 | 
			
		||||
  has_many :chat_users
 | 
			
		||||
  has_many :chat_names, foreign_key: :service_id
 | 
			
		||||
 | 
			
		||||
  def valid_token?(token)
 | 
			
		||||
    self.respond_to?(:token) && self.token.present? && ActiveSupport::SecurityUtils.variable_size_secure_compare(token, self.token)
 | 
			
		||||
    self.respond_to?(:token) &&
 | 
			
		||||
      self.token.present? &&
 | 
			
		||||
      ActiveSupport::SecurityUtils.variable_size_secure_compare(token, self.token)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def supported_events
 | 
			
		||||
    []
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def trigger(params)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,12 @@
 | 
			
		|||
# Base class for Chat services
 | 
			
		||||
class MattermostChatService < ChatService
 | 
			
		||||
  include TriggersHelper
 | 
			
		||||
 | 
			
		||||
  prop_accessor :token
 | 
			
		||||
 | 
			
		||||
  def can_test?
 | 
			
		||||
    false
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def title
 | 
			
		||||
    'Mattermost'
 | 
			
		||||
  end
 | 
			
		||||
| 
						 | 
				
			
			@ -13,28 +20,40 @@ class MattermostChatService < ChatService
 | 
			
		|||
  end
 | 
			
		||||
 | 
			
		||||
  def help
 | 
			
		||||
    'This service allows you to use slash commands with your Mattermost installation.<br/>
 | 
			
		||||
    To setup this Service you need to create a new <b>"Slash commands"</b> in your Mattermost integration panel,
 | 
			
		||||
    and enter the token below.'
 | 
			
		||||
    "This service allows you to use slash commands with your Mattermost installation.<br/>
 | 
			
		||||
    To setup this Service you need to create a new <b>Slash commands</b> in your Mattermost integration panel.<br/>
 | 
			
		||||
    <br/>
 | 
			
		||||
    Create integration with URL #{service_trigger_url(self)} and enter the token below."
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def fields
 | 
			
		||||
    [
 | 
			
		||||
      { type: 'text', name: 'token', placeholder: 'https://hooks.slack.com/services/...' }
 | 
			
		||||
      { type: 'text', name: 'token', placeholder: '' }
 | 
			
		||||
    ]
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def trigger(params)
 | 
			
		||||
    user = ChatNames::FindUserService.new(chat_names, params).execute
 | 
			
		||||
    return nil unless valid_token?(params[:token])
 | 
			
		||||
 | 
			
		||||
    user = find_chat_user(params)
 | 
			
		||||
    return authorize_chat_name(params) unless user
 | 
			
		||||
 | 
			
		||||
    Mattermost::CommandService.new(project, user, params).execute
 | 
			
		||||
    Mattermost::CommandService.new(project, user, params.slice(:command, :text)).
 | 
			
		||||
      execute
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  private
 | 
			
		||||
 | 
			
		||||
  def find_chat_user(params)
 | 
			
		||||
    params = params.slice(:team_id, :user_id)
 | 
			
		||||
    ChatNames::FindUserService.
 | 
			
		||||
      new(chat_names, params).
 | 
			
		||||
      execute
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def authorize_chat_name(params)
 | 
			
		||||
    url = ChatNames::RequestService.new(service, params).execute
 | 
			
		||||
    params = params.slice(:team_id, :team_domain, :user_id, :user_name)
 | 
			
		||||
    url = ChatNames::AuthorizeUserService.new(self, params).execute
 | 
			
		||||
 | 
			
		||||
    {
 | 
			
		||||
      response_type: :ephemeral,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -214,6 +214,7 @@ class Service < ActiveRecord::Base
 | 
			
		|||
      hipchat
 | 
			
		||||
      irker
 | 
			
		||||
      jira
 | 
			
		||||
      mattermost_chat
 | 
			
		||||
      pivotaltracker
 | 
			
		||||
      pushover
 | 
			
		||||
      redmine
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -10,26 +10,27 @@
 | 
			
		|||
  .col-sm-10
 | 
			
		||||
    = form.check_box :active
 | 
			
		||||
 | 
			
		||||
.form-group
 | 
			
		||||
  = form.label :url, "Trigger", class: 'control-label'
 | 
			
		||||
- if @service.supported_events.present?
 | 
			
		||||
  .form-group
 | 
			
		||||
    = form.label :url, "Trigger", class: 'control-label'
 | 
			
		||||
 | 
			
		||||
  .col-sm-10
 | 
			
		||||
    - @service.supported_events.each do |event|
 | 
			
		||||
      %div
 | 
			
		||||
        = form.check_box service_event_field_name(event), class: 'pull-left'
 | 
			
		||||
        .prepend-left-20
 | 
			
		||||
          = form.label service_event_field_name(event), class: 'list-label' do
 | 
			
		||||
            %strong
 | 
			
		||||
              = event.humanize
 | 
			
		||||
    .col-sm-10
 | 
			
		||||
      - @service.supported_events.each do |event|
 | 
			
		||||
        %div
 | 
			
		||||
          = form.check_box service_event_field_name(event), class: 'pull-left'
 | 
			
		||||
          .prepend-left-20
 | 
			
		||||
            = form.label service_event_field_name(event), class: 'list-label' do
 | 
			
		||||
              %strong
 | 
			
		||||
                = event.humanize
 | 
			
		||||
 | 
			
		||||
      - field = @service.event_field(event)
 | 
			
		||||
        - field = @service.event_field(event)
 | 
			
		||||
 | 
			
		||||
      - if field
 | 
			
		||||
        %p
 | 
			
		||||
          = form.text_field field[:name], class: "form-control", placeholder: field[:placeholder]
 | 
			
		||||
        - if field
 | 
			
		||||
          %p
 | 
			
		||||
            = form.text_field field[:name], class: "form-control", placeholder: field[:placeholder]
 | 
			
		||||
 | 
			
		||||
      %p.light
 | 
			
		||||
        = service_event_description(event)
 | 
			
		||||
        %p.light
 | 
			
		||||
          = service_event_description(event)
 | 
			
		||||
 | 
			
		||||
- @service.global_fields.each do |field|
 | 
			
		||||
  - type = field[:type]
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -45,4 +45,7 @@ Rails.application.configure do
 | 
			
		|||
 | 
			
		||||
  # Do not log asset requests
 | 
			
		||||
  config.assets.quiet = true
 | 
			
		||||
 | 
			
		||||
  # Make hot reloading to work with Grape API
 | 
			
		||||
  ActiveSupport::Dependencies.explicitly_unloadable_constants << "API"
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,10 +1,10 @@
 | 
			
		|||
module API
 | 
			
		||||
  # Projects API
 | 
			
		||||
  class Services < Grape::API
 | 
			
		||||
    before { authenticate! }
 | 
			
		||||
    before { authorize_admin_project }
 | 
			
		||||
 | 
			
		||||
    resource :projects do
 | 
			
		||||
      before { authenticate! }
 | 
			
		||||
      before { authorize_admin_project }
 | 
			
		||||
 | 
			
		||||
      # Set <service_slug> service for project
 | 
			
		||||
      #
 | 
			
		||||
      # Example Request:
 | 
			
		||||
| 
						 | 
				
			
			@ -59,5 +59,28 @@ module API
 | 
			
		|||
        present project_service, with: Entities::ProjectService, include_passwords: current_user.is_admin?
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    resource :projects do
 | 
			
		||||
      post ':id/services/:service_slug/trigger' do
 | 
			
		||||
        project = Project.find_with_namespace(params[:id]) || Project.find_by(id: params[:id])
 | 
			
		||||
 | 
			
		||||
        underscored_service = params[:service_slug].underscore
 | 
			
		||||
 | 
			
		||||
        not_found!('Service') unless Service.available_services_names.include?(underscored_service)
 | 
			
		||||
        service_method = "#{underscored_service}_service"
 | 
			
		||||
 | 
			
		||||
        service = project.public_send(service_method)
 | 
			
		||||
 | 
			
		||||
        result = if service.try(:active?) && service.respond_to?(:trigger)
 | 
			
		||||
          service.trigger(params)
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        if result
 | 
			
		||||
          present result, status: result[:status] || 200
 | 
			
		||||
        else
 | 
			
		||||
          not_found!('Service')
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue