From b1bcd8c78798c08f22b285636e9bd78859e99796 Mon Sep 17 00:00:00 2001
From: Aishwarya Subramanian <asubramanian@gitlab.com>
Date: Wed, 11 Sep 2019 15:03:32 +0000
Subject: [PATCH] Added controller for country list

Added specs for countries controller
Added missing frozen string literal
Reworded comments for gemfile
Addressing Rubocop public_send offence
---
 Gemfile                                       |  3 +
 Gemfile.lock                                  |  8 +++
 config/dependency_decisions.yml               |  7 +++
 config/initializers/countries.rb              | 61 +++++++++++++++++++
 config/routes.rb                              |  1 +
 ee/app/controllers/countries_controller.rb    | 12 ++++
 ee/config/routes/country.rb                   |  3 +
 ee/lib/world.rb                               | 16 +++++
 .../controllers/countries_controller_spec.rb  | 25 ++++++++
 ee/spec/lib/world_spec.rb                     | 21 +++++++
 10 files changed, 157 insertions(+)
 create mode 100644 config/initializers/countries.rb
 create mode 100644 ee/app/controllers/countries_controller.rb
 create mode 100644 ee/config/routes/country.rb
 create mode 100644 ee/lib/world.rb
 create mode 100644 ee/spec/controllers/countries_controller_spec.rb
 create mode 100644 ee/spec/lib/world_spec.rb

diff --git a/Gemfile b/Gemfile
index ea521c7f19156..088ce9a0aef72 100644
--- a/Gemfile
+++ b/Gemfile
@@ -465,3 +465,6 @@ gem 'grape_logging', '~> 1.7'
 
 # DNS Lookup
 gem 'net-dns', '~> 0.9.0'
+
+# Countries list
+gem 'countries', '~> 3.0'
diff --git a/Gemfile.lock b/Gemfile.lock
index df572cbe0e0db..2d6d3d196d8e3 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -167,6 +167,10 @@ GEM
     contracts (0.11.0)
     cork (0.3.0)
       colored2 (~> 3.1)
+    countries (3.0.0)
+      i18n_data (~> 0.8.0)
+      sixarm_ruby_unaccent (~> 1.1)
+      unicode_utils (~> 1.4)
     crack (0.4.3)
       safe_yaml (~> 1.0.0)
     crass (1.0.4)
@@ -485,6 +489,7 @@ GEM
     httpclient (2.8.3)
     i18n (1.6.0)
       concurrent-ruby (~> 1.0)
+    i18n_data (0.8.0)
     icalendar (2.4.1)
     ice_nine (0.11.2)
     influxdb (0.2.3)
@@ -954,6 +959,7 @@ GEM
       json (>= 1.8, < 3)
       simplecov-html (~> 0.10.0)
     simplecov-html (0.10.2)
+    sixarm_ruby_unaccent (1.2.0)
     slack-notifier (1.5.1)
     snowplow-tracker (0.6.1)
       contracts (~> 0.7, <= 0.11)
@@ -1018,6 +1024,7 @@ GEM
       unf_ext
     unf_ext (0.0.7.5)
     unicode-display_width (1.6.0)
+    unicode_utils (1.4.0)
     unicorn (5.4.1)
       kgio (~> 2.6)
       raindrops (~> 0.7)
@@ -1117,6 +1124,7 @@ DEPENDENCIES
   commonmarker (~> 0.17)
   concurrent-ruby (~> 1.1)
   connection_pool (~> 2.0)
+  countries (~> 3.0)
   creole (~> 0.5.0)
   danger (~> 6.0)
   database_cleaner (~> 1.7.0)
diff --git a/config/dependency_decisions.yml b/config/dependency_decisions.yml
index 33c909895487d..5346bf4547316 100644
--- a/config/dependency_decisions.yml
+++ b/config/dependency_decisions.yml
@@ -613,3 +613,10 @@
     :why: https://bitbucket.org/atlassian/atlassian-jwt-ruby/src/master/LICENSE.txt
     :versions: []
     :when: 2019-08-30 05:45:35.317663000 Z
+- - :license
+  - unicode_utils
+  - MIT
+  - :who: Aishwarya Subramanain
+    :why: https://github.com/hexorx/countries/blob/master/LICENSE
+    :versions: []
+    :when: 2019-09-11 13:08:28.431132000 Z
diff --git a/config/initializers/countries.rb b/config/initializers/countries.rb
new file mode 100644
index 0000000000000..d65ae19852f0e
--- /dev/null
+++ b/config/initializers/countries.rb
@@ -0,0 +1,61 @@
+# frozen_string_literal: true
+
+ISO3166.configure do |config|
+  config.locales = [:en]
+end
+
+# GitLab permits users to sign up in Ukraine except the Crimean Region: https://about.gitlab.com/handbook/people-operations/code-of-conduct/#trade-compliance-exportimport-control
+# This overrides the display name for Ukraine to Ukraine (except Crimean Region)
+# To be removed after https://gitlab.com/gitlab-org/gitlab-ee/issues/14784 is implemented
+# Data fetched is based on https://github.com/hexorx/countries/blob/master/lib/countries/data/countries/UA.yaml
+ISO3166::Data.register(
+  continent: "Europe",
+  address_format: "|-
+  {{recipient}}
+  {{street}}
+  {{city}} {{region_short}}
+  {{postalcode}}
+  {{country}}",
+  alpha2: "UA",
+  alpha3: "UKR",
+  country_code: '380',
+  international_prefix: '810',
+  ioc: "UKR",
+  gec: "UP",
+  name: "Ukraine (except Crimean Region)",
+  national_destination_code_lengths: [2],
+  national_number_lengths: [8, 9],
+  national_prefix: '8',
+  number: '804',
+  region: "Europe",
+  subregion: "Eastern Europe",
+  world_region: "EMEA",
+  un_locode: "UA",
+  nationality: "Ukrainian",
+  vat_rates: {
+    standard: 20
+  },
+  reduced: [7],
+  super_reduced: {
+    parking: { postal_code: true }
+  },
+  unofficial_names: %w(Ukraine Ucrania ウクライナ Oekraïne Украина Україна Украіна),
+  languages_official: ["uk"],
+  languages_spoken: ["uk"],
+  geo: {
+    latitude: 48.379433,
+    latitude_dec: '48.92656326293945',
+    longitude: 31.16558,
+    longitude_dec: '31.47578239440918',
+    max_latitude: 52.37958099999999,
+    max_longitude: 40.2285809,
+    min_latitude: 44.2924,
+    min_longitude: 22.137159,
+    bounds: {
+      northeast: { lat: 52.37958099999999, lng: 40.2285809 },
+      southwest: { lat: 44.2924, lng: 22.137159 }
+    }
+  },
+  currency_code: "UAH",
+  start_of_week: "monday"
+)
diff --git a/config/routes.rb b/config/routes.rb
index 8ba3a7f3130a7..9dbcd7fffa2c8 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -113,6 +113,7 @@
       draw :username
       draw :trial
       draw :trial_registration
+      draw :country
     end
 
     Gitlab.ee do
diff --git a/ee/app/controllers/countries_controller.rb b/ee/app/controllers/countries_controller.rb
new file mode 100644
index 0000000000000..f703258e3c282
--- /dev/null
+++ b/ee/app/controllers/countries_controller.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+class CountriesController < ActionController::Metal
+  include AbstractController::Rendering
+  include ActionController::Renderers::All
+
+  def index
+    countries = World.countries_for_select
+
+    render json: countries, status: (countries ? :ok : :not_found)
+  end
+end
diff --git a/ee/config/routes/country.rb b/ee/config/routes/country.rb
new file mode 100644
index 0000000000000..419e37485bc36
--- /dev/null
+++ b/ee/config/routes/country.rb
@@ -0,0 +1,3 @@
+# frozen_string_literal: true
+
+resources :countries, only: [:index]
diff --git a/ee/lib/world.rb b/ee/lib/world.rb
new file mode 100644
index 0000000000000..d99f8573f33ca
--- /dev/null
+++ b/ee/lib/world.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+module World
+  include ::Gitlab::Utils::StrongMemoize
+  extend self
+
+  DENYLIST = ['Iran (Islamic Republic of)', 'Sudan', 'Syrian Arab Republic', 'Korea', 'Democratic People\'s Republic of', 'Cuba'].freeze
+
+  def countries_for_select
+    strong_memoize(:countries_for_select) { all_countries.sort_by(&:name).map { |c| [c.name, c.alpha2] } }
+  end
+
+  def all_countries
+    strong_memoize(:all_countries) { ISO3166::Country.all.reject {|item| DENYLIST.include?(item.name) } }
+  end
+end
diff --git a/ee/spec/controllers/countries_controller_spec.rb b/ee/spec/controllers/countries_controller_spec.rb
new file mode 100644
index 0000000000000..315fbefa8d706
--- /dev/null
+++ b/ee/spec/controllers/countries_controller_spec.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe CountriesController do
+  describe 'GET #index' do
+    it 'returns list of countries as json' do
+      get :index
+
+      expected_json = World.countries_for_select.to_json
+
+      expect(response.status).to eq(200)
+      expect(response.body).to eq(expected_json)
+    end
+
+    it 'does not include list of denied countries' do
+      get :index
+
+      # response is returned as [["Afghanistan", "AF"], ["Albania", "AL"], ..]
+      resultant_countries = JSON.parse(response.body).map {|row| row[0]}
+
+      expect(resultant_countries).not_to include(World::DENYLIST)
+    end
+  end
+end
diff --git a/ee/spec/lib/world_spec.rb b/ee/spec/lib/world_spec.rb
new file mode 100644
index 0000000000000..f4ec8977ad0a4
--- /dev/null
+++ b/ee/spec/lib/world_spec.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe World do
+  describe '.all_countries' do
+    it 'does not return countries that are in the denied list' do
+      result = described_class.all_countries
+
+      expect(result.map(&:name)).not_to include(World::DENYLIST)
+    end
+  end
+
+  describe '.countries_for_select' do
+    it 'returns list of country name and iso_code in alphabetical format' do
+      result = described_class.countries_for_select
+
+      expect(result.first).to eq(%w[Afghanistan AF])
+    end
+  end
+end
-- 
GitLab