summaryrefslogtreecommitdiff
path: root/lib/api/helpers/internal_helpers.rb
blob: bff245fe9a2dca50ae3fd53f233a8f7fc599e6df (plain)
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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
module API
  module Helpers
    module InternalHelpers
      include Gitlab::Utils::StrongMemoize

      attr_reader :redirected_path

      def wiki?
        set_project unless defined?(@wiki) # rubocop:disable Gitlab/ModuleWithInstanceVariables
        @wiki # rubocop:disable Gitlab/ModuleWithInstanceVariables
      end

      def project
        set_project unless defined?(@project) # rubocop:disable Gitlab/ModuleWithInstanceVariables
        @project # rubocop:disable Gitlab/ModuleWithInstanceVariables
      end

      def ssh_authentication_abilities
        [
          :read_project,
          :download_code,
          :push_code
        ]
      end

      def parse_env
        return {} if params[:env].blank?

        JSON.parse(params[:env])
      rescue JSON::ParserError
        {}
      end

      def fix_git_env_repository_paths(env, repository_path)
        if obj_dir_relative = env['GIT_OBJECT_DIRECTORY_RELATIVE'].presence
          env['GIT_OBJECT_DIRECTORY'] = File.join(repository_path, obj_dir_relative)
        end

        if alt_obj_dirs_relative = env['GIT_ALTERNATE_OBJECT_DIRECTORIES_RELATIVE'].presence
          env['GIT_ALTERNATE_OBJECT_DIRECTORIES'] = alt_obj_dirs_relative.map { |dir| File.join(repository_path, dir) }
        end

        env
      end

      def log_user_activity(actor)
        commands = Gitlab::GitAccess::DOWNLOAD_COMMANDS

        ::Users::ActivityService.new(actor, 'Git SSH').execute if commands.include?(params[:action])
      end

      def receive_pack?
        params[:action] == 'git-receive-pack'
      end

      def merge_request_urls
        ::MergeRequests::GetUrlsService.new(project).execute(params[:changes])
      end

      def redis_ping
        result = Gitlab::Redis::SharedState.with { |redis| redis.ping }

        result == 'PONG'
      rescue => e
        Rails.logger.warn("GitLab: An unexpected error occurred in pinging to Redis: #{e}")
        false
      end

      def project_namespace
        strong_memoize(:project_namespace) do
          project&.namespace || Namespace.find_by_full_path(project_match[:namespace_path])
        end
      end

      private

      def project_match
        @project_match ||= params[:project].match(Gitlab::PathRegex.full_project_git_path_regex) || {}
      end

      # rubocop:disable Gitlab/ModuleWithInstanceVariables
      def set_project
        if params[:gl_repository]
          @project, @wiki = Gitlab::GlRepository.parse(params[:gl_repository])
          @redirected_path = nil
        else
          @project, @wiki, @redirected_path = Gitlab::RepoPath.parse(params[:project])
        end
      end
      # rubocop:enable Gitlab/ModuleWithInstanceVariables

      # Project id to pass between components that don't share/don't have
      # access to the same filesystem mounts
      def gl_repository
        Gitlab::GlRepository.gl_repository(project, wiki?)
      end

      # Return the repository depending on whether we want the wiki or the
      # regular repository
      def repository
        if wiki?
          project.wiki.repository
        else
          project.repository
        end
      end

      # Return the repository full path so that gitlab-shell has it when
      # handling ssh commands
      def repository_path
        repository.path_to_repo
      end

      # Return the Gitaly Address if it is enabled
      def gitaly_payload(action)
        return unless %w[git-receive-pack git-upload-pack].include?(action)

        if action == 'git-receive-pack'
          return unless Gitlab::GitalyClient.feature_enabled?(
            :ssh_receive_pack,
            status: Gitlab::GitalyClient::MigrationStatus::OPT_OUT
          )
        end

        {
          repository: repository.gitaly_repository,
          address: Gitlab::GitalyClient.address(project.repository_storage),
          token: Gitlab::GitalyClient.token(project.repository_storage)
        }
      end
    end
  end
end