diff --git a/controllers/verification.go b/controllers/verification.go index ec79eaa3..4f9b2220 100644 --- a/controllers/verification.go +++ b/controllers/verification.go @@ -295,7 +295,7 @@ func (c *ApiController) SendVerificationCode() { vform.CountryCode = mfaProps.CountryCode } - provider, err = application.GetSmsProvider(vform.Method) + provider, err = application.GetSmsProvider(vform.Method, vform.CountryCode) if err != nil { c.ResponseError(err.Error()) return diff --git a/object/application_item.go b/object/application_item.go index 442daed5..b5ce5bee 100644 --- a/object/application_item.go +++ b/object/application_item.go @@ -38,7 +38,7 @@ func (application *Application) GetProviderByCategory(category string) (*Provide return nil, nil } -func (application *Application) GetProviderByCategoryAndRule(category string, method string) (*Provider, error) { +func (application *Application) GetProviderByCategoryAndRule(category string, method string, countryCode string) (*Provider, error) { providers, err := GetProviders(application.Organization) if err != nil { return nil, err @@ -54,7 +54,15 @@ func (application *Application) GetProviderByCategoryAndRule(category string, me } for _, providerItem := range application.Providers { - if providerItem.Rule == method || (providerItem.Rule == "all" || providerItem.Rule == "" || providerItem.Rule == "None") { + includeCode := false + if providerItem.CountryCode != nil { + for _, item := range providerItem.CountryCode { + if item == countryCode || item == "All" || item == "" { + includeCode = true + } + } + } + if (providerItem.Rule == method || (providerItem.Rule == "All" || providerItem.Rule == "" || providerItem.Rule == "None")) && includeCode { if provider, ok := m[providerItem.Name]; ok { return provider, nil } @@ -65,11 +73,11 @@ func (application *Application) GetProviderByCategoryAndRule(category string, me } func (application *Application) GetEmailProvider(method string) (*Provider, error) { - return application.GetProviderByCategoryAndRule("Email", method) + return application.GetProviderByCategoryAndRule("Email", method, "All") } -func (application *Application) GetSmsProvider(method string) (*Provider, error) { - return application.GetProviderByCategoryAndRule("SMS", method) +func (application *Application) GetSmsProvider(method string, countryCode string) (*Provider, error) { + return application.GetProviderByCategoryAndRule("SMS", method, countryCode) } func (application *Application) GetStorageProvider() (*Provider, error) { diff --git a/object/provider_item.go b/object/provider_item.go index fce694bc..c797a9c1 100644 --- a/object/provider_item.go +++ b/object/provider_item.go @@ -21,6 +21,7 @@ type ProviderItem struct { CanSignUp bool `json:"canSignUp"` CanSignIn bool `json:"canSignIn"` CanUnlink bool `json:"canUnlink"` + CountryCode []string `json:"countryCode"` Prompted bool `json:"prompted"` SignupGroup string `json:"signupGroup"` Rule string `json:"rule"` diff --git a/web/src/auth/LoginPage.js b/web/src/auth/LoginPage.js index 1a43d97c..6b955928 100644 --- a/web/src/auth/LoginPage.js +++ b/web/src/auth/LoginPage.js @@ -840,7 +840,7 @@ class LoginPage extends React.Component { {application.displayName} - : + :
{ diff --git a/web/src/common/select/CountryCodeSelect.js b/web/src/common/select/CountryCodeSelect.js index cb91479e..abc29631 100644 --- a/web/src/common/select/CountryCodeSelect.js +++ b/web/src/common/select/CountryCodeSelect.js @@ -13,11 +13,14 @@ // limitations under the License. import {Select} from "antd"; +import i18next from "i18next"; import * as Setting from "../../Setting"; import React from "react"; +const {Option} = Select; + export const CountryCodeSelect = (props) => { - const {onChange, style, disabled, initValue} = props; + const {onChange, style, disabled, initValue, mode} = props; const countryCodes = props.countryCodes ?? []; const [value, setValue] = React.useState(""); @@ -42,11 +45,19 @@ export const CountryCodeSelect = (props) => { style={style} disabled={disabled} value={value} + mode={mode} dropdownMatchSelectWidth={false} optionLabelProp={"label"} onChange={handleOnChange} filterOption={(input, option) => (option?.text ?? "").toLowerCase().includes(input.toLowerCase())} > + { + props.hasDefault ? () : null + } { Setting.getCountryCodeData(countryCodes).map((country) => Setting.getCountryCodeOption(country)) } diff --git a/web/src/table/ProviderTable.js b/web/src/table/ProviderTable.js index 29e47ec3..098708dd 100644 --- a/web/src/table/ProviderTable.js +++ b/web/src/table/ProviderTable.js @@ -15,6 +15,7 @@ import React from "react"; import {DeleteOutlined, DownOutlined, UpOutlined} from "@ant-design/icons"; import {Button, Col, Input, Row, Select, Switch, Table, Tooltip} from "antd"; +import {CountryCodeSelect} from "../common/select/CountryCodeSelect"; import * as Setting from "../Setting"; import i18next from "i18next"; import * as Provider from "../auth/Provider"; @@ -29,6 +30,10 @@ class ProviderTable extends React.Component { }; } + getUserOrganization() { + return this.props.application?.organizationObj; + } + updateTable(table) { this.props.onUpdateTable(table); } @@ -109,6 +114,30 @@ class ProviderTable extends React.Component { return Provider.getProviderLogoWidget(provider); }, }, + { + title: i18next.t("user:Country/Region"), + dataIndex: "countryCode", + key: "countryCode", + width: "80px", + render: (text, record, index) => { + if (record.provider?.category !== "SMS") { + return null; + } + + return ( + { + this.updateField(table, index, "countryCode", value); + }} + countryCodes={this.getUserOrganization()?.countryCodes} + /> + ); + }, + }, { title: i18next.t("provider:Can signup"), dataIndex: "canSignUp",