1# frozen_string_literal: true
2
3module API
4  module Terraform
5    class StateVersion < ::API::Base
6      default_format :json
7
8      feature_category :infrastructure_as_code
9
10      before do
11        authenticate!
12        authorize! :read_terraform_state, user_project
13      end
14
15      params do
16        requires :id, type: String, desc: 'The ID of a project'
17      end
18
19      resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
20        namespace ':id/terraform/state/:name/versions/:serial' do
21          params do
22            requires :name, type: String, desc: 'The name of a Terraform state'
23            requires :serial, type: Integer, desc: 'The version number of the state'
24          end
25
26          helpers do
27            def remote_state_handler
28              ::Terraform::RemoteStateHandler.new(user_project, current_user, name: params[:name])
29            end
30
31            def find_version(serial)
32              remote_state_handler.find_with_lock do |state|
33                version = state.versions.find_by_version(serial)
34
35                if version.present?
36                  yield version
37                else
38                  not_found!
39                end
40              end
41            end
42          end
43
44          desc 'Get a terraform state version'
45          route_setting :authentication, basic_auth_personal_access_token: true, job_token_allowed: :basic_auth
46          get do
47            find_version(params[:serial]) do |version|
48              env['api.format'] = :binary # Bypass json serialization
49              body version.file.read
50              status :ok
51            end
52          end
53
54          desc 'Delete a terraform state version'
55          route_setting :authentication, basic_auth_personal_access_token: true, job_token_allowed: :basic_auth
56          delete do
57            authorize! :admin_terraform_state, user_project
58
59            find_version(params[:serial]) do |version|
60              version.destroy!
61
62              body false
63              status :no_content
64            end
65          end
66        end
67      end
68    end
69  end
70end
71