From f4fb3545b0749d3d7263ef1d4561706b2b0ed6fb Mon Sep 17 00:00:00 2001 From: Seth Vargo Date: Wed, 23 Sep 2020 18:05:07 -0400 Subject: [PATCH] Add SMS country picker for default code --- cmd/server/assets/header.html | 5 + cmd/server/assets/home.html | 9 + cmd/server/assets/realm.html | 4 +- cmd/server/assets/realmadmin/_form_sms.html | 16 ++ pkg/controller/realmadmin/settings.go | 3 + pkg/database/countries.go | 246 ++++++++++++++++++++ pkg/database/migrations.go | 19 ++ pkg/database/realm.go | 8 + 8 files changed, 308 insertions(+), 2 deletions(-) create mode 100644 pkg/database/countries.go diff --git a/cmd/server/assets/header.html b/cmd/server/assets/header.html index 49ecf354c..e4aae6b7c 100644 --- a/cmd/server/assets/header.html +++ b/cmd/server/assets/header.html @@ -18,6 +18,9 @@ + @@ -25,6 +28,8 @@ integrity="sha384-9/reFTGAW83EW2RDu2S0VKaIzap3H66lZH81PoYlFhbGU+6BZp6G7niu735Sk7lN" crossorigin="anonymous"> + {{if .title}}{{.title}}{{else}}Diagnosis Verification Server{{end}} diff --git a/cmd/server/assets/home.html b/cmd/server/assets/home.html index dbcf33492..558ed7754 100644 --- a/cmd/server/assets/home.html +++ b/cmd/server/assets/home.html @@ -317,6 +317,15 @@

Create verification code

$formArea.removeClass('d-none'); }); + let phone = document.querySelector('#phone'); + let iti = window.intlTelInput(phone, { + nationalMode: true, + {{- if $currentRealm.SMSCountry }} + initialCountry: '{{$currentRealm.SMSCountry}}', + {{- end }} + utilsScript: 'https://cdnjs.cloudflare.com/ajax/libs/intl-tel-input/17.0.0/js/utils.js', + }); + {{if $currentRealm.RequireDate}} let $dates = $('input#test-date,input#symptom-date'); $dates.on('input', function() { diff --git a/cmd/server/assets/realm.html b/cmd/server/assets/realm.html index df1b4bd8d..7246538a7 100644 --- a/cmd/server/assets/realm.html +++ b/cmd/server/assets/realm.html @@ -154,7 +154,7 @@

Realm settings

- @@ -165,7 +165,7 @@

Realm settings

- diff --git a/cmd/server/assets/realmadmin/_form_sms.html b/cmd/server/assets/realmadmin/_form_sms.html index 49a8f0b3b..e5308ca0d 100644 --- a/cmd/server/assets/realmadmin/_form_sms.html +++ b/cmd/server/assets/realmadmin/_form_sms.html @@ -2,6 +2,7 @@ {{$realm := .realm}} {{$smsConfig := .smsConfig}} +{{$countries := .countries}}

These are the settings for configuring the

+
+ + {{template "errorable" $realm.ErrorsFor "smsCountry"}} + + This is the default value for the country code to use for SMS numbers. + Case workers will still be able to select a default value, but you should + set this to your most common region. + +
+
diff --git a/pkg/controller/realmadmin/settings.go b/pkg/controller/realmadmin/settings.go index 2b32e10ce..2e6e968a0 100644 --- a/pkg/controller/realmadmin/settings.go +++ b/pkg/controller/realmadmin/settings.go @@ -62,6 +62,7 @@ func (c *Controller) HandleSettings() http.Handler { SMS bool `form:"sms"` UseSystemSMSConfig bool `form:"use_system_sms_config"` + SMSCountry string `form:"sms_country"` TwilioAccountSid string `form:"twilio_account_sid"` TwilioAuthToken string `form:"twilio_auth_token"` TwilioFromNumber string `form:"twilio_from_number"` @@ -130,6 +131,7 @@ func (c *Controller) HandleSettings() http.Handler { // SMS if form.SMS { realm.UseSystemSMSConfig = form.UseSystemSMSConfig + realm.SMSCountry = form.SMSCountry } // Security @@ -277,6 +279,7 @@ func (c *Controller) renderSettings(ctx context.Context, w http.ResponseWriter, m := controller.TemplateMapFromContext(ctx) m["realm"] = realm m["smsConfig"] = smsConfig + m["countries"] = database.Countries m["testTypes"] = map[string]database.TestType{ "confirmed": database.TestTypeConfirmed, "likely": database.TestTypeConfirmed | database.TestTypeLikely, diff --git a/pkg/database/countries.go b/pkg/database/countries.go new file mode 100644 index 000000000..33016fbb0 --- /dev/null +++ b/pkg/database/countries.go @@ -0,0 +1,246 @@ +package database + +var Countries = map[string]string{ + "Afghanistan": "af", + "Aland Islands": "ax", + "Albania": "al", + "Algeria": "dz", + "American Samoa": "as", + "Andorra": "ad", + "Angola": "ao", + "Anguilla": "ai", + "Antigua and Barbuda": "ag", + "Argentina": "ar", + "Armenia": "am", + "Aruba": "aw", + "Australia": "au", + "Austria": "at", + "Azerbaijan": "az", + "Bahamas": "bs", + "Bahrain": "bh", + "Bangladesh": "bd", + "Barbados": "bb", + "Belarus": "by", + "Belgium": "be", + "Belize": "bz", + "Benin": "bj", + "Bermuda": "bm", + "Bhutan": "bt", + "Bolivia": "bo", + "Bosnia and Herzegovina": "ba", + "Botswana": "bw", + "Brazil": "br", + "British Indian Ocean Territory": "io", + "British Virgin Islands": "vg", + "Brunei": "bn", + "Bulgaria": "bg", + "Burkina Faso": "bf", + "Burundi": "bi", + "Cambodia": "kh", + "Cameroon": "cm", + "Canada": "ca", + "Cape Verde": "cv", + "Caribbean Netherlands": "bq", + "Cayman Islands": "ky", + "Central African Republic": "cf", + "Chad": "td", + "Chile": "cl", + "China": "cn", + "Christmas Island": "cx", + "Cocos Islands": "cc", + "Colombia": "co", + "Comoros": "km", + "Congo": "cd", + "Cook Islands": "ck", + "Costa Rica": "cr", + "Côte d’Ivoire": "ci", + "Croatia": "hr", + "Cuba": "cu", + "Curaçao": "cw", + "Cyprus": "cy", + "Czech Republic": "cz", + "Denmark": "dk", + "Djibouti": "dj", + "Dominica": "dm", + "Dominican Republic": "do", + "Ecuador": "ec", + "Egypt": "eg", + "El Salvador": "sv", + "Equatorial Guinea": "gq", + "Eritrea": "er", + "Estonia": "ee", + "Ethiopia": "et", + "Falkland Islands": "fk", + "Faroe Islands": "fo", + "Fiji": "fj", + "Finland": "fi", + "France": "fr", + "French Guiana": "gf", + "French Polynesia": "pf", + "Gabon": "ga", + "Gambia": "gm", + "Georgia": "ge", + "Germany": "de", + "Ghana": "gh", + "Gibraltar": "gi", + "Greece": "gr", + "Greenland": "gl", + "Grenada": "gd", + "Guadeloupe": "gp", + "Guam": "gu", + "Guatemala": "gt", + "Guernsey": "gg", + "Guinea-Bissau": "gw", + "Guinea": "gn", + "Guyana": "gy", + "Haiti": "ht", + "Honduras": "hn", + "Hong Kong": "hk", + "Hungary": "hu", + "Iceland": "is", + "India": "in", + "Indonesia": "id", + "Iran": "ir", + "Iraq": "iq", + "Ireland": "ie", + "Isle of Man": "im", + "Israel": "il", + "Italy": "it", + "Jamaica": "jm", + "Japan": "jp", + "Jersey": "je", + "Jordan": "jo", + "Kazakhstan": "kz", + "Kenya": "ke", + "Kiribati": "ki", + "Kosovo": "xk", + "Kuwait": "kw", + "Kyrgyzstan": "kg", + "Laos": "la", + "Latvia": "lv", + "Lebanon": "lb", + "Lesotho": "ls", + "Liberia": "lr", + "Libya": "ly", + "Liechtenstein": "li", + "Lithuania": "lt", + "Luxembourg": "lu", + "Macau": "mo", + "Macedonia": "mk", + "Madagascar": "mg", + "Malawi": "mw", + "Malaysia": "my", + "Maldives": "mv", + "Mali": "ml", + "Malta": "mt", + "Marshall Islands": "mh", + "Martinique": "mq", + "Mauritania": "mr", + "Mauritius": "mu", + "Mayotte": "yt", + "Mexico": "mx", + "Micronesia": "fm", + "Moldova": "md", + "Monaco": "mc", + "Mongolia": "mn", + "Montenegro": "me", + "Montserrat": "ms", + "Morocco": "ma", + "Mozambique": "mz", + "Myanmar": "mm", + "Namibia": "na", + "Nauru": "nr", + "Nepal": "np", + "Netherlands": "nl", + "New Caledonia": "nc", + "New Zealand": "nz", + "Nicaragua": "ni", + "Niger": "ne", + "Nigeria": "ng", + "Niue": "nu", + "Norfolk Island": "nf", + "North Korea": "kp", + "Northern Mariana Islands": "mp", + "Norway": "no", + "Oman": "om", + "Pakistan": "pk", + "Palau": "pw", + "Palestine": "ps", + "Panama": "pa", + "Papua New Guinea": "pg", + "Paraguay": "py", + "Peru": "pe", + "Philippines": "ph", + "Poland": "pl", + "Portugal": "pt", + "Puerto Rico": "pr", + "Qatar": "qa", + "Réunion": "re", + "Romania": "ro", + "Russia": "ru", + "Rwanda": "rw", + "Saint Barthélemy": "bl", + "Saint Helena": "sh", + "Saint Kitts and Nevis": "kn", + "Saint Lucia": "lc", + "Saint Martin": "mf", + "Saint Pierre and Miquelon": "pm", + "Saint Vincent and the Grenadines": "vc", + "Samoa": "ws", + "San Marino": "sm", + "São Tomé and Príncipe": "st", + "Saudi Arabia": "sa", + "Senegal": "sn", + "Serbia": "rs", + "Seychelles": "sc", + "Sierra Leone": "sl", + "Singapore": "sg", + "Sint Maarten": "sx", + "Slovakia": "sk", + "Slovenia": "si", + "Solomon Islands": "sb", + "Somalia": "so", + "South Africa": "za", + "South Korea": "kr", + "South Sudan": "ss", + "Spain": "es", + "Sri Lanka": "lk", + "Sudan": "sd", + "Suriname": "sr", + "Svalbard and Jan Mayen": "sj", + "Swaziland": "sz", + "Sweden": "se", + "Switzerland": "ch", + "Syria": "sy", + "Taiwan": "tw", + "Tajikistan": "tj", + "Tanzania": "tz", + "Thailand": "th", + "Timor-Leste": "tl", + "Togo": "tg", + "Tokelau": "tk", + "Tonga": "to", + "Trinidad and Tobago": "tt", + "Tunisia": "tn", + "Turkey": "tr", + "Turkmenistan": "tm", + "Turks and Caicos Islands": "tc", + "Tuvalu": "tv", + "U.S. Virgin Islands": "vi", + "Uganda": "ug", + "Ukraine": "ua", + "United Arab Emirates": "ae", + "United Kingdom": "gb", + "United States": "us", + "Uruguay": "uy", + "Uzbekistan": "uz", + "Vanuatu": "vu", + "Vatican City": "va", + "Venezuela": "ve", + "Vietnam": "vn", + "Wallis and Futuna": "wf", + "Western Sahara": "eh", + "Yemen": "ye", + "Zambia": "zm", + "Zimbabwe": "zw", +} diff --git a/pkg/database/migrations.go b/pkg/database/migrations.go index 2db10dd2f..84bdecfd2 100644 --- a/pkg/database/migrations.go +++ b/pkg/database/migrations.go @@ -1296,6 +1296,25 @@ func (db *Database) getMigrations(ctx context.Context) *gormigrate.Gormigrate { } } + return nil + }, + }, + { + ID: "00053-AddRealmSMSCountry", + Migrate: func(tx *gorm.DB) error { + return tx.AutoMigrate(&Realm{}).Error + }, + Rollback: func(tx *gorm.DB) error { + sqls := []string{ + `ALTER TABLE realms DROP COLUMN IF EXISTS sms_country`, + } + + for _, sql := range sqls { + if err := tx.Exec(sql).Error; err != nil { + return err + } + } + return nil }, }, diff --git a/pkg/database/realm.go b/pkg/database/realm.go index aab67fb0c..8faa26fa7 100644 --- a/pkg/database/realm.go +++ b/pkg/database/realm.go @@ -104,6 +104,11 @@ type Realm struct { // SMS configuration SMSTextTemplate string `gorm:"type:varchar(400); not null; default: 'This is your Exposure Notifications Verification code: [longcode] Expires in [longexpires] hours'"` + // SMSCountry is an optional field to hint the default phone picker country + // code. + SMSCountry string `gorm:"-"` + SMSCountryPtr *string `gorm:"column:sms_country; type:varchar(5);"` + // CanUseSystemSMSConfig is configured by system administrators to share the // system SMS config with this realm. Note that the system SMS config could be // empty and a local SMS config is preferred over the system value. @@ -217,6 +222,7 @@ func (r *Realm) SigningKeyID() string { func (r *Realm) AfterFind(tx *gorm.DB) error { r.RegionCode = stringValue(r.RegionCodePtr) r.WelcomeMessage = stringValue(r.WelcomeMessagePtr) + r.SMSCountry = stringValue(r.SMSCountryPtr) return nil } @@ -241,6 +247,8 @@ func (r *Realm) BeforeSave(tx *gorm.DB) error { r.AddError("useSystemSMSConfig", "is not allowed on this realm") } + r.SMSCountryPtr = stringPtr(r.SMSCountry) + if r.EnableENExpress { if r.RegionCode == "" { r.AddError("regionCode", "cannot be blank when using EN Express")