mirror of
https://github.com/casdoor/casdoor.git
synced 2025-07-03 20:50:19 +08:00
Add Email provider.
This commit is contained in:
@ -25,9 +25,12 @@ type Provider struct {
|
|||||||
CreatedTime string `xorm:"varchar(100)" json:"createdTime"`
|
CreatedTime string `xorm:"varchar(100)" json:"createdTime"`
|
||||||
|
|
||||||
DisplayName string `xorm:"varchar(100)" json:"displayName"`
|
DisplayName string `xorm:"varchar(100)" json:"displayName"`
|
||||||
|
Category string `xorm:"varchar(100)" json:"category"`
|
||||||
Type string `xorm:"varchar(100)" json:"type"`
|
Type string `xorm:"varchar(100)" json:"type"`
|
||||||
ClientId string `xorm:"varchar(100)" json:"clientId"`
|
ClientId string `xorm:"varchar(100)" json:"clientId"`
|
||||||
ClientSecret string `xorm:"varchar(100)" json:"clientSecret"`
|
ClientSecret string `xorm:"varchar(100)" json:"clientSecret"`
|
||||||
|
Host string `xorm:"varchar(100)" json:"host"`
|
||||||
|
Port int `json:"port"`
|
||||||
ProviderUrl string `xorm:"varchar(200)" json:"providerUrl"`
|
ProviderUrl string `xorm:"varchar(200)" json:"providerUrl"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -121,7 +121,7 @@ class OrganizationEditPage extends React.Component {
|
|||||||
{i18next.t("organization:Website URL")}:
|
{i18next.t("organization:Website URL")}:
|
||||||
</Col>
|
</Col>
|
||||||
<Col span={22} >
|
<Col span={22} >
|
||||||
<Input value={this.state.organization.websiteUrl} onChange={e => {
|
<Input prefix={<LinkOutlined/>} value={this.state.organization.websiteUrl} onChange={e => {
|
||||||
this.updateOrganizationField('websiteUrl', e.target.value);
|
this.updateOrganizationField('websiteUrl', e.target.value);
|
||||||
}} />
|
}} />
|
||||||
</Col>
|
</Col>
|
||||||
|
@ -13,7 +13,8 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import {Button, Card, Col, Input, Row, Select} from 'antd';
|
import {Button, Card, Col, Input, InputNumber, Row, Select} from 'antd';
|
||||||
|
import {LinkOutlined} from "@ant-design/icons";
|
||||||
import * as ProviderBackend from "./backend/ProviderBackend";
|
import * as ProviderBackend from "./backend/ProviderBackend";
|
||||||
import * as Setting from "./Setting";
|
import * as Setting from "./Setting";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
@ -44,9 +45,9 @@ class ProviderEditPage extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
parseProviderField(key, value) {
|
parseProviderField(key, value) {
|
||||||
// if ([].includes(key)) {
|
if (["port"].includes(key)) {
|
||||||
// value = Setting.myParseInt(value);
|
value = Setting.myParseInt(value);
|
||||||
// }
|
}
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -60,6 +61,29 @@ class ProviderEditPage extends React.Component {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getProviderTypeOptions(provider) {
|
||||||
|
if (provider.category === "OAuth") {
|
||||||
|
return (
|
||||||
|
[
|
||||||
|
{id: 'Google', name: 'Google'},
|
||||||
|
{id: 'GitHub', name: 'GitHub'},
|
||||||
|
{id: 'QQ', name: 'QQ'},
|
||||||
|
{id: 'WeChat', name: 'WeChat'},
|
||||||
|
]
|
||||||
|
);
|
||||||
|
} else if (provider.category === "Email") {
|
||||||
|
return (
|
||||||
|
[
|
||||||
|
{id: 'Default', name: 'Default'},
|
||||||
|
]
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return (
|
||||||
|
[]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
renderProvider() {
|
renderProvider() {
|
||||||
return (
|
return (
|
||||||
<Card size="small" title={
|
<Card size="small" title={
|
||||||
@ -90,24 +114,35 @@ class ProviderEditPage extends React.Component {
|
|||||||
</Row>
|
</Row>
|
||||||
<Row style={{marginTop: '20px'}} >
|
<Row style={{marginTop: '20px'}} >
|
||||||
<Col style={{marginTop: '5px'}} span={2}>
|
<Col style={{marginTop: '5px'}} span={2}>
|
||||||
{i18next.t("provider:Type")}:
|
{i18next.t("provider:Category")}:
|
||||||
</Col>
|
</Col>
|
||||||
<Col span={22} >
|
<Col span={22} >
|
||||||
<Select virtual={false} style={{width: '100%'}} value={this.state.provider.type} onChange={(value => {this.updateProviderField('type', value);})}>
|
<Select virtual={false} style={{width: '100%'}} value={this.state.provider.category} onChange={(value => {this.updateProviderField('category', value);})}>
|
||||||
{
|
{
|
||||||
[
|
[
|
||||||
{id: 'Google', name: 'Google'},
|
{id: 'OAuth', name: 'OAuth'},
|
||||||
{id: 'GitHub', name: 'GitHub'},
|
{id: 'Email', name: 'Email'},
|
||||||
{id: 'QQ', name: 'QQ'},
|
{id: 'Phone', name: 'Phone'},
|
||||||
{id: 'WeChat', name: 'WeChat'},
|
].map((providerCategory, index) => <Option key={index} value={providerCategory.id}>{providerCategory.name}</Option>)
|
||||||
].map((providerType, index) => <Option key={index} value={providerType.id}>{providerType.name}</Option>)
|
|
||||||
}
|
}
|
||||||
</Select>
|
</Select>
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
<Row style={{marginTop: '20px'}} >
|
<Row style={{marginTop: '20px'}} >
|
||||||
<Col style={{marginTop: '5px'}} span={2}>
|
<Col style={{marginTop: '5px'}} span={2}>
|
||||||
{i18next.t("provider:Client ID")}:
|
{i18next.t("provider:Type")}:
|
||||||
|
</Col>
|
||||||
|
<Col span={22} >
|
||||||
|
<Select virtual={false} style={{width: '100%'}} value={this.state.provider.type} onChange={(value => {this.updateProviderField('type', value);})}>
|
||||||
|
{
|
||||||
|
this.getProviderTypeOptions(this.state.provider).map((providerType, index) => <Option key={index} value={providerType.id}>{providerType.name}</Option>)
|
||||||
|
}
|
||||||
|
</Select>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
<Row style={{marginTop: '20px'}} >
|
||||||
|
<Col style={{marginTop: '5px'}} span={2}>
|
||||||
|
{this.state.provider.category === "Email" ? i18next.t("signup:Username") : i18next.t("provider:Client ID")}:
|
||||||
</Col>
|
</Col>
|
||||||
<Col span={22} >
|
<Col span={22} >
|
||||||
<Input value={this.state.provider.clientId} onChange={e => {
|
<Input value={this.state.provider.clientId} onChange={e => {
|
||||||
@ -117,7 +152,7 @@ class ProviderEditPage extends React.Component {
|
|||||||
</Row>
|
</Row>
|
||||||
<Row style={{marginTop: '20px'}} >
|
<Row style={{marginTop: '20px'}} >
|
||||||
<Col style={{marginTop: '5px'}} span={2}>
|
<Col style={{marginTop: '5px'}} span={2}>
|
||||||
{i18next.t("provider:Client secret")}:
|
{this.state.provider.category === "Email" ? i18next.t("login:Password") : i18next.t("provider:Client secret")}:
|
||||||
</Col>
|
</Col>
|
||||||
<Col span={22} >
|
<Col span={22} >
|
||||||
<Input value={this.state.provider.clientSecret} onChange={e => {
|
<Input value={this.state.provider.clientSecret} onChange={e => {
|
||||||
@ -125,12 +160,32 @@ class ProviderEditPage extends React.Component {
|
|||||||
}} />
|
}} />
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
|
<Row style={{marginTop: '20px'}} >
|
||||||
|
<Col style={{marginTop: '5px'}} span={2}>
|
||||||
|
{i18next.t("provider:Host")}:
|
||||||
|
</Col>
|
||||||
|
<Col span={22} >
|
||||||
|
<Input prefix={<LinkOutlined/>} value={this.state.provider.host} onChange={e => {
|
||||||
|
this.updateProviderField('host', e.target.value);
|
||||||
|
}} />
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
<Row style={{marginTop: '20px'}} >
|
||||||
|
<Col style={{marginTop: '5px'}} span={2}>
|
||||||
|
{i18next.t("provider:Port")}:
|
||||||
|
</Col>
|
||||||
|
<Col span={22} >
|
||||||
|
<InputNumber value={this.state.provider.port} onChange={value => {
|
||||||
|
this.updateProviderField('port', value);
|
||||||
|
}} />
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
<Row style={{marginTop: '20px'}} >
|
<Row style={{marginTop: '20px'}} >
|
||||||
<Col style={{marginTop: '5px'}} span={2}>
|
<Col style={{marginTop: '5px'}} span={2}>
|
||||||
{i18next.t("provider:Provider URL")}:
|
{i18next.t("provider:Provider URL")}:
|
||||||
</Col>
|
</Col>
|
||||||
<Col span={22} >
|
<Col span={22} >
|
||||||
<Input value={this.state.provider.providerUrl} onChange={e => {
|
<Input prefix={<LinkOutlined/>} value={this.state.provider.providerUrl} onChange={e => {
|
||||||
this.updateProviderField('providerUrl', e.target.value);
|
this.updateProviderField('providerUrl', e.target.value);
|
||||||
}} />
|
}} />
|
||||||
</Col>
|
</Col>
|
||||||
|
@ -49,9 +49,12 @@ class ProviderListPage extends React.Component {
|
|||||||
name: `provider_${this.state.providers.length}`,
|
name: `provider_${this.state.providers.length}`,
|
||||||
createdTime: moment().format(),
|
createdTime: moment().format(),
|
||||||
displayName: `New Provider - ${this.state.providers.length}`,
|
displayName: `New Provider - ${this.state.providers.length}`,
|
||||||
|
category: "OAuth",
|
||||||
type: "GitHub",
|
type: "GitHub",
|
||||||
clientId: "",
|
clientId: "",
|
||||||
clientSecret: "",
|
clientSecret: "",
|
||||||
|
host: "",
|
||||||
|
port: 0,
|
||||||
providerUrl: "https://github.com/organizations/xxx/settings/applications/1234567",
|
providerUrl: "https://github.com/organizations/xxx/settings/applications/1234567",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -118,6 +121,13 @@ class ProviderListPage extends React.Component {
|
|||||||
// width: '100px',
|
// width: '100px',
|
||||||
sorter: (a, b) => a.displayName.localeCompare(b.displayName),
|
sorter: (a, b) => a.displayName.localeCompare(b.displayName),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: i18next.t("provider:Category"),
|
||||||
|
dataIndex: 'category',
|
||||||
|
key: 'category',
|
||||||
|
width: '100px',
|
||||||
|
sorter: (a, b) => a.category.localeCompare(b.category),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: i18next.t("provider:Type"),
|
title: i18next.t("provider:Type"),
|
||||||
dataIndex: 'type',
|
dataIndex: 'type',
|
||||||
@ -125,10 +135,14 @@ class ProviderListPage extends React.Component {
|
|||||||
width: '80px',
|
width: '80px',
|
||||||
sorter: (a, b) => a.type.localeCompare(b.type),
|
sorter: (a, b) => a.type.localeCompare(b.type),
|
||||||
render: (text, record, index) => {
|
render: (text, record, index) => {
|
||||||
|
if (record.category !== "OAuth") {
|
||||||
|
return text;
|
||||||
|
} else {
|
||||||
return (
|
return (
|
||||||
<img width={30} height={30} src={Provider.getAuthLogo(record)} alt={record.displayName} />
|
<img width={30} height={30} src={Provider.getAuthLogo(record)} alt={record.displayName} />
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: i18next.t("provider:Client ID"),
|
title: i18next.t("provider:Client ID"),
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import {DownOutlined, DeleteOutlined, UpOutlined} from '@ant-design/icons';
|
import {DownOutlined, DeleteOutlined, UpOutlined, LinkOutlined} from '@ant-design/icons';
|
||||||
import {Button, Col, Input, Row, Table, Tooltip} from 'antd';
|
import {Button, Col, Input, Row, Table, Tooltip} from 'antd';
|
||||||
import * as Setting from "./Setting";
|
import * as Setting from "./Setting";
|
||||||
|
|
||||||
@ -66,7 +66,7 @@ class UrlTable extends React.Component {
|
|||||||
key: 'id',
|
key: 'id',
|
||||||
render: (text, record, index) => {
|
render: (text, record, index) => {
|
||||||
return (
|
return (
|
||||||
<Input value={text} onChange={e => {
|
<Input prefix={<LinkOutlined/>} value={text} onChange={e => {
|
||||||
this.updateField(table, index, e.target.value);
|
this.updateField(table, index, e.target.value);
|
||||||
}} />
|
}} />
|
||||||
)
|
)
|
||||||
|
@ -184,7 +184,7 @@ class LoginPage extends React.Component {
|
|||||||
<Input
|
<Input
|
||||||
prefix={<LockOutlined className="site-form-item-icon" />}
|
prefix={<LockOutlined className="site-form-item-icon" />}
|
||||||
type="password"
|
type="password"
|
||||||
placeholder={i18next.t("login:password")}
|
placeholder={i18next.t("login:Password")}
|
||||||
disabled={!application.enablePassword}
|
disabled={!application.enablePassword}
|
||||||
/>
|
/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
@ -55,7 +55,7 @@
|
|||||||
"Please input your username, Email or phone number!": "Please input your username, Email or phone number!",
|
"Please input your username, Email or phone number!": "Please input your username, Email or phone number!",
|
||||||
"username, Email or phone number": "username, Email or phone number",
|
"username, Email or phone number": "username, Email or phone number",
|
||||||
"Please input your password!": "Please input your password!",
|
"Please input your password!": "Please input your password!",
|
||||||
"password": "password",
|
"Password": "Password",
|
||||||
"Auto login": "Auto login",
|
"Auto login": "Auto login",
|
||||||
"Forgot password?": "Forgot password?",
|
"Forgot password?": "Forgot password?",
|
||||||
"Sign In": "Sign In",
|
"Sign In": "Sign In",
|
||||||
@ -77,6 +77,9 @@
|
|||||||
},
|
},
|
||||||
"provider":
|
"provider":
|
||||||
{
|
{
|
||||||
|
"Name": "Name",
|
||||||
|
"Display name": "Display name",
|
||||||
|
"Category": "Category",
|
||||||
"Type": "Type",
|
"Type": "Type",
|
||||||
"Client ID": "Client ID",
|
"Client ID": "Client ID",
|
||||||
"Client secret": "Client secret",
|
"Client secret": "Client secret",
|
||||||
|
@ -30,7 +30,7 @@
|
|||||||
"OAuth providers": "OAuth提供方",
|
"OAuth providers": "OAuth提供方",
|
||||||
"Applications that requires authentication": "需要鉴权的应用",
|
"Applications that requires authentication": "需要鉴权的应用",
|
||||||
"Swagger": "API总览",
|
"Swagger": "API总览",
|
||||||
"Phone Prefix": "电话前缀"
|
"Phone Prefix": "手机号前缀"
|
||||||
},
|
},
|
||||||
"signup":
|
"signup":
|
||||||
{
|
{
|
||||||
@ -55,7 +55,7 @@
|
|||||||
"Please input your username, Email or phone number!": "请输入您的用户名、Email或手机号!",
|
"Please input your username, Email or phone number!": "请输入您的用户名、Email或手机号!",
|
||||||
"username, Email or phone number": "用户名、Email或手机号",
|
"username, Email or phone number": "用户名、Email或手机号",
|
||||||
"Please input your password!": "请输入您的密码!",
|
"Please input your password!": "请输入您的密码!",
|
||||||
"password": "密码",
|
"Password": "密码",
|
||||||
"Auto login": "下次自动登录",
|
"Auto login": "下次自动登录",
|
||||||
"Forgot password?": "忘记密码?",
|
"Forgot password?": "忘记密码?",
|
||||||
"Sign In": "登录",
|
"Sign In": "登录",
|
||||||
@ -79,6 +79,7 @@
|
|||||||
{
|
{
|
||||||
"Name": "名称",
|
"Name": "名称",
|
||||||
"Display name": "显示名称",
|
"Display name": "显示名称",
|
||||||
|
"Category": "分类",
|
||||||
"Type": "类型",
|
"Type": "类型",
|
||||||
"Client ID": "Client ID",
|
"Client ID": "Client ID",
|
||||||
"Client secret": "Client secret",
|
"Client secret": "Client secret",
|
||||||
@ -123,7 +124,7 @@
|
|||||||
"Reset Phone": "重置手机号",
|
"Reset Phone": "重置手机号",
|
||||||
"Send Code": "发送验证码",
|
"Send Code": "发送验证码",
|
||||||
"Empty email": "邮箱为空",
|
"Empty email": "邮箱为空",
|
||||||
"Empty phone": "电话为空",
|
"Empty phone": "手机号为空",
|
||||||
"Empty Code": "验证码为空",
|
"Empty Code": "验证码为空",
|
||||||
"phone reset": "手机号已设置",
|
"phone reset": "手机号已设置",
|
||||||
"email reset": "邮箱已设置",
|
"email reset": "邮箱已设置",
|
||||||
|
Reference in New Issue
Block a user