# frozen_string_literal: true module StaticSiteEditor class ConfigService < ::BaseContainerService ValidationError = Class.new(StandardError) def initialize(container:, current_user: nil, params: {}) super @project = container @repository = project.repository @ref = params.fetch(:ref) end def execute check_access! file_config = load_file_config! file_data = file_config.to_hash_with_defaults generated_data = load_generated_config.data check_for_duplicate_keys!(generated_data, file_data) data = merged_data(generated_data, file_data) ServiceResponse.success(payload: data) rescue ValidationError => e ServiceResponse.error(message: e.message) rescue => e Gitlab::ErrorTracking.track_and_raise_exception(e) end private attr_reader :project, :repository, :ref def static_site_editor_config_file '.gitlab/static-site-editor.yml' end def check_access! unless can?(current_user, :download_code, project) raise ValidationError, 'Insufficient permissions to read configuration' end end def load_file_config! yaml = yaml_from_repo.presence || '{}' file_config = Gitlab::StaticSiteEditor::Config::FileConfig.new(yaml) unless file_config.valid? raise ValidationError, file_config.errors.first end file_config rescue Gitlab::StaticSiteEditor::Config::FileConfig::ConfigError => e raise ValidationError, e.message end def load_generated_config Gitlab::StaticSiteEditor::Config::GeneratedConfig.new( repository, ref, params.fetch(:path), params[:return_url] ) end def check_for_duplicate_keys!(generated_data, file_data) duplicate_keys = generated_data.keys & file_data.keys raise ValidationError.new("Duplicate key(s) '#{duplicate_keys}' found.") if duplicate_keys.present? end def merged_data(generated_data, file_data) generated_data.merge(file_data) end def yaml_from_repo repository.blob_data_at(ref, static_site_editor_config_file) rescue GRPC::NotFound # Return nil in the case of a GRPC::NotFound exception, so the default config will be used. # Allow any other unexpected exception will be tracked and re-raised. nil end end end