feat: support custom user mapping (#2029)

* feat: support custom user mapping

* fix: parse id to string

* Update data.json

* Update data.json

---------

Co-authored-by: hsluoyz <hsluoyz@qq.com>
This commit is contained in:
Yaodong Yu
2023-07-05 20:35:02 +08:00
committed by GitHub
parent ba97458edd
commit 3d4ca1adb1
24 changed files with 297 additions and 127 deletions

View File

@ -56,8 +56,10 @@ class ProviderEditPage extends React.Component {
}
if (res.status === "ok") {
const provider = res.data;
provider.userMapping = provider.userMapping || {};
this.setState({
provider: res.data,
provider: provider,
});
} else {
Setting.showMessage("error", res.msg);
@ -93,6 +95,40 @@ class ProviderEditPage extends React.Component {
});
}
updateUserMappingField(key, value) {
const provider = this.state.provider;
provider.userMapping[key] = value;
this.setState({
provider: provider,
});
}
renderUserMappingInput() {
return (
<React.Fragment>
{Setting.getLabel(i18next.t("general:ID"), i18next.t("general:ID - Tooltip"))} :
<Input value={this.state.provider.userMapping.id} onChange={e => {
this.updateUserMappingField("id", e.target.value);
}} />
{Setting.getLabel(i18next.t("signup:Username"), i18next.t("signup:Username - Tooltip"))} :
<Input value={this.state.provider.userMapping.username} onChange={e => {
this.updateUserMappingField("username", e.target.value);
}} />
{Setting.getLabel(i18next.t("general:Display name"), i18next.t("general:Display name - Tooltip"))} :
<Input value={this.state.provider.userMapping.displayName} onChange={e => {
this.updateUserMappingField("displayName", e.target.value);
}} />
{Setting.getLabel(i18next.t("general:Email"), i18next.t("general:Email - Tooltip"))} :
<Input value={this.state.provider.userMapping.email} onChange={e => {
this.updateUserMappingField("email", e.target.value);
}} />
{Setting.getLabel(i18next.t("general:Avatar"), i18next.t("general:Avatar - Tooltip"))} :
<Input value={this.state.provider.userMapping.avatarUrl} onChange={e => {
this.updateUserMappingField("avatarUrl", e.target.value);
}} />
</React.Fragment>
);
}
getClientIdLabel(provider) {
switch (provider.category) {
case "Email":
@ -350,7 +386,7 @@ class ProviderEditPage extends React.Component {
}
if (value === "Custom") {
this.updateProviderField("customAuthUrl", "https://door.casdoor.com/login/oauth/authorize");
this.updateProviderField("customScope", "openid profile email");
this.updateProviderField("scopes", "openid profile email");
this.updateProviderField("customTokenUrl", "https://door.casdoor.com/api/login/oauth/access_token");
this.updateProviderField("customUserInfoUrl", "https://door.casdoor.com/api/userinfo");
}
@ -416,16 +452,6 @@ class ProviderEditPage extends React.Component {
}} />
</Col>
</Row>
<Row style={{marginTop: "20px"}} >
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
{Setting.getLabel(i18next.t("provider:Scope"), i18next.t("provider:Scope - Tooltip"))}
</Col>
<Col span={22} >
<Input value={this.state.provider.customScope} onChange={e => {
this.updateProviderField("customScope", e.target.value);
}} />
</Col>
</Row>
<Row style={{marginTop: "20px"}} >
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
{Setting.getLabel(i18next.t("provider:Token URL"), i18next.t("provider:Token URL - Tooltip"))}
@ -436,6 +462,16 @@ class ProviderEditPage extends React.Component {
}} />
</Col>
</Row>
<Row style={{marginTop: "20px"}} >
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
{Setting.getLabel(i18next.t("provider:Scope"), i18next.t("provider:Scope - Tooltip"))}
</Col>
<Col span={22} >
<Input value={this.state.provider.scopes} onChange={e => {
this.updateProviderField("scopes", e.target.value);
}} />
</Col>
</Row>
<Row style={{marginTop: "20px"}} >
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
{Setting.getLabel(i18next.t("provider:UserInfo URL"), i18next.t("provider:UserInfo URL - Tooltip"))}
@ -446,6 +482,14 @@ class ProviderEditPage extends React.Component {
}} />
</Col>
</Row>
<Row style={{marginTop: "20px"}} >
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
{Setting.getLabel(i18next.t("provider:User mapping"), i18next.t("provider:User mapping - Tooltip"))} :
</Col>
<Col span={22} >
{this.renderUserMappingInput()}
</Col>
</Row>
<Row style={{marginTop: "20px"}} >
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
{Setting.getLabel(i18next.t("general:Favicon"), i18next.t("general:Favicon - Tooltip"))} :

View File

@ -448,7 +448,7 @@ export function getAuthUrl(application, provider, method) {
} else if (provider.type === "Douyin" || provider.type === "TikTok") {
return `${endpoint}?client_key=${provider.clientId}&redirect_uri=${redirectUri}&state=${state}&response_type=code&scope=${scope}`;
} else if (provider.type === "Custom") {
return `${provider.customAuthUrl}?client_id=${provider.clientId}&redirect_uri=${redirectUri}&scope=${provider.customScope}&response_type=code&state=${state}`;
return `${provider.customAuthUrl}?client_id=${provider.clientId}&redirect_uri=${redirectUri}&scope=${provider.scopes}&response_type=code&state=${state}`;
} else if (provider.type === "Bilibili") {
return `${endpoint}#/?client_id=${provider.clientId}&return_url=${redirectUri}&state=${state}&response_type=code`;
} else if (provider.type === "Deezer") {

View File

@ -570,8 +570,8 @@
"pricing": {
"Copy pricing page URL": "Preisseite URL kopieren",
"Edit Pricing": "Edit Pricing",
"Free": "Kostenlos",
"Failed to get plans": "Es konnten keine Pläne abgerufen werden",
"Free": "Kostenlos",
"Getting started": "Loslegen",
"New Pricing": "New Pricing",
"Trial duration": "Testphase Dauer",
@ -739,6 +739,8 @@
"Token URL - Tooltip": "Token-URL",
"Type": "Typ",
"Type - Tooltip": "Wählen Sie einen Typ aus",
"User mapping": "User mapping",
"User mapping - Tooltip": "User mapping - Tooltip",
"UserInfo URL": "UserInfo-URL",
"UserInfo URL - Tooltip": "UserInfo-URL",
"admin (Shared)": "admin (Shared)"

View File

@ -739,6 +739,8 @@
"Token URL - Tooltip": "Token URL",
"Type": "Type",
"Type - Tooltip": "Select a type",
"User mapping": "User mapping",
"User mapping - Tooltip": "User mapping - Tooltip",
"UserInfo URL": "UserInfo URL",
"UserInfo URL - Tooltip": "UserInfo URL",
"admin (Shared)": "admin (Shared)"

View File

@ -739,6 +739,8 @@
"Token URL - Tooltip": "URL de token",
"Type": "Tipo",
"Type - Tooltip": "Seleccionar un tipo",
"User mapping": "User mapping",
"User mapping - Tooltip": "User mapping - Tooltip",
"UserInfo URL": "URL de información del usuario",
"UserInfo URL - Tooltip": "URL de información de usuario",
"admin (Shared)": "administrador (compartido)"

View File

@ -739,6 +739,8 @@
"Token URL - Tooltip": "URL de jeton",
"Type": "Type",
"Type - Tooltip": "Sélectionnez un type",
"User mapping": "User mapping",
"User mapping - Tooltip": "User mapping - Tooltip",
"UserInfo URL": "URL d'informations utilisateur",
"UserInfo URL - Tooltip": "URL d'informations sur l'utilisateur",
"admin (Shared)": "admin (Partagé)"

View File

@ -739,6 +739,8 @@
"Token URL - Tooltip": "Token URL: URL Token",
"Type": "Jenis",
"Type - Tooltip": "Pilih tipe",
"User mapping": "User mapping",
"User mapping - Tooltip": "User mapping - Tooltip",
"UserInfo URL": "URL UserInfo",
"UserInfo URL - Tooltip": "URL Informasi Pengguna",
"admin (Shared)": "Admin (Berbagi)"

View File

@ -739,6 +739,8 @@
"Token URL - Tooltip": "トークンURL",
"Type": "タイプ",
"Type - Tooltip": "タイプを選択してください",
"User mapping": "User mapping",
"User mapping - Tooltip": "User mapping - Tooltip",
"UserInfo URL": "UserInfo URLを日本語に翻訳すると、「ユーザー情報のURL」となります",
"UserInfo URL - Tooltip": "ユーザー情報URL",
"admin (Shared)": "管理者(共有)"

View File

@ -739,6 +739,8 @@
"Token URL - Tooltip": "토큰 URL",
"Type": "타입",
"Type - Tooltip": "유형을 선택하세요",
"User mapping": "User mapping",
"User mapping - Tooltip": "User mapping - Tooltip",
"UserInfo URL": "사용자 정보 URL",
"UserInfo URL - Tooltip": "UserInfo URL: 사용자 정보 URL",
"admin (Shared)": "관리자 (공유)"

View File

@ -739,6 +739,8 @@
"Token URL - Tooltip": "URL do Token",
"Type": "Tipo",
"Type - Tooltip": "Selecione um tipo",
"User mapping": "User mapping",
"User mapping - Tooltip": "User mapping - Tooltip",
"UserInfo URL": "URL do UserInfo",
"UserInfo URL - Tooltip": "URL do UserInfo",
"admin (Shared)": "admin (Compartilhado)"

View File

@ -739,6 +739,8 @@
"Token URL - Tooltip": "Токен URL",
"Type": "Тип",
"Type - Tooltip": "Выберите тип",
"User mapping": "User mapping",
"User mapping - Tooltip": "User mapping - Tooltip",
"UserInfo URL": "URL информации о пользователе",
"UserInfo URL - Tooltip": "URL пользовательской информации (URL информации о пользователе)",
"admin (Shared)": "администратор (общий)"

View File

@ -739,6 +739,8 @@
"Token URL - Tooltip": "Địa chỉ URL của Token",
"Type": "Kiểu",
"Type - Tooltip": "Chọn loại",
"User mapping": "User mapping",
"User mapping - Tooltip": "User mapping - Tooltip",
"UserInfo URL": "Đường dẫn UserInfo",
"UserInfo URL - Tooltip": "Địa chỉ URL của Thông tin người dùng",
"admin (Shared)": "quản trị viên (Chung)"

View File

@ -570,8 +570,8 @@
"pricing": {
"Copy pricing page URL": "复制定价页面链接",
"Edit Pricing": "编辑定价",
"Free": "免费",
"Failed to get plans": "未能获取计划",
"Free": "免费",
"Getting started": "开始使用",
"New Pricing": "添加定价",
"Trial duration": "试用期时长",

View File

@ -66,7 +66,7 @@ class PricingPage extends React.Component {
.then(results => {
const hasError = results.some(result => result.status === "error");
if (hasError) {
Setting.showMessage("error", `${i18next.t("Failed to get plans")}`);
Setting.showMessage("error", i18next.t("pricing:Failed to get plans"));
return;
}
this.setState({
@ -75,7 +75,7 @@ class PricingPage extends React.Component {
});
})
.catch(error => {
Setting.showMessage("error", `Failed to get plans: ${error}`);
Setting.showMessage("error", i18next.t("pricing:Failed to get plans") + `: ${error}`);
});
}

View File

@ -173,7 +173,7 @@
lru-cache "^5.1.1"
semver "^6.3.0"
"@babel/helper-create-class-features-plugin@^7.18.6", "@babel/helper-create-class-features-plugin@^7.22.5":
"@babel/helper-create-class-features-plugin@^7.18.6", "@babel/helper-create-class-features-plugin@^7.21.0", "@babel/helper-create-class-features-plugin@^7.22.5":
version "7.22.5"
resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.22.5.tgz#2192a1970ece4685fbff85b48da2c32fcb130b7c"
integrity sha512-xkb58MyOYIslxu3gKmVXmjTtUPvBU4odYzbiIQbWwLKIHCsx6UGZGX6F1IznMFVnDdirseUZopzN+ZRt8Xb33Q==
@ -433,6 +433,16 @@
resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz#7844f9289546efa9febac2de4cfe358a050bd703"
integrity sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==
"@babel/plugin-proposal-private-property-in-object@^7.21.11":
version "7.21.11"
resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.11.tgz#69d597086b6760c4126525cfa154f34631ff272c"
integrity sha512-0QZ8qP/3RLDVBwBFoWAwCtgcDZJVwA5LUJRZU8x2YFfKNuFq161wK3cuGrALu5yiPu+vzwTAg/sMWVNeWeNyaw==
dependencies:
"@babel/helper-annotate-as-pure" "^7.18.6"
"@babel/helper-create-class-features-plugin" "^7.21.0"
"@babel/helper-plugin-utils" "^7.20.2"
"@babel/plugin-syntax-private-property-in-object" "^7.14.5"
"@babel/plugin-proposal-unicode-property-regex@^7.4.4":
version "7.18.6"
resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.18.6.tgz#af613d2cd5e643643b65cded64207b15c85cb78e"