mirror of
https://github.com/casdoor/casdoor.git
synced 2025-08-02 18:50:32 +08:00
Compare commits
8 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
a8937d3046 | ||
![]() |
32b05047dc | ||
![]() |
117ee509cf | ||
![]() |
daf3d374b5 | ||
![]() |
337ee2faef | ||
![]() |
989fec72bf | ||
![]() |
76eb606335 | ||
![]() |
c6146a9149 |
@@ -87,6 +87,7 @@ p, *, *, POST, /api/logout, *, *
|
||||
p, *, *, GET, /api/logout, *, *
|
||||
p, *, *, GET, /api/get-account, *, *
|
||||
p, *, *, GET, /api/userinfo, *, *
|
||||
p, *, *, GET, /api/user, *, *
|
||||
p, *, *, POST, /api/webhook, *, *
|
||||
p, *, *, GET, /api/get-webhook-event, *, *
|
||||
p, *, *, *, /api/login/oauth, *, *
|
||||
|
@@ -50,6 +50,7 @@ type RequestForm struct {
|
||||
Region string `json:"region"`
|
||||
|
||||
Application string `json:"application"`
|
||||
ClientId string `json:"clientId"`
|
||||
Provider string `json:"provider"`
|
||||
Code string `json:"code"`
|
||||
State string `json:"state"`
|
||||
@@ -369,6 +370,43 @@ func (c *ApiController) GetUserinfo() {
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// GetUserinfo2
|
||||
// LaravelResponse
|
||||
// @Title UserInfo2
|
||||
// @Tag Account API
|
||||
// @Description return Laravel compatible user information according to OAuth 2.0
|
||||
// @Success 200 {object} LaravelResponse The Response object
|
||||
// @router /user [get]
|
||||
func (c *ApiController) GetUserinfo2() {
|
||||
user, ok := c.RequireSignedInUser()
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
// this API is used by "Api URL" of Flarum's FoF Passport plugin
|
||||
// https://github.com/FriendsOfFlarum/passport
|
||||
type LaravelResponse struct {
|
||||
Id string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Email string `json:"email"`
|
||||
EmailVerifiedAt string `json:"email_verified_at"`
|
||||
CreatedAt string `json:"created_at"`
|
||||
UpdatedAt string `json:"updated_at"`
|
||||
}
|
||||
|
||||
response := LaravelResponse{
|
||||
Id: user.Id,
|
||||
Name: user.Name,
|
||||
Email: user.Email,
|
||||
EmailVerifiedAt: user.CreatedTime,
|
||||
CreatedAt: user.CreatedTime,
|
||||
UpdatedAt: user.UpdatedTime,
|
||||
}
|
||||
|
||||
c.Data["json"] = response
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// GetCaptcha ...
|
||||
// @Tag Login API
|
||||
// @Title GetCaptcha
|
||||
|
@@ -334,7 +334,13 @@ func (c *ApiController) Login() {
|
||||
util.SafeGoroutine(func() { object.AddRecord(record) })
|
||||
}
|
||||
} else if form.Provider != "" {
|
||||
application := object.GetApplication(fmt.Sprintf("admin/%s", form.Application))
|
||||
var application *object.Application
|
||||
if form.ClientId != "" {
|
||||
application = object.GetApplicationByClientId(form.ClientId)
|
||||
} else {
|
||||
application = object.GetApplication(fmt.Sprintf("admin/%s", form.Application))
|
||||
}
|
||||
|
||||
if application == nil {
|
||||
c.ResponseError(fmt.Sprintf(c.T("auth:The application: %s does not exist"), form.Application))
|
||||
return
|
||||
|
@@ -21,9 +21,8 @@ import (
|
||||
// GetSystemInfo
|
||||
// @Title GetSystemInfo
|
||||
// @Tag System API
|
||||
// @Description get user's system info
|
||||
// @Param id query string true "The id ( owner/name ) of the user"
|
||||
// @Success 200 {object} object.SystemInfo The Response object
|
||||
// @Description get system info like CPU and memory usage
|
||||
// @Success 200 {object} util.SystemInfo The Response object
|
||||
// @router /get-system-info [get]
|
||||
func (c *ApiController) GetSystemInfo() {
|
||||
_, ok := c.RequireAdmin()
|
||||
@@ -43,8 +42,8 @@ func (c *ApiController) GetSystemInfo() {
|
||||
// GetVersionInfo
|
||||
// @Title GetVersionInfo
|
||||
// @Tag System API
|
||||
// @Description get local git repo's latest release version info
|
||||
// @Success 200 {string} local latest version hash of Casdoor
|
||||
// @Description get version info like Casdoor release version and commit ID
|
||||
// @Success 200 {object} util.VersionInfo The Response object
|
||||
// @router /get-version-info [get]
|
||||
func (c *ApiController) GetVersionInfo() {
|
||||
versionInfo, err := util.GetVersionInfo()
|
||||
|
@@ -36,13 +36,11 @@ func ParseSamlResponse(samlResponse string, providerType string) (string, error)
|
||||
return "", err
|
||||
}
|
||||
assertionInfo, err := sp.RetrieveAssertionInfo(samlResponse)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return assertionInfo.NameID, nil
|
||||
|
||||
return assertionInfo.NameID, err
|
||||
}
|
||||
|
||||
func GenerateSamlLoginUrl(id, relayState, lang string) (string, string, error) {
|
||||
func GenerateSamlLoginUrl(id, relayState, lang string) (auth string, method string, err error) {
|
||||
provider := GetProvider(id)
|
||||
if provider.Category != "SAML" {
|
||||
return "", "", fmt.Errorf(i18n.Translate(lang, "saml_sp:provider %s's category is not SAML"), provider.Name)
|
||||
@@ -51,8 +49,7 @@ func GenerateSamlLoginUrl(id, relayState, lang string) (string, string, error) {
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
auth := ""
|
||||
method := ""
|
||||
|
||||
if provider.EnableSignAuthnRequest {
|
||||
post, err := sp.BuildAuthBodyPost(relayState)
|
||||
if err != nil {
|
||||
|
@@ -613,7 +613,8 @@ func GetClientCredentialsToken(application *Application, clientSecret string, sc
|
||||
nullUser := &User{
|
||||
Owner: application.Owner,
|
||||
Id: application.GetId(),
|
||||
Name: fmt.Sprintf("app/%s", application.Name),
|
||||
Name: application.Name,
|
||||
Type: "application",
|
||||
}
|
||||
|
||||
accessToken, _, tokenName, err := generateJwtToken(application, nullUser, "", scope, host)
|
||||
|
@@ -50,6 +50,7 @@ func initAPI() {
|
||||
beego.Router("/api/logout", &controllers.ApiController{}, "GET,POST:Logout")
|
||||
beego.Router("/api/get-account", &controllers.ApiController{}, "GET:GetAccount")
|
||||
beego.Router("/api/userinfo", &controllers.ApiController{}, "GET:GetUserinfo")
|
||||
beego.Router("/api/user", &controllers.ApiController{}, "GET:GetUserinfo2")
|
||||
beego.Router("/api/unlink", &controllers.ApiController{}, "POST:Unlink")
|
||||
beego.Router("/api/get-saml-login", &controllers.ApiController{}, "GET:GetSamlLogin")
|
||||
beego.Router("/api/acs", &controllers.ApiController{}, "POST:HandleSamlLogin")
|
||||
|
@@ -2058,22 +2058,13 @@
|
||||
"tags": [
|
||||
"System API"
|
||||
],
|
||||
"description": "get user's system info",
|
||||
"description": "get system info like CPU and memory usage",
|
||||
"operationId": "ApiController.GetSystemInfo",
|
||||
"parameters": [
|
||||
{
|
||||
"in": "query",
|
||||
"name": "id",
|
||||
"description": "The id ( owner/name ) of the user",
|
||||
"required": true,
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "The Response object",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/object.SystemInfo"
|
||||
"$ref": "#/definitions/util.SystemInfo"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2323,11 +2314,14 @@
|
||||
"tags": [
|
||||
"System API"
|
||||
],
|
||||
"description": "get local git repo's latest release version info",
|
||||
"description": "get version info like Casdoor release version and commit ID",
|
||||
"operationId": "ApiController.GetVersionInfo",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "{string} local latest version hash of Casdoor"
|
||||
"description": "The Response object",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/util.VersionInfo"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3494,6 +3488,23 @@
|
||||
"operationId": "ApiController.UploadResource"
|
||||
}
|
||||
},
|
||||
"/api/user": {
|
||||
"get": {
|
||||
"tags": [
|
||||
"Account API"
|
||||
],
|
||||
"description": "return Laravel compatible user information according to OAuth 2.0",
|
||||
"operationId": "ApiController.UserInfo2",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "The Response object",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/LaravelResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/userinfo": {
|
||||
"get": {
|
||||
"tags": [
|
||||
@@ -3627,14 +3638,18 @@
|
||||
}
|
||||
},
|
||||
"definitions": {
|
||||
"2268.0xc000528cf0.false": {
|
||||
"2306.0xc0000a7410.false": {
|
||||
"title": "false",
|
||||
"type": "object"
|
||||
},
|
||||
"2302.0xc000528d20.false": {
|
||||
"2340.0xc0000a7440.false": {
|
||||
"title": "false",
|
||||
"type": "object"
|
||||
},
|
||||
"LaravelResponse": {
|
||||
"title": "LaravelResponse",
|
||||
"type": "object"
|
||||
},
|
||||
"Response": {
|
||||
"title": "Response",
|
||||
"type": "object"
|
||||
@@ -3682,6 +3697,9 @@
|
||||
"captchaType": {
|
||||
"type": "string"
|
||||
},
|
||||
"clientId": {
|
||||
"type": "string"
|
||||
},
|
||||
"clientSecret": {
|
||||
"type": "string"
|
||||
},
|
||||
@@ -3758,10 +3776,10 @@
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"data": {
|
||||
"$ref": "#/definitions/2268.0xc000528cf0.false"
|
||||
"$ref": "#/definitions/2306.0xc0000a7410.false"
|
||||
},
|
||||
"data2": {
|
||||
"$ref": "#/definitions/2302.0xc000528d20.false"
|
||||
"$ref": "#/definitions/2340.0xc0000a7440.false"
|
||||
},
|
||||
"msg": {
|
||||
"type": "string"
|
||||
@@ -4830,10 +4848,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"object.SystemInfo": {
|
||||
"title": "SystemInfo",
|
||||
"type": "object"
|
||||
},
|
||||
"object.TableColumn": {
|
||||
"title": "TableColumn",
|
||||
"type": "object",
|
||||
@@ -5475,6 +5489,43 @@
|
||||
"title": "CredentialCreationResponse",
|
||||
"type": "object"
|
||||
},
|
||||
"util.SystemInfo": {
|
||||
"title": "SystemInfo",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"cpuUsage": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "number",
|
||||
"format": "double"
|
||||
}
|
||||
},
|
||||
"memoryTotal": {
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
},
|
||||
"memoryUsed": {
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
}
|
||||
}
|
||||
},
|
||||
"util.VersionInfo": {
|
||||
"title": "VersionInfo",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"commitId": {
|
||||
"type": "string"
|
||||
},
|
||||
"commitOffset": {
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
},
|
||||
"version": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"webauthn.Credential": {
|
||||
"title": "Credential",
|
||||
"type": "object"
|
||||
|
@@ -1340,19 +1340,13 @@ paths:
|
||||
get:
|
||||
tags:
|
||||
- System API
|
||||
description: get user's system info
|
||||
description: get system info like CPU and memory usage
|
||||
operationId: ApiController.GetSystemInfo
|
||||
parameters:
|
||||
- in: query
|
||||
name: id
|
||||
description: The id ( owner/name ) of the user
|
||||
required: true
|
||||
type: string
|
||||
responses:
|
||||
"200":
|
||||
description: The Response object
|
||||
schema:
|
||||
$ref: '#/definitions/object.SystemInfo'
|
||||
$ref: '#/definitions/util.SystemInfo'
|
||||
/api/get-token:
|
||||
get:
|
||||
tags:
|
||||
@@ -1515,11 +1509,13 @@ paths:
|
||||
get:
|
||||
tags:
|
||||
- System API
|
||||
description: get local git repo's latest release version info
|
||||
description: get version info like Casdoor release version and commit ID
|
||||
operationId: ApiController.GetVersionInfo
|
||||
responses:
|
||||
"200":
|
||||
description: '{string} local latest version hash of Casdoor'
|
||||
description: The Response object
|
||||
schema:
|
||||
$ref: '#/definitions/util.VersionInfo'
|
||||
/api/get-webhook:
|
||||
get:
|
||||
tags:
|
||||
@@ -2288,6 +2284,17 @@ paths:
|
||||
tags:
|
||||
- Resource API
|
||||
operationId: ApiController.UploadResource
|
||||
/api/user:
|
||||
get:
|
||||
tags:
|
||||
- Account API
|
||||
description: return Laravel compatible user information according to OAuth 2.0
|
||||
operationId: ApiController.UserInfo2
|
||||
responses:
|
||||
"200":
|
||||
description: The Response object
|
||||
schema:
|
||||
$ref: '#/definitions/LaravelResponse'
|
||||
/api/userinfo:
|
||||
get:
|
||||
tags:
|
||||
@@ -2374,12 +2381,15 @@ paths:
|
||||
schema:
|
||||
$ref: '#/definitions/Response'
|
||||
definitions:
|
||||
2268.0xc000528cf0.false:
|
||||
2306.0xc0000a7410.false:
|
||||
title: "false"
|
||||
type: object
|
||||
2302.0xc000528d20.false:
|
||||
2340.0xc0000a7440.false:
|
||||
title: "false"
|
||||
type: object
|
||||
LaravelResponse:
|
||||
title: LaravelResponse
|
||||
type: object
|
||||
Response:
|
||||
title: Response
|
||||
type: object
|
||||
@@ -2413,6 +2423,8 @@ definitions:
|
||||
type: string
|
||||
captchaType:
|
||||
type: string
|
||||
clientId:
|
||||
type: string
|
||||
clientSecret:
|
||||
type: string
|
||||
code:
|
||||
@@ -2464,9 +2476,9 @@ definitions:
|
||||
type: object
|
||||
properties:
|
||||
data:
|
||||
$ref: '#/definitions/2268.0xc000528cf0.false'
|
||||
$ref: '#/definitions/2306.0xc0000a7410.false'
|
||||
data2:
|
||||
$ref: '#/definitions/2302.0xc000528d20.false'
|
||||
$ref: '#/definitions/2340.0xc0000a7440.false'
|
||||
msg:
|
||||
type: string
|
||||
name:
|
||||
@@ -3183,9 +3195,6 @@ definitions:
|
||||
type: string
|
||||
user:
|
||||
type: string
|
||||
object.SystemInfo:
|
||||
title: SystemInfo
|
||||
type: object
|
||||
object.TableColumn:
|
||||
title: TableColumn
|
||||
type: object
|
||||
@@ -3617,6 +3626,32 @@ definitions:
|
||||
protocol.CredentialCreationResponse:
|
||||
title: CredentialCreationResponse
|
||||
type: object
|
||||
util.SystemInfo:
|
||||
title: SystemInfo
|
||||
type: object
|
||||
properties:
|
||||
cpuUsage:
|
||||
type: array
|
||||
items:
|
||||
type: number
|
||||
format: double
|
||||
memoryTotal:
|
||||
type: integer
|
||||
format: int64
|
||||
memoryUsed:
|
||||
type: integer
|
||||
format: int64
|
||||
util.VersionInfo:
|
||||
title: VersionInfo
|
||||
type: object
|
||||
properties:
|
||||
commitId:
|
||||
type: string
|
||||
commitOffset:
|
||||
type: integer
|
||||
format: int64
|
||||
version:
|
||||
type: string
|
||||
webauthn.Credential:
|
||||
title: Credential
|
||||
type: object
|
||||
|
@@ -21,7 +21,7 @@ import i18next from "i18next";
|
||||
|
||||
import "codemirror/lib/codemirror.css";
|
||||
import * as ModelBackend from "./backend/ModelBackend";
|
||||
import PolicyTable from "./common/PoliciyTable";
|
||||
import PolicyTable from "./table/PoliciyTable";
|
||||
require("codemirror/theme/material-darker.css");
|
||||
require("codemirror/mode/javascript/javascript");
|
||||
|
||||
|
@@ -52,7 +52,7 @@ import PaymentEditPage from "./PaymentEditPage";
|
||||
import PaymentResultPage from "./PaymentResultPage";
|
||||
import AccountPage from "./account/AccountPage";
|
||||
import HomePage from "./basic/HomePage";
|
||||
import CustomGithubCorner from "./CustomGithubCorner";
|
||||
import CustomGithubCorner from "./common/CustomGithubCorner";
|
||||
import * as Conf from "./Conf";
|
||||
|
||||
import * as Auth from "./auth/Auth";
|
||||
@@ -60,7 +60,7 @@ import EntryPage from "./EntryPage";
|
||||
import ResultPage from "./auth/ResultPage";
|
||||
import * as AuthBackend from "./auth/AuthBackend";
|
||||
import AuthCallback from "./auth/AuthCallback";
|
||||
import SelectLanguageBox from "./SelectLanguageBox";
|
||||
import LanguageSelect from "./common/select/LanguageSelect";
|
||||
import i18next from "i18next";
|
||||
import OdicDiscoveryPage from "./auth/OidcDiscoveryPage";
|
||||
import SamlCallback from "./auth/SamlCallback";
|
||||
@@ -70,7 +70,7 @@ import SystemInfo from "./SystemInfo";
|
||||
import AdapterListPage from "./AdapterListPage";
|
||||
import AdapterEditPage from "./AdapterEditPage";
|
||||
import {withTranslation} from "react-i18next";
|
||||
import SelectThemeBox from "./SelectThemeBox";
|
||||
import ThemeSelect from "./common/select/ThemeSelect";
|
||||
import SessionListPage from "./SessionListPage";
|
||||
|
||||
const {Header, Footer, Content} = Layout;
|
||||
@@ -352,7 +352,7 @@ class App extends Component {
|
||||
return (
|
||||
<React.Fragment>
|
||||
{this.renderRightDropdown()}
|
||||
<SelectThemeBox
|
||||
<ThemeSelect
|
||||
themeAlgorithm={this.state.themeAlgorithm}
|
||||
onChange={(nextThemeAlgorithm) => {
|
||||
this.setState({
|
||||
@@ -360,7 +360,7 @@ class App extends Component {
|
||||
logo: this.getLogo(nextThemeAlgorithm),
|
||||
});
|
||||
}} />
|
||||
<SelectLanguageBox languages={this.state.account.organization.languages} />
|
||||
<LanguageSelect languages={this.state.account.organization.languages} />
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
||||
|
@@ -25,9 +25,9 @@ import * as ResourceBackend from "./backend/ResourceBackend";
|
||||
import SignupPage from "./auth/SignupPage";
|
||||
import LoginPage from "./auth/LoginPage";
|
||||
import i18next from "i18next";
|
||||
import UrlTable from "./UrlTable";
|
||||
import ProviderTable from "./ProviderTable";
|
||||
import SignupTable from "./SignupTable";
|
||||
import UrlTable from "./table/UrlTable";
|
||||
import ProviderTable from "./table/ProviderTable";
|
||||
import SignupTable from "./table/SignupTable";
|
||||
import PromptPage from "./auth/PromptPage";
|
||||
import copy from "copy-to-clipboard";
|
||||
|
||||
|
@@ -21,8 +21,8 @@ import * as Setting from "./Setting";
|
||||
import * as Conf from "./Conf";
|
||||
import i18next from "i18next";
|
||||
import {LinkOutlined} from "@ant-design/icons";
|
||||
import LdapTable from "./LdapTable";
|
||||
import AccountTable from "./AccountTable";
|
||||
import LdapTable from "./table/LdapTable";
|
||||
import AccountTable from "./table/AccountTable";
|
||||
import ThemeEditor from "./common/theme/ThemeEditor";
|
||||
|
||||
const {Option} = Select;
|
||||
|
@@ -19,12 +19,12 @@ import * as ProviderBackend from "./backend/ProviderBackend";
|
||||
import * as Setting from "./Setting";
|
||||
import i18next from "i18next";
|
||||
import {authConfig} from "./auth/Auth";
|
||||
import * as ProviderEditTestEmail from "./TestEmailWidget";
|
||||
import * as ProviderEditTestSms from "./TestSmsWidget";
|
||||
import * as ProviderEditTestEmail from "./common/TestEmailWidget";
|
||||
import * as ProviderEditTestSms from "./common/TestSmsWidget";
|
||||
import copy from "copy-to-clipboard";
|
||||
import {CaptchaPreview} from "./common/CaptchaPreview";
|
||||
import * as OrganizationBackend from "./backend/OrganizationBackend";
|
||||
import {CountryCodeSelect} from "./common/CountryCodeSelect";
|
||||
import {CountryCodeSelect} from "./common/select/CountryCodeSelect";
|
||||
|
||||
const {Option} = Select;
|
||||
const {TextArea} = Input;
|
||||
@@ -110,7 +110,7 @@ class ProviderEditPage extends React.Component {
|
||||
getClientSecretLabel(provider) {
|
||||
switch (provider.category) {
|
||||
case "Email":
|
||||
return Setting.getLabel(i18next.t("login:Password"), i18next.t("login:Password - Tooltip"));
|
||||
return Setting.getLabel(i18next.t("general:Password"), i18next.t("general:Password - Tooltip"));
|
||||
case "SMS":
|
||||
if (provider.type === "Volc Engine SMS") {
|
||||
return Setting.getLabel(i18next.t("provider:Secret access key"), i18next.t("provider:Secret access key - Tooltip"));
|
||||
@@ -130,6 +130,24 @@ class ProviderEditPage extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
getProviderSubTypeOptions(type) {
|
||||
if (type === "WeCom" || type === "Infoflow") {
|
||||
return (
|
||||
[
|
||||
{id: "Internal", name: i18next.t("provider:Internal")},
|
||||
{id: "Third-party", name: i18next.t("provider:Third-party")},
|
||||
]
|
||||
);
|
||||
} else if (type === "Aliyun Captcha") {
|
||||
return [
|
||||
{id: "nc", name: i18next.t("provider:Sliding Validation")},
|
||||
{id: "ic", name: i18next.t("provider:Intelligent Validation")},
|
||||
];
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
getAppIdRow(provider) {
|
||||
let text = "";
|
||||
let tooltip = "";
|
||||
@@ -315,7 +333,7 @@ class ProviderEditPage extends React.Component {
|
||||
this.updateProviderField("subType", value);
|
||||
}}>
|
||||
{
|
||||
Setting.getProviderSubTypeOptions(this.state.provider.type).map((providerSubType, index) => <Option key={index} value={providerSubType.id}>{providerSubType.name}</Option>)
|
||||
this.getProviderSubTypeOptions(this.state.provider.type).map((providerSubType, index) => <Option key={index} value={providerSubType.id}>{providerSubType.name}</Option>)
|
||||
}
|
||||
</Select>
|
||||
</Col>
|
||||
@@ -331,7 +349,10 @@ class ProviderEditPage extends React.Component {
|
||||
this.updateProviderField("method", value);
|
||||
}}>
|
||||
{
|
||||
[{name: "Normal"}, {name: "Silent"}].map((method, index) => <Option key={index} value={method.name}>{method.name}</Option>)
|
||||
[
|
||||
{id: "Normal", name: i18next.t("provider:Normal")},
|
||||
{id: "Silent", name: i18next.t("provider:Silent")},
|
||||
].map((method, index) => <Option key={index} value={method.name}>{method.name}</Option>)
|
||||
}
|
||||
</Select>
|
||||
</Col>
|
||||
@@ -484,7 +505,7 @@ class ProviderEditPage extends React.Component {
|
||||
)
|
||||
}
|
||||
{
|
||||
this.state.provider.type !== "Adfs" && this.state.provider.type !== "Casdoor" && this.state.provider.type !== "Okta" ? null : (
|
||||
this.state.provider.type !== "Adfs" && this.state.provider.type !== "AzureAD" && this.state.provider.type !== "Casdoor" && this.state.provider.type !== "Okta" ? null : (
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={2}>
|
||||
{Setting.getLabel(i18next.t("provider:Domain"), i18next.t("provider:Domain - Tooltip"))} :
|
||||
|
@@ -14,7 +14,7 @@
|
||||
|
||||
import React from "react";
|
||||
import {Link} from "react-router-dom";
|
||||
import {Checkbox, Form, Modal, Select, Tag, Tooltip, message, theme} from "antd";
|
||||
import {Select, Tag, Tooltip, message, theme} from "antd";
|
||||
import {QuestionCircleTwoTone} from "@ant-design/icons";
|
||||
import {isMobile as isMobileDevice} from "react-device-detect";
|
||||
import "./i18n";
|
||||
@@ -552,10 +552,6 @@ export function addRow(array, row, position = "end") {
|
||||
return position === "end" ? [...array, row] : [row, ...array];
|
||||
}
|
||||
|
||||
export function prependRow(array, row) {
|
||||
return [row, ...array];
|
||||
}
|
||||
|
||||
export function deleteRow(array, i) {
|
||||
// return array = array.slice(0, i).concat(array.slice(i + 1));
|
||||
return [...array.slice(0, i), ...array.slice(i + 1)];
|
||||
@@ -585,76 +581,6 @@ export function isMobile() {
|
||||
return isMobileDevice;
|
||||
}
|
||||
|
||||
export function getTermsOfUseContent(url, setTermsOfUseContent) {
|
||||
fetch(url, {
|
||||
method: "GET",
|
||||
}).then(r => {
|
||||
r.text().then(setTermsOfUseContent);
|
||||
});
|
||||
}
|
||||
|
||||
export function isAgreementRequired(application) {
|
||||
if (application) {
|
||||
const agreementItem = application.signupItems.find(item => item.name === "Agreement");
|
||||
if (!agreementItem || agreementItem.rule === "None" || !agreementItem.rule) {
|
||||
return false;
|
||||
}
|
||||
if (agreementItem.required) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
export function isDefaultTrue(application) {
|
||||
const agreementItem = application.signupItems.find(item => item.name === "Agreement");
|
||||
|
||||
return isAgreementRequired(application) && agreementItem.rule === "Signin (Default True)";
|
||||
}
|
||||
|
||||
export function renderAgreement(required, onClick, noStyle, layout, initialValue) {
|
||||
return (
|
||||
<Form.Item
|
||||
name="agreement"
|
||||
key="agreement"
|
||||
valuePropName="checked"
|
||||
rules={[
|
||||
{
|
||||
required: required,
|
||||
message: i18next.t("signup:Please accept the agreement!"),
|
||||
},
|
||||
]}
|
||||
{...layout}
|
||||
noStyle={noStyle}
|
||||
initialValue={initialValue}
|
||||
>
|
||||
<Checkbox style={{float: "left"}}>
|
||||
{i18next.t("signup:Accept")}
|
||||
<a onClick={onClick}>
|
||||
{i18next.t("signup:Terms of Use")}
|
||||
</a>
|
||||
</Checkbox>
|
||||
</Form.Item>
|
||||
);
|
||||
}
|
||||
|
||||
export function renderModal(isOpen, onOk, onCancel, doc) {
|
||||
return (
|
||||
<Modal
|
||||
title={i18next.t("signup:Terms of Use")}
|
||||
open={isOpen}
|
||||
width={"55vw"}
|
||||
closable={false}
|
||||
okText={i18next.t("signup:Accept")}
|
||||
cancelText={i18next.t("signup:Decline")}
|
||||
onOk={onOk}
|
||||
onCancel={onCancel}
|
||||
>
|
||||
<iframe title={"terms"} style={{border: 0, width: "100%", height: "60vh"}} srcDoc={doc} />
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
|
||||
export function getFormattedDate(date) {
|
||||
if (date === undefined) {
|
||||
return null;
|
||||
@@ -731,14 +657,6 @@ export function getAvatarColor(s) {
|
||||
return colorList[hash % 4];
|
||||
}
|
||||
|
||||
export function getLogo(theme) {
|
||||
if (theme === "Dark") {
|
||||
return `${StaticBaseUrl}/img/casdoor-logo_1185x256_dark.png`;
|
||||
} else {
|
||||
return `${StaticBaseUrl}/img/casdoor-logo_1185x256.png`;
|
||||
}
|
||||
}
|
||||
|
||||
export function getLanguageText(text) {
|
||||
if (!text.includes("|")) {
|
||||
return text;
|
||||
@@ -763,11 +681,6 @@ export function setLanguage(language) {
|
||||
i18next.changeLanguage(language);
|
||||
}
|
||||
|
||||
export function setTheme(themeKey) {
|
||||
localStorage.setItem("theme", themeKey);
|
||||
dispatchEvent(new Event("changeTheme"));
|
||||
}
|
||||
|
||||
export function getAcceptLanguage() {
|
||||
if (i18next.language === null || i18next.language === "") {
|
||||
return "en;q=0.9,en;q=0.8";
|
||||
@@ -948,24 +861,6 @@ export function getProviderTypeOptions(category) {
|
||||
}
|
||||
}
|
||||
|
||||
export function getProviderSubTypeOptions(type) {
|
||||
if (type === "WeCom" || type === "Infoflow") {
|
||||
return (
|
||||
[
|
||||
{id: "Internal", name: "Internal"},
|
||||
{id: "Third-party", name: "Third-party"},
|
||||
]
|
||||
);
|
||||
} else if (type === "Aliyun Captcha") {
|
||||
return [
|
||||
{id: "nc", name: "Sliding Validation"},
|
||||
{id: "ic", name: "Intelligent Validation"},
|
||||
];
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
export function renderLogo(application) {
|
||||
if (application === null) {
|
||||
return null;
|
||||
@@ -1239,94 +1134,3 @@ export function inIframe() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
export function getSyncerTableColumns(syncer) {
|
||||
switch (syncer.type) {
|
||||
case "Keycloak":
|
||||
return [
|
||||
{
|
||||
"name": "ID",
|
||||
"type": "string",
|
||||
"casdoorName": "Id",
|
||||
"isHashed": true,
|
||||
"values": [
|
||||
|
||||
],
|
||||
},
|
||||
{
|
||||
"name": "USERNAME",
|
||||
"type": "string",
|
||||
"casdoorName": "Name",
|
||||
"isHashed": true,
|
||||
"values": [
|
||||
|
||||
],
|
||||
},
|
||||
{
|
||||
"name": "LAST_NAME+FIRST_NAME",
|
||||
"type": "string",
|
||||
"casdoorName": "DisplayName",
|
||||
"isHashed": true,
|
||||
"values": [
|
||||
|
||||
],
|
||||
},
|
||||
{
|
||||
"name": "EMAIL",
|
||||
"type": "string",
|
||||
"casdoorName": "Email",
|
||||
"isHashed": true,
|
||||
"values": [
|
||||
|
||||
],
|
||||
},
|
||||
{
|
||||
"name": "EMAIL_VERIFIED",
|
||||
"type": "boolean",
|
||||
"casdoorName": "EmailVerified",
|
||||
"isHashed": true,
|
||||
"values": [
|
||||
|
||||
],
|
||||
},
|
||||
{
|
||||
"name": "FIRST_NAME",
|
||||
"type": "string",
|
||||
"casdoorName": "FirstName",
|
||||
"isHashed": true,
|
||||
"values": [
|
||||
|
||||
],
|
||||
},
|
||||
{
|
||||
"name": "LAST_NAME",
|
||||
"type": "string",
|
||||
"casdoorName": "LastName",
|
||||
"isHashed": true,
|
||||
"values": [
|
||||
|
||||
],
|
||||
},
|
||||
{
|
||||
"name": "CREATED_TIMESTAMP",
|
||||
"type": "string",
|
||||
"casdoorName": "CreatedTime",
|
||||
"isHashed": true,
|
||||
"values": [
|
||||
|
||||
],
|
||||
},
|
||||
{
|
||||
"name": "ENABLED",
|
||||
"type": "boolean",
|
||||
"casdoorName": "IsForbidden",
|
||||
"isHashed": true,
|
||||
"values": [
|
||||
|
||||
],
|
||||
},
|
||||
];
|
||||
default:
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
@@ -19,7 +19,7 @@ import * as SyncerBackend from "./backend/SyncerBackend";
|
||||
import * as OrganizationBackend from "./backend/OrganizationBackend";
|
||||
import * as Setting from "./Setting";
|
||||
import i18next from "i18next";
|
||||
import SyncerTableColumnTable from "./SyncerTableColumnTable";
|
||||
import SyncerTableColumnTable from "./table/SyncerTableColumnTable";
|
||||
|
||||
import {Controlled as CodeMirror} from "react-codemirror2";
|
||||
import "codemirror/lib/codemirror.css";
|
||||
@@ -80,6 +80,97 @@ class SyncerEditPage extends React.Component {
|
||||
});
|
||||
}
|
||||
|
||||
getSyncerTableColumns(syncer) {
|
||||
switch (syncer.type) {
|
||||
case "Keycloak":
|
||||
return [
|
||||
{
|
||||
"name": "ID",
|
||||
"type": "string",
|
||||
"casdoorName": "Id",
|
||||
"isHashed": true,
|
||||
"values": [
|
||||
|
||||
],
|
||||
},
|
||||
{
|
||||
"name": "USERNAME",
|
||||
"type": "string",
|
||||
"casdoorName": "Name",
|
||||
"isHashed": true,
|
||||
"values": [
|
||||
|
||||
],
|
||||
},
|
||||
{
|
||||
"name": "LAST_NAME+FIRST_NAME",
|
||||
"type": "string",
|
||||
"casdoorName": "DisplayName",
|
||||
"isHashed": true,
|
||||
"values": [
|
||||
|
||||
],
|
||||
},
|
||||
{
|
||||
"name": "EMAIL",
|
||||
"type": "string",
|
||||
"casdoorName": "Email",
|
||||
"isHashed": true,
|
||||
"values": [
|
||||
|
||||
],
|
||||
},
|
||||
{
|
||||
"name": "EMAIL_VERIFIED",
|
||||
"type": "boolean",
|
||||
"casdoorName": "EmailVerified",
|
||||
"isHashed": true,
|
||||
"values": [
|
||||
|
||||
],
|
||||
},
|
||||
{
|
||||
"name": "FIRST_NAME",
|
||||
"type": "string",
|
||||
"casdoorName": "FirstName",
|
||||
"isHashed": true,
|
||||
"values": [
|
||||
|
||||
],
|
||||
},
|
||||
{
|
||||
"name": "LAST_NAME",
|
||||
"type": "string",
|
||||
"casdoorName": "LastName",
|
||||
"isHashed": true,
|
||||
"values": [
|
||||
|
||||
],
|
||||
},
|
||||
{
|
||||
"name": "CREATED_TIMESTAMP",
|
||||
"type": "string",
|
||||
"casdoorName": "CreatedTime",
|
||||
"isHashed": true,
|
||||
"values": [
|
||||
|
||||
],
|
||||
},
|
||||
{
|
||||
"name": "ENABLED",
|
||||
"type": "boolean",
|
||||
"casdoorName": "IsForbidden",
|
||||
"isHashed": true,
|
||||
"values": [
|
||||
|
||||
],
|
||||
},
|
||||
];
|
||||
default:
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
renderSyncer() {
|
||||
return (
|
||||
<Card size="small" title={
|
||||
@@ -120,7 +211,7 @@ class SyncerEditPage extends React.Component {
|
||||
<Select virtual={false} style={{width: "100%"}} value={this.state.syncer.type} onChange={(value => {
|
||||
this.updateSyncerField("type", value);
|
||||
const syncer = this.state.syncer;
|
||||
syncer["tableColumns"] = Setting.getSyncerTableColumns(this.state.syncer);
|
||||
syncer["tableColumns"] = this.getSyncerTableColumns(this.state.syncer);
|
||||
syncer.table = (value === "Keycloak") ? "user_entity" : this.state.syncer.table;
|
||||
this.setState({
|
||||
syncer: syncer,
|
||||
|
@@ -18,18 +18,18 @@ import * as UserBackend from "./backend/UserBackend";
|
||||
import * as OrganizationBackend from "./backend/OrganizationBackend";
|
||||
import * as Setting from "./Setting";
|
||||
import i18next from "i18next";
|
||||
import CropperDiv from "./CropperDiv.js";
|
||||
import CropperDivModal from "./common/modal/CropperDivModal.js";
|
||||
import * as ApplicationBackend from "./backend/ApplicationBackend";
|
||||
import PasswordModal from "./PasswordModal";
|
||||
import ResetModal from "./ResetModal";
|
||||
import AffiliationSelect from "./common/AffiliationSelect";
|
||||
import PasswordModal from "./common/modal/PasswordModal";
|
||||
import ResetModal from "./common/modal/ResetModal";
|
||||
import AffiliationSelect from "./common/select/AffiliationSelect";
|
||||
import OAuthWidget from "./common/OAuthWidget";
|
||||
import SamlWidget from "./common/SamlWidget";
|
||||
import SelectRegionBox from "./SelectRegionBox";
|
||||
import WebAuthnCredentialTable from "./WebauthnCredentialTable";
|
||||
import ManagedAccountTable from "./ManagedAccountTable";
|
||||
import PropertyTable from "./propertyTable";
|
||||
import {CountryCodeSelect} from "./common/CountryCodeSelect";
|
||||
import RegionSelect from "./common/select/RegionSelect";
|
||||
import WebAuthnCredentialTable from "./table/WebauthnCredentialTable";
|
||||
import ManagedAccountTable from "./table/ManagedAccountTable";
|
||||
import PropertyTable from "./table/propertyTable";
|
||||
import {CountryCodeSelect} from "./common/select/CountryCodeSelect";
|
||||
|
||||
const {Option} = Select;
|
||||
|
||||
@@ -253,7 +253,7 @@ class UserEditPage extends React.Component {
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}}>
|
||||
<CropperDiv buttonText={`${i18next.t("user:Upload a photo")}...`} title={i18next.t("user:Upload a photo")} user={this.state.user} organization={this.state.organizations.find(organization => organization.name === this.state.organizationName)} />
|
||||
<CropperDivModal buttonText={`${i18next.t("user:Upload a photo")}...`} title={i18next.t("user:Upload a photo")} user={this.state.user} organization={this.state.organizations.find(organization => organization.name === this.state.organizationName)} />
|
||||
</Row>
|
||||
</Col>
|
||||
</Row>
|
||||
@@ -341,7 +341,7 @@ class UserEditPage extends React.Component {
|
||||
{Setting.getLabel(i18next.t("user:Country/Region"), i18next.t("user:Country/Region - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<SelectRegionBox defaultValue={this.state.user.region} onChange={(value) => {
|
||||
<RegionSelect defaultValue={this.state.user.region} onChange={(value) => {
|
||||
this.updateUserField("region", value);
|
||||
}} />
|
||||
</Col>
|
||||
|
@@ -19,7 +19,7 @@ import * as WebhookBackend from "./backend/WebhookBackend";
|
||||
import * as OrganizationBackend from "./backend/OrganizationBackend";
|
||||
import * as Setting from "./Setting";
|
||||
import i18next from "i18next";
|
||||
import WebhookHeaderTable from "./WebhookHeaderTable";
|
||||
import WebhookHeaderTable from "./table/WebhookHeaderTable";
|
||||
|
||||
import {Controlled as CodeMirror} from "react-codemirror2";
|
||||
import "codemirror/lib/codemirror.css";
|
||||
|
@@ -22,7 +22,7 @@ import i18next from "i18next";
|
||||
import {SendCodeInput} from "../common/SendCodeInput";
|
||||
import * as UserBackend from "../backend/UserBackend";
|
||||
import {CheckCircleOutlined, KeyOutlined, LockOutlined, SolutionOutlined, UserOutlined} from "@ant-design/icons";
|
||||
import CustomGithubCorner from "../CustomGithubCorner";
|
||||
import CustomGithubCorner from "../common/CustomGithubCorner";
|
||||
import {withRouter} from "react-router-dom";
|
||||
const {Option} = Select;
|
||||
|
||||
@@ -32,7 +32,6 @@ class ForgetPage extends React.Component {
|
||||
this.state = {
|
||||
classes: props,
|
||||
applicationName: props.applicationName ?? props.match.params?.applicationName,
|
||||
application: null,
|
||||
msg: null,
|
||||
userId: "",
|
||||
username: "",
|
||||
@@ -49,7 +48,7 @@ class ForgetPage extends React.Component {
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
if (this.getApplicationObj() === null) {
|
||||
if (this.getApplicationObj() === undefined) {
|
||||
if (this.state.applicationName !== undefined) {
|
||||
this.getApplication();
|
||||
} else {
|
||||
@@ -66,14 +65,11 @@ class ForgetPage extends React.Component {
|
||||
ApplicationBackend.getApplication("admin", this.state.applicationName)
|
||||
.then((application) => {
|
||||
this.onUpdateApplication(application);
|
||||
this.setState({
|
||||
application: application,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
getApplicationObj() {
|
||||
return this.props.application ?? this.state.application;
|
||||
return this.props.application;
|
||||
}
|
||||
|
||||
onUpdateApplication(application) {
|
||||
@@ -436,6 +432,9 @@ class ForgetPage extends React.Component {
|
||||
|
||||
render() {
|
||||
const application = this.getApplicationObj();
|
||||
if (application === undefined) {
|
||||
return null;
|
||||
}
|
||||
if (application === null) {
|
||||
return Util.renderMessageLarge(this, this.state.msg);
|
||||
}
|
||||
|
@@ -24,12 +24,13 @@ import * as Provider from "./Provider";
|
||||
import * as ProviderButton from "./ProviderButton";
|
||||
import * as Util from "./Util";
|
||||
import * as Setting from "../Setting";
|
||||
import * as AgreementModal from "../common/modal/AgreementModal";
|
||||
import SelfLoginButton from "./SelfLoginButton";
|
||||
import i18next from "i18next";
|
||||
import CustomGithubCorner from "../CustomGithubCorner";
|
||||
import CustomGithubCorner from "../common/CustomGithubCorner";
|
||||
import {SendCodeInput} from "../common/SendCodeInput";
|
||||
import SelectLanguageBox from "../SelectLanguageBox";
|
||||
import {CaptchaModal} from "../common/CaptchaModal";
|
||||
import LanguageSelect from "../common/select/LanguageSelect";
|
||||
import {CaptchaModal} from "../common/modal/CaptchaModal";
|
||||
import RedirectForm from "../common/RedirectForm";
|
||||
|
||||
class LoginPage extends React.Component {
|
||||
@@ -38,10 +39,9 @@ class LoginPage extends React.Component {
|
||||
this.state = {
|
||||
classes: props,
|
||||
type: props.type,
|
||||
applicationName: props.applicationName !== undefined ? props.applicationName : (props.match === undefined ? null : props.match.params.applicationName),
|
||||
owner: props.owner !== undefined ? props.owner : (props.match === undefined ? null : props.match.params.owner),
|
||||
application: null,
|
||||
mode: props.mode !== undefined ? props.mode : (props.match === undefined ? null : props.match.params.mode), // "signup" or "signin"
|
||||
applicationName: props.applicationName ?? (props.match?.params?.applicationName ?? null),
|
||||
owner: props.owner ?? (props.match?.params?.owner ?? null),
|
||||
mode: props.mode ?? (props.match?.params?.mode ?? null), // "signup" or "signin"
|
||||
msg: null,
|
||||
username: null,
|
||||
validEmailOrPhone: false,
|
||||
@@ -58,21 +58,19 @@ class LoginPage extends React.Component {
|
||||
};
|
||||
|
||||
if (this.state.type === "cas" && props.match?.params.casApplicationName !== undefined) {
|
||||
this.state.owner = props.match?.params.owner;
|
||||
this.state.applicationName = props.match?.params.casApplicationName;
|
||||
this.state.owner = props.match?.params?.owner;
|
||||
this.state.applicationName = props.match?.params?.casApplicationName;
|
||||
}
|
||||
|
||||
this.form = React.createRef();
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
if (this.getApplicationObj() === null) {
|
||||
if (this.state.type === "login" || this.state.type === "cas") {
|
||||
if (this.getApplicationObj() === undefined) {
|
||||
if (this.state.type === "login" || this.state.type === "cas" || this.state.type === "saml") {
|
||||
this.getApplication();
|
||||
} else if (this.state.type === "code") {
|
||||
this.getApplicationLogin();
|
||||
} else if (this.state.type === "saml") {
|
||||
this.getSamlApplication();
|
||||
} else {
|
||||
Setting.showMessage("error", `Unknown authentication type: ${this.state.type}`);
|
||||
}
|
||||
@@ -80,14 +78,35 @@ class LoginPage extends React.Component {
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps, prevState, snapshot) {
|
||||
if (this.state.application && !prevState.application) {
|
||||
const captchaProviderItems = this.getCaptchaProviderItems(this.state.application);
|
||||
|
||||
if (!captchaProviderItems) {
|
||||
return;
|
||||
if (prevProps.application !== this.props.application) {
|
||||
const captchaProviderItems = this.getCaptchaProviderItems(this.props.application);
|
||||
if (captchaProviderItems) {
|
||||
this.setState({enableCaptchaModal: captchaProviderItems.some(providerItem => providerItem.rule === "Always")});
|
||||
}
|
||||
|
||||
this.setState({enableCaptchaModal: captchaProviderItems.some(providerItem => providerItem.rule === "Always")});
|
||||
if (this.props.account && this.props.account.owner === this.props.application?.organization) {
|
||||
const params = new URLSearchParams(this.props.location.search);
|
||||
const silentSignin = params.get("silentSignin");
|
||||
if (silentSignin !== null) {
|
||||
this.sendSilentSigninData("signing-in");
|
||||
|
||||
const values = {};
|
||||
values["application"] = this.props.application.name;
|
||||
this.login(values);
|
||||
}
|
||||
|
||||
if (params.get("popup") === "1") {
|
||||
window.addEventListener("beforeunload", () => {
|
||||
this.sendPopupData({type: "windowClosed"}, params.get("redirect_uri"));
|
||||
});
|
||||
}
|
||||
|
||||
if (this.props.application.enableAutoSignin) {
|
||||
const values = {};
|
||||
values["application"] = this.props.application.name;
|
||||
this.login(values);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,47 +115,37 @@ class LoginPage extends React.Component {
|
||||
AuthBackend.getApplicationLogin(oAuthParams)
|
||||
.then((res) => {
|
||||
if (res.status === "ok") {
|
||||
this.onUpdateApplication(res.data);
|
||||
this.setState({
|
||||
application: res.data,
|
||||
});
|
||||
const application = res.data;
|
||||
this.onUpdateApplication(application);
|
||||
} else {
|
||||
// Setting.showMessage("error", res.msg);
|
||||
this.onUpdateApplication(null);
|
||||
this.setState({
|
||||
application: res.data,
|
||||
msg: res.msg,
|
||||
});
|
||||
}
|
||||
});
|
||||
return null;
|
||||
}
|
||||
|
||||
getApplication() {
|
||||
if (this.state.applicationName === null) {
|
||||
return;
|
||||
return null;
|
||||
}
|
||||
|
||||
if (this.state.owner === null || this.state.owner === undefined || this.state.owner === "") {
|
||||
if (this.state.owner === null || this.state.type === "saml") {
|
||||
ApplicationBackend.getApplication("admin", this.state.applicationName)
|
||||
.then((application) => {
|
||||
this.onUpdateApplication(application);
|
||||
this.setState({
|
||||
application: application,
|
||||
}, () => Setting.getTermsOfUseContent(this.state.application.termsOfUse, res => {
|
||||
this.setState({termsOfUseContent: res});
|
||||
}));
|
||||
});
|
||||
} else {
|
||||
OrganizationBackend.getDefaultApplication("admin", this.state.owner)
|
||||
.then((res) => {
|
||||
if (res.status === "ok") {
|
||||
this.onUpdateApplication(res.data);
|
||||
const application = res.data;
|
||||
this.onUpdateApplication(application);
|
||||
this.setState({
|
||||
application: res.data,
|
||||
applicationName: res.data.name,
|
||||
}, () => Setting.getTermsOfUseContent(this.state.application.termsOfUse, res => {
|
||||
this.setState({termsOfUseContent: res});
|
||||
}));
|
||||
});
|
||||
} else {
|
||||
this.onUpdateApplication(null);
|
||||
Setting.showMessage("error", res.msg);
|
||||
@@ -145,21 +154,8 @@ class LoginPage extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
getSamlApplication() {
|
||||
if (this.state.applicationName === null) {
|
||||
return;
|
||||
}
|
||||
ApplicationBackend.getApplication(this.state.owner, this.state.applicationName)
|
||||
.then((application) => {
|
||||
this.onUpdateApplication(application);
|
||||
this.setState({
|
||||
application: application,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
getApplicationObj() {
|
||||
return this.props.application ?? this.state.application;
|
||||
return this.props.application;
|
||||
}
|
||||
|
||||
onUpdateAccount(account) {
|
||||
@@ -183,25 +179,19 @@ class LoginPage extends React.Component {
|
||||
}
|
||||
|
||||
populateOauthValues(values) {
|
||||
const oAuthParams = Util.getOAuthGetParameters();
|
||||
if (oAuthParams !== null && oAuthParams.responseType !== null && oAuthParams.responseType !== "") {
|
||||
values["type"] = oAuthParams.responseType;
|
||||
} else {
|
||||
values["type"] = this.state.type;
|
||||
}
|
||||
|
||||
if (oAuthParams !== null) {
|
||||
values["samlRequest"] = oAuthParams.samlRequest;
|
||||
}
|
||||
|
||||
if (values["samlRequest"] !== null && values["samlRequest"] !== "" && values["samlRequest"] !== undefined) {
|
||||
values["type"] = "saml";
|
||||
values["relayState"] = oAuthParams.relayState;
|
||||
}
|
||||
|
||||
if (this.getApplicationObj()?.organization) {
|
||||
values["organization"] = this.getApplicationObj().organization;
|
||||
}
|
||||
|
||||
const oAuthParams = Util.getOAuthGetParameters();
|
||||
|
||||
values["type"] = oAuthParams?.responseType ?? this.state.type;
|
||||
|
||||
if (oAuthParams?.samlRequest) {
|
||||
values["samlRequest"] = oAuthParams.samlRequest;
|
||||
values["type"] = "saml";
|
||||
values["relayState"] = oAuthParams.relayState;
|
||||
}
|
||||
}
|
||||
|
||||
sendPopupData(message, redirectUri) {
|
||||
@@ -305,7 +295,6 @@ class LoginPage extends React.Component {
|
||||
// OAuth
|
||||
const oAuthParams = Util.getOAuthGetParameters();
|
||||
this.populateOauthValues(values);
|
||||
|
||||
AuthBackend.login(values, oAuthParams)
|
||||
.then((res) => {
|
||||
if (res.status === "ok") {
|
||||
@@ -318,7 +307,6 @@ class LoginPage extends React.Component {
|
||||
Setting.goToLink(link);
|
||||
} else if (responseType === "code") {
|
||||
this.postCodeLoginAction(res);
|
||||
// Setting.showMessage("success", `Authorization code: ${res.data}`);
|
||||
} else if (responseType === "token" || responseType === "id_token") {
|
||||
const accessToken = res.data;
|
||||
Setting.goToLink(`${oAuthParams.redirectUri}#${responseType}=${accessToken}?state=${oAuthParams.state}&token_type=bearer`);
|
||||
@@ -471,25 +459,17 @@ class LoginPage extends React.Component {
|
||||
this.renderPasswordOrCodeInput()
|
||||
}
|
||||
</Row>
|
||||
<Form.Item>
|
||||
{
|
||||
Setting.isAgreementRequired(application) ?
|
||||
Setting.renderAgreement(true, () => {
|
||||
this.setState({
|
||||
isTermsOfUseVisible: true,
|
||||
});
|
||||
}, true, {}, Setting.isDefaultTrue(application)) : (
|
||||
<Form.Item name="autoSignin" valuePropName="checked" noStyle>
|
||||
<Checkbox style={{float: "left"}} disabled={!application.enablePassword}>
|
||||
{i18next.t("login:Auto sign in")}
|
||||
</Checkbox>
|
||||
</Form.Item>
|
||||
)
|
||||
}
|
||||
<div style={{display: "inline-flex", justifyContent: "space-between", width: "320px", marginBottom: AgreementModal.isAgreementRequired(application) ? "5px" : "25px"}}>
|
||||
<Form.Item name="autoSignin" valuePropName="checked" noStyle>
|
||||
<Checkbox style={{float: "left"}} disabled={!application.enablePassword}>
|
||||
{i18next.t("login:Auto sign in")}
|
||||
</Checkbox>
|
||||
</Form.Item>
|
||||
{
|
||||
Setting.renderForgetLink(application, i18next.t("login:Forgot password?"))
|
||||
}
|
||||
</Form.Item>
|
||||
</div>
|
||||
{AgreementModal.isAgreementRequired(application) ? AgreementModal.renderAgreementFormItem(application, true, {}, this) : null}
|
||||
<Form.Item>
|
||||
<Button
|
||||
type="primary"
|
||||
@@ -634,37 +614,12 @@ class LoginPage extends React.Component {
|
||||
}
|
||||
|
||||
const application = this.getApplicationObj();
|
||||
if (this.props.account.owner !== application.organization) {
|
||||
if (this.props.account.owner !== application?.organization) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const params = new URLSearchParams(this.props.location.search);
|
||||
const silentSignin = params.get("silentSignin");
|
||||
if (silentSignin !== null) {
|
||||
this.sendSilentSigninData("signing-in");
|
||||
|
||||
const values = {};
|
||||
values["application"] = application.name;
|
||||
this.onFinish(values);
|
||||
}
|
||||
|
||||
if (params.get("popup") === "1") {
|
||||
window.addEventListener("beforeunload", () => {
|
||||
this.sendPopupData({type: "windowClosed"}, params.get("redirect_uri"));
|
||||
});
|
||||
}
|
||||
|
||||
if (application.enableAutoSignin) {
|
||||
const values = {};
|
||||
values["application"] = application.name;
|
||||
this.onFinish(values);
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
{/* {*/}
|
||||
{/* JSON.stringify(silentSignin)*/}
|
||||
{/* }*/}
|
||||
<div style={{fontSize: 16, textAlign: "left"}}>
|
||||
{i18next.t("login:Continue with")} :
|
||||
</div>
|
||||
@@ -672,7 +627,7 @@ class LoginPage extends React.Component {
|
||||
<SelfLoginButton account={this.props.account} onClick={() => {
|
||||
const values = {};
|
||||
values["application"] = application.name;
|
||||
this.onFinish(values);
|
||||
this.login(values);
|
||||
}} />
|
||||
<br />
|
||||
<br />
|
||||
@@ -814,6 +769,9 @@ class LoginPage extends React.Component {
|
||||
|
||||
render() {
|
||||
const application = this.getApplicationObj();
|
||||
if (application === undefined) {
|
||||
return null;
|
||||
}
|
||||
if (application === null) {
|
||||
return Util.renderMessageLarge(this, this.state.msg);
|
||||
}
|
||||
@@ -856,29 +814,13 @@ class LoginPage extends React.Component {
|
||||
{
|
||||
Setting.renderLogo(application)
|
||||
}
|
||||
{/* {*/}
|
||||
{/* this.state.clientId !== null ? "Redirect" : null*/}
|
||||
{/* }*/}
|
||||
<SelectLanguageBox languages={application.organizationObj.languages} style={{top: "55px", right: "5px", position: "absolute"}} />
|
||||
<LanguageSelect languages={application.organizationObj.languages} style={{top: "55px", right: "5px", position: "absolute"}} />
|
||||
{
|
||||
this.renderSignedInBox()
|
||||
}
|
||||
{
|
||||
this.renderForm(application)
|
||||
}
|
||||
{
|
||||
Setting.renderModal(this.state.isTermsOfUseVisible, () => {
|
||||
this.form.current.setFieldsValue({agreement: true});
|
||||
this.setState({
|
||||
isTermsOfUseVisible: false,
|
||||
});
|
||||
}, () => {
|
||||
this.form.current.setFieldsValue({agreement: false});
|
||||
this.setState({
|
||||
isTermsOfUseVisible: false,
|
||||
});
|
||||
}, this.state.termsOfUseContent)
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@@ -19,9 +19,9 @@ import * as UserBackend from "../backend/UserBackend";
|
||||
import * as AuthBackend from "./AuthBackend";
|
||||
import * as Setting from "../Setting";
|
||||
import i18next from "i18next";
|
||||
import AffiliationSelect from "../common/AffiliationSelect";
|
||||
import AffiliationSelect from "../common/select/AffiliationSelect";
|
||||
import OAuthWidget from "../common/OAuthWidget";
|
||||
import SelectRegionBox from "../SelectRegionBox";
|
||||
import RegionSelect from "../common/select/RegionSelect";
|
||||
import {withRouter} from "react-router-dom";
|
||||
|
||||
class PromptPage extends React.Component {
|
||||
@@ -151,7 +151,7 @@ class PromptPage extends React.Component {
|
||||
</span>
|
||||
</Col>
|
||||
<Col >
|
||||
<SelectRegionBox defaultValue={this.state.user.region} onChange={(value) => {
|
||||
<RegionSelect defaultValue={this.state.user.region} onChange={(value) => {
|
||||
this.updateUserFieldWithoutSubmit("region", value);
|
||||
}} />
|
||||
</Col>
|
||||
|
@@ -378,6 +378,12 @@ export function getAuthUrl(application, provider, method) {
|
||||
const state = Util.getStateFromQueryParams(application.name, provider.name, method, isShortState);
|
||||
const codeChallenge = "P3S-a7dr8bgM4bF6vOyiKkKETDl16rcAzao9F8UIL1Y"; // SHA256(Base64-URL-encode("casdoor-verifier"))
|
||||
|
||||
if (provider.type === "AzureAD") {
|
||||
if (provider.domain !== "") {
|
||||
endpoint = endpoint.replace("common", provider.domain);
|
||||
}
|
||||
}
|
||||
|
||||
if (provider.type === "Google" || provider.type === "GitHub" || provider.type === "QQ" || provider.type === "Facebook"
|
||||
|| provider.type === "Weibo" || provider.type === "Gitee" || provider.type === "LinkedIn" || provider.type === "GitLab" || provider.type === "AzureAD"
|
||||
|| provider.type === "Slack" || provider.type === "Line" || provider.type === "Amazon" || provider.type === "Auth0" || provider.type === "BattleNet"
|
||||
|
@@ -101,12 +101,13 @@ function getSigninButton(type) {
|
||||
|
||||
function getSamlUrl(provider, location) {
|
||||
const params = new URLSearchParams(location.search);
|
||||
const clientId = params.get("client_id");
|
||||
const application = params.get("state");
|
||||
const clientId = params.get("client_id") ?? "";
|
||||
const state = params.get("state");
|
||||
const realRedirectUri = params.get("redirect_uri");
|
||||
const redirectUri = `${window.location.origin}/callback/saml`;
|
||||
const providerName = provider.name;
|
||||
const relayState = `${clientId}&${application}&${providerName}&${realRedirectUri}&${redirectUri}`;
|
||||
|
||||
const relayState = `${clientId}&${state}&${providerName}&${realRedirectUri}&${redirectUri}`;
|
||||
AuthBackend.getSamlLogin(`${provider.owner}/${providerName}`, btoa(relayState)).then((res) => {
|
||||
if (res.data2 === "POST") {
|
||||
document.write(res.data);
|
||||
|
@@ -49,18 +49,21 @@ class SamlCallback extends React.Component {
|
||||
const params = new URLSearchParams(this.props.location.search);
|
||||
const relayState = params.get("relayState");
|
||||
const samlResponse = params.get("samlResponse");
|
||||
|
||||
const messages = atob(relayState).split("&");
|
||||
const clientId = messages[0];
|
||||
const applicationName = (messages[1] === "null" || messages[1] === "undefined") ? "app-built-in" : messages[1];
|
||||
const clientId = messages[0] === "" ? "" : messages[0];
|
||||
const application = messages[0] === "" ? "app-built-in" : "";
|
||||
const state = messages[1];
|
||||
const providerName = messages[2];
|
||||
const redirectUri = messages[3];
|
||||
const responseType = this.getResponseType(redirectUri);
|
||||
|
||||
const body = {
|
||||
type: responseType,
|
||||
application: applicationName,
|
||||
clientId: clientId,
|
||||
provider: providerName,
|
||||
state: applicationName,
|
||||
state: state,
|
||||
application: application,
|
||||
redirectUri: `${window.location.origin}/callback`,
|
||||
method: "signup",
|
||||
relayState: relayState,
|
||||
@@ -71,7 +74,7 @@ class SamlCallback extends React.Component {
|
||||
if (clientId === null || clientId === "") {
|
||||
param = "";
|
||||
} else {
|
||||
param = `?clientId=${clientId}&responseType=${responseType}&redirectUri=${redirectUri}&scope=read&state=${applicationName}`;
|
||||
param = `?clientId=${clientId}&responseType=${responseType}&redirectUri=${redirectUri}&scope=read&state=${state}`;
|
||||
}
|
||||
|
||||
AuthBackend.loginWithSaml(body, param)
|
||||
@@ -83,7 +86,7 @@ class SamlCallback extends React.Component {
|
||||
Setting.goToLink("/");
|
||||
} else if (responseType === "code") {
|
||||
const code = res.data;
|
||||
Setting.goToLink(`${redirectUri}?code=${code}&state=${applicationName}`);
|
||||
Setting.goToLink(`${redirectUri}?code=${code}&state=${state}`);
|
||||
}
|
||||
} else {
|
||||
this.setState({
|
||||
|
@@ -40,7 +40,7 @@ class SelfLoginButton extends React.Component {
|
||||
};
|
||||
|
||||
const SelfLoginButton = createButton(config);
|
||||
return <SelfLoginButton text={this.getAccountShowName()} onClick={() => this.props.onClick()} align={"center"} />;
|
||||
return <SelfLoginButton text={this.getAccountShowName()} onClick={this.props.onClick} align={"center"} />;
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -21,12 +21,13 @@ import i18next from "i18next";
|
||||
import * as Util from "./Util";
|
||||
import {authConfig} from "./Auth";
|
||||
import * as ApplicationBackend from "../backend/ApplicationBackend";
|
||||
import * as AgreementModal from "../common/modal/AgreementModal";
|
||||
import {SendCodeInput} from "../common/SendCodeInput";
|
||||
import SelectRegionBox from "../SelectRegionBox";
|
||||
import CustomGithubCorner from "../CustomGithubCorner";
|
||||
import SelectLanguageBox from "../SelectLanguageBox";
|
||||
import RegionSelect from "../common/select/RegionSelect";
|
||||
import CustomGithubCorner from "../common/CustomGithubCorner";
|
||||
import LanguageSelect from "../common/select/LanguageSelect";
|
||||
import {withRouter} from "react-router-dom";
|
||||
import {CountryCodeSelect} from "../common/CountryCodeSelect";
|
||||
import {CountryCodeSelect} from "../common/select/CountryCodeSelect";
|
||||
|
||||
const formItemLayout = {
|
||||
labelCol: {
|
||||
@@ -47,7 +48,7 @@ const formItemLayout = {
|
||||
},
|
||||
};
|
||||
|
||||
const tailFormItemLayout = {
|
||||
export const tailFormItemLayout = {
|
||||
wrapperCol: {
|
||||
xs: {
|
||||
span: 24,
|
||||
@@ -65,8 +66,7 @@ class SignupPage extends React.Component {
|
||||
super(props);
|
||||
this.state = {
|
||||
classes: props,
|
||||
applicationName: props.match.params?.applicationName ?? authConfig.appName,
|
||||
application: null,
|
||||
applicationName: props.match?.params?.applicationName ?? authConfig.appName,
|
||||
email: "",
|
||||
phone: "",
|
||||
countryCode: "",
|
||||
@@ -83,20 +83,17 @@ class SignupPage extends React.Component {
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
let applicationName = this.state.applicationName;
|
||||
const oAuthParams = Util.getOAuthGetParameters();
|
||||
if (oAuthParams !== null) {
|
||||
applicationName = oAuthParams.state;
|
||||
this.setState({applicationName: oAuthParams.state});
|
||||
const signinUrl = window.location.href.replace("/signup/oauth/authorize", "/login/oauth/authorize");
|
||||
sessionStorage.setItem("signinUrl", signinUrl);
|
||||
}
|
||||
|
||||
if (this.getApplicationObj() === null) {
|
||||
if (applicationName !== undefined) {
|
||||
this.getApplication(applicationName);
|
||||
if (this.getApplicationObj() === undefined) {
|
||||
if (this.state.applicationName !== null) {
|
||||
this.getApplication(this.state.applicationName);
|
||||
} else {
|
||||
Setting.showMessage("error", `Unknown application name: ${applicationName}`);
|
||||
Setting.showMessage("error", `Unknown application name: ${this.state.applicationName}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -109,15 +106,6 @@ class SignupPage extends React.Component {
|
||||
ApplicationBackend.getApplication("admin", applicationName)
|
||||
.then((application) => {
|
||||
this.onUpdateApplication(application);
|
||||
this.setState({
|
||||
application: application,
|
||||
});
|
||||
|
||||
if (application !== null && application !== undefined) {
|
||||
Setting.getTermsOfUseContent(application.termsOfUse, res => {
|
||||
this.setState({termsOfUseContent: res});
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -134,7 +122,7 @@ class SignupPage extends React.Component {
|
||||
}
|
||||
|
||||
getApplicationObj() {
|
||||
return this.props.application ?? this.state.application;
|
||||
return this.props.application;
|
||||
}
|
||||
|
||||
onUpdateAccount(account) {
|
||||
@@ -318,7 +306,7 @@ class SignupPage extends React.Component {
|
||||
},
|
||||
]}
|
||||
>
|
||||
<SelectRegionBox onChange={(value) => {this.setState({region: value});}} />
|
||||
<RegionSelect onChange={(value) => {this.setState({region: value});}} />
|
||||
</Form.Item>
|
||||
);
|
||||
} else if (signupItem.name === "Email") {
|
||||
@@ -484,32 +472,10 @@ class SignupPage extends React.Component {
|
||||
</Form.Item>
|
||||
);
|
||||
} else if (signupItem.name === "Agreement") {
|
||||
return (
|
||||
Setting.renderAgreement(Setting.isAgreementRequired(application), () => {
|
||||
this.setState({
|
||||
isTermsOfUseVisible: true,
|
||||
});
|
||||
}, false, tailFormItemLayout, Setting.isDefaultTrue(application))
|
||||
);
|
||||
return AgreementModal.renderAgreementFormItem(application, required, tailFormItemLayout, this);
|
||||
}
|
||||
}
|
||||
|
||||
renderModal() {
|
||||
return (
|
||||
Setting.renderModal(this.state.isTermsOfUseVisible, () => {
|
||||
this.form.current.setFieldsValue({agreement: true});
|
||||
this.setState({
|
||||
isTermsOfUseVisible: false,
|
||||
});
|
||||
}, () => {
|
||||
this.form.current.setFieldsValue({agreement: false});
|
||||
this.setState({
|
||||
isTermsOfUseVisible: false,
|
||||
});
|
||||
}, this.state.termsOfUseContent)
|
||||
);
|
||||
}
|
||||
|
||||
renderForm(application) {
|
||||
if (!application.enableSignUp) {
|
||||
return (
|
||||
@@ -596,7 +562,7 @@ class SignupPage extends React.Component {
|
||||
|
||||
render() {
|
||||
const application = this.getApplicationObj();
|
||||
if (application === null) {
|
||||
if (application === undefined || application === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -622,16 +588,13 @@ class SignupPage extends React.Component {
|
||||
{
|
||||
Setting.renderLogo(application)
|
||||
}
|
||||
<SelectLanguageBox languages={application.organizationObj.languages} style={{top: "55px", right: "5px", position: "absolute"}} />
|
||||
<LanguageSelect languages={application.organizationObj.languages} style={{top: "55px", right: "5px", position: "absolute"}} />
|
||||
{
|
||||
this.renderForm(application)
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{
|
||||
this.renderModal()
|
||||
}
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
||||
|
@@ -43,27 +43,20 @@ export function renderMessage(msg) {
|
||||
export function renderMessageLarge(ths, msg) {
|
||||
if (msg !== null) {
|
||||
return (
|
||||
<div style={{display: "inline"}}>
|
||||
<Result
|
||||
status="error"
|
||||
title="There was a problem signing you in.."
|
||||
subTitle={msg}
|
||||
extra={[
|
||||
<Button type="primary" key="back" onClick={() => {
|
||||
window.history.go(-2);
|
||||
}}>
|
||||
<Result
|
||||
style={{margin: "0px auto"}}
|
||||
status="error"
|
||||
title="There was a problem signing you in.."
|
||||
subTitle={msg}
|
||||
extra={[
|
||||
<Button type="primary" key="back" onClick={() => {
|
||||
window.history.go(-2);
|
||||
}}>
|
||||
Back
|
||||
</Button>,
|
||||
// <Button key="home" onClick={() => Setting.goToLinkSoft(ths, "/")}>
|
||||
// Home
|
||||
// </Button>,
|
||||
// <Button type="primary" key="signup" onClick={() => Setting.goToLinkSoft(ths, "/signup")}>
|
||||
// Sign Up
|
||||
// </Button>,
|
||||
]}
|
||||
>
|
||||
</Result>
|
||||
</div>
|
||||
</Button>,
|
||||
]}
|
||||
>
|
||||
</Result>
|
||||
);
|
||||
} else {
|
||||
return null;
|
||||
@@ -71,7 +64,7 @@ export function renderMessageLarge(ths, msg) {
|
||||
}
|
||||
|
||||
function getRefinedValue(value) {
|
||||
return (value === null) ? "" : value;
|
||||
return value ?? "";
|
||||
}
|
||||
|
||||
export function getCasParameters(params) {
|
||||
@@ -100,7 +93,7 @@ export function getOAuthGetParameters(params) {
|
||||
const relayState = getRefinedValue(queries.get("RelayState"));
|
||||
const noRedirect = getRefinedValue(queries.get("noRedirect"));
|
||||
|
||||
if ((clientId === undefined || clientId === null || clientId === "") && (samlRequest === "" || samlRequest === undefined)) {
|
||||
if (clientId === "" && samlRequest === "") {
|
||||
// login
|
||||
return null;
|
||||
} else {
|
||||
|
@@ -15,7 +15,7 @@
|
||||
import {Button} from "antd";
|
||||
import React from "react";
|
||||
import i18next from "i18next";
|
||||
import {CaptchaModal} from "./CaptchaModal";
|
||||
import {CaptchaModal} from "./modal/CaptchaModal";
|
||||
import * as UserBackend from "../backend/UserBackend";
|
||||
|
||||
export const CaptchaPreview = (props) => {
|
||||
|
@@ -13,7 +13,7 @@
|
||||
// limitations under the License.
|
||||
|
||||
import React from "react";
|
||||
import * as Conf from "./Conf";
|
||||
import * as Conf from "../Conf";
|
||||
import GithubCorner from "react-github-corner";
|
||||
|
||||
class CustomGithubCorner extends React.Component {
|
@@ -17,7 +17,7 @@ import React from "react";
|
||||
import i18next from "i18next";
|
||||
import * as UserBackend from "../backend/UserBackend";
|
||||
import {SafetyOutlined} from "@ant-design/icons";
|
||||
import {CaptchaModal} from "./CaptchaModal";
|
||||
import {CaptchaModal} from "./modal/CaptchaModal";
|
||||
|
||||
const {Search} = Input;
|
||||
|
||||
|
@@ -12,7 +12,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import * as Setting from "./Setting";
|
||||
import * as Setting from "../Setting";
|
||||
import i18next from "i18next";
|
||||
|
||||
export function sendTestEmail(provider, email) {
|
@@ -12,7 +12,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import * as Setting from "./Setting";
|
||||
import * as Setting from "../Setting";
|
||||
import i18next from "i18next";
|
||||
|
||||
export function sendTestSms(provider, phone) {
|
126
web/src/common/modal/AgreementModal.js
Normal file
126
web/src/common/modal/AgreementModal.js
Normal file
@@ -0,0 +1,126 @@
|
||||
// Copyright 2023 The Casdoor Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import {Checkbox, Form, Modal} from "antd";
|
||||
import i18next from "i18next";
|
||||
import React, {useEffect, useState} from "react";
|
||||
|
||||
export const AgreementModal = (props) => {
|
||||
const {open, onOk, onCancel, application} = props;
|
||||
const [doc, setDoc] = useState("");
|
||||
|
||||
useEffect(() => {
|
||||
getTermsOfUseContent(application.termsOfUseUrl).then((data) => {
|
||||
setDoc(data);
|
||||
});
|
||||
}, []);
|
||||
|
||||
return (
|
||||
|
||||
<Modal
|
||||
title={i18next.t("signup:Terms of Use")}
|
||||
open={open}
|
||||
width={"55vw"}
|
||||
closable={false}
|
||||
okText={i18next.t("signup:Accept")}
|
||||
cancelText={i18next.t("signup:Decline")}
|
||||
onOk={onOk}
|
||||
onCancel={onCancel}
|
||||
>
|
||||
<iframe title={"terms"} style={{border: 0, width: "100%", height: "60vh"}} srcDoc={doc} />
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
||||
function getTermsOfUseContent(url) {
|
||||
return fetch(url, {
|
||||
method: "GET",
|
||||
}).then(r => r.text());
|
||||
}
|
||||
|
||||
export function isAgreementRequired(application) {
|
||||
if (application) {
|
||||
const agreementItem = application.signupItems.find(item => item.name === "Agreement");
|
||||
if (!agreementItem || agreementItem.rule === "None" || !agreementItem.rule) {
|
||||
return false;
|
||||
}
|
||||
if (agreementItem.required) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function initDefaultValue(application) {
|
||||
const agreementItem = application.signupItems.find(item => item.name === "Agreement");
|
||||
|
||||
return isAgreementRequired(application) && agreementItem.rule === "Signin (Default True)";
|
||||
}
|
||||
|
||||
export function renderAgreementFormItem(application, required, layout, ths) {
|
||||
return (<React.Fragment>
|
||||
<Form.Item
|
||||
name="agreement"
|
||||
key="agreement"
|
||||
valuePropName="checked"
|
||||
rules={[
|
||||
{
|
||||
required: required,
|
||||
},
|
||||
() => ({
|
||||
validator: (_, value) => {
|
||||
if (!required) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
if (!value) {
|
||||
return Promise.reject(i18next.t("signup:Please accept the agreement!"));
|
||||
} else {
|
||||
return Promise.resolve();
|
||||
}
|
||||
},
|
||||
}),
|
||||
]
|
||||
}
|
||||
{...layout}
|
||||
initialValue={initDefaultValue(application)}
|
||||
>
|
||||
<Checkbox style={{float: "left"}}>
|
||||
{i18next.t("signup:Accept")}
|
||||
<a onClick={() => {
|
||||
ths.setState({
|
||||
isTermsOfUseVisible: true,
|
||||
});
|
||||
}}
|
||||
>
|
||||
{i18next.t("signup:Terms of Use")}
|
||||
</a>
|
||||
</Checkbox>
|
||||
</Form.Item>
|
||||
<AgreementModal application={application} layout={layout} open={ths.state.isTermsOfUseVisible}
|
||||
onOk={() => {
|
||||
ths.form.current.setFieldsValue({agreement: true});
|
||||
ths.setState({
|
||||
isTermsOfUseVisible: false,
|
||||
});
|
||||
}}
|
||||
onCancel={() => {
|
||||
ths.form.current.setFieldsValue({agreement: false});
|
||||
ths.setState({
|
||||
isTermsOfUseVisible: false,
|
||||
});
|
||||
}} />
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
@@ -15,8 +15,8 @@
|
||||
import {Button, Col, Input, Modal, Row} from "antd";
|
||||
import i18next from "i18next";
|
||||
import React, {useEffect} from "react";
|
||||
import * as UserBackend from "../backend/UserBackend";
|
||||
import {CaptchaWidget} from "./CaptchaWidget";
|
||||
import * as UserBackend from "../../backend/UserBackend";
|
||||
import {CaptchaWidget} from "../CaptchaWidget";
|
||||
import {SafetyOutlined} from "@ant-design/icons";
|
||||
|
||||
export const CaptchaModal = (props) => {
|
@@ -15,12 +15,12 @@
|
||||
import React, {useEffect, useState} from "react";
|
||||
import Cropper from "react-cropper";
|
||||
import "cropperjs/dist/cropper.css";
|
||||
import * as Setting from "./Setting";
|
||||
import * as Setting from "../../Setting";
|
||||
import {Button, Col, Modal, Row, Select} from "antd";
|
||||
import i18next from "i18next";
|
||||
import * as ResourceBackend from "./backend/ResourceBackend";
|
||||
import * as ResourceBackend from "../../backend/ResourceBackend";
|
||||
|
||||
export const CropperDiv = (props) => {
|
||||
export const CropperDivModal = (props) => {
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [options, setOptions] = useState([]);
|
||||
const [image, setImage] = useState("");
|
||||
@@ -60,7 +60,7 @@ export const CropperDiv = (props) => {
|
||||
// Setting.showMessage("success", "uploading...");
|
||||
const extension = image.substring(image.indexOf("/") + 1, image.indexOf(";base64"));
|
||||
const fullFilePath = `avatar/${user.owner}/${user.name}.${extension}`;
|
||||
ResourceBackend.uploadResource(user.owner, user.name, "avatar", "CropperDiv", fullFilePath, blob)
|
||||
ResourceBackend.uploadResource(user.owner, user.name, "avatar", "CropperDivModal", fullFilePath, blob)
|
||||
.then((res) => {
|
||||
if (res.status === "ok") {
|
||||
window.location.href = window.location.pathname;
|
||||
@@ -187,4 +187,4 @@ export const CropperDiv = (props) => {
|
||||
);
|
||||
};
|
||||
|
||||
export default CropperDiv;
|
||||
export default CropperDivModal;
|
@@ -15,8 +15,8 @@
|
||||
import {Button, Col, Input, Modal, Row} from "antd";
|
||||
import i18next from "i18next";
|
||||
import React from "react";
|
||||
import * as UserBackend from "./backend/UserBackend";
|
||||
import * as Setting from "./Setting";
|
||||
import * as UserBackend from "../../backend/UserBackend";
|
||||
import * as Setting from "../../Setting";
|
||||
|
||||
export const PasswordModal = (props) => {
|
||||
const [visible, setVisible] = React.useState(false);
|
@@ -15,9 +15,9 @@
|
||||
import {Button, Col, Input, Modal, Row} from "antd";
|
||||
import i18next from "i18next";
|
||||
import React from "react";
|
||||
import * as Setting from "./Setting";
|
||||
import * as UserBackend from "./backend/UserBackend";
|
||||
import {SendCodeInput} from "./common/SendCodeInput";
|
||||
import * as Setting from "../../Setting";
|
||||
import * as UserBackend from "../../backend/UserBackend";
|
||||
import {SendCodeInput} from "../SendCodeInput";
|
||||
import {MailOutlined, PhoneOutlined} from "@ant-design/icons";
|
||||
|
||||
export const ResetModal = (props) => {
|
@@ -1,119 +1,119 @@
|
||||
// Copyright 2021 The Casdoor Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import React from "react";
|
||||
import {Cascader, Col, Input, Row, Select} from "antd";
|
||||
import i18next from "i18next";
|
||||
import * as UserBackend from "../backend/UserBackend";
|
||||
import * as Setting from "../Setting";
|
||||
|
||||
class AffiliationSelect extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
classes: props,
|
||||
addressOptions: [],
|
||||
affiliationOptions: [],
|
||||
};
|
||||
}
|
||||
|
||||
UNSAFE_componentWillMount() {
|
||||
this.getAddressOptions(this.props.application);
|
||||
this.getAffiliationOptions(this.props.application, this.props.user);
|
||||
}
|
||||
|
||||
getAddressOptions(application) {
|
||||
if (application.affiliationUrl === "") {
|
||||
return;
|
||||
}
|
||||
|
||||
const addressUrl = application.affiliationUrl.split("|")[0];
|
||||
UserBackend.getAddressOptions(addressUrl)
|
||||
.then((addressOptions) => {
|
||||
this.setState({
|
||||
addressOptions: addressOptions,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
getAffiliationOptions(application, user) {
|
||||
if (application.affiliationUrl === "") {
|
||||
return;
|
||||
}
|
||||
|
||||
const affiliationUrl = application.affiliationUrl.split("|")[1];
|
||||
const code = user.address[user.address.length - 1];
|
||||
UserBackend.getAffiliationOptions(affiliationUrl, code)
|
||||
.then((affiliationOptions) => {
|
||||
this.setState({
|
||||
affiliationOptions: affiliationOptions,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
updateUserField(key, value) {
|
||||
this.props.onUpdateUserField(key, value);
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<React.Fragment>
|
||||
{
|
||||
this.props.application?.affiliationUrl === "" ? null : (
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={this.props.labelSpan}>
|
||||
{Setting.getLabel(i18next.t("user:Address"), i18next.t("user:Address - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={24 - this.props.labelSpan} >
|
||||
<Cascader style={{width: "100%", maxWidth: "400px"}} value={this.props.user.address} options={this.state.addressOptions} onChange={value => {
|
||||
this.updateUserField("address", value);
|
||||
this.updateUserField("affiliation", "");
|
||||
this.updateUserField("score", 0);
|
||||
this.getAffiliationOptions(this.props.application, this.props.user);
|
||||
}} placeholder={i18next.t("signup:Please input your address!")} />
|
||||
</Col>
|
||||
</Row>
|
||||
)
|
||||
}
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={this.props.labelSpan}>
|
||||
{Setting.getLabel(i18next.t("user:Affiliation"), i18next.t("user:Affiliation - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
{
|
||||
this.props.application?.affiliationUrl === "" ? (
|
||||
<Input value={this.props.user.affiliation} onChange={e => {
|
||||
this.updateUserField("affiliation", e.target.value);
|
||||
}} />
|
||||
) : (
|
||||
<Select virtual={false} style={{width: "100%"}} value={this.props.user.affiliation}
|
||||
onChange={(value => {
|
||||
const name = value;
|
||||
const affiliationOption = Setting.getArrayItem(this.state.affiliationOptions, "name", name);
|
||||
const id = affiliationOption.id;
|
||||
this.updateUserField("affiliation", name);
|
||||
this.updateUserField("score", id);
|
||||
})}
|
||||
options={[Setting.getOption(`(${i18next.t("general:empty")})`, "")].concat(this.state.affiliationOptions.map((affiliationOption) => Setting.getOption(affiliationOption.name, affiliationOption.name))
|
||||
)} />
|
||||
)
|
||||
}
|
||||
</Col>
|
||||
</Row>
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default AffiliationSelect;
|
||||
// Copyright 2021 The Casdoor Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import React from "react";
|
||||
import {Cascader, Col, Input, Row, Select} from "antd";
|
||||
import i18next from "i18next";
|
||||
import * as UserBackend from "../../backend/UserBackend";
|
||||
import * as Setting from "../../Setting";
|
||||
|
||||
class AffiliationSelect extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
classes: props,
|
||||
addressOptions: [],
|
||||
affiliationOptions: [],
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.getAddressOptions(this.props.application);
|
||||
this.getAffiliationOptions(this.props.application, this.props.user);
|
||||
}
|
||||
|
||||
getAddressOptions(application) {
|
||||
if (application.affiliationUrl === "") {
|
||||
return;
|
||||
}
|
||||
|
||||
const addressUrl = application.affiliationUrl.split("|")[0];
|
||||
UserBackend.getAddressOptions(addressUrl)
|
||||
.then((addressOptions) => {
|
||||
this.setState({
|
||||
addressOptions: addressOptions,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
getAffiliationOptions(application, user) {
|
||||
if (application.affiliationUrl === "") {
|
||||
return;
|
||||
}
|
||||
|
||||
const affiliationUrl = application.affiliationUrl.split("|")[1];
|
||||
const code = user.address[user.address.length - 1];
|
||||
UserBackend.getAffiliationOptions(affiliationUrl, code)
|
||||
.then((affiliationOptions) => {
|
||||
this.setState({
|
||||
affiliationOptions: affiliationOptions,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
updateUserField(key, value) {
|
||||
this.props.onUpdateUserField(key, value);
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<React.Fragment>
|
||||
{
|
||||
this.props.application?.affiliationUrl === "" ? null : (
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={this.props.labelSpan}>
|
||||
{Setting.getLabel(i18next.t("user:Address"), i18next.t("user:Address - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={24 - this.props.labelSpan} >
|
||||
<Cascader style={{width: "100%", maxWidth: "400px"}} value={this.props.user.address} options={this.state.addressOptions} onChange={value => {
|
||||
this.updateUserField("address", value);
|
||||
this.updateUserField("affiliation", "");
|
||||
this.updateUserField("score", 0);
|
||||
this.getAffiliationOptions(this.props.application, this.props.user);
|
||||
}} placeholder={i18next.t("signup:Please input your address!")} />
|
||||
</Col>
|
||||
</Row>
|
||||
)
|
||||
}
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={this.props.labelSpan}>
|
||||
{Setting.getLabel(i18next.t("user:Affiliation"), i18next.t("user:Affiliation - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
{
|
||||
this.props.application?.affiliationUrl === "" ? (
|
||||
<Input value={this.props.user.affiliation} onChange={e => {
|
||||
this.updateUserField("affiliation", e.target.value);
|
||||
}} />
|
||||
) : (
|
||||
<Select virtual={false} style={{width: "100%"}} value={this.props.user.affiliation}
|
||||
onChange={(value => {
|
||||
const name = value;
|
||||
const affiliationOption = Setting.getArrayItem(this.state.affiliationOptions, "name", name);
|
||||
const id = affiliationOption.id;
|
||||
this.updateUserField("affiliation", name);
|
||||
this.updateUserField("score", id);
|
||||
})}
|
||||
options={[Setting.getOption(`(${i18next.t("general:empty")})`, "")].concat(this.state.affiliationOptions.map((affiliationOption) => Setting.getOption(affiliationOption.name, affiliationOption.name))
|
||||
)} />
|
||||
)
|
||||
}
|
||||
</Col>
|
||||
</Row>
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default AffiliationSelect;
|
@@ -13,7 +13,7 @@
|
||||
// limitations under the License.
|
||||
|
||||
import {Select} from "antd";
|
||||
import * as Setting from "../Setting";
|
||||
import * as Setting from "../../Setting";
|
||||
import React from "react";
|
||||
|
||||
export const CountryCodeSelect = (props) => {
|
@@ -13,9 +13,9 @@
|
||||
// limitations under the License.
|
||||
|
||||
import React from "react";
|
||||
import * as Setting from "./Setting";
|
||||
import * as Setting from "../../Setting";
|
||||
import {Dropdown} from "antd";
|
||||
import "./App.less";
|
||||
import "../../App.less";
|
||||
import {GlobalOutlined} from "@ant-design/icons";
|
||||
|
||||
function flagIcon(country, alt) {
|
||||
@@ -24,7 +24,7 @@ function flagIcon(country, alt) {
|
||||
);
|
||||
}
|
||||
|
||||
class SelectLanguageBox extends React.Component {
|
||||
class LanguageSelect extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
@@ -63,4 +63,4 @@ class SelectLanguageBox extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
export default SelectLanguageBox;
|
||||
export default LanguageSelect;
|
@@ -13,12 +13,12 @@
|
||||
// limitations under the License.
|
||||
|
||||
import React from "react";
|
||||
import * as Setting from "./Setting";
|
||||
import * as Setting from "../../Setting";
|
||||
import {Select} from "antd";
|
||||
|
||||
const {Option} = Select;
|
||||
|
||||
class SelectRegionBox extends React.Component {
|
||||
class RegionSelect extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
@@ -59,4 +59,4 @@ class SelectRegionBox extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
export default SelectRegionBox;
|
||||
export default RegionSelect;
|
@@ -13,9 +13,9 @@
|
||||
// limitations under the License.
|
||||
|
||||
import React from "react";
|
||||
import * as Setting from "./Setting";
|
||||
import * as Setting from "../../Setting";
|
||||
import {Dropdown} from "antd";
|
||||
import "./App.less";
|
||||
import "../../App.less";
|
||||
import i18next from "i18next";
|
||||
import {CheckOutlined} from "@ant-design/icons";
|
||||
import {CompactTheme, DarkTheme, Light} from "antd-token-previewer/es/icons";
|
||||
@@ -34,7 +34,7 @@ function getIcon(themeKey) {
|
||||
}
|
||||
}
|
||||
|
||||
class SelectThemeBox extends React.Component {
|
||||
class ThemeSelect extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
}
|
||||
@@ -91,4 +91,4 @@ class SelectThemeBox extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
export default SelectThemeBox;
|
||||
export default ThemeSelect;
|
@@ -41,6 +41,7 @@
|
||||
"Enable signup - Tooltip": "Ob Benutzern erlaubt werden soll, ein neues Konto zu registrieren",
|
||||
"Failed to sign in": "Fehler bei der Anmeldung",
|
||||
"File uploaded successfully": "Datei erfolgreich hochgeladen",
|
||||
"First, last": "First, last",
|
||||
"Follow organization theme": "Folge dem Thema der Organisation",
|
||||
"Form CSS": "Formular CSS",
|
||||
"Form CSS - Edit": "Formular CSS - Bearbeiten",
|
||||
@@ -49,15 +50,21 @@
|
||||
"Form position - Tooltip": "Ort der Anmelde-, Anmelde- und Passwort vergessen-Formulare",
|
||||
"Grant types": "Grant-Typen",
|
||||
"Grant types - Tooltip": "Wählen Sie aus, welche Förderarten im OAuth-Protokoll zulässig sind",
|
||||
"Incremental": "Incremental",
|
||||
"Left": "Links",
|
||||
"Logged in successfully": "Erfolgreich eingeloggt",
|
||||
"Logged out successfully": "Erfolgreich ausgeloggt",
|
||||
"New Application": "Neue Anwendung",
|
||||
"No verification": "No verification",
|
||||
"None": "kein",
|
||||
"Normal": "Normal",
|
||||
"Only signup": "Only signup",
|
||||
"Please input your application!": "Bitte geben Sie Ihre Bewerbung ein!",
|
||||
"Please input your organization!": "Bitte geben Sie Ihre Organisation ein!",
|
||||
"Please select a HTML file": "Bitte wählen Sie eine HTML-Datei aus",
|
||||
"Prompt page URL copied to clipboard successfully, please paste it into the incognito window or another browser": "Die URL der Seite wurde erfolgreich in die Zwischenablage kopiert. Bitte fügen Sie sie in das Inkognito-Fenster oder einen anderen Browser ein",
|
||||
"Random": "Random",
|
||||
"Real name": "Real name",
|
||||
"Redirect URL": "Weiterleitungs-URL",
|
||||
"Redirect URL (Assertion Consumer Service POST Binding URL) - Tooltip": "Weiterleitungs-URL (Assertion Consumer Service POST Binding URL)",
|
||||
"Redirect URLs": "Weiterleitungs-URLs",
|
||||
@@ -74,6 +81,8 @@
|
||||
"Side panel HTML - Edit": "Seitenleisten HTML - Bearbeiten",
|
||||
"Side panel HTML - Tooltip": "Passen Sie den HTML-Code für das Seitenfeld der Login-Seite an",
|
||||
"Sign Up Error": "Registrierungsfehler",
|
||||
"Signin": "Signin",
|
||||
"Signin (Default True)": "Signin (Default True)",
|
||||
"Signin page URL copied to clipboard successfully, please paste it into the incognito window or another browser": "Die URL der Anmeldeseite wurde erfolgreich in die Zwischenablage kopiert. Bitte fügen Sie sie in das Inkognito-Fenster oder einen anderen Browser ein",
|
||||
"Signin session": "Anmeldesitzung",
|
||||
"Signup items": "Anmeldungsartikel",
|
||||
@@ -504,6 +513,8 @@
|
||||
"Host - Tooltip": "Name des Gastgebers",
|
||||
"IdP": "IdP",
|
||||
"IdP certificate": "IdP-Zertifikat",
|
||||
"Intelligent Validation": "Intelligent Validation",
|
||||
"Internal": "Internal",
|
||||
"Issuer URL": "Emittenten-URL",
|
||||
"Issuer URL - Tooltip": "Emittenten-URL",
|
||||
"Link copied to clipboard successfully": "Link wurde erfolgreich in die Zwischenablage kopiert",
|
||||
@@ -511,6 +522,7 @@
|
||||
"Metadata - Tooltip": "SAML-Metadaten",
|
||||
"Method - Tooltip": "Anmeldeverfahren, QR-Code oder geräuschloser Login",
|
||||
"New Provider": "Neuer Anbieter",
|
||||
"Normal": "Normal",
|
||||
"Parse": "parsen",
|
||||
"Parse metadata successfully": "Metadaten erfolgreich analysiert",
|
||||
"Path prefix": "Pfadpräfix",
|
||||
@@ -555,8 +567,10 @@
|
||||
"Signup HTML": "Anmeldung HTML",
|
||||
"Signup HTML - Edit": "Registrierung HTML - Bearbeiten",
|
||||
"Signup HTML - Tooltip": "Benutzerdefiniertes HTML zur Ersetzung des Standard-Anmelde-Seitenstils",
|
||||
"Silent": "Silent",
|
||||
"Site key": "Seitenschlüssel",
|
||||
"Site key - Tooltip": "Site-Schlüssel",
|
||||
"Sliding Validation": "Sliding Validation",
|
||||
"Sub type": "Untertyp",
|
||||
"Sub type - Tooltip": "Unterart",
|
||||
"Template code": "Vorlagen-Code",
|
||||
@@ -564,6 +578,7 @@
|
||||
"Test Email": "Test E-Mail",
|
||||
"Test Email - Tooltip": "E-Mail-Adresse zum Empfangen von Test-E-Mails",
|
||||
"Test SMTP Connection": "Testen Sie die SMTP-Verbindung",
|
||||
"Third-party": "Third-party",
|
||||
"Token URL": "Token-URL",
|
||||
"Token URL - Tooltip": "Token-URL",
|
||||
"Type": "Typ",
|
||||
@@ -621,6 +636,7 @@
|
||||
"The input is not valid Email!": "Die Eingabe ist keine gültige E-Mail-Adresse!",
|
||||
"The input is not valid Phone!": "Die Eingabe ist kein gültiges Telefon!",
|
||||
"Username": "Benutzername",
|
||||
"Username - Tooltip": "Username - Tooltip",
|
||||
"Your account has been created!": "Ihr Konto wurde erstellt!",
|
||||
"Your confirmed password is inconsistent with the password!": "Dein bestätigtes Passwort stimmt nicht mit dem Passwort überein!",
|
||||
"sign in now": "Jetzt anmelden"
|
||||
|
@@ -41,6 +41,7 @@
|
||||
"Enable signup - Tooltip": "Whether to allow users to register a new account",
|
||||
"Failed to sign in": "Failed to sign in",
|
||||
"File uploaded successfully": "File uploaded successfully",
|
||||
"First, last": "First, last",
|
||||
"Follow organization theme": "Follow organization theme",
|
||||
"Form CSS": "Form CSS",
|
||||
"Form CSS - Edit": "Form CSS - Edit",
|
||||
@@ -49,15 +50,21 @@
|
||||
"Form position - Tooltip": "Location of the signup, signin and forget password forms",
|
||||
"Grant types": "Grant types",
|
||||
"Grant types - Tooltip": "Select which grant types are allowed in the OAuth protocol",
|
||||
"Incremental": "Incremental",
|
||||
"Left": "Left",
|
||||
"Logged in successfully": "Logged in successfully",
|
||||
"Logged out successfully": "Logged out successfully",
|
||||
"New Application": "New Application",
|
||||
"No verification": "No verification",
|
||||
"None": "None",
|
||||
"Normal": "Normal",
|
||||
"Only signup": "Only signup",
|
||||
"Please input your application!": "Please input your application!",
|
||||
"Please input your organization!": "Please input your organization!",
|
||||
"Please select a HTML file": "Please select a HTML file",
|
||||
"Prompt page URL copied to clipboard successfully, please paste it into the incognito window or another browser": "Prompt page URL copied to clipboard successfully, please paste it into the incognito window or another browser",
|
||||
"Random": "Random",
|
||||
"Real name": "Real name",
|
||||
"Redirect URL": "Redirect URL",
|
||||
"Redirect URL (Assertion Consumer Service POST Binding URL) - Tooltip": "Redirect URL (Assertion Consumer Service POST Binding URL)",
|
||||
"Redirect URLs": "Redirect URLs",
|
||||
@@ -74,6 +81,8 @@
|
||||
"Side panel HTML - Edit": "Side panel HTML - Edit",
|
||||
"Side panel HTML - Tooltip": "Customize the HTML code for the side panel of the login page",
|
||||
"Sign Up Error": "Sign Up Error",
|
||||
"Signin": "Signin",
|
||||
"Signin (Default True)": "Signin (Default True)",
|
||||
"Signin page URL copied to clipboard successfully, please paste it into the incognito window or another browser": "Signin page URL copied to clipboard successfully, please paste it into the incognito window or another browser",
|
||||
"Signin session": "Signin session",
|
||||
"Signup items": "Signup items",
|
||||
@@ -504,6 +513,8 @@
|
||||
"Host - Tooltip": "Name of host",
|
||||
"IdP": "IdP",
|
||||
"IdP certificate": "IdP certificate",
|
||||
"Intelligent Validation": "Intelligent Validation",
|
||||
"Internal": "Internal",
|
||||
"Issuer URL": "Issuer URL",
|
||||
"Issuer URL - Tooltip": "Issuer URL",
|
||||
"Link copied to clipboard successfully": "Link copied to clipboard successfully",
|
||||
@@ -511,6 +522,7 @@
|
||||
"Metadata - Tooltip": "SAML metadata",
|
||||
"Method - Tooltip": "Login method, QR code or silent login",
|
||||
"New Provider": "New Provider",
|
||||
"Normal": "Normal",
|
||||
"Parse": "Parse",
|
||||
"Parse metadata successfully": "Parse metadata successfully",
|
||||
"Path prefix": "Path prefix",
|
||||
@@ -555,8 +567,10 @@
|
||||
"Signup HTML": "Signup HTML",
|
||||
"Signup HTML - Edit": "Signup HTML - Edit",
|
||||
"Signup HTML - Tooltip": "Custom HTML for replacing the default signup page style",
|
||||
"Silent": "Silent",
|
||||
"Site key": "Site key",
|
||||
"Site key - Tooltip": "Site key",
|
||||
"Sliding Validation": "Sliding Validation",
|
||||
"Sub type": "Sub type",
|
||||
"Sub type - Tooltip": "Sub type",
|
||||
"Template code": "Template code",
|
||||
@@ -564,6 +578,7 @@
|
||||
"Test Email": "Test Email",
|
||||
"Test Email - Tooltip": "Email address to receive test mails",
|
||||
"Test SMTP Connection": "Test SMTP Connection",
|
||||
"Third-party": "Third-party",
|
||||
"Token URL": "Token URL",
|
||||
"Token URL - Tooltip": "Token URL",
|
||||
"Type": "Type",
|
||||
@@ -621,6 +636,7 @@
|
||||
"The input is not valid Email!": "The input is not valid Email!",
|
||||
"The input is not valid Phone!": "The input is not valid Phone!",
|
||||
"Username": "Username",
|
||||
"Username - Tooltip": "Username - Tooltip",
|
||||
"Your account has been created!": "Your account has been created!",
|
||||
"Your confirmed password is inconsistent with the password!": "Your confirmed password is inconsistent with the password!",
|
||||
"sign in now": "sign in now"
|
||||
|
@@ -41,6 +41,7 @@
|
||||
"Enable signup - Tooltip": "Ya sea permitir que los usuarios registren una nueva cuenta",
|
||||
"Failed to sign in": "Error al iniciar sesión",
|
||||
"File uploaded successfully": "Archivo subido exitosamente",
|
||||
"First, last": "First, last",
|
||||
"Follow organization theme": "Seguir el tema de la organización",
|
||||
"Form CSS": "Formulario CSS",
|
||||
"Form CSS - Edit": "Formulario CSS - Editar",
|
||||
@@ -49,15 +50,21 @@
|
||||
"Form position - Tooltip": "Ubicación de los formularios de registro, inicio de sesión y olvido de contraseña",
|
||||
"Grant types": "Tipos de subvenciones",
|
||||
"Grant types - Tooltip": "Selecciona cuáles tipos de subvenciones están permitidas en el protocolo OAuth",
|
||||
"Incremental": "Incremental",
|
||||
"Left": "Izquierda",
|
||||
"Logged in successfully": "Acceso satisfactorio",
|
||||
"Logged out successfully": "Cerró sesión exitosamente",
|
||||
"New Application": "Nueva aplicación",
|
||||
"No verification": "No verification",
|
||||
"None": "Ninguno",
|
||||
"Normal": "Normal",
|
||||
"Only signup": "Only signup",
|
||||
"Please input your application!": "¡Por favor, ingrese su solicitud!",
|
||||
"Please input your organization!": "¡Por favor, ingrese su organización!",
|
||||
"Please select a HTML file": "Por favor, seleccione un archivo HTML",
|
||||
"Prompt page URL copied to clipboard successfully, please paste it into the incognito window or another browser": "URL de la página de acceso exitosamente copiada al portapapeles, por favor péguela en la ventana de incógnito o en otro navegador",
|
||||
"Random": "Random",
|
||||
"Real name": "Real name",
|
||||
"Redirect URL": "Redireccionar URL",
|
||||
"Redirect URL (Assertion Consumer Service POST Binding URL) - Tooltip": "URL de redireccionamiento (URL de enlace de publicación del servicio consumidor de afirmaciones)",
|
||||
"Redirect URLs": "Redireccionar URLs",
|
||||
@@ -74,6 +81,8 @@
|
||||
"Side panel HTML - Edit": "Panel lateral HTML - Editar",
|
||||
"Side panel HTML - Tooltip": "Personaliza el código HTML del panel lateral de la página de inicio de sesión",
|
||||
"Sign Up Error": "Error de registro",
|
||||
"Signin": "Signin",
|
||||
"Signin (Default True)": "Signin (Default True)",
|
||||
"Signin page URL copied to clipboard successfully, please paste it into the incognito window or another browser": "La URL de la página de inicio de sesión fue copiada al portapapeles exitosamente, por favor péguela en una ventana de incógnito o en otro navegador",
|
||||
"Signin session": "Sesión de inicio de sesión",
|
||||
"Signup items": "Artículos de registro",
|
||||
@@ -504,6 +513,8 @@
|
||||
"Host - Tooltip": "Nombre del anfitrión",
|
||||
"IdP": "IdP = Proveedor de Identidad",
|
||||
"IdP certificate": "Certificado de proveedor de identidad (IdP)",
|
||||
"Intelligent Validation": "Intelligent Validation",
|
||||
"Internal": "Internal",
|
||||
"Issuer URL": "URL del emisor",
|
||||
"Issuer URL - Tooltip": "URL del emisor",
|
||||
"Link copied to clipboard successfully": "Enlace copiado al portapapeles satisfactoriamente",
|
||||
@@ -511,6 +522,7 @@
|
||||
"Metadata - Tooltip": "Metadatos SAML",
|
||||
"Method - Tooltip": "Método de inicio de sesión, código QR o inicio de sesión silencioso",
|
||||
"New Provider": "Nuevo proveedor",
|
||||
"Normal": "Normal",
|
||||
"Parse": "Analizar",
|
||||
"Parse metadata successfully": "Analizar los metadatos con éxito",
|
||||
"Path prefix": "Prefijo de ruta",
|
||||
@@ -555,8 +567,10 @@
|
||||
"Signup HTML": "Registro HTML",
|
||||
"Signup HTML - Edit": "Registro HTML - Editar",
|
||||
"Signup HTML - Tooltip": "HTML personalizado para reemplazar el estilo predeterminado de la página de registro",
|
||||
"Silent": "Silent",
|
||||
"Site key": "Clave del sitio",
|
||||
"Site key - Tooltip": "Clave del sitio",
|
||||
"Sliding Validation": "Sliding Validation",
|
||||
"Sub type": "Subtipo",
|
||||
"Sub type - Tooltip": "Subtipo",
|
||||
"Template code": "Código de plantilla",
|
||||
@@ -564,6 +578,7 @@
|
||||
"Test Email": "Correo de prueba",
|
||||
"Test Email - Tooltip": "Dirección de correo electrónico para recibir mensajes de prueba",
|
||||
"Test SMTP Connection": "Prueba de conexión SMTP",
|
||||
"Third-party": "Third-party",
|
||||
"Token URL": "Token URL",
|
||||
"Token URL - Tooltip": "URL de token",
|
||||
"Type": "Tipo",
|
||||
@@ -621,6 +636,7 @@
|
||||
"The input is not valid Email!": "¡La entrada no es un correo electrónico válido!",
|
||||
"The input is not valid Phone!": "¡La entrada no es un número de teléfono válido!",
|
||||
"Username": "Nombre de usuario",
|
||||
"Username - Tooltip": "Username - Tooltip",
|
||||
"Your account has been created!": "¡Su cuenta ha sido creada!",
|
||||
"Your confirmed password is inconsistent with the password!": "¡Su contraseña confirmada no es coherente con la contraseña!",
|
||||
"sign in now": "Inicie sesión ahora"
|
||||
|
@@ -41,6 +41,7 @@
|
||||
"Enable signup - Tooltip": "Doit-on autoriser les utilisateurs à créer un nouveau compte ?",
|
||||
"Failed to sign in": "Échec de la connexion",
|
||||
"File uploaded successfully": "Fichier téléchargé avec succès",
|
||||
"First, last": "First, last",
|
||||
"Follow organization theme": "Suivre le thème de l'organisation",
|
||||
"Form CSS": "Formulaire CSS",
|
||||
"Form CSS - Edit": "Form CSS - Modifier",
|
||||
@@ -49,15 +50,21 @@
|
||||
"Form position - Tooltip": "Emplacement des formulaires d'inscription, de connexion et de récupération de mot de passe",
|
||||
"Grant types": "Types de subventions",
|
||||
"Grant types - Tooltip": "Sélectionnez les types d'autorisations autorisés dans le protocole OAuth",
|
||||
"Incremental": "Incremental",
|
||||
"Left": "gauche",
|
||||
"Logged in successfully": "Connecté avec succès",
|
||||
"Logged out successfully": "Déconnecté avec succès",
|
||||
"New Application": "Nouvelle application",
|
||||
"No verification": "No verification",
|
||||
"None": "Aucun",
|
||||
"Normal": "Normal",
|
||||
"Only signup": "Only signup",
|
||||
"Please input your application!": "Veuillez saisir votre demande d'application !",
|
||||
"Please input your organization!": "S'il vous plaît saisir votre organisation !",
|
||||
"Please select a HTML file": "S'il vous plaît sélectionnez un fichier HTML",
|
||||
"Prompt page URL copied to clipboard successfully, please paste it into the incognito window or another browser": "URL de la page rapide copiée avec succès dans le presse-papiers, veuillez la coller dans la fenêtre de navigation privée ou dans un autre navigateur",
|
||||
"Random": "Random",
|
||||
"Real name": "Real name",
|
||||
"Redirect URL": "Rediriger l'URL",
|
||||
"Redirect URL (Assertion Consumer Service POST Binding URL) - Tooltip": "URL de redirection (URL de liaison POST du service consommateur d'assertions)",
|
||||
"Redirect URLs": "Rediriger les URL",
|
||||
@@ -74,6 +81,8 @@
|
||||
"Side panel HTML - Edit": "Panneau latéral HTML - Modifier",
|
||||
"Side panel HTML - Tooltip": "Personnalisez le code HTML du panneau latéral de la page de connexion",
|
||||
"Sign Up Error": "Erreur d'inscription",
|
||||
"Signin": "Signin",
|
||||
"Signin (Default True)": "Signin (Default True)",
|
||||
"Signin page URL copied to clipboard successfully, please paste it into the incognito window or another browser": "L'URL de la page de connexion a été copiée avec succès dans le presse-papiers, veuillez la coller dans la fenêtre de navigation privée ou dans un autre navigateur",
|
||||
"Signin session": "Session de connexion",
|
||||
"Signup items": "Les éléments d'inscription",
|
||||
@@ -504,6 +513,8 @@
|
||||
"Host - Tooltip": "Nom d'hôte",
|
||||
"IdP": "IdP",
|
||||
"IdP certificate": "Certificat IdP",
|
||||
"Intelligent Validation": "Intelligent Validation",
|
||||
"Internal": "Internal",
|
||||
"Issuer URL": "URL de l'émetteur",
|
||||
"Issuer URL - Tooltip": "URL de l'émetteur",
|
||||
"Link copied to clipboard successfully": "Lien copié avec succès dans le presse-papiers",
|
||||
@@ -511,6 +522,7 @@
|
||||
"Metadata - Tooltip": "Métadonnées SAML",
|
||||
"Method - Tooltip": "Méthode de connexion, code QR ou connexion silencieuse",
|
||||
"New Provider": "Nouveau fournisseur",
|
||||
"Normal": "Normal",
|
||||
"Parse": "Parser",
|
||||
"Parse metadata successfully": "Parcourir les métadonnées avec succès",
|
||||
"Path prefix": "Préfixe de chemin",
|
||||
@@ -555,8 +567,10 @@
|
||||
"Signup HTML": "Inscription HTML",
|
||||
"Signup HTML - Edit": "Inscription HTML - éditer",
|
||||
"Signup HTML - Tooltip": "HTML personnalisé pour remplacer le style par défaut de la page d'inscription",
|
||||
"Silent": "Silent",
|
||||
"Site key": "Clé de site",
|
||||
"Site key - Tooltip": "Clé de site",
|
||||
"Sliding Validation": "Sliding Validation",
|
||||
"Sub type": "Sous-type",
|
||||
"Sub type - Tooltip": "Sous-type",
|
||||
"Template code": "Code modèle",
|
||||
@@ -564,6 +578,7 @@
|
||||
"Test Email": "Courriel de test",
|
||||
"Test Email - Tooltip": "Adresse e-mail pour recevoir des courriels de test",
|
||||
"Test SMTP Connection": "Test de connexion SMTP",
|
||||
"Third-party": "Third-party",
|
||||
"Token URL": "URL de jeton",
|
||||
"Token URL - Tooltip": "URL de jeton",
|
||||
"Type": "Type",
|
||||
@@ -621,6 +636,7 @@
|
||||
"The input is not valid Email!": "L'entrée n'est pas un e-mail valide !",
|
||||
"The input is not valid Phone!": "L'entrée n'est pas un numéro de téléphone valide !",
|
||||
"Username": "Nom d'utilisateur",
|
||||
"Username - Tooltip": "Username - Tooltip",
|
||||
"Your account has been created!": "Votre compte a été créé !",
|
||||
"Your confirmed password is inconsistent with the password!": "Votre mot de passe confirmé est incompatible avec le mot de passe !",
|
||||
"sign in now": "Connectez-vous maintenant"
|
||||
|
@@ -41,6 +41,7 @@
|
||||
"Enable signup - Tooltip": "Apakah akan mengizinkan pengguna untuk mendaftar akun baru",
|
||||
"Failed to sign in": "Gagal masuk",
|
||||
"File uploaded successfully": "Berkas telah diunggah dengan sukses",
|
||||
"First, last": "First, last",
|
||||
"Follow organization theme": "Ikuti tema organisasi",
|
||||
"Form CSS": "Formulir CSS",
|
||||
"Form CSS - Edit": "Formulir CSS - Edit",
|
||||
@@ -49,15 +50,21 @@
|
||||
"Form position - Tooltip": "Tempat pendaftaran, masuk, dan lupa kata sandi",
|
||||
"Grant types": "Jenis-jenis hibah",
|
||||
"Grant types - Tooltip": "Pilih jenis hibah apa yang diperbolehkan dalam protokol OAuth",
|
||||
"Incremental": "Incremental",
|
||||
"Left": "Kiri",
|
||||
"Logged in successfully": "Berhasil masuk",
|
||||
"Logged out successfully": "Berhasil keluar dari sistem",
|
||||
"New Application": "Aplikasi Baru",
|
||||
"No verification": "No verification",
|
||||
"None": "Tidak ada",
|
||||
"Normal": "Normal",
|
||||
"Only signup": "Only signup",
|
||||
"Please input your application!": "Silakan masukkan aplikasi Anda!",
|
||||
"Please input your organization!": "Silakan masukkan organisasi Anda!",
|
||||
"Please select a HTML file": "Silahkan pilih file HTML",
|
||||
"Prompt page URL copied to clipboard successfully, please paste it into the incognito window or another browser": "Tautan halaman Prompt berhasil disalin ke papan klip, silakan tempelkan ke jendela penyamaran atau browser lainnya",
|
||||
"Random": "Random",
|
||||
"Real name": "Real name",
|
||||
"Redirect URL": "Mengalihkan URL",
|
||||
"Redirect URL (Assertion Consumer Service POST Binding URL) - Tooltip": "URL pengalihan (Penyanggah Konsumen Layanan Ikatan POST URL)",
|
||||
"Redirect URLs": "Mengarahkan URL",
|
||||
@@ -74,6 +81,8 @@
|
||||
"Side panel HTML - Edit": "Panel sisi HTML - Sunting",
|
||||
"Side panel HTML - Tooltip": "Menyesuaikan kode HTML untuk panel samping halaman login",
|
||||
"Sign Up Error": "Kesalahan Pendaftaran",
|
||||
"Signin": "Signin",
|
||||
"Signin (Default True)": "Signin (Default True)",
|
||||
"Signin page URL copied to clipboard successfully, please paste it into the incognito window or another browser": "URL halaman masuk berhasil disalin ke clipboard, silakan tempelkan di jendela penyamaran atau browser lainnya",
|
||||
"Signin session": "Sesi masuk",
|
||||
"Signup items": "Item pendaftaran",
|
||||
@@ -504,6 +513,8 @@
|
||||
"Host - Tooltip": "Nama tuan rumah",
|
||||
"IdP": "IdP",
|
||||
"IdP certificate": "Sertifikat IdP",
|
||||
"Intelligent Validation": "Intelligent Validation",
|
||||
"Internal": "Internal",
|
||||
"Issuer URL": "URL penerbit",
|
||||
"Issuer URL - Tooltip": "URL Penerbit",
|
||||
"Link copied to clipboard successfully": "Tautan berhasil disalin ke papan klip",
|
||||
@@ -511,6 +522,7 @@
|
||||
"Metadata - Tooltip": "Metadata SAML",
|
||||
"Method - Tooltip": "Metode login, kode QR atau login tanpa suara",
|
||||
"New Provider": "Penyedia Baru",
|
||||
"Normal": "Normal",
|
||||
"Parse": "Parse: Memecah atau mengurai data atau teks menjadi bagian-bagian yang lebih kecil dan lebih mudah dipahami atau dimanipulasi",
|
||||
"Parse metadata successfully": "Berhasil mem-parse metadata",
|
||||
"Path prefix": "Awalan jalur",
|
||||
@@ -555,8 +567,10 @@
|
||||
"Signup HTML": "Pendaftaran HTML",
|
||||
"Signup HTML - Edit": "Pendaftaran HTML - Sunting",
|
||||
"Signup HTML - Tooltip": "HTML khusus untuk mengganti gaya halaman pendaftaran bawaan",
|
||||
"Silent": "Silent",
|
||||
"Site key": "Kunci situs",
|
||||
"Site key - Tooltip": "Kunci situs atau kunci halaman web",
|
||||
"Sliding Validation": "Sliding Validation",
|
||||
"Sub type": "Sub jenis",
|
||||
"Sub type - Tooltip": "Sub jenis",
|
||||
"Template code": "Kode template",
|
||||
@@ -564,6 +578,7 @@
|
||||
"Test Email": "Email Uji Coba",
|
||||
"Test Email - Tooltip": "Alamat email untuk menerima email percobaan",
|
||||
"Test SMTP Connection": "Tes Koneksi SMTP",
|
||||
"Third-party": "Third-party",
|
||||
"Token URL": "Token URL: Tautan Token",
|
||||
"Token URL - Tooltip": "Token URL: URL Token",
|
||||
"Type": "Jenis",
|
||||
@@ -621,6 +636,7 @@
|
||||
"The input is not valid Email!": "Input yang dimasukkan bukan sesuai dengan format Email yang valid!",
|
||||
"The input is not valid Phone!": "Masukan ponsel tidak valid!",
|
||||
"Username": "Nama pengguna",
|
||||
"Username - Tooltip": "Username - Tooltip",
|
||||
"Your account has been created!": "Akun Anda telah dibuat!",
|
||||
"Your confirmed password is inconsistent with the password!": "Kata sandi yang dikonfirmasi tidak konsisten dengan kata sandi!",
|
||||
"sign in now": "Masuk sekarang"
|
||||
|
@@ -41,6 +41,7 @@
|
||||
"Enable signup - Tooltip": "新しいアカウントの登録をユーザーに許可するかどうか",
|
||||
"Failed to sign in": "ログインに失敗しました",
|
||||
"File uploaded successfully": "ファイルが正常にアップロードされました",
|
||||
"First, last": "First, last",
|
||||
"Follow organization theme": "組織のテーマに従ってください",
|
||||
"Form CSS": "フォームCSS",
|
||||
"Form CSS - Edit": "フォームのCSS - 編集",
|
||||
@@ -49,15 +50,21 @@
|
||||
"Form position - Tooltip": "登録、ログイン、パスワード忘れフォームの位置",
|
||||
"Grant types": "グラント種類",
|
||||
"Grant types - Tooltip": "OAuthプロトコルで許可されているグラントタイプを選択してください",
|
||||
"Incremental": "Incremental",
|
||||
"Left": "左",
|
||||
"Logged in successfully": "正常にログインしました",
|
||||
"Logged out successfully": "正常にログアウトしました",
|
||||
"New Application": "新しいアプリケーション",
|
||||
"No verification": "No verification",
|
||||
"None": "なし",
|
||||
"Normal": "Normal",
|
||||
"Only signup": "Only signup",
|
||||
"Please input your application!": "あなたの申請を入力してください!",
|
||||
"Please input your organization!": "あなたの組織を入力してください!",
|
||||
"Please select a HTML file": "HTMLファイルを選択してください",
|
||||
"Prompt page URL copied to clipboard successfully, please paste it into the incognito window or another browser": "プロンプトページのURLが正常にクリップボードにコピーされました。インコグニートウィンドウまたは別のブラウザに貼り付けてください",
|
||||
"Random": "Random",
|
||||
"Real name": "Real name",
|
||||
"Redirect URL": "リダイレクトURL",
|
||||
"Redirect URL (Assertion Consumer Service POST Binding URL) - Tooltip": "リダイレクトURL(アサーションコンシューマサービスPOSTバインディングURL)",
|
||||
"Redirect URLs": "リダイレクトURL",
|
||||
@@ -74,6 +81,8 @@
|
||||
"Side panel HTML - Edit": "サイドパネルのHTML - 編集",
|
||||
"Side panel HTML - Tooltip": "ログインページのサイドパネルに対するHTMLコードをカスタマイズしてください",
|
||||
"Sign Up Error": "サインアップエラー",
|
||||
"Signin": "Signin",
|
||||
"Signin (Default True)": "Signin (Default True)",
|
||||
"Signin page URL copied to clipboard successfully, please paste it into the incognito window or another browser": "サインインページのURLがクリップボードに正常にコピーされました。インコグニートウィンドウまたは別のブラウザに貼り付けてください",
|
||||
"Signin session": "サインインセッション",
|
||||
"Signup items": "サインアップアイテム",
|
||||
@@ -504,6 +513,8 @@
|
||||
"Host - Tooltip": "ホストの名前",
|
||||
"IdP": "IdP",
|
||||
"IdP certificate": "IdP証明書",
|
||||
"Intelligent Validation": "Intelligent Validation",
|
||||
"Internal": "Internal",
|
||||
"Issuer URL": "発行者のURL",
|
||||
"Issuer URL - Tooltip": "発行者URL",
|
||||
"Link copied to clipboard successfully": "リンクがクリップボードに正常にコピーされました",
|
||||
@@ -511,6 +522,7 @@
|
||||
"Metadata - Tooltip": "SAMLのメタデータ",
|
||||
"Method - Tooltip": "ログイン方法、QRコードまたはサイレントログイン",
|
||||
"New Provider": "新しい提供者",
|
||||
"Normal": "Normal",
|
||||
"Parse": "パースする",
|
||||
"Parse metadata successfully": "メタデータを正常に解析しました",
|
||||
"Path prefix": "パスプレフィックス",
|
||||
@@ -555,8 +567,10 @@
|
||||
"Signup HTML": "サインアップ HTML",
|
||||
"Signup HTML - Edit": "サインアップ HTML - 編集",
|
||||
"Signup HTML - Tooltip": "デフォルトのサインアップページスタイルを置き換えるためのカスタムHTML",
|
||||
"Silent": "Silent",
|
||||
"Site key": "サイトキー",
|
||||
"Site key - Tooltip": "サイトキー",
|
||||
"Sliding Validation": "Sliding Validation",
|
||||
"Sub type": "サブタイプ",
|
||||
"Sub type - Tooltip": "サブタイプ",
|
||||
"Template code": "テンプレートコード",
|
||||
@@ -564,6 +578,7 @@
|
||||
"Test Email": "テストメール",
|
||||
"Test Email - Tooltip": "テストメールを受け取るためのメールアドレス",
|
||||
"Test SMTP Connection": "SMTP接続をテストする",
|
||||
"Third-party": "Third-party",
|
||||
"Token URL": "トークンのURL",
|
||||
"Token URL - Tooltip": "トークンURL",
|
||||
"Type": "タイプ",
|
||||
@@ -621,6 +636,7 @@
|
||||
"The input is not valid Email!": "入力されたものは有効なメールではありません",
|
||||
"The input is not valid Phone!": "この入力は有効な電話番号ではありません!",
|
||||
"Username": "ユーザー名",
|
||||
"Username - Tooltip": "Username - Tooltip",
|
||||
"Your account has been created!": "あなたのアカウントが作成されました!",
|
||||
"Your confirmed password is inconsistent with the password!": "確認されたパスワードは、パスワードと矛盾しています!",
|
||||
"sign in now": "今すぐサインインしてください"
|
||||
|
@@ -41,6 +41,7 @@
|
||||
"Enable signup - Tooltip": "사용자가 새로운 계정을 등록할지 여부",
|
||||
"Failed to sign in": "로그인 실패했습니다",
|
||||
"File uploaded successfully": "파일이 성공적으로 업로드되었습니다",
|
||||
"First, last": "First, last",
|
||||
"Follow organization theme": "조직의 주제를 따르세요",
|
||||
"Form CSS": "CSS 양식",
|
||||
"Form CSS - Edit": "폼 CSS - 편집",
|
||||
@@ -49,15 +50,21 @@
|
||||
"Form position - Tooltip": "가입, 로그인 및 비밀번호 재설정 양식의 위치",
|
||||
"Grant types": "Grant types: 부여 유형",
|
||||
"Grant types - Tooltip": "OAuth 프로토콜에서 허용되는 그란트 유형을 선택하십시오",
|
||||
"Incremental": "Incremental",
|
||||
"Left": "왼쪽",
|
||||
"Logged in successfully": "성공적으로 로그인했습니다",
|
||||
"Logged out successfully": "로그아웃이 성공적으로 되었습니다",
|
||||
"New Application": "새로운 응용 프로그램",
|
||||
"No verification": "No verification",
|
||||
"None": "없음",
|
||||
"Normal": "Normal",
|
||||
"Only signup": "Only signup",
|
||||
"Please input your application!": "당신의 신청서를 입력해주세요!",
|
||||
"Please input your organization!": "귀하의 조직을 입력해 주세요!",
|
||||
"Please select a HTML file": "HTML 파일을 선택해 주세요",
|
||||
"Prompt page URL copied to clipboard successfully, please paste it into the incognito window or another browser": "프롬프트 페이지 URL이 클립 보드에 성공적으로 복사되었습니다. 시크릿 모드 창이나 다른 브라우저에 붙여 넣으세요",
|
||||
"Random": "Random",
|
||||
"Real name": "Real name",
|
||||
"Redirect URL": "리디렉트 URL",
|
||||
"Redirect URL (Assertion Consumer Service POST Binding URL) - Tooltip": "리디렉션 URL (단언 서비스 소비자 POST 바인딩 URL)",
|
||||
"Redirect URLs": "URL 리디렉트",
|
||||
@@ -74,6 +81,8 @@
|
||||
"Side panel HTML - Edit": "사이드 패널 HTML - 편집",
|
||||
"Side panel HTML - Tooltip": "로그인 페이지의 측면 패널용 HTML 코드를 맞춤 설정하십시오",
|
||||
"Sign Up Error": "가입 오류",
|
||||
"Signin": "Signin",
|
||||
"Signin (Default True)": "Signin (Default True)",
|
||||
"Signin page URL copied to clipboard successfully, please paste it into the incognito window or another browser": "로그인 페이지 URL이 클립보드에 성공적으로 복사되었습니다. 익명 창이나 다른 브라우저에 붙여넣어주세요",
|
||||
"Signin session": "로그인 세션",
|
||||
"Signup items": "가입 항목",
|
||||
@@ -504,6 +513,8 @@
|
||||
"Host - Tooltip": "호스트의 이름",
|
||||
"IdP": "IdP",
|
||||
"IdP certificate": "IdP 인증서",
|
||||
"Intelligent Validation": "Intelligent Validation",
|
||||
"Internal": "Internal",
|
||||
"Issuer URL": "발행자 URL",
|
||||
"Issuer URL - Tooltip": "발급자 URL",
|
||||
"Link copied to clipboard successfully": "링크가 클립보드에 성공적으로 복사되었습니다",
|
||||
@@ -511,6 +522,7 @@
|
||||
"Metadata - Tooltip": "SAML 메타데이터",
|
||||
"Method - Tooltip": "로그인 방법, QR 코드 또는 음성 로그인",
|
||||
"New Provider": "새로운 공급 업체",
|
||||
"Normal": "Normal",
|
||||
"Parse": "파싱",
|
||||
"Parse metadata successfully": "메타데이터를 성공적으로 분석했습니다",
|
||||
"Path prefix": "경로 접두어",
|
||||
@@ -555,8 +567,10 @@
|
||||
"Signup HTML": "가입 양식 HTML",
|
||||
"Signup HTML - Edit": "가입 HTML - 수정",
|
||||
"Signup HTML - Tooltip": "기본 가입 페이지 스타일을 바꾸기 위한 사용자 지정 HTML",
|
||||
"Silent": "Silent",
|
||||
"Site key": "사이트 키",
|
||||
"Site key - Tooltip": "사이트 키",
|
||||
"Sliding Validation": "Sliding Validation",
|
||||
"Sub type": "하위 유형",
|
||||
"Sub type - Tooltip": "서브 타입",
|
||||
"Template code": "템플릿 코드",
|
||||
@@ -564,6 +578,7 @@
|
||||
"Test Email": "테스트 이메일",
|
||||
"Test Email - Tooltip": "테스트 메일을 받을 이메일 주소",
|
||||
"Test SMTP Connection": "테스트 SMTP 연결",
|
||||
"Third-party": "Third-party",
|
||||
"Token URL": "토큰 URL",
|
||||
"Token URL - Tooltip": "토큰 URL",
|
||||
"Type": "타입",
|
||||
@@ -621,6 +636,7 @@
|
||||
"The input is not valid Email!": "입력 값은 유효한 이메일이 아닙니다!",
|
||||
"The input is not valid Phone!": "입력이 유효한 전화번호가 아닙니다!",
|
||||
"Username": "사용자 이름",
|
||||
"Username - Tooltip": "Username - Tooltip",
|
||||
"Your account has been created!": "계정이 생성되었습니다!",
|
||||
"Your confirmed password is inconsistent with the password!": "확인된 비밀번호가 비밀번호와 일치하지 않습니다!",
|
||||
"sign in now": "지금 로그인하십시오"
|
||||
|
@@ -41,6 +41,7 @@
|
||||
"Enable signup - Tooltip": "Разрешить ли пользователям зарегистрировать новый аккаунт",
|
||||
"Failed to sign in": "Не удалось войти в систему",
|
||||
"File uploaded successfully": "Файл успешно загружен",
|
||||
"First, last": "First, last",
|
||||
"Follow organization theme": "Cледуйте теме организации",
|
||||
"Form CSS": "Форма CSS",
|
||||
"Form CSS - Edit": "Форма CSS - Редактирование",
|
||||
@@ -49,15 +50,21 @@
|
||||
"Form position - Tooltip": "Местоположение форм регистрации, входа и восстановления пароля",
|
||||
"Grant types": "Типы грантов",
|
||||
"Grant types - Tooltip": "Выберите, какие типы грантов разрешены в протоколе OAuth",
|
||||
"Incremental": "Incremental",
|
||||
"Left": "Левый",
|
||||
"Logged in successfully": "Успешный вход в систему",
|
||||
"Logged out successfully": "Успешный выход из системы",
|
||||
"New Application": "Новое приложение",
|
||||
"No verification": "No verification",
|
||||
"None": "Никакой",
|
||||
"Normal": "Normal",
|
||||
"Only signup": "Only signup",
|
||||
"Please input your application!": "Пожалуйста, введите свою заявку!",
|
||||
"Please input your organization!": "Пожалуйста, введите название вашей организации!",
|
||||
"Please select a HTML file": "Пожалуйста, выберите файл HTML",
|
||||
"Prompt page URL copied to clipboard successfully, please paste it into the incognito window or another browser": "URL страницы успешно скопирован в буфер обмена, пожалуйста, вставьте его в режиме инкогнито или в другом браузере",
|
||||
"Random": "Random",
|
||||
"Real name": "Real name",
|
||||
"Redirect URL": "Перенаправление URL",
|
||||
"Redirect URL (Assertion Consumer Service POST Binding URL) - Tooltip": "Перенаправление URL (адрес сервиса потребителя утверждения POST-связывание)",
|
||||
"Redirect URLs": "Перенаправление URL-адресов",
|
||||
@@ -74,6 +81,8 @@
|
||||
"Side panel HTML - Edit": "Боковая панель HTML - Редактировать",
|
||||
"Side panel HTML - Tooltip": "Настроить HTML-код для боковой панели страницы входа в систему",
|
||||
"Sign Up Error": "Ошибка при регистрации",
|
||||
"Signin": "Signin",
|
||||
"Signin (Default True)": "Signin (Default True)",
|
||||
"Signin page URL copied to clipboard successfully, please paste it into the incognito window or another browser": "URL страницы входа скопирован успешно, пожалуйста, вставьте ее в инкогнито-окно или другой браузер",
|
||||
"Signin session": "Сессия входа в систему",
|
||||
"Signup items": "Элементы регистрации",
|
||||
@@ -504,6 +513,8 @@
|
||||
"Host - Tooltip": "Имя хоста",
|
||||
"IdP": "IdP",
|
||||
"IdP certificate": "Сертификат IdP",
|
||||
"Intelligent Validation": "Intelligent Validation",
|
||||
"Internal": "Internal",
|
||||
"Issuer URL": "URL выпускающего органа",
|
||||
"Issuer URL - Tooltip": "URL эмитента",
|
||||
"Link copied to clipboard successfully": "Ссылка успешно скопирована в буфер обмена",
|
||||
@@ -511,6 +522,7 @@
|
||||
"Metadata - Tooltip": "Метаданные SAML",
|
||||
"Method - Tooltip": "Метод входа, QR-код или беззвучный вход",
|
||||
"New Provider": "Новый провайдер",
|
||||
"Normal": "Normal",
|
||||
"Parse": "Спарсить",
|
||||
"Parse metadata successfully": "Успешно обработана метаданные",
|
||||
"Path prefix": "Префикс пути",
|
||||
@@ -555,8 +567,10 @@
|
||||
"Signup HTML": "Регистрационная форма HTML",
|
||||
"Signup HTML - Edit": "Регистрационная форма HTML - Редактировать",
|
||||
"Signup HTML - Tooltip": "Пользовательский HTML для замены стиля стандартной страницы регистрации",
|
||||
"Silent": "Silent",
|
||||
"Site key": "Ключ сайта",
|
||||
"Site key - Tooltip": "Ключ сайта",
|
||||
"Sliding Validation": "Sliding Validation",
|
||||
"Sub type": "Подтип",
|
||||
"Sub type - Tooltip": "Подтип",
|
||||
"Template code": "Шаблонный код",
|
||||
@@ -564,6 +578,7 @@
|
||||
"Test Email": "Тестовое письмо",
|
||||
"Test Email - Tooltip": "Адрес электронной почты для получения тестовых писем",
|
||||
"Test SMTP Connection": "Тестирование соединения SMTP",
|
||||
"Third-party": "Third-party",
|
||||
"Token URL": "Токен URL (URL-адрес маркера)",
|
||||
"Token URL - Tooltip": "Токен URL",
|
||||
"Type": "Тип",
|
||||
@@ -621,6 +636,7 @@
|
||||
"The input is not valid Email!": "Ввод не является действительным адресом электронной почты!",
|
||||
"The input is not valid Phone!": "Ввод не является действительным телефоном!",
|
||||
"Username": "Имя пользователя",
|
||||
"Username - Tooltip": "Username - Tooltip",
|
||||
"Your account has been created!": "Ваш аккаунт был создан!",
|
||||
"Your confirmed password is inconsistent with the password!": "Ваш подтвержденный пароль не соответствует паролю!",
|
||||
"sign in now": "войти сейчас"
|
||||
|
@@ -41,6 +41,7 @@
|
||||
"Enable signup - Tooltip": "Có cho phép người dùng đăng ký tài khoản mới không?",
|
||||
"Failed to sign in": "Không đăng nhập được",
|
||||
"File uploaded successfully": "Tệp được tải lên thành công",
|
||||
"First, last": "First, last",
|
||||
"Follow organization theme": "Theo chủ đề tổ chức",
|
||||
"Form CSS": "Mẫu CSS",
|
||||
"Form CSS - Edit": "Biểu mẫu CSS - Chỉnh sửa",
|
||||
@@ -49,15 +50,21 @@
|
||||
"Form position - Tooltip": "Vị trí của các biểu mẫu đăng ký, đăng nhập và quên mật khẩu",
|
||||
"Grant types": "Loại hỗ trợ",
|
||||
"Grant types - Tooltip": "Chọn loại hỗ trợ được cho phép trong giao thức OAuth",
|
||||
"Incremental": "Incremental",
|
||||
"Left": "Trái",
|
||||
"Logged in successfully": "Đăng nhập thành công",
|
||||
"Logged out successfully": "Đã đăng xuất thành công",
|
||||
"New Application": "Ứng dụng mới",
|
||||
"No verification": "No verification",
|
||||
"None": "Không có gì",
|
||||
"Normal": "Normal",
|
||||
"Only signup": "Only signup",
|
||||
"Please input your application!": "Vui lòng nhập đơn của bạn!",
|
||||
"Please input your organization!": "Vui lòng nhập tên tổ chức của bạn!",
|
||||
"Please select a HTML file": "Vui lòng chọn tệp HTML",
|
||||
"Prompt page URL copied to clipboard successfully, please paste it into the incognito window or another browser": "Đã sao chép đường dẫn trang một cách thành công, hãy dán nó vào cửa sổ ẩn danh hoặc trình duyệt khác",
|
||||
"Random": "Random",
|
||||
"Real name": "Real name",
|
||||
"Redirect URL": "Chuyển hướng đường dẫn URL",
|
||||
"Redirect URL (Assertion Consumer Service POST Binding URL) - Tooltip": "Điều hướng URL (URL khung POST Dịch vụ Tiêu thụ Khẳng định)",
|
||||
"Redirect URLs": "Chuyển hướng URL",
|
||||
@@ -74,6 +81,8 @@
|
||||
"Side panel HTML - Edit": "Bảng Panel Bên - Chỉnh sửa HTML",
|
||||
"Side panel HTML - Tooltip": "Tùy chỉnh mã HTML cho bảng điều khiển bên của trang đăng nhập",
|
||||
"Sign Up Error": "Lỗi đăng ký",
|
||||
"Signin": "Signin",
|
||||
"Signin (Default True)": "Signin (Default True)",
|
||||
"Signin page URL copied to clipboard successfully, please paste it into the incognito window or another browser": "Đã sao chép thành công địa chỉ URL trang Đăng nhập vào clipboard, vui lòng dán nó vào cửa sổ ẩn danh hoặc trình duyệt khác",
|
||||
"Signin session": "Phiên đăng nhập",
|
||||
"Signup items": "Các mục đăng ký",
|
||||
@@ -504,6 +513,8 @@
|
||||
"Host - Tooltip": "Tên của người chủ chỗ ở",
|
||||
"IdP": "IdP",
|
||||
"IdP certificate": "Chứng chỉ IdP",
|
||||
"Intelligent Validation": "Intelligent Validation",
|
||||
"Internal": "Internal",
|
||||
"Issuer URL": "Địa chỉ URL của người phát hành",
|
||||
"Issuer URL - Tooltip": "Địa chỉ URL của nhà phát hành",
|
||||
"Link copied to clipboard successfully": "Đã sao chép liên kết vào bộ nhớ tạm thành công",
|
||||
@@ -511,6 +522,7 @@
|
||||
"Metadata - Tooltip": "SAML metadata: siêu dữ liệu SAML",
|
||||
"Method - Tooltip": "Phương thức đăng nhập, mã QR hoặc đăng nhập im lặng",
|
||||
"New Provider": "Nhà cung cấp mới",
|
||||
"Normal": "Normal",
|
||||
"Parse": "Phân tích cú pháp",
|
||||
"Parse metadata successfully": "Phân tích siêu dữ liệu thành công",
|
||||
"Path prefix": "Tiền tố đường dẫn",
|
||||
@@ -555,8 +567,10 @@
|
||||
"Signup HTML": "Đăng ký HTML",
|
||||
"Signup HTML - Edit": "Đăng ký HTML - Chỉnh sửa",
|
||||
"Signup HTML - Tooltip": "Trang HTML tùy chỉnh để thay thế phong cách trang đăng ký mặc định",
|
||||
"Silent": "Silent",
|
||||
"Site key": "Khóa trang web",
|
||||
"Site key - Tooltip": "Khóa trang web",
|
||||
"Sliding Validation": "Sliding Validation",
|
||||
"Sub type": "Loại phụ",
|
||||
"Sub type - Tooltip": "Loại phụ",
|
||||
"Template code": "Mã mẫu của template",
|
||||
@@ -564,6 +578,7 @@
|
||||
"Test Email": "Thư Email kiểm tra",
|
||||
"Test Email - Tooltip": "Địa chỉ email để nhận thư kiểm tra",
|
||||
"Test SMTP Connection": "Kiểm tra kết nối SMTP",
|
||||
"Third-party": "Third-party",
|
||||
"Token URL": "Đường dẫn Token",
|
||||
"Token URL - Tooltip": "Địa chỉ URL của Token",
|
||||
"Type": "Kiểu",
|
||||
@@ -621,6 +636,7 @@
|
||||
"The input is not valid Email!": "Đầu vào không phải là địa chỉ Email hợp lệ!",
|
||||
"The input is not valid Phone!": "Đầu vào không hợp lệ! Số điện thoại không hợp lệ!",
|
||||
"Username": "Tên đăng nhập",
|
||||
"Username - Tooltip": "Username - Tooltip",
|
||||
"Your account has been created!": "Tài khoản của bạn đã được tạo!",
|
||||
"Your confirmed password is inconsistent with the password!": "Mật khẩu xác nhận của bạn không khớp với mật khẩu đã nhập!",
|
||||
"sign in now": "Đăng nhập ngay bây giờ"
|
||||
|
@@ -41,6 +41,7 @@
|
||||
"Enable signup - Tooltip": "是否允许用户注册",
|
||||
"Failed to sign in": "登录失败",
|
||||
"File uploaded successfully": "文件上传成功",
|
||||
"First, last": "名字, 姓氏",
|
||||
"Follow organization theme": "使用组织主题",
|
||||
"Form CSS": "表单CSS",
|
||||
"Form CSS - Edit": "编辑表单CSS",
|
||||
@@ -49,15 +50,21 @@
|
||||
"Form position - Tooltip": "注册、登录、忘记密码等表单的位置",
|
||||
"Grant types": "OAuth授权类型",
|
||||
"Grant types - Tooltip": "选择允许哪些OAuth协议中的grant types",
|
||||
"Incremental": "递增",
|
||||
"Left": "居左",
|
||||
"Logged in successfully": "登录成功",
|
||||
"Logged out successfully": "登出成功",
|
||||
"New Application": "添加应用",
|
||||
"No verification": "不校验",
|
||||
"None": "关闭",
|
||||
"Normal": "标准",
|
||||
"Only signup": "仅注册",
|
||||
"Please input your application!": "请输入你的应用",
|
||||
"Please input your organization!": "请输入你的组织",
|
||||
"Please select a HTML file": "请选择一个HTML文件",
|
||||
"Prompt page URL copied to clipboard successfully, please paste it into the incognito window or another browser": "提醒页面URL已成功复制到剪贴板,请粘贴到当前浏览器的隐身模式窗口或另一个浏览器访问",
|
||||
"Random": "随机",
|
||||
"Real name": "真实姓名",
|
||||
"Redirect URL": "重定向 URL",
|
||||
"Redirect URL (Assertion Consumer Service POST Binding URL) - Tooltip": "回复 URL (断言使用者服务 URL, 使用POST请求返回响应) - Tooltip",
|
||||
"Redirect URLs": "重定向 URLs",
|
||||
@@ -74,6 +81,8 @@
|
||||
"Side panel HTML - Edit": "侧面板HTML - 编辑",
|
||||
"Side panel HTML - Tooltip": "自定义登录页面侧面板的HTML代码",
|
||||
"Sign Up Error": "注册错误",
|
||||
"Signin": "登录",
|
||||
"Signin (Default True)": "登录 (默认同意)",
|
||||
"Signin page URL copied to clipboard successfully, please paste it into the incognito window or another browser": "登录页面URL已成功复制到剪贴板,请粘贴到当前浏览器的隐身模式窗口或另一个浏览器访问",
|
||||
"Signin session": "保持登录会话",
|
||||
"Signup items": "注册项",
|
||||
@@ -504,6 +513,8 @@
|
||||
"Host - Tooltip": "主机名",
|
||||
"IdP": "IdP",
|
||||
"IdP certificate": "IdP公钥证书",
|
||||
"Intelligent Validation": "智能验证",
|
||||
"Internal": "内部",
|
||||
"Issuer URL": "Issuer链接",
|
||||
"Issuer URL - Tooltip": "Issuer链接URL",
|
||||
"Link copied to clipboard successfully": "链接已成功复制到剪贴板",
|
||||
@@ -511,6 +522,7 @@
|
||||
"Metadata - Tooltip": "SAML元数据",
|
||||
"Method - Tooltip": "登录方法,二维码或者静默授权登录",
|
||||
"New Provider": "添加提供商",
|
||||
"Normal": "标准",
|
||||
"Parse": "解析",
|
||||
"Parse metadata successfully": "解析元数据成功",
|
||||
"Path prefix": "路径前缀",
|
||||
@@ -555,8 +567,10 @@
|
||||
"Signup HTML": "注册页面HTML",
|
||||
"Signup HTML - Edit": "注册页面HTML - 编辑",
|
||||
"Signup HTML - Tooltip": "自定义HTML,用于替换默认的注册页面样式",
|
||||
"Silent": "静默",
|
||||
"Site key": "Site key",
|
||||
"Site key - Tooltip": "Site key",
|
||||
"Sliding Validation": "滑块验证",
|
||||
"Sub type": "子类型",
|
||||
"Sub type - Tooltip": "子类型",
|
||||
"Template code": "模板代码",
|
||||
@@ -564,6 +578,7 @@
|
||||
"Test Email": "测试Email配置",
|
||||
"Test Email - Tooltip": "接收测试邮件的Email邮箱",
|
||||
"Test SMTP Connection": "测试SMTP连接",
|
||||
"Third-party": "第三方",
|
||||
"Token URL": "Token URL",
|
||||
"Token URL - Tooltip": "自定义OAuth的Token URL",
|
||||
"Type": "类型",
|
||||
@@ -621,6 +636,7 @@
|
||||
"The input is not valid Email!": "您输入的电子邮箱格式有误!",
|
||||
"The input is not valid Phone!": "您输入的手机号格式有误!",
|
||||
"Username": "用户名",
|
||||
"Username - Tooltip": "用户名",
|
||||
"Your account has been created!": "您的账号已成功创建!",
|
||||
"Your confirmed password is inconsistent with the password!": "您两次输入的密码不一致!",
|
||||
"sign in now": "立即登录"
|
||||
|
@@ -15,7 +15,7 @@
|
||||
import React from "react";
|
||||
import {DeleteOutlined, DownOutlined, UpOutlined} from "@ant-design/icons";
|
||||
import {Button, Col, Row, Select, Switch, Table, Tooltip} from "antd";
|
||||
import * as Setting from "./Setting";
|
||||
import * as Setting from "../Setting";
|
||||
import i18next from "i18next";
|
||||
|
||||
const {Option} = Select;
|
@@ -14,11 +14,11 @@
|
||||
|
||||
import React from "react";
|
||||
import {Button, Col, Row, Table} from "antd";
|
||||
import * as Setting from "./Setting";
|
||||
import * as Setting from "../Setting";
|
||||
import i18next from "i18next";
|
||||
import * as LdapBackend from "./backend/LdapBackend";
|
||||
import * as LdapBackend from "../backend/LdapBackend";
|
||||
import {Link} from "react-router-dom";
|
||||
import PopconfirmModal from "./PopconfirmModal";
|
||||
import PopconfirmModal from "../PopconfirmModal";
|
||||
|
||||
class LdapTable extends React.Component {
|
||||
constructor(props) {
|
@@ -15,7 +15,7 @@
|
||||
import React from "react";
|
||||
import {DeleteOutlined, DownOutlined, UpOutlined} from "@ant-design/icons";
|
||||
import {Button, Col, Input, Row, Select, Table, Tooltip} from "antd";
|
||||
import * as Setting from "./Setting";
|
||||
import * as Setting from "../Setting";
|
||||
import i18next from "i18next";
|
||||
|
||||
const {Option} = Select;
|
@@ -15,9 +15,9 @@
|
||||
import React from "react";
|
||||
import {DeleteOutlined, DownOutlined, UpOutlined} from "@ant-design/icons";
|
||||
import {Button, Col, Row, Select, Switch, Table, Tooltip} from "antd";
|
||||
import * as Setting from "./Setting";
|
||||
import * as Setting from "../Setting";
|
||||
import i18next from "i18next";
|
||||
import * as Provider from "./auth/Provider";
|
||||
import * as Provider from "../auth/Provider";
|
||||
|
||||
const {Option} = Select;
|
||||
|
@@ -15,7 +15,7 @@
|
||||
import React from "react";
|
||||
import {DeleteOutlined, DownOutlined, UpOutlined} from "@ant-design/icons";
|
||||
import {Button, Col, Row, Select, Switch, Table, Tooltip} from "antd";
|
||||
import * as Setting from "./Setting";
|
||||
import * as Setting from "../Setting";
|
||||
import i18next from "i18next";
|
||||
|
||||
const {Option} = Select;
|
||||
@@ -172,25 +172,25 @@ class SignupTable extends React.Component {
|
||||
let options = [];
|
||||
if (record.name === "ID") {
|
||||
options = [
|
||||
{id: "Random", name: "Random"},
|
||||
{id: "Incremental", name: "Incremental"},
|
||||
{id: "Random", name: i18next.t("application:Random")},
|
||||
{id: "Incremental", name: i18next.t("application:Incremental")},
|
||||
];
|
||||
} else if (record.name === "Display name") {
|
||||
options = [
|
||||
{id: "None", name: "None"},
|
||||
{id: "Real name", name: "Real name"},
|
||||
{id: "First, last", name: "First, last"},
|
||||
{id: "None", name: i18next.t("application:None")},
|
||||
{id: "Real name", name: i18next.t("application:Real name")},
|
||||
{id: "First, last", name: i18next.t("application:First, last")},
|
||||
];
|
||||
} else if (record.name === "Email") {
|
||||
options = [
|
||||
{id: "Normal", name: "Normal"},
|
||||
{id: "No verification", name: "No verification"},
|
||||
{id: "Normal", name: i18next.t("application:Normal")},
|
||||
{id: "No verification", name: i18next.t("application:No verification")},
|
||||
];
|
||||
} else if (record.name === "Agreement") {
|
||||
options = [
|
||||
{id: "None", name: "None"},
|
||||
{id: "Signin", name: "Signin"},
|
||||
{id: "Signin (Default True)", name: "Signin (Default True)"},
|
||||
{id: "None", name: i18next.t("application:Only signup")},
|
||||
{id: "Signin", name: i18next.t("application:Signin")},
|
||||
{id: "Signin (Default True)", name: i18next.t("application:Signin (Default True)")},
|
||||
];
|
||||
}
|
||||
|
@@ -15,7 +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 * as Setting from "./Setting";
|
||||
import * as Setting from "../Setting";
|
||||
import i18next from "i18next";
|
||||
|
||||
const {Option} = Select;
|
@@ -15,7 +15,7 @@
|
||||
import React from "react";
|
||||
import {DeleteOutlined, DownOutlined, LinkOutlined, UpOutlined} from "@ant-design/icons";
|
||||
import {Button, Col, Input, Row, Table, Tooltip} from "antd";
|
||||
import * as Setting from "./Setting";
|
||||
import * as Setting from "../Setting";
|
||||
import i18next from "i18next";
|
||||
|
||||
class UrlTable extends React.Component {
|
@@ -15,8 +15,8 @@
|
||||
import React from "react";
|
||||
import {Button, Table} from "antd";
|
||||
import i18next from "i18next";
|
||||
import * as UserWebauthnBackend from "./backend/UserWebauthnBackend";
|
||||
import * as Setting from "./Setting";
|
||||
import * as UserWebauthnBackend from "../backend/UserWebauthnBackend";
|
||||
import * as Setting from "../Setting";
|
||||
|
||||
class WebAuthnCredentialTable extends React.Component {
|
||||
deleteRow(table, i) {
|
@@ -15,7 +15,7 @@
|
||||
import React from "react";
|
||||
import {DeleteOutlined, DownOutlined, UpOutlined} from "@ant-design/icons";
|
||||
import {Button, Col, Input, Row, Table, Tooltip} from "antd";
|
||||
import * as Setting from "./Setting";
|
||||
import * as Setting from "../Setting";
|
||||
import i18next from "i18next";
|
||||
|
||||
class WebhookHeaderTable extends React.Component {
|
@@ -16,7 +16,7 @@ import React from "react";
|
||||
import {Button, Input, Table} from "antd";
|
||||
import i18next from "i18next";
|
||||
import {DeleteOutlined} from "@ant-design/icons";
|
||||
import * as Setting from "./Setting";
|
||||
import * as Setting from "../Setting";
|
||||
|
||||
class PropertyTable extends React.Component {
|
||||
constructor(props) {
|
Reference in New Issue
Block a user