require_dependency 'declarative_policy'

module API
  class ProjectMirror < Grape::API
    helpers do
      def github_webhook_signature
        @github_webhook_signature ||= headers['X-Hub-Signature']
      end

      def authenticate_from_github_webhook!
        return unless github_webhook_signature

        unless valid_github_signature?
          Guest.can?(:read_project, project) ? unauthorized! : not_found!
        end
      end

      def valid_github_signature?
        request.body.rewind

        token        = project.external_webhook_token
        payload_body = request.body.read
        signature    = 'sha1=' + OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha1'), token, payload_body)

        Rack::Utils.secure_compare(signature, github_webhook_signature)
      end

      def authenticate_with_webhook_token!
        if github_webhook_signature
          not_found! unless project

          authenticate_from_github_webhook!
        else
          authenticate!
          authorize_admin_project
        end
      end

      def project
        @project ||= github_webhook_signature ? find_project(params[:id]) : user_project
      end
    end

    params do
      requires :id, type: String, desc: 'The ID of a project'
    end
    resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
      desc 'Triggers a pull mirror operation'
      post ":id/mirror/pull" do
        authenticate_with_webhook_token!

        break render_api_error!('The project is not mirrored', 400) unless project.mirror?

        project.import_state.force_import_job!

        status 200
      end
    end
  end
end