internal.rb 3.61 KB
Newer Older
1
module API
2
  # Internal access API
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
3
  class Internal < Grape::API
4
    before { authenticate_by_gitlab_shell_token! }
5

6 7
    helpers ::API::Helpers::InternalHelpers

8
    namespace 'internal' do
9
      # Check if git command is allowed to project
10
      #
11
      # Params:
12 13
      #   key_id - ssh key id for Git over SSH
      #   user_id - user id for Git over HTTP
14 15 16
      #   project - project path with namespace
      #   action - git action (git-upload-pack or git-receive-pack)
      #   ref - branch name
17
      #   forced_push - forced_push
18
      #   protocol - Git access protocol being used, e.g. HTTP or SSH
19
      post "/allowed" do
20
        status 200
21

22
        actor =
23 24 25 26 27
          if params[:key_id]
            Key.find_by(id: params[:key_id])
          elsif params[:user_id]
            User.find_by(id: params[:user_id])
          end
28

29 30
        protocol = params[:protocol]

31
        access =
32
          if wiki?
33
            Gitlab::GitAccessWiki.new(actor, project, protocol, authentication_abilities: ssh_authentication_abilities)
34
          else
35 36 37 38 39
            Gitlab::GitAccess.new(actor,
                                  project,
                                  protocol,
                                  authentication_abilities: ssh_authentication_abilities,
                                  env: parse_allowed_environment_variables)
40
          end
41

42 43 44 45 46 47 48
        access_status = access.check(params[:action], params[:changes])

        response = { status: access_status.status, message: access_status.message }

        if access_status.status
          # Return the repository full path so that gitlab-shell has it when
          # handling ssh commands
49 50 51 52 53 54
          response[:repository_path] =
            if wiki?
              project.wiki.repository.path_to_repo
            else
              project.repository.path_to_repo
            end
55 56 57
        end

        response
58 59
      end

60 61 62 63 64 65 66 67
      post "/lfs_authenticate" do
        status 200

        key = Key.find(params[:key_id])
        token_handler = Gitlab::LfsToken.new(key)

        {
          username: token_handler.actor_name,
68
          lfs_token: token_handler.token,
69 70 71 72
          repository_http_path: project.http_url_to_repo
        }
      end

73 74 75 76
      get "/merge_request_urls" do
        ::MergeRequests::GetUrlsService.new(project).execute(params[:changes])
      end

77 78 79 80 81
      #
      # Discover user by ssh key
      #
      get "/discover" do
        key = Key.find(params[:key_id])
82
        present key.user, with: Entities::UserSafe
83
      end
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
84 85 86

      get "/check" do
        {
87
          api_version: API.version,
88 89
          gitlab_version: Gitlab::VERSION,
          gitlab_rev: Gitlab::REVISION,
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
90 91
        }
      end
92 93 94 95

      get "/broadcast_message" do
        if message = BroadcastMessage.current
          present message, with: Entities::BroadcastMessage
96 97
        else
          {}
98 99
        end
      end
100 101 102 103

      post '/two_factor_recovery_codes' do
        status 200

104 105 106 107 108
        key = Key.find_by(id: params[:key_id])

        unless key
          return { 'success' => false, 'message' => 'Could not find the given key' }
        end
109

110
        if key.is_a?(DeployKey)
111 112 113
          return { success: false, message: 'Deploy keys cannot be used to retrieve recovery codes' }
        end

114 115 116
        user = key.user

        unless user
117 118 119 120 121 122 123 124 125 126 127 128
          return { success: false, message: 'Could not find a user for the given key' }
        end

        unless user.two_factor_enabled?
          return { success: false, message: 'Two-factor authentication is not enabled for this user' }
        end

        codes = user.generate_otp_backup_codes!
        user.save!

        { success: true, recovery_codes: codes }
      end
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
129 130 131
    end
  end
end