mirror of
https://github.com/casdoor/casdoor.git
synced 2025-07-02 11:20:18 +08:00
feat: support multiple SMS providers for different regions (#2914)
* feat: support using different sms provider for different region * feat: add multiple support for select and remove log * feat: revert change for countryCode in loginPage * feat: revert change for countryCode in user_util.go * feat: revert change for countryCode in auth.go * Update application_item.go * Update CountryCodeSelect.js * Update ProviderTable.js --------- Co-authored-by: Yang Luo <hsluoyz@qq.com>
This commit is contained in:
@ -295,7 +295,7 @@ func (c *ApiController) SendVerificationCode() {
|
|||||||
vform.CountryCode = mfaProps.CountryCode
|
vform.CountryCode = mfaProps.CountryCode
|
||||||
}
|
}
|
||||||
|
|
||||||
provider, err = application.GetSmsProvider(vform.Method)
|
provider, err = application.GetSmsProvider(vform.Method, vform.CountryCode)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.ResponseError(err.Error())
|
c.ResponseError(err.Error())
|
||||||
return
|
return
|
||||||
|
@ -38,7 +38,7 @@ func (application *Application) GetProviderByCategory(category string) (*Provide
|
|||||||
return nil, nil
|
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)
|
providers, err := GetProviders(application.Organization)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -54,7 +54,15 @@ func (application *Application) GetProviderByCategoryAndRule(category string, me
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, providerItem := range application.Providers {
|
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 {
|
if provider, ok := m[providerItem.Name]; ok {
|
||||||
return provider, nil
|
return provider, nil
|
||||||
}
|
}
|
||||||
@ -65,11 +73,11 @@ func (application *Application) GetProviderByCategoryAndRule(category string, me
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (application *Application) GetEmailProvider(method string) (*Provider, error) {
|
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) {
|
func (application *Application) GetSmsProvider(method string, countryCode string) (*Provider, error) {
|
||||||
return application.GetProviderByCategoryAndRule("SMS", method)
|
return application.GetProviderByCategoryAndRule("SMS", method, countryCode)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (application *Application) GetStorageProvider() (*Provider, error) {
|
func (application *Application) GetStorageProvider() (*Provider, error) {
|
||||||
|
@ -21,6 +21,7 @@ type ProviderItem struct {
|
|||||||
CanSignUp bool `json:"canSignUp"`
|
CanSignUp bool `json:"canSignUp"`
|
||||||
CanSignIn bool `json:"canSignIn"`
|
CanSignIn bool `json:"canSignIn"`
|
||||||
CanUnlink bool `json:"canUnlink"`
|
CanUnlink bool `json:"canUnlink"`
|
||||||
|
CountryCode []string `json:"countryCode"`
|
||||||
Prompted bool `json:"prompted"`
|
Prompted bool `json:"prompted"`
|
||||||
SignupGroup string `json:"signupGroup"`
|
SignupGroup string `json:"signupGroup"`
|
||||||
Rule string `json:"rule"`
|
Rule string `json:"rule"`
|
||||||
|
@ -840,7 +840,7 @@ class LoginPage extends React.Component {
|
|||||||
{application.displayName}
|
{application.displayName}
|
||||||
</span>
|
</span>
|
||||||
</a>
|
</a>
|
||||||
:
|
:
|
||||||
</div>
|
</div>
|
||||||
<br />
|
<br />
|
||||||
{
|
{
|
||||||
|
@ -13,11 +13,14 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
import {Select} from "antd";
|
import {Select} from "antd";
|
||||||
|
import i18next from "i18next";
|
||||||
import * as Setting from "../../Setting";
|
import * as Setting from "../../Setting";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
|
||||||
|
const {Option} = Select;
|
||||||
|
|
||||||
export const CountryCodeSelect = (props) => {
|
export const CountryCodeSelect = (props) => {
|
||||||
const {onChange, style, disabled, initValue} = props;
|
const {onChange, style, disabled, initValue, mode} = props;
|
||||||
const countryCodes = props.countryCodes ?? [];
|
const countryCodes = props.countryCodes ?? [];
|
||||||
const [value, setValue] = React.useState("");
|
const [value, setValue] = React.useState("");
|
||||||
|
|
||||||
@ -42,11 +45,19 @@ export const CountryCodeSelect = (props) => {
|
|||||||
style={style}
|
style={style}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
value={value}
|
value={value}
|
||||||
|
mode={mode}
|
||||||
dropdownMatchSelectWidth={false}
|
dropdownMatchSelectWidth={false}
|
||||||
optionLabelProp={"label"}
|
optionLabelProp={"label"}
|
||||||
onChange={handleOnChange}
|
onChange={handleOnChange}
|
||||||
filterOption={(input, option) => (option?.text ?? "").toLowerCase().includes(input.toLowerCase())}
|
filterOption={(input, option) => (option?.text ?? "").toLowerCase().includes(input.toLowerCase())}
|
||||||
>
|
>
|
||||||
|
{
|
||||||
|
props.hasDefault ? (<Option key={"All"} value={"All"} label={i18next.t("organization:All")} text={"organization:All"} >
|
||||||
|
<div style={{display: "flex", justifyContent: "space-between", marginRight: "10px"}}>
|
||||||
|
{i18next.t("organization:All")}
|
||||||
|
</div>
|
||||||
|
</Option>) : null
|
||||||
|
}
|
||||||
{
|
{
|
||||||
Setting.getCountryCodeData(countryCodes).map((country) => Setting.getCountryCodeOption(country))
|
Setting.getCountryCodeData(countryCodes).map((country) => Setting.getCountryCodeOption(country))
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import {DeleteOutlined, DownOutlined, UpOutlined} from "@ant-design/icons";
|
import {DeleteOutlined, DownOutlined, UpOutlined} from "@ant-design/icons";
|
||||||
import {Button, Col, Input, Row, Select, Switch, Table, Tooltip} from "antd";
|
import {Button, Col, Input, Row, Select, Switch, Table, Tooltip} from "antd";
|
||||||
|
import {CountryCodeSelect} from "../common/select/CountryCodeSelect";
|
||||||
import * as Setting from "../Setting";
|
import * as Setting from "../Setting";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
import * as Provider from "../auth/Provider";
|
import * as Provider from "../auth/Provider";
|
||||||
@ -29,6 +30,10 @@ class ProviderTable extends React.Component {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getUserOrganization() {
|
||||||
|
return this.props.application?.organizationObj;
|
||||||
|
}
|
||||||
|
|
||||||
updateTable(table) {
|
updateTable(table) {
|
||||||
this.props.onUpdateTable(table);
|
this.props.onUpdateTable(table);
|
||||||
}
|
}
|
||||||
@ -109,6 +114,30 @@ class ProviderTable extends React.Component {
|
|||||||
return Provider.getProviderLogoWidget(provider);
|
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 (
|
||||||
|
<CountryCodeSelect
|
||||||
|
style={{width: "100%"}}
|
||||||
|
hasDefault={true}
|
||||||
|
mode={"multiple"}
|
||||||
|
initValue={text ? text : ["All"]}
|
||||||
|
onChange={(value) => {
|
||||||
|
this.updateField(table, index, "countryCode", value);
|
||||||
|
}}
|
||||||
|
countryCodes={this.getUserOrganization()?.countryCodes}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: i18next.t("provider:Can signup"),
|
title: i18next.t("provider:Can signup"),
|
||||||
dataIndex: "canSignUp",
|
dataIndex: "canSignUp",
|
||||||
|
Reference in New Issue
Block a user