# frozen_string_literal: true

class Discourse::Cors
  ORIGINS_ENV = "Discourse_Cors_Origins"

  def initialize(app, options = nil)
    @app = app
    if GlobalSetting.enable_cors && GlobalSetting.cors_origin.present?
      @global_origins = GlobalSetting.cors_origin.split(",").map { |x| x.strip.chomp("/") }
    end
  end

  def call(env)
    return @app.call(env) if !GlobalSetting.enable_cors && !GlobalSetting.cdn_url

    cors_origins = @global_origins || []
    cors_origins += SiteSetting.cors_origins.split("|") if SiteSetting.cors_origins.present?
    cors_origins = cors_origins.presence

    if env["REQUEST_METHOD"] == ("OPTIONS") && env["HTTP_ACCESS_CONTROL_REQUEST_METHOD"]
      return 200, Discourse::Cors.apply_headers(cors_origins, env, {}), []
    end

    env[Discourse::Cors::ORIGINS_ENV] = cors_origins if cors_origins

    status, headers, body = @app.call(env)
    headers ||= {}

    Discourse::Cors.apply_headers(cors_origins, env, headers)

    [status, headers, body]
  end

  def self.apply_headers(cors_origins, env, headers)
    request_method = env["REQUEST_METHOD"]

    if headers["Access-Control-Allow-Origin"]
      # Already configured. Probably by ApplicationController#apply_cdn_headers
    elsif cors_origins
      origin = nil
      if origin = env["HTTP_ORIGIN"]
        origin = nil if cors_origins.exclude?(origin)
      end

      headers["Access-Control-Allow-Origin"] = origin || cors_origins[0]
      headers[
        "Access-Control-Allow-Headers"
      ] = "Content-Type, Cache-Control, X-Requested-With, X-CSRF-Token, Discourse-Present, User-Api-Key, User-Api-Client-Id, Authorization"
      headers["Access-Control-Allow-Credentials"] = "true"
      headers["Access-Control-Allow-Methods"] = "POST, PUT, GET, OPTIONS, DELETE"
      headers["Access-Control-Max-Age"] = "7200"
    end

    headers
  end
end

Rails.configuration.middleware.insert_before ActionDispatch::Flash, Discourse::Cors