Compare commits

..

20 Commits

Author SHA1 Message Date
65d4946042 feat: add valid key for creating token (#1411) 2022-12-20 22:05:00 +08:00
Liu
26acece8af feat: add all other missing objects to init_data (#1407)
* Add all other missing objects to init_data.json

* Format golang code

* feat: add all other missing objects to init_data

* feat: add all other missing objects to init_data
2022-12-18 01:49:42 +08:00
48a0c8473f Improve README 2022-12-18 01:41:12 +08:00
082ae3c91e fix: fix undefined owner bug in AdapterEditPage (#1406) 2022-12-17 21:21:39 +08:00
1ee2ff1d30 feat: now dingtalk OAuth returns all error messages to frontend (#1405) 2022-12-17 21:10:20 +08:00
c0d9969013 Add description to product 2022-12-16 23:35:30 +08:00
1bdee13150 Fix bug in renderQrCodeModal() 2022-12-16 23:28:43 +08:00
d668022af0 feat: fix length of policy and [policy_define] in model inconsistent (#1400) 2022-12-15 20:42:55 +08:00
e227875c2b feat: add post methed for saml response (#1399) 2022-12-13 22:32:45 +08:00
e473de3162 feat: fix sign in error via webauthn (#1398)
* fix: fix sign in error via webauthn

* fix review problems
2022-12-13 16:57:42 +08:00
c5ef841d3f Disable isValidIdCard() 2022-12-12 01:07:31 +08:00
d46288b591 Add renderQrCodeModal() 2022-12-12 00:42:45 +08:00
b968bf033c fix: case insensitive country name and country abbreviation search in region selection (#1394) 2022-12-11 18:14:25 +08:00
eca2527bc0 feat: fix bug in signup and reset phone and email (#1396)
* fix: fix bug in signup and reset phone and email

* delete useless addition
2022-12-11 15:52:36 +08:00
ef836acfe9 fix: login page flag icon preload (#1393) 2022-12-11 11:22:58 +08:00
a51f0d7c08 feat: init score in organization (#1388)
* feat: init score in organization

* Update OrganizationEditPage.js

Co-authored-by: hsluoyz <hsluoyz@qq.com>
2022-12-10 22:27:12 +08:00
e3c36beaf4 fix: the link button with disabled style but can click (#1390) 2022-12-10 22:14:20 +08:00
19dce838d1 fix: fix invalid url in applications page (#1389) 2022-12-10 22:06:21 +08:00
b41d8652f0 feat: fix showing wrong error messages (#1385) 2022-12-09 15:11:13 +08:00
e705eecffe feat: response with status in casbin_adapter.go (#1384)
* fix: response standardized information with status in `casbin_adapter.go`

* fix: remove redundant statements
2022-12-08 10:22:59 +08:00
48 changed files with 777 additions and 135 deletions

View File

@ -44,14 +44,12 @@
## Online demo ## Online demo
- International: https://door.casdoor.org (read-only) - Read-only site: https://door.casdoor.com (any modification operation will fail)
- Asian mirror: https://door.casdoor.com (read-only) - Writable site: https://demo.casdoor.com (original data will be restored for every 5 minutes)
- Asian mirror: https://demo.casdoor.com (read-write, will restore for every 5 minutes)
## Documentation ## Documentation
- International: https://casdoor.org https://casdoor.org
- Asian mirror: https://casdoor.cn
## Install ## Install

View File

@ -161,7 +161,7 @@ func (c *ApiController) Signup() {
username = id username = id
} }
initScore, err := getInitScore() initScore, err := getInitScore(organization)
if err != nil { if err != nil {
c.ResponseError(fmt.Errorf(c.T("account:Get init score failed, error: %w"), err).Error()) c.ResponseError(fmt.Errorf(c.T("account:Get init score failed, error: %w"), err).Error())
return return

View File

@ -412,7 +412,7 @@ func (c *ApiController) Login() {
properties := map[string]string{} properties := map[string]string{}
properties["no"] = strconv.Itoa(len(object.GetUsers(application.Organization)) + 2) properties["no"] = strconv.Itoa(len(object.GetUsers(application.Organization)) + 2)
initScore, err := getInitScore() initScore, err := getInitScore(organization)
if err != nil { if err != nil {
c.ResponseError(fmt.Errorf(c.T("auth:Get init score failed, error: %w"), err).Error()) c.ResponseError(fmt.Errorf(c.T("auth:Get init score failed, error: %w"), err).Error())
return return

View File

@ -32,8 +32,8 @@ func (c *ApiController) GetCasbinAdapters() {
sortField := c.Input().Get("sortField") sortField := c.Input().Get("sortField")
sortOrder := c.Input().Get("sortOrder") sortOrder := c.Input().Get("sortOrder")
if limit == "" || page == "" { if limit == "" || page == "" {
c.Data["json"] = object.GetCasbinAdapters(owner) adapters := object.GetCasbinAdapters(owner)
c.ServeJSON() c.ResponseOk(adapters)
} else { } else {
limit := util.ParseInt(limit) limit := util.ParseInt(limit)
paginator := pagination.SetPaginator(c.Ctx, limit, int64(object.GetCasbinAdapterCount(owner, field, value))) paginator := pagination.SetPaginator(c.Ctx, limit, int64(object.GetCasbinAdapterCount(owner, field, value)))
@ -44,8 +44,8 @@ func (c *ApiController) GetCasbinAdapters() {
func (c *ApiController) GetCasbinAdapter() { func (c *ApiController) GetCasbinAdapter() {
id := c.Input().Get("id") id := c.Input().Get("id")
c.Data["json"] = object.GetCasbinAdapter(id) adapter := object.GetCasbinAdapter(id)
c.ServeJSON() c.ResponseOk(adapter)
} }
func (c *ApiController) UpdateCasbinAdapter() { func (c *ApiController) UpdateCasbinAdapter() {
@ -96,8 +96,7 @@ func (c *ApiController) SyncPolicies() {
return return
} }
c.Data["json"] = policies c.ResponseOk(policies)
c.ServeJSON()
} }
func (c *ApiController) UpdatePolicy() { func (c *ApiController) UpdatePolicy() {

View File

@ -84,7 +84,7 @@ func (c *ApiController) SetTokenErrorHttpStatus() {
func (c *ApiController) RequireSignedIn() (string, bool) { func (c *ApiController) RequireSignedIn() (string, bool) {
userId := c.GetSessionUsername() userId := c.GetSessionUsername()
if userId == "" { if userId == "" {
c.ResponseError(c.T("util:Please login first"), "util:Please login first") c.ResponseError(c.T("util:Please login first"), "Please login first")
return "", false return "", false
} }
return userId, true return userId, true
@ -119,8 +119,12 @@ func (c *ApiController) RequireAdmin() (string, bool) {
return user.Owner, true return user.Owner, true
} }
func getInitScore() (int, error) { func getInitScore(organization *object.Organization) (int, error) {
return strconv.Atoi(conf.GetConfigString("initScore")) if organization != nil {
return organization.InitScore, nil
} else {
return strconv.Atoi(conf.GetConfigString("initScore"))
}
} }
func (c *ApiController) GetProviderFromContext(category string) (*object.Provider, *object.User, bool) { func (c *ApiController) GetProviderFromContext(category string) (*object.Provider, *object.User, bool) {

View File

@ -47,6 +47,7 @@ func (c *ApiController) SendVerificationCode() {
checkKey := c.Ctx.Request.Form.Get("checkKey") checkKey := c.Ctx.Request.Form.Get("checkKey")
checkUser := c.Ctx.Request.Form.Get("checkUser") checkUser := c.Ctx.Request.Form.Get("checkUser")
applicationId := c.Ctx.Request.Form.Get("applicationId") applicationId := c.Ctx.Request.Form.Get("applicationId")
method := c.Ctx.Request.Form.Get("method")
remoteAddr := util.GetIPFromRequest(c.Ctx.Request) remoteAddr := util.GetIPFromRequest(c.Ctx.Request)
if destType == "" { if destType == "" {
@ -119,7 +120,7 @@ func (c *ApiController) SendVerificationCode() {
} }
userByEmail := object.GetUserByEmail(organization.Name, dest) userByEmail := object.GetUserByEmail(organization.Name, dest)
if userByEmail == nil { if userByEmail == nil && method != "signup" && method != "reset" {
c.ResponseError(c.T("verification:the user does not exist, please sign up first")) c.ResponseError(c.T("verification:the user does not exist, please sign up first"))
return return
} }
@ -136,7 +137,7 @@ func (c *ApiController) SendVerificationCode() {
} }
userByPhone := object.GetUserByPhone(organization.Name, dest) userByPhone := object.GetUserByPhone(organization.Name, dest)
if userByPhone == nil { if userByPhone == nil && method != "signup" && method != "reset" {
c.ResponseError(c.T("verification:the user does not exist, please sign up first")) c.ResponseError(c.T("verification:the user does not exist, please sign up first"))
return return
} }

View File

@ -256,6 +256,8 @@ func (idp *DingTalkIdProvider) isUserInOrg(unionId string) (bool, error) {
} }
if data.ErrCode == 60121 { if data.ErrCode == 60121 {
return false, fmt.Errorf("the user is not found in the organization where clientId and clientSecret belong") return false, fmt.Errorf("the user is not found in the organization where clientId and clientSecret belong")
} else if data.ErrCode != 0 {
return false, fmt.Errorf(data.ErrMessage)
} }
return true, nil return true, nil
} }

View File

@ -156,5 +156,187 @@
"autoSync": 0, "autoSync": 0,
"lastSync": "" "lastSync": ""
} }
],
"models": [
{
"owner": "",
"name": "",
"modelText": "",
"displayName": ""
}
],
"permissions": [
{
"actions": [
""
],
"displayName": "",
"effect": "",
"isEnabled": true,
"model": "",
"name": "",
"owner": "",
"resourceType": "",
"resources": [
""
],
"roles": [
""
],
"users": [
""
]
}
],
"payments": [
{
"currency": "",
"detail": "",
"displayName": "",
"invoiceRemark": "",
"invoiceTaxId": "",
"invoiceTitle": "",
"invoiceType": "",
"invoiceUrl": "",
"message": "",
"name": "",
"organization": "",
"owner": "",
"payUrl": "",
"personEmail": "",
"personIdCard": "",
"personName": "",
"personPhone": "",
"price": 0,
"productDisplayName": "",
"productName": "",
"provider": "",
"returnUrl": "",
"state": "",
"tag": "",
"type": "",
"user": ""
}
],
"products": [
{
"currency": "",
"detail": "",
"displayName": "",
"image": "",
"name": "",
"owner": "",
"price": 0,
"providers": [
""
],
"quantity": 0,
"returnUrl": "",
"sold": 0,
"state": "",
"tag": ""
}
],
"resources": [
{
"owner": "",
"name": "",
"user": "",
"provider": "",
"application": "",
"tag": "",
"parent": "",
"fileName": "",
"fileType": "",
"fileFormat": "",
"url": "",
"description": ""
}
],
"roles": [
{
"displayName": "",
"isEnabled": true,
"name": "",
"owner": "",
"roles": [
""
],
"users": [
""
]
}
],
"syncers": [
{
"affiliationTable": "",
"avatarBaseUrl": "",
"database": "",
"databaseType": "",
"errorText": "",
"host": "",
"isEnabled": true,
"name": "",
"organization": "",
"owner": "",
"password": "",
"port": 0,
"syncInterval": 0,
"table": "",
"tableColumns": [
{
"casdoorName": "",
"isHashed": true,
"name": "",
"type": "",
"values": [
""
]
}
],
"tablePrimaryKey": "",
"type": "",
"user": ""
}
],
"tokens": [
{
"accessToken": "",
"application": "",
"code": "",
"codeChallenge": "",
"codeExpireIn": 0,
"codeIsUsed": true,
"createdTime": "",
"expiresIn": 0,
"name": "",
"organization": "",
"owner": "",
"refreshToken": "",
"scope": "",
"tokenType": "",
"user": ""
}
],
"webhooks": [
{
"contentType": "",
"events": [
""
],
"headers": [
{
"name": "",
"value": ""
}
],
"isEnabled": true,
"isUserExtended": true,
"method": "",
"name": "",
"organization": "",
"owner": "",
"url": ""
}
] ]
} }

View File

@ -51,6 +51,7 @@ type Application struct {
EnableCodeSignin bool `json:"enableCodeSignin"` EnableCodeSignin bool `json:"enableCodeSignin"`
EnableSamlCompress bool `json:"enableSamlCompress"` EnableSamlCompress bool `json:"enableSamlCompress"`
EnableWebAuthn bool `json:"enableWebAuthn"` EnableWebAuthn bool `json:"enableWebAuthn"`
SamlReplyUrl string `xorm:"varchar(100)" json:"samlReplyUrl"`
Providers []*ProviderItem `xorm:"mediumtext" json:"providers"` Providers []*ProviderItem `xorm:"mediumtext" json:"providers"`
SignupItems []*SignupItem `xorm:"varchar(1000)" json:"signupItems"` SignupItems []*SignupItem `xorm:"varchar(1000)" json:"signupItems"`
GrantTypes []string `xorm:"varchar(1000)" json:"grantTypes"` GrantTypes []string `xorm:"varchar(1000)" json:"grantTypes"`

View File

@ -59,6 +59,7 @@ func initBuiltInOrganization() bool {
DefaultAvatar: fmt.Sprintf("%s/img/casbin.svg", conf.GetConfigString("staticBaseUrl")), DefaultAvatar: fmt.Sprintf("%s/img/casbin.svg", conf.GetConfigString("staticBaseUrl")),
Tags: []string{}, Tags: []string{},
Languages: []string{"en", "zh", "es", "fr", "de", "ja", "ko", "ru"}, Languages: []string{"en", "zh", "es", "fr", "de", "ja", "ko", "ru"},
InitScore: 2000,
AccountItems: []*AccountItem{ AccountItems: []*AccountItem{
{Name: "Organization", Visible: true, ViewRule: "Public", ModifyRule: "Admin"}, {Name: "Organization", Visible: true, ViewRule: "Public", ModifyRule: "Admin"},
{Name: "ID", Visible: true, ViewRule: "Public", ModifyRule: "Immutable"}, {Name: "ID", Visible: true, ViewRule: "Public", ModifyRule: "Immutable"},

View File

@ -23,6 +23,15 @@ type InitData struct {
Certs []*Cert `json:"certs"` Certs []*Cert `json:"certs"`
Providers []*Provider `json:"providers"` Providers []*Provider `json:"providers"`
Ldaps []*Ldap `json:"ldaps"` Ldaps []*Ldap `json:"ldaps"`
Models []*Model `json:"models"`
Permissions []*Permission `json:"permissions"`
Payments []*Payment `json:"payments"`
Products []*Product `json:"products"`
Resources []*Resource `json:"resources"`
Roles []*Role `json:"roles"`
Syncers []*Syncer `json:"syncers"`
Tokens []*Token `json:"tokens"`
Webhooks []*Webhook `json:"webhooks"`
} }
func InitFromFile() { func InitFromFile() {
@ -46,6 +55,33 @@ func InitFromFile() {
for _, ldap := range initData.Ldaps { for _, ldap := range initData.Ldaps {
initDefinedLdap(ldap) initDefinedLdap(ldap)
} }
for _, model := range initData.Models {
initDefinedModel(model)
}
for _, permission := range initData.Permissions {
initDefinedPermission(permission)
}
for _, payment := range initData.Payments {
initDefinedPayment(payment)
}
for _, product := range initData.Products {
initDefinedProduct(product)
}
for _, resource := range initData.Resources {
initDefinedResource(resource)
}
for _, role := range initData.Roles {
initDefinedRole(role)
}
for _, syncer := range initData.Syncers {
initDefinedSyncer(syncer)
}
for _, token := range initData.Tokens {
initDefinedToken(token)
}
for _, webhook := range initData.Webhooks {
initDefinedWebhook(webhook)
}
} }
} }
@ -63,6 +99,15 @@ func readInitDataFromFile(filePath string) *InitData {
Certs: []*Cert{}, Certs: []*Cert{},
Providers: []*Provider{}, Providers: []*Provider{},
Ldaps: []*Ldap{}, Ldaps: []*Ldap{},
Models: []*Model{},
Permissions: []*Permission{},
Payments: []*Payment{},
Products: []*Product{},
Resources: []*Resource{},
Roles: []*Role{},
Syncers: []*Syncer{},
Tokens: []*Token{},
Webhooks: []*Webhook{},
} }
err := util.JsonToStruct(s, data) err := util.JsonToStruct(s, data)
if err != nil { if err != nil {
@ -89,6 +134,41 @@ func readInitDataFromFile(filePath string) *InitData {
application.RedirectUris = []string{} application.RedirectUris = []string{}
} }
} }
for _, permission := range data.Permissions {
if permission.Actions == nil {
permission.Actions = []string{}
}
if permission.Resources == nil {
permission.Resources = []string{}
}
if permission.Roles == nil {
permission.Roles = []string{}
}
if permission.Users == nil {
permission.Users = []string{}
}
}
for _, role := range data.Roles {
if role.Roles == nil {
role.Roles = []string{}
}
if role.Users == nil {
role.Users = []string{}
}
}
for _, syncer := range data.Syncers {
if syncer.TableColumns == nil {
syncer.TableColumns = []*TableColumn{}
}
}
for _, webhook := range data.Webhooks {
if webhook.Events == nil {
webhook.Events = []string{}
}
if webhook.Headers == nil {
webhook.Headers = []*Header{}
}
}
return data return data
} }
@ -174,3 +254,84 @@ func initDefinedProvider(provider *Provider) {
} }
AddProvider(provider) AddProvider(provider)
} }
func initDefinedModel(model *Model) {
existed := GetModel(model.GetId())
if existed != nil {
return
}
model.CreatedTime = util.GetCurrentTime()
AddModel(model)
}
func initDefinedPermission(permission *Permission) {
existed := GetPermission(permission.GetId())
if existed != nil {
return
}
permission.CreatedTime = util.GetCurrentTime()
AddPermission(permission)
}
func initDefinedPayment(payment *Payment) {
existed := GetPayment(payment.GetId())
if existed != nil {
return
}
payment.CreatedTime = util.GetCurrentTime()
AddPayment(payment)
}
func initDefinedProduct(product *Product) {
existed := GetProduct(product.GetId())
if existed != nil {
return
}
product.CreatedTime = util.GetCurrentTime()
AddProduct(product)
}
func initDefinedResource(resource *Resource) {
existed := GetResource(resource.GetId())
if existed != nil {
return
}
resource.CreatedTime = util.GetCurrentTime()
AddResource(resource)
}
func initDefinedRole(role *Role) {
existed := GetRole(role.GetId())
if existed != nil {
return
}
role.CreatedTime = util.GetCurrentTime()
AddRole(role)
}
func initDefinedSyncer(syncer *Syncer) {
existed := GetSyncer(syncer.GetId())
if existed != nil {
return
}
syncer.CreatedTime = util.GetCurrentTime()
AddSyncer(syncer)
}
func initDefinedToken(token *Token) {
existed := GetToken(token.GetId())
if existed != nil {
return
}
token.CreatedTime = util.GetCurrentTime()
AddToken(token)
}
func initDefinedWebhook(webhook *Webhook) {
existed := GetWebhook(webhook.GetId())
if existed != nil {
return
}
webhook.CreatedTime = util.GetCurrentTime()
AddWebhook(webhook)
}

View File

@ -47,6 +47,7 @@ type Organization struct {
Tags []string `xorm:"mediumtext" json:"tags"` Tags []string `xorm:"mediumtext" json:"tags"`
Languages []string `xorm:"varchar(255)" json:"languages"` Languages []string `xorm:"varchar(255)" json:"languages"`
MasterPassword string `xorm:"varchar(100)" json:"masterPassword"` MasterPassword string `xorm:"varchar(100)" json:"masterPassword"`
InitScore int `json:"initScore"`
EnableSoftDeletion bool `json:"enableSoftDeletion"` EnableSoftDeletion bool `json:"enableSoftDeletion"`
IsProfilePublic bool `json:"isProfilePublic"` IsProfilePublic bool `json:"isProfilePublic"`

View File

@ -41,7 +41,7 @@ func getEnforcer(permission *Permission) *casbin.Enforcer {
r = sub, obj, act r = sub, obj, act
[policy_definition] [policy_definition]
p = sub, obj, act p = sub, obj, act, "", "", permissionId
[role_definition] [role_definition]
g = _, _ g = _, _

View File

@ -27,15 +27,16 @@ type Product struct {
CreatedTime string `xorm:"varchar(100)" json:"createdTime"` CreatedTime string `xorm:"varchar(100)" json:"createdTime"`
DisplayName string `xorm:"varchar(100)" json:"displayName"` DisplayName string `xorm:"varchar(100)" json:"displayName"`
Image string `xorm:"varchar(100)" json:"image"` Image string `xorm:"varchar(100)" json:"image"`
Detail string `xorm:"varchar(255)" json:"detail"` Detail string `xorm:"varchar(255)" json:"detail"`
Tag string `xorm:"varchar(100)" json:"tag"` Description string `xorm:"varchar(100)" json:"description"`
Currency string `xorm:"varchar(100)" json:"currency"` Tag string `xorm:"varchar(100)" json:"tag"`
Price float64 `json:"price"` Currency string `xorm:"varchar(100)" json:"currency"`
Quantity int `json:"quantity"` Price float64 `json:"price"`
Sold int `json:"sold"` Quantity int `json:"quantity"`
Providers []string `xorm:"varchar(100)" json:"providers"` Sold int `json:"sold"`
ReturnUrl string `xorm:"varchar(1000)" json:"returnUrl"` Providers []string `xorm:"varchar(100)" json:"providers"`
ReturnUrl string `xorm:"varchar(1000)" json:"returnUrl"`
State string `xorm:"varchar(100)" json:"state"` State string `xorm:"varchar(100)" json:"state"`
@ -213,6 +214,10 @@ func BuyProduct(id string, providerName string, user *User, host string) (string
} }
func ExtendProductWithProviders(product *Product) { func ExtendProductWithProviders(product *Product) {
if product == nil {
return
}
product.ProviderObjs = []*Provider{} product.ProviderObjs = []*Provider{}
m := getProviderMap(product.Owner) m := getProviderMap(product.Owner)

View File

@ -251,6 +251,11 @@ func GetSamlResponse(application *Application, user *User, samlRequest string, h
_, originBackend := getOriginFromHost(host) _, originBackend := getOriginFromHost(host)
// redirect Url (Assertion Consumer Url)
if application.SamlReplyUrl != "" {
authnRequest.AssertionConsumerServiceURL = application.SamlReplyUrl
}
// build signedResponse // build signedResponse
samlResponse, _ := NewSamlResponse(user, originBackend, certificate, authnRequest.AssertionConsumerServiceURL, authnRequest.Issuer.Url, authnRequest.ID, application.RedirectUris) samlResponse, _ := NewSamlResponse(user, originBackend, certificate, authnRequest.AssertionConsumerServiceURL, authnRequest.Issuer.Url, authnRequest.ID, application.RedirectUris)
randomKeyStore := &X509Key{ randomKeyStore := &X509Key{

View File

@ -169,6 +169,10 @@ func GetToken(id string) *Token {
return getToken(owner, name) return getToken(owner, name)
} }
func (token *Token) GetId() string {
return fmt.Sprintf("%s/%s", token.Owner, token.Name)
}
func UpdateToken(id string, token *Token) bool { func UpdateToken(id string, token *Token) bool {
owner, name := util.GetOwnerAndNameFromId(id) owner, name := util.GetOwnerAndNameFromId(id)
if getToken(owner, name) == nil { if getToken(owner, name) == nil {

View File

@ -9,7 +9,7 @@
"@testing-library/jest-dom": "^4.2.4", "@testing-library/jest-dom": "^4.2.4",
"@testing-library/react": "^9.3.2", "@testing-library/react": "^9.3.2",
"@testing-library/user-event": "^7.1.2", "@testing-library/user-event": "^7.1.2",
"antd": "5.0.3", "antd": "5.0.5",
"codemirror": "^5.61.1", "codemirror": "^5.61.1",
"copy-to-clipboard": "^3.3.1", "copy-to-clipboard": "^3.3.1",
"core-js": "^3.25.0", "core-js": "^3.25.0",

View File

@ -48,12 +48,14 @@ class AdapterEditPage extends React.Component {
getAdapter() { getAdapter() {
AdapterBackend.getAdapter(this.state.owner, this.state.adapterName) AdapterBackend.getAdapter(this.state.owner, this.state.adapterName)
.then((adapter) => { .then((res) => {
this.setState({ if (res.status === "ok") {
adapter: adapter, this.setState({
}); adapter: res.data,
});
this.getModels(adapter.owner); this.getModels(this.state.owner);
}
}); });
} }

View File

@ -87,7 +87,7 @@ class AdapterListPage extends BaseListPage {
...this.getColumnSearchProps("name"), ...this.getColumnSearchProps("name"),
render: (text, record, index) => { render: (text, record, index) => {
return ( return (
<Link to={`/adapters/${text}`}> <Link to={`/adapters/${record.organization}/${text}`}>
{text} {text}
</Link> </Link>
); );

View File

@ -224,7 +224,7 @@ class App extends Component {
this.setLanguage(account); this.setLanguage(account);
} else { } else {
if (res.data !== "Please login first") { if (res.data !== "Please login first") {
Setting.showMessage("error", `Failed to sign in: ${res.msg}`); Setting.showMessage("error", `${i18next.t("application:Failed to sign in")}: ${res.msg}`);
} }
} }
@ -249,7 +249,7 @@ class App extends Component {
account: null, account: null,
}); });
Setting.showMessage("success", "Logged out successfully"); Setting.showMessage("success", i18next.t("application:Logged out successfully"));
const redirectUri = res.data2; const redirectUri = res.data2;
if (redirectUri !== null && redirectUri !== undefined && redirectUri !== "") { if (redirectUri !== null && redirectUri !== undefined && redirectUri !== "") {
Setting.goToLink(redirectUri); Setting.goToLink(redirectUri);

View File

@ -545,6 +545,16 @@ class ApplicationEditPage extends React.Component {
</Select> </Select>
</Col> </Col>
</Row> </Row>
<Row style={{marginTop: "20px"}} >
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
{Setting.getLabel(i18next.t("application:SAML Reply URL"), i18next.t("application:Redirect URL (Assertion Consumer Service POST Binding URL) - Tooltip"))} :
</Col>
<Col span={22} >
<Input prefix={<LinkOutlined />} value={this.state.application.samlReplyUrl} onChange={e => {
this.updateApplicationField("samlReplyUrl", e.target.value);
}} />
</Col>
</Row>
<Row style={{marginTop: "20px"}} > <Row style={{marginTop: "20px"}} >
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 19 : 2}> <Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 19 : 2}>
{Setting.getLabel(i18next.t("application:Enable SAML compress"), i18next.t("application:Enable SAML compress - Tooltip"))} : {Setting.getLabel(i18next.t("application:Enable SAML compress"), i18next.t("application:Enable SAML compress - Tooltip"))} :

View File

@ -197,9 +197,9 @@ class ApplicationListPage extends BaseListPage {
<List.Item> <List.Item>
<div style={{display: "inline"}}> <div style={{display: "inline"}}>
<Tooltip placement="topLeft" title="Edit"> <Tooltip placement="topLeft" title="Edit">
<Button style={{marginRight: "5px"}} icon={<EditOutlined />} size="small" onClick={() => Setting.goToLinkSoft(this, `/providers/${providerItem.name}`)} /> <Button style={{marginRight: "5px"}} icon={<EditOutlined />} size="small" onClick={() => Setting.goToLinkSoft(this, `/providers/${record.organization}/${providerItem.name}`)} />
</Tooltip> </Tooltip>
<Link to={`/providers/${providerItem.name}`}> <Link to={`/providers/${record.organization}/${providerItem.name}`}>
{providerItem.name} {providerItem.name}
</Link> </Link>
</div> </div>

View File

@ -13,7 +13,7 @@
// limitations under the License. // limitations under the License.
import React from "react"; import React from "react";
import {Button, Card, Col, Input, Row, Select, Switch} from "antd"; import {Button, Card, Col, Input, InputNumber, Row, Select, Switch} from "antd";
import * as OrganizationBackend from "./backend/OrganizationBackend"; import * as OrganizationBackend from "./backend/OrganizationBackend";
import * as ApplicationBackend from "./backend/ApplicationBackend"; import * as ApplicationBackend from "./backend/ApplicationBackend";
import * as LdapBackend from "./backend/LdapBackend"; import * as LdapBackend from "./backend/LdapBackend";
@ -86,7 +86,6 @@ class OrganizationEditPage extends React.Component {
updateOrganizationField(key, value) { updateOrganizationField(key, value) {
value = this.parseOrganizationField(key, value); value = this.parseOrganizationField(key, value);
const organization = this.state.organization; const organization = this.state.organization;
organization[key] = value; organization[key] = value;
this.setState({ this.setState({
@ -280,6 +279,16 @@ class OrganizationEditPage extends React.Component {
</Select> </Select>
</Col> </Col>
</Row> </Row>
<Row style={{marginTop: "20px"}} >
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 19 : 2}>
{Setting.getLabel(i18next.t("organization:InitScore"), i18next.t("organization:The user's initScore - Tooltip"))} :
</Col>
<Col span={4} >
<InputNumber value={this.state.organization.initScore} onChange={value => {
this.updateOrganizationField("initScore", value);
}} />
</Col>
</Row>
<Row style={{marginTop: "20px"}} > <Row style={{marginTop: "20px"}} >
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 19 : 2}> <Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 19 : 2}>
{Setting.getLabel(i18next.t("organization:Soft deletion"), i18next.t("organization:Soft deletion - Tooltip"))} : {Setting.getLabel(i18next.t("organization:Soft deletion"), i18next.t("organization:Soft deletion - Tooltip"))} :

View File

@ -13,7 +13,8 @@
// limitations under the License. // limitations under the License.
import React from "react"; import React from "react";
import {Button, Descriptions, Spin} from "antd"; import {Button, Descriptions, Modal, Spin} from "antd";
import {CheckCircleTwoTone} from "@ant-design/icons";
import i18next from "i18next"; import i18next from "i18next";
import * as ProductBackend from "./backend/ProductBackend"; import * as ProductBackend from "./backend/ProductBackend";
import * as Setting from "./Setting"; import * as Setting from "./Setting";
@ -26,6 +27,7 @@ class ProductBuyPage extends React.Component {
productName: props.match?.params.productName, productName: props.match?.params.productName,
product: null, product: null,
isPlacingOrder: false, isPlacingOrder: false,
qrCodeModalProvider: null,
}; };
} }
@ -34,6 +36,10 @@ class ProductBuyPage extends React.Component {
} }
getProduct() { getProduct() {
if (this.state.productName === undefined) {
return;
}
ProductBackend.getProduct("admin", this.state.productName) ProductBackend.getProduct("admin", this.state.productName)
.then((product) => { .then((product) => {
this.setState({ this.setState({
@ -75,6 +81,13 @@ class ProductBuyPage extends React.Component {
} }
buyProduct(product, provider) { buyProduct(product, provider) {
if (provider.clientId.startsWith("http")) {
this.setState({
qrCodeModalProvider: provider,
});
return;
}
this.setState({ this.setState({
isPlacingOrder: true, isPlacingOrder: true,
}); });
@ -97,6 +110,45 @@ class ProductBuyPage extends React.Component {
}); });
} }
renderQrCodeModal() {
if (this.state.qrCodeModalProvider === undefined || this.state.qrCodeModalProvider === null) {
return null;
}
return (
<Modal title={
<div>
<CheckCircleTwoTone twoToneColor="rgb(45,120,213)" />
{" " + i18next.t("product:Please scan the QR code to pay")}
</div>
}
open={this.state.qrCodeModalProvider !== undefined && this.state.qrCodeModalProvider !== null}
onOk={() => {
Setting.goToLink(this.state.product.returnUrl);
}}
onCancel={() => {
this.setState({
qrCodeModalProvider: null,
});
}}
okText={i18next.t("product:I have completed the payment")}
cancelText={i18next.t("general:Cancel")}>
<p key={this.state.qrCodeModalProvider?.name}>
{
i18next.t("product:Please provide your username in the remark")
}
:&nbsp;&nbsp;
{
Setting.getTag("default", this.props.account.name)
}
<br />
<br />
<img src={this.state.qrCodeModalProvider?.clientId} alt={this.state.qrCodeModalProvider?.name} width={"472px"} style={{marginBottom: "20px"}} />
</p>
</Modal>
);
}
getPayButton(provider) { getPayButton(provider) {
let text = provider.type; let text = provider.type;
if (provider.type === "Alipay") { if (provider.type === "Alipay") {
@ -185,6 +237,9 @@ class ProductBuyPage extends React.Component {
</Descriptions.Item> </Descriptions.Item>
</Descriptions> </Descriptions>
</Spin> </Spin>
{
this.renderQrCodeModal()
}
</div> </div>
); );
} }

View File

@ -153,6 +153,16 @@ class ProductEditPage extends React.Component {
}} /> }} />
</Col> </Col>
</Row> </Row>
<Row style={{marginTop: "20px"}} >
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
{Setting.getLabel(i18next.t("product:Description"), i18next.t("product:Description - Tooltip"))} :
</Col>
<Col span={22} >
<Input value={this.state.product.description} onChange={e => {
this.updateProductField("description", e.target.value);
}} />
</Col>
</Row>
<Row style={{marginTop: "20px"}} > <Row style={{marginTop: "20px"}} >
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}> <Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
{Setting.getLabel(i18next.t("product:Currency"), i18next.t("product:Currency - Tooltip"))} : {Setting.getLabel(i18next.t("product:Currency"), i18next.t("product:Currency - Tooltip"))} :

View File

@ -92,6 +92,7 @@ export const ResetModal = (props) => {
<CountDownInput <CountDownInput
textBefore={i18next.t("code:Code You Received")} textBefore={i18next.t("code:Code You Received")}
onChange={setCode} onChange={setCode}
method={"reset"}
onButtonClickArgs={[dest, destType, Setting.getApplicationName(application)]} onButtonClickArgs={[dest, destType, Setting.getApplicationName(application)]}
application={application} application={application}
/> />

View File

@ -113,7 +113,7 @@ class ResourceListPage extends BaseListPage {
...this.getColumnSearchProps("application"), ...this.getColumnSearchProps("application"),
render: (text, record, index) => { render: (text, record, index) => {
return ( return (
<Link to={`/applications/${text}`}> <Link to={`/applications/${record.organization}/${text}`}>
{text} {text}
</Link> </Link>
); );

View File

@ -14,7 +14,7 @@
import React from "react"; import React from "react";
import * as Setting from "./Setting"; import * as Setting from "./Setting";
import {Dropdown, Menu} from "antd"; import {Dropdown} from "antd";
import "./App.less"; import "./App.less";
function flagIcon(country, alt) { function flagIcon(country, alt) {
@ -32,16 +32,7 @@ class SelectLanguageBox extends React.Component {
}; };
} }
items = [ items = Setting.Countries.map((country) => Setting.getItem(country.label, country.key, flagIcon(country.country, country.alt)));
Setting.getItem("English", "en", flagIcon("US", "English")),
Setting.getItem("简体中文", "zh", flagIcon("CN", "简体中文")),
Setting.getItem("Español", "es", flagIcon("ES", "Español")),
Setting.getItem("Français", "fr", flagIcon("FR", "Français")),
Setting.getItem("Deutsch", "de", flagIcon("DE", "Deutsch")),
Setting.getItem("日本語", "ja", flagIcon("JP", "日本語")),
Setting.getItem("한국어", "ko", flagIcon("KR", "한국어")),
Setting.getItem("Русский", "ru", flagIcon("RU", "Русский")),
];
getOrganizationLanguages(languages) { getOrganizationLanguages(languages) {
const select = []; const select = [];
@ -53,15 +44,12 @@ class SelectLanguageBox extends React.Component {
render() { render() {
const languageItems = this.getOrganizationLanguages(this.state.languages); const languageItems = this.getOrganizationLanguages(this.state.languages);
const menu = ( const onClick = (e) => {
<Menu items={languageItems} onClick={(e) => { Setting.setLanguage(e.key);
Setting.setLanguage(e.key); };
}}>
</Menu>
);
return ( return (
<Dropdown overlay={menu} > <Dropdown menu={{items: languageItems, onClick}} >
<div className="language-box" style={{display: languageItems.length === 0 ? "none" : null, ...this.props.style}} /> <div className="language-box" style={{display: languageItems.length === 0 ? "none" : null, ...this.props.style}} />
</Dropdown> </Dropdown>
); );

View File

@ -42,12 +42,15 @@ class SelectRegionBox extends React.Component {
placeholder="Please select country/region" placeholder="Please select country/region"
onChange={(value => {this.onChange(value);})} onChange={(value => {this.onChange(value);})}
filterOption={(input, option) => filterOption={(input, option) =>
option.label.indexOf(input) >= 0 (option?.label ?? "").toLowerCase().includes(input.toLowerCase())
}
filterSort={(optionA, optionB) =>
(optionA?.label ?? "").toLowerCase().localeCompare((optionB?.label ?? "").toLowerCase())
} }
> >
{ {
Setting.CountryRegionData.map((item, index) => ( Setting.CountryRegionData.map((item, index) => (
<Option key={index} value={item.code} label={item.code} > <Option key={index} value={item.code} label={`${item.name} (${item.code})`} >
<img src={`${Setting.StaticBaseUrl}/flag-icons/${item.code}.svg`} alt={item.name} height={20} style={{marginRight: 10}} /> <img src={`${Setting.StaticBaseUrl}/flag-icons/${item.code}.svg`} alt={item.name} height={20} style={{marginRight: 10}} />
{`${item.name} (${item.code})`} {`${item.name} (${item.code})`}
</Option> </Option>

View File

@ -33,6 +33,16 @@ export const StaticBaseUrl = "https://cdn.casbin.org";
// https://catamphetamine.gitlab.io/country-flag-icons/3x2/index.html // https://catamphetamine.gitlab.io/country-flag-icons/3x2/index.html
export const CountryRegionData = getCountryRegionData(); export const CountryRegionData = getCountryRegionData();
export const Countries = [{label: "English", key: "en", country: "US", alt: "English"},
{label: "简体中文", key: "zh", country: "CN", alt: "简体中文"},
{label: "Español", key: "es", country: "ES", alt: "Español"},
{label: "Français", key: "fr", country: "FR", alt: "Français"},
{label: "Deutsch", key: "de", country: "DE", alt: "Deutsch"},
{label: "日本語", key: "ja", country: "JP", alt: "日本語"},
{label: "한국어", key: "ko", country: "KR", alt: "한국어"},
{label: "Русский", key: "ru", country: "RU", alt: "Русский"},
];
export const OtherProviderInfo = { export const OtherProviderInfo = {
SMS: { SMS: {
"Aliyun SMS": { "Aliyun SMS": {
@ -251,8 +261,10 @@ export function isValidPersonName(personName) {
} }
export function isValidIdCard(idCard) { export function isValidIdCard(idCard) {
const idCardRegex = /^[1-9]\d{5}(18|19|20)\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[0-9X]$/; return idCard !== "";
return idCardRegex.test(idCard);
// const idCardRegex = /^[1-9]\d{5}(18|19|20)\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[0-9X]$/;
// return idCardRegex.test(idCard);
} }
export function isValidEmail(email) { export function isValidEmail(email) {
@ -262,34 +274,40 @@ export function isValidEmail(email) {
} }
export function isValidPhone(phone) { export function isValidPhone(phone) {
if (phone === "") { return phone !== "";
return false;
}
// https://learnku.com/articles/31543, `^s*$` filter empty email individually. // if (phone === "") {
const phoneRegex = /^\s*$|^1(3\d|4[5-9]|5[0-35-9]|6[2567]|7[0-8]|8\d|9[0-35-9])\d{8}$/; // return false;
return phoneRegex.test(phone); // }
//
// // https://learnku.com/articles/31543, `^s*$` filter empty email individually.
// const phoneRegex = /^\s*$|^1(3\d|4[5-9]|5[0-35-9]|6[2567]|7[0-8]|8\d|9[0-35-9])\d{8}$/;
// return phoneRegex.test(phone);
} }
export function isValidInvoiceTitle(invoiceTitle) { export function isValidInvoiceTitle(invoiceTitle) {
if (invoiceTitle === "") { return invoiceTitle !== "";
return false;
}
// https://blog.css8.cn/post/14210975.html // if (invoiceTitle === "") {
const invoiceTitleRegex = /^[()\u4e00-\u9fa5]{0,50}$/; // return false;
return invoiceTitleRegex.test(invoiceTitle); // }
//
// // https://blog.css8.cn/post/14210975.html
// const invoiceTitleRegex = /^[()\u4e00-\u9fa5]{0,50}$/;
// return invoiceTitleRegex.test(invoiceTitle);
} }
export function isValidTaxId(taxId) { export function isValidTaxId(taxId) {
// https://www.codetd.com/article/8592083 return taxId !== "";
const regArr = [/^[\da-z]{10,15}$/i, /^\d{6}[\da-z]{10,12}$/i, /^[a-z]\d{6}[\da-z]{9,11}$/i, /^[a-z]{2}\d{6}[\da-z]{8,10}$/i, /^\d{14}[\dx][\da-z]{4,5}$/i, /^\d{17}[\dx][\da-z]{1,2}$/i, /^[a-z]\d{14}[\dx][\da-z]{3,4}$/i, /^[a-z]\d{17}[\dx][\da-z]{0,1}$/i, /^[\d]{6}[\da-z]{13,14}$/i];
for (let i = 0; i < regArr.length; i++) { // // https://www.codetd.com/article/8592083
if (regArr[i].test(taxId)) { // const regArr = [/^[\da-z]{10,15}$/i, /^\d{6}[\da-z]{10,12}$/i, /^[a-z]\d{6}[\da-z]{9,11}$/i, /^[a-z]{2}\d{6}[\da-z]{8,10}$/i, /^\d{14}[\dx][\da-z]{4,5}$/i, /^\d{17}[\dx][\da-z]{1,2}$/i, /^[a-z]\d{14}[\dx][\da-z]{3,4}$/i, /^[a-z]\d{17}[\dx][\da-z]{0,1}$/i, /^[\d]{6}[\da-z]{13,14}$/i];
return true; // for (let i = 0; i < regArr.length; i++) {
} // if (regArr[i].test(taxId)) {
} // return true;
return false; // }
// }
// return false;
} }
export function isAffiliationPrompted(application) { export function isAffiliationPrompted(application) {

View File

@ -62,6 +62,7 @@ class UserListPage extends BaseListPage {
isAdmin: (owner === "built-in"), isAdmin: (owner === "built-in"),
isGlobalAdmin: (owner === "built-in"), isGlobalAdmin: (owner === "built-in"),
IsForbidden: false, IsForbidden: false,
score: this.state.organization.initScore,
isDeleted: false, isDeleted: false,
properties: {}, properties: {},
signupApplication: "app-built-in", signupApplication: "app-built-in",

View File

@ -355,12 +355,14 @@ class ForgetPage extends React.Component {
{this.state.verifyType === "email" ? ( {this.state.verifyType === "email" ? (
<CountDownInput <CountDownInput
disabled={this.state.username === "" || this.state.verifyType === ""} disabled={this.state.username === "" || this.state.verifyType === ""}
method={"forget"}
onButtonClickArgs={[this.state.email, "email", Setting.getApplicationName(this.state.application), this.state.name]} onButtonClickArgs={[this.state.email, "email", Setting.getApplicationName(this.state.application), this.state.name]}
application={application} application={application}
/> />
) : ( ) : (
<CountDownInput <CountDownInput
disabled={this.state.username === "" || this.state.verifyType === ""} disabled={this.state.username === "" || this.state.verifyType === ""}
method={"forget"}
onButtonClickArgs={[this.state.phone, "phone", Setting.getApplicationName(this.state.application), this.state.name]} onButtonClickArgs={[this.state.phone, "phone", Setting.getApplicationName(this.state.application), this.state.name]}
application={application} application={application}
/> />

View File

@ -29,6 +29,7 @@ import CustomGithubCorner from "../CustomGithubCorner";
import {CountDownInput} from "../common/CountDownInput"; import {CountDownInput} from "../common/CountDownInput";
import SelectLanguageBox from "../SelectLanguageBox"; import SelectLanguageBox from "../SelectLanguageBox";
import {CaptchaModal} from "../common/CaptchaModal"; import {CaptchaModal} from "../common/CaptchaModal";
import RedirectForm from "../common/RedirectForm";
class LoginPage extends React.Component { class LoginPage extends React.Component {
constructor(props) { constructor(props) {
@ -49,6 +50,9 @@ class LoginPage extends React.Component {
enableCaptchaModal: false, enableCaptchaModal: false,
openCaptchaModal: false, openCaptchaModal: false,
verifyCaptcha: undefined, verifyCaptcha: undefined,
samlResponse: "",
relayState: "",
redirectUrl: "",
}; };
if (this.state.type === "cas" && props.match?.params.casApplicationName !== undefined) { if (this.state.type === "cas" && props.match?.params.casApplicationName !== undefined) {
@ -69,6 +73,12 @@ class LoginPage extends React.Component {
} }
} }
componentDidMount() {
Setting.Countries.forEach((country) => {
new Image().src = `${Setting.StaticBaseUrl}/flag-icons/${country.country}.svg`;
});
}
componentDidUpdate(prevProps, prevState, snapshot) { componentDidUpdate(prevProps, prevState, snapshot) {
if (this.state.application && !prevState.application) { if (this.state.application && !prevState.application) {
const defaultCaptchaProviderItems = this.getDefaultCaptchaProviderItems(this.state.application); const defaultCaptchaProviderItems = this.getDefaultCaptchaProviderItems(this.state.application);
@ -178,6 +188,7 @@ class LoginPage extends React.Component {
if (values["samlRequest"] !== null && values["samlRequest"] !== "" && values["samlRequest"] !== undefined) { if (values["samlRequest"] !== null && values["samlRequest"] !== "" && values["samlRequest"] !== undefined) {
values["type"] = "saml"; values["type"] = "saml";
values["relayState"] = oAuthParams.relayState;
} }
if (this.state.application.organization !== null && this.state.application.organization !== undefined) { if (this.state.application.organization !== null && this.state.application.organization !== undefined) {
@ -293,7 +304,7 @@ class LoginPage extends React.Component {
const responseType = values["type"]; const responseType = values["type"];
if (responseType === "login") { if (responseType === "login") {
Setting.showMessage("success", "Logged in successfully"); Setting.showMessage("success", i18next.t("application:Logged in successfully"));
const link = Setting.getFromLink(); const link = Setting.getFromLink();
Setting.goToLink(link); Setting.goToLink(link);
@ -306,7 +317,15 @@ class LoginPage extends React.Component {
} else if (responseType === "saml") { } else if (responseType === "saml") {
const SAMLResponse = res.data; const SAMLResponse = res.data;
const redirectUri = res.data2; const redirectUri = res.data2;
Setting.goToLink(`${redirectUri}?SAMLResponse=${encodeURIComponent(SAMLResponse)}&RelayState=${oAuthParams.relayState}`); if (this.state.application.assertionConsumerUrl !== "") {
this.setState({
samlResponse: res.data,
redirectUrl: res.data2,
relayState: oAuthParams.relayState,
});
} else {
Setting.goToLink(`${redirectUri}?SAMLResponse=${encodeURIComponent(SAMLResponse)}&RelayState=${oAuthParams.relayState}`);
}
} }
} else { } else {
this.setState({openCaptchaModal: false}); this.setState({openCaptchaModal: false});
@ -655,7 +674,7 @@ class LoginPage extends React.Component {
const rawId = assertion.rawId; const rawId = assertion.rawId;
const sig = assertion.response.signature; const sig = assertion.response.signature;
const userHandle = assertion.response.userHandle; const userHandle = assertion.response.userHandle;
return fetch(`${Setting.ServerUrl}/api/webauthn/signin/finish${AuthBackend.oAuthParamsToQuery(oAuthParams)}`, { return fetch(`${Setting.ServerUrl}/api/webauthn/signin/finish?responseType=${values["type"]}`, {
method: "POST", method: "POST",
credentials: "include", credentials: "include",
body: JSON.stringify({ body: JSON.stringify({
@ -719,6 +738,7 @@ class LoginPage extends React.Component {
> >
<CountDownInput <CountDownInput
disabled={this.state.username?.length === 0 || !this.state.validEmailOrPhone} disabled={this.state.username?.length === 0 || !this.state.validEmailOrPhone}
method={"login"}
onButtonClickArgs={[this.state.username, this.state.validEmail ? "email" : "phone", Setting.getApplicationName(application)]} onButtonClickArgs={[this.state.username, this.state.validEmail ? "email" : "phone", Setting.getApplicationName(application)]}
application={application} application={application}
/> />
@ -754,6 +774,10 @@ class LoginPage extends React.Component {
return Util.renderMessageLarge(this, this.state.msg); return Util.renderMessageLarge(this, this.state.msg);
} }
if (this.state.samlResponse !== "") {
return <RedirectForm samlResponse={this.state.samlResponse} redirectUrl={this.state.redirectUrl} relayState={this.state.relayState} />;
}
if (application.signinHtml !== "") { if (application.signinHtml !== "") {
return ( return (
<div dangerouslySetInnerHTML={{__html: application.signinHtml}} /> <div dangerouslySetInnerHTML={{__html: application.signinHtml}} />

View File

@ -373,6 +373,7 @@ class SignupPage extends React.Component {
> >
<CountDownInput <CountDownInput
disabled={!this.state.validEmail} disabled={!this.state.validEmail}
method={"signup"}
onButtonClickArgs={[this.state.email, "email", Setting.getApplicationName(application)]} onButtonClickArgs={[this.state.email, "email", Setting.getApplicationName(application)]}
application={application} application={application}
/> />
@ -426,6 +427,7 @@ class SignupPage extends React.Component {
> >
<CountDownInput <CountDownInput
disabled={!this.state.validPhone} disabled={!this.state.validPhone}
method={"signup"}
onButtonClickArgs={[this.state.phone, "phone", Setting.getApplicationName(application)]} onButtonClickArgs={[this.state.phone, "phone", Setting.getApplicationName(application)]}
application={application} application={application}
/> />

View File

@ -109,11 +109,12 @@ export function setPassword(userOwner, userName, oldPassword, newPassword) {
}).then(res => res.json()); }).then(res => res.json());
} }
export function sendCode(checkType, checkId, checkKey, dest, type, applicationId, checkUser) { export function sendCode(checkType, checkId, checkKey, method, dest, type, applicationId, checkUser) {
const formData = new FormData(); const formData = new FormData();
formData.append("checkType", checkType); formData.append("checkType", checkType);
formData.append("checkId", checkId); formData.append("checkId", checkId);
formData.append("checkKey", checkKey); formData.append("checkKey", checkKey);
formData.append("method", method);
formData.append("dest", dest); formData.append("dest", dest);
formData.append("type", type); formData.append("type", type);
formData.append("applicationId", applicationId); formData.append("applicationId", applicationId);

View File

@ -125,5 +125,5 @@ export const CaptchaWidget = ({captchaType, subType, siteKey, clientSecret, onCh
} }
}, [captchaType, subType, siteKey, clientSecret, clientId2, clientSecret2]); }, [captchaType, subType, siteKey, clientSecret, clientId2, clientSecret2]);
return <div id="captcha"></div>; return <div id="captcha" />;
}; };

View File

@ -22,7 +22,7 @@ import {CaptchaWidget} from "./CaptchaWidget";
const {Search} = Input; const {Search} = Input;
export const CountDownInput = (props) => { export const CountDownInput = (props) => {
const {disabled, textBefore, onChange, onButtonClickArgs, application} = props; const {disabled, textBefore, onChange, onButtonClickArgs, application, method} = props;
const [visible, setVisible] = React.useState(false); const [visible, setVisible] = React.useState(false);
const [key, setKey] = React.useState(""); const [key, setKey] = React.useState("");
const [captchaImg, setCaptchaImg] = React.useState(""); const [captchaImg, setCaptchaImg] = React.useState("");
@ -53,7 +53,7 @@ export const CountDownInput = (props) => {
const handleOk = () => { const handleOk = () => {
setVisible(false); setVisible(false);
setButtonLoading(true); setButtonLoading(true);
UserBackend.sendCode(checkType, checkId, key, ...onButtonClickArgs).then(res => { UserBackend.sendCode(checkType, checkId, key, method, ...onButtonClickArgs).then(res => {
setKey(""); setKey("");
setButtonLoading(false); setButtonLoading(false);
if (res) { if (res) {
@ -70,7 +70,7 @@ export const CountDownInput = (props) => {
const loadCaptcha = () => { const loadCaptcha = () => {
UserBackend.getCaptcha(application.owner, application.name, false).then(res => { UserBackend.getCaptcha(application.owner, application.name, false).then(res => {
if (res.type === "none") { if (res.type === "none") {
UserBackend.sendCode("none", "", "", ...onButtonClickArgs).then(res => { UserBackend.sendCode("none", "", "", method, ...onButtonClickArgs).then(res => {
if (res) { if (res) {
handleCountDown(60); handleCountDown(60);
} }

View File

@ -164,7 +164,7 @@ class OAuthWidget extends React.Component {
</span> </span>
{ {
linkedValue === "" ? ( linkedValue === "" ? (
<a key={provider.displayName} href={Provider.getAuthUrl(application, provider, "link")}> <a key={provider.displayName} href={user.id !== account.id ? null : Provider.getAuthUrl(application, provider, "link")}>
<Button style={{marginLeft: "20px", width: "80px"}} type="primary" disabled={user.id !== account.id}>{i18next.t("user:Link")}</Button> <Button style={{marginLeft: "20px", width: "80px"}} type="primary" disabled={user.id !== account.id}>{i18next.t("user:Link")}</Button>
</a> </a>
) : ( ) : (

View File

@ -91,7 +91,8 @@ class PolicyTable extends React.Component {
AdapterBackend.syncPolicies(this.props.owner, this.props.name) AdapterBackend.syncPolicies(this.props.owner, this.props.name)
.then((res) => { .then((res) => {
if (res.status === "ok") { if (res.status === "ok") {
this.setState({policyLists: res}); this.setState({policyLists: res.data});
Setting.showMessage("success", i18next.t("adapter:Sync policies successfully"));
} else { } else {
Setting.showMessage("error", `${i18next.t("adapter:Failed to sync policies")}: ${res.msg}`); Setting.showMessage("error", `${i18next.t("adapter:Failed to sync policies")}: ${res.msg}`);
} }
@ -293,7 +294,7 @@ class PolicyTable extends React.Component {
render() { render() {
return (<> return (<>
<Button type="primary" onClick={() => {this.synPolicies();}}> <Button type="primary" disabled={this.state.editingIndex !== ""} onClick={() => {this.synPolicies();}}>
{i18next.t("adapter:Sync")} {i18next.t("adapter:Sync")}
</Button> </Button>
{ {

View File

@ -0,0 +1,43 @@
// Copyright 2022 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, {useEffect} from "react";
export const RedirectForm = (props) => {
useEffect(() => {
document.getElementById("saml").submit();
}, []);
return (<>
<p>Redirecting, please wait.</p>
<form id="saml" method="post" action={props.redirectUrl}>
<input
type="hidden"
name="SAMLResponse"
id="samlResponse"
value={props.samlResponse}
/>
<input
type="hidden"
name="RelayState"
id="relayState"
value={props.relayState}
/>
</form>
</>
);
};
export default RedirectForm;

View File

@ -7,12 +7,13 @@
}, },
"adapter": { "adapter": {
"Edit Adapter": "Edit Adapter", "Edit Adapter": "Edit Adapter",
"Failed to sync policies: ": "Failed to sync policies: ", "Failed to sync policies": "Failed to sync policies",
"New Adapter": "New Adapter", "New Adapter": "New Adapter",
"Policies": "Policies", "Policies": "Policies",
"Policies - Tooltip": "Policies - Tooltip", "Policies - Tooltip": "Policies - Tooltip",
"Repeated policy rules": "Repeated policy rules", "Repeated policy rules": "Repeated policy rules",
"Sync": "Sync" "Sync": "Sync",
"Sync policies successfully": "Sync policies successfully"
}, },
"application": { "application": {
"Always": "Always", "Always": "Always",
@ -36,6 +37,7 @@
"Enable signin session - Tooltip": "Aktiviere Anmeldesession - Tooltip", "Enable signin session - Tooltip": "Aktiviere Anmeldesession - Tooltip",
"Enable signup": "Anmeldung aktivieren", "Enable signup": "Anmeldung aktivieren",
"Enable signup - Tooltip": "Whether to allow users to sign up", "Enable signup - Tooltip": "Whether to allow users to sign up",
"Failed to sign in": "Failed to sign in",
"File uploaded successfully": "Datei erfolgreich hochgeladen", "File uploaded successfully": "Datei erfolgreich hochgeladen",
"Form CSS": "Form CSS", "Form CSS": "Form CSS",
"Form CSS - Edit": "Form CSS - Edit", "Form CSS - Edit": "Form CSS - Edit",
@ -45,6 +47,8 @@
"Grant types": "Grant types", "Grant types": "Grant types",
"Grant types - Tooltip": "Grant types - Tooltip", "Grant types - Tooltip": "Grant types - Tooltip",
"Left": "Left", "Left": "Left",
"Logged in successfully": "Logged in successfully",
"Logged out successfully": "Logged out successfully",
"New Application": "New Application", "New Application": "New Application",
"None": "None", "None": "None",
"Password ON": "Passwort AN", "Password ON": "Passwort AN",
@ -54,12 +58,14 @@
"Please select a HTML file": "Bitte wählen Sie eine HTML-Datei", "Please select a HTML file": "Bitte wählen Sie eine HTML-Datei",
"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", "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",
"Redirect URL": "Weiterleitungs-URL", "Redirect URL": "Weiterleitungs-URL",
"Redirect URL (Assertion Consumer Service POST Binding URL) - Tooltip": "Redirect URL (Assertion Consumer Service POST Binding URL) - Tooltip",
"Redirect URLs": "Umleitungs-URLs", "Redirect URLs": "Umleitungs-URLs",
"Redirect URLs - Tooltip": "List of redirect addresses after successful login", "Redirect URLs - Tooltip": "List of redirect addresses after successful login",
"Refresh token expire": "Aktualisierungs-Token läuft ab", "Refresh token expire": "Aktualisierungs-Token läuft ab",
"Refresh token expire - Tooltip": "Aktualisierungs-Token läuft ab - Tooltip", "Refresh token expire - Tooltip": "Aktualisierungs-Token läuft ab - Tooltip",
"Right": "Right", "Right": "Right",
"Rule": "Rule", "Rule": "Rule",
"SAML Reply URL": "SAML Reply URL",
"SAML metadata": "SAML metadata", "SAML metadata": "SAML metadata",
"SAML metadata - Tooltip": "SAML metadata - Tooltip", "SAML metadata - Tooltip": "SAML metadata - Tooltip",
"SAML metadata URL copied to clipboard successfully": "SAML metadata URL copied to clipboard successfully", "SAML metadata URL copied to clipboard successfully": "SAML metadata URL copied to clipboard successfully",
@ -326,6 +332,7 @@
"Default avatar": "Standard Avatar", "Default avatar": "Standard Avatar",
"Edit Organization": "Organisation bearbeiten", "Edit Organization": "Organisation bearbeiten",
"Favicon": "Févicon", "Favicon": "Févicon",
"InitScore": "InitScore",
"Is profile public": "Is profile public", "Is profile public": "Is profile public",
"Is profile public - Tooltip": "Is profile public - Tooltip", "Is profile public - Tooltip": "Is profile public - Tooltip",
"Modify rule": "Modify rule", "Modify rule": "Modify rule",
@ -334,6 +341,7 @@
"Soft deletion - Tooltip": "Weiche Löschung - Tooltip", "Soft deletion - Tooltip": "Weiche Löschung - Tooltip",
"Tags": "Tags", "Tags": "Tags",
"Tags - Tooltip": "Tags - Tooltip", "Tags - Tooltip": "Tags - Tooltip",
"The user's initScore - Tooltip": "The user's initScore - Tooltip",
"View rule": "View rule", "View rule": "View rule",
"Visible": "Visible", "Visible": "Visible",
"Website URL": "Website-URL", "Website URL": "Website-URL",
@ -426,9 +434,12 @@
"CNY": "CNY", "CNY": "CNY",
"Currency": "Currency", "Currency": "Currency",
"Currency - Tooltip": "Currency - Tooltip", "Currency - Tooltip": "Currency - Tooltip",
"Description": "Description",
"Description - Tooltip": "Description - Tooltip",
"Detail": "Detail", "Detail": "Detail",
"Detail - Tooltip": "Detail - Tooltip", "Detail - Tooltip": "Detail - Tooltip",
"Edit Product": "Edit Product", "Edit Product": "Edit Product",
"I have completed the payment": "I have completed the payment",
"Image": "Image", "Image": "Image",
"Image - Tooltip": "Image - Tooltip", "Image - Tooltip": "Image - Tooltip",
"New Product": "New Product", "New Product": "New Product",
@ -437,6 +448,8 @@
"Payment providers - Tooltip": "Payment providers - Tooltip", "Payment providers - Tooltip": "Payment providers - Tooltip",
"Paypal": "Paypal", "Paypal": "Paypal",
"Placing order...": "Placing order...", "Placing order...": "Placing order...",
"Please provide your username in the remark": "Please provide your username in the remark",
"Please scan the QR code to pay": "Please scan the QR code to pay",
"Price": "Price", "Price": "Price",
"Price - Tooltip": "Price - Tooltip", "Price - Tooltip": "Price - Tooltip",
"Quantity": "Quantity", "Quantity": "Quantity",

View File

@ -7,12 +7,13 @@
}, },
"adapter": { "adapter": {
"Edit Adapter": "Edit Adapter", "Edit Adapter": "Edit Adapter",
"Failed to sync policies: ": "Failed to sync policies: ", "Failed to sync policies": "Failed to sync policies",
"New Adapter": "New Adapter", "New Adapter": "New Adapter",
"Policies": "Policies", "Policies": "Policies",
"Policies - Tooltip": "Policies - Tooltip", "Policies - Tooltip": "Policies - Tooltip",
"Repeated policy rules": "Repeated policy rules", "Repeated policy rules": "Repeated policy rules",
"Sync": "Sync" "Sync": "Sync",
"Sync policies successfully": "Sync policies successfully"
}, },
"application": { "application": {
"Always": "Always", "Always": "Always",
@ -36,6 +37,7 @@
"Enable signin session - Tooltip": "Enable signin session - Tooltip", "Enable signin session - Tooltip": "Enable signin session - Tooltip",
"Enable signup": "Enable signup", "Enable signup": "Enable signup",
"Enable signup - Tooltip": "Enable signup - Tooltip", "Enable signup - Tooltip": "Enable signup - Tooltip",
"Failed to sign in": "Failed to sign in",
"File uploaded successfully": "File uploaded successfully", "File uploaded successfully": "File uploaded successfully",
"Form CSS": "Form CSS", "Form CSS": "Form CSS",
"Form CSS - Edit": "Form CSS - Edit", "Form CSS - Edit": "Form CSS - Edit",
@ -45,6 +47,8 @@
"Grant types": "Grant types", "Grant types": "Grant types",
"Grant types - Tooltip": "Grant types - Tooltip", "Grant types - Tooltip": "Grant types - Tooltip",
"Left": "Left", "Left": "Left",
"Logged in successfully": "Logged in successfully",
"Logged out successfully": "Logged out successfully",
"New Application": "New Application", "New Application": "New Application",
"None": "None", "None": "None",
"Password ON": "Password ON", "Password ON": "Password ON",
@ -54,12 +58,14 @@
"Please select a HTML file": "Please select a HTML file", "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", "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",
"Redirect URL": "Redirect URL", "Redirect URL": "Redirect URL",
"Redirect URL (Assertion Consumer Service POST Binding URL) - Tooltip": "Redirect URL (Assertion Consumer Service POST Binding URL) - Tooltip",
"Redirect URLs": "Redirect URLs", "Redirect URLs": "Redirect URLs",
"Redirect URLs - Tooltip": "Redirect URLs - Tooltip", "Redirect URLs - Tooltip": "Redirect URLs - Tooltip",
"Refresh token expire": "Refresh token expire", "Refresh token expire": "Refresh token expire",
"Refresh token expire - Tooltip": "Refresh token expire - Tooltip", "Refresh token expire - Tooltip": "Refresh token expire - Tooltip",
"Right": "Right", "Right": "Right",
"Rule": "Rule", "Rule": "Rule",
"SAML Reply URL": "SAML Reply URL",
"SAML metadata": "SAML metadata", "SAML metadata": "SAML metadata",
"SAML metadata - Tooltip": "SAML metadata - Tooltip", "SAML metadata - Tooltip": "SAML metadata - Tooltip",
"SAML metadata URL copied to clipboard successfully": "SAML metadata URL copied to clipboard successfully", "SAML metadata URL copied to clipboard successfully": "SAML metadata URL copied to clipboard successfully",
@ -326,6 +332,7 @@
"Default avatar": "Default avatar", "Default avatar": "Default avatar",
"Edit Organization": "Edit Organization", "Edit Organization": "Edit Organization",
"Favicon": "Favicon", "Favicon": "Favicon",
"InitScore": "InitScore",
"Is profile public": "Is profile public", "Is profile public": "Is profile public",
"Is profile public - Tooltip": "Is profile public - Tooltip", "Is profile public - Tooltip": "Is profile public - Tooltip",
"Modify rule": "Modify rule", "Modify rule": "Modify rule",
@ -334,6 +341,7 @@
"Soft deletion - Tooltip": "Soft deletion - Tooltip", "Soft deletion - Tooltip": "Soft deletion - Tooltip",
"Tags": "Tags", "Tags": "Tags",
"Tags - Tooltip": "Tags - Tooltip", "Tags - Tooltip": "Tags - Tooltip",
"The user's initScore - Tooltip": "The user's initScore - Tooltip",
"View rule": "View rule", "View rule": "View rule",
"Visible": "Visible", "Visible": "Visible",
"Website URL": "Website URL", "Website URL": "Website URL",
@ -426,9 +434,12 @@
"CNY": "CNY", "CNY": "CNY",
"Currency": "Currency", "Currency": "Currency",
"Currency - Tooltip": "Currency - Tooltip", "Currency - Tooltip": "Currency - Tooltip",
"Description": "Description",
"Description - Tooltip": "Description - Tooltip",
"Detail": "Detail", "Detail": "Detail",
"Detail - Tooltip": "Detail - Tooltip", "Detail - Tooltip": "Detail - Tooltip",
"Edit Product": "Edit Product", "Edit Product": "Edit Product",
"I have completed the payment": "I have completed the payment",
"Image": "Image", "Image": "Image",
"Image - Tooltip": "Image - Tooltip", "Image - Tooltip": "Image - Tooltip",
"New Product": "New Product", "New Product": "New Product",
@ -437,6 +448,8 @@
"Payment providers - Tooltip": "Payment providers - Tooltip", "Payment providers - Tooltip": "Payment providers - Tooltip",
"Paypal": "Paypal", "Paypal": "Paypal",
"Placing order...": "Placing order...", "Placing order...": "Placing order...",
"Please provide your username in the remark": "Please provide your username in the remark",
"Please scan the QR code to pay": "Please scan the QR code to pay",
"Price": "Price", "Price": "Price",
"Price - Tooltip": "Price - Tooltip", "Price - Tooltip": "Price - Tooltip",
"Quantity": "Quantity", "Quantity": "Quantity",

View File

@ -7,12 +7,13 @@
}, },
"adapter": { "adapter": {
"Edit Adapter": "Edit Adapter", "Edit Adapter": "Edit Adapter",
"Failed to sync policies: ": "Failed to sync policies: ", "Failed to sync policies": "Failed to sync policies",
"New Adapter": "New Adapter", "New Adapter": "New Adapter",
"Policies": "Policies", "Policies": "Policies",
"Policies - Tooltip": "Policies - Tooltip", "Policies - Tooltip": "Policies - Tooltip",
"Repeated policy rules": "Repeated policy rules", "Repeated policy rules": "Repeated policy rules",
"Sync": "Sync" "Sync": "Sync",
"Sync policies successfully": "Sync policies successfully"
}, },
"application": { "application": {
"Always": "Always", "Always": "Always",
@ -36,6 +37,7 @@
"Enable signin session - Tooltip": "Activer la session de connexion - infobulle", "Enable signin session - Tooltip": "Activer la session de connexion - infobulle",
"Enable signup": "Activer l'inscription", "Enable signup": "Activer l'inscription",
"Enable signup - Tooltip": "Whether to allow users to sign up", "Enable signup - Tooltip": "Whether to allow users to sign up",
"Failed to sign in": "Failed to sign in",
"File uploaded successfully": "Fichier téléchargé avec succès", "File uploaded successfully": "Fichier téléchargé avec succès",
"Form CSS": "Form CSS", "Form CSS": "Form CSS",
"Form CSS - Edit": "Form CSS - Edit", "Form CSS - Edit": "Form CSS - Edit",
@ -45,6 +47,8 @@
"Grant types": "Grant types", "Grant types": "Grant types",
"Grant types - Tooltip": "Grant types - Tooltip", "Grant types - Tooltip": "Grant types - Tooltip",
"Left": "Left", "Left": "Left",
"Logged in successfully": "Logged in successfully",
"Logged out successfully": "Logged out successfully",
"New Application": "New Application", "New Application": "New Application",
"None": "None", "None": "None",
"Password ON": "Mot de passe activé", "Password ON": "Mot de passe activé",
@ -54,12 +58,14 @@
"Please select a HTML file": "Veuillez sélectionner un fichier HTML", "Please select a HTML file": "Veuillez sélectionner un fichier HTML",
"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", "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",
"Redirect URL": "URL de redirection", "Redirect URL": "URL de redirection",
"Redirect URL (Assertion Consumer Service POST Binding URL) - Tooltip": "Redirect URL (Assertion Consumer Service POST Binding URL) - Tooltip",
"Redirect URLs": "URL de redirection", "Redirect URLs": "URL de redirection",
"Redirect URLs - Tooltip": "List of redirect addresses after successful login", "Redirect URLs - Tooltip": "List of redirect addresses after successful login",
"Refresh token expire": "Expiration du jeton d'actualisation", "Refresh token expire": "Expiration du jeton d'actualisation",
"Refresh token expire - Tooltip": "Expiration du jeton d'actualisation - infobulle", "Refresh token expire - Tooltip": "Expiration du jeton d'actualisation - infobulle",
"Right": "Right", "Right": "Right",
"Rule": "Rule", "Rule": "Rule",
"SAML Reply URL": "SAML Reply URL",
"SAML metadata": "SAML metadata", "SAML metadata": "SAML metadata",
"SAML metadata - Tooltip": "SAML metadata - Tooltip", "SAML metadata - Tooltip": "SAML metadata - Tooltip",
"SAML metadata URL copied to clipboard successfully": "SAML metadata URL copied to clipboard successfully", "SAML metadata URL copied to clipboard successfully": "SAML metadata URL copied to clipboard successfully",
@ -326,6 +332,7 @@
"Default avatar": "Avatar par défaut", "Default avatar": "Avatar par défaut",
"Edit Organization": "Modifier l'organisation", "Edit Organization": "Modifier l'organisation",
"Favicon": "Favicon", "Favicon": "Favicon",
"InitScore": "InitScore",
"Is profile public": "Is profile public", "Is profile public": "Is profile public",
"Is profile public - Tooltip": "Is profile public - Tooltip", "Is profile public - Tooltip": "Is profile public - Tooltip",
"Modify rule": "Modify rule", "Modify rule": "Modify rule",
@ -334,6 +341,7 @@
"Soft deletion - Tooltip": "Suppression de soft - infobulle", "Soft deletion - Tooltip": "Suppression de soft - infobulle",
"Tags": "Tags", "Tags": "Tags",
"Tags - Tooltip": "Tags - Tooltip", "Tags - Tooltip": "Tags - Tooltip",
"The user's initScore - Tooltip": "The user's initScore - Tooltip",
"View rule": "View rule", "View rule": "View rule",
"Visible": "Visible", "Visible": "Visible",
"Website URL": "URL du site web", "Website URL": "URL du site web",
@ -426,9 +434,12 @@
"CNY": "CNY", "CNY": "CNY",
"Currency": "Currency", "Currency": "Currency",
"Currency - Tooltip": "Currency - Tooltip", "Currency - Tooltip": "Currency - Tooltip",
"Description": "Description",
"Description - Tooltip": "Description - Tooltip",
"Detail": "Detail", "Detail": "Detail",
"Detail - Tooltip": "Detail - Tooltip", "Detail - Tooltip": "Detail - Tooltip",
"Edit Product": "Edit Product", "Edit Product": "Edit Product",
"I have completed the payment": "I have completed the payment",
"Image": "Image", "Image": "Image",
"Image - Tooltip": "Image - Tooltip", "Image - Tooltip": "Image - Tooltip",
"New Product": "New Product", "New Product": "New Product",
@ -437,6 +448,8 @@
"Payment providers - Tooltip": "Payment providers - Tooltip", "Payment providers - Tooltip": "Payment providers - Tooltip",
"Paypal": "Paypal", "Paypal": "Paypal",
"Placing order...": "Placing order...", "Placing order...": "Placing order...",
"Please provide your username in the remark": "Please provide your username in the remark",
"Please scan the QR code to pay": "Please scan the QR code to pay",
"Price": "Price", "Price": "Price",
"Price - Tooltip": "Price - Tooltip", "Price - Tooltip": "Price - Tooltip",
"Quantity": "Quantity", "Quantity": "Quantity",

View File

@ -7,12 +7,13 @@
}, },
"adapter": { "adapter": {
"Edit Adapter": "Edit Adapter", "Edit Adapter": "Edit Adapter",
"Failed to sync policies: ": "Failed to sync policies: ", "Failed to sync policies": "Failed to sync policies",
"New Adapter": "New Adapter", "New Adapter": "New Adapter",
"Policies": "Policies", "Policies": "Policies",
"Policies - Tooltip": "Policies - Tooltip", "Policies - Tooltip": "Policies - Tooltip",
"Repeated policy rules": "Repeated policy rules", "Repeated policy rules": "Repeated policy rules",
"Sync": "Sync" "Sync": "Sync",
"Sync policies successfully": "Sync policies successfully"
}, },
"application": { "application": {
"Always": "Always", "Always": "Always",
@ -36,6 +37,7 @@
"Enable signin session - Tooltip": "Enable signin session - Tooltip", "Enable signin session - Tooltip": "Enable signin session - Tooltip",
"Enable signup": "サインアップを有効にする", "Enable signup": "サインアップを有効にする",
"Enable signup - Tooltip": "Whether to allow users to sign up", "Enable signup - Tooltip": "Whether to allow users to sign up",
"Failed to sign in": "Failed to sign in",
"File uploaded successfully": "ファイルが正常にアップロードされました", "File uploaded successfully": "ファイルが正常にアップロードされました",
"Form CSS": "Form CSS", "Form CSS": "Form CSS",
"Form CSS - Edit": "Form CSS - Edit", "Form CSS - Edit": "Form CSS - Edit",
@ -45,6 +47,8 @@
"Grant types": "Grant types", "Grant types": "Grant types",
"Grant types - Tooltip": "Grant types - Tooltip", "Grant types - Tooltip": "Grant types - Tooltip",
"Left": "Left", "Left": "Left",
"Logged in successfully": "Logged in successfully",
"Logged out successfully": "Logged out successfully",
"New Application": "New Application", "New Application": "New Application",
"None": "None", "None": "None",
"Password ON": "パスワードON", "Password ON": "パスワードON",
@ -54,12 +58,14 @@
"Please select a HTML file": "HTMLファイルを選択してください", "Please select a HTML file": "HTMLファイルを選択してください",
"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", "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",
"Redirect URL": "リダイレクトURL", "Redirect URL": "リダイレクトURL",
"Redirect URL (Assertion Consumer Service POST Binding URL) - Tooltip": "Redirect URL (Assertion Consumer Service POST Binding URL) - Tooltip",
"Redirect URLs": "リダイレクトURL", "Redirect URLs": "リダイレクトURL",
"Redirect URLs - Tooltip": "List of redirect addresses after successful login", "Redirect URLs - Tooltip": "List of redirect addresses after successful login",
"Refresh token expire": "トークンの更新の期限が切れます", "Refresh token expire": "トークンの更新の期限が切れます",
"Refresh token expire - Tooltip": "トークンの有効期限を更新する - ツールチップ", "Refresh token expire - Tooltip": "トークンの有効期限を更新する - ツールチップ",
"Right": "Right", "Right": "Right",
"Rule": "Rule", "Rule": "Rule",
"SAML Reply URL": "SAML Reply URL",
"SAML metadata": "SAML metadata", "SAML metadata": "SAML metadata",
"SAML metadata - Tooltip": "SAML metadata - Tooltip", "SAML metadata - Tooltip": "SAML metadata - Tooltip",
"SAML metadata URL copied to clipboard successfully": "SAML metadata URL copied to clipboard successfully", "SAML metadata URL copied to clipboard successfully": "SAML metadata URL copied to clipboard successfully",
@ -326,6 +332,7 @@
"Default avatar": "デフォルトのアバター", "Default avatar": "デフォルトのアバター",
"Edit Organization": "組織を編集", "Edit Organization": "組織を編集",
"Favicon": "ファビコン", "Favicon": "ファビコン",
"InitScore": "InitScore",
"Is profile public": "Is profile public", "Is profile public": "Is profile public",
"Is profile public - Tooltip": "Is profile public - Tooltip", "Is profile public - Tooltip": "Is profile public - Tooltip",
"Modify rule": "Modify rule", "Modify rule": "Modify rule",
@ -334,6 +341,7 @@
"Soft deletion - Tooltip": "ソフト削除 - ツールチップ", "Soft deletion - Tooltip": "ソフト削除 - ツールチップ",
"Tags": "Tags", "Tags": "Tags",
"Tags - Tooltip": "Tags - Tooltip", "Tags - Tooltip": "Tags - Tooltip",
"The user's initScore - Tooltip": "The user's initScore - Tooltip",
"View rule": "View rule", "View rule": "View rule",
"Visible": "Visible", "Visible": "Visible",
"Website URL": "Website URL", "Website URL": "Website URL",
@ -426,9 +434,12 @@
"CNY": "CNY", "CNY": "CNY",
"Currency": "Currency", "Currency": "Currency",
"Currency - Tooltip": "Currency - Tooltip", "Currency - Tooltip": "Currency - Tooltip",
"Description": "Description",
"Description - Tooltip": "Description - Tooltip",
"Detail": "Detail", "Detail": "Detail",
"Detail - Tooltip": "Detail - Tooltip", "Detail - Tooltip": "Detail - Tooltip",
"Edit Product": "Edit Product", "Edit Product": "Edit Product",
"I have completed the payment": "I have completed the payment",
"Image": "Image", "Image": "Image",
"Image - Tooltip": "Image - Tooltip", "Image - Tooltip": "Image - Tooltip",
"New Product": "New Product", "New Product": "New Product",
@ -437,6 +448,8 @@
"Payment providers - Tooltip": "Payment providers - Tooltip", "Payment providers - Tooltip": "Payment providers - Tooltip",
"Paypal": "Paypal", "Paypal": "Paypal",
"Placing order...": "Placing order...", "Placing order...": "Placing order...",
"Please provide your username in the remark": "Please provide your username in the remark",
"Please scan the QR code to pay": "Please scan the QR code to pay",
"Price": "Price", "Price": "Price",
"Price - Tooltip": "Price - Tooltip", "Price - Tooltip": "Price - Tooltip",
"Quantity": "Quantity", "Quantity": "Quantity",

View File

@ -7,12 +7,13 @@
}, },
"adapter": { "adapter": {
"Edit Adapter": "Edit Adapter", "Edit Adapter": "Edit Adapter",
"Failed to sync policies: ": "Failed to sync policies: ", "Failed to sync policies": "Failed to sync policies",
"New Adapter": "New Adapter", "New Adapter": "New Adapter",
"Policies": "Policies", "Policies": "Policies",
"Policies - Tooltip": "Policies - Tooltip", "Policies - Tooltip": "Policies - Tooltip",
"Repeated policy rules": "Repeated policy rules", "Repeated policy rules": "Repeated policy rules",
"Sync": "Sync" "Sync": "Sync",
"Sync policies successfully": "Sync policies successfully"
}, },
"application": { "application": {
"Always": "Always", "Always": "Always",
@ -36,6 +37,7 @@
"Enable signin session - Tooltip": "Enable signin session - Tooltip", "Enable signin session - Tooltip": "Enable signin session - Tooltip",
"Enable signup": "Enable signup", "Enable signup": "Enable signup",
"Enable signup - Tooltip": "Whether to allow users to sign up", "Enable signup - Tooltip": "Whether to allow users to sign up",
"Failed to sign in": "Failed to sign in",
"File uploaded successfully": "File uploaded successfully", "File uploaded successfully": "File uploaded successfully",
"Form CSS": "Form CSS", "Form CSS": "Form CSS",
"Form CSS - Edit": "Form CSS - Edit", "Form CSS - Edit": "Form CSS - Edit",
@ -45,6 +47,8 @@
"Grant types": "Grant types", "Grant types": "Grant types",
"Grant types - Tooltip": "Grant types - Tooltip", "Grant types - Tooltip": "Grant types - Tooltip",
"Left": "Left", "Left": "Left",
"Logged in successfully": "Logged in successfully",
"Logged out successfully": "Logged out successfully",
"New Application": "New Application", "New Application": "New Application",
"None": "None", "None": "None",
"Password ON": "Password ON", "Password ON": "Password ON",
@ -54,12 +58,14 @@
"Please select a HTML file": "Please select a HTML file", "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", "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",
"Redirect URL": "Redirect URL", "Redirect URL": "Redirect URL",
"Redirect URL (Assertion Consumer Service POST Binding URL) - Tooltip": "Redirect URL (Assertion Consumer Service POST Binding URL) - Tooltip",
"Redirect URLs": "Redirect URLs", "Redirect URLs": "Redirect URLs",
"Redirect URLs - Tooltip": "List of redirect addresses after successful login", "Redirect URLs - Tooltip": "List of redirect addresses after successful login",
"Refresh token expire": "Refresh token expire", "Refresh token expire": "Refresh token expire",
"Refresh token expire - Tooltip": "Refresh token expire - Tooltip", "Refresh token expire - Tooltip": "Refresh token expire - Tooltip",
"Right": "Right", "Right": "Right",
"Rule": "Rule", "Rule": "Rule",
"SAML Reply URL": "SAML Reply URL",
"SAML metadata": "SAML metadata", "SAML metadata": "SAML metadata",
"SAML metadata - Tooltip": "SAML metadata - Tooltip", "SAML metadata - Tooltip": "SAML metadata - Tooltip",
"SAML metadata URL copied to clipboard successfully": "SAML metadata URL copied to clipboard successfully", "SAML metadata URL copied to clipboard successfully": "SAML metadata URL copied to clipboard successfully",
@ -326,6 +332,7 @@
"Default avatar": "Default avatar", "Default avatar": "Default avatar",
"Edit Organization": "Edit Organization", "Edit Organization": "Edit Organization",
"Favicon": "Favicon", "Favicon": "Favicon",
"InitScore": "InitScore",
"Is profile public": "Is profile public", "Is profile public": "Is profile public",
"Is profile public - Tooltip": "Is profile public - Tooltip", "Is profile public - Tooltip": "Is profile public - Tooltip",
"Modify rule": "Modify rule", "Modify rule": "Modify rule",
@ -334,6 +341,7 @@
"Soft deletion - Tooltip": "Soft deletion - Tooltip", "Soft deletion - Tooltip": "Soft deletion - Tooltip",
"Tags": "Tags", "Tags": "Tags",
"Tags - Tooltip": "Tags - Tooltip", "Tags - Tooltip": "Tags - Tooltip",
"The user's initScore - Tooltip": "The user's initScore - Tooltip",
"View rule": "View rule", "View rule": "View rule",
"Visible": "Visible", "Visible": "Visible",
"Website URL": "Website URL", "Website URL": "Website URL",
@ -426,9 +434,12 @@
"CNY": "CNY", "CNY": "CNY",
"Currency": "Currency", "Currency": "Currency",
"Currency - Tooltip": "Currency - Tooltip", "Currency - Tooltip": "Currency - Tooltip",
"Description": "Description",
"Description - Tooltip": "Description - Tooltip",
"Detail": "Detail", "Detail": "Detail",
"Detail - Tooltip": "Detail - Tooltip", "Detail - Tooltip": "Detail - Tooltip",
"Edit Product": "Edit Product", "Edit Product": "Edit Product",
"I have completed the payment": "I have completed the payment",
"Image": "Image", "Image": "Image",
"Image - Tooltip": "Image - Tooltip", "Image - Tooltip": "Image - Tooltip",
"New Product": "New Product", "New Product": "New Product",
@ -437,6 +448,8 @@
"Payment providers - Tooltip": "Payment providers - Tooltip", "Payment providers - Tooltip": "Payment providers - Tooltip",
"Paypal": "Paypal", "Paypal": "Paypal",
"Placing order...": "Placing order...", "Placing order...": "Placing order...",
"Please provide your username in the remark": "Please provide your username in the remark",
"Please scan the QR code to pay": "Please scan the QR code to pay",
"Price": "Price", "Price": "Price",
"Price - Tooltip": "Price - Tooltip", "Price - Tooltip": "Price - Tooltip",
"Quantity": "Quantity", "Quantity": "Quantity",

View File

@ -7,12 +7,13 @@
}, },
"adapter": { "adapter": {
"Edit Adapter": "Edit Adapter", "Edit Adapter": "Edit Adapter",
"Failed to sync policies: ": "Failed to sync policies: ", "Failed to sync policies": "Failed to sync policies",
"New Adapter": "New Adapter", "New Adapter": "New Adapter",
"Policies": "Policies", "Policies": "Policies",
"Policies - Tooltip": "Policies - Tooltip", "Policies - Tooltip": "Policies - Tooltip",
"Repeated policy rules": "Repeated policy rules", "Repeated policy rules": "Repeated policy rules",
"Sync": "Sync" "Sync": "Sync",
"Sync policies successfully": "Sync policies successfully"
}, },
"application": { "application": {
"Always": "Always", "Always": "Always",
@ -36,6 +37,7 @@
"Enable signin session - Tooltip": "Включить сеанс входа - Подсказка", "Enable signin session - Tooltip": "Включить сеанс входа - Подсказка",
"Enable signup": "Включить регистрацию", "Enable signup": "Включить регистрацию",
"Enable signup - Tooltip": "Whether to allow users to sign up", "Enable signup - Tooltip": "Whether to allow users to sign up",
"Failed to sign in": "Failed to sign in",
"File uploaded successfully": "Файл успешно загружен", "File uploaded successfully": "Файл успешно загружен",
"Form CSS": "Form CSS", "Form CSS": "Form CSS",
"Form CSS - Edit": "Form CSS - Edit", "Form CSS - Edit": "Form CSS - Edit",
@ -45,6 +47,8 @@
"Grant types": "Виды грантов", "Grant types": "Виды грантов",
"Grant types - Tooltip": "Виды грантов - Подсказка", "Grant types - Tooltip": "Виды грантов - Подсказка",
"Left": "Left", "Left": "Left",
"Logged in successfully": "Logged in successfully",
"Logged out successfully": "Logged out successfully",
"New Application": "Новое приложение", "New Application": "Новое приложение",
"None": "None", "None": "None",
"Password ON": "Пароль ВКЛ", "Password ON": "Пароль ВКЛ",
@ -54,12 +58,14 @@
"Please select a HTML file": "Пожалуйста, выберите HTML-файл", "Please select a HTML file": "Пожалуйста, выберите HTML-файл",
"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": "Ссылка на страницу успешно скопирована в буфер обмена, пожалуйста, вставьте ее в окно инкогнито или другой браузер",
"Redirect URL": "URL перенаправления", "Redirect URL": "URL перенаправления",
"Redirect URL (Assertion Consumer Service POST Binding URL) - Tooltip": "Redirect URL (Assertion Consumer Service POST Binding URL) - Tooltip",
"Redirect URLs": "Перенаправление URL", "Redirect URLs": "Перенаправление URL",
"Redirect URLs - Tooltip": "List of redirect addresses after successful login", "Redirect URLs - Tooltip": "List of redirect addresses after successful login",
"Refresh token expire": "Срок действия обновления токена истекает", "Refresh token expire": "Срок действия обновления токена истекает",
"Refresh token expire - Tooltip": "Срок обновления токена истекает - Подсказка", "Refresh token expire - Tooltip": "Срок обновления токена истекает - Подсказка",
"Right": "Right", "Right": "Right",
"Rule": "правило", "Rule": "правило",
"SAML Reply URL": "SAML Reply URL",
"SAML metadata": "Метаданные SAML", "SAML metadata": "Метаданные SAML",
"SAML metadata - Tooltip": "Метаданные SAML - Подсказка", "SAML metadata - Tooltip": "Метаданные SAML - Подсказка",
"SAML metadata URL copied to clipboard successfully": "Адрес метаданных SAML скопирован в буфер обмена", "SAML metadata URL copied to clipboard successfully": "Адрес метаданных SAML скопирован в буфер обмена",
@ -326,6 +332,7 @@
"Default avatar": "Аватар по умолчанию", "Default avatar": "Аватар по умолчанию",
"Edit Organization": "Изменить организацию", "Edit Organization": "Изменить организацию",
"Favicon": "Иконка", "Favicon": "Иконка",
"InitScore": "InitScore",
"Is profile public": "Is profile public", "Is profile public": "Is profile public",
"Is profile public - Tooltip": "Is profile public - Tooltip", "Is profile public - Tooltip": "Is profile public - Tooltip",
"Modify rule": "Modify rule", "Modify rule": "Modify rule",
@ -334,6 +341,7 @@
"Soft deletion - Tooltip": "Мягкое удаление - Подсказка", "Soft deletion - Tooltip": "Мягкое удаление - Подсказка",
"Tags": "Tags", "Tags": "Tags",
"Tags - Tooltip": "Tags - Tooltip", "Tags - Tooltip": "Tags - Tooltip",
"The user's initScore - Tooltip": "The user's initScore - Tooltip",
"View rule": "View rule", "View rule": "View rule",
"Visible": "Visible", "Visible": "Visible",
"Website URL": "URL сайта", "Website URL": "URL сайта",
@ -426,9 +434,12 @@
"CNY": "CNY", "CNY": "CNY",
"Currency": "Currency", "Currency": "Currency",
"Currency - Tooltip": "Currency - Tooltip", "Currency - Tooltip": "Currency - Tooltip",
"Description": "Description",
"Description - Tooltip": "Description - Tooltip",
"Detail": "Сведения", "Detail": "Сведения",
"Detail - Tooltip": "Detail - Tooltip", "Detail - Tooltip": "Detail - Tooltip",
"Edit Product": "Редактирование продукта", "Edit Product": "Редактирование продукта",
"I have completed the payment": "I have completed the payment",
"Image": "Изображение", "Image": "Изображение",
"Image - Tooltip": "Image - Tooltip", "Image - Tooltip": "Image - Tooltip",
"New Product": "Новый продукт", "New Product": "Новый продукт",
@ -437,6 +448,8 @@
"Payment providers - Tooltip": "Payment providers - Tooltip", "Payment providers - Tooltip": "Payment providers - Tooltip",
"Paypal": "PayPal", "Paypal": "PayPal",
"Placing order...": "Placing order...", "Placing order...": "Placing order...",
"Please provide your username in the remark": "Please provide your username in the remark",
"Please scan the QR code to pay": "Please scan the QR code to pay",
"Price": "Цена", "Price": "Цена",
"Price - Tooltip": "Price - Tooltip", "Price - Tooltip": "Price - Tooltip",
"Quantity": "Quantity", "Quantity": "Quantity",

View File

@ -7,12 +7,13 @@
}, },
"adapter": { "adapter": {
"Edit Adapter": "编辑适配器", "Edit Adapter": "编辑适配器",
"Failed to sync policies: ": "同步策略失败: ", "Failed to sync policies": "同步策略失败",
"New Adapter": "添加适配器", "New Adapter": "添加适配器",
"Policies": "策略", "Policies": "策略",
"Policies - Tooltip": "策略", "Policies - Tooltip": "策略",
"Repeated policy rules": "重复的策略", "Repeated policy rules": "重复的策略",
"Sync": "同步" "Sync": "同步",
"Sync policies successfully": "同步策略成功"
}, },
"application": { "application": {
"Always": "始终开启", "Always": "始终开启",
@ -36,6 +37,7 @@
"Enable signin session - Tooltip": "从应用登录Casdoor后Casdoor是否保持会话", "Enable signin session - Tooltip": "从应用登录Casdoor后Casdoor是否保持会话",
"Enable signup": "启用注册", "Enable signup": "启用注册",
"Enable signup - Tooltip": "是否允许用户注册", "Enable signup - Tooltip": "是否允许用户注册",
"Failed to sign in": "登录失败",
"File uploaded successfully": "文件上传成功", "File uploaded successfully": "文件上传成功",
"Form CSS": "表单CSS", "Form CSS": "表单CSS",
"Form CSS - Edit": "编辑表单CSS", "Form CSS - Edit": "编辑表单CSS",
@ -45,6 +47,8 @@
"Grant types": "OAuth授权类型", "Grant types": "OAuth授权类型",
"Grant types - Tooltip": "选择允许哪些OAuth协议中的Grant types", "Grant types - Tooltip": "选择允许哪些OAuth协议中的Grant types",
"Left": "居左", "Left": "居左",
"Logged in successfully": "登录成功",
"Logged out successfully": "登出成功",
"New Application": "添加应用", "New Application": "添加应用",
"None": "关闭", "None": "关闭",
"Password ON": "开启密码", "Password ON": "开启密码",
@ -54,12 +58,14 @@
"Please select a HTML file": "请选择一个HTML文件", "Please select a HTML file": "请选择一个HTML文件",
"Prompt page URL copied to clipboard successfully, please paste it into the incognito window or another browser": "提醒页面URL已成功复制到剪贴板请粘贴到当前浏览器的隐身模式窗口或另一个浏览器访问", "Prompt page URL copied to clipboard successfully, please paste it into the incognito window or another browser": "提醒页面URL已成功复制到剪贴板请粘贴到当前浏览器的隐身模式窗口或另一个浏览器访问",
"Redirect URL": "重定向 URL", "Redirect URL": "重定向 URL",
"Redirect URL (Assertion Consumer Service POST Binding URL) - Tooltip": "回复 URL (断言使用者服务 URL, 使用POST请求返回响应) - Tooltip",
"Redirect URLs": "重定向 URLs", "Redirect URLs": "重定向 URLs",
"Redirect URLs - Tooltip": "登录成功后重定向地址列表", "Redirect URLs - Tooltip": "登录成功后重定向地址列表",
"Refresh token expire": "Refresh Token过期", "Refresh token expire": "Refresh Token过期",
"Refresh token expire - Tooltip": "Refresh Token过期时间", "Refresh token expire - Tooltip": "Refresh Token过期时间",
"Right": "居右", "Right": "居右",
"Rule": "规则", "Rule": "规则",
"SAML Reply URL": "SAML回复 URL",
"SAML metadata": "SAML元数据", "SAML metadata": "SAML元数据",
"SAML metadata - Tooltip": "SAML协议的元数据Metadata信息", "SAML metadata - Tooltip": "SAML协议的元数据Metadata信息",
"SAML metadata URL copied to clipboard successfully": "SAML元数据URL已成功复制到剪贴板", "SAML metadata URL copied to clipboard successfully": "SAML元数据URL已成功复制到剪贴板",
@ -326,6 +332,7 @@
"Default avatar": "默认头像", "Default avatar": "默认头像",
"Edit Organization": "编辑组织", "Edit Organization": "编辑组织",
"Favicon": "图标", "Favicon": "图标",
"InitScore": "初始积分",
"Is profile public": "用户个人页公开", "Is profile public": "用户个人页公开",
"Is profile public - Tooltip": "关闭后,只有全局管理员或同组织用户才能访问用户主页", "Is profile public - Tooltip": "关闭后,只有全局管理员或同组织用户才能访问用户主页",
"Modify rule": "修改规则", "Modify rule": "修改规则",
@ -334,6 +341,7 @@
"Soft deletion - Tooltip": "启用后,删除用户信息时不会在数据库彻底清除,只会标记为已删除状态", "Soft deletion - Tooltip": "启用后,删除用户信息时不会在数据库彻底清除,只会标记为已删除状态",
"Tags": "标签集合", "Tags": "标签集合",
"Tags - Tooltip": "可供用户选择的标签的集合", "Tags - Tooltip": "可供用户选择的标签的集合",
"The user's initScore - Tooltip": "用户的初始积分",
"View rule": "查看规则", "View rule": "查看规则",
"Visible": "是否可见", "Visible": "是否可见",
"Website URL": "网页地址", "Website URL": "网页地址",
@ -426,9 +434,12 @@
"CNY": "人民币", "CNY": "人民币",
"Currency": "币种", "Currency": "币种",
"Currency - Tooltip": "币种 - 工具提示", "Currency - Tooltip": "币种 - 工具提示",
"Description": "描述",
"Description - Tooltip": "描述 - 工具提示",
"Detail": "详情", "Detail": "详情",
"Detail - Tooltip": "详情 - 工具提示", "Detail - Tooltip": "详情 - 工具提示",
"Edit Product": "编辑商品", "Edit Product": "编辑商品",
"I have completed the payment": "支付完成",
"Image": "图片", "Image": "图片",
"Image - Tooltip": "图片 - 工具提示", "Image - Tooltip": "图片 - 工具提示",
"New Product": "添加商品", "New Product": "添加商品",
@ -437,6 +448,8 @@
"Payment providers - Tooltip": "支付提供商 - 工具提示", "Payment providers - Tooltip": "支付提供商 - 工具提示",
"Paypal": "PayPal贝宝", "Paypal": "PayPal贝宝",
"Placing order...": "正在下单...", "Placing order...": "正在下单...",
"Please provide your username in the remark": "Please provide your username in the remark",
"Please scan the QR code to pay": "请扫描二维码支付",
"Price": "价格", "Price": "价格",
"Price - Tooltip": "价格 - 工具提示", "Price - Tooltip": "价格 - 工具提示",
"Quantity": "库存", "Quantity": "库存",

View File

@ -2096,6 +2096,13 @@
schema-utils "^3.0.0" schema-utils "^3.0.0"
source-map "^0.7.3" source-map "^0.7.3"
"@rc-component/mini-decimal@^1.0.1":
version "1.0.1"
resolved "https://registry.yarnpkg.com/@rc-component/mini-decimal/-/mini-decimal-1.0.1.tgz#e5dbc20a6a5b0e234d279bc71ce730ab865d3910"
integrity sha512-9N8nRk0oKj1qJzANKl+n9eNSMUGsZtjwNuDCiZ/KA+dt1fE3zq5x2XxclRcAbOIXnZcJ53ozP2Pa60gyELXagA==
dependencies:
"@babel/runtime" "^7.18.0"
"@rc-component/portal@^1.0.0-6", "@rc-component/portal@^1.0.0-8", "@rc-component/portal@^1.0.0-9", "@rc-component/portal@^1.0.2": "@rc-component/portal@^1.0.0-6", "@rc-component/portal@^1.0.0-8", "@rc-component/portal@^1.0.0-9", "@rc-component/portal@^1.0.2":
version "1.0.3" version "1.0.3"
resolved "https://registry.yarnpkg.com/@rc-component/portal/-/portal-1.0.3.tgz#3aa2c229a7a20ac2412d864e8977e6377973416e" resolved "https://registry.yarnpkg.com/@rc-component/portal/-/portal-1.0.3.tgz#3aa2c229a7a20ac2412d864e8977e6377973416e"
@ -3134,10 +3141,10 @@ ansi-styles@^6.0.0:
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.1.0.tgz#87313c102b8118abd57371afab34618bf7350ed3" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.1.0.tgz#87313c102b8118abd57371afab34618bf7350ed3"
integrity sha512-VbqNsoz55SYGczauuup0MFUyXNQviSpFTj1RQtFzmQLk18qbVSpTFFGMT293rmDaQuKCT6InmbuEyUne4mTuxQ== integrity sha512-VbqNsoz55SYGczauuup0MFUyXNQviSpFTj1RQtFzmQLk18qbVSpTFFGMT293rmDaQuKCT6InmbuEyUne4mTuxQ==
antd@5.0.3: antd@5.0.5:
version "5.0.3" version "5.0.5"
resolved "https://registry.yarnpkg.com/antd/-/antd-5.0.3.tgz#2cdaffe1afdb5c2f0f3325b2d06d508ec6ddf85a" resolved "https://registry.yarnpkg.com/antd/-/antd-5.0.5.tgz#16f0ade8b2d2ea9f7bd47a8e0af81884dc504a7d"
integrity sha512-Gqkba0earlR5H6gfT4nsyV3W9rL1Up1+clEXsa1+9Jem/geC2phBImpjWgVjqOjH3L5Oi8SHe0NeYBagDxwP5g== integrity sha512-8jWUjZ65urNHZPg9/Ywa9V0PlNfqjhewKgSPF4nraN9X5v434lDJkRBQGN7meNixQ6aM2B/JhXPm9UaJ/tAQmA==
dependencies: dependencies:
"@ant-design/colors" "^6.0.0" "@ant-design/colors" "^6.0.0"
"@ant-design/cssinjs" "^1.0.0" "@ant-design/cssinjs" "^1.0.0"
@ -3159,7 +3166,7 @@ antd@5.0.3:
rc-field-form "~1.27.0" rc-field-form "~1.27.0"
rc-image "~5.12.0" rc-image "~5.12.0"
rc-input "~0.1.4" rc-input "~0.1.4"
rc-input-number "~7.3.9" rc-input-number "~7.4.0"
rc-mentions "~1.13.1" rc-mentions "~1.13.1"
rc-menu "~9.8.0" rc-menu "~9.8.0"
rc-motion "^2.6.1" rc-motion "^2.6.1"
@ -3175,15 +3182,15 @@ antd@5.0.3:
rc-steps "~6.0.0-alpha.2" rc-steps "~6.0.0-alpha.2"
rc-switch "~4.0.0" rc-switch "~4.0.0"
rc-table "~7.26.0" rc-table "~7.26.0"
rc-tabs "~12.4.1" rc-tabs "~12.4.2"
rc-textarea "~0.4.5" rc-textarea "~0.4.5"
rc-tooltip "~5.2.0" rc-tooltip "~5.2.0"
rc-tree "~5.7.0" rc-tree "~5.7.0"
rc-tree-select "~5.5.4" rc-tree-select "~5.5.4"
rc-trigger "^5.2.10" rc-trigger "^5.2.10"
rc-upload "~4.3.0" rc-upload "~4.3.0"
rc-util "^5.22.5" rc-util "^5.25.2"
scroll-into-view-if-needed "^2.2.25" scroll-into-view-if-needed "^3.0.3"
shallowequal "^1.1.0" shallowequal "^1.1.0"
anymatch@^3.0.3, anymatch@~3.1.2: anymatch@^3.0.3, anymatch@~3.1.2:
@ -4011,10 +4018,10 @@ compression@^1.7.4:
safe-buffer "5.1.2" safe-buffer "5.1.2"
vary "~1.1.2" vary "~1.1.2"
compute-scroll-into-view@^1.0.17: compute-scroll-into-view@^2.0.2:
version "1.0.17" version "2.0.2"
resolved "https://registry.yarnpkg.com/compute-scroll-into-view/-/compute-scroll-into-view-1.0.17.tgz#6a88f18acd9d42e9cf4baa6bec7e0522607ab7ab" resolved "https://registry.yarnpkg.com/compute-scroll-into-view/-/compute-scroll-into-view-2.0.2.tgz#ac5cc71ca833884866e581a82d8558a6ed7ee877"
integrity sha512-j4dx+Fb0URmzbwwMUrhqWM2BEWHdFGx+qZ9qqASHRPqvTYdqvWnHg0H1hIbcyLnvgnoNAVMlwkepyqM3DaIFUg== integrity sha512-W+4Iti92hktsTtNPNeRM1vE0JdqCBk5qIabRafpr5pGrQhQ+xzCv0NGnFzTCKmW4yGLm9Aovbw8YNxloe2z9tQ==
concat-map@0.0.1: concat-map@0.0.1:
version "0.0.1" version "0.0.1"
@ -8934,12 +8941,13 @@ rc-image@~5.12.0:
rc-dialog "~9.0.0" rc-dialog "~9.0.0"
rc-util "^5.0.6" rc-util "^5.0.6"
rc-input-number@~7.3.9: rc-input-number@~7.4.0:
version "7.3.11" version "7.4.0"
resolved "https://registry.yarnpkg.com/rc-input-number/-/rc-input-number-7.3.11.tgz#c7089705a220e1a59ba974fabf89693e00dd2442" resolved "https://registry.yarnpkg.com/rc-input-number/-/rc-input-number-7.4.0.tgz#b8b4ffa8bbc04198e79ce8b9611756d046d128ec"
integrity sha512-aMWPEjFeles6PQnMqP5eWpxzsvHm9rh1jQOWXExUEIxhX62Fyl/ptifLHOn17+waDG1T/YUb6flfJbvwRhHrbA== integrity sha512-r/Oub/sPYbzqLNUOHnnc9sbCu78a81KX+RCbRwmpvB4W6nptUySbdWS5KHV4Hak5CAE1LAd+wWm5JjvZizG1FA==
dependencies: dependencies:
"@babel/runtime" "^7.10.1" "@babel/runtime" "^7.10.1"
"@rc-component/mini-decimal" "^1.0.1"
classnames "^2.2.5" classnames "^2.2.5"
rc-util "^5.23.0" rc-util "^5.23.0"
@ -9148,10 +9156,10 @@ rc-table@~7.26.0:
rc-util "^5.22.5" rc-util "^5.22.5"
shallowequal "^1.1.0" shallowequal "^1.1.0"
rc-tabs@~12.4.1: rc-tabs@~12.4.2:
version "12.4.1" version "12.4.2"
resolved "https://registry.yarnpkg.com/rc-tabs/-/rc-tabs-12.4.1.tgz#a45aa7560ae4e2a91426e74a2e76566f5c8ec9cc" resolved "https://registry.yarnpkg.com/rc-tabs/-/rc-tabs-12.4.2.tgz#487a1b3f8d8cf0bfc121224013dab00d4a8e0532"
integrity sha512-yViBZypldDnPffk3IPTarplF1RAv8VQDDnOt9sHDU7pjCnqE72csCU+7kjbLPtPpYniIMQJYyWxh/lsBUcagSA== integrity sha512-FFlGwuTjQUznWzJtyhmHc6KAp5lRQFxKUv9Aj1UtsOYe2e7WGmuzcrd+/LQchuPe0VjhaZPdGkmFGcqGqNO6ow==
dependencies: dependencies:
"@babel/runtime" "^7.11.2" "@babel/runtime" "^7.11.2"
classnames "2.x" classnames "2.x"
@ -9269,6 +9277,15 @@ rc-util@^5.21.2, rc-util@^5.23.0:
react-is "^16.12.0" react-is "^16.12.0"
shallowequal "^1.1.0" shallowequal "^1.1.0"
rc-util@^5.25.2:
version "5.25.2"
resolved "https://registry.yarnpkg.com/rc-util/-/rc-util-5.25.2.tgz#09fd3ce88da7d2149427d51e40a84e3527f5a263"
integrity sha512-OyCO675K/rh4zG3e+LYaHw54WQFEYGV9ibkGawQxqCvf0G0PzUrLQjgZ6SfoHORdbEKN7eQMFn3hHQyA/P8Y5Q==
dependencies:
"@babel/runtime" "^7.18.3"
react-is "^16.12.0"
shallowequal "^1.1.0"
rc-virtual-list@^3.2.0, rc-virtual-list@^3.4.8: rc-virtual-list@^3.2.0, rc-virtual-list@^3.4.8:
version "3.4.8" version "3.4.8"
resolved "https://registry.yarnpkg.com/rc-virtual-list/-/rc-virtual-list-3.4.8.tgz#c24c10c6940546b7e2a5e9809402c6716adfd26c" resolved "https://registry.yarnpkg.com/rc-virtual-list/-/rc-virtual-list-3.4.8.tgz#c24c10c6940546b7e2a5e9809402c6716adfd26c"
@ -9901,12 +9918,12 @@ schema-utils@^4.0.0:
ajv-formats "^2.1.1" ajv-formats "^2.1.1"
ajv-keywords "^5.0.0" ajv-keywords "^5.0.0"
scroll-into-view-if-needed@^2.2.25: scroll-into-view-if-needed@^3.0.3:
version "2.2.29" version "3.0.3"
resolved "https://registry.yarnpkg.com/scroll-into-view-if-needed/-/scroll-into-view-if-needed-2.2.29.tgz#551791a84b7e2287706511f8c68161e4990ab885" resolved "https://registry.yarnpkg.com/scroll-into-view-if-needed/-/scroll-into-view-if-needed-3.0.3.tgz#57256bef78f3c3c288070d2aaa63cf547aa11e70"
integrity sha512-hxpAR6AN+Gh53AdAimHM6C8oTN1ppwVZITihix+WqalywBeFcQ6LdQP5ABNl26nX8GTEL7VT+b8lKpdqq65wXg== integrity sha512-QoCH0lVw0tbA7Rl6sToH7e1tO3n95Oi6JgBgC8hEpNNZUC91MfasJ/4E1ZdbzGueNDZ+Y7ObfRaelKUgTyPbJA==
dependencies: dependencies:
compute-scroll-into-view "^1.0.17" compute-scroll-into-view "^2.0.2"
select-hose@^2.0.0: select-hose@^2.0.0:
version "2.0.0" version "2.0.0"