mirror of
https://github.com/casdoor/casdoor.git
synced 2025-07-18 18:03:50 +08:00
Compare commits
53 Commits
Author | SHA1 | Date | |
---|---|---|---|
6daadf8d3c | |||
090389b86a | |||
b566af8e11 | |||
57028c2059 | |||
a6e9084973 | |||
6fb3e2cd7f | |||
8b6bde6d82 | |||
fb2b03f00f | |||
1681138729 | |||
1d8b0a264e | |||
b525210835 | |||
4ab2ca7a25 | |||
dcf148fb7f | |||
c8846f1a2d | |||
0559298d6c | |||
ddb5e26fcd | |||
1f39027b78 | |||
eae3b0d367 | |||
186f0ac97b | |||
308f305c53 | |||
d498bc60ce | |||
7bbe1e38c1 | |||
f465fc6ce0 | |||
c952c2f2f4 | |||
86ae97d1e5 | |||
6ea73e3eca | |||
a71a190db5 | |||
da69d94445 | |||
b8b915abe1 | |||
5d1548e989 | |||
a0dc6e06cd | |||
ae130788ec | |||
f075d0fd74 | |||
65d4946042 | |||
26acece8af | |||
48a0c8473f | |||
082ae3c91e | |||
1ee2ff1d30 | |||
c0d9969013 | |||
1bdee13150 | |||
d668022af0 | |||
e227875c2b | |||
e473de3162 | |||
c5ef841d3f | |||
d46288b591 | |||
b968bf033c | |||
eca2527bc0 | |||
ef836acfe9 | |||
a51f0d7c08 | |||
e3c36beaf4 | |||
19dce838d1 | |||
b41d8652f0 | |||
e705eecffe |
3
.gitattributes
vendored
3
.gitattributes
vendored
@ -1,2 +1,5 @@
|
|||||||
*.go linguist-detectable=true
|
*.go linguist-detectable=true
|
||||||
*.js linguist-detectable=false
|
*.js linguist-detectable=false
|
||||||
|
# Declare files that will always have LF line endings on checkout.
|
||||||
|
# Git will always convert line endings to LF on checkout. You should use this for files that must keep LF endings, even on Windows.
|
||||||
|
*.sh text eol=lf
|
39
.github/workflows/build.yml
vendored
39
.github/workflows/build.yml
vendored
@ -76,11 +76,48 @@ jobs:
|
|||||||
version: latest
|
version: latest
|
||||||
args: --disable-all -c dummy.yml -E=gofumpt --max-same-issues=0 --timeout 5m --modules-download-mode=mod
|
args: --disable-all -c dummy.yml -E=gofumpt --max-same-issues=0 --timeout 5m --modules-download-mode=mod
|
||||||
|
|
||||||
|
e2e:
|
||||||
|
name: e2e-test
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: [ frontend, backend, linter ]
|
||||||
|
services:
|
||||||
|
mysql:
|
||||||
|
image: mysql:5.7
|
||||||
|
env:
|
||||||
|
MYSQL_DATABASE: casdoor
|
||||||
|
MYSQL_ROOT_PASSWORD: 123456
|
||||||
|
ports:
|
||||||
|
- 3306:3306
|
||||||
|
options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- uses: actions/setup-go@v2
|
||||||
|
with:
|
||||||
|
go-version: '^1.16.5'
|
||||||
|
- uses: actions/setup-node@v2
|
||||||
|
with:
|
||||||
|
node-version: 16
|
||||||
|
- name: front install
|
||||||
|
run: yarn install
|
||||||
|
working-directory: ./web
|
||||||
|
- name: front start
|
||||||
|
run: nohup yarn start &
|
||||||
|
working-directory: ./web
|
||||||
|
- name: back start
|
||||||
|
run: nohup go run ./main.go &
|
||||||
|
working-directory: ./
|
||||||
|
- name: Sleep for starting
|
||||||
|
run: sleep 60s
|
||||||
|
shell: bash
|
||||||
|
- name: e2e
|
||||||
|
run: npx cypress run --spec "**/e2e/**.cy.js"
|
||||||
|
working-directory: ./web
|
||||||
|
|
||||||
release-and-push:
|
release-and-push:
|
||||||
name: Release And Push
|
name: Release And Push
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
if: github.repository == 'casdoor/casdoor' && github.event_name == 'push'
|
if: github.repository == 'casdoor/casdoor' && github.event_name == 'push'
|
||||||
needs: [ frontend, backend, linter ]
|
needs: [ frontend, backend, linter, e2e ]
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v2
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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
|
||||||
@ -242,6 +242,7 @@ func (c *ApiController) Signup() {
|
|||||||
// @router /logout [get,post]
|
// @router /logout [get,post]
|
||||||
func (c *ApiController) Logout() {
|
func (c *ApiController) Logout() {
|
||||||
user := c.GetSessionUsername()
|
user := c.GetSessionUsername()
|
||||||
|
object.DeleteSessionId(user, c.Ctx.Input.CruSession.SessionID())
|
||||||
util.LogInfo(c.Ctx, "API: [%s] logged out", user)
|
util.LogInfo(c.Ctx, "API: [%s] logged out", user)
|
||||||
|
|
||||||
application := c.GetSessionApplication()
|
application := c.GetSessionApplication()
|
||||||
@ -271,12 +272,17 @@ func (c *ApiController) GetAccount() {
|
|||||||
user = object.ExtendManagedAccountsWithUser(user)
|
user = object.ExtendManagedAccountsWithUser(user)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
object.ExtendUserWithRolesAndPermissions(user)
|
||||||
|
|
||||||
|
user.Permissions = object.GetMaskedPermissions(user.Permissions)
|
||||||
|
user.Roles = object.GetMaskedRoles(user.Roles)
|
||||||
|
|
||||||
organization := object.GetMaskedOrganization(object.GetOrganizationByUser(user))
|
organization := object.GetMaskedOrganization(object.GetOrganizationByUser(user))
|
||||||
resp := Response{
|
resp := Response{
|
||||||
Status: "ok",
|
Status: "ok",
|
||||||
Sub: user.Id,
|
Sub: user.Id,
|
||||||
Name: user.Name,
|
Name: user.Name,
|
||||||
Data: user,
|
Data: object.GetMaskedUser(user),
|
||||||
Data2: organization,
|
Data2: organization,
|
||||||
}
|
}
|
||||||
c.Data["json"] = resp
|
c.Data["json"] = resp
|
||||||
|
@ -86,7 +86,7 @@ func (c *ApiController) GetUserApplication() {
|
|||||||
id := c.Input().Get("id")
|
id := c.Input().Get("id")
|
||||||
user := object.GetUser(id)
|
user := object.GetUser(id)
|
||||||
if user == nil {
|
if user == nil {
|
||||||
c.ResponseError(fmt.Sprintf(c.T("application:The user: %s doesn't exist"), id))
|
c.ResponseError(fmt.Sprintf(c.T("general:The user: %s doesn't exist"), id))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -103,12 +103,12 @@ func (c *ApiController) HandleLoggedIn(application *object.Application, user *ob
|
|||||||
resp = tokenToResponse(token)
|
resp = tokenToResponse(token)
|
||||||
}
|
}
|
||||||
} else if form.Type == ResponseTypeSaml { // saml flow
|
} else if form.Type == ResponseTypeSaml { // saml flow
|
||||||
res, redirectUrl, err := object.GetSamlResponse(application, user, form.SamlRequest, c.Ctx.Request.Host)
|
res, redirectUrl, method, err := object.GetSamlResponse(application, user, form.SamlRequest, c.Ctx.Request.Host)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.ResponseError(err.Error(), nil)
|
c.ResponseError(err.Error(), nil)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
resp = &Response{Status: "ok", Msg: "", Data: res, Data2: redirectUrl}
|
resp = &Response{Status: "ok", Msg: "", Data: res, Data2: map[string]string{"redirectUrl": redirectUrl, "method": method}}
|
||||||
} else if form.Type == ResponseTypeCas {
|
} else if form.Type == ResponseTypeCas {
|
||||||
// not oauth but CAS SSO protocol
|
// not oauth but CAS SSO protocol
|
||||||
service := c.Input().Get("service")
|
service := c.Input().Get("service")
|
||||||
@ -139,6 +139,10 @@ func (c *ApiController) HandleLoggedIn(application *object.Application, user *ob
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if resp.Status == "ok" {
|
||||||
|
object.SetSession(user.GetId(), c.Ctx.Input.CruSession.SessionID())
|
||||||
|
}
|
||||||
|
|
||||||
return resp
|
return resp
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -170,7 +174,7 @@ func (c *ApiController) GetApplicationLogin() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func setHttpClient(idProvider idp.IdProvider, providerType string) {
|
func setHttpClient(idProvider idp.IdProvider, providerType string) {
|
||||||
if providerType == "GitHub" || providerType == "Google" || providerType == "Facebook" || providerType == "LinkedIn" || providerType == "Steam" {
|
if providerType == "GitHub" || providerType == "Google" || providerType == "Facebook" || providerType == "LinkedIn" || providerType == "Steam" || providerType == "Line" {
|
||||||
idProvider.SetHttpClient(proxy.ProxyHttpClient)
|
idProvider.SetHttpClient(proxy.ProxyHttpClient)
|
||||||
} else {
|
} else {
|
||||||
idProvider.SetHttpClient(proxy.DefaultHttpClient)
|
idProvider.SetHttpClient(proxy.DefaultHttpClient)
|
||||||
@ -205,7 +209,7 @@ func (c *ApiController) Login() {
|
|||||||
if form.Username != "" {
|
if form.Username != "" {
|
||||||
if form.Type == ResponseTypeLogin {
|
if form.Type == ResponseTypeLogin {
|
||||||
if c.GetSessionUsername() != "" {
|
if c.GetSessionUsername() != "" {
|
||||||
c.ResponseError(c.T("auth:Please sign out first before signing in"), c.GetSessionUsername())
|
c.ResponseError(c.T("account:Please sign out first before signing in"), c.GetSessionUsername())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -222,12 +226,13 @@ func (c *ApiController) Login() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// check result through Email or Phone
|
// check result through Email or Phone
|
||||||
|
var checkDest string
|
||||||
if strings.Contains(form.Username, "@") {
|
if strings.Contains(form.Username, "@") {
|
||||||
verificationCodeType = "email"
|
verificationCodeType = "email"
|
||||||
if user != nil && util.GetMaskedEmail(user.Email) == form.Username {
|
if user != nil && util.GetMaskedEmail(user.Email) == form.Username {
|
||||||
form.Username = user.Email
|
form.Username = user.Email
|
||||||
}
|
}
|
||||||
checkResult = object.CheckVerificationCode(form.Username, form.Code, c.GetAcceptLanguage())
|
checkDest = form.Username
|
||||||
} else {
|
} else {
|
||||||
verificationCodeType = "phone"
|
verificationCodeType = "phone"
|
||||||
if len(form.PhonePrefix) == 0 {
|
if len(form.PhonePrefix) == 0 {
|
||||||
@ -238,11 +243,16 @@ func (c *ApiController) Login() {
|
|||||||
if user != nil && util.GetMaskedPhone(user.Phone) == form.Username {
|
if user != nil && util.GetMaskedPhone(user.Phone) == form.Username {
|
||||||
form.Username = user.Phone
|
form.Username = user.Phone
|
||||||
}
|
}
|
||||||
checkPhone := fmt.Sprintf("+%s%s", form.PhonePrefix, form.Username)
|
checkDest = fmt.Sprintf("+%s%s", form.PhonePrefix, form.Username)
|
||||||
checkResult = object.CheckVerificationCode(checkPhone, form.Code, c.GetAcceptLanguage())
|
|
||||||
}
|
}
|
||||||
|
user = object.GetUserByFields(form.Organization, form.Username)
|
||||||
|
if user == nil {
|
||||||
|
c.ResponseError(fmt.Sprintf(c.T("general:The user: %s doesn't exist"), util.GetId(form.Organization, form.Username)))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
checkResult = object.CheckSigninCode(user, checkDest, form.Code, c.GetAcceptLanguage())
|
||||||
if len(checkResult) != 0 {
|
if len(checkResult) != 0 {
|
||||||
responseText := fmt.Sprintf("%s%s", verificationCodeType, checkResult)
|
responseText := fmt.Sprintf("%s - %s", verificationCodeType, checkResult)
|
||||||
c.ResponseError(responseText)
|
c.ResponseError(responseText)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -253,18 +263,16 @@ func (c *ApiController) Login() {
|
|||||||
} else {
|
} else {
|
||||||
object.DisableVerificationCode(fmt.Sprintf("+%s%s", form.PhonePrefix, form.Username))
|
object.DisableVerificationCode(fmt.Sprintf("+%s%s", form.PhonePrefix, form.Username))
|
||||||
}
|
}
|
||||||
|
|
||||||
user = object.GetUserByFields(form.Organization, form.Username)
|
|
||||||
if user == nil {
|
|
||||||
c.ResponseError(fmt.Sprintf(c.T("auth:The user: %s/%s doesn't exist"), form.Organization, form.Username))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
application := object.GetApplication(fmt.Sprintf("admin/%s", form.Application))
|
application := object.GetApplication(fmt.Sprintf("admin/%s", form.Application))
|
||||||
if application == nil {
|
if application == nil {
|
||||||
c.ResponseError(fmt.Sprintf(c.T("auth:The application: %s does not exist"), form.Application))
|
c.ResponseError(fmt.Sprintf(c.T("auth:The application: %s does not exist"), form.Application))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if !application.EnablePassword {
|
||||||
|
c.ResponseError(c.T("auth:The login method: login with password is not enabled for the application"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if object.CheckToEnableCaptcha(application) {
|
if object.CheckToEnableCaptcha(application) {
|
||||||
isHuman, err := captcha.VerifyCaptchaByCaptchaType(form.CaptchaType, form.CaptchaToken, form.ClientSecret)
|
isHuman, err := captcha.VerifyCaptchaByCaptchaType(form.CaptchaType, form.CaptchaToken, form.ClientSecret)
|
||||||
@ -412,9 +420,9 @@ 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("account:Get init score failed, error: %w"), err).Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -460,13 +468,13 @@ func (c *ApiController) Login() {
|
|||||||
record2.User = user.Name
|
record2.User = user.Name
|
||||||
util.SafeGoroutine(func() { object.AddRecord(record2) })
|
util.SafeGoroutine(func() { object.AddRecord(record2) })
|
||||||
} else if provider.Category == "SAML" {
|
} else if provider.Category == "SAML" {
|
||||||
resp = &Response{Status: "error", Msg: "The account does not exist"}
|
resp = &Response{Status: "error", Msg: fmt.Sprintf(c.T("general:The user: %s doesn't exist"), util.GetId(application.Organization, userInfo.Id))}
|
||||||
}
|
}
|
||||||
// resp = &Response{Status: "ok", Msg: "", Data: res}
|
// resp = &Response{Status: "ok", Msg: "", Data: res}
|
||||||
} else { // form.Method != "signup"
|
} else { // form.Method != "signup"
|
||||||
userId := c.GetSessionUsername()
|
userId := c.GetSessionUsername()
|
||||||
if userId == "" {
|
if userId == "" {
|
||||||
c.ResponseError(c.T("auth:The account does not exist"), userInfo)
|
c.ResponseError(fmt.Sprintf(c.T("general:The user: %s doesn't exist"), util.GetId(application.Organization, userInfo.Id)), userInfo)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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() {
|
||||||
|
@ -47,7 +47,7 @@ func (c *ApiController) BatchEnforce() {
|
|||||||
func (c *ApiController) GetAllObjects() {
|
func (c *ApiController) GetAllObjects() {
|
||||||
userId := c.GetSessionUsername()
|
userId := c.GetSessionUsername()
|
||||||
if userId == "" {
|
if userId == "" {
|
||||||
c.ResponseError(c.T("enforcer:Please sign in first"))
|
c.ResponseError(c.T("general:Please login first"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -58,7 +58,7 @@ func (c *ApiController) GetAllObjects() {
|
|||||||
func (c *ApiController) GetAllActions() {
|
func (c *ApiController) GetAllActions() {
|
||||||
userId := c.GetSessionUsername()
|
userId := c.GetSessionUsername()
|
||||||
if userId == "" {
|
if userId == "" {
|
||||||
c.ResponseError(c.T("enforcer:Please sign in first"))
|
c.ResponseError(c.T("general:Please login first"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -69,7 +69,7 @@ func (c *ApiController) GetAllActions() {
|
|||||||
func (c *ApiController) GetAllRoles() {
|
func (c *ApiController) GetAllRoles() {
|
||||||
userId := c.GetSessionUsername()
|
userId := c.GetSessionUsername()
|
||||||
if userId == "" {
|
if userId == "" {
|
||||||
c.ResponseError(c.T("enforcer:Please sign in first"))
|
c.ResponseError(c.T("general:Please login first"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -141,13 +141,13 @@ func (c *ApiController) BuyProduct() {
|
|||||||
|
|
||||||
userId := c.GetSessionUsername()
|
userId := c.GetSessionUsername()
|
||||||
if userId == "" {
|
if userId == "" {
|
||||||
c.ResponseError(c.T("product:Please login first"))
|
c.ResponseError(c.T("general:Please login first"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
user := object.GetUser(userId)
|
user := object.GetUser(userId)
|
||||||
if user == nil {
|
if user == nil {
|
||||||
c.ResponseError(fmt.Sprintf(c.T("product:The user: %s doesn't exist"), userId))
|
c.ResponseError(fmt.Sprintf(c.T("general:The user: %s doesn't exist"), userId))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
68
controllers/session.go
Normal file
68
controllers/session.go
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
package controllers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
|
||||||
|
"github.com/beego/beego/utils/pagination"
|
||||||
|
"github.com/casdoor/casdoor/object"
|
||||||
|
"github.com/casdoor/casdoor/util"
|
||||||
|
)
|
||||||
|
|
||||||
|
// DeleteSession
|
||||||
|
// @Title DeleteSession
|
||||||
|
// @Tag Session API
|
||||||
|
// @Description Delete session by userId
|
||||||
|
// @Param ID query string true "The ID(owner/name) of user."
|
||||||
|
// @Success 200 {array} string The Response object
|
||||||
|
// @router /delete-session [post]
|
||||||
|
func (c *ApiController) DeleteSession() {
|
||||||
|
var session object.Session
|
||||||
|
err := json.Unmarshal(c.Ctx.Input.RequestBody, &session)
|
||||||
|
if err != nil {
|
||||||
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c.Data["json"] = wrapActionResponse(object.DeleteSession(util.GetId(session.Owner, session.Name)))
|
||||||
|
c.ServeJSON()
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetSessions
|
||||||
|
// @Title GetSessions
|
||||||
|
// @Tag Session API
|
||||||
|
// @Description Get organization user sessions
|
||||||
|
// @Param owner query string true "The organization name"
|
||||||
|
// @Success 200 {array} string The Response object
|
||||||
|
// @router /get-sessions [get]
|
||||||
|
func (c *ApiController) GetSessions() {
|
||||||
|
limit := c.Input().Get("pageSize")
|
||||||
|
page := c.Input().Get("p")
|
||||||
|
field := c.Input().Get("field")
|
||||||
|
value := c.Input().Get("value")
|
||||||
|
sortField := c.Input().Get("sortField")
|
||||||
|
sortOrder := c.Input().Get("sortOrder")
|
||||||
|
owner := c.Input().Get("owner")
|
||||||
|
if limit == "" || page == "" {
|
||||||
|
c.Data["json"] = object.GetSessions(owner)
|
||||||
|
c.ServeJSON()
|
||||||
|
} else {
|
||||||
|
limit := util.ParseInt(limit)
|
||||||
|
paginator := pagination.SetPaginator(c.Ctx, limit, int64(object.GetSessionCount(owner, field, value)))
|
||||||
|
sessions := object.GetPaginationSessions(owner, paginator.Offset(), limit, field, value, sortField, sortOrder)
|
||||||
|
c.ResponseOk(sessions, paginator.Nums())
|
||||||
|
}
|
||||||
|
}
|
@ -40,7 +40,7 @@ func (c *ApiController) GetSystemInfo() {
|
|||||||
|
|
||||||
user := object.GetUser(id)
|
user := object.GetUser(id)
|
||||||
if user == nil || !user.IsGlobalAdmin {
|
if user == nil || !user.IsGlobalAdmin {
|
||||||
c.ResponseError(c.T("system_info:You are not authorized to access this resource"))
|
c.ResponseError(c.T("auth:Unauthorized operation"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -150,7 +150,7 @@ func (c *ApiController) GetOAuthCode() {
|
|||||||
codeChallenge := c.Input().Get("code_challenge")
|
codeChallenge := c.Input().Get("code_challenge")
|
||||||
|
|
||||||
if challengeMethod != "S256" && challengeMethod != "null" && challengeMethod != "" {
|
if challengeMethod != "S256" && challengeMethod != "null" && challengeMethod != "" {
|
||||||
c.ResponseError(c.T("token:Challenge method should be S256"))
|
c.ResponseError(c.T("auth:Challenge method should be S256"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
host := c.Ctx.Request.Host
|
host := c.Ctx.Request.Host
|
||||||
@ -261,7 +261,7 @@ func (c *ApiController) TokenLogout() {
|
|||||||
flag, application := object.DeleteTokenByAccessToken(token)
|
flag, application := object.DeleteTokenByAccessToken(token)
|
||||||
redirectUri := c.Input().Get("post_logout_redirect_uri")
|
redirectUri := c.Input().Get("post_logout_redirect_uri")
|
||||||
state := c.Input().Get("state")
|
state := c.Input().Get("state")
|
||||||
if application != nil && object.CheckRedirectUriValid(application, redirectUri) {
|
if application != nil && application.IsRedirectUriValid(redirectUri) {
|
||||||
c.Ctx.Redirect(http.StatusFound, redirectUri+"?state="+state)
|
c.Ctx.Redirect(http.StatusFound, redirectUri+"?state="+state)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -159,6 +159,12 @@ func (c *ApiController) UpdateUser() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
isGlobalAdmin := c.IsGlobalAdmin()
|
isGlobalAdmin := c.IsGlobalAdmin()
|
||||||
|
|
||||||
|
if pass, err := checkPermissionForUpdateUser(id, user, c); !pass {
|
||||||
|
c.ResponseError(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
affected := object.UpdateUser(id, &user, columns, isGlobalAdmin)
|
affected := object.UpdateUser(id, &user, columns, isGlobalAdmin)
|
||||||
if affected {
|
if affected {
|
||||||
object.UpdateUserToOriginalDatabase(&user)
|
object.UpdateUserToOriginalDatabase(&user)
|
||||||
@ -236,7 +242,7 @@ func (c *ApiController) GetEmailAndPhone() {
|
|||||||
|
|
||||||
user := object.GetUserByFields(form.Organization, form.Username)
|
user := object.GetUserByFields(form.Organization, form.Username)
|
||||||
if user == nil {
|
if user == nil {
|
||||||
c.ResponseError(fmt.Sprintf(c.T("user:The user: %s/%s doesn't exist"), form.Organization, form.Username))
|
c.ResponseError(fmt.Sprintf(c.T("general:The user: %s doesn't exist"), util.GetId(form.Organization, form.Username)))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
142
controllers/user_util.go
Normal file
142
controllers/user_util.go
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
// Copyright 2023 The Casdoor Authors. All Rights Reserved.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package controllers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
|
||||||
|
"github.com/casdoor/casdoor/object"
|
||||||
|
)
|
||||||
|
|
||||||
|
func checkPermissionForUpdateUser(userId string, newUser object.User, c *ApiController) (bool, string) {
|
||||||
|
oldUser := object.GetUser(userId)
|
||||||
|
organization := object.GetOrganizationByUser(oldUser)
|
||||||
|
var itemsChanged []*object.AccountItem
|
||||||
|
|
||||||
|
if oldUser.Owner != newUser.Owner {
|
||||||
|
item := object.GetAccountItemByName("Organization", organization)
|
||||||
|
itemsChanged = append(itemsChanged, item)
|
||||||
|
}
|
||||||
|
if oldUser.Name != newUser.Name {
|
||||||
|
item := object.GetAccountItemByName("Name", organization)
|
||||||
|
itemsChanged = append(itemsChanged, item)
|
||||||
|
}
|
||||||
|
if oldUser.Id != newUser.Id {
|
||||||
|
item := object.GetAccountItemByName("ID", organization)
|
||||||
|
itemsChanged = append(itemsChanged, item)
|
||||||
|
}
|
||||||
|
if oldUser.DisplayName != newUser.DisplayName {
|
||||||
|
item := object.GetAccountItemByName("Display name", organization)
|
||||||
|
itemsChanged = append(itemsChanged, item)
|
||||||
|
}
|
||||||
|
if oldUser.Avatar != newUser.Avatar {
|
||||||
|
item := object.GetAccountItemByName("Avatar", organization)
|
||||||
|
itemsChanged = append(itemsChanged, item)
|
||||||
|
}
|
||||||
|
if oldUser.Type != newUser.Type {
|
||||||
|
item := object.GetAccountItemByName("User type", organization)
|
||||||
|
itemsChanged = append(itemsChanged, item)
|
||||||
|
}
|
||||||
|
// The password is *** when not modified
|
||||||
|
if oldUser.Password != newUser.Password && newUser.Password != "***" {
|
||||||
|
item := object.GetAccountItemByName("Password", organization)
|
||||||
|
itemsChanged = append(itemsChanged, item)
|
||||||
|
}
|
||||||
|
if oldUser.Email != newUser.Email {
|
||||||
|
item := object.GetAccountItemByName("Email", organization)
|
||||||
|
itemsChanged = append(itemsChanged, item)
|
||||||
|
}
|
||||||
|
if oldUser.Phone != newUser.Phone {
|
||||||
|
item := object.GetAccountItemByName("Phone", organization)
|
||||||
|
itemsChanged = append(itemsChanged, item)
|
||||||
|
}
|
||||||
|
if oldUser.Region != newUser.Region {
|
||||||
|
item := object.GetAccountItemByName("Country/Region", organization)
|
||||||
|
itemsChanged = append(itemsChanged, item)
|
||||||
|
}
|
||||||
|
if oldUser.Location != newUser.Location {
|
||||||
|
item := object.GetAccountItemByName("Location", organization)
|
||||||
|
itemsChanged = append(itemsChanged, item)
|
||||||
|
}
|
||||||
|
if oldUser.Affiliation != newUser.Affiliation {
|
||||||
|
item := object.GetAccountItemByName("Affiliation", organization)
|
||||||
|
itemsChanged = append(itemsChanged, item)
|
||||||
|
}
|
||||||
|
if oldUser.Title != newUser.Title {
|
||||||
|
item := object.GetAccountItemByName("Title", organization)
|
||||||
|
itemsChanged = append(itemsChanged, item)
|
||||||
|
}
|
||||||
|
if oldUser.Homepage != newUser.Homepage {
|
||||||
|
item := object.GetAccountItemByName("Homepage", organization)
|
||||||
|
itemsChanged = append(itemsChanged, item)
|
||||||
|
}
|
||||||
|
if oldUser.Bio != newUser.Bio {
|
||||||
|
item := object.GetAccountItemByName("Bio", organization)
|
||||||
|
itemsChanged = append(itemsChanged, item)
|
||||||
|
}
|
||||||
|
if oldUser.Tag != newUser.Tag {
|
||||||
|
item := object.GetAccountItemByName("Tag", organization)
|
||||||
|
itemsChanged = append(itemsChanged, item)
|
||||||
|
}
|
||||||
|
if oldUser.SignupApplication != newUser.SignupApplication {
|
||||||
|
item := object.GetAccountItemByName("Signup application", organization)
|
||||||
|
itemsChanged = append(itemsChanged, item)
|
||||||
|
}
|
||||||
|
|
||||||
|
oldUserRolesJson, _ := json.Marshal(oldUser.Roles)
|
||||||
|
newUserRolesJson, _ := json.Marshal(newUser.Roles)
|
||||||
|
if string(oldUserRolesJson) != string(newUserRolesJson) {
|
||||||
|
item := object.GetAccountItemByName("Roles", organization)
|
||||||
|
itemsChanged = append(itemsChanged, item)
|
||||||
|
}
|
||||||
|
|
||||||
|
oldUserPermissionJson, _ := json.Marshal(oldUser.Permissions)
|
||||||
|
newUserPermissionJson, _ := json.Marshal(newUser.Permissions)
|
||||||
|
if string(oldUserPermissionJson) != string(newUserPermissionJson) {
|
||||||
|
item := object.GetAccountItemByName("Permissions", organization)
|
||||||
|
itemsChanged = append(itemsChanged, item)
|
||||||
|
}
|
||||||
|
|
||||||
|
oldUserPropertiesJson, _ := json.Marshal(oldUser.Properties)
|
||||||
|
newUserPropertiesJson, _ := json.Marshal(newUser.Properties)
|
||||||
|
if string(oldUserPropertiesJson) != string(newUserPropertiesJson) {
|
||||||
|
item := object.GetAccountItemByName("Properties", organization)
|
||||||
|
itemsChanged = append(itemsChanged, item)
|
||||||
|
}
|
||||||
|
|
||||||
|
if oldUser.IsAdmin != newUser.IsAdmin {
|
||||||
|
item := object.GetAccountItemByName("Is admin", organization)
|
||||||
|
itemsChanged = append(itemsChanged, item)
|
||||||
|
}
|
||||||
|
if oldUser.IsGlobalAdmin != newUser.IsGlobalAdmin {
|
||||||
|
item := object.GetAccountItemByName("Is global admin", organization)
|
||||||
|
itemsChanged = append(itemsChanged, item)
|
||||||
|
}
|
||||||
|
if oldUser.IsForbidden != newUser.IsForbidden {
|
||||||
|
item := object.GetAccountItemByName("Is forbidden", organization)
|
||||||
|
itemsChanged = append(itemsChanged, item)
|
||||||
|
}
|
||||||
|
if oldUser.IsDeleted != newUser.IsDeleted {
|
||||||
|
item := object.GetAccountItemByName("Is deleted", organization)
|
||||||
|
itemsChanged = append(itemsChanged, item)
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := range itemsChanged {
|
||||||
|
if pass, err := object.CheckAccountItemModifyRule(itemsChanged[i], c.getCurrentUser(), c.GetAcceptLanguage()); !pass {
|
||||||
|
return pass, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true, ""
|
||||||
|
}
|
@ -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("general:Please login first"), "Please login first")
|
||||||
return "", false
|
return "", false
|
||||||
}
|
}
|
||||||
return userId, true
|
return userId, true
|
||||||
@ -100,7 +100,7 @@ func (c *ApiController) RequireSignedInUser() (*object.User, bool) {
|
|||||||
user := object.GetUser(userId)
|
user := object.GetUser(userId)
|
||||||
if user == nil {
|
if user == nil {
|
||||||
c.ClearUserSession()
|
c.ClearUserSession()
|
||||||
c.ResponseError(fmt.Sprintf(c.T("util:The user: %s doesn't exist"), userId))
|
c.ResponseError(fmt.Sprintf(c.T("general:The user: %s doesn't exist"), userId))
|
||||||
return nil, false
|
return nil, false
|
||||||
}
|
}
|
||||||
return user, true
|
return user, true
|
||||||
@ -119,9 +119,13 @@ 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) {
|
||||||
|
if organization != nil {
|
||||||
|
return organization.InitScore, nil
|
||||||
|
} else {
|
||||||
return strconv.Atoi(conf.GetConfigString("initScore"))
|
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) {
|
||||||
providerName := c.Input().Get("provider")
|
providerName := c.Input().Get("provider")
|
||||||
|
@ -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 == "" {
|
||||||
@ -98,7 +99,7 @@ func (c *ApiController) SendVerificationCode() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if checkUser == "true" && user == nil && object.GetUserByFields(organization.Name, dest) == nil {
|
if checkUser == "true" && user == nil && object.GetUserByFields(organization.Name, dest) == nil {
|
||||||
c.ResponseError(c.T("verification:Please login first"))
|
c.ResponseError(c.T("general:Please login first"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -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
|
||||||
}
|
}
|
||||||
|
@ -35,7 +35,7 @@ func (c *ApiController) WebAuthnSignupBegin() {
|
|||||||
webauthnObj := object.GetWebAuthnObject(c.Ctx.Request.Host)
|
webauthnObj := object.GetWebAuthnObject(c.Ctx.Request.Host)
|
||||||
user := c.getCurrentUser()
|
user := c.getCurrentUser()
|
||||||
if user == nil {
|
if user == nil {
|
||||||
c.ResponseError(c.T("webauthn:Please login first"))
|
c.ResponseError(c.T("general:Please login first"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -66,7 +66,7 @@ func (c *ApiController) WebAuthnSignupFinish() {
|
|||||||
webauthnObj := object.GetWebAuthnObject(c.Ctx.Request.Host)
|
webauthnObj := object.GetWebAuthnObject(c.Ctx.Request.Host)
|
||||||
user := c.getCurrentUser()
|
user := c.getCurrentUser()
|
||||||
if user == nil {
|
if user == nil {
|
||||||
c.ResponseError(c.T("webauthn:Please login first"))
|
c.ResponseError(c.T("general:Please login first"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
sessionObj := c.GetSession("registration")
|
sessionObj := c.GetSession("registration")
|
||||||
@ -101,7 +101,7 @@ func (c *ApiController) WebAuthnSigninBegin() {
|
|||||||
userName := c.Input().Get("name")
|
userName := c.Input().Get("name")
|
||||||
user := object.GetUserByFields(userOwner, userName)
|
user := object.GetUserByFields(userOwner, userName)
|
||||||
if user == nil {
|
if user == nil {
|
||||||
c.ResponseError(fmt.Sprintf(c.T("webauthn:The user: %s/%s doesn't exist"), userOwner, userName))
|
c.ResponseError(fmt.Sprintf(c.T("general:The user: %s doesn't exist"), util.GetId(userOwner, userName)))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if len(user.WebauthnCredentials) == 0 {
|
if len(user.WebauthnCredentials) == 0 {
|
||||||
|
@ -26,16 +26,22 @@ import (
|
|||||||
|
|
||||||
type I18nData map[string]map[string]string
|
type I18nData map[string]map[string]string
|
||||||
|
|
||||||
var reI18n *regexp.Regexp
|
var (
|
||||||
|
reI18nFrontend *regexp.Regexp
|
||||||
|
reI18nBackendObject *regexp.Regexp
|
||||||
|
reI18nBackendController *regexp.Regexp
|
||||||
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
reI18n, _ = regexp.Compile("i18next.t\\(\"(.*?)\"\\)")
|
reI18nFrontend, _ = regexp.Compile("i18next.t\\(\"(.*?)\"\\)")
|
||||||
|
reI18nBackendObject, _ = regexp.Compile("i18n.Translate\\((.*?)\"\\)")
|
||||||
|
reI18nBackendController, _ = regexp.Compile("c.T\\((.*?)\"\\)")
|
||||||
}
|
}
|
||||||
|
|
||||||
func getAllI18nStrings(fileContent string) []string {
|
func getAllI18nStringsFrontend(fileContent string) []string {
|
||||||
res := []string{}
|
res := []string{}
|
||||||
|
|
||||||
matches := reI18n.FindAllStringSubmatch(fileContent, -1)
|
matches := reI18nFrontend.FindAllStringSubmatch(fileContent, -1)
|
||||||
if matches == nil {
|
if matches == nil {
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
@ -46,17 +52,39 @@ func getAllI18nStrings(fileContent string) []string {
|
|||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
func getAllJsFilePaths() []string {
|
func getAllI18nStringsBackend(fileContent string, isObjectPackage bool) []string {
|
||||||
path := "../web/src"
|
|
||||||
|
|
||||||
res := []string{}
|
res := []string{}
|
||||||
err := filepath.Walk(path,
|
if isObjectPackage {
|
||||||
|
matches := reI18nBackendObject.FindAllStringSubmatch(fileContent, -1)
|
||||||
|
if matches == nil {
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
for _, match := range matches {
|
||||||
|
match := strings.SplitN(match[1], ",", 2)
|
||||||
|
res = append(res, match[1][2:])
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
matches := reI18nBackendController.FindAllStringSubmatch(fileContent, -1)
|
||||||
|
if matches == nil {
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
for _, match := range matches {
|
||||||
|
res = append(res, match[1][1:])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
func getAllFilePathsInFolder(folder string, fileSuffix string) []string {
|
||||||
|
res := []string{}
|
||||||
|
err := filepath.Walk(folder,
|
||||||
func(path string, info os.FileInfo, err error) error {
|
func(path string, info os.FileInfo, err error) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if !strings.HasSuffix(info.Name(), ".js") {
|
if !strings.HasSuffix(info.Name(), fileSuffix) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -71,12 +99,25 @@ func getAllJsFilePaths() []string {
|
|||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseToData() *I18nData {
|
func parseEnData(category string) *I18nData {
|
||||||
|
var paths []string
|
||||||
|
if category == "backend" {
|
||||||
|
paths = getAllFilePathsInFolder("../", ".go")
|
||||||
|
} else {
|
||||||
|
paths = getAllFilePathsInFolder("../web/src", ".js")
|
||||||
|
}
|
||||||
|
|
||||||
allWords := []string{}
|
allWords := []string{}
|
||||||
paths := getAllJsFilePaths()
|
|
||||||
for _, path := range paths {
|
for _, path := range paths {
|
||||||
fileContent := util.ReadStringFromPath(path)
|
fileContent := util.ReadStringFromPath(path)
|
||||||
words := getAllI18nStrings(fileContent)
|
|
||||||
|
var words []string
|
||||||
|
if category == "backend" {
|
||||||
|
isObjectPackage := strings.Contains(path, "object")
|
||||||
|
words = getAllI18nStringsBackend(fileContent, isObjectPackage)
|
||||||
|
} else {
|
||||||
|
words = getAllI18nStringsFrontend(fileContent)
|
||||||
|
}
|
||||||
allWords = append(allWords, words...)
|
allWords = append(allWords, words...)
|
||||||
}
|
}
|
||||||
fmt.Printf("%v\n", allWords)
|
fmt.Printf("%v\n", allWords)
|
||||||
|
@ -1,115 +0,0 @@
|
|||||||
// 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.
|
|
||||||
|
|
||||||
package i18n
|
|
||||||
|
|
||||||
import (
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"regexp"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/casdoor/casdoor/util"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
reI18nBackendObject *regexp.Regexp
|
|
||||||
re18nBackendController *regexp.Regexp
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
reI18nBackendObject, _ = regexp.Compile("i18n.Translate\\((.*?)\"\\)")
|
|
||||||
re18nBackendController, _ = regexp.Compile("c.T\\((.*?)\"\\)")
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetAllI18nStrings(fileContent string, path string) []string {
|
|
||||||
res := []string{}
|
|
||||||
if strings.Contains(path, "object") {
|
|
||||||
matches := reI18nBackendObject.FindAllStringSubmatch(fileContent, -1)
|
|
||||||
if matches == nil {
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
for _, match := range matches {
|
|
||||||
match := strings.SplitN(match[1], ",", 2)
|
|
||||||
res = append(res, match[1][2:])
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
matches := re18nBackendController.FindAllStringSubmatch(fileContent, -1)
|
|
||||||
if matches == nil {
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
for _, match := range matches {
|
|
||||||
res = append(res, match[1][1:])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
|
|
||||||
func getAllGoFilePaths() []string {
|
|
||||||
path := "../"
|
|
||||||
|
|
||||||
res := []string{}
|
|
||||||
err := filepath.Walk(path,
|
|
||||||
func(path string, info os.FileInfo, err error) error {
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if !strings.HasSuffix(info.Name(), ".go") {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
res = append(res, path)
|
|
||||||
// fmt.Println(path, info.Name())
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
|
|
||||||
func getErrName(paths []string) map[string]string {
|
|
||||||
ErrName := make(map[string]string)
|
|
||||||
for i := 0; i < len(paths); i++ {
|
|
||||||
content := util.ReadStringFromPath(paths[i])
|
|
||||||
words := GetAllI18nStrings(content, paths[i])
|
|
||||||
for j := 0; j < len(words); j++ {
|
|
||||||
ErrName[words[j]] = paths[i]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ErrName
|
|
||||||
}
|
|
||||||
|
|
||||||
func getI18nJSONData(errName map[string]string) *I18nData {
|
|
||||||
data := I18nData{}
|
|
||||||
for k, v := range errName {
|
|
||||||
var index int
|
|
||||||
if strings.Contains(v, "/") {
|
|
||||||
index = strings.LastIndex(v, "/")
|
|
||||||
} else {
|
|
||||||
index = strings.LastIndex(v, "\\")
|
|
||||||
}
|
|
||||||
namespace := v[index+1 : len(v)-3]
|
|
||||||
key := k[len(namespace)+1:]
|
|
||||||
// fmt.Printf("k=%s,v=%s,namespace=%s,key=%s\n", k, v, namespace, key)
|
|
||||||
if _, ok := data[namespace]; !ok {
|
|
||||||
data[namespace] = map[string]string{}
|
|
||||||
}
|
|
||||||
data[namespace][key] = key
|
|
||||||
}
|
|
||||||
return &data
|
|
||||||
}
|
|
@ -15,50 +15,39 @@
|
|||||||
package i18n
|
package i18n
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func applyToOtherLanguage(dataEn *I18nData, lang string) {
|
func applyToOtherLanguage(category string, language string, i18nData *I18nData) {
|
||||||
dataOther := readI18nFile(lang)
|
newData := readI18nFile(category, language)
|
||||||
println(dataOther)
|
println(newData)
|
||||||
|
|
||||||
applyData(dataEn, dataOther)
|
applyData(i18nData, newData)
|
||||||
writeI18nFile(lang, dataEn)
|
writeI18nFile(category, language, i18nData)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGenerateI18nStringsForFrontend(t *testing.T) {
|
func TestGenerateI18nFrontend(t *testing.T) {
|
||||||
dataEn := parseToData()
|
enData := parseEnData("frontend")
|
||||||
writeI18nFile("en", dataEn)
|
writeI18nFile("frontend", "en", enData)
|
||||||
|
|
||||||
applyToOtherLanguage(dataEn, "de")
|
applyToOtherLanguage("frontend", "de", enData)
|
||||||
applyToOtherLanguage(dataEn, "fr")
|
applyToOtherLanguage("frontend", "es", enData)
|
||||||
applyToOtherLanguage(dataEn, "ja")
|
applyToOtherLanguage("frontend", "fr", enData)
|
||||||
applyToOtherLanguage(dataEn, "ko")
|
applyToOtherLanguage("frontend", "ja", enData)
|
||||||
applyToOtherLanguage(dataEn, "ru")
|
applyToOtherLanguage("frontend", "ko", enData)
|
||||||
applyToOtherLanguage(dataEn, "zh")
|
applyToOtherLanguage("frontend", "ru", enData)
|
||||||
|
applyToOtherLanguage("frontend", "zh", enData)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGenerateI18nStringsForBackend(t *testing.T) {
|
func TestGenerateI18nBackend(t *testing.T) {
|
||||||
paths := getAllGoFilePaths()
|
enData := parseEnData("backend")
|
||||||
|
writeI18nFile("backend", "en", enData)
|
||||||
|
|
||||||
errName := getErrName(paths)
|
applyToOtherLanguage("backend", "de", enData)
|
||||||
|
applyToOtherLanguage("backend", "es", enData)
|
||||||
dataEn := getI18nJSONData(errName)
|
applyToOtherLanguage("backend", "fr", enData)
|
||||||
|
applyToOtherLanguage("backend", "ja", enData)
|
||||||
writeI18nFile("backend_en", dataEn)
|
applyToOtherLanguage("backend", "ko", enData)
|
||||||
|
applyToOtherLanguage("backend", "ru", enData)
|
||||||
applyToOtherLanguage(dataEn, "backend_de")
|
applyToOtherLanguage("backend", "zh", enData)
|
||||||
applyToOtherLanguage(dataEn, "backend_es")
|
|
||||||
applyToOtherLanguage(dataEn, "backend_fr")
|
|
||||||
applyToOtherLanguage(dataEn, "backend_ja")
|
|
||||||
applyToOtherLanguage(dataEn, "backend_ko")
|
|
||||||
applyToOtherLanguage(dataEn, "backend_ru")
|
|
||||||
applyToOtherLanguage(dataEn, "backend_zh")
|
|
||||||
|
|
||||||
fmt.Println("Total Err Words:", len(errName))
|
|
||||||
|
|
||||||
for i := range errName {
|
|
||||||
fmt.Println(i)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -4,31 +4,28 @@
|
|||||||
"Get init score failed, error: %w": "Get init score failed, error: %w",
|
"Get init score failed, error: %w": "Get init score failed, error: %w",
|
||||||
"Invalid information": "Invalid information",
|
"Invalid information": "Invalid information",
|
||||||
"Phone: %s": "Phone: %s",
|
"Phone: %s": "Phone: %s",
|
||||||
|
"Please sign out first before signing in": "Please sign out first before signing in",
|
||||||
"Please sign out first before signing up": "Please sign out first before signing up",
|
"Please sign out first before signing up": "Please sign out first before signing up",
|
||||||
"The application does not allow to sign up new account": "The application does not allow to sign up new account"
|
"The application does not allow to sign up new account": "The application does not allow to sign up new account"
|
||||||
},
|
},
|
||||||
"application": {
|
"application": {
|
||||||
"Parameter organization is missing": "Parameter organization is missing",
|
"Parameter organization is missing": "Parameter organization is missing"
|
||||||
"The user: %s doesn't exist": "The user: %s doesn't exist"
|
|
||||||
},
|
},
|
||||||
"auth": {
|
"auth": {
|
||||||
"%s No phone prefix": "%s No phone prefix",
|
"%s No phone prefix": "%s No phone prefix",
|
||||||
"Challenge method should be S256": "Challenge method should be S256",
|
"Challenge method should be S256": "Challenge method should be S256",
|
||||||
"Failed to create user, user information is invalid: %s": "Failed to create user, user information is invalid: %s",
|
"Failed to create user, user information is invalid: %s": "Failed to create user, user information is invalid: %s",
|
||||||
"Failed to login in: %s": "Failed to login in: %s",
|
"Failed to login in: %s": "Failed to login in: %s",
|
||||||
"Get init score failed, error: %w": "Get init score failed, error: %w",
|
|
||||||
"Invalid token": "Invalid token",
|
"Invalid token": "Invalid token",
|
||||||
"Please sign out first before signing in": "Please sign out first before signing in",
|
|
||||||
"State expected: %s, but got: %s": "State expected: %s, but got: %s",
|
"State expected: %s, but got: %s": "State expected: %s, but got: %s",
|
||||||
"The account does not exist": "The account does not exist",
|
|
||||||
"The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account via %%s, please use another way to sign up": "The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account via %%s, please use another way to sign up",
|
"The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account via %%s, please use another way to sign up": "The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account via %%s, please use another way to sign up",
|
||||||
"The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support": "The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support",
|
"The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support": "The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support",
|
||||||
"The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)": "The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)",
|
"The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)": "The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)",
|
||||||
"The application: %s does not exist": "The application: %s does not exist",
|
"The application: %s does not exist": "The application: %s does not exist",
|
||||||
|
"The login method: login with password is not enabled for the application": "The login method: login with password is not enabled for the application",
|
||||||
"The provider type: %s is not supported": "The provider type: %s is not supported",
|
"The provider type: %s is not supported": "The provider type: %s is not supported",
|
||||||
"The provider: %s is not enabled for the application": "The provider: %s is not enabled for the application",
|
"The provider: %s is not enabled for the application": "The provider: %s is not enabled for the application",
|
||||||
"The user is forbidden to sign in, please contact the administrator": "The user is forbidden to sign in, please contact the administrator",
|
"The user is forbidden to sign in, please contact the administrator": "The user is forbidden to sign in, please contact the administrator",
|
||||||
"The user: %s/%s doesn't exist": "The user: %s/%s doesn't exist",
|
|
||||||
"Turing test failed.": "Turing test failed.",
|
"Turing test failed.": "Turing test failed.",
|
||||||
"Unauthorized operation": "Unauthorized operation",
|
"Unauthorized operation": "Unauthorized operation",
|
||||||
"Unknown authentication type (not password or provider), form = %s": "Unknown authentication type (not password or provider), form = %s"
|
"Unknown authentication type (not password or provider), form = %s": "Unknown authentication type (not password or provider), form = %s"
|
||||||
@ -53,11 +50,8 @@
|
|||||||
"Phone already exists": "Phone already exists",
|
"Phone already exists": "Phone already exists",
|
||||||
"Phone cannot be empty": "Phone cannot be empty",
|
"Phone cannot be empty": "Phone cannot be empty",
|
||||||
"Phone number is invalid": "Phone number is invalid",
|
"Phone number is invalid": "Phone number is invalid",
|
||||||
"Please login first": "Please login first",
|
|
||||||
"Session outdated, please login again": "Session outdated, please login again",
|
"Session outdated, please login again": "Session outdated, please login again",
|
||||||
"The user doesn't exist": "The user doesn't exist",
|
|
||||||
"The user is forbidden to sign in, please contact the administrator": "The user is forbidden to sign in, please contact the administrator",
|
"The user is forbidden to sign in, please contact the administrator": "The user is forbidden to sign in, please contact the administrator",
|
||||||
"The user: %s doesn't exist": "The user: %s doesn't exist",
|
|
||||||
"The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline.": "The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline.",
|
"The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline.": "The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline.",
|
||||||
"Username already exists": "Username already exists",
|
"Username already exists": "Username already exists",
|
||||||
"Username cannot be an email address": "Username cannot be an email address",
|
"Username cannot be an email address": "Username cannot be an email address",
|
||||||
@ -65,16 +59,13 @@
|
|||||||
"Username cannot start with a digit": "Username cannot start with a digit",
|
"Username cannot start with a digit": "Username cannot start with a digit",
|
||||||
"Username is too long (maximum is 39 characters).": "Username is too long (maximum is 39 characters).",
|
"Username is too long (maximum is 39 characters).": "Username is too long (maximum is 39 characters).",
|
||||||
"Username must have at least 2 characters": "Username must have at least 2 characters",
|
"Username must have at least 2 characters": "Username must have at least 2 characters",
|
||||||
"You don't have the permission to do this": "You don't have the permission to do this",
|
"You have entered the wrong password or code too many times, please wait for %d minutes and try again": "You have entered the wrong password or code too many times, please wait for %d minutes and try again",
|
||||||
"You have entered the wrong password too many times, please wait for %d minutes %d seconds and try again": "You have entered the wrong password too many times, please wait for %d minutes %d seconds and try again",
|
"password or code is incorrect, you have %d remaining chances": "password or code is incorrect, you have %d remaining chances",
|
||||||
"unsupported password type: %s": "unsupported password type: %s"
|
"unsupported password type: %s": "unsupported password type: %s"
|
||||||
},
|
},
|
||||||
"check_util": {
|
"general": {
|
||||||
"You have entered the wrong password too many times, please wait for %d minutes and try again": "You have entered the wrong password too many times, please wait for %d minutes and try again",
|
"Please login first": "Please login first",
|
||||||
"password is incorrect, you have %d remaining chances": "password is incorrect, you have %d remaining chances"
|
"The user: %s doesn't exist": "The user: %s doesn't exist"
|
||||||
},
|
|
||||||
"enforcer": {
|
|
||||||
"Please sign in first": "Please sign in first"
|
|
||||||
},
|
},
|
||||||
"ldap": {
|
"ldap": {
|
||||||
"Ldap server exist": "Ldap server exist",
|
"Ldap server exist": "Ldap server exist",
|
||||||
@ -93,10 +84,6 @@
|
|||||||
"The %s is immutable.": "The %s is immutable.",
|
"The %s is immutable.": "The %s is immutable.",
|
||||||
"Unknown modify rule %s.": "Unknown modify rule %s."
|
"Unknown modify rule %s.": "Unknown modify rule %s."
|
||||||
},
|
},
|
||||||
"product": {
|
|
||||||
"Please login first": "Please login first",
|
|
||||||
"The user: %s doesn't exist": "The user: %s doesn't exist"
|
|
||||||
},
|
|
||||||
"provider": {
|
"provider": {
|
||||||
"Invalid application id": "Invalid application id",
|
"Invalid application id": "Invalid application id",
|
||||||
"the provider: %s does not exist": "the provider: %s does not exist"
|
"the provider: %s does not exist": "the provider: %s does not exist"
|
||||||
@ -120,11 +107,7 @@
|
|||||||
"The objectKey: %s is not allowed": "The objectKey: %s is not allowed",
|
"The objectKey: %s is not allowed": "The objectKey: %s is not allowed",
|
||||||
"The provider type: %s is not supported": "The provider type: %s is not supported"
|
"The provider type: %s is not supported": "The provider type: %s is not supported"
|
||||||
},
|
},
|
||||||
"system_info": {
|
|
||||||
"You are not authorized to access this resource": "You are not authorized to access this resource"
|
|
||||||
},
|
|
||||||
"token": {
|
"token": {
|
||||||
"Challenge method should be S256": "Challenge method should be S256",
|
|
||||||
"Empty clientId or clientSecret": "Empty clientId or clientSecret",
|
"Empty clientId or clientSecret": "Empty clientId or clientSecret",
|
||||||
"Grant_type: %s is not supported in this application": "Grant_type: %s is not supported in this application",
|
"Grant_type: %s is not supported in this application": "Grant_type: %s is not supported in this application",
|
||||||
"Invalid application or wrong clientSecret": "Invalid application or wrong clientSecret",
|
"Invalid application or wrong clientSecret": "Invalid application or wrong clientSecret",
|
||||||
@ -134,8 +117,7 @@
|
|||||||
"user": {
|
"user": {
|
||||||
"Display name cannot be empty": "Display name cannot be empty",
|
"Display name cannot be empty": "Display name cannot be empty",
|
||||||
"New password cannot contain blank space.": "New password cannot contain blank space.",
|
"New password cannot contain blank space.": "New password cannot contain blank space.",
|
||||||
"New password must have at least 6 characters": "New password must have at least 6 characters",
|
"New password must have at least 6 characters": "New password must have at least 6 characters"
|
||||||
"The user: %s/%s doesn't exist": "The user: %s/%s doesn't exist"
|
|
||||||
},
|
},
|
||||||
"user_upload": {
|
"user_upload": {
|
||||||
"Failed to import users": "Failed to import users"
|
"Failed to import users": "Failed to import users"
|
||||||
@ -143,9 +125,7 @@
|
|||||||
"util": {
|
"util": {
|
||||||
"No application is found for userId: %s": "No application is found for userId: %s",
|
"No application is found for userId: %s": "No application is found for userId: %s",
|
||||||
"No provider for category: %s is found for application: %s": "No provider for category: %s is found for application: %s",
|
"No provider for category: %s is found for application: %s": "No provider for category: %s is found for application: %s",
|
||||||
"Please login first": "Please login first",
|
"The provider: %s is not found": "The provider: %s is not found"
|
||||||
"The provider: %s is not found": "The provider: %s is not found",
|
|
||||||
"The user: %s doesn't exist": "The user: %s doesn't exist"
|
|
||||||
},
|
},
|
||||||
"verification": {
|
"verification": {
|
||||||
"Code has not been sent yet!": "Code has not been sent yet!",
|
"Code has not been sent yet!": "Code has not been sent yet!",
|
||||||
@ -154,7 +134,6 @@
|
|||||||
"Missing parameter": "Missing parameter",
|
"Missing parameter": "Missing parameter",
|
||||||
"Organization does not exist": "Organization does not exist",
|
"Organization does not exist": "Organization does not exist",
|
||||||
"Phone number is invalid": "Phone number is invalid",
|
"Phone number is invalid": "Phone number is invalid",
|
||||||
"Please login first": "Please login first",
|
|
||||||
"Turing test failed.": "Turing test failed.",
|
"Turing test failed.": "Turing test failed.",
|
||||||
"Unable to get the email modify rule.": "Unable to get the email modify rule.",
|
"Unable to get the email modify rule.": "Unable to get the email modify rule.",
|
||||||
"Unable to get the phone modify rule.": "Unable to get the phone modify rule.",
|
"Unable to get the phone modify rule.": "Unable to get the phone modify rule.",
|
||||||
@ -165,8 +144,6 @@
|
|||||||
},
|
},
|
||||||
"webauthn": {
|
"webauthn": {
|
||||||
"Found no credentials for this user": "Found no credentials for this user",
|
"Found no credentials for this user": "Found no credentials for this user",
|
||||||
"Please call WebAuthnSigninBegin first": "Please call WebAuthnSigninBegin first",
|
"Please call WebAuthnSigninBegin first": "Please call WebAuthnSigninBegin first"
|
||||||
"Please login first": "Please login first",
|
|
||||||
"The user: %s/%s doesn't exist": "The user: %s/%s doesn't exist"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,31 +4,28 @@
|
|||||||
"Get init score failed, error: %w": "Get init score failed, error: %w",
|
"Get init score failed, error: %w": "Get init score failed, error: %w",
|
||||||
"Invalid information": "Invalid information",
|
"Invalid information": "Invalid information",
|
||||||
"Phone: %s": "Phone: %s",
|
"Phone: %s": "Phone: %s",
|
||||||
|
"Please sign out first before signing in": "Please sign out first before signing in",
|
||||||
"Please sign out first before signing up": "Please sign out first before signing up",
|
"Please sign out first before signing up": "Please sign out first before signing up",
|
||||||
"The application does not allow to sign up new account": "The application does not allow to sign up new account"
|
"The application does not allow to sign up new account": "The application does not allow to sign up new account"
|
||||||
},
|
},
|
||||||
"application": {
|
"application": {
|
||||||
"Parameter organization is missing": "Parameter organization is missing",
|
"Parameter organization is missing": "Parameter organization is missing"
|
||||||
"The user: %s doesn't exist": "The user: %s doesn't exist"
|
|
||||||
},
|
},
|
||||||
"auth": {
|
"auth": {
|
||||||
"%s No phone prefix": "%s No phone prefix",
|
"%s No phone prefix": "%s No phone prefix",
|
||||||
"Challenge method should be S256": "Challenge method should be S256",
|
"Challenge method should be S256": "Challenge method should be S256",
|
||||||
"Failed to create user, user information is invalid: %s": "Failed to create user, user information is invalid: %s",
|
"Failed to create user, user information is invalid: %s": "Failed to create user, user information is invalid: %s",
|
||||||
"Failed to login in: %s": "Failed to login in: %s",
|
"Failed to login in: %s": "Failed to login in: %s",
|
||||||
"Get init score failed, error: %w": "Get init score failed, error: %w",
|
|
||||||
"Invalid token": "Invalid token",
|
"Invalid token": "Invalid token",
|
||||||
"Please sign out first before signing in": "Please sign out first before signing in",
|
|
||||||
"State expected: %s, but got: %s": "State expected: %s, but got: %s",
|
"State expected: %s, but got: %s": "State expected: %s, but got: %s",
|
||||||
"The account does not exist": "The account does not exist",
|
|
||||||
"The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account via %%s, please use another way to sign up": "The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account via %%s, please use another way to sign up",
|
"The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account via %%s, please use another way to sign up": "The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account via %%s, please use another way to sign up",
|
||||||
"The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support": "The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support",
|
"The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support": "The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support",
|
||||||
"The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)": "The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)",
|
"The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)": "The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)",
|
||||||
"The application: %s does not exist": "The application: %s does not exist",
|
"The application: %s does not exist": "The application: %s does not exist",
|
||||||
|
"The login method: login with password is not enabled for the application": "The login method: login with password is not enabled for the application",
|
||||||
"The provider type: %s is not supported": "The provider type: %s is not supported",
|
"The provider type: %s is not supported": "The provider type: %s is not supported",
|
||||||
"The provider: %s is not enabled for the application": "The provider: %s is not enabled for the application",
|
"The provider: %s is not enabled for the application": "The provider: %s is not enabled for the application",
|
||||||
"The user is forbidden to sign in, please contact the administrator": "The user is forbidden to sign in, please contact the administrator",
|
"The user is forbidden to sign in, please contact the administrator": "The user is forbidden to sign in, please contact the administrator",
|
||||||
"The user: %s/%s doesn't exist": "The user: %s/%s doesn't exist",
|
|
||||||
"Turing test failed.": "Turing test failed.",
|
"Turing test failed.": "Turing test failed.",
|
||||||
"Unauthorized operation": "Unauthorized operation",
|
"Unauthorized operation": "Unauthorized operation",
|
||||||
"Unknown authentication type (not password or provider), form = %s": "Unknown authentication type (not password or provider), form = %s"
|
"Unknown authentication type (not password or provider), form = %s": "Unknown authentication type (not password or provider), form = %s"
|
||||||
@ -53,11 +50,8 @@
|
|||||||
"Phone already exists": "Phone already exists",
|
"Phone already exists": "Phone already exists",
|
||||||
"Phone cannot be empty": "Phone cannot be empty",
|
"Phone cannot be empty": "Phone cannot be empty",
|
||||||
"Phone number is invalid": "Phone number is invalid",
|
"Phone number is invalid": "Phone number is invalid",
|
||||||
"Please login first": "Please login first",
|
|
||||||
"Session outdated, please login again": "Session outdated, please login again",
|
"Session outdated, please login again": "Session outdated, please login again",
|
||||||
"The user doesn't exist": "The user doesn't exist",
|
|
||||||
"The user is forbidden to sign in, please contact the administrator": "The user is forbidden to sign in, please contact the administrator",
|
"The user is forbidden to sign in, please contact the administrator": "The user is forbidden to sign in, please contact the administrator",
|
||||||
"The user: %s doesn't exist": "The user: %s doesn't exist",
|
|
||||||
"The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline.": "The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline.",
|
"The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline.": "The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline.",
|
||||||
"Username already exists": "Username already exists",
|
"Username already exists": "Username already exists",
|
||||||
"Username cannot be an email address": "Username cannot be an email address",
|
"Username cannot be an email address": "Username cannot be an email address",
|
||||||
@ -65,16 +59,13 @@
|
|||||||
"Username cannot start with a digit": "Username cannot start with a digit",
|
"Username cannot start with a digit": "Username cannot start with a digit",
|
||||||
"Username is too long (maximum is 39 characters).": "Username is too long (maximum is 39 characters).",
|
"Username is too long (maximum is 39 characters).": "Username is too long (maximum is 39 characters).",
|
||||||
"Username must have at least 2 characters": "Username must have at least 2 characters",
|
"Username must have at least 2 characters": "Username must have at least 2 characters",
|
||||||
"You don't have the permission to do this": "You don't have the permission to do this",
|
"You have entered the wrong password or code too many times, please wait for %d minutes and try again": "You have entered the wrong password or code too many times, please wait for %d minutes and try again",
|
||||||
"You have entered the wrong password too many times, please wait for %d minutes %d seconds and try again": "You have entered the wrong password too many times, please wait for %d minutes %d seconds and try again",
|
"password or code is incorrect, you have %d remaining chances": "password or code is incorrect, you have %d remaining chances",
|
||||||
"unsupported password type: %s": "unsupported password type: %s"
|
"unsupported password type: %s": "unsupported password type: %s"
|
||||||
},
|
},
|
||||||
"check_util": {
|
"general": {
|
||||||
"You have entered the wrong password too many times, please wait for %d minutes and try again": "You have entered the wrong password too many times, please wait for %d minutes and try again",
|
"Please login first": "Please login first",
|
||||||
"password is incorrect, you have %d remaining chances": "password is incorrect, you have %d remaining chances"
|
"The user: %s doesn't exist": "The user: %s doesn't exist"
|
||||||
},
|
|
||||||
"enforcer": {
|
|
||||||
"Please sign in first": "Please sign in first"
|
|
||||||
},
|
},
|
||||||
"ldap": {
|
"ldap": {
|
||||||
"Ldap server exist": "Ldap server exist",
|
"Ldap server exist": "Ldap server exist",
|
||||||
@ -93,10 +84,6 @@
|
|||||||
"The %s is immutable.": "The %s is immutable.",
|
"The %s is immutable.": "The %s is immutable.",
|
||||||
"Unknown modify rule %s.": "Unknown modify rule %s."
|
"Unknown modify rule %s.": "Unknown modify rule %s."
|
||||||
},
|
},
|
||||||
"product": {
|
|
||||||
"Please login first": "Please login first",
|
|
||||||
"The user: %s doesn't exist": "The user: %s doesn't exist"
|
|
||||||
},
|
|
||||||
"provider": {
|
"provider": {
|
||||||
"Invalid application id": "Invalid application id",
|
"Invalid application id": "Invalid application id",
|
||||||
"the provider: %s does not exist": "the provider: %s does not exist"
|
"the provider: %s does not exist": "the provider: %s does not exist"
|
||||||
@ -120,11 +107,7 @@
|
|||||||
"The objectKey: %s is not allowed": "The objectKey: %s is not allowed",
|
"The objectKey: %s is not allowed": "The objectKey: %s is not allowed",
|
||||||
"The provider type: %s is not supported": "The provider type: %s is not supported"
|
"The provider type: %s is not supported": "The provider type: %s is not supported"
|
||||||
},
|
},
|
||||||
"system_info": {
|
|
||||||
"You are not authorized to access this resource": "You are not authorized to access this resource"
|
|
||||||
},
|
|
||||||
"token": {
|
"token": {
|
||||||
"Challenge method should be S256": "Challenge method should be S256",
|
|
||||||
"Empty clientId or clientSecret": "Empty clientId or clientSecret",
|
"Empty clientId or clientSecret": "Empty clientId or clientSecret",
|
||||||
"Grant_type: %s is not supported in this application": "Grant_type: %s is not supported in this application",
|
"Grant_type: %s is not supported in this application": "Grant_type: %s is not supported in this application",
|
||||||
"Invalid application or wrong clientSecret": "Invalid application or wrong clientSecret",
|
"Invalid application or wrong clientSecret": "Invalid application or wrong clientSecret",
|
||||||
@ -134,8 +117,7 @@
|
|||||||
"user": {
|
"user": {
|
||||||
"Display name cannot be empty": "Display name cannot be empty",
|
"Display name cannot be empty": "Display name cannot be empty",
|
||||||
"New password cannot contain blank space.": "New password cannot contain blank space.",
|
"New password cannot contain blank space.": "New password cannot contain blank space.",
|
||||||
"New password must have at least 6 characters": "New password must have at least 6 characters",
|
"New password must have at least 6 characters": "New password must have at least 6 characters"
|
||||||
"The user: %s/%s doesn't exist": "The user: %s/%s doesn't exist"
|
|
||||||
},
|
},
|
||||||
"user_upload": {
|
"user_upload": {
|
||||||
"Failed to import users": "Failed to import users"
|
"Failed to import users": "Failed to import users"
|
||||||
@ -143,9 +125,7 @@
|
|||||||
"util": {
|
"util": {
|
||||||
"No application is found for userId: %s": "No application is found for userId: %s",
|
"No application is found for userId: %s": "No application is found for userId: %s",
|
||||||
"No provider for category: %s is found for application: %s": "No provider for category: %s is found for application: %s",
|
"No provider for category: %s is found for application: %s": "No provider for category: %s is found for application: %s",
|
||||||
"Please login first": "Please login first",
|
"The provider: %s is not found": "The provider: %s is not found"
|
||||||
"The provider: %s is not found": "The provider: %s is not found",
|
|
||||||
"The user: %s doesn't exist": "The user: %s doesn't exist"
|
|
||||||
},
|
},
|
||||||
"verification": {
|
"verification": {
|
||||||
"Code has not been sent yet!": "Code has not been sent yet!",
|
"Code has not been sent yet!": "Code has not been sent yet!",
|
||||||
@ -154,7 +134,6 @@
|
|||||||
"Missing parameter": "Missing parameter",
|
"Missing parameter": "Missing parameter",
|
||||||
"Organization does not exist": "Organization does not exist",
|
"Organization does not exist": "Organization does not exist",
|
||||||
"Phone number is invalid": "Phone number is invalid",
|
"Phone number is invalid": "Phone number is invalid",
|
||||||
"Please login first": "Please login first",
|
|
||||||
"Turing test failed.": "Turing test failed.",
|
"Turing test failed.": "Turing test failed.",
|
||||||
"Unable to get the email modify rule.": "Unable to get the email modify rule.",
|
"Unable to get the email modify rule.": "Unable to get the email modify rule.",
|
||||||
"Unable to get the phone modify rule.": "Unable to get the phone modify rule.",
|
"Unable to get the phone modify rule.": "Unable to get the phone modify rule.",
|
||||||
@ -165,8 +144,6 @@
|
|||||||
},
|
},
|
||||||
"webauthn": {
|
"webauthn": {
|
||||||
"Found no credentials for this user": "Found no credentials for this user",
|
"Found no credentials for this user": "Found no credentials for this user",
|
||||||
"Please call WebAuthnSigninBegin first": "Please call WebAuthnSigninBegin first",
|
"Please call WebAuthnSigninBegin first": "Please call WebAuthnSigninBegin first"
|
||||||
"Please login first": "Please login first",
|
|
||||||
"The user: %s/%s doesn't exist": "The user: %s/%s doesn't exist"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,31 +4,28 @@
|
|||||||
"Get init score failed, error: %w": "Get init score failed, error: %w",
|
"Get init score failed, error: %w": "Get init score failed, error: %w",
|
||||||
"Invalid information": "Invalid information",
|
"Invalid information": "Invalid information",
|
||||||
"Phone: %s": "Phone: %s",
|
"Phone: %s": "Phone: %s",
|
||||||
|
"Please sign out first before signing in": "Please sign out first before signing in",
|
||||||
"Please sign out first before signing up": "Please sign out first before signing up",
|
"Please sign out first before signing up": "Please sign out first before signing up",
|
||||||
"The application does not allow to sign up new account": "The application does not allow to sign up new account"
|
"The application does not allow to sign up new account": "The application does not allow to sign up new account"
|
||||||
},
|
},
|
||||||
"application": {
|
"application": {
|
||||||
"Parameter organization is missing": "Parameter organization is missing",
|
"Parameter organization is missing": "Parameter organization is missing"
|
||||||
"The user: %s doesn't exist": "The user: %s doesn't exist"
|
|
||||||
},
|
},
|
||||||
"auth": {
|
"auth": {
|
||||||
"%s No phone prefix": "%s No phone prefix",
|
"%s No phone prefix": "%s No phone prefix",
|
||||||
"Challenge method should be S256": "Challenge method should be S256",
|
"Challenge method should be S256": "Challenge method should be S256",
|
||||||
"Failed to create user, user information is invalid: %s": "Failed to create user, user information is invalid: %s",
|
"Failed to create user, user information is invalid: %s": "Failed to create user, user information is invalid: %s",
|
||||||
"Failed to login in: %s": "Failed to login in: %s",
|
"Failed to login in: %s": "Failed to login in: %s",
|
||||||
"Get init score failed, error: %w": "Get init score failed, error: %w",
|
|
||||||
"Invalid token": "Invalid token",
|
"Invalid token": "Invalid token",
|
||||||
"Please sign out first before signing in": "Please sign out first before signing in",
|
|
||||||
"State expected: %s, but got: %s": "State expected: %s, but got: %s",
|
"State expected: %s, but got: %s": "State expected: %s, but got: %s",
|
||||||
"The account does not exist": "The account does not exist",
|
|
||||||
"The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account via %%s, please use another way to sign up": "The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account via %%s, please use another way to sign up",
|
"The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account via %%s, please use another way to sign up": "The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account via %%s, please use another way to sign up",
|
||||||
"The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support": "The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support",
|
"The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support": "The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support",
|
||||||
"The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)": "The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)",
|
"The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)": "The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)",
|
||||||
"The application: %s does not exist": "The application: %s does not exist",
|
"The application: %s does not exist": "The application: %s does not exist",
|
||||||
|
"The login method: login with password is not enabled for the application": "The login method: login with password is not enabled for the application",
|
||||||
"The provider type: %s is not supported": "The provider type: %s is not supported",
|
"The provider type: %s is not supported": "The provider type: %s is not supported",
|
||||||
"The provider: %s is not enabled for the application": "The provider: %s is not enabled for the application",
|
"The provider: %s is not enabled for the application": "The provider: %s is not enabled for the application",
|
||||||
"The user is forbidden to sign in, please contact the administrator": "The user is forbidden to sign in, please contact the administrator",
|
"The user is forbidden to sign in, please contact the administrator": "The user is forbidden to sign in, please contact the administrator",
|
||||||
"The user: %s/%s doesn't exist": "The user: %s/%s doesn't exist",
|
|
||||||
"Turing test failed.": "Turing test failed.",
|
"Turing test failed.": "Turing test failed.",
|
||||||
"Unauthorized operation": "Unauthorized operation",
|
"Unauthorized operation": "Unauthorized operation",
|
||||||
"Unknown authentication type (not password or provider), form = %s": "Unknown authentication type (not password or provider), form = %s"
|
"Unknown authentication type (not password or provider), form = %s": "Unknown authentication type (not password or provider), form = %s"
|
||||||
@ -53,11 +50,8 @@
|
|||||||
"Phone already exists": "Phone already exists",
|
"Phone already exists": "Phone already exists",
|
||||||
"Phone cannot be empty": "Phone cannot be empty",
|
"Phone cannot be empty": "Phone cannot be empty",
|
||||||
"Phone number is invalid": "Phone number is invalid",
|
"Phone number is invalid": "Phone number is invalid",
|
||||||
"Please login first": "Please login first",
|
|
||||||
"Session outdated, please login again": "Session outdated, please login again",
|
"Session outdated, please login again": "Session outdated, please login again",
|
||||||
"The user doesn't exist": "The user doesn't exist",
|
|
||||||
"The user is forbidden to sign in, please contact the administrator": "The user is forbidden to sign in, please contact the administrator",
|
"The user is forbidden to sign in, please contact the administrator": "The user is forbidden to sign in, please contact the administrator",
|
||||||
"The user: %s doesn't exist": "The user: %s doesn't exist",
|
|
||||||
"The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline.": "The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline.",
|
"The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline.": "The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline.",
|
||||||
"Username already exists": "Username already exists",
|
"Username already exists": "Username already exists",
|
||||||
"Username cannot be an email address": "Username cannot be an email address",
|
"Username cannot be an email address": "Username cannot be an email address",
|
||||||
@ -65,16 +59,13 @@
|
|||||||
"Username cannot start with a digit": "Username cannot start with a digit",
|
"Username cannot start with a digit": "Username cannot start with a digit",
|
||||||
"Username is too long (maximum is 39 characters).": "Username is too long (maximum is 39 characters).",
|
"Username is too long (maximum is 39 characters).": "Username is too long (maximum is 39 characters).",
|
||||||
"Username must have at least 2 characters": "Username must have at least 2 characters",
|
"Username must have at least 2 characters": "Username must have at least 2 characters",
|
||||||
"You don't have the permission to do this": "You don't have the permission to do this",
|
"You have entered the wrong password or code too many times, please wait for %d minutes and try again": "You have entered the wrong password or code too many times, please wait for %d minutes and try again",
|
||||||
"You have entered the wrong password too many times, please wait for %d minutes %d seconds and try again": "You have entered the wrong password too many times, please wait for %d minutes %d seconds and try again",
|
"password or code is incorrect, you have %d remaining chances": "password or code is incorrect, you have %d remaining chances",
|
||||||
"unsupported password type: %s": "unsupported password type: %s"
|
"unsupported password type: %s": "unsupported password type: %s"
|
||||||
},
|
},
|
||||||
"check_util": {
|
"general": {
|
||||||
"You have entered the wrong password too many times, please wait for %d minutes and try again": "You have entered the wrong password too many times, please wait for %d minutes and try again",
|
"Please login first": "Please login first",
|
||||||
"password is incorrect, you have %d remaining chances": "password is incorrect, you have %d remaining chances"
|
"The user: %s doesn't exist": "The user: %s doesn't exist"
|
||||||
},
|
|
||||||
"enforcer": {
|
|
||||||
"Please sign in first": "Please sign in first"
|
|
||||||
},
|
},
|
||||||
"ldap": {
|
"ldap": {
|
||||||
"Ldap server exist": "Ldap server exist",
|
"Ldap server exist": "Ldap server exist",
|
||||||
@ -93,10 +84,6 @@
|
|||||||
"The %s is immutable.": "The %s is immutable.",
|
"The %s is immutable.": "The %s is immutable.",
|
||||||
"Unknown modify rule %s.": "Unknown modify rule %s."
|
"Unknown modify rule %s.": "Unknown modify rule %s."
|
||||||
},
|
},
|
||||||
"product": {
|
|
||||||
"Please login first": "Please login first",
|
|
||||||
"The user: %s doesn't exist": "The user: %s doesn't exist"
|
|
||||||
},
|
|
||||||
"provider": {
|
"provider": {
|
||||||
"Invalid application id": "Invalid application id",
|
"Invalid application id": "Invalid application id",
|
||||||
"the provider: %s does not exist": "the provider: %s does not exist"
|
"the provider: %s does not exist": "the provider: %s does not exist"
|
||||||
@ -120,11 +107,7 @@
|
|||||||
"The objectKey: %s is not allowed": "The objectKey: %s is not allowed",
|
"The objectKey: %s is not allowed": "The objectKey: %s is not allowed",
|
||||||
"The provider type: %s is not supported": "The provider type: %s is not supported"
|
"The provider type: %s is not supported": "The provider type: %s is not supported"
|
||||||
},
|
},
|
||||||
"system_info": {
|
|
||||||
"You are not authorized to access this resource": "You are not authorized to access this resource"
|
|
||||||
},
|
|
||||||
"token": {
|
"token": {
|
||||||
"Challenge method should be S256": "Challenge method should be S256",
|
|
||||||
"Empty clientId or clientSecret": "Empty clientId or clientSecret",
|
"Empty clientId or clientSecret": "Empty clientId or clientSecret",
|
||||||
"Grant_type: %s is not supported in this application": "Grant_type: %s is not supported in this application",
|
"Grant_type: %s is not supported in this application": "Grant_type: %s is not supported in this application",
|
||||||
"Invalid application or wrong clientSecret": "Invalid application or wrong clientSecret",
|
"Invalid application or wrong clientSecret": "Invalid application or wrong clientSecret",
|
||||||
@ -134,8 +117,7 @@
|
|||||||
"user": {
|
"user": {
|
||||||
"Display name cannot be empty": "Display name cannot be empty",
|
"Display name cannot be empty": "Display name cannot be empty",
|
||||||
"New password cannot contain blank space.": "New password cannot contain blank space.",
|
"New password cannot contain blank space.": "New password cannot contain blank space.",
|
||||||
"New password must have at least 6 characters": "New password must have at least 6 characters",
|
"New password must have at least 6 characters": "New password must have at least 6 characters"
|
||||||
"The user: %s/%s doesn't exist": "The user: %s/%s doesn't exist"
|
|
||||||
},
|
},
|
||||||
"user_upload": {
|
"user_upload": {
|
||||||
"Failed to import users": "Failed to import users"
|
"Failed to import users": "Failed to import users"
|
||||||
@ -143,9 +125,7 @@
|
|||||||
"util": {
|
"util": {
|
||||||
"No application is found for userId: %s": "No application is found for userId: %s",
|
"No application is found for userId: %s": "No application is found for userId: %s",
|
||||||
"No provider for category: %s is found for application: %s": "No provider for category: %s is found for application: %s",
|
"No provider for category: %s is found for application: %s": "No provider for category: %s is found for application: %s",
|
||||||
"Please login first": "Please login first",
|
"The provider: %s is not found": "The provider: %s is not found"
|
||||||
"The provider: %s is not found": "The provider: %s is not found",
|
|
||||||
"The user: %s doesn't exist": "The user: %s doesn't exist"
|
|
||||||
},
|
},
|
||||||
"verification": {
|
"verification": {
|
||||||
"Code has not been sent yet!": "Code has not been sent yet!",
|
"Code has not been sent yet!": "Code has not been sent yet!",
|
||||||
@ -154,7 +134,6 @@
|
|||||||
"Missing parameter": "Missing parameter",
|
"Missing parameter": "Missing parameter",
|
||||||
"Organization does not exist": "Organization does not exist",
|
"Organization does not exist": "Organization does not exist",
|
||||||
"Phone number is invalid": "Phone number is invalid",
|
"Phone number is invalid": "Phone number is invalid",
|
||||||
"Please login first": "Please login first",
|
|
||||||
"Turing test failed.": "Turing test failed.",
|
"Turing test failed.": "Turing test failed.",
|
||||||
"Unable to get the email modify rule.": "Unable to get the email modify rule.",
|
"Unable to get the email modify rule.": "Unable to get the email modify rule.",
|
||||||
"Unable to get the phone modify rule.": "Unable to get the phone modify rule.",
|
"Unable to get the phone modify rule.": "Unable to get the phone modify rule.",
|
||||||
@ -165,8 +144,6 @@
|
|||||||
},
|
},
|
||||||
"webauthn": {
|
"webauthn": {
|
||||||
"Found no credentials for this user": "Found no credentials for this user",
|
"Found no credentials for this user": "Found no credentials for this user",
|
||||||
"Please call WebAuthnSigninBegin first": "Please call WebAuthnSigninBegin first",
|
"Please call WebAuthnSigninBegin first": "Please call WebAuthnSigninBegin first"
|
||||||
"Please login first": "Please login first",
|
|
||||||
"The user: %s/%s doesn't exist": "The user: %s/%s doesn't exist"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,31 +4,28 @@
|
|||||||
"Get init score failed, error: %w": "Get init score failed, error: %w",
|
"Get init score failed, error: %w": "Get init score failed, error: %w",
|
||||||
"Invalid information": "Invalid information",
|
"Invalid information": "Invalid information",
|
||||||
"Phone: %s": "Phone: %s",
|
"Phone: %s": "Phone: %s",
|
||||||
|
"Please sign out first before signing in": "Please sign out first before signing in",
|
||||||
"Please sign out first before signing up": "Please sign out first before signing up",
|
"Please sign out first before signing up": "Please sign out first before signing up",
|
||||||
"The application does not allow to sign up new account": "The application does not allow to sign up new account"
|
"The application does not allow to sign up new account": "The application does not allow to sign up new account"
|
||||||
},
|
},
|
||||||
"application": {
|
"application": {
|
||||||
"Parameter organization is missing": "Parameter organization is missing",
|
"Parameter organization is missing": "Parameter organization is missing"
|
||||||
"The user: %s doesn't exist": "The user: %s doesn't exist"
|
|
||||||
},
|
},
|
||||||
"auth": {
|
"auth": {
|
||||||
"%s No phone prefix": "%s No phone prefix",
|
"%s No phone prefix": "%s No phone prefix",
|
||||||
"Challenge method should be S256": "Challenge method should be S256",
|
"Challenge method should be S256": "Challenge method should be S256",
|
||||||
"Failed to create user, user information is invalid: %s": "Failed to create user, user information is invalid: %s",
|
"Failed to create user, user information is invalid: %s": "Failed to create user, user information is invalid: %s",
|
||||||
"Failed to login in: %s": "Failed to login in: %s",
|
"Failed to login in: %s": "Failed to login in: %s",
|
||||||
"Get init score failed, error: %w": "Get init score failed, error: %w",
|
|
||||||
"Invalid token": "Invalid token",
|
"Invalid token": "Invalid token",
|
||||||
"Please sign out first before signing in": "Please sign out first before signing in",
|
|
||||||
"State expected: %s, but got: %s": "State expected: %s, but got: %s",
|
"State expected: %s, but got: %s": "State expected: %s, but got: %s",
|
||||||
"The account does not exist": "The account does not exist",
|
|
||||||
"The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account via %%s, please use another way to sign up": "The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account via %%s, please use another way to sign up",
|
"The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account via %%s, please use another way to sign up": "The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account via %%s, please use another way to sign up",
|
||||||
"The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support": "The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support",
|
"The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support": "The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support",
|
||||||
"The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)": "The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)",
|
"The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)": "The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)",
|
||||||
"The application: %s does not exist": "The application: %s does not exist",
|
"The application: %s does not exist": "The application: %s does not exist",
|
||||||
|
"The login method: login with password is not enabled for the application": "The login method: login with password is not enabled for the application",
|
||||||
"The provider type: %s is not supported": "The provider type: %s is not supported",
|
"The provider type: %s is not supported": "The provider type: %s is not supported",
|
||||||
"The provider: %s is not enabled for the application": "The provider: %s is not enabled for the application",
|
"The provider: %s is not enabled for the application": "The provider: %s is not enabled for the application",
|
||||||
"The user is forbidden to sign in, please contact the administrator": "The user is forbidden to sign in, please contact the administrator",
|
"The user is forbidden to sign in, please contact the administrator": "The user is forbidden to sign in, please contact the administrator",
|
||||||
"The user: %s/%s doesn't exist": "The user: %s/%s doesn't exist",
|
|
||||||
"Turing test failed.": "Turing test failed.",
|
"Turing test failed.": "Turing test failed.",
|
||||||
"Unauthorized operation": "Unauthorized operation",
|
"Unauthorized operation": "Unauthorized operation",
|
||||||
"Unknown authentication type (not password or provider), form = %s": "Unknown authentication type (not password or provider), form = %s"
|
"Unknown authentication type (not password or provider), form = %s": "Unknown authentication type (not password or provider), form = %s"
|
||||||
@ -53,11 +50,8 @@
|
|||||||
"Phone already exists": "Phone already exists",
|
"Phone already exists": "Phone already exists",
|
||||||
"Phone cannot be empty": "Phone cannot be empty",
|
"Phone cannot be empty": "Phone cannot be empty",
|
||||||
"Phone number is invalid": "Phone number is invalid",
|
"Phone number is invalid": "Phone number is invalid",
|
||||||
"Please login first": "Please login first",
|
|
||||||
"Session outdated, please login again": "Session outdated, please login again",
|
"Session outdated, please login again": "Session outdated, please login again",
|
||||||
"The user doesn't exist": "The user doesn't exist",
|
|
||||||
"The user is forbidden to sign in, please contact the administrator": "The user is forbidden to sign in, please contact the administrator",
|
"The user is forbidden to sign in, please contact the administrator": "The user is forbidden to sign in, please contact the administrator",
|
||||||
"The user: %s doesn't exist": "The user: %s doesn't exist",
|
|
||||||
"The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline.": "The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline.",
|
"The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline.": "The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline.",
|
||||||
"Username already exists": "Username already exists",
|
"Username already exists": "Username already exists",
|
||||||
"Username cannot be an email address": "Username cannot be an email address",
|
"Username cannot be an email address": "Username cannot be an email address",
|
||||||
@ -65,16 +59,13 @@
|
|||||||
"Username cannot start with a digit": "Username cannot start with a digit",
|
"Username cannot start with a digit": "Username cannot start with a digit",
|
||||||
"Username is too long (maximum is 39 characters).": "Username is too long (maximum is 39 characters).",
|
"Username is too long (maximum is 39 characters).": "Username is too long (maximum is 39 characters).",
|
||||||
"Username must have at least 2 characters": "Username must have at least 2 characters",
|
"Username must have at least 2 characters": "Username must have at least 2 characters",
|
||||||
"You don't have the permission to do this": "You don't have the permission to do this",
|
"You have entered the wrong password or code too many times, please wait for %d minutes and try again": "You have entered the wrong password or code too many times, please wait for %d minutes and try again",
|
||||||
"You have entered the wrong password too many times, please wait for %d minutes %d seconds and try again": "You have entered the wrong password too many times, please wait for %d minutes %d seconds and try again",
|
"password or code is incorrect, you have %d remaining chances": "password or code is incorrect, you have %d remaining chances",
|
||||||
"unsupported password type: %s": "unsupported password type: %s"
|
"unsupported password type: %s": "unsupported password type: %s"
|
||||||
},
|
},
|
||||||
"check_util": {
|
"general": {
|
||||||
"You have entered the wrong password too many times, please wait for %d minutes and try again": "You have entered the wrong password too many times, please wait for %d minutes and try again",
|
"Please login first": "Please login first",
|
||||||
"password is incorrect, you have %d remaining chances": "password is incorrect, you have %d remaining chances"
|
"The user: %s doesn't exist": "The user: %s doesn't exist"
|
||||||
},
|
|
||||||
"enforcer": {
|
|
||||||
"Please sign in first": "Please sign in first"
|
|
||||||
},
|
},
|
||||||
"ldap": {
|
"ldap": {
|
||||||
"Ldap server exist": "Ldap server exist",
|
"Ldap server exist": "Ldap server exist",
|
||||||
@ -93,10 +84,6 @@
|
|||||||
"The %s is immutable.": "The %s is immutable.",
|
"The %s is immutable.": "The %s is immutable.",
|
||||||
"Unknown modify rule %s.": "Unknown modify rule %s."
|
"Unknown modify rule %s.": "Unknown modify rule %s."
|
||||||
},
|
},
|
||||||
"product": {
|
|
||||||
"Please login first": "Please login first",
|
|
||||||
"The user: %s doesn't exist": "The user: %s doesn't exist"
|
|
||||||
},
|
|
||||||
"provider": {
|
"provider": {
|
||||||
"Invalid application id": "Invalid application id",
|
"Invalid application id": "Invalid application id",
|
||||||
"the provider: %s does not exist": "the provider: %s does not exist"
|
"the provider: %s does not exist": "the provider: %s does not exist"
|
||||||
@ -120,11 +107,7 @@
|
|||||||
"The objectKey: %s is not allowed": "The objectKey: %s is not allowed",
|
"The objectKey: %s is not allowed": "The objectKey: %s is not allowed",
|
||||||
"The provider type: %s is not supported": "The provider type: %s is not supported"
|
"The provider type: %s is not supported": "The provider type: %s is not supported"
|
||||||
},
|
},
|
||||||
"system_info": {
|
|
||||||
"You are not authorized to access this resource": "You are not authorized to access this resource"
|
|
||||||
},
|
|
||||||
"token": {
|
"token": {
|
||||||
"Challenge method should be S256": "Challenge method should be S256",
|
|
||||||
"Empty clientId or clientSecret": "Empty clientId or clientSecret",
|
"Empty clientId or clientSecret": "Empty clientId or clientSecret",
|
||||||
"Grant_type: %s is not supported in this application": "Grant_type: %s is not supported in this application",
|
"Grant_type: %s is not supported in this application": "Grant_type: %s is not supported in this application",
|
||||||
"Invalid application or wrong clientSecret": "Invalid application or wrong clientSecret",
|
"Invalid application or wrong clientSecret": "Invalid application or wrong clientSecret",
|
||||||
@ -134,8 +117,7 @@
|
|||||||
"user": {
|
"user": {
|
||||||
"Display name cannot be empty": "Display name cannot be empty",
|
"Display name cannot be empty": "Display name cannot be empty",
|
||||||
"New password cannot contain blank space.": "New password cannot contain blank space.",
|
"New password cannot contain blank space.": "New password cannot contain blank space.",
|
||||||
"New password must have at least 6 characters": "New password must have at least 6 characters",
|
"New password must have at least 6 characters": "New password must have at least 6 characters"
|
||||||
"The user: %s/%s doesn't exist": "The user: %s/%s doesn't exist"
|
|
||||||
},
|
},
|
||||||
"user_upload": {
|
"user_upload": {
|
||||||
"Failed to import users": "Failed to import users"
|
"Failed to import users": "Failed to import users"
|
||||||
@ -143,9 +125,7 @@
|
|||||||
"util": {
|
"util": {
|
||||||
"No application is found for userId: %s": "No application is found for userId: %s",
|
"No application is found for userId: %s": "No application is found for userId: %s",
|
||||||
"No provider for category: %s is found for application: %s": "No provider for category: %s is found for application: %s",
|
"No provider for category: %s is found for application: %s": "No provider for category: %s is found for application: %s",
|
||||||
"Please login first": "Please login first",
|
"The provider: %s is not found": "The provider: %s is not found"
|
||||||
"The provider: %s is not found": "The provider: %s is not found",
|
|
||||||
"The user: %s doesn't exist": "The user: %s doesn't exist"
|
|
||||||
},
|
},
|
||||||
"verification": {
|
"verification": {
|
||||||
"Code has not been sent yet!": "Code has not been sent yet!",
|
"Code has not been sent yet!": "Code has not been sent yet!",
|
||||||
@ -154,7 +134,6 @@
|
|||||||
"Missing parameter": "Missing parameter",
|
"Missing parameter": "Missing parameter",
|
||||||
"Organization does not exist": "Organization does not exist",
|
"Organization does not exist": "Organization does not exist",
|
||||||
"Phone number is invalid": "Phone number is invalid",
|
"Phone number is invalid": "Phone number is invalid",
|
||||||
"Please login first": "Please login first",
|
|
||||||
"Turing test failed.": "Turing test failed.",
|
"Turing test failed.": "Turing test failed.",
|
||||||
"Unable to get the email modify rule.": "Unable to get the email modify rule.",
|
"Unable to get the email modify rule.": "Unable to get the email modify rule.",
|
||||||
"Unable to get the phone modify rule.": "Unable to get the phone modify rule.",
|
"Unable to get the phone modify rule.": "Unable to get the phone modify rule.",
|
||||||
@ -165,8 +144,6 @@
|
|||||||
},
|
},
|
||||||
"webauthn": {
|
"webauthn": {
|
||||||
"Found no credentials for this user": "Found no credentials for this user",
|
"Found no credentials for this user": "Found no credentials for this user",
|
||||||
"Please call WebAuthnSigninBegin first": "Please call WebAuthnSigninBegin first",
|
"Please call WebAuthnSigninBegin first": "Please call WebAuthnSigninBegin first"
|
||||||
"Please login first": "Please login first",
|
|
||||||
"The user: %s/%s doesn't exist": "The user: %s/%s doesn't exist"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,31 +4,28 @@
|
|||||||
"Get init score failed, error: %w": "Get init score failed, error: %w",
|
"Get init score failed, error: %w": "Get init score failed, error: %w",
|
||||||
"Invalid information": "Invalid information",
|
"Invalid information": "Invalid information",
|
||||||
"Phone: %s": "Phone: %s",
|
"Phone: %s": "Phone: %s",
|
||||||
|
"Please sign out first before signing in": "Please sign out first before signing in",
|
||||||
"Please sign out first before signing up": "Please sign out first before signing up",
|
"Please sign out first before signing up": "Please sign out first before signing up",
|
||||||
"The application does not allow to sign up new account": "The application does not allow to sign up new account"
|
"The application does not allow to sign up new account": "The application does not allow to sign up new account"
|
||||||
},
|
},
|
||||||
"application": {
|
"application": {
|
||||||
"Parameter organization is missing": "Parameter organization is missing",
|
"Parameter organization is missing": "Parameter organization is missing"
|
||||||
"The user: %s doesn't exist": "The user: %s doesn't exist"
|
|
||||||
},
|
},
|
||||||
"auth": {
|
"auth": {
|
||||||
"%s No phone prefix": "%s No phone prefix",
|
"%s No phone prefix": "%s No phone prefix",
|
||||||
"Challenge method should be S256": "Challenge method should be S256",
|
"Challenge method should be S256": "Challenge method should be S256",
|
||||||
"Failed to create user, user information is invalid: %s": "Failed to create user, user information is invalid: %s",
|
"Failed to create user, user information is invalid: %s": "Failed to create user, user information is invalid: %s",
|
||||||
"Failed to login in: %s": "Failed to login in: %s",
|
"Failed to login in: %s": "Failed to login in: %s",
|
||||||
"Get init score failed, error: %w": "Get init score failed, error: %w",
|
|
||||||
"Invalid token": "Invalid token",
|
"Invalid token": "Invalid token",
|
||||||
"Please sign out first before signing in": "Please sign out first before signing in",
|
|
||||||
"State expected: %s, but got: %s": "State expected: %s, but got: %s",
|
"State expected: %s, but got: %s": "State expected: %s, but got: %s",
|
||||||
"The account does not exist": "The account does not exist",
|
|
||||||
"The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account via %%s, please use another way to sign up": "The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account via %%s, please use another way to sign up",
|
"The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account via %%s, please use another way to sign up": "The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account via %%s, please use another way to sign up",
|
||||||
"The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support": "The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support",
|
"The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support": "The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support",
|
||||||
"The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)": "The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)",
|
"The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)": "The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)",
|
||||||
"The application: %s does not exist": "The application: %s does not exist",
|
"The application: %s does not exist": "The application: %s does not exist",
|
||||||
|
"The login method: login with password is not enabled for the application": "The login method: login with password is not enabled for the application",
|
||||||
"The provider type: %s is not supported": "The provider type: %s is not supported",
|
"The provider type: %s is not supported": "The provider type: %s is not supported",
|
||||||
"The provider: %s is not enabled for the application": "The provider: %s is not enabled for the application",
|
"The provider: %s is not enabled for the application": "The provider: %s is not enabled for the application",
|
||||||
"The user is forbidden to sign in, please contact the administrator": "The user is forbidden to sign in, please contact the administrator",
|
"The user is forbidden to sign in, please contact the administrator": "The user is forbidden to sign in, please contact the administrator",
|
||||||
"The user: %s/%s doesn't exist": "The user: %s/%s doesn't exist",
|
|
||||||
"Turing test failed.": "Turing test failed.",
|
"Turing test failed.": "Turing test failed.",
|
||||||
"Unauthorized operation": "Unauthorized operation",
|
"Unauthorized operation": "Unauthorized operation",
|
||||||
"Unknown authentication type (not password or provider), form = %s": "Unknown authentication type (not password or provider), form = %s"
|
"Unknown authentication type (not password or provider), form = %s": "Unknown authentication type (not password or provider), form = %s"
|
||||||
@ -53,11 +50,8 @@
|
|||||||
"Phone already exists": "Phone already exists",
|
"Phone already exists": "Phone already exists",
|
||||||
"Phone cannot be empty": "Phone cannot be empty",
|
"Phone cannot be empty": "Phone cannot be empty",
|
||||||
"Phone number is invalid": "Phone number is invalid",
|
"Phone number is invalid": "Phone number is invalid",
|
||||||
"Please login first": "Please login first",
|
|
||||||
"Session outdated, please login again": "Session outdated, please login again",
|
"Session outdated, please login again": "Session outdated, please login again",
|
||||||
"The user doesn't exist": "The user doesn't exist",
|
|
||||||
"The user is forbidden to sign in, please contact the administrator": "The user is forbidden to sign in, please contact the administrator",
|
"The user is forbidden to sign in, please contact the administrator": "The user is forbidden to sign in, please contact the administrator",
|
||||||
"The user: %s doesn't exist": "The user: %s doesn't exist",
|
|
||||||
"The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline.": "The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline.",
|
"The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline.": "The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline.",
|
||||||
"Username already exists": "Username already exists",
|
"Username already exists": "Username already exists",
|
||||||
"Username cannot be an email address": "Username cannot be an email address",
|
"Username cannot be an email address": "Username cannot be an email address",
|
||||||
@ -65,16 +59,13 @@
|
|||||||
"Username cannot start with a digit": "Username cannot start with a digit",
|
"Username cannot start with a digit": "Username cannot start with a digit",
|
||||||
"Username is too long (maximum is 39 characters).": "Username is too long (maximum is 39 characters).",
|
"Username is too long (maximum is 39 characters).": "Username is too long (maximum is 39 characters).",
|
||||||
"Username must have at least 2 characters": "Username must have at least 2 characters",
|
"Username must have at least 2 characters": "Username must have at least 2 characters",
|
||||||
"You don't have the permission to do this": "You don't have the permission to do this",
|
"You have entered the wrong password or code too many times, please wait for %d minutes and try again": "You have entered the wrong password or code too many times, please wait for %d minutes and try again",
|
||||||
"You have entered the wrong password too many times, please wait for %d minutes %d seconds and try again": "You have entered the wrong password too many times, please wait for %d minutes %d seconds and try again",
|
"password or code is incorrect, you have %d remaining chances": "password or code is incorrect, you have %d remaining chances",
|
||||||
"unsupported password type: %s": "unsupported password type: %s"
|
"unsupported password type: %s": "unsupported password type: %s"
|
||||||
},
|
},
|
||||||
"check_util": {
|
"general": {
|
||||||
"You have entered the wrong password too many times, please wait for %d minutes and try again": "You have entered the wrong password too many times, please wait for %d minutes and try again",
|
"Please login first": "Please login first",
|
||||||
"password is incorrect, you have %d remaining chances": "password is incorrect, you have %d remaining chances"
|
"The user: %s doesn't exist": "The user: %s doesn't exist"
|
||||||
},
|
|
||||||
"enforcer": {
|
|
||||||
"Please sign in first": "Please sign in first"
|
|
||||||
},
|
},
|
||||||
"ldap": {
|
"ldap": {
|
||||||
"Ldap server exist": "Ldap server exist",
|
"Ldap server exist": "Ldap server exist",
|
||||||
@ -93,10 +84,6 @@
|
|||||||
"The %s is immutable.": "The %s is immutable.",
|
"The %s is immutable.": "The %s is immutable.",
|
||||||
"Unknown modify rule %s.": "Unknown modify rule %s."
|
"Unknown modify rule %s.": "Unknown modify rule %s."
|
||||||
},
|
},
|
||||||
"product": {
|
|
||||||
"Please login first": "Please login first",
|
|
||||||
"The user: %s doesn't exist": "The user: %s doesn't exist"
|
|
||||||
},
|
|
||||||
"provider": {
|
"provider": {
|
||||||
"Invalid application id": "Invalid application id",
|
"Invalid application id": "Invalid application id",
|
||||||
"the provider: %s does not exist": "the provider: %s does not exist"
|
"the provider: %s does not exist": "the provider: %s does not exist"
|
||||||
@ -120,11 +107,7 @@
|
|||||||
"The objectKey: %s is not allowed": "The objectKey: %s is not allowed",
|
"The objectKey: %s is not allowed": "The objectKey: %s is not allowed",
|
||||||
"The provider type: %s is not supported": "The provider type: %s is not supported"
|
"The provider type: %s is not supported": "The provider type: %s is not supported"
|
||||||
},
|
},
|
||||||
"system_info": {
|
|
||||||
"You are not authorized to access this resource": "You are not authorized to access this resource"
|
|
||||||
},
|
|
||||||
"token": {
|
"token": {
|
||||||
"Challenge method should be S256": "Challenge method should be S256",
|
|
||||||
"Empty clientId or clientSecret": "Empty clientId or clientSecret",
|
"Empty clientId or clientSecret": "Empty clientId or clientSecret",
|
||||||
"Grant_type: %s is not supported in this application": "Grant_type: %s is not supported in this application",
|
"Grant_type: %s is not supported in this application": "Grant_type: %s is not supported in this application",
|
||||||
"Invalid application or wrong clientSecret": "Invalid application or wrong clientSecret",
|
"Invalid application or wrong clientSecret": "Invalid application or wrong clientSecret",
|
||||||
@ -134,8 +117,7 @@
|
|||||||
"user": {
|
"user": {
|
||||||
"Display name cannot be empty": "Display name cannot be empty",
|
"Display name cannot be empty": "Display name cannot be empty",
|
||||||
"New password cannot contain blank space.": "New password cannot contain blank space.",
|
"New password cannot contain blank space.": "New password cannot contain blank space.",
|
||||||
"New password must have at least 6 characters": "New password must have at least 6 characters",
|
"New password must have at least 6 characters": "New password must have at least 6 characters"
|
||||||
"The user: %s/%s doesn't exist": "The user: %s/%s doesn't exist"
|
|
||||||
},
|
},
|
||||||
"user_upload": {
|
"user_upload": {
|
||||||
"Failed to import users": "Failed to import users"
|
"Failed to import users": "Failed to import users"
|
||||||
@ -143,9 +125,7 @@
|
|||||||
"util": {
|
"util": {
|
||||||
"No application is found for userId: %s": "No application is found for userId: %s",
|
"No application is found for userId: %s": "No application is found for userId: %s",
|
||||||
"No provider for category: %s is found for application: %s": "No provider for category: %s is found for application: %s",
|
"No provider for category: %s is found for application: %s": "No provider for category: %s is found for application: %s",
|
||||||
"Please login first": "Please login first",
|
"The provider: %s is not found": "The provider: %s is not found"
|
||||||
"The provider: %s is not found": "The provider: %s is not found",
|
|
||||||
"The user: %s doesn't exist": "The user: %s doesn't exist"
|
|
||||||
},
|
},
|
||||||
"verification": {
|
"verification": {
|
||||||
"Code has not been sent yet!": "Code has not been sent yet!",
|
"Code has not been sent yet!": "Code has not been sent yet!",
|
||||||
@ -154,7 +134,6 @@
|
|||||||
"Missing parameter": "Missing parameter",
|
"Missing parameter": "Missing parameter",
|
||||||
"Organization does not exist": "Organization does not exist",
|
"Organization does not exist": "Organization does not exist",
|
||||||
"Phone number is invalid": "Phone number is invalid",
|
"Phone number is invalid": "Phone number is invalid",
|
||||||
"Please login first": "Please login first",
|
|
||||||
"Turing test failed.": "Turing test failed.",
|
"Turing test failed.": "Turing test failed.",
|
||||||
"Unable to get the email modify rule.": "Unable to get the email modify rule.",
|
"Unable to get the email modify rule.": "Unable to get the email modify rule.",
|
||||||
"Unable to get the phone modify rule.": "Unable to get the phone modify rule.",
|
"Unable to get the phone modify rule.": "Unable to get the phone modify rule.",
|
||||||
@ -165,8 +144,6 @@
|
|||||||
},
|
},
|
||||||
"webauthn": {
|
"webauthn": {
|
||||||
"Found no credentials for this user": "Found no credentials for this user",
|
"Found no credentials for this user": "Found no credentials for this user",
|
||||||
"Please call WebAuthnSigninBegin first": "Please call WebAuthnSigninBegin first",
|
"Please call WebAuthnSigninBegin first": "Please call WebAuthnSigninBegin first"
|
||||||
"Please login first": "Please login first",
|
|
||||||
"The user: %s/%s doesn't exist": "The user: %s/%s doesn't exist"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,31 +4,28 @@
|
|||||||
"Get init score failed, error: %w": "Get init score failed, error: %w",
|
"Get init score failed, error: %w": "Get init score failed, error: %w",
|
||||||
"Invalid information": "Invalid information",
|
"Invalid information": "Invalid information",
|
||||||
"Phone: %s": "Phone: %s",
|
"Phone: %s": "Phone: %s",
|
||||||
|
"Please sign out first before signing in": "Please sign out first before signing in",
|
||||||
"Please sign out first before signing up": "Please sign out first before signing up",
|
"Please sign out first before signing up": "Please sign out first before signing up",
|
||||||
"The application does not allow to sign up new account": "The application does not allow to sign up new account"
|
"The application does not allow to sign up new account": "The application does not allow to sign up new account"
|
||||||
},
|
},
|
||||||
"application": {
|
"application": {
|
||||||
"Parameter organization is missing": "Parameter organization is missing",
|
"Parameter organization is missing": "Parameter organization is missing"
|
||||||
"The user: %s doesn't exist": "The user: %s doesn't exist"
|
|
||||||
},
|
},
|
||||||
"auth": {
|
"auth": {
|
||||||
"%s No phone prefix": "%s No phone prefix",
|
"%s No phone prefix": "%s No phone prefix",
|
||||||
"Challenge method should be S256": "Challenge method should be S256",
|
"Challenge method should be S256": "Challenge method should be S256",
|
||||||
"Failed to create user, user information is invalid: %s": "Failed to create user, user information is invalid: %s",
|
"Failed to create user, user information is invalid: %s": "Failed to create user, user information is invalid: %s",
|
||||||
"Failed to login in: %s": "Failed to login in: %s",
|
"Failed to login in: %s": "Failed to login in: %s",
|
||||||
"Get init score failed, error: %w": "Get init score failed, error: %w",
|
|
||||||
"Invalid token": "Invalid token",
|
"Invalid token": "Invalid token",
|
||||||
"Please sign out first before signing in": "Please sign out first before signing in",
|
|
||||||
"State expected: %s, but got: %s": "State expected: %s, but got: %s",
|
"State expected: %s, but got: %s": "State expected: %s, but got: %s",
|
||||||
"The account does not exist": "The account does not exist",
|
|
||||||
"The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account via %%s, please use another way to sign up": "The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account via %%s, please use another way to sign up",
|
"The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account via %%s, please use another way to sign up": "The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account via %%s, please use another way to sign up",
|
||||||
"The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support": "The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support",
|
"The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support": "The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support",
|
||||||
"The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)": "The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)",
|
"The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)": "The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)",
|
||||||
"The application: %s does not exist": "The application: %s does not exist",
|
"The application: %s does not exist": "The application: %s does not exist",
|
||||||
|
"The login method: login with password is not enabled for the application": "The login method: login with password is not enabled for the application",
|
||||||
"The provider type: %s is not supported": "The provider type: %s is not supported",
|
"The provider type: %s is not supported": "The provider type: %s is not supported",
|
||||||
"The provider: %s is not enabled for the application": "The provider: %s is not enabled for the application",
|
"The provider: %s is not enabled for the application": "The provider: %s is not enabled for the application",
|
||||||
"The user is forbidden to sign in, please contact the administrator": "The user is forbidden to sign in, please contact the administrator",
|
"The user is forbidden to sign in, please contact the administrator": "The user is forbidden to sign in, please contact the administrator",
|
||||||
"The user: %s/%s doesn't exist": "The user: %s/%s doesn't exist",
|
|
||||||
"Turing test failed.": "Turing test failed.",
|
"Turing test failed.": "Turing test failed.",
|
||||||
"Unauthorized operation": "Unauthorized operation",
|
"Unauthorized operation": "Unauthorized operation",
|
||||||
"Unknown authentication type (not password or provider), form = %s": "Unknown authentication type (not password or provider), form = %s"
|
"Unknown authentication type (not password or provider), form = %s": "Unknown authentication type (not password or provider), form = %s"
|
||||||
@ -53,11 +50,8 @@
|
|||||||
"Phone already exists": "Phone already exists",
|
"Phone already exists": "Phone already exists",
|
||||||
"Phone cannot be empty": "Phone cannot be empty",
|
"Phone cannot be empty": "Phone cannot be empty",
|
||||||
"Phone number is invalid": "Phone number is invalid",
|
"Phone number is invalid": "Phone number is invalid",
|
||||||
"Please login first": "Please login first",
|
|
||||||
"Session outdated, please login again": "Session outdated, please login again",
|
"Session outdated, please login again": "Session outdated, please login again",
|
||||||
"The user doesn't exist": "The user doesn't exist",
|
|
||||||
"The user is forbidden to sign in, please contact the administrator": "The user is forbidden to sign in, please contact the administrator",
|
"The user is forbidden to sign in, please contact the administrator": "The user is forbidden to sign in, please contact the administrator",
|
||||||
"The user: %s doesn't exist": "The user: %s doesn't exist",
|
|
||||||
"The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline.": "The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline.",
|
"The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline.": "The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline.",
|
||||||
"Username already exists": "Username already exists",
|
"Username already exists": "Username already exists",
|
||||||
"Username cannot be an email address": "Username cannot be an email address",
|
"Username cannot be an email address": "Username cannot be an email address",
|
||||||
@ -65,16 +59,13 @@
|
|||||||
"Username cannot start with a digit": "Username cannot start with a digit",
|
"Username cannot start with a digit": "Username cannot start with a digit",
|
||||||
"Username is too long (maximum is 39 characters).": "Username is too long (maximum is 39 characters).",
|
"Username is too long (maximum is 39 characters).": "Username is too long (maximum is 39 characters).",
|
||||||
"Username must have at least 2 characters": "Username must have at least 2 characters",
|
"Username must have at least 2 characters": "Username must have at least 2 characters",
|
||||||
"You don't have the permission to do this": "You don't have the permission to do this",
|
"You have entered the wrong password or code too many times, please wait for %d minutes and try again": "You have entered the wrong password or code too many times, please wait for %d minutes and try again",
|
||||||
"You have entered the wrong password too many times, please wait for %d minutes %d seconds and try again": "You have entered the wrong password too many times, please wait for %d minutes %d seconds and try again",
|
"password or code is incorrect, you have %d remaining chances": "password or code is incorrect, you have %d remaining chances",
|
||||||
"unsupported password type: %s": "unsupported password type: %s"
|
"unsupported password type: %s": "unsupported password type: %s"
|
||||||
},
|
},
|
||||||
"check_util": {
|
"general": {
|
||||||
"You have entered the wrong password too many times, please wait for %d minutes and try again": "You have entered the wrong password too many times, please wait for %d minutes and try again",
|
"Please login first": "Please login first",
|
||||||
"password is incorrect, you have %d remaining chances": "password is incorrect, you have %d remaining chances"
|
"The user: %s doesn't exist": "The user: %s doesn't exist"
|
||||||
},
|
|
||||||
"enforcer": {
|
|
||||||
"Please sign in first": "Please sign in first"
|
|
||||||
},
|
},
|
||||||
"ldap": {
|
"ldap": {
|
||||||
"Ldap server exist": "Ldap server exist",
|
"Ldap server exist": "Ldap server exist",
|
||||||
@ -93,10 +84,6 @@
|
|||||||
"The %s is immutable.": "The %s is immutable.",
|
"The %s is immutable.": "The %s is immutable.",
|
||||||
"Unknown modify rule %s.": "Unknown modify rule %s."
|
"Unknown modify rule %s.": "Unknown modify rule %s."
|
||||||
},
|
},
|
||||||
"product": {
|
|
||||||
"Please login first": "Please login first",
|
|
||||||
"The user: %s doesn't exist": "The user: %s doesn't exist"
|
|
||||||
},
|
|
||||||
"provider": {
|
"provider": {
|
||||||
"Invalid application id": "Invalid application id",
|
"Invalid application id": "Invalid application id",
|
||||||
"the provider: %s does not exist": "the provider: %s does not exist"
|
"the provider: %s does not exist": "the provider: %s does not exist"
|
||||||
@ -120,11 +107,7 @@
|
|||||||
"The objectKey: %s is not allowed": "The objectKey: %s is not allowed",
|
"The objectKey: %s is not allowed": "The objectKey: %s is not allowed",
|
||||||
"The provider type: %s is not supported": "The provider type: %s is not supported"
|
"The provider type: %s is not supported": "The provider type: %s is not supported"
|
||||||
},
|
},
|
||||||
"system_info": {
|
|
||||||
"You are not authorized to access this resource": "You are not authorized to access this resource"
|
|
||||||
},
|
|
||||||
"token": {
|
"token": {
|
||||||
"Challenge method should be S256": "Challenge method should be S256",
|
|
||||||
"Empty clientId or clientSecret": "Empty clientId or clientSecret",
|
"Empty clientId or clientSecret": "Empty clientId or clientSecret",
|
||||||
"Grant_type: %s is not supported in this application": "Grant_type: %s is not supported in this application",
|
"Grant_type: %s is not supported in this application": "Grant_type: %s is not supported in this application",
|
||||||
"Invalid application or wrong clientSecret": "Invalid application or wrong clientSecret",
|
"Invalid application or wrong clientSecret": "Invalid application or wrong clientSecret",
|
||||||
@ -134,8 +117,7 @@
|
|||||||
"user": {
|
"user": {
|
||||||
"Display name cannot be empty": "Display name cannot be empty",
|
"Display name cannot be empty": "Display name cannot be empty",
|
||||||
"New password cannot contain blank space.": "New password cannot contain blank space.",
|
"New password cannot contain blank space.": "New password cannot contain blank space.",
|
||||||
"New password must have at least 6 characters": "New password must have at least 6 characters",
|
"New password must have at least 6 characters": "New password must have at least 6 characters"
|
||||||
"The user: %s/%s doesn't exist": "The user: %s/%s doesn't exist"
|
|
||||||
},
|
},
|
||||||
"user_upload": {
|
"user_upload": {
|
||||||
"Failed to import users": "Failed to import users"
|
"Failed to import users": "Failed to import users"
|
||||||
@ -143,9 +125,7 @@
|
|||||||
"util": {
|
"util": {
|
||||||
"No application is found for userId: %s": "No application is found for userId: %s",
|
"No application is found for userId: %s": "No application is found for userId: %s",
|
||||||
"No provider for category: %s is found for application: %s": "No provider for category: %s is found for application: %s",
|
"No provider for category: %s is found for application: %s": "No provider for category: %s is found for application: %s",
|
||||||
"Please login first": "Please login first",
|
"The provider: %s is not found": "The provider: %s is not found"
|
||||||
"The provider: %s is not found": "The provider: %s is not found",
|
|
||||||
"The user: %s doesn't exist": "The user: %s doesn't exist"
|
|
||||||
},
|
},
|
||||||
"verification": {
|
"verification": {
|
||||||
"Code has not been sent yet!": "Code has not been sent yet!",
|
"Code has not been sent yet!": "Code has not been sent yet!",
|
||||||
@ -154,7 +134,6 @@
|
|||||||
"Missing parameter": "Missing parameter",
|
"Missing parameter": "Missing parameter",
|
||||||
"Organization does not exist": "Organization does not exist",
|
"Organization does not exist": "Organization does not exist",
|
||||||
"Phone number is invalid": "Phone number is invalid",
|
"Phone number is invalid": "Phone number is invalid",
|
||||||
"Please login first": "Please login first",
|
|
||||||
"Turing test failed.": "Turing test failed.",
|
"Turing test failed.": "Turing test failed.",
|
||||||
"Unable to get the email modify rule.": "Unable to get the email modify rule.",
|
"Unable to get the email modify rule.": "Unable to get the email modify rule.",
|
||||||
"Unable to get the phone modify rule.": "Unable to get the phone modify rule.",
|
"Unable to get the phone modify rule.": "Unable to get the phone modify rule.",
|
||||||
@ -165,8 +144,6 @@
|
|||||||
},
|
},
|
||||||
"webauthn": {
|
"webauthn": {
|
||||||
"Found no credentials for this user": "Found no credentials for this user",
|
"Found no credentials for this user": "Found no credentials for this user",
|
||||||
"Please call WebAuthnSigninBegin first": "Please call WebAuthnSigninBegin first",
|
"Please call WebAuthnSigninBegin first": "Please call WebAuthnSigninBegin first"
|
||||||
"Please login first": "Please login first",
|
|
||||||
"The user: %s/%s doesn't exist": "The user: %s/%s doesn't exist"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,31 +4,28 @@
|
|||||||
"Get init score failed, error: %w": "Get init score failed, error: %w",
|
"Get init score failed, error: %w": "Get init score failed, error: %w",
|
||||||
"Invalid information": "Invalid information",
|
"Invalid information": "Invalid information",
|
||||||
"Phone: %s": "Phone: %s",
|
"Phone: %s": "Phone: %s",
|
||||||
|
"Please sign out first before signing in": "Please sign out first before signing in",
|
||||||
"Please sign out first before signing up": "Please sign out first before signing up",
|
"Please sign out first before signing up": "Please sign out first before signing up",
|
||||||
"The application does not allow to sign up new account": "The application does not allow to sign up new account"
|
"The application does not allow to sign up new account": "The application does not allow to sign up new account"
|
||||||
},
|
},
|
||||||
"application": {
|
"application": {
|
||||||
"Parameter organization is missing": "Parameter organization is missing",
|
"Parameter organization is missing": "Parameter organization is missing"
|
||||||
"The user: %s doesn't exist": "The user: %s doesn't exist"
|
|
||||||
},
|
},
|
||||||
"auth": {
|
"auth": {
|
||||||
"%s No phone prefix": "%s No phone prefix",
|
"%s No phone prefix": "%s No phone prefix",
|
||||||
"Challenge method should be S256": "Challenge method should be S256",
|
"Challenge method should be S256": "Challenge method should be S256",
|
||||||
"Failed to create user, user information is invalid: %s": "Failed to create user, user information is invalid: %s",
|
"Failed to create user, user information is invalid: %s": "Failed to create user, user information is invalid: %s",
|
||||||
"Failed to login in: %s": "Failed to login in: %s",
|
"Failed to login in: %s": "Failed to login in: %s",
|
||||||
"Get init score failed, error: %w": "Get init score failed, error: %w",
|
|
||||||
"Invalid token": "Invalid token",
|
"Invalid token": "Invalid token",
|
||||||
"Please sign out first before signing in": "Please sign out first before signing in",
|
|
||||||
"State expected: %s, but got: %s": "State expected: %s, but got: %s",
|
"State expected: %s, but got: %s": "State expected: %s, but got: %s",
|
||||||
"The account does not exist": "The account does not exist",
|
|
||||||
"The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account via %%s, please use another way to sign up": "The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account via %%s, please use another way to sign up",
|
"The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account via %%s, please use another way to sign up": "The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account via %%s, please use another way to sign up",
|
||||||
"The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support": "The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support",
|
"The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support": "The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support",
|
||||||
"The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)": "The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)",
|
"The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)": "The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)",
|
||||||
"The application: %s does not exist": "The application: %s does not exist",
|
"The application: %s does not exist": "The application: %s does not exist",
|
||||||
|
"The login method: login with password is not enabled for the application": "The login method: login with password is not enabled for the application",
|
||||||
"The provider type: %s is not supported": "The provider type: %s is not supported",
|
"The provider type: %s is not supported": "The provider type: %s is not supported",
|
||||||
"The provider: %s is not enabled for the application": "The provider: %s is not enabled for the application",
|
"The provider: %s is not enabled for the application": "The provider: %s is not enabled for the application",
|
||||||
"The user is forbidden to sign in, please contact the administrator": "The user is forbidden to sign in, please contact the administrator",
|
"The user is forbidden to sign in, please contact the administrator": "The user is forbidden to sign in, please contact the administrator",
|
||||||
"The user: %s/%s doesn't exist": "The user: %s/%s doesn't exist",
|
|
||||||
"Turing test failed.": "Turing test failed.",
|
"Turing test failed.": "Turing test failed.",
|
||||||
"Unauthorized operation": "Unauthorized operation",
|
"Unauthorized operation": "Unauthorized operation",
|
||||||
"Unknown authentication type (not password or provider), form = %s": "Unknown authentication type (not password or provider), form = %s"
|
"Unknown authentication type (not password or provider), form = %s": "Unknown authentication type (not password or provider), form = %s"
|
||||||
@ -53,11 +50,8 @@
|
|||||||
"Phone already exists": "Phone already exists",
|
"Phone already exists": "Phone already exists",
|
||||||
"Phone cannot be empty": "Phone cannot be empty",
|
"Phone cannot be empty": "Phone cannot be empty",
|
||||||
"Phone number is invalid": "Phone number is invalid",
|
"Phone number is invalid": "Phone number is invalid",
|
||||||
"Please login first": "Please login first",
|
|
||||||
"Session outdated, please login again": "Session outdated, please login again",
|
"Session outdated, please login again": "Session outdated, please login again",
|
||||||
"The user doesn't exist": "The user doesn't exist",
|
|
||||||
"The user is forbidden to sign in, please contact the administrator": "The user is forbidden to sign in, please contact the administrator",
|
"The user is forbidden to sign in, please contact the administrator": "The user is forbidden to sign in, please contact the administrator",
|
||||||
"The user: %s doesn't exist": "The user: %s doesn't exist",
|
|
||||||
"The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline.": "The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline.",
|
"The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline.": "The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline.",
|
||||||
"Username already exists": "Username already exists",
|
"Username already exists": "Username already exists",
|
||||||
"Username cannot be an email address": "Username cannot be an email address",
|
"Username cannot be an email address": "Username cannot be an email address",
|
||||||
@ -65,16 +59,13 @@
|
|||||||
"Username cannot start with a digit": "Username cannot start with a digit",
|
"Username cannot start with a digit": "Username cannot start with a digit",
|
||||||
"Username is too long (maximum is 39 characters).": "Username is too long (maximum is 39 characters).",
|
"Username is too long (maximum is 39 characters).": "Username is too long (maximum is 39 characters).",
|
||||||
"Username must have at least 2 characters": "Username must have at least 2 characters",
|
"Username must have at least 2 characters": "Username must have at least 2 characters",
|
||||||
"You don't have the permission to do this": "You don't have the permission to do this",
|
"You have entered the wrong password or code too many times, please wait for %d minutes and try again": "You have entered the wrong password or code too many times, please wait for %d minutes and try again",
|
||||||
"You have entered the wrong password too many times, please wait for %d minutes %d seconds and try again": "You have entered the wrong password too many times, please wait for %d minutes %d seconds and try again",
|
"password or code is incorrect, you have %d remaining chances": "password or code is incorrect, you have %d remaining chances",
|
||||||
"unsupported password type: %s": "unsupported password type: %s"
|
"unsupported password type: %s": "unsupported password type: %s"
|
||||||
},
|
},
|
||||||
"check_util": {
|
"general": {
|
||||||
"You have entered the wrong password too many times, please wait for %d minutes and try again": "You have entered the wrong password too many times, please wait for %d minutes and try again",
|
"Please login first": "Please login first",
|
||||||
"password is incorrect, you have %d remaining chances": "password is incorrect, you have %d remaining chances"
|
"The user: %s doesn't exist": "The user: %s doesn't exist"
|
||||||
},
|
|
||||||
"enforcer": {
|
|
||||||
"Please sign in first": "Please sign in first"
|
|
||||||
},
|
},
|
||||||
"ldap": {
|
"ldap": {
|
||||||
"Ldap server exist": "Ldap server exist",
|
"Ldap server exist": "Ldap server exist",
|
||||||
@ -93,10 +84,6 @@
|
|||||||
"The %s is immutable.": "The %s is immutable.",
|
"The %s is immutable.": "The %s is immutable.",
|
||||||
"Unknown modify rule %s.": "Unknown modify rule %s."
|
"Unknown modify rule %s.": "Unknown modify rule %s."
|
||||||
},
|
},
|
||||||
"product": {
|
|
||||||
"Please login first": "Please login first",
|
|
||||||
"The user: %s doesn't exist": "The user: %s doesn't exist"
|
|
||||||
},
|
|
||||||
"provider": {
|
"provider": {
|
||||||
"Invalid application id": "Invalid application id",
|
"Invalid application id": "Invalid application id",
|
||||||
"the provider: %s does not exist": "the provider: %s does not exist"
|
"the provider: %s does not exist": "the provider: %s does not exist"
|
||||||
@ -120,11 +107,7 @@
|
|||||||
"The objectKey: %s is not allowed": "The objectKey: %s is not allowed",
|
"The objectKey: %s is not allowed": "The objectKey: %s is not allowed",
|
||||||
"The provider type: %s is not supported": "The provider type: %s is not supported"
|
"The provider type: %s is not supported": "The provider type: %s is not supported"
|
||||||
},
|
},
|
||||||
"system_info": {
|
|
||||||
"You are not authorized to access this resource": "You are not authorized to access this resource"
|
|
||||||
},
|
|
||||||
"token": {
|
"token": {
|
||||||
"Challenge method should be S256": "Challenge method should be S256",
|
|
||||||
"Empty clientId or clientSecret": "Empty clientId or clientSecret",
|
"Empty clientId or clientSecret": "Empty clientId or clientSecret",
|
||||||
"Grant_type: %s is not supported in this application": "Grant_type: %s is not supported in this application",
|
"Grant_type: %s is not supported in this application": "Grant_type: %s is not supported in this application",
|
||||||
"Invalid application or wrong clientSecret": "Invalid application or wrong clientSecret",
|
"Invalid application or wrong clientSecret": "Invalid application or wrong clientSecret",
|
||||||
@ -134,8 +117,7 @@
|
|||||||
"user": {
|
"user": {
|
||||||
"Display name cannot be empty": "Display name cannot be empty",
|
"Display name cannot be empty": "Display name cannot be empty",
|
||||||
"New password cannot contain blank space.": "New password cannot contain blank space.",
|
"New password cannot contain blank space.": "New password cannot contain blank space.",
|
||||||
"New password must have at least 6 characters": "New password must have at least 6 characters",
|
"New password must have at least 6 characters": "New password must have at least 6 characters"
|
||||||
"The user: %s/%s doesn't exist": "The user: %s/%s doesn't exist"
|
|
||||||
},
|
},
|
||||||
"user_upload": {
|
"user_upload": {
|
||||||
"Failed to import users": "Failed to import users"
|
"Failed to import users": "Failed to import users"
|
||||||
@ -143,9 +125,7 @@
|
|||||||
"util": {
|
"util": {
|
||||||
"No application is found for userId: %s": "No application is found for userId: %s",
|
"No application is found for userId: %s": "No application is found for userId: %s",
|
||||||
"No provider for category: %s is found for application: %s": "No provider for category: %s is found for application: %s",
|
"No provider for category: %s is found for application: %s": "No provider for category: %s is found for application: %s",
|
||||||
"Please login first": "Please login first",
|
"The provider: %s is not found": "The provider: %s is not found"
|
||||||
"The provider: %s is not found": "The provider: %s is not found",
|
|
||||||
"The user: %s doesn't exist": "The user: %s doesn't exist"
|
|
||||||
},
|
},
|
||||||
"verification": {
|
"verification": {
|
||||||
"Code has not been sent yet!": "Code has not been sent yet!",
|
"Code has not been sent yet!": "Code has not been sent yet!",
|
||||||
@ -154,7 +134,6 @@
|
|||||||
"Missing parameter": "Missing parameter",
|
"Missing parameter": "Missing parameter",
|
||||||
"Organization does not exist": "Organization does not exist",
|
"Organization does not exist": "Organization does not exist",
|
||||||
"Phone number is invalid": "Phone number is invalid",
|
"Phone number is invalid": "Phone number is invalid",
|
||||||
"Please login first": "Please login first",
|
|
||||||
"Turing test failed.": "Turing test failed.",
|
"Turing test failed.": "Turing test failed.",
|
||||||
"Unable to get the email modify rule.": "Unable to get the email modify rule.",
|
"Unable to get the email modify rule.": "Unable to get the email modify rule.",
|
||||||
"Unable to get the phone modify rule.": "Unable to get the phone modify rule.",
|
"Unable to get the phone modify rule.": "Unable to get the phone modify rule.",
|
||||||
@ -165,8 +144,6 @@
|
|||||||
},
|
},
|
||||||
"webauthn": {
|
"webauthn": {
|
||||||
"Found no credentials for this user": "Found no credentials for this user",
|
"Found no credentials for this user": "Found no credentials for this user",
|
||||||
"Please call WebAuthnSigninBegin first": "Please call WebAuthnSigninBegin first",
|
"Please call WebAuthnSigninBegin first": "Please call WebAuthnSigninBegin first"
|
||||||
"Please login first": "Please login first",
|
|
||||||
"The user: %s/%s doesn't exist": "The user: %s/%s doesn't exist"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,161 +3,140 @@
|
|||||||
"Email: %s": "邮件: %s",
|
"Email: %s": "邮件: %s",
|
||||||
"Get init score failed, error: %w": "初始化分数失败: %w",
|
"Get init score failed, error: %w": "初始化分数失败: %w",
|
||||||
"Invalid information": "无效信息",
|
"Invalid information": "无效信息",
|
||||||
"Phone: %s": "电话: %s",
|
"Phone: %s": "手机号: %s",
|
||||||
"Please sign out first before signing up": "请在登陆前登出",
|
"Please sign out first before signing in": "请在登录前先退出登录",
|
||||||
"The application does not allow to sign up new account": "该应用不允许注册新账户"
|
"Please sign out first before signing up": "请在注册前先退出登录",
|
||||||
|
"The application does not allow to sign up new account": "该应用不允许注册新用户"
|
||||||
},
|
},
|
||||||
"application": {
|
"application": {
|
||||||
"Parameter organization is missing": "Organization参数丢失",
|
"Parameter organization is missing": "缺少organization参数"
|
||||||
"The user: %s doesn't exist": "用户不存在: %s"
|
|
||||||
},
|
},
|
||||||
"auth": {
|
"auth": {
|
||||||
"%s No phone prefix": "%s 无此电话前缀",
|
"%s No phone prefix": "%s 无此手机号前缀",
|
||||||
"Challenge method should be S256": "Challenge 方法应该为 S256",
|
"Challenge method should be S256": "Challenge 方法应该为 S256",
|
||||||
"Failed to create user, user information is invalid: %s": "创建用户失败,用户信息无效: %s",
|
"Failed to create user, user information is invalid: %s": "创建用户失败,用户信息无效: %s",
|
||||||
"Failed to login in: %s": "无法登录: %s",
|
"Failed to login in: %s": "登录失败: %s",
|
||||||
"Get init score failed, error: %w": "初始化分数失败: %w",
|
|
||||||
"Invalid token": "无效token",
|
"Invalid token": "无效token",
|
||||||
"Please sign out first before signing in": "请在登陆前登出",
|
"State expected: %s, but got: %s": "期望状态为: %s, 实际状态为: %s",
|
||||||
"State expected: %s, but got: %s": "期望状态位: %s, 实际状态为: %s",
|
|
||||||
"The account does not exist": "账户不存在",
|
|
||||||
"The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account via %%s, please use another way to sign up": "提供商账户: %s 与用户名: %s (%s) 不存在且 不允许通过 %s 注册新账户, 请使用其他方式注册",
|
"The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account via %%s, please use another way to sign up": "提供商账户: %s 与用户名: %s (%s) 不存在且 不允许通过 %s 注册新账户, 请使用其他方式注册",
|
||||||
"The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support": "提供商账户: %s 与用户名: %s (%s) 不存在且 不允许注册新账户, 请联系IT支持",
|
"The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support": "提供商账户: %s 与用户名: %s (%s) 不存在且 不允许注册新账户, 请联系IT支持",
|
||||||
"The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)": "提供商账户: %s 与用户名: %s (%s) 已经与其他账户绑定: %s (%s)",
|
"The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)": "提供商账户: %s 与用户名: %s (%s) 已经与其他账户绑定: %s (%s)",
|
||||||
"The application: %s does not exist": "应用 %s 不存在",
|
"The application: %s does not exist": "应用 %s 不存在",
|
||||||
|
"The login method: login with password is not enabled for the application": "该应用禁止采用密码登录方式",
|
||||||
"The provider type: %s is not supported": "不支持该类型的提供商: %s",
|
"The provider type: %s is not supported": "不支持该类型的提供商: %s",
|
||||||
"The provider: %s is not enabled for the application": "提供商: %s 未被启用",
|
"The provider: %s is not enabled for the application": "该应用的提供商: %s 未被启用",
|
||||||
"The user is forbidden to sign in, please contact the administrator": "该用户被禁止登陆,请联系管理员",
|
"The user is forbidden to sign in, please contact the administrator": "该用户被禁止登录,请联系管理员",
|
||||||
"The user: %s/%s doesn't exist": "用户不存在: %s/%s",
|
"Turing test failed.": "人机验证失败",
|
||||||
"Turing test failed.": "真人验证失败",
|
|
||||||
"Unauthorized operation": "未授权的操作",
|
"Unauthorized operation": "未授权的操作",
|
||||||
"Unknown authentication type (not password or provider), form = %s": "未授权的操作"
|
"Unknown authentication type (not password or provider), form = %s": "未知的认证类型(非密码或第三方提供商):%s"
|
||||||
},
|
},
|
||||||
"cas": {
|
"cas": {
|
||||||
"Service %s and %s do not match": "服务 %s 与 %s 不匹配"
|
"Service %s and %s do not match": "服务 %s 与 %s 不匹配"
|
||||||
},
|
},
|
||||||
"check": {
|
"check": {
|
||||||
"Affiliation cannot be blank": "联系方式不可为空",
|
"Affiliation cannot be blank": "工作单位不可为空",
|
||||||
"DisplayName cannot be blank": "展示名称不可为空",
|
"DisplayName cannot be blank": "显示名称不可为空",
|
||||||
"DisplayName is not valid real name": "展示名称无效",
|
"DisplayName is not valid real name": "显示名称必须是真实姓名",
|
||||||
"Email already exists": "该邮箱已存在",
|
"Email already exists": "该邮箱已存在",
|
||||||
"Email cannot be empty": "邮箱不可为空",
|
"Email cannot be empty": "邮箱不可为空",
|
||||||
"Email is invalid": "无效邮箱",
|
"Email is invalid": "无效邮箱",
|
||||||
"Empty username.": "用户名不可为空",
|
"Empty username.": "用户名不可为空",
|
||||||
"FirstName cannot be blank": "名不可以为空",
|
"FirstName cannot be blank": "名不可以为空",
|
||||||
"LastName cannot be blank": "姓不可以为空",
|
"LastName cannot be blank": "姓不可以为空",
|
||||||
"Ldap user name or password incorrect": "Ldap密码错误",
|
"Ldap user name or password incorrect": "LDAP密码错误",
|
||||||
"Multiple accounts with same uid, please check your ldap server": "多个帐户具有相同的uid,请检查您的 ldap 服务器",
|
"Multiple accounts with same uid, please check your ldap server": "多个帐户具有相同的uid,请检查您的 LDAP 服务器",
|
||||||
"Organization does not exist": "组织不存在",
|
"Organization does not exist": "组织不存在",
|
||||||
"Password must have at least 6 characters": "新密码至少为6位",
|
"Password must have at least 6 characters": "新密码至少为6位",
|
||||||
"Phone already exists": "该电话已存在",
|
"Phone already exists": "该手机号已存在",
|
||||||
"Phone cannot be empty": "电话不可为空",
|
"Phone cannot be empty": "手机号不可为空",
|
||||||
"Phone number is invalid": "无效电话",
|
"Phone number is invalid": "无效手机号",
|
||||||
"Please login first": "请先登录",
|
"Session outdated, please login again": "会话已过期,请重新登录",
|
||||||
"Session outdated, please login again": "Session已过期,请重新登陆",
|
"The user is forbidden to sign in, please contact the administrator": "该用户被禁止登录,请联系管理员",
|
||||||
"The user doesn't exist": "用户不存在",
|
|
||||||
"The user is forbidden to sign in, please contact the administrator": "该用户被禁止登陆,请联系管理员",
|
|
||||||
"The user: %s doesn't exist": "用户不存在: %s",
|
|
||||||
"The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline.": "用户名只能包含字母数字字符、下划线或连字符,不能有连续的连字符或下划线,也不能以连字符或下划线开头或结尾",
|
"The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline.": "用户名只能包含字母数字字符、下划线或连字符,不能有连续的连字符或下划线,也不能以连字符或下划线开头或结尾",
|
||||||
"Username already exists": "用户名已存在",
|
"Username already exists": "用户名已存在",
|
||||||
"Username cannot be an email address": "用户名不可以是邮箱地址",
|
"Username cannot be an email address": "用户名不可以是邮箱地址",
|
||||||
"Username cannot contain white spaces": "用户名不可以包含空格",
|
"Username cannot contain white spaces": "用户名禁止包含空格",
|
||||||
"Username cannot start with a digit": "用户名禁止使用数字作为第一个字符",
|
"Username cannot start with a digit": "用户名禁止使用数字开头",
|
||||||
"Username is too long (maximum is 39 characters).": "用户名过长(最大长度为39个字符)",
|
"Username is too long (maximum is 39 characters).": "用户名过长(最大允许长度为39个字符)",
|
||||||
"Username must have at least 2 characters": "用户名至少要有2个字符",
|
"Username must have at least 2 characters": "用户名至少要有2个字符",
|
||||||
"You don't have the permission to do this": "用户名至少要有2个字符",
|
"You have entered the wrong password or code too many times, please wait for %d minutes and try again": "密码错误次数已达上限,请在 %d 分后重试",
|
||||||
"You have entered the wrong password too many times, please wait for %d minutes %d seconds and try again": "输入密码错误次数已达上限,请在 %d 分 %d 秒后重试",
|
"password or code is incorrect, you have %d remaining chances": "密码错误,您还有 %d 次尝试的机会",
|
||||||
"unsupported password type: %s": "不支持的密码类型: %s"
|
"unsupported password type: %s": "不支持的密码类型: %s"
|
||||||
},
|
},
|
||||||
"check_util": {
|
"general": {
|
||||||
"You have entered the wrong password too many times, please wait for %d minutes and try again": "输入密码错误次数已达上限,请在 %d 分后重试",
|
"Please login first": "请先登录",
|
||||||
"password is incorrect, you have %d remaining chances": "密码错误,您还有 %d 次尝试的机会"
|
"The user: %s doesn't exist": "用户: %s 不存在"
|
||||||
},
|
|
||||||
"enforcer": {
|
|
||||||
"Please sign in first": "请先登录"
|
|
||||||
},
|
},
|
||||||
"ldap": {
|
"ldap": {
|
||||||
"Ldap server exist": "Ldap服务器已存在",
|
"Ldap server exist": "LDAP服务器已存在",
|
||||||
"Missing parameter": "参数丢失"
|
"Missing parameter": "LDAP缺少参数"
|
||||||
},
|
},
|
||||||
"link": {
|
"link": {
|
||||||
"Please link first": "请先绑定",
|
"Please link first": "请先绑定",
|
||||||
"This application has no providers": "该应用无提供商",
|
"This application has no providers": "该应用无可用的提供商",
|
||||||
"This application has no providers of type": "应用没有该类型的提供商",
|
"This application has no providers of type": "应用没有该类型的提供商",
|
||||||
"This provider can't be unlinked": "该提供商不可被链接",
|
"This provider can't be unlinked": "该提供商被禁止解绑",
|
||||||
"You are not the global admin, you can't unlink other users": "您不是全局管理员,无法取消链接其他用户",
|
"You are not the global admin, you can't unlink other users": "您不是全局管理员,无法解绑其他用户",
|
||||||
"You can't unlink yourself, you are not a member of any application": "您无法取消链接,您不是任何应用程序的成员"
|
"You can't unlink yourself, you are not a member of any application": "您无法自行解绑,您不是任何应用程序的成员"
|
||||||
},
|
},
|
||||||
"organization": {
|
"organization": {
|
||||||
"Only admin can modify the %s.": "您无法取消链接,您不是任何应用程序的成员",
|
"Only admin can modify the %s.": "仅允许管理员可以修改 %s",
|
||||||
"The %s is immutable.": "%s 是不可变的",
|
"The %s is immutable.": "%s 是不可变的",
|
||||||
"Unknown modify rule %s.": "未知的修改规则"
|
"Unknown modify rule %s.": "未知的修改规则: %s"
|
||||||
},
|
|
||||||
"product": {
|
|
||||||
"Please login first": "请先登录",
|
|
||||||
"The user: %s doesn't exist": "用户不存在: %s"
|
|
||||||
},
|
},
|
||||||
"provider": {
|
"provider": {
|
||||||
"Invalid application id": "无效的Application ID",
|
"Invalid application id": "无效的应用ID",
|
||||||
"the provider: %s does not exist": "提供商: %s 不存在"
|
"the provider: %s does not exist": "提供商: %s 不存在"
|
||||||
},
|
},
|
||||||
"resource": {
|
"resource": {
|
||||||
"User is nil for tag: avatar": "用户头像标签为空",
|
"User is nil for tag: avatar": "上传头像时用户为空",
|
||||||
"Username or fullFilePath is empty: username = %s, fullFilePath = %s": "username或FilePath为空: username = %s, fullFilePath = %s"
|
"Username or fullFilePath is empty: username = %s, fullFilePath = %s": "username或fullFilePath为空: username = %s, fullFilePath = %s"
|
||||||
},
|
},
|
||||||
"saml": {
|
"saml": {
|
||||||
"Application %s not found": "应用 %s 未找到"
|
"Application %s not found": "未找到应用: %s"
|
||||||
},
|
},
|
||||||
"saml_sp": {
|
"saml_sp": {
|
||||||
"provider %s's category is not SAML": "提供商 %s类型不是SAML"
|
"provider %s's category is not SAML": "提供商: %s 不是SAML类型"
|
||||||
},
|
},
|
||||||
"service": {
|
"service": {
|
||||||
"Empty parameters for emailForm: %v": "邮件参数为空: %v",
|
"Empty parameters for emailForm: %v": "邮件参数为空: %v",
|
||||||
"Invalid Email receivers: %s": " 无效的邮箱接收者: %s",
|
"Invalid Email receivers: %s": " 无效的邮箱收件人: %s",
|
||||||
"Invalid phone receivers: %s": "无效的电话接收者: %s"
|
"Invalid phone receivers: %s": "无效的手机短信收信人: %s"
|
||||||
},
|
},
|
||||||
"storage": {
|
"storage": {
|
||||||
"The objectKey: %s is not allowed": "object key :%s 不被允许",
|
"The objectKey: %s is not allowed": "objectKey: %s 被禁止",
|
||||||
"The provider type: %s is not supported": "提供商类型: %s 尚未支持"
|
"The provider type: %s is not supported": "不支持的提供商类型: %s"
|
||||||
},
|
|
||||||
"system_info": {
|
|
||||||
"You are not authorized to access this resource": "您无权获取此资源"
|
|
||||||
},
|
},
|
||||||
"token": {
|
"token": {
|
||||||
"Challenge method should be S256": "Challenge 方法应该为 S256",
|
|
||||||
"Empty clientId or clientSecret": "clientId或clientSecret为空",
|
"Empty clientId or clientSecret": "clientId或clientSecret为空",
|
||||||
"Grant_type: %s is not supported in this application": "此应用中不支持此授权类型: %s",
|
"Grant_type: %s is not supported in this application": "该应用不支持Grant_type: %s",
|
||||||
"Invalid application or wrong clientSecret": "无效应用或错误的clientSecret",
|
"Invalid application or wrong clientSecret": "无效应用或错误的clientSecret",
|
||||||
"Invalid client_id": "无效的ClientId",
|
"Invalid client_id": "无效的ClientId",
|
||||||
"Redirect URI: %s doesn't exist in the allowed Redirect URI list": "重定向 URI:%s 在可列表中未找到"
|
"Redirect URI: %s doesn't exist in the allowed Redirect URI list": "重定向 URI:%s 在许可跳转列表中未找到"
|
||||||
},
|
},
|
||||||
"user": {
|
"user": {
|
||||||
"Display name cannot be empty": "展示名称不可为空",
|
"Display name cannot be empty": "显示名称不可为空",
|
||||||
"New password cannot contain blank space.": "新密码不可以包含空格",
|
"New password cannot contain blank space.": "新密码不可以包含空格",
|
||||||
"New password must have at least 6 characters": "新密码至少需要6位字符",
|
"New password must have at least 6 characters": "新密码至少需要6位字符"
|
||||||
"The user: %s/%s doesn't exist": "用户不存在: %s/%s"
|
|
||||||
},
|
},
|
||||||
"user_upload": {
|
"user_upload": {
|
||||||
"Failed to import users": "导入用户失败"
|
"Failed to import users": "导入用户失败"
|
||||||
},
|
},
|
||||||
"util": {
|
"util": {
|
||||||
"No application is found for userId: %s": "找不到该用户的应用程序 %s",
|
"No application is found for userId: %s": "未找到用户: %s 的应用",
|
||||||
"No provider for category: %s is found for application: %s": "找不到该用户的应用程序 %s",
|
"No provider for category: %s is found for application: %s": "未找到类别为: %s 的提供商来满足应用: %s",
|
||||||
"Please login first": "请先登录",
|
"The provider: %s is not found": "未找到提供商: %s"
|
||||||
"The provider: %s is not found": "该提供商未找到: %s",
|
|
||||||
"The user: %s doesn't exist": "用户不存在: %s"
|
|
||||||
},
|
},
|
||||||
"verification": {
|
"verification": {
|
||||||
"Code has not been sent yet!": "验证码还未发送",
|
"Code has not been sent yet!": "验证码还未发送",
|
||||||
"Email is invalid": "非法的邮箱",
|
"Email is invalid": "非法的邮箱",
|
||||||
"Invalid captcha provider.": "非法的验证码提供商",
|
"Invalid captcha provider.": "非法的验证码提供商",
|
||||||
"Missing parameter": "参数丢失",
|
"Missing parameter": "缺少参数",
|
||||||
"Organization does not exist": "组织不存在",
|
"Organization does not exist": "组织不存在",
|
||||||
"Phone number is invalid": "非法的电话号码",
|
"Phone number is invalid": "非法的手机号码",
|
||||||
"Please login first": "请先登录",
|
|
||||||
"Turing test failed.": "验证码还未发送",
|
"Turing test failed.": "验证码还未发送",
|
||||||
"Unable to get the email modify rule.": "无法得到邮箱修改规则",
|
"Unable to get the email modify rule.": "无法获取邮箱修改规则",
|
||||||
"Unable to get the phone modify rule.": "无法得到电话修改规则",
|
"Unable to get the phone modify rule.": "无法获取手机号修改规则",
|
||||||
"Unknown type": "未知类型",
|
"Unknown type": "未知类型",
|
||||||
"Wrong parameter": "参数错误",
|
"Wrong parameter": "参数错误",
|
||||||
"You should verify your code in %d min!": "请在 %d 分钟内输入正确验证码",
|
"You should verify your code in %d min!": "请在 %d 分钟内输入正确验证码",
|
||||||
@ -165,8 +144,6 @@
|
|||||||
},
|
},
|
||||||
"webauthn": {
|
"webauthn": {
|
||||||
"Found no credentials for this user": "该用户没有 WebAuthn 凭据",
|
"Found no credentials for this user": "该用户没有 WebAuthn 凭据",
|
||||||
"Please call WebAuthnSigninBegin first": "请先调用 WebAuthnSigninBegi",
|
"Please call WebAuthnSigninBegin first": "请先调用 WebAuthnSigninBegin"
|
||||||
"Please login first": "请先登录",
|
|
||||||
"The user: %s/%s doesn't exist": "用户: %s/%s 不存在"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
14
i18n/util.go
14
i18n/util.go
@ -27,18 +27,16 @@ var f embed.FS
|
|||||||
|
|
||||||
var langMap = make(map[string]map[string]map[string]string) // for example : langMap[en][account][Invalid information] = Invalid information
|
var langMap = make(map[string]map[string]map[string]string) // for example : langMap[en][account][Invalid information] = Invalid information
|
||||||
|
|
||||||
func getI18nFilePath(language string) string {
|
func getI18nFilePath(category string, language string) string {
|
||||||
if strings.Contains(language, "backend") {
|
if category == "backend" {
|
||||||
// change language from 'backend_en' to 'en'
|
|
||||||
language = language[8:]
|
|
||||||
return fmt.Sprintf("../i18n/locales/%s/data.json", language)
|
return fmt.Sprintf("../i18n/locales/%s/data.json", language)
|
||||||
} else {
|
} else {
|
||||||
return fmt.Sprintf("../web/src/locales/%s/data.json", language)
|
return fmt.Sprintf("../web/src/locales/%s/data.json", language)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func readI18nFile(language string) *I18nData {
|
func readI18nFile(category string, language string) *I18nData {
|
||||||
s := util.ReadStringFromPath(getI18nFilePath(language))
|
s := util.ReadStringFromPath(getI18nFilePath(category, language))
|
||||||
|
|
||||||
data := &I18nData{}
|
data := &I18nData{}
|
||||||
err := util.JsonToStruct(s, data)
|
err := util.JsonToStruct(s, data)
|
||||||
@ -48,13 +46,13 @@ func readI18nFile(language string) *I18nData {
|
|||||||
return data
|
return data
|
||||||
}
|
}
|
||||||
|
|
||||||
func writeI18nFile(language string, data *I18nData) {
|
func writeI18nFile(category string, language string, data *I18nData) {
|
||||||
s := util.StructToJsonFormatted(data)
|
s := util.StructToJsonFormatted(data)
|
||||||
s = strings.ReplaceAll(s, "\\u0026", "&")
|
s = strings.ReplaceAll(s, "\\u0026", "&")
|
||||||
s += "\n"
|
s += "\n"
|
||||||
println(s)
|
println(s)
|
||||||
|
|
||||||
util.WriteStringToPath(s, getI18nFilePath(language))
|
util.WriteStringToPath(s, getI18nFilePath(category, language))
|
||||||
}
|
}
|
||||||
|
|
||||||
func applyData(data1 *I18nData, data2 *I18nData) {
|
func applyData(data1 *I18nData, data2 *I18nData) {
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -98,7 +98,7 @@ func GetIdProvider(typ string, subType string, clientId string, clientSecret str
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var gothList = []string{"Apple", "AzureAD", "Slack", "Steam"}
|
var gothList = []string{"Apple", "AzureAD", "Slack", "Steam", "Line"}
|
||||||
|
|
||||||
func isGothSupport(provider string) bool {
|
func isGothSupport(provider string) bool {
|
||||||
for _, value := range gothList {
|
for _, value := range gothList {
|
||||||
|
@ -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": ""
|
||||||
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -222,6 +222,11 @@ func (a *Adapter) createTable() {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err = a.Engine.Sync2(new(Session))
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetSession(owner string, offset, limit int, field, value, sortField, sortOrder string) *xorm.Session {
|
func GetSession(owner string, offset, limit int, field, value, sortField, sortOrder string) *xorm.Session {
|
||||||
|
@ -16,7 +16,6 @@ package object
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/url"
|
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@ -51,6 +50,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"`
|
||||||
@ -353,54 +353,28 @@ func (application *Application) GetId() string {
|
|||||||
return fmt.Sprintf("%s/%s", application.Owner, application.Name)
|
return fmt.Sprintf("%s/%s", application.Owner, application.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
func CheckRedirectUriValid(application *Application, redirectUri string) bool {
|
func (application *Application) IsRedirectUriValid(redirectUri string) bool {
|
||||||
validUri := false
|
isValid := false
|
||||||
for _, tmpUri := range application.RedirectUris {
|
for _, targetUri := range application.RedirectUris {
|
||||||
tmpUriRegex := regexp.MustCompile(tmpUri)
|
targetUriRegex := regexp.MustCompile(targetUri)
|
||||||
if tmpUriRegex.MatchString(redirectUri) || strings.Contains(redirectUri, tmpUri) {
|
if targetUriRegex.MatchString(redirectUri) || strings.Contains(redirectUri, targetUri) {
|
||||||
validUri = true
|
isValid = true
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return validUri
|
return isValid
|
||||||
}
|
}
|
||||||
|
|
||||||
func IsAllowOrigin(origin string) bool {
|
func IsOriginAllowed(origin string) bool {
|
||||||
allowOrigin := false
|
applications := GetApplications("")
|
||||||
originUrl, err := url.Parse(origin)
|
for _, application := range applications {
|
||||||
if err != nil {
|
if application.IsRedirectUriValid(origin) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
rows, err := adapter.Engine.Cols("redirect_uris").Rows(&Application{})
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
application := Application{}
|
|
||||||
for rows.Next() {
|
|
||||||
err := rows.Scan(&application)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
for _, tmpRedirectUri := range application.RedirectUris {
|
|
||||||
u1, err := url.Parse(tmpRedirectUri)
|
|
||||||
if err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if u1.Scheme == originUrl.Scheme && u1.Host == originUrl.Host {
|
|
||||||
allowOrigin = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if allowOrigin {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return allowOrigin
|
|
||||||
}
|
|
||||||
|
|
||||||
func getApplicationMap(organization string) map[string]*Application {
|
func getApplicationMap(organization string) map[string]*Application {
|
||||||
applications := GetOrganizationApplications("admin", organization)
|
applications := GetOrganizationApplications("admin", organization)
|
||||||
|
|
||||||
|
@ -143,11 +143,11 @@ func checkSigninErrorTimes(user *User, lang string) string {
|
|||||||
if user.SigninWrongTimes >= SigninWrongTimesLimit {
|
if user.SigninWrongTimes >= SigninWrongTimesLimit {
|
||||||
lastSignWrongTime, _ := time.Parse(time.RFC3339, user.LastSigninWrongTime)
|
lastSignWrongTime, _ := time.Parse(time.RFC3339, user.LastSigninWrongTime)
|
||||||
passedTime := time.Now().UTC().Sub(lastSignWrongTime)
|
passedTime := time.Now().UTC().Sub(lastSignWrongTime)
|
||||||
seconds := int(LastSignWrongTimeDuration.Seconds() - passedTime.Seconds())
|
minutes := int(LastSignWrongTimeDuration.Minutes() - passedTime.Minutes())
|
||||||
|
|
||||||
// deny the login if the error times is greater than the limit and the last login time is less than the duration
|
// deny the login if the error times is greater than the limit and the last login time is less than the duration
|
||||||
if seconds > 0 {
|
if minutes > 0 {
|
||||||
return fmt.Sprintf(i18n.Translate(lang, "check:You have entered the wrong password too many times, please wait for %d minutes %d seconds and try again"), seconds/60, seconds%60)
|
return fmt.Sprintf(i18n.Translate(lang, "check:You have entered the wrong password or code too many times, please wait for %d minutes and try again"), minutes)
|
||||||
}
|
}
|
||||||
|
|
||||||
// reset the error times
|
// reset the error times
|
||||||
@ -229,7 +229,7 @@ func checkLdapUserPassword(user *User, password string, lang string) (*User, str
|
|||||||
func CheckUserPassword(organization string, username string, password string, lang string) (*User, string) {
|
func CheckUserPassword(organization string, username string, password string, lang string) (*User, string) {
|
||||||
user := GetUserByFields(organization, username)
|
user := GetUserByFields(organization, username)
|
||||||
if user == nil || user.IsDeleted == true {
|
if user == nil || user.IsDeleted == true {
|
||||||
return nil, i18n.Translate(lang, "check:The user doesn't exist")
|
return nil, fmt.Sprintf(i18n.Translate(lang, "general:The user: %s doesn't exist"), util.GetId(organization, username))
|
||||||
}
|
}
|
||||||
|
|
||||||
if user.IsForbidden {
|
if user.IsForbidden {
|
||||||
@ -254,13 +254,13 @@ func filterField(field string) bool {
|
|||||||
|
|
||||||
func CheckUserPermission(requestUserId, userId, userOwner string, strict bool, lang string) (bool, error) {
|
func CheckUserPermission(requestUserId, userId, userOwner string, strict bool, lang string) (bool, error) {
|
||||||
if requestUserId == "" {
|
if requestUserId == "" {
|
||||||
return false, fmt.Errorf(i18n.Translate(lang, "check:Please login first"))
|
return false, fmt.Errorf(i18n.Translate(lang, "general:Please login first"))
|
||||||
}
|
}
|
||||||
|
|
||||||
if userId != "" {
|
if userId != "" {
|
||||||
targetUser := GetUser(userId)
|
targetUser := GetUser(userId)
|
||||||
if targetUser == nil {
|
if targetUser == nil {
|
||||||
return false, fmt.Errorf(i18n.Translate(lang, "check:The user: %s doesn't exist"), userId)
|
return false, fmt.Errorf(i18n.Translate(lang, "general:The user: %s doesn't exist"), userId)
|
||||||
}
|
}
|
||||||
|
|
||||||
userOwner = targetUser.Owner
|
userOwner = targetUser.Owner
|
||||||
@ -287,7 +287,7 @@ func CheckUserPermission(requestUserId, userId, userOwner string, strict bool, l
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return hasPermission, fmt.Errorf(i18n.Translate(lang, "check:You don't have the permission to do this"))
|
return hasPermission, fmt.Errorf(i18n.Translate(lang, "auth:Unauthorized operation"))
|
||||||
}
|
}
|
||||||
|
|
||||||
func CheckAccessPermission(userId string, application *Application) (bool, error) {
|
func CheckAccessPermission(userId string, application *Application) (bool, error) {
|
||||||
@ -313,8 +313,9 @@ func CheckAccessPermission(userId string, application *Application) (bool, error
|
|||||||
return true, err
|
return true, err
|
||||||
}
|
}
|
||||||
enforcer := getEnforcer(permission)
|
enforcer := getEnforcer(permission)
|
||||||
allowed, err = enforcer.Enforce(userId, application.Name, "read")
|
if allowed, err = enforcer.Enforce(userId, application.Name, "read"); allowed {
|
||||||
break
|
return allowed, err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return allowed, err
|
return allowed, err
|
||||||
|
@ -58,9 +58,9 @@ func recordSigninErrorInfo(user *User, lang string) string {
|
|||||||
UpdateUser(user.GetId(), user, []string{"signin_wrong_times", "last_signin_wrong_time"}, user.IsGlobalAdmin)
|
UpdateUser(user.GetId(), user, []string{"signin_wrong_times", "last_signin_wrong_time"}, user.IsGlobalAdmin)
|
||||||
leftChances := SigninWrongTimesLimit - user.SigninWrongTimes
|
leftChances := SigninWrongTimesLimit - user.SigninWrongTimes
|
||||||
if leftChances > 0 {
|
if leftChances > 0 {
|
||||||
return fmt.Sprintf(i18n.Translate(lang, "check_util:password is incorrect, you have %d remaining chances"), leftChances)
|
return fmt.Sprintf(i18n.Translate(lang, "check:password or code is incorrect, you have %d remaining chances"), leftChances)
|
||||||
}
|
}
|
||||||
|
|
||||||
// don't show the chance error message if the user has no chance left
|
// don't show the chance error message if the user has no chance left
|
||||||
return fmt.Sprintf(i18n.Translate(lang, "check_util:You have entered the wrong password too many times, please wait for %d minutes and try again"), int(LastSignWrongTimeDuration.Minutes()))
|
return fmt.Sprintf(i18n.Translate(lang, "check:You have entered the wrong password or code too many times, please wait for %d minutes and try again"), int(LastSignWrongTimeDuration.Minutes()))
|
||||||
}
|
}
|
||||||
|
@ -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"},
|
||||||
|
@ -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)
|
||||||
|
}
|
||||||
|
@ -76,7 +76,7 @@ func GetOidcDiscovery(host string) OidcDiscovery {
|
|||||||
JwksUri: fmt.Sprintf("%s/.well-known/jwks", originBackend),
|
JwksUri: fmt.Sprintf("%s/.well-known/jwks", originBackend),
|
||||||
IntrospectionEndpoint: fmt.Sprintf("%s/api/login/oauth/introspect", originBackend),
|
IntrospectionEndpoint: fmt.Sprintf("%s/api/login/oauth/introspect", originBackend),
|
||||||
ResponseTypesSupported: []string{"code", "token", "id_token", "code token", "code id_token", "token id_token", "code token id_token", "none"},
|
ResponseTypesSupported: []string{"code", "token", "id_token", "code token", "code id_token", "token id_token", "code token id_token", "none"},
|
||||||
ResponseModesSupported: []string{"login", "code", "link"},
|
ResponseModesSupported: []string{"query", "fragment", "login", "code", "link"},
|
||||||
GrantTypesSupported: []string{"password", "authorization_code"},
|
GrantTypesSupported: []string{"password", "authorization_code"},
|
||||||
SubjectTypesSupported: []string{"public"},
|
SubjectTypesSupported: []string{"public"},
|
||||||
IdTokenSigningAlgValuesSupported: []string{"RS256"},
|
IdTokenSigningAlgValuesSupported: []string{"RS256"},
|
||||||
|
@ -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"`
|
||||||
|
|
||||||
@ -203,7 +204,7 @@ func GetAccountItemByName(name string, organization *Organization) *AccountItem
|
|||||||
func CheckAccountItemModifyRule(accountItem *AccountItem, user *User, lang string) (bool, string) {
|
func CheckAccountItemModifyRule(accountItem *AccountItem, user *User, lang string) (bool, string) {
|
||||||
switch accountItem.ModifyRule {
|
switch accountItem.ModifyRule {
|
||||||
case "Admin":
|
case "Admin":
|
||||||
if !(user.IsAdmin || user.IsGlobalAdmin) {
|
if user == nil || !user.IsAdmin && !user.IsGlobalAdmin {
|
||||||
return false, fmt.Sprintf(i18n.Translate(lang, "organization:Only admin can modify the %s."), accountItem.Name)
|
return false, fmt.Sprintf(i18n.Translate(lang, "organization:Only admin can modify the %s."), accountItem.Name)
|
||||||
}
|
}
|
||||||
case "Immutable":
|
case "Immutable":
|
||||||
|
@ -269,3 +269,12 @@ func ContainsAsterisk(userId string, users []string) bool {
|
|||||||
|
|
||||||
return containsAsterisk
|
return containsAsterisk
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GetMaskedPermissions(permissions []*Permission) []*Permission {
|
||||||
|
for _, permission := range permissions {
|
||||||
|
permission.Users = nil
|
||||||
|
permission.Submitter = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
return permissions
|
||||||
|
}
|
||||||
|
@ -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 = _, _
|
||||||
|
@ -29,6 +29,7 @@ type Product struct {
|
|||||||
|
|
||||||
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"`
|
||||||
|
Description string `xorm:"varchar(100)" json:"description"`
|
||||||
Tag string `xorm:"varchar(100)" json:"tag"`
|
Tag string `xorm:"varchar(100)" json:"tag"`
|
||||||
Currency string `xorm:"varchar(100)" json:"currency"`
|
Currency string `xorm:"varchar(100)" json:"currency"`
|
||||||
Price float64 `json:"price"`
|
Price float64 `json:"price"`
|
||||||
@ -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)
|
||||||
|
@ -192,3 +192,11 @@ func roleChangeTrigger(oldName string, newName string) error {
|
|||||||
|
|
||||||
return session.Commit()
|
return session.Commit()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GetMaskedRoles(roles []*Role) []*Role {
|
||||||
|
for _, role := range roles {
|
||||||
|
role.Users = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return roles
|
||||||
|
}
|
||||||
|
@ -223,11 +223,14 @@ func GetSamlMeta(application *Application, host string) (*IdpEntityDescriptor, e
|
|||||||
|
|
||||||
// GetSamlResponse generates a SAML2.0 response
|
// GetSamlResponse generates a SAML2.0 response
|
||||||
// parameter samlRequest is saml request in base64 format
|
// parameter samlRequest is saml request in base64 format
|
||||||
func GetSamlResponse(application *Application, user *User, samlRequest string, host string) (string, string, error) {
|
func GetSamlResponse(application *Application, user *User, samlRequest string, host string) (string, string, string, error) {
|
||||||
|
// request type
|
||||||
|
method := "GET"
|
||||||
|
|
||||||
// base64 decode
|
// base64 decode
|
||||||
defated, err := base64.StdEncoding.DecodeString(samlRequest)
|
defated, err := base64.StdEncoding.DecodeString(samlRequest)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", "", fmt.Errorf("err: %s", err.Error())
|
return "", "", method, fmt.Errorf("err: %s", err.Error())
|
||||||
}
|
}
|
||||||
// decompress
|
// decompress
|
||||||
var buffer bytes.Buffer
|
var buffer bytes.Buffer
|
||||||
@ -236,12 +239,12 @@ func GetSamlResponse(application *Application, user *User, samlRequest string, h
|
|||||||
var authnRequest saml.AuthnRequest
|
var authnRequest saml.AuthnRequest
|
||||||
err = xml.Unmarshal(buffer.Bytes(), &authnRequest)
|
err = xml.Unmarshal(buffer.Bytes(), &authnRequest)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", "", fmt.Errorf("err: %s", err.Error())
|
return "", "", method, fmt.Errorf("err: %s", err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
// verify samlRequest
|
// verify samlRequest
|
||||||
if valid := CheckRedirectUriValid(application, authnRequest.Issuer.Url); !valid {
|
if isValid := application.IsRedirectUriValid(authnRequest.Issuer.Url); !isValid {
|
||||||
return "", "", fmt.Errorf("err: invalid issuer url")
|
return "", "", method, fmt.Errorf("err: Issuer URI: %s doesn't exist in the allowed Redirect URI list", authnRequest.Issuer.Url)
|
||||||
}
|
}
|
||||||
|
|
||||||
// get certificate string
|
// get certificate string
|
||||||
@ -251,6 +254,12 @@ func GetSamlResponse(application *Application, user *User, samlRequest string, h
|
|||||||
|
|
||||||
_, originBackend := getOriginFromHost(host)
|
_, originBackend := getOriginFromHost(host)
|
||||||
|
|
||||||
|
// redirect Url (Assertion Consumer Url)
|
||||||
|
if application.SamlReplyUrl != "" {
|
||||||
|
method = "POST"
|
||||||
|
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{
|
||||||
@ -270,7 +279,7 @@ func GetSamlResponse(application *Application, user *User, samlRequest string, h
|
|||||||
doc.SetRoot(samlResponse)
|
doc.SetRoot(samlResponse)
|
||||||
xmlBytes, err := doc.WriteToBytes()
|
xmlBytes, err := doc.WriteToBytes()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", "", fmt.Errorf("err: %s", err.Error())
|
return "", "", method, fmt.Errorf("err: %s", err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
// compress
|
// compress
|
||||||
@ -278,7 +287,7 @@ func GetSamlResponse(application *Application, user *User, samlRequest string, h
|
|||||||
flated := bytes.NewBuffer(nil)
|
flated := bytes.NewBuffer(nil)
|
||||||
writer, err := flate.NewWriter(flated, flate.DefaultCompression)
|
writer, err := flate.NewWriter(flated, flate.DefaultCompression)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", "", fmt.Errorf("err: %s", err.Error())
|
return "", "", method, fmt.Errorf("err: %s", err.Error())
|
||||||
}
|
}
|
||||||
writer.Write(xmlBytes)
|
writer.Write(xmlBytes)
|
||||||
writer.Close()
|
writer.Close()
|
||||||
@ -286,7 +295,7 @@ func GetSamlResponse(application *Application, user *User, samlRequest string, h
|
|||||||
}
|
}
|
||||||
// base64 encode
|
// base64 encode
|
||||||
res := base64.StdEncoding.EncodeToString(xmlBytes)
|
res := base64.StdEncoding.EncodeToString(xmlBytes)
|
||||||
return res, authnRequest.AssertionConsumerServiceURL, nil
|
return res, authnRequest.AssertionConsumerServiceURL, method, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewSamlResponse11 return a saml1.1 response(not 2.0)
|
// NewSamlResponse11 return a saml1.1 response(not 2.0)
|
||||||
|
132
object/session.go
Normal file
132
object/session.go
Normal file
@ -0,0 +1,132 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
package object
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/beego/beego"
|
||||||
|
"github.com/casdoor/casdoor/util"
|
||||||
|
"xorm.io/core"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Session struct {
|
||||||
|
Owner string `xorm:"varchar(100) notnull pk" json:"owner"`
|
||||||
|
Name string `xorm:"varchar(100) notnull pk" json:"name"`
|
||||||
|
CreatedTime string `xorm:"varchar(100)" json:"createdTime"`
|
||||||
|
|
||||||
|
SessionId []string `json:"sessionId"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func SetSession(id string, sessionId string) {
|
||||||
|
owner, name := util.GetOwnerAndNameFromIdNoCheck(id)
|
||||||
|
session := &Session{Owner: owner, Name: name}
|
||||||
|
get, err := adapter.Engine.Get(session)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
session.SessionId = append(session.SessionId, sessionId)
|
||||||
|
if get {
|
||||||
|
_, err = adapter.Engine.ID(core.PK{owner, name}).Update(session)
|
||||||
|
} else {
|
||||||
|
session.CreatedTime = time.Now().Format(time.RFC3339)
|
||||||
|
_, err = adapter.Engine.Insert(session)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func DeleteSession(id string) bool {
|
||||||
|
owner, name := util.GetOwnerAndNameFromIdNoCheck(id)
|
||||||
|
|
||||||
|
session := &Session{Owner: owner, Name: name}
|
||||||
|
_, err := adapter.Engine.ID(core.PK{owner, name}).Get(session)
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
DeleteBeegoSession(session.SessionId)
|
||||||
|
|
||||||
|
affected, err := adapter.Engine.ID(core.PK{owner, name}).Delete(session)
|
||||||
|
return affected != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func DeleteSessionId(id string, sessionId string) bool {
|
||||||
|
owner, name := util.GetOwnerAndNameFromIdNoCheck(id)
|
||||||
|
|
||||||
|
session := &Session{Owner: owner, Name: name}
|
||||||
|
_, err := adapter.Engine.ID(core.PK{owner, name}).Get(session)
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
DeleteBeegoSession([]string{sessionId})
|
||||||
|
session.SessionId = util.DeleteVal(session.SessionId, sessionId)
|
||||||
|
|
||||||
|
if len(session.SessionId) < 1 {
|
||||||
|
affected, _ := adapter.Engine.ID(core.PK{owner, name}).Delete(session)
|
||||||
|
return affected != 0
|
||||||
|
} else {
|
||||||
|
affected, _ := adapter.Engine.ID(core.PK{owner, name}).Update(session)
|
||||||
|
return affected != 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func DeleteBeegoSession(sessionIds []string) {
|
||||||
|
for _, sessionId := range sessionIds {
|
||||||
|
err := beego.GlobalSessions.GetProvider().SessionDestroy(sessionId)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetSessions(owner string) []*Session {
|
||||||
|
sessions := []*Session{}
|
||||||
|
var err error
|
||||||
|
if owner != "" {
|
||||||
|
err = adapter.Engine.Desc("created_time").Where("owner = ?", owner).Find(&sessions)
|
||||||
|
} else {
|
||||||
|
err = adapter.Engine.Desc("created_time").Find(&sessions)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return sessions
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetPaginationSessions(owner string, offset, limit int, field, value, sortField, sortOrder string) []*Session {
|
||||||
|
sessions := []*Session{}
|
||||||
|
session := GetSession(owner, offset, limit, field, value, sortField, sortOrder)
|
||||||
|
err := session.Find(&sessions)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return sessions
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetSessionCount(owner, field, value string) int {
|
||||||
|
session := GetSession(owner, -1, -1, field, value, "", "")
|
||||||
|
count, err := session.Count(&Session{})
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return int(count)
|
||||||
|
}
|
@ -18,7 +18,6 @@ import (
|
|||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/casdoor/casdoor/i18n"
|
"github.com/casdoor/casdoor/i18n"
|
||||||
@ -169,6 +168,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 {
|
||||||
@ -249,14 +252,7 @@ func CheckOAuthLogin(clientId string, responseType string, redirectUri string, s
|
|||||||
return i18n.Translate(lang, "token:Invalid client_id"), nil
|
return i18n.Translate(lang, "token:Invalid client_id"), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
validUri := false
|
if !application.IsRedirectUriValid(redirectUri) {
|
||||||
for _, tmpUri := range application.RedirectUris {
|
|
||||||
if strings.Contains(redirectUri, tmpUri) {
|
|
||||||
validUri = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !validUri {
|
|
||||||
return fmt.Sprintf(i18n.Translate(lang, "token:Redirect URI: %s doesn't exist in the allowed Redirect URI list"), redirectUri), application
|
return fmt.Sprintf(i18n.Translate(lang, "token:Redirect URI: %s doesn't exist in the allowed Redirect URI list"), redirectUri), application
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -269,7 +265,7 @@ func GetOAuthCode(userId string, clientId string, responseType string, redirectU
|
|||||||
user := GetUser(userId)
|
user := GetUser(userId)
|
||||||
if user == nil {
|
if user == nil {
|
||||||
return &Code{
|
return &Code{
|
||||||
Message: fmt.Sprintf("token:The user: %s doesn't exist", userId),
|
Message: fmt.Sprintf("general:The user: %s doesn't exist", userId),
|
||||||
Code: "",
|
Code: "",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -102,6 +102,7 @@ type User struct {
|
|||||||
Bilibili string `xorm:"bilibili varchar(100)" json:"bilibili"`
|
Bilibili string `xorm:"bilibili varchar(100)" json:"bilibili"`
|
||||||
Okta string `xorm:"okta varchar(100)" json:"okta"`
|
Okta string `xorm:"okta varchar(100)" json:"okta"`
|
||||||
Douyin string `xorm:"douyin varchar(100)" json:"douyin"`
|
Douyin string `xorm:"douyin varchar(100)" json:"douyin"`
|
||||||
|
Line string `xorm:"line varchar(100)" json:"line"`
|
||||||
Custom string `xorm:"custom varchar(100)" json:"custom"`
|
Custom string `xorm:"custom varchar(100)" json:"custom"`
|
||||||
|
|
||||||
WebauthnCredentials []webauthn.Credential `xorm:"webauthnCredentials blob" json:"webauthnCredentials"`
|
WebauthnCredentials []webauthn.Credential `xorm:"webauthnCredentials blob" json:"webauthnCredentials"`
|
||||||
@ -528,6 +529,9 @@ func AddUsersInBatch(users []*User) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func DeleteUser(user *User) bool {
|
func DeleteUser(user *User) bool {
|
||||||
|
// Forced offline the user first
|
||||||
|
DeleteSession(user.GetId())
|
||||||
|
|
||||||
affected, err := adapter.Engine.ID(core.PK{user.Owner, user.Name}).Delete(&User{})
|
affected, err := adapter.Engine.ID(core.PK{user.Owner, user.Name}).Delete(&User{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
|
@ -26,6 +26,10 @@ import (
|
|||||||
"xorm.io/core"
|
"xorm.io/core"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
wrongCode = "wrongCode"
|
||||||
|
)
|
||||||
|
|
||||||
type VerificationRecord struct {
|
type VerificationRecord struct {
|
||||||
Owner string `xorm:"varchar(100) notnull pk" json:"owner"`
|
Owner string `xorm:"varchar(100) notnull pk" json:"owner"`
|
||||||
Name string `xorm:"varchar(100) notnull pk" json:"name"`
|
Name string `xorm:"varchar(100) notnull pk" json:"name"`
|
||||||
@ -167,7 +171,7 @@ func CheckVerificationCode(dest, code, lang string) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if record.Code != code {
|
if record.Code != code {
|
||||||
return "Wrong code!"
|
return wrongCode
|
||||||
}
|
}
|
||||||
|
|
||||||
return ""
|
return ""
|
||||||
@ -186,6 +190,24 @@ func DisableVerificationCode(dest string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func CheckSigninCode(user *User, dest, code, lang string) string {
|
||||||
|
// check the login error times
|
||||||
|
if msg := checkSigninErrorTimes(user, lang); msg != "" {
|
||||||
|
return msg
|
||||||
|
}
|
||||||
|
|
||||||
|
result := CheckVerificationCode(dest, code, lang)
|
||||||
|
switch result {
|
||||||
|
case "":
|
||||||
|
resetUserSigninErrorTimes(user)
|
||||||
|
return ""
|
||||||
|
case wrongCode:
|
||||||
|
return recordSigninErrorInfo(user, lang)
|
||||||
|
default:
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// From Casnode/object/validateCode.go line 116
|
// From Casnode/object/validateCode.go line 116
|
||||||
var stdNums = []byte("0123456789")
|
var stdNums = []byte("0123456789")
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@ func CorsFilter(ctx *context.Context) {
|
|||||||
originConf := conf.GetConfigString("origin")
|
originConf := conf.GetConfigString("origin")
|
||||||
|
|
||||||
if origin != "" && originConf != "" && origin != originConf {
|
if origin != "" && originConf != "" && origin != originConf {
|
||||||
if object.IsAllowOrigin(origin) {
|
if object.IsOriginAllowed(origin) {
|
||||||
ctx.Output.Header(headerAllowOrigin, origin)
|
ctx.Output.Header(headerAllowOrigin, origin)
|
||||||
ctx.Output.Header(headerAllowMethods, "POST, GET, OPTIONS")
|
ctx.Output.Header(headerAllowMethods, "POST, GET, OPTIONS")
|
||||||
ctx.Output.Header(headerAllowHeaders, "Content-Type, Authorization")
|
ctx.Output.Header(headerAllowHeaders, "Content-Type, Authorization")
|
||||||
|
@ -164,6 +164,9 @@ func initAPI() {
|
|||||||
beego.Router("/api/get-records-filter", &controllers.ApiController{}, "POST:GetRecordsByFilter")
|
beego.Router("/api/get-records-filter", &controllers.ApiController{}, "POST:GetRecordsByFilter")
|
||||||
beego.Router("/api/add-record", &controllers.ApiController{}, "POST:AddRecord")
|
beego.Router("/api/add-record", &controllers.ApiController{}, "POST:AddRecord")
|
||||||
|
|
||||||
|
beego.Router("/api/get-sessions", &controllers.ApiController{}, "GET:GetSessions")
|
||||||
|
beego.Router("/api/delete-session", &controllers.ApiController{}, "POST:DeleteSession")
|
||||||
|
|
||||||
beego.Router("/api/get-webhooks", &controllers.ApiController{}, "GET:GetWebhooks")
|
beego.Router("/api/get-webhooks", &controllers.ApiController{}, "GET:GetWebhooks")
|
||||||
beego.Router("/api/get-webhook", &controllers.ApiController{}, "GET:GetWebhook")
|
beego.Router("/api/get-webhook", &controllers.ApiController{}, "GET:GetWebhook")
|
||||||
beego.Router("/api/update-webhook", &controllers.ApiController{}, "POST:UpdateWebhook")
|
beego.Router("/api/update-webhook", &controllers.ApiController{}, "POST:UpdateWebhook")
|
||||||
|
25
util/slice.go
Normal file
25
util/slice.go
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
package util
|
||||||
|
|
||||||
|
func DeleteVal(values []string, val string) []string {
|
||||||
|
newValues := []string{}
|
||||||
|
for _, v := range values {
|
||||||
|
if v != val {
|
||||||
|
newValues = append(newValues, v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return newValues
|
||||||
|
}
|
7
web/cypress.config.js
Normal file
7
web/cypress.config.js
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
module.exports = {
|
||||||
|
e2e: {
|
||||||
|
setupNodeEvents(on, config) {
|
||||||
|
// implement node event listeners here
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
56
web/cypress/e2e/login.cy.js
Normal file
56
web/cypress/e2e/login.cy.js
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
describe("Login test", () => {
|
||||||
|
const selector = {
|
||||||
|
username: "#input",
|
||||||
|
password: "#normal_login_password",
|
||||||
|
loginButton: ".ant-btn",
|
||||||
|
};
|
||||||
|
it("Login succeeded", () => {
|
||||||
|
cy.request({
|
||||||
|
method: "POST",
|
||||||
|
url: "http://localhost:7001/api/login",
|
||||||
|
body: {
|
||||||
|
"application": "app-built-in",
|
||||||
|
"organization": "built-in",
|
||||||
|
"username": "admin",
|
||||||
|
"password": "123",
|
||||||
|
"autoSignin": true,
|
||||||
|
"type": "login",
|
||||||
|
"phonePrefix": "86",
|
||||||
|
},
|
||||||
|
}).then((Response) => {
|
||||||
|
expect(Response).property("body").property("status").to.equal("ok");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it("ui Login succeeded", () => {
|
||||||
|
cy.visit("http://localhost:7001");
|
||||||
|
cy.get(selector.username).type("admin");
|
||||||
|
cy.get(selector.password).type("123");
|
||||||
|
cy.get(selector.loginButton).click();
|
||||||
|
cy.url().should("eq", "http://localhost:7001/");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Login failed", () => {
|
||||||
|
cy.request({
|
||||||
|
method: "POST",
|
||||||
|
url: "http://localhost:7001/api/login",
|
||||||
|
body: {
|
||||||
|
"application": "app-built-in",
|
||||||
|
"organization": "built-in",
|
||||||
|
"username": "admin",
|
||||||
|
"password": "1234",
|
||||||
|
"autoSignin": true,
|
||||||
|
"type": "login",
|
||||||
|
"phonePrefix": "86",
|
||||||
|
},
|
||||||
|
}).then((Response) => {
|
||||||
|
expect(Response).property("body").property("status").to.equal("error");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it("ui Login failed", () => {
|
||||||
|
cy.visit("http://localhost:7001");
|
||||||
|
cy.get(selector.username).type("admin");
|
||||||
|
cy.get(selector.password).type("1234");
|
||||||
|
cy.get(selector.loginButton).click();
|
||||||
|
cy.url().should("eq", "http://localhost:7001/login");
|
||||||
|
});
|
||||||
|
});
|
25
web/cypress/support/commands.js
Normal file
25
web/cypress/support/commands.js
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
// ***********************************************
|
||||||
|
// This example commands.js shows you how to
|
||||||
|
// create various custom commands and overwrite
|
||||||
|
// existing commands.
|
||||||
|
//
|
||||||
|
// For more comprehensive examples of custom
|
||||||
|
// commands please read more here:
|
||||||
|
// https://on.cypress.io/custom-commands
|
||||||
|
// ***********************************************
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// -- This is a parent command --
|
||||||
|
// Cypress.Commands.add('login', (email, password) => { ... })
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// -- This is a child command --
|
||||||
|
// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... })
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// -- This is a dual command --
|
||||||
|
// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... })
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// -- This will overwrite an existing command --
|
||||||
|
// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... })
|
20
web/cypress/support/e2e.js
Normal file
20
web/cypress/support/e2e.js
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
// ***********************************************************
|
||||||
|
// This example support/e2e.js is processed and
|
||||||
|
// loaded automatically before your test files.
|
||||||
|
//
|
||||||
|
// This is a great place to put global configuration and
|
||||||
|
// behavior that modifies Cypress.
|
||||||
|
//
|
||||||
|
// You can change the location of this file or turn off
|
||||||
|
// automatically serving support files with the
|
||||||
|
// 'supportFile' configuration option.
|
||||||
|
//
|
||||||
|
// You can read more here:
|
||||||
|
// https://on.cypress.io/configuration
|
||||||
|
// ***********************************************************
|
||||||
|
|
||||||
|
// Import commands.js using ES2015 syntax:
|
||||||
|
import './commands'
|
||||||
|
|
||||||
|
// Alternatively you can use CommonJS syntax:
|
||||||
|
// require('./commands')
|
@ -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.1.2",
|
||||||
"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",
|
||||||
|
@ -170,7 +170,7 @@ class AccountTable extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let options;
|
let options;
|
||||||
if (record.viewRule === "Admin") {
|
if (record.viewRule === "Admin" || record.name === "Is admin" || record.name === "Is global admin") {
|
||||||
options = [
|
options = [
|
||||||
{id: "Admin", name: "Admin"},
|
{id: "Admin", name: "Admin"},
|
||||||
{id: "Immutable", name: "Immutable"},
|
{id: "Immutable", name: "Immutable"},
|
||||||
|
@ -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) => {
|
||||||
|
if (res.status === "ok") {
|
||||||
this.setState({
|
this.setState({
|
||||||
adapter: adapter,
|
adapter: res.data,
|
||||||
});
|
});
|
||||||
|
|
||||||
this.getModels(adapter.owner);
|
this.getModels(this.state.owner);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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>
|
||||||
);
|
);
|
||||||
@ -260,6 +260,13 @@ class AdapterListPage extends BaseListPage {
|
|||||||
searchText: params.searchText,
|
searchText: params.searchText,
|
||||||
searchedColumn: params.searchedColumn,
|
searchedColumn: params.searchedColumn,
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
if (res.msg.includes("Unauthorized")) {
|
||||||
|
this.setState({
|
||||||
|
loading: false,
|
||||||
|
isAuthorized: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
115
web/src/App.js
115
web/src/App.js
@ -17,7 +17,7 @@ import "./App.less";
|
|||||||
import {Helmet} from "react-helmet";
|
import {Helmet} from "react-helmet";
|
||||||
import * as Setting from "./Setting";
|
import * as Setting from "./Setting";
|
||||||
import {BarsOutlined, DownOutlined, LogoutOutlined, SettingOutlined} from "@ant-design/icons";
|
import {BarsOutlined, DownOutlined, LogoutOutlined, SettingOutlined} from "@ant-design/icons";
|
||||||
import {Avatar, Button, Card, ConfigProvider, Drawer, Dropdown, FloatButton, Layout, Menu, Result} from "antd";
|
import {Avatar, Button, Card, ConfigProvider, Drawer, Dropdown, FloatButton, Layout, Menu, Result, theme} from "antd";
|
||||||
import {Link, Redirect, Route, Switch, withRouter} from "react-router-dom";
|
import {Link, Redirect, Route, Switch, withRouter} from "react-router-dom";
|
||||||
import OrganizationListPage from "./OrganizationListPage";
|
import OrganizationListPage from "./OrganizationListPage";
|
||||||
import OrganizationEditPage from "./OrganizationEditPage";
|
import OrganizationEditPage from "./OrganizationEditPage";
|
||||||
@ -55,26 +55,22 @@ import CustomGithubCorner from "./CustomGithubCorner";
|
|||||||
import * as Conf from "./Conf";
|
import * as Conf from "./Conf";
|
||||||
|
|
||||||
import * as Auth from "./auth/Auth";
|
import * as Auth from "./auth/Auth";
|
||||||
import SignupPage from "./auth/SignupPage";
|
import EntryPage from "./EntryPage";
|
||||||
import ResultPage from "./auth/ResultPage";
|
import ResultPage from "./auth/ResultPage";
|
||||||
import LoginPage from "./auth/LoginPage";
|
|
||||||
import SelfLoginPage from "./auth/SelfLoginPage";
|
|
||||||
import SelfForgetPage from "./auth/SelfForgetPage";
|
|
||||||
import ForgetPage from "./auth/ForgetPage";
|
|
||||||
import * as AuthBackend from "./auth/AuthBackend";
|
import * as AuthBackend from "./auth/AuthBackend";
|
||||||
import AuthCallback from "./auth/AuthCallback";
|
import AuthCallback from "./auth/AuthCallback";
|
||||||
import SelectLanguageBox from "./SelectLanguageBox";
|
import SelectLanguageBox from "./SelectLanguageBox";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
import PromptPage from "./auth/PromptPage";
|
|
||||||
import OdicDiscoveryPage from "./auth/OidcDiscoveryPage";
|
import OdicDiscoveryPage from "./auth/OidcDiscoveryPage";
|
||||||
import SamlCallback from "./auth/SamlCallback";
|
import SamlCallback from "./auth/SamlCallback";
|
||||||
import CasLogout from "./auth/CasLogout";
|
|
||||||
import ModelListPage from "./ModelListPage";
|
import ModelListPage from "./ModelListPage";
|
||||||
import ModelEditPage from "./ModelEditPage";
|
import ModelEditPage from "./ModelEditPage";
|
||||||
import SystemInfo from "./SystemInfo";
|
import SystemInfo from "./SystemInfo";
|
||||||
import AdapterListPage from "./AdapterListPage";
|
import AdapterListPage from "./AdapterListPage";
|
||||||
import AdapterEditPage from "./AdapterEditPage";
|
import AdapterEditPage from "./AdapterEditPage";
|
||||||
import {withTranslation} from "react-i18next";
|
import {withTranslation} from "react-i18next";
|
||||||
|
import SelectThemeBox from "./SelectThemeBox";
|
||||||
|
import SessionListPage from "./SessionListPage";
|
||||||
|
|
||||||
const {Header, Footer, Content} = Layout;
|
const {Header, Footer, Content} = Layout;
|
||||||
|
|
||||||
@ -87,6 +83,8 @@ class App extends Component {
|
|||||||
account: undefined,
|
account: undefined,
|
||||||
uri: null,
|
uri: null,
|
||||||
menuVisible: false,
|
menuVisible: false,
|
||||||
|
themeAlgorithm: null,
|
||||||
|
logo: null,
|
||||||
};
|
};
|
||||||
|
|
||||||
Setting.initServerUrl();
|
Setting.initServerUrl();
|
||||||
@ -101,6 +99,16 @@ class App extends Component {
|
|||||||
this.getAccount();
|
this.getAccount();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
localStorage.getItem("theme") ?
|
||||||
|
this.setState({"themeAlgorithm": this.getTheme()}) : this.setState({"themeAlgorithm": theme.defaultAlgorithm});
|
||||||
|
this.setState({"logo": Setting.getLogo(localStorage.getItem("theme"))});
|
||||||
|
addEventListener("themeChange", (e) => {
|
||||||
|
this.setState({"themeAlgorithm": this.getTheme()});
|
||||||
|
this.setState({"logo": Setting.getLogo(localStorage.getItem("theme"))});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
componentDidUpdate() {
|
componentDidUpdate() {
|
||||||
// eslint-disable-next-line no-restricted-globals
|
// eslint-disable-next-line no-restricted-globals
|
||||||
const uri = location.pathname;
|
const uri = location.pathname;
|
||||||
@ -190,6 +198,10 @@ class App extends Component {
|
|||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getTheme() {
|
||||||
|
return Setting.Themes.find(t => t.key === localStorage.getItem("theme"))["style"];
|
||||||
|
}
|
||||||
|
|
||||||
setLanguage(account) {
|
setLanguage(account) {
|
||||||
const language = account?.language;
|
const language = account?.language;
|
||||||
if (language !== "" && language !== i18next.language) {
|
if (language !== "" && language !== i18next.language) {
|
||||||
@ -224,7 +236,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 +261,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);
|
||||||
@ -410,6 +422,10 @@ class App extends Component {
|
|||||||
"/tokens"
|
"/tokens"
|
||||||
));
|
));
|
||||||
|
|
||||||
|
res.push(Setting.getItem(<Link to="/sessions">{i18next.t("general:Sessions")}</Link>,
|
||||||
|
"/sessions"
|
||||||
|
));
|
||||||
|
|
||||||
res.push(Setting.getItem(<Link to="/webhooks">{i18next.t("general:Webhooks")}</Link>,
|
res.push(Setting.getItem(<Link to="/webhooks">{i18next.t("general:Webhooks")}</Link>,
|
||||||
"/webhooks"
|
"/webhooks"
|
||||||
));
|
));
|
||||||
@ -471,6 +487,13 @@ class App extends Component {
|
|||||||
|
|
||||||
renderRouter() {
|
renderRouter() {
|
||||||
return (
|
return (
|
||||||
|
<ConfigProvider theme={{
|
||||||
|
token: {
|
||||||
|
colorPrimary: "rgb(89,54,213)",
|
||||||
|
colorInfo: "rgb(89,54,213)",
|
||||||
|
},
|
||||||
|
algorithm: this.state.themeAlgorithm,
|
||||||
|
}}>
|
||||||
<div>
|
<div>
|
||||||
<Switch>
|
<Switch>
|
||||||
<Route exact path="/result" render={(props) => this.renderHomeIfLoggedIn(<ResultPage {...props} />)} />
|
<Route exact path="/result" render={(props) => this.renderHomeIfLoggedIn(<ResultPage {...props} />)} />
|
||||||
@ -499,6 +522,7 @@ class App extends Component {
|
|||||||
<Route exact path="/ldap/:ldapId" render={(props) => this.renderLoginIfNotLoggedIn(<LdapEditPage account={this.state.account} {...props} />)} />
|
<Route exact path="/ldap/:ldapId" render={(props) => this.renderLoginIfNotLoggedIn(<LdapEditPage account={this.state.account} {...props} />)} />
|
||||||
<Route exact path="/ldap/sync/:ldapId" render={(props) => this.renderLoginIfNotLoggedIn(<LdapSyncPage account={this.state.account} {...props} />)} />
|
<Route exact path="/ldap/sync/:ldapId" render={(props) => this.renderLoginIfNotLoggedIn(<LdapSyncPage account={this.state.account} {...props} />)} />
|
||||||
<Route exact path="/tokens" render={(props) => this.renderLoginIfNotLoggedIn(<TokenListPage account={this.state.account} {...props} />)} />
|
<Route exact path="/tokens" render={(props) => this.renderLoginIfNotLoggedIn(<TokenListPage account={this.state.account} {...props} />)} />
|
||||||
|
<Route exact path="/sessions" render={(props) => this.renderLoginIfNotLoggedIn(<SessionListPage account={this.state.account} {...props} />)} />
|
||||||
<Route exact path="/tokens/:tokenName" render={(props) => this.renderLoginIfNotLoggedIn(<TokenEditPage account={this.state.account} {...props} />)} />
|
<Route exact path="/tokens/:tokenName" render={(props) => this.renderLoginIfNotLoggedIn(<TokenEditPage account={this.state.account} {...props} />)} />
|
||||||
<Route exact path="/webhooks" render={(props) => this.renderLoginIfNotLoggedIn(<WebhookListPage account={this.state.account} {...props} />)} />
|
<Route exact path="/webhooks" render={(props) => this.renderLoginIfNotLoggedIn(<WebhookListPage account={this.state.account} {...props} />)} />
|
||||||
<Route exact path="/webhooks/:webhookName" render={(props) => this.renderLoginIfNotLoggedIn(<WebhookEditPage account={this.state.account} {...props} />)} />
|
<Route exact path="/webhooks/:webhookName" render={(props) => this.renderLoginIfNotLoggedIn(<WebhookEditPage account={this.state.account} {...props} />)} />
|
||||||
@ -519,6 +543,7 @@ class App extends Component {
|
|||||||
extra={<a href="/"><Button type="primary">{i18next.t("general:Back Home")}</Button></a>} />} />
|
extra={<a href="/"><Button type="primary">{i18next.t("general:Back Home")}</Button></a>} />} />
|
||||||
</Switch>
|
</Switch>
|
||||||
</div>
|
</div>
|
||||||
|
</ConfigProvider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -538,30 +563,27 @@ class App extends Component {
|
|||||||
if (!Setting.isMobile()) {
|
if (!Setting.isMobile()) {
|
||||||
return (
|
return (
|
||||||
<Layout id="parent-area">
|
<Layout id="parent-area">
|
||||||
<Header style={{marginBottom: "3px", paddingInline: 0}}>
|
<Header style={{marginBottom: "3px", paddingInline: 0, backgroundColor: this.state.themeAlgorithm === theme.darkAlgorithm ? "black" : "white"}}>
|
||||||
{
|
{
|
||||||
Setting.isMobile() ? null : (
|
Setting.isMobile() ? null : (
|
||||||
<Link to={"/"}>
|
<Link to={"/"}>
|
||||||
<div className="logo" />
|
<div className="logo" style={{background: `url(${this.state.logo})`}} />
|
||||||
</Link>
|
</Link>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
<div>
|
|
||||||
<Menu
|
<Menu
|
||||||
// theme="dark"
|
|
||||||
items={this.renderMenu()}
|
items={this.renderMenu()}
|
||||||
mode={(Setting.isMobile() && this.isStartPages()) ? "inline" : "horizontal"}
|
mode={(Setting.isMobile() && this.isStartPages()) ? "inline" : "horizontal"}
|
||||||
selectedKeys={[`${this.state.selectedMenuKey}`]}
|
selectedKeys={[`${this.state.selectedMenuKey}`]}
|
||||||
style={{lineHeight: "64px", position: "absolute", left: "145px", right: "200px"}}
|
style={{position: "absolute", left: "145px", backgroundColor: this.state.themeAlgorithm === theme.darkAlgorithm ? "black" : "white"}}
|
||||||
>
|
/>
|
||||||
</Menu>
|
|
||||||
{
|
{
|
||||||
this.renderAccount()
|
this.renderAccount()
|
||||||
}
|
}
|
||||||
|
{this.state.account && <SelectThemeBox themes={this.state.account.organization.themes} />}
|
||||||
{this.state.account && <SelectLanguageBox languages={this.state.account.organization.languages} />}
|
{this.state.account && <SelectLanguageBox languages={this.state.account.organization.languages} />}
|
||||||
</div>
|
|
||||||
</Header>
|
</Header>
|
||||||
<Content style={{backgroundColor: "#f5f5f5", alignItems: "stretch", display: "flex", flexDirection: "column"}}>
|
<Content style={{alignItems: "stretch", display: "flex", flexDirection: "column"}}>
|
||||||
<Card className="content-warp-card">
|
<Card className="content-warp-card">
|
||||||
{
|
{
|
||||||
this.renderRouter()
|
this.renderRouter()
|
||||||
@ -576,11 +598,11 @@ class App extends Component {
|
|||||||
} else {
|
} else {
|
||||||
return (
|
return (
|
||||||
<Layout>
|
<Layout>
|
||||||
<Header style={{padding: "0", marginBottom: "3px"}}>
|
<Header style={{padding: "0", marginBottom: "3px", backgroundColor: this.state.themeAlgorithm === theme.darkAlgorithm ? "black" : "white"}}>
|
||||||
{
|
{
|
||||||
Setting.isMobile() ? null : (
|
Setting.isMobile() ? null : (
|
||||||
<Link to={"/"}>
|
<Link to={"/"}>
|
||||||
<div className="logo" />
|
<div className="logo" style={{background: `url(${this.state.logo})`}} />
|
||||||
</Link>
|
</Link>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -598,12 +620,11 @@ class App extends Component {
|
|||||||
<Button icon={<BarsOutlined />} onClick={this.showMenu} type="text">
|
<Button icon={<BarsOutlined />} onClick={this.showMenu} type="text">
|
||||||
{i18next.t("general:Menu")}
|
{i18next.t("general:Menu")}
|
||||||
</Button>
|
</Button>
|
||||||
<div style = {{float: "right"}}>
|
|
||||||
{
|
{
|
||||||
this.renderAccount()
|
this.renderAccount()
|
||||||
}
|
}
|
||||||
|
{this.state.account && <SelectThemeBox themes={this.state.account.organization.themes} />}
|
||||||
{this.state.account && <SelectLanguageBox languages={this.state.account.organization.languages} />}
|
{this.state.account && <SelectLanguageBox languages={this.state.account.organization.languages} />}
|
||||||
</div>
|
|
||||||
</Header>
|
</Header>
|
||||||
<Content style={{display: "flex", flexDirection: "column"}} >{
|
<Content style={{display: "flex", flexDirection: "column"}} >{
|
||||||
this.renderRouter()}
|
this.renderRouter()}
|
||||||
@ -619,74 +640,66 @@ class App extends Component {
|
|||||||
// https://www.freecodecamp.org/neyarnws/how-to-keep-your-footer-where-it-belongs-59c6aa05c59c/
|
// https://www.freecodecamp.org/neyarnws/how-to-keep-your-footer-where-it-belongs-59c6aa05c59c/
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<React.Fragment>
|
||||||
{!this.state.account ? null : <div style={{display: "none"}} id="CasdoorApplicationName" value={this.state.account.signupApplication} />}
|
{!this.state.account ? null : <div style={{display: "none"}} id="CasdoorApplicationName" value={this.state.account.signupApplication} />}
|
||||||
<Footer id="footer" style={
|
<Footer id="footer" style={
|
||||||
{
|
{
|
||||||
borderTop: "1px solid #e8e8e8",
|
|
||||||
backgroundColor: "white",
|
|
||||||
textAlign: "center",
|
textAlign: "center",
|
||||||
}
|
}
|
||||||
}>
|
}>
|
||||||
Powered by <a target="_blank" href="https://casdoor.org" rel="noreferrer"><img style={{paddingBottom: "3px"}} height={"20px"} alt={"Casdoor"} src={`${Setting.StaticBaseUrl}/img/casdoor-logo_1185x256.png`} /></a>
|
Powered by <a target="_blank" href="https://casdoor.org" rel="noreferrer"><img style={{paddingBottom: "3px"}} height={"20px"} alt={"Casdoor"} src={this.state.logo} /></a>
|
||||||
</Footer>
|
</Footer>
|
||||||
</>
|
</React.Fragment>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
isDoorPages() {
|
isDoorPages() {
|
||||||
|
return this.isEntryPages() || window.location.pathname.startsWith("/callback");
|
||||||
|
}
|
||||||
|
|
||||||
|
isEntryPages() {
|
||||||
return window.location.pathname.startsWith("/signup") ||
|
return window.location.pathname.startsWith("/signup") ||
|
||||||
window.location.pathname.startsWith("/login") ||
|
window.location.pathname.startsWith("/login") ||
|
||||||
window.location.pathname.startsWith("/callback") ||
|
|
||||||
window.location.pathname.startsWith("/prompt") ||
|
|
||||||
window.location.pathname.startsWith("/forget") ||
|
window.location.pathname.startsWith("/forget") ||
|
||||||
window.location.pathname.startsWith("/cas");
|
window.location.pathname.startsWith("/prompt") ||
|
||||||
|
window.location.pathname.startsWith("/cas") ||
|
||||||
|
window.location.pathname.startsWith("/auto-signup");
|
||||||
}
|
}
|
||||||
|
|
||||||
renderPage() {
|
renderPage() {
|
||||||
if (this.isDoorPages()) {
|
if (this.isDoorPages()) {
|
||||||
return (
|
return (
|
||||||
<>
|
<React.Fragment>
|
||||||
<Layout id="parent-area">
|
<Layout id="parent-area">
|
||||||
<Content style={{display: "flex", justifyContent: "center"}}>
|
<Content style={{display: "flex", justifyContent: "center"}}>
|
||||||
|
{
|
||||||
|
this.isEntryPages() ?
|
||||||
|
<EntryPage account={this.state.account} onUpdateAccount={(account) => {this.onUpdateAccount(account);}} />
|
||||||
|
:
|
||||||
<Switch>
|
<Switch>
|
||||||
<Route exact path="/signup" render={(props) => this.renderHomeIfLoggedIn(<SignupPage account={this.state.account} {...props} />)} />
|
|
||||||
<Route exact path="/signup/:applicationName" render={(props) => this.renderHomeIfLoggedIn(<SignupPage account={this.state.account} {...props} onUpdateAccount={(account) => {this.onUpdateAccount(account);}} />)} />
|
|
||||||
<Route exact path="/login" render={(props) => this.renderHomeIfLoggedIn(<SelfLoginPage account={this.state.account} {...props} />)} />
|
|
||||||
<Route exact path="/login/:owner" render={(props) => this.renderHomeIfLoggedIn(<SelfLoginPage account={this.state.account} {...props} />)} />
|
|
||||||
<Route exact path="/auto-signup/oauth/authorize" render={(props) => <LoginPage account={this.state.account} type={"code"} mode={"signup"} {...props} onUpdateAccount={(account) => {this.onUpdateAccount(account);}} />} />
|
|
||||||
<Route exact path="/signup/oauth/authorize" render={(props) => <SignupPage account={this.state.account} {...props} onUpdateAccount={(account) => {this.onUpdateAccount(account);}} />} />
|
|
||||||
<Route exact path="/login/oauth/authorize" render={(props) => <LoginPage account={this.state.account} type={"code"} mode={"signin"} {...props} onUpdateAccount={(account) => {this.onUpdateAccount(account);}} />} />
|
|
||||||
<Route exact path="/login/saml/authorize/:owner/:applicationName" render={(props) => <LoginPage account={this.state.account} type={"saml"} mode={"signin"} {...props} onUpdateAccount={(account) => {this.onUpdateAccount(account);}} />} />
|
|
||||||
<Route exact path="/cas/:owner/:casApplicationName/logout" render={(props) => this.renderHomeIfLoggedIn(<CasLogout clearAccount={() => this.setState({account: null})} {...props} />)} />
|
|
||||||
<Route exact path="/cas/:owner/:casApplicationName/login" render={(props) => {return (<LoginPage type={"cas"} mode={"signup"} account={this.state.account} {...props} />);}} />
|
|
||||||
<Route exact path="/callback" component={AuthCallback} />
|
<Route exact path="/callback" component={AuthCallback} />
|
||||||
<Route exact path="/callback/saml" component={SamlCallback} />
|
<Route exact path="/callback/saml" component={SamlCallback} />
|
||||||
<Route exact path="/forget" render={(props) => this.renderHomeIfLoggedIn(<SelfForgetPage {...props} />)} />
|
|
||||||
<Route exact path="/forget/:applicationName" render={(props) => this.renderHomeIfLoggedIn(<ForgetPage {...props} />)} />
|
|
||||||
<Route exact path="/prompt" render={(props) => this.renderLoginIfNotLoggedIn(<PromptPage account={this.state.account} {...props} />)} />
|
|
||||||
<Route exact path="/prompt/:applicationName" render={(props) => this.renderLoginIfNotLoggedIn(<PromptPage account={this.state.account} onUpdateAccount={(account) => {this.onUpdateAccount(account);}} {...props} />)} />
|
|
||||||
<Route exact path="/sysinfo" render={(props) => this.renderLoginIfNotLoggedIn(<SystemInfo {...props} />)} />
|
|
||||||
<Route path="" render={() => <Result status="404" title="404 NOT FOUND" subTitle={i18next.t("general:Sorry, the page you visited does not exist.")}
|
<Route path="" render={() => <Result status="404" title="404 NOT FOUND" subTitle={i18next.t("general:Sorry, the page you visited does not exist.")}
|
||||||
extra={<a href="/"><Button type="primary">{i18next.t("general:Back Home")}</Button></a>} />} />
|
extra={<a href="/"><Button type="primary">{i18next.t("general:Back Home")}</Button></a>} />} />
|
||||||
</Switch>
|
</Switch>
|
||||||
|
}
|
||||||
</Content>
|
</Content>
|
||||||
{
|
{
|
||||||
this.renderFooter()
|
this.renderFooter()
|
||||||
}
|
}
|
||||||
</Layout>
|
</Layout>
|
||||||
</>
|
</React.Fragment>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<React.Fragment>
|
||||||
<FloatButton.BackTop />
|
<FloatButton.BackTop />
|
||||||
<CustomGithubCorner />
|
<CustomGithubCorner />
|
||||||
{
|
{
|
||||||
this.renderContent()
|
this.renderContent()
|
||||||
}
|
}
|
||||||
</>
|
</React.Fragment>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -702,6 +715,7 @@ class App extends Component {
|
|||||||
colorPrimary: "rgb(89,54,213)",
|
colorPrimary: "rgb(89,54,213)",
|
||||||
colorInfo: "rgb(89,54,213)",
|
colorInfo: "rgb(89,54,213)",
|
||||||
},
|
},
|
||||||
|
algorithm: this.state.themeAlgorithm,
|
||||||
}}>
|
}}>
|
||||||
{
|
{
|
||||||
this.renderPage()
|
this.renderPage()
|
||||||
@ -723,6 +737,7 @@ class App extends Component {
|
|||||||
colorPrimary: "rgb(89,54,213)",
|
colorPrimary: "rgb(89,54,213)",
|
||||||
colorInfo: "rgb(89,54,213)",
|
colorInfo: "rgb(89,54,213)",
|
||||||
},
|
},
|
||||||
|
algorithm: this.state.themeAlgorithm,
|
||||||
}}>
|
}}>
|
||||||
{
|
{
|
||||||
this.renderPage()
|
this.renderPage()
|
||||||
|
@ -13,14 +13,12 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.App-header {
|
.App-header {
|
||||||
background-color: #282c34;
|
|
||||||
min-height: 100vh;
|
min-height: 100vh;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
font-size: calc(10px + 2vmin);
|
font-size: calc(10px + 2vmin);
|
||||||
color: white;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.App-link {
|
.App-link {
|
||||||
@ -41,7 +39,6 @@ img {
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
min-height: 100vh;
|
min-height: 100vh;
|
||||||
background-color: #f5f5f5;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.panel-logo {
|
.panel-logo {
|
||||||
@ -55,7 +52,7 @@ img {
|
|||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
width: 45px;
|
width: 45px;
|
||||||
height: 65px;
|
height: 100%;
|
||||||
float: right;
|
float: right;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
||||||
@ -64,9 +61,32 @@ img {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.login-form .language-box {
|
||||||
|
height: 65px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.theme-box {
|
||||||
|
background: url("@{StaticBaseUrl}/img/muti_language.svg");
|
||||||
|
background-size: 25px, 25px;
|
||||||
|
background-position: center !important;
|
||||||
|
background-repeat: no-repeat !important;
|
||||||
|
border-radius: 5px;
|
||||||
|
width: 45px;
|
||||||
|
height: 100%;
|
||||||
|
float: right;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: #f5f5f5 !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.rightDropDown {
|
.rightDropDown {
|
||||||
|
border-radius: 7px;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background-color: #f5f5f5;
|
background-color: #f5f5f5;
|
||||||
|
color: black;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -128,3 +148,9 @@ img {
|
|||||||
background-size: 100% 100%;
|
background-size: 100% 100%;
|
||||||
background-attachment: fixed;
|
background-attachment: fixed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ant-menu-horizontal {
|
||||||
|
border-bottom: none !important;
|
||||||
|
margin-right: 30px;
|
||||||
|
right: 230px;
|
||||||
|
}
|
||||||
|
@ -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, Popover, Radio, Row, Select, Switch, Upload} from "antd";
|
import {Button, Card, Col, Input, Popover, Radio, Result, Row, Select, Switch, Upload} from "antd";
|
||||||
import {CopyOutlined, LinkOutlined, UploadOutlined} from "@ant-design/icons";
|
import {CopyOutlined, LinkOutlined, UploadOutlined} from "@ant-design/icons";
|
||||||
import * as ApplicationBackend from "./backend/ApplicationBackend";
|
import * as ApplicationBackend from "./backend/ApplicationBackend";
|
||||||
import * as CertBackend from "./backend/CertBackend";
|
import * as CertBackend from "./backend/CertBackend";
|
||||||
@ -103,6 +103,7 @@ class ApplicationEditPage extends React.Component {
|
|||||||
uploading: false,
|
uploading: false,
|
||||||
mode: props.location.mode !== undefined ? props.location.mode : "edit",
|
mode: props.location.mode !== undefined ? props.location.mode : "edit",
|
||||||
samlMetadata: null,
|
samlMetadata: null,
|
||||||
|
isAuthorized: true,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -129,9 +130,15 @@ class ApplicationEditPage extends React.Component {
|
|||||||
getOrganizations() {
|
getOrganizations() {
|
||||||
OrganizationBackend.getOrganizations("admin")
|
OrganizationBackend.getOrganizations("admin")
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
|
if (res?.status === "error") {
|
||||||
|
this.setState({
|
||||||
|
isAuthorized: false,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
this.setState({
|
this.setState({
|
||||||
organizations: (res.msg === undefined) ? res : [],
|
organizations: (res.msg === undefined) ? res : [],
|
||||||
});
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -545,6 +552,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"))} :
|
||||||
@ -716,7 +733,7 @@ class ApplicationEditPage extends React.Component {
|
|||||||
renderSignupSigninPreview() {
|
renderSignupSigninPreview() {
|
||||||
let signUpUrl = `/signup/${this.state.application.name}`;
|
let signUpUrl = `/signup/${this.state.application.name}`;
|
||||||
const signInUrl = `/login/oauth/authorize?client_id=${this.state.application.clientId}&response_type=code&redirect_uri=${this.state.application.redirectUris[0]}&scope=read&state=casdoor`;
|
const signInUrl = `/login/oauth/authorize?client_id=${this.state.application.clientId}&response_type=code&redirect_uri=${this.state.application.redirectUris[0]}&scope=read&state=casdoor`;
|
||||||
const maskStyle = {position: "absolute", top: "0px", left: "0px", zIndex: 10, height: "100%", width: "100%", background: "rgba(0,0,0,0.4)"};
|
const maskStyle = {position: "absolute", top: "0px", left: "0px", zIndex: 10, height: "97%", width: "100%", background: "rgba(0,0,0,0.4)"};
|
||||||
if (!this.state.application.enablePassword) {
|
if (!this.state.application.enablePassword) {
|
||||||
signUpUrl = signInUrl.replace("/login/oauth/authorize", "/signup/oauth/authorize");
|
signUpUrl = signInUrl.replace("/login/oauth/authorize", "/signup/oauth/authorize");
|
||||||
}
|
}
|
||||||
@ -732,15 +749,19 @@ class ApplicationEditPage extends React.Component {
|
|||||||
{i18next.t("application:Copy signup page URL")}
|
{i18next.t("application:Copy signup page URL")}
|
||||||
</Button>
|
</Button>
|
||||||
<br />
|
<br />
|
||||||
<div style={{position: "relative", width: previewWidth, border: "1px solid rgb(217,217,217)", boxShadow: "10px 10px 5px #888888", alignItems: "center", overflow: "auto", flexDirection: "column", flex: "auto"}}>
|
<div style={{position: "relative", width: previewWidth, border: "1px solid rgb(217,217,217)", boxShadow: "10px 10px 5px #888888", overflow: "auto"}}>
|
||||||
{
|
{
|
||||||
this.state.application.enablePassword ? (
|
this.state.application.enablePassword ? (
|
||||||
<SignupPage application={this.state.application} />
|
<div className="loginBackground" style={{backgroundImage: `url(${this.state.application?.formBackgroundUrl})`, overflow: "auto"}}>
|
||||||
|
<SignupPage application={this.state.application} preview = "auto" />
|
||||||
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<LoginPage type={"login"} mode={"signup"} application={this.state.application} />
|
<div className="loginBackground" style={{backgroundImage: `url(${this.state.application?.formBackgroundUrl})`, overflow: "auto"}}>
|
||||||
|
<LoginPage type={"login"} mode={"signup"} application={this.state.application} preview = "auto" />
|
||||||
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
<div style={maskStyle} />
|
<div style={{overflow: "auto", ...maskStyle}} />
|
||||||
</div>
|
</div>
|
||||||
</Col>
|
</Col>
|
||||||
<Col span={previewGrid}>
|
<Col span={previewGrid}>
|
||||||
@ -752,9 +773,11 @@ class ApplicationEditPage extends React.Component {
|
|||||||
{i18next.t("application:Copy signin page URL")}
|
{i18next.t("application:Copy signin page URL")}
|
||||||
</Button>
|
</Button>
|
||||||
<br />
|
<br />
|
||||||
<div style={{position: "relative", width: previewWidth, border: "1px solid rgb(217,217,217)", boxShadow: "10px 10px 5px #888888", alignItems: "center", overflow: "auto", flexDirection: "column", flex: "auto"}}>
|
<div style={{position: "relative", width: previewWidth, border: "1px solid rgb(217,217,217)", boxShadow: "10px 10px 5px #888888", overflow: "auto"}}>
|
||||||
<LoginPage type={"login"} mode={"signin"} application={this.state.application} />
|
<div className="loginBackground" style={{backgroundImage: `url(${this.state.application?.formBackgroundUrl})`, overflow: "auto"}}>
|
||||||
<div style={maskStyle} />
|
<LoginPage type={"login"} mode={"signin"} application={this.state.application} preview = "auto" />
|
||||||
|
</div>
|
||||||
|
<div style={{overflow: "auto", ...maskStyle}} />
|
||||||
</div>
|
</div>
|
||||||
</Col>
|
</Col>
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
@ -822,6 +845,17 @@ class ApplicationEditPage extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
if (!this.state.isAuthorized) {
|
||||||
|
return (
|
||||||
|
<Result
|
||||||
|
status="403"
|
||||||
|
title="403 Unauthorized"
|
||||||
|
subTitle={i18next.t("general:Sorry, you do not have permission to access this page or logged in status invalid.")}
|
||||||
|
extra={<a href="/"><Button type="primary">{i18next.t("general:Back Home")}</Button></a>}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
{
|
{
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import {Link} from "react-router-dom";
|
import {Link} from "react-router-dom";
|
||||||
import {Button, Col, List, Popconfirm, Row, Table, Tooltip} from "antd";
|
import {Button, Col, List, Popconfirm, Result, Row, Table, Tooltip} from "antd";
|
||||||
import {EditOutlined} from "@ant-design/icons";
|
import {EditOutlined} from "@ant-design/icons";
|
||||||
import moment from "moment";
|
import moment from "moment";
|
||||||
import * as Setting from "./Setting";
|
import * as Setting from "./Setting";
|
||||||
@ -36,6 +36,7 @@ class ApplicationListPage extends BaseListPage {
|
|||||||
loading: false,
|
loading: false,
|
||||||
searchText: "",
|
searchText: "",
|
||||||
searchedColumn: "",
|
searchedColumn: "",
|
||||||
|
isAuthorized: true,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -197,9 +198,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>
|
||||||
@ -258,6 +259,17 @@ class ApplicationListPage extends BaseListPage {
|
|||||||
showTotal: () => i18next.t("general:{total} in total").replace("{total}", this.state.pagination.total),
|
showTotal: () => i18next.t("general:{total} in total").replace("{total}", this.state.pagination.total),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (!this.state.isAuthorized) {
|
||||||
|
return (
|
||||||
|
<Result
|
||||||
|
status="403"
|
||||||
|
title="403 Unauthorized"
|
||||||
|
subTitle={i18next.t("general:Sorry, you do not have permission to access this page or logged in status invalid.")}
|
||||||
|
extra={<a href="/"><Button type="primary">{i18next.t("general:Back Home")}</Button></a>}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Table scroll={{x: "max-content"}} columns={columns} dataSource={applications} rowKey="name" size="middle" bordered pagination={paginationProps}
|
<Table scroll={{x: "max-content"}} columns={columns} dataSource={applications} rowKey="name" size="middle" bordered pagination={paginationProps}
|
||||||
@ -292,6 +304,13 @@ class ApplicationListPage extends BaseListPage {
|
|||||||
searchText: params.searchText,
|
searchText: params.searchText,
|
||||||
searchedColumn: params.searchedColumn,
|
searchedColumn: params.searchedColumn,
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
if (res.msg.includes("Unauthorized")) {
|
||||||
|
this.setState({
|
||||||
|
loading: false,
|
||||||
|
isAuthorized: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -13,9 +13,10 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import {Button, Input, Space} from "antd";
|
import {Button, Input, Result, Space} from "antd";
|
||||||
import {SearchOutlined} from "@ant-design/icons";
|
import {SearchOutlined} from "@ant-design/icons";
|
||||||
import Highlighter from "react-highlight-words";
|
import Highlighter from "react-highlight-words";
|
||||||
|
import i18next from "i18next";
|
||||||
|
|
||||||
class BaseListPage extends React.Component {
|
class BaseListPage extends React.Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
@ -127,6 +128,17 @@ class BaseListPage extends React.Component {
|
|||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
if (!this.state.isAuthorized) {
|
||||||
|
return (
|
||||||
|
<Result
|
||||||
|
status="403"
|
||||||
|
title="403 Unauthorized"
|
||||||
|
subTitle={i18next.t("general:Sorry, you do not have permission to access this page or logged in status invalid.")}
|
||||||
|
extra={<a href="/"><Button type="primary">{i18next.t("general:Back Home")}</Button></a>}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
{
|
{
|
||||||
|
@ -227,6 +227,13 @@ class CertListPage extends BaseListPage {
|
|||||||
searchText: params.searchText,
|
searchText: params.searchText,
|
||||||
searchedColumn: params.searchedColumn,
|
searchedColumn: params.searchedColumn,
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
if (res.msg.includes("Unauthorized")) {
|
||||||
|
this.setState({
|
||||||
|
loading: false,
|
||||||
|
isAuthorized: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
84
web/src/EntryPage.js
Normal file
84
web/src/EntryPage.js
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
// 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 from "react";
|
||||||
|
import {Redirect, Route, Switch} from "react-router-dom";
|
||||||
|
import {Spin} from "antd";
|
||||||
|
import i18next from "i18next";
|
||||||
|
import * as Setting from "./Setting";
|
||||||
|
import SignupPage from "./auth/SignupPage";
|
||||||
|
import SelfLoginPage from "./auth/SelfLoginPage";
|
||||||
|
import LoginPage from "./auth/LoginPage";
|
||||||
|
import SelfForgetPage from "./auth/SelfForgetPage";
|
||||||
|
import ForgetPage from "./auth/ForgetPage";
|
||||||
|
import PromptPage from "./auth/PromptPage";
|
||||||
|
import CasLogout from "./auth/CasLogout";
|
||||||
|
|
||||||
|
class EntryPage extends React.Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.state = {
|
||||||
|
application: undefined,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
renderHomeIfLoggedIn(component) {
|
||||||
|
if (this.props.account !== null && this.props.account !== undefined) {
|
||||||
|
return <Redirect to="/" />;
|
||||||
|
} else {
|
||||||
|
return component;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
renderLoginIfNotLoggedIn(component) {
|
||||||
|
if (this.props.account === null) {
|
||||||
|
sessionStorage.setItem("from", window.location.pathname);
|
||||||
|
return <Redirect to="/login" />;
|
||||||
|
} else if (this.props.account === undefined) {
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
return component;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const onUpdateApplication = (application) => {
|
||||||
|
this.setState({
|
||||||
|
application: application,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return <div className="loginBackground" style={{backgroundImage: Setting.inIframe() || Setting.isMobile() ? null : `url(${this.state.application?.formBackgroundUrl})`}}>
|
||||||
|
<Spin spinning={this.state.application === undefined} tip={i18next.t("login:Loading")} style={{margin: "0 auto"}} />
|
||||||
|
<Switch>
|
||||||
|
<Route exact path="/signup" render={(props) => this.renderHomeIfLoggedIn(<SignupPage {...this.props} application={this.state.application} onUpdateApplication={onUpdateApplication} {...props} />)} />
|
||||||
|
<Route exact path="/signup/:applicationName" render={(props) => this.renderHomeIfLoggedIn(<SignupPage {...this.props} application={this.state.application} onUpdateApplication={onUpdateApplication} {...props} />)} />
|
||||||
|
<Route exact path="/login" render={(props) => this.renderHomeIfLoggedIn(<SelfLoginPage {...this.props} application={this.state.application} onUpdateApplication={onUpdateApplication} {...props} />)} />
|
||||||
|
<Route exact path="/login/:owner" render={(props) => this.renderHomeIfLoggedIn(<SelfLoginPage {...this.props} application={this.state.application} onUpdateApplication={onUpdateApplication} {...props} />)} />
|
||||||
|
<Route exact path="/auto-signup/oauth/authorize" render={(props) => <LoginPage {...this.props} application={this.state.application} type={"code"} mode={"signup"} onUpdateApplication={onUpdateApplication}{...props} />} />
|
||||||
|
<Route exact path="/signup/oauth/authorize" render={(props) => <SignupPage {...this.props} application={this.state.application} onUpdateApplication={onUpdateApplication} {...props} />} />
|
||||||
|
<Route exact path="/login/oauth/authorize" render={(props) => <LoginPage {...this.props} application={this.state.application} type={"code"} mode={"signin"} onUpdateApplication={onUpdateApplication} {...props} />} />
|
||||||
|
<Route exact path="/login/saml/authorize/:owner/:applicationName" render={(props) => <LoginPage {...this.props} application={this.state.application} type={"saml"} mode={"signin"} onUpdateApplication={onUpdateApplication} {...props} />} />
|
||||||
|
<Route exact path="/forget" render={(props) => this.renderHomeIfLoggedIn(<SelfForgetPage {...this.props} application={this.state.application} onUpdateApplication={onUpdateApplication} {...props} />)} />
|
||||||
|
<Route exact path="/forget/:applicationName" render={(props) => this.renderHomeIfLoggedIn(<ForgetPage {...this.props} application={this.state.application} onUpdateApplication={onUpdateApplication} {...props} />)} />
|
||||||
|
<Route exact path="/prompt" render={(props) => this.renderLoginIfNotLoggedIn(<PromptPage {...this.props} application={this.state.application} onUpdateApplication={onUpdateApplication} {...props} />)} />
|
||||||
|
<Route exact path="/prompt/:applicationName" render={(props) => this.renderLoginIfNotLoggedIn(<PromptPage {...this.props} application={this.state.application} onUpdateApplication={onUpdateApplication} {...props} />)} />
|
||||||
|
<Route exact path="/cas/:owner/:casApplicationName/logout" render={(props) => this.renderHomeIfLoggedIn(<CasLogout {...this.props} application={this.state.application} {...props} />)} />
|
||||||
|
<Route exact path="/cas/:owner/:casApplicationName/login" render={(props) => {return (<LoginPage {...this.props} application={this.state.application} type={"cas"} mode={"signup"} {...props} />);}} />
|
||||||
|
</Switch>
|
||||||
|
</div>;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default EntryPage;
|
@ -200,6 +200,13 @@ class ModelListPage extends BaseListPage {
|
|||||||
searchText: params.searchText,
|
searchText: params.searchText,
|
||||||
searchedColumn: params.searchedColumn,
|
searchedColumn: params.searchedColumn,
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
if (res.msg.includes("Unauthorized")) {
|
||||||
|
this.setState({
|
||||||
|
loading: false,
|
||||||
|
isAuthorized: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -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"))} :
|
||||||
|
@ -251,7 +251,7 @@ class OrganizationListPage extends BaseListPage {
|
|||||||
<Result
|
<Result
|
||||||
status="403"
|
status="403"
|
||||||
title="403 Unauthorized"
|
title="403 Unauthorized"
|
||||||
subTitle={i18next.t("general:Sorry, you do not have permission to access this page.")}
|
subTitle={i18next.t("general:Sorry, you do not have permission to access this page or logged in status invalid.")}
|
||||||
extra={<a href="/"><Button type="primary">{i18next.t("general:Back Home")}</Button></a>}
|
extra={<a href="/"><Button type="primary">{i18next.t("general:Back Home")}</Button></a>}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
@ -278,6 +278,13 @@ class PaymentListPage extends BaseListPage {
|
|||||||
searchText: params.searchText,
|
searchText: params.searchText,
|
||||||
searchedColumn: params.searchedColumn,
|
searchedColumn: params.searchedColumn,
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
if (res.msg.includes("Unauthorized")) {
|
||||||
|
this.setState({
|
||||||
|
loading: false,
|
||||||
|
isAuthorized: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -358,6 +358,13 @@ class PermissionListPage extends BaseListPage {
|
|||||||
searchText: params.searchText,
|
searchText: params.searchText,
|
||||||
searchedColumn: params.searchedColumn,
|
searchedColumn: params.searchedColumn,
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
if (res.msg.includes("Unauthorized")) {
|
||||||
|
this.setState({
|
||||||
|
loading: false,
|
||||||
|
isAuthorized: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -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")
|
||||||
|
}
|
||||||
|
:
|
||||||
|
{
|
||||||
|
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>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -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"))} :
|
||||||
|
@ -295,6 +295,13 @@ class ProductListPage extends BaseListPage {
|
|||||||
searchText: params.searchText,
|
searchText: params.searchText,
|
||||||
searchedColumn: params.searchedColumn,
|
searchedColumn: params.searchedColumn,
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
if (res.msg.includes("Unauthorized")) {
|
||||||
|
this.setState({
|
||||||
|
loading: false,
|
||||||
|
isAuthorized: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import {Link} from "react-router-dom";
|
import {Link} from "react-router-dom";
|
||||||
import {Button, Popconfirm, Table} from "antd";
|
import {Button, Popconfirm, Result, Table} from "antd";
|
||||||
import moment from "moment";
|
import moment from "moment";
|
||||||
import * as Setting from "./Setting";
|
import * as Setting from "./Setting";
|
||||||
import * as ProviderBackend from "./backend/ProviderBackend";
|
import * as ProviderBackend from "./backend/ProviderBackend";
|
||||||
@ -36,6 +36,7 @@ class ProviderListPage extends BaseListPage {
|
|||||||
loading: false,
|
loading: false,
|
||||||
searchText: "",
|
searchText: "",
|
||||||
searchedColumn: "",
|
searchedColumn: "",
|
||||||
|
isAuthorized: true,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
newProvider() {
|
newProvider() {
|
||||||
@ -227,6 +228,17 @@ class ProviderListPage extends BaseListPage {
|
|||||||
showTotal: () => i18next.t("general:{total} in total").replace("{total}", this.state.pagination.total),
|
showTotal: () => i18next.t("general:{total} in total").replace("{total}", this.state.pagination.total),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (!this.state.isAuthorized) {
|
||||||
|
return (
|
||||||
|
<Result
|
||||||
|
status="403"
|
||||||
|
title="403 Unauthorized"
|
||||||
|
subTitle={i18next.t("general:Sorry, you do not have permission to access this page or logged in status invalid.")}
|
||||||
|
extra={<a href="/"><Button type="primary">{i18next.t("general:Back Home")}</Button></a>}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Table scroll={{x: "max-content"}} columns={columns} dataSource={providers} rowKey="name" size="middle" bordered pagination={paginationProps}
|
<Table scroll={{x: "max-content"}} columns={columns} dataSource={providers} rowKey="name" size="middle" bordered pagination={paginationProps}
|
||||||
@ -268,6 +280,13 @@ class ProviderListPage extends BaseListPage {
|
|||||||
searchText: params.searchText,
|
searchText: params.searchText,
|
||||||
searchedColumn: params.searchedColumn,
|
searchedColumn: params.searchedColumn,
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
if (res.msg.includes("Unauthorized")) {
|
||||||
|
this.setState({
|
||||||
|
loading: false,
|
||||||
|
isAuthorized: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -222,6 +222,13 @@ class RecordListPage extends BaseListPage {
|
|||||||
searchText: params.searchText,
|
searchText: params.searchText,
|
||||||
searchedColumn: params.searchedColumn,
|
searchedColumn: params.searchedColumn,
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
if (res.data.includes("Please login first")) {
|
||||||
|
this.setState({
|
||||||
|
loading: false,
|
||||||
|
isAuthorized: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -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}
|
||||||
/>
|
/>
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import {Button, Popconfirm, Table, Upload} from "antd";
|
import {Button, Popconfirm, Result, Table, Upload} from "antd";
|
||||||
import {UploadOutlined} from "@ant-design/icons";
|
import {UploadOutlined} from "@ant-design/icons";
|
||||||
import copy from "copy-to-clipboard";
|
import copy from "copy-to-clipboard";
|
||||||
import * as Setting from "./Setting";
|
import * as Setting from "./Setting";
|
||||||
@ -37,6 +37,7 @@ class ResourceListPage extends BaseListPage {
|
|||||||
searchedColumn: "",
|
searchedColumn: "",
|
||||||
fileList: [],
|
fileList: [],
|
||||||
uploading: false,
|
uploading: false,
|
||||||
|
isAuthorized: true,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -113,7 +114,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>
|
||||||
);
|
);
|
||||||
@ -272,6 +273,17 @@ class ResourceListPage extends BaseListPage {
|
|||||||
showTotal: () => i18next.t("general:{total} in total").replace("{total}", this.state.pagination.total),
|
showTotal: () => i18next.t("general:{total} in total").replace("{total}", this.state.pagination.total),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (!this.state.isAuthorized) {
|
||||||
|
return (
|
||||||
|
<Result
|
||||||
|
status="403"
|
||||||
|
title="403 Unauthorized"
|
||||||
|
subTitle={i18next.t("general:Sorry, you do not have permission to access this page or logged in status invalid.")}
|
||||||
|
extra={<a href="/"><Button type="primary">{i18next.t("general:Back Home")}</Button></a>}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Table scroll={{x: "max-content"}} columns={columns} dataSource={resources} rowKey="name" size="middle" bordered pagination={paginationProps}
|
<Table scroll={{x: "max-content"}} columns={columns} dataSource={resources} rowKey="name" size="middle" bordered pagination={paginationProps}
|
||||||
@ -308,6 +320,13 @@ class ResourceListPage extends BaseListPage {
|
|||||||
searchText: params.searchText,
|
searchText: params.searchText,
|
||||||
searchedColumn: params.searchedColumn,
|
searchedColumn: params.searchedColumn,
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
if (res.data.includes("Please login first")) {
|
||||||
|
this.setState({
|
||||||
|
loading: false,
|
||||||
|
isAuthorized: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -231,6 +231,13 @@ class RoleListPage extends BaseListPage {
|
|||||||
searchText: params.searchText,
|
searchText: params.searchText,
|
||||||
searchedColumn: params.searchedColumn,
|
searchedColumn: params.searchedColumn,
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
if (res.msg.includes("Unauthorized")) {
|
||||||
|
this.setState({
|
||||||
|
loading: false,
|
||||||
|
isAuthorized: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -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>
|
||||||
);
|
);
|
||||||
|
@ -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>
|
||||||
|
81
web/src/SelectThemeBox.js
Normal file
81
web/src/SelectThemeBox.js
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
// Copyright 2021 The Casdoor Authors. All Rights Reserved.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
import React from "react";
|
||||||
|
import * as Setting from "./Setting";
|
||||||
|
import {Dropdown} from "antd";
|
||||||
|
import "./App.less";
|
||||||
|
import i18next from "i18next";
|
||||||
|
|
||||||
|
function themeIcon(themeKey) {
|
||||||
|
return <img width={24} alt={themeKey} src={getLogoURL(themeKey)} />;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getLogoURL(themeKey) {
|
||||||
|
if (themeKey) {
|
||||||
|
return Setting.Themes.find(t => t.key === themeKey)["selectThemeLogo"];
|
||||||
|
} else {
|
||||||
|
return Setting.Themes.find(t => t.key === localStorage.getItem("theme"))["selectThemeLogo"];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class SelectThemeBox extends React.Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.state = {
|
||||||
|
classes: props,
|
||||||
|
themes: props.theme ?? ["Default", "Dark", "Compact"],
|
||||||
|
icon: null,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
items = this.getThemes();
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
i18next.on("languageChanged", () => {
|
||||||
|
this.items = this.getThemes();
|
||||||
|
});
|
||||||
|
localStorage.getItem("theme") ? this.setState({"icon": getLogoURL()}) : this.setState({"icon": getLogoURL("Default")});
|
||||||
|
addEventListener("themeChange", (e) => {
|
||||||
|
this.setState({"icon": getLogoURL()});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
getThemes() {
|
||||||
|
return Setting.Themes.map((theme) => Setting.getItem(i18next.t(`general:${theme.label}`), theme.key, themeIcon(theme.key)));
|
||||||
|
}
|
||||||
|
|
||||||
|
getOrganizationThemes(themes) {
|
||||||
|
const select = [];
|
||||||
|
for (const theme of themes) {
|
||||||
|
this.items.map((item, index) => item.key === theme ? select.push(item) : null);
|
||||||
|
}
|
||||||
|
return select;
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const themeItems = this.getOrganizationThemes(this.state.themes);
|
||||||
|
const onClick = (e) => {
|
||||||
|
Setting.setTheme(e.key);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Dropdown menu={{items: themeItems, onClick}} >
|
||||||
|
<div className="theme-box" style={{display: themeItems.length === 0 ? "none" : null, background: `url(${this.state.icon})`, ...this.props.style}} />
|
||||||
|
</Dropdown>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default SelectThemeBox;
|
162
web/src/SessionListPage.js
Normal file
162
web/src/SessionListPage.js
Normal file
@ -0,0 +1,162 @@
|
|||||||
|
// 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 BaseListPage from "./BaseListPage";
|
||||||
|
import * as Setting from "./Setting";
|
||||||
|
import i18next from "i18next";
|
||||||
|
import {Link} from "react-router-dom";
|
||||||
|
import {Button, Popconfirm, Table, Tag} from "antd";
|
||||||
|
import React from "react";
|
||||||
|
import * as SessionBackend from "./backend/SessionBackend";
|
||||||
|
|
||||||
|
class SessionListPage extends BaseListPage {
|
||||||
|
|
||||||
|
deleteSession(i) {
|
||||||
|
SessionBackend.deleteSession(this.state.data[i])
|
||||||
|
.then((res) => {
|
||||||
|
if (res.status === "ok") {
|
||||||
|
Setting.showMessage("success", i18next.t("general:Successfully deleted"));
|
||||||
|
this.setState({
|
||||||
|
data: Setting.deleteRow(this.state.data, i),
|
||||||
|
pagination: {total: this.state.pagination.total - 1},
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
Setting.showMessage("error", `${i18next.t("general:Failed to delete")}: ${res.msg}`);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
Setting.showMessage("error", `${i18next.t("general:Failed to connect to server")}: ${error}`);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
renderTable(sessions) {
|
||||||
|
const columns = [
|
||||||
|
{
|
||||||
|
title: i18next.t("general:Name"),
|
||||||
|
dataIndex: "name",
|
||||||
|
key: "name",
|
||||||
|
width: "150px",
|
||||||
|
fixed: "left",
|
||||||
|
sorter: true,
|
||||||
|
...this.getColumnSearchProps("name"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: i18next.t("general:Organization"),
|
||||||
|
dataIndex: "owner",
|
||||||
|
key: "organization",
|
||||||
|
width: "110px",
|
||||||
|
sorter: true,
|
||||||
|
...this.getColumnSearchProps("organization"),
|
||||||
|
render: (text, record, index) => {
|
||||||
|
return (
|
||||||
|
<Link to={`/organizations/${text}`}>
|
||||||
|
{text}
|
||||||
|
</Link>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: i18next.t("general:Created time"),
|
||||||
|
dataIndex: "createdTime",
|
||||||
|
key: "createdTime",
|
||||||
|
width: "180px",
|
||||||
|
sorter: true,
|
||||||
|
render: (text, record, index) => {
|
||||||
|
return Setting.getFormattedDate(text);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: i18next.t("general:Session ID"),
|
||||||
|
dataIndex: "sessionId",
|
||||||
|
key: "sessionId",
|
||||||
|
width: "180px",
|
||||||
|
sorter: true,
|
||||||
|
render: (text, record, index) => {
|
||||||
|
return text.map((item, index) =>
|
||||||
|
<Tag key={index}>{item}</Tag>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: i18next.t("general:Action"),
|
||||||
|
dataIndex: "",
|
||||||
|
key: "op",
|
||||||
|
width: "70px",
|
||||||
|
fixed: (Setting.isMobile()) ? "false" : "right",
|
||||||
|
render: (text, record, index) => {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<Popconfirm
|
||||||
|
title={`Sure to delete session: ${record.name} ?`}
|
||||||
|
onConfirm={() => this.deleteSession(index)}
|
||||||
|
>
|
||||||
|
<Button style={{marginBottom: "10px"}} type="primary" danger>{i18next.t("general:Delete")}</Button>
|
||||||
|
</Popconfirm>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const paginationProps = {
|
||||||
|
total: this.state.pagination.total,
|
||||||
|
showQuickJumper: true,
|
||||||
|
showSizeChanger: true,
|
||||||
|
showTotal: () => i18next.t("general:{total} in total").replace("{total}", this.state.pagination.total),
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<Table scroll={{x: "max-content"}} columns={columns} dataSource={sessions} rowKey="name" size="middle" bordered pagination={paginationProps}
|
||||||
|
loading={this.state.loading}
|
||||||
|
onChange={this.handleTableChange}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
fetch = (params = {}) => {
|
||||||
|
let field = params.searchedColumn, value = params.searchText;
|
||||||
|
const sortField = params.sortField, sortOrder = params.sortOrder;
|
||||||
|
if (params.contentType !== undefined && params.contentType !== null) {
|
||||||
|
field = "contentType";
|
||||||
|
value = params.contentType;
|
||||||
|
}
|
||||||
|
this.setState({loading: true});
|
||||||
|
SessionBackend.getSessions("", params.pagination.current, params.pagination.pageSize, field, value, sortField, sortOrder)
|
||||||
|
.then((res) => {
|
||||||
|
if (res.status === "ok") {
|
||||||
|
this.setState({
|
||||||
|
loading: false,
|
||||||
|
data: res.data,
|
||||||
|
pagination: {
|
||||||
|
...params.pagination,
|
||||||
|
total: res.data2,
|
||||||
|
},
|
||||||
|
searchText: params.searchText,
|
||||||
|
searchedColumn: params.searchedColumn,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
if (res.msg.includes("Unauthorized")) {
|
||||||
|
this.setState({
|
||||||
|
loading: false,
|
||||||
|
isAuthorized: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export default SessionListPage;
|
@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import {Link} from "react-router-dom";
|
import {Link} from "react-router-dom";
|
||||||
import {Tag, Tooltip, message} from "antd";
|
import {Tag, Tooltip, message, theme} from "antd";
|
||||||
import {QuestionCircleTwoTone} from "@ant-design/icons";
|
import {QuestionCircleTwoTone} from "@ant-design/icons";
|
||||||
import {isMobile as isMobileDevice} from "react-device-detect";
|
import {isMobile as isMobileDevice} from "react-device-detect";
|
||||||
import "./i18n";
|
import "./i18n";
|
||||||
@ -33,6 +33,23 @@ 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: "Русский"},
|
||||||
|
];
|
||||||
|
|
||||||
|
const {defaultAlgorithm, darkAlgorithm, compactAlgorithm} = theme;
|
||||||
|
|
||||||
|
export const Themes = [{label: i18next.t("general:Dark"), key: "Dark", style: darkAlgorithm, selectThemeLogo: `${StaticBaseUrl}/img/dark.svg`},
|
||||||
|
{label: i18next.t("general:Compact"), key: "Compact", style: compactAlgorithm, selectThemeLogo: `${StaticBaseUrl}/img/compact.svg`},
|
||||||
|
{label: i18next.t("general:Default"), key: "Default", style: defaultAlgorithm, selectThemeLogo: `${StaticBaseUrl}/img/light.svg`},
|
||||||
|
];
|
||||||
|
|
||||||
export const OtherProviderInfo = {
|
export const OtherProviderInfo = {
|
||||||
SMS: {
|
SMS: {
|
||||||
"Aliyun SMS": {
|
"Aliyun SMS": {
|
||||||
@ -251,8 +268,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 +281,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) {
|
||||||
@ -544,6 +569,14 @@ export function getAvatarColor(s) {
|
|||||||
return colorList[hash % 4];
|
return colorList[hash % 4];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getLogo(theme) {
|
||||||
|
if (theme === "Dark") {
|
||||||
|
return `${StaticBaseUrl}/img/casdoor-logo_1185x256_dark.png`;
|
||||||
|
} else {
|
||||||
|
return `${StaticBaseUrl}/img/casdoor-logo_1185x256.png`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export function getLanguageText(text) {
|
export function getLanguageText(text) {
|
||||||
if (!text.includes("|")) {
|
if (!text.includes("|")) {
|
||||||
return text;
|
return text;
|
||||||
@ -569,6 +602,11 @@ export function setLanguage(language) {
|
|||||||
i18next.changeLanguage(language);
|
i18next.changeLanguage(language);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function setTheme(themeKey) {
|
||||||
|
localStorage.setItem("theme", themeKey);
|
||||||
|
dispatchEvent(new Event("themeChange"));
|
||||||
|
}
|
||||||
|
|
||||||
export function getAcceptLanguage() {
|
export function getAcceptLanguage() {
|
||||||
if (i18next.language === null || i18next.language === "") {
|
if (i18next.language === null || i18next.language === "") {
|
||||||
return "en;q=0.9,en;q=0.8";
|
return "en;q=0.9,en;q=0.8";
|
||||||
@ -663,6 +701,7 @@ export function getProviderTypeOptions(category) {
|
|||||||
{id: "Bilibili", name: "Bilibili"},
|
{id: "Bilibili", name: "Bilibili"},
|
||||||
{id: "Okta", name: "Okta"},
|
{id: "Okta", name: "Okta"},
|
||||||
{id: "Douyin", name: "Douyin"},
|
{id: "Douyin", name: "Douyin"},
|
||||||
|
{id: "Line", name: "Line"},
|
||||||
{id: "Custom", name: "Custom"},
|
{id: "Custom", name: "Custom"},
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
@ -780,6 +819,9 @@ export function renderLoginLink(application, text) {
|
|||||||
|
|
||||||
export function redirectToLoginPage(application, history) {
|
export function redirectToLoginPage(application, history) {
|
||||||
const loginLink = getLoginLink(application);
|
const loginLink = getLoginLink(application);
|
||||||
|
if (loginLink.indexOf("http") === 0 || loginLink.indexOf("https") === 0) {
|
||||||
|
window.location.replace(loginLink);
|
||||||
|
}
|
||||||
history.push(loginLink);
|
history.push(loginLink);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -288,6 +288,13 @@ class SyncerListPage extends BaseListPage {
|
|||||||
searchText: params.searchText,
|
searchText: params.searchText,
|
||||||
searchedColumn: params.searchedColumn,
|
searchedColumn: params.searchedColumn,
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
if (res.msg.includes("Unauthorized")) {
|
||||||
|
this.setState({
|
||||||
|
loading: false,
|
||||||
|
isAuthorized: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -253,6 +253,13 @@ class TokenListPage extends BaseListPage {
|
|||||||
searchText: params.searchText,
|
searchText: params.searchText,
|
||||||
searchedColumn: params.searchedColumn,
|
searchedColumn: params.searchedColumn,
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
if (res.msg.includes("Unauthorized")) {
|
||||||
|
this.setState({
|
||||||
|
loading: false,
|
||||||
|
isAuthorized: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -28,11 +28,7 @@ import SamlWidget from "./common/SamlWidget";
|
|||||||
import SelectRegionBox from "./SelectRegionBox";
|
import SelectRegionBox from "./SelectRegionBox";
|
||||||
import WebAuthnCredentialTable from "./WebauthnCredentialTable";
|
import WebAuthnCredentialTable from "./WebauthnCredentialTable";
|
||||||
import ManagedAccountTable from "./ManagedAccountTable";
|
import ManagedAccountTable from "./ManagedAccountTable";
|
||||||
|
import PropertyTable from "./propertyTable";
|
||||||
import {Controlled as CodeMirror} from "react-codemirror2";
|
|
||||||
import "codemirror/lib/codemirror.css";
|
|
||||||
require("codemirror/theme/material-darker.css");
|
|
||||||
require("codemirror/mode/javascript/javascript");
|
|
||||||
|
|
||||||
const {Option} = Select;
|
const {Option} = Select;
|
||||||
|
|
||||||
@ -490,13 +486,10 @@ class UserEditPage extends React.Component {
|
|||||||
return (
|
return (
|
||||||
<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}>
|
||||||
{i18next.t("user:Properties")}:
|
{Setting.getLabel(i18next.t("user:Properties"), i18next.t("user:Properties - Tooltip"))} :
|
||||||
</Col>
|
</Col>
|
||||||
<Col span={22} >
|
<Col span={22} >
|
||||||
<CodeMirror
|
<PropertyTable properties={this.state.user.properties} onUpdateTable={(value) => {this.updateUserField("properties", value);}} />
|
||||||
value={JSON.stringify(this.state.user.properties, null, 4)}
|
|
||||||
options={{mode: "javascript", theme: "material-darker"}}
|
|
||||||
/>
|
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
);
|
);
|
||||||
@ -507,7 +500,7 @@ class UserEditPage extends React.Component {
|
|||||||
{Setting.getLabel(i18next.t("user:Is admin"), i18next.t("user:Is admin - Tooltip"))} :
|
{Setting.getLabel(i18next.t("user:Is admin"), i18next.t("user:Is admin - Tooltip"))} :
|
||||||
</Col>
|
</Col>
|
||||||
<Col span={(Setting.isMobile()) ? 22 : 2} >
|
<Col span={(Setting.isMobile()) ? 22 : 2} >
|
||||||
<Switch disabled={this.state.user.owner === "built-in"} checked={this.state.user.isAdmin} onChange={checked => {
|
<Switch disabled={disabled} checked={this.state.user.isAdmin} onChange={checked => {
|
||||||
this.updateUserField("isAdmin", checked);
|
this.updateUserField("isAdmin", checked);
|
||||||
}} />
|
}} />
|
||||||
</Col>
|
</Col>
|
||||||
@ -520,7 +513,7 @@ class UserEditPage extends React.Component {
|
|||||||
{Setting.getLabel(i18next.t("user:Is global admin"), i18next.t("user:Is global admin - Tooltip"))} :
|
{Setting.getLabel(i18next.t("user:Is global admin"), i18next.t("user:Is global admin - Tooltip"))} :
|
||||||
</Col>
|
</Col>
|
||||||
<Col span={(Setting.isMobile()) ? 22 : 2} >
|
<Col span={(Setting.isMobile()) ? 22 : 2} >
|
||||||
<Switch disabled={this.state.user.owner === "built-in"} checked={this.state.user.isGlobalAdmin} onChange={checked => {
|
<Switch disabled={disabled} checked={this.state.user.isGlobalAdmin} onChange={checked => {
|
||||||
this.updateUserField("isGlobalAdmin", checked);
|
this.updateUserField("isGlobalAdmin", checked);
|
||||||
}} />
|
}} />
|
||||||
</Col>
|
</Col>
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import {Link} from "react-router-dom";
|
import {Link} from "react-router-dom";
|
||||||
import {Button, Popconfirm, Switch, Table, Upload} from "antd";
|
import {Button, Popconfirm, Result, Switch, Table, Upload} from "antd";
|
||||||
import {UploadOutlined} from "@ant-design/icons";
|
import {UploadOutlined} from "@ant-design/icons";
|
||||||
import moment from "moment";
|
import moment from "moment";
|
||||||
import * as OrganizationBackend from "./backend/OrganizationBackend";
|
import * as OrganizationBackend from "./backend/OrganizationBackend";
|
||||||
@ -38,6 +38,7 @@ class UserListPage extends BaseListPage {
|
|||||||
loading: false,
|
loading: false,
|
||||||
searchText: "",
|
searchText: "",
|
||||||
searchedColumn: "",
|
searchedColumn: "",
|
||||||
|
isAuthorized: true,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,6 +63,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",
|
||||||
@ -368,6 +370,17 @@ class UserListPage extends BaseListPage {
|
|||||||
showTotal: () => i18next.t("general:{total} in total").replace("{total}", this.state.pagination.total),
|
showTotal: () => i18next.t("general:{total} in total").replace("{total}", this.state.pagination.total),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (!this.state.isAuthorized) {
|
||||||
|
return (
|
||||||
|
<Result
|
||||||
|
status="403"
|
||||||
|
title="403 Unauthorized"
|
||||||
|
subTitle={i18next.t("general:Sorry, you do not have permission to access this page or logged in status invalid.")}
|
||||||
|
extra={<a href="/"><Button type="primary">{i18next.t("general:Back Home")}</Button></a>}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Table scroll={{x: "max-content"}} columns={columns} dataSource={users} rowKey={(record) => `${record.owner}/${record.name}`} size="middle" bordered pagination={paginationProps}
|
<Table scroll={{x: "max-content"}} columns={columns} dataSource={users} rowKey={(record) => `${record.owner}/${record.name}`} size="middle" bordered pagination={paginationProps}
|
||||||
@ -410,6 +423,13 @@ class UserListPage extends BaseListPage {
|
|||||||
if (users.length > 0) {
|
if (users.length > 0) {
|
||||||
this.getOrganization(users[0].owner);
|
this.getOrganization(users[0].owner);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
if (res.msg.includes("Unauthorized")) {
|
||||||
|
this.setState({
|
||||||
|
loading: false,
|
||||||
|
isAuthorized: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
@ -431,6 +451,13 @@ class UserListPage extends BaseListPage {
|
|||||||
if (users.length > 0) {
|
if (users.length > 0) {
|
||||||
this.getOrganization(users[0].owner);
|
this.getOrganization(users[0].owner);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
if (res.msg.includes("Unauthorized")) {
|
||||||
|
this.setState({
|
||||||
|
loading: false,
|
||||||
|
isAuthorized: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -253,6 +253,13 @@ class WebhookListPage extends BaseListPage {
|
|||||||
searchText: params.searchText,
|
searchText: params.searchText,
|
||||||
searchedColumn: params.searchedColumn,
|
searchedColumn: params.searchedColumn,
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
if (res.msg.includes("Unauthorized")) {
|
||||||
|
this.setState({
|
||||||
|
loading: false,
|
||||||
|
isAuthorized: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -20,6 +20,7 @@ import * as Util from "./Util";
|
|||||||
import {authConfig} from "./Auth";
|
import {authConfig} from "./Auth";
|
||||||
import * as Setting from "../Setting";
|
import * as Setting from "../Setting";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
|
import RedirectForm from "../common/RedirectForm";
|
||||||
|
|
||||||
class AuthCallback extends React.Component {
|
class AuthCallback extends React.Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
@ -27,6 +28,9 @@ class AuthCallback extends React.Component {
|
|||||||
this.state = {
|
this.state = {
|
||||||
classes: props,
|
classes: props,
|
||||||
msg: null,
|
msg: null,
|
||||||
|
samlResponse: "",
|
||||||
|
relayState: "",
|
||||||
|
redirectUrl: "",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -164,10 +168,18 @@ class AuthCallback extends React.Component {
|
|||||||
const from = innerParams.get("from");
|
const from = innerParams.get("from");
|
||||||
Setting.goToLinkSoft(this, from);
|
Setting.goToLinkSoft(this, from);
|
||||||
} else if (responseType === "saml") {
|
} else if (responseType === "saml") {
|
||||||
|
if (res.data2.method === "POST") {
|
||||||
|
this.setState({
|
||||||
|
samlResponse: res.data,
|
||||||
|
redirectUrl: res.data2.redirectUrl,
|
||||||
|
relayState: oAuthParams.relayState,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
const SAMLResponse = res.data;
|
const SAMLResponse = res.data;
|
||||||
const redirectUri = res.data2;
|
const redirectUri = res.data2.redirectUrl;
|
||||||
Setting.goToLink(`${redirectUri}?SAMLResponse=${encodeURIComponent(SAMLResponse)}&RelayState=${oAuthParams.relayState}`);
|
Setting.goToLink(`${redirectUri}?SAMLResponse=${encodeURIComponent(SAMLResponse)}&RelayState=${oAuthParams.relayState}`);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
this.setState({
|
this.setState({
|
||||||
msg: res.msg,
|
msg: res.msg,
|
||||||
@ -177,8 +189,12 @@ class AuthCallback extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
if (this.state.samlResponse !== "") {
|
||||||
|
return <RedirectForm samlResponse={this.state.samlResponse} redirectUrl={this.state.redirectUrl} relayState={this.state.relayState} />;
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={{textAlign: "center"}}>
|
<div style={{display: "flex", justifyContent: "center", alignItems: "center"}}>
|
||||||
{
|
{
|
||||||
(this.state.msg === null) ? (
|
(this.state.msg === null) ? (
|
||||||
<Spin size="large" tip={i18next.t("login:Signing in...")} style={{paddingTop: "10%"}} />
|
<Spin size="large" tip={i18next.t("login:Signing in...")} style={{paddingTop: "10%"}} />
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import {Spin} from "antd";
|
import {Card, Spin} from "antd";
|
||||||
import {withRouter} from "react-router-dom";
|
import {withRouter} from "react-router-dom";
|
||||||
import * as AuthBackend from "./AuthBackend";
|
import * as AuthBackend from "./AuthBackend";
|
||||||
import * as Setting from "../Setting";
|
import * as Setting from "../Setting";
|
||||||
@ -39,7 +39,8 @@ class CasLogout extends React.Component {
|
|||||||
.then((res) => {
|
.then((res) => {
|
||||||
if (res.status === "ok") {
|
if (res.status === "ok") {
|
||||||
Setting.showMessage("success", "Logged out successfully");
|
Setting.showMessage("success", "Logged out successfully");
|
||||||
this.props.clearAccount();
|
this.props.onUpdateAccount(null);
|
||||||
|
this.onUpdateApplication(null);
|
||||||
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);
|
||||||
@ -49,6 +50,7 @@ class CasLogout extends React.Component {
|
|||||||
Setting.goToLinkSoft(this, `/cas/${this.state.owner}/${this.state.applicationName}/login`);
|
Setting.goToLinkSoft(this, `/cas/${this.state.owner}/${this.state.applicationName}/login`);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
this.onUpdateApplication(null);
|
||||||
Setting.showMessage("error", `Failed to log out: ${res.msg}`);
|
Setting.showMessage("error", `Failed to log out: ${res.msg}`);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -57,11 +59,13 @@ class CasLogout extends React.Component {
|
|||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<div style={{textAlign: "center"}}>
|
<Card>
|
||||||
|
<div style={{display: "flex", justifyContent: "center", alignItems: "center"}}>
|
||||||
{
|
{
|
||||||
<Spin size="large" tip={i18next.t("login:Logging out...")} style={{paddingTop: "10%"}} />
|
<Spin size="large" tip={i18next.t("login:Logging out...")} style={{paddingTop: "10%"}} />
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
|
</Card>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,12 +34,7 @@ class ForgetPage extends React.Component {
|
|||||||
this.state = {
|
this.state = {
|
||||||
classes: props,
|
classes: props,
|
||||||
account: props.account,
|
account: props.account,
|
||||||
applicationName:
|
applicationName: props.applicationName ?? props.match.params?.applicationName,
|
||||||
props.applicationName !== undefined
|
|
||||||
? props.applicationName
|
|
||||||
: props.match === undefined
|
|
||||||
? null
|
|
||||||
: props.match.params.applicationName,
|
|
||||||
application: null,
|
application: null,
|
||||||
msg: null,
|
msg: null,
|
||||||
userId: "",
|
userId: "",
|
||||||
@ -57,34 +52,36 @@ class ForgetPage extends React.Component {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
UNSAFE_componentWillMount() {
|
componentDidMount() {
|
||||||
|
if (this.getApplicationObj() === null) {
|
||||||
if (this.state.applicationName !== undefined) {
|
if (this.state.applicationName !== undefined) {
|
||||||
this.getApplication();
|
this.getApplication();
|
||||||
} else {
|
} else {
|
||||||
Setting.showMessage("error", i18next.t("forget:Unknown forget type: ") + this.state.type);
|
Setting.showMessage("error", i18next.t("forget:Unknown forget type: ") + this.state.type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
getApplication() {
|
getApplication() {
|
||||||
if (this.state.applicationName === null) {
|
if (this.state.applicationName === undefined) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ApplicationBackend.getApplication("admin", this.state.applicationName).then(
|
ApplicationBackend.getApplication("admin", this.state.applicationName)
|
||||||
(application) => {
|
.then((application) => {
|
||||||
|
this.onUpdateApplication(application);
|
||||||
this.setState({
|
this.setState({
|
||||||
application: application,
|
application: application,
|
||||||
});
|
});
|
||||||
}
|
});
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getApplicationObj() {
|
getApplicationObj() {
|
||||||
if (this.props.application !== undefined) {
|
return this.props.application ?? this.state.application;
|
||||||
return this.props.application;
|
|
||||||
} else {
|
|
||||||
return this.state.application;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onUpdateApplication(application) {
|
||||||
|
this.props.onUpdateApplication(application);
|
||||||
}
|
}
|
||||||
|
|
||||||
onFormFinish(name, info, forms) {
|
onFormFinish(name, info, forms) {
|
||||||
@ -143,7 +140,7 @@ class ForgetPage extends React.Component {
|
|||||||
username: this.state.username,
|
username: this.state.username,
|
||||||
name: this.state.name,
|
name: this.state.name,
|
||||||
code: forms.step2.getFieldValue("emailCode"),
|
code: forms.step2.getFieldValue("emailCode"),
|
||||||
phonePrefix: this.state.application?.organizationObj.phonePrefix,
|
phonePrefix: this.getApplicationObj()?.organizationObj.phonePrefix,
|
||||||
type: "login",
|
type: "login",
|
||||||
}, oAuthParams).then(res => {
|
}, oAuthParams).then(res => {
|
||||||
if (res.status === "ok") {
|
if (res.status === "ok") {
|
||||||
@ -166,10 +163,10 @@ class ForgetPage extends React.Component {
|
|||||||
|
|
||||||
onFinish(values) {
|
onFinish(values) {
|
||||||
values.username = this.state.username;
|
values.username = this.state.username;
|
||||||
values.userOwner = this.state.application?.organizationObj.name;
|
values.userOwner = this.getApplicationObj()?.organizationObj.name;
|
||||||
UserBackend.setPassword(values.userOwner, values.username, "", values?.newPassword).then(res => {
|
UserBackend.setPassword(values.userOwner, values.username, "", values?.newPassword).then(res => {
|
||||||
if (res.status === "ok") {
|
if (res.status === "ok") {
|
||||||
Setting.redirectToLoginPage(this.state.application, this.props.history);
|
Setting.redirectToLoginPage(this.getApplicationObj(), this.props.history);
|
||||||
} else {
|
} else {
|
||||||
Setting.showMessage("error", i18next.t(`signup:${res.msg}`));
|
Setting.showMessage("error", i18next.t(`signup:${res.msg}`));
|
||||||
}
|
}
|
||||||
@ -355,13 +352,15 @@ 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 === ""}
|
||||||
onButtonClickArgs={[this.state.email, "email", Setting.getApplicationName(this.state.application), this.state.name]}
|
method={"forget"}
|
||||||
|
onButtonClickArgs={[this.state.email, "email", Setting.getApplicationName(this.getApplicationObj()), this.state.name]}
|
||||||
application={application}
|
application={application}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<CountDownInput
|
<CountDownInput
|
||||||
disabled={this.state.username === "" || this.state.verifyType === ""}
|
disabled={this.state.username === "" || this.state.verifyType === ""}
|
||||||
onButtonClickArgs={[this.state.phone, "phone", Setting.getApplicationName(this.state.application), this.state.name]}
|
method={"forget"}
|
||||||
|
onButtonClickArgs={[this.state.phone, "phone", Setting.getApplicationName(this.getApplicationObj()), this.state.name]}
|
||||||
application={application}
|
application={application}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
@ -490,7 +489,7 @@ class ForgetPage extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="loginBackground" style={{backgroundImage: Setting.inIframe() || Setting.isMobile() ? null : `url(${application.formBackgroundUrl})`}}>
|
<React.Fragment>
|
||||||
<CustomGithubCorner />
|
<CustomGithubCorner />
|
||||||
<div className="forget-content" style={{padding: Setting.isMobile() ? "0" : null, boxShadow: Setting.isMobile() ? "none" : null}}>
|
<div className="forget-content" style={{padding: Setting.isMobile() ? "0" : null, boxShadow: Setting.isMobile() ? "none" : null}}>
|
||||||
<Row>
|
<Row>
|
||||||
@ -548,7 +547,7 @@ class ForgetPage extends React.Component {
|
|||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</React.Fragment>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
32
web/src/auth/LineLoginButton.js
Normal file
32
web/src/auth/LineLoginButton.js
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
// Copyright 2021 The Casdoor Authors. All Rights Reserved.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
import {createButton} from "react-social-login-buttons";
|
||||||
|
import {StaticBaseUrl} from "../Setting";
|
||||||
|
|
||||||
|
function Icon({width = 24, height = 24, color}) {
|
||||||
|
return <img src={`${StaticBaseUrl}/buttons/line.svg`} alt="Sign in with Line" style={{width: 24, height: 24}} />;
|
||||||
|
}
|
||||||
|
|
||||||
|
const config = {
|
||||||
|
text: "Sign in with Line",
|
||||||
|
icon: Icon,
|
||||||
|
iconFormat: name => `fa fa-${name}`,
|
||||||
|
style: {background: "#ffffff", color: "#000000"},
|
||||||
|
activeStyle: {background: "#ededee"},
|
||||||
|
};
|
||||||
|
|
||||||
|
const LineLoginButton = createButton(config);
|
||||||
|
|
||||||
|
export default LineLoginButton;
|
@ -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) {
|
||||||
@ -57,7 +61,8 @@ class LoginPage extends React.Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
UNSAFE_componentWillMount() {
|
componentDidMount() {
|
||||||
|
if (this.getApplicationObj() === null) {
|
||||||
if (this.state.type === "login" || this.state.type === "cas") {
|
if (this.state.type === "login" || this.state.type === "cas") {
|
||||||
this.getApplication();
|
this.getApplication();
|
||||||
} else if (this.state.type === "code") {
|
} else if (this.state.type === "code") {
|
||||||
@ -69,6 +74,11 @@ class LoginPage extends React.Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
@ -86,11 +96,13 @@ class LoginPage extends React.Component {
|
|||||||
AuthBackend.getApplicationLogin(oAuthParams)
|
AuthBackend.getApplicationLogin(oAuthParams)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
if (res.status === "ok") {
|
if (res.status === "ok") {
|
||||||
|
this.onUpdateApplication(res.data);
|
||||||
this.setState({
|
this.setState({
|
||||||
application: res.data,
|
application: res.data,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
// Setting.showMessage("error", res.msg);
|
// Setting.showMessage("error", res.msg);
|
||||||
|
this.onUpdateApplication(null);
|
||||||
this.setState({
|
this.setState({
|
||||||
application: res.data,
|
application: res.data,
|
||||||
msg: res.msg,
|
msg: res.msg,
|
||||||
@ -107,6 +119,7 @@ class LoginPage extends React.Component {
|
|||||||
if (this.state.owner === null || this.state.owner === undefined || this.state.owner === "") {
|
if (this.state.owner === null || this.state.owner === undefined || this.state.owner === "") {
|
||||||
ApplicationBackend.getApplication("admin", this.state.applicationName)
|
ApplicationBackend.getApplication("admin", this.state.applicationName)
|
||||||
.then((application) => {
|
.then((application) => {
|
||||||
|
this.onUpdateApplication(application);
|
||||||
this.setState({
|
this.setState({
|
||||||
application: application,
|
application: application,
|
||||||
});
|
});
|
||||||
@ -115,11 +128,13 @@ class LoginPage extends React.Component {
|
|||||||
OrganizationBackend.getDefaultApplication("admin", this.state.owner)
|
OrganizationBackend.getDefaultApplication("admin", this.state.owner)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
if (res.status === "ok") {
|
if (res.status === "ok") {
|
||||||
|
this.onUpdateApplication(res.data);
|
||||||
this.setState({
|
this.setState({
|
||||||
application: res.data,
|
application: res.data,
|
||||||
applicationName: res.data.name,
|
applicationName: res.data.name,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
this.onUpdateApplication(null);
|
||||||
Setting.showMessage("error", res.msg);
|
Setting.showMessage("error", res.msg);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -132,25 +147,25 @@ class LoginPage extends React.Component {
|
|||||||
}
|
}
|
||||||
ApplicationBackend.getApplication(this.state.owner, this.state.applicationName)
|
ApplicationBackend.getApplication(this.state.owner, this.state.applicationName)
|
||||||
.then((application) => {
|
.then((application) => {
|
||||||
|
this.onUpdateApplication(application);
|
||||||
this.setState({
|
this.setState({
|
||||||
application: application,
|
application: application,
|
||||||
});
|
});
|
||||||
}
|
});
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getApplicationObj() {
|
getApplicationObj() {
|
||||||
if (this.props.application !== undefined) {
|
return this.props.application ?? this.state.application;
|
||||||
return this.props.application;
|
|
||||||
} else {
|
|
||||||
return this.state.application;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onUpdateAccount(account) {
|
onUpdateAccount(account) {
|
||||||
this.props.onUpdateAccount(account);
|
this.props.onUpdateAccount(account);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onUpdateApplication(application) {
|
||||||
|
this.props.onUpdateApplication(application);
|
||||||
|
}
|
||||||
|
|
||||||
parseOffset(offset) {
|
parseOffset(offset) {
|
||||||
if (offset === 2 || offset === 4 || Setting.inIframe() || Setting.isMobile()) {
|
if (offset === 2 || offset === 4 || Setting.inIframe() || Setting.isMobile()) {
|
||||||
return "0 auto";
|
return "0 auto";
|
||||||
@ -178,10 +193,11 @@ 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.getApplicationObj()?.organization) {
|
||||||
values["organization"] = this.state.application.organization;
|
values["organization"] = this.getApplicationObj().organization;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
postCodeLoginAction(res) {
|
postCodeLoginAction(res) {
|
||||||
@ -293,7 +309,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);
|
||||||
@ -304,10 +320,18 @@ class LoginPage extends React.Component {
|
|||||||
const accessToken = res.data;
|
const accessToken = res.data;
|
||||||
Setting.goToLink(`${oAuthParams.redirectUri}#${responseType}=${accessToken}?state=${oAuthParams.state}&token_type=bearer`);
|
Setting.goToLink(`${oAuthParams.redirectUri}#${responseType}=${accessToken}?state=${oAuthParams.state}&token_type=bearer`);
|
||||||
} else if (responseType === "saml") {
|
} else if (responseType === "saml") {
|
||||||
|
if (res.data2.method === "POST") {
|
||||||
|
this.setState({
|
||||||
|
samlResponse: res.data,
|
||||||
|
redirectUrl: res.data2.redirectUrl,
|
||||||
|
relayState: oAuthParams.relayState,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
const SAMLResponse = res.data;
|
const SAMLResponse = res.data;
|
||||||
const redirectUri = res.data2;
|
const redirectUri = res.data2.redirectUrl;
|
||||||
Setting.goToLink(`${redirectUri}?SAMLResponse=${encodeURIComponent(SAMLResponse)}&RelayState=${oAuthParams.relayState}`);
|
Setting.goToLink(`${redirectUri}?SAMLResponse=${encodeURIComponent(SAMLResponse)}&RelayState=${oAuthParams.relayState}`);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
this.setState({openCaptchaModal: false});
|
this.setState({openCaptchaModal: false});
|
||||||
Setting.showMessage("error", `Failed to log in: ${res.msg}`);
|
Setting.showMessage("error", `Failed to log in: ${res.msg}`);
|
||||||
@ -554,12 +578,12 @@ class LoginPage extends React.Component {
|
|||||||
<span style={{float: "right"}}>
|
<span style={{float: "right"}}>
|
||||||
{
|
{
|
||||||
!application.enableSignUp ? null : (
|
!application.enableSignUp ? null : (
|
||||||
<>
|
<React.Fragment>
|
||||||
{i18next.t("login:No account?")}
|
{i18next.t("login:No account?")}
|
||||||
{
|
{
|
||||||
Setting.renderSignupLink(application, i18next.t("login:sign up now"))
|
Setting.renderSignupLink(application, i18next.t("login:sign up now"))
|
||||||
}
|
}
|
||||||
</>
|
</React.Fragment>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
</span>
|
</span>
|
||||||
@ -592,13 +616,13 @@ class LoginPage extends React.Component {
|
|||||||
this.sendSilentSigninData("signing-in");
|
this.sendSilentSigninData("signing-in");
|
||||||
|
|
||||||
const values = {};
|
const values = {};
|
||||||
values["application"] = this.state.application.name;
|
values["application"] = application.name;
|
||||||
this.onFinish(values);
|
this.onFinish(values);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (application.enableAutoSignin) {
|
if (application.enableAutoSignin) {
|
||||||
const values = {};
|
const values = {};
|
||||||
values["application"] = this.state.application.name;
|
values["application"] = application.name;
|
||||||
this.onFinish(values);
|
this.onFinish(values);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -613,7 +637,7 @@ class LoginPage extends React.Component {
|
|||||||
<br />
|
<br />
|
||||||
<SelfLoginButton account={this.props.account} onClick={() => {
|
<SelfLoginButton account={this.props.account} onClick={() => {
|
||||||
const values = {};
|
const values = {};
|
||||||
values["application"] = this.state.application.name;
|
values["application"] = application.name;
|
||||||
this.onFinish(values);
|
this.onFinish(values);
|
||||||
}} />
|
}} />
|
||||||
<br />
|
<br />
|
||||||
@ -655,7 +679,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 +743,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 +779,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}} />
|
||||||
@ -764,16 +793,16 @@ class LoginPage extends React.Component {
|
|||||||
if (this.props.application === undefined && !application.enablePassword && visibleOAuthProviderItems.length === 1) {
|
if (this.props.application === undefined && !application.enablePassword && visibleOAuthProviderItems.length === 1) {
|
||||||
Setting.goToLink(Provider.getAuthUrl(application, visibleOAuthProviderItems[0].provider, "signup"));
|
Setting.goToLink(Provider.getAuthUrl(application, visibleOAuthProviderItems[0].provider, "signup"));
|
||||||
return (
|
return (
|
||||||
<div style={{textAlign: "center"}}>
|
<div style={{display: "flex", justifyContent: "center", alignItems: "center"}}>
|
||||||
<Spin size="large" tip={i18next.t("login:Signing in...")} style={{paddingTop: "10%"}} />
|
<Spin size="large" tip={i18next.t("login:Signing in...")} style={{paddingTop: "10%"}} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="loginBackground" style={{backgroundImage: Setting.inIframe() || Setting.isMobile() ? null : `url(${application.formBackgroundUrl})`}}>
|
<React.Fragment>
|
||||||
<CustomGithubCorner />
|
<CustomGithubCorner />
|
||||||
<div className="login-content" style={{margin: this.parseOffset(application.formOffset)}}>
|
<div className="login-content" style={{margin: this.props.preview ?? this.parseOffset(application.formOffset)}}>
|
||||||
{Setting.inIframe() || Setting.isMobile() ? null : <div dangerouslySetInnerHTML={{__html: application.formCss}} />}
|
{Setting.inIframe() || Setting.isMobile() ? null : <div dangerouslySetInnerHTML={{__html: application.formCss}} />}
|
||||||
<div className="login-panel">
|
<div className="login-panel">
|
||||||
<div className="side-image" style={{display: application.formOffset !== 4 ? "none" : null}}>
|
<div className="side-image" style={{display: application.formOffset !== 4 ? "none" : null}}>
|
||||||
@ -803,7 +832,7 @@ class LoginPage extends React.Component {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</React.Fragment>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import {Button, Col, Result, Row} from "antd";
|
import {Button, Card, Col, Result, Row} from "antd";
|
||||||
import * as ApplicationBackend from "../backend/ApplicationBackend";
|
import * as ApplicationBackend from "../backend/ApplicationBackend";
|
||||||
import * as UserBackend from "../backend/UserBackend";
|
import * as UserBackend from "../backend/UserBackend";
|
||||||
import * as AuthBackend from "./AuthBackend";
|
import * as AuthBackend from "./AuthBackend";
|
||||||
@ -30,7 +30,7 @@ class PromptPage extends React.Component {
|
|||||||
this.state = {
|
this.state = {
|
||||||
classes: props,
|
classes: props,
|
||||||
type: props.type,
|
type: props.type,
|
||||||
applicationName: props.applicationName !== undefined ? props.applicationName : (props.match === undefined ? null : props.match.params.applicationName),
|
applicationName: props.applicationName ?? (props.match === undefined ? null : props.match.params.applicationName),
|
||||||
application: null,
|
application: null,
|
||||||
user: null,
|
user: null,
|
||||||
};
|
};
|
||||||
@ -38,8 +38,10 @@ class PromptPage extends React.Component {
|
|||||||
|
|
||||||
UNSAFE_componentWillMount() {
|
UNSAFE_componentWillMount() {
|
||||||
this.getUser();
|
this.getUser();
|
||||||
|
if (this.getApplicationObj() === null) {
|
||||||
this.getApplication();
|
this.getApplication();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
getUser() {
|
getUser() {
|
||||||
const organizationName = this.props.account.owner;
|
const organizationName = this.props.account.owner;
|
||||||
@ -59,6 +61,7 @@ class PromptPage extends React.Component {
|
|||||||
|
|
||||||
ApplicationBackend.getApplication("admin", this.state.applicationName)
|
ApplicationBackend.getApplication("admin", this.state.applicationName)
|
||||||
.then((application) => {
|
.then((application) => {
|
||||||
|
this.onUpdateApplication(application);
|
||||||
this.setState({
|
this.setState({
|
||||||
application: application,
|
application: application,
|
||||||
});
|
});
|
||||||
@ -66,11 +69,11 @@ class PromptPage extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getApplicationObj() {
|
getApplicationObj() {
|
||||||
if (this.props.application !== undefined) {
|
return this.props.application ?? this.state.application;
|
||||||
return this.props.application;
|
|
||||||
} else {
|
|
||||||
return this.state.application;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onUpdateApplication(application) {
|
||||||
|
this.props.onUpdateApplication(application);
|
||||||
}
|
}
|
||||||
|
|
||||||
parseUserField(key, value) {
|
parseUserField(key, value) {
|
||||||
@ -122,7 +125,7 @@ class PromptPage extends React.Component {
|
|||||||
|
|
||||||
renderContent(application) {
|
renderContent(application) {
|
||||||
return (
|
return (
|
||||||
<div style={{width: "400px"}}>
|
<div style={{width: "500px"}}>
|
||||||
{
|
{
|
||||||
this.renderAffiliation(application)
|
this.renderAffiliation(application)
|
||||||
}
|
}
|
||||||
@ -247,9 +250,9 @@ class PromptPage extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Row>
|
<div style={{display: "flex", flex: "1", justifyContent: "center"}}>
|
||||||
<Col span={24} style={{display: "flex", justifyContent: "center"}}>
|
<Card>
|
||||||
<div style={{marginTop: "80px", marginBottom: "50px", textAlign: "center"}}>
|
<div style={{marginTop: "30px", marginBottom: "30px", textAlign: "center"}}>
|
||||||
{
|
{
|
||||||
Setting.renderHelmet(application)
|
Setting.renderHelmet(application)
|
||||||
}
|
}
|
||||||
@ -259,16 +262,12 @@ class PromptPage extends React.Component {
|
|||||||
{
|
{
|
||||||
this.renderContent(application)
|
this.renderContent(application)
|
||||||
}
|
}
|
||||||
<Row style={{margin: 10}}>
|
|
||||||
<Col span={18}>
|
|
||||||
</Col>
|
|
||||||
</Row>
|
|
||||||
<div style={{marginTop: "50px"}}>
|
<div style={{marginTop: "50px"}}>
|
||||||
<Button disabled={!Setting.isPromptAnswered(this.state.user, application)} type="primary" size="large" onClick={() => {this.submitUserEdit(true);}}>{i18next.t("code:Submit and complete")}</Button>
|
<Button disabled={!Setting.isPromptAnswered(this.state.user, application)} type="primary" size="large" onClick={() => {this.submitUserEdit(true);}}>{i18next.t("code:Submit and complete")}</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Col>
|
</Card>
|
||||||
</Row>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -121,6 +121,10 @@ const authInfo = {
|
|||||||
Bilibili: {
|
Bilibili: {
|
||||||
endpoint: "https://passport.bilibili.com/register/pc_oauth2.html",
|
endpoint: "https://passport.bilibili.com/register/pc_oauth2.html",
|
||||||
},
|
},
|
||||||
|
Line: {
|
||||||
|
scope: "profile%20openid%20email",
|
||||||
|
endpoint: "https://access.line.me/oauth2/v2.1/authorize",
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export function getProviderUrl(provider) {
|
export function getProviderUrl(provider) {
|
||||||
@ -256,5 +260,7 @@ export function getAuthUrl(application, provider, method) {
|
|||||||
return `${provider.customAuthUrl}?client_id=${provider.clientId}&redirect_uri=${redirectUri}&scope=${provider.customScope}&response_type=code&state=${state}`;
|
return `${provider.customAuthUrl}?client_id=${provider.clientId}&redirect_uri=${redirectUri}&scope=${provider.customScope}&response_type=code&state=${state}`;
|
||||||
} else if (provider.type === "Bilibili") {
|
} else if (provider.type === "Bilibili") {
|
||||||
return `${endpoint}#/?client_id=${provider.clientId}&return_url=${redirectUri}&state=${state}&response_type=code`;
|
return `${endpoint}#/?client_id=${provider.clientId}&return_url=${redirectUri}&state=${state}&response_type=code`;
|
||||||
|
} else if (provider.type === "Line") {
|
||||||
|
return `${endpoint}?client_id=${provider.clientId}&redirect_uri=${redirectUri}&state=${state}&response_type=code&scope=${scope}`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -39,6 +39,7 @@ import SteamLoginButton from "./SteamLoginButton";
|
|||||||
import BilibiliLoginButton from "./BilibiliLoginButton";
|
import BilibiliLoginButton from "./BilibiliLoginButton";
|
||||||
import OktaLoginButton from "./OktaLoginButton";
|
import OktaLoginButton from "./OktaLoginButton";
|
||||||
import DouyinLoginButton from "./DouyinLoginButton";
|
import DouyinLoginButton from "./DouyinLoginButton";
|
||||||
|
import LineLoginButton from "./LineLoginButton";
|
||||||
import * as AuthBackend from "./AuthBackend";
|
import * as AuthBackend from "./AuthBackend";
|
||||||
import {getEvent} from "./Util";
|
import {getEvent} from "./Util";
|
||||||
import {Modal} from "antd";
|
import {Modal} from "antd";
|
||||||
@ -93,6 +94,8 @@ function getSigninButton(type) {
|
|||||||
return <OktaLoginButton text={text} align={"center"} />;
|
return <OktaLoginButton text={text} align={"center"} />;
|
||||||
} else if (type === "Douyin") {
|
} else if (type === "Douyin") {
|
||||||
return <DouyinLoginButton text={text} align={"center"} />;
|
return <DouyinLoginButton text={text} align={"center"} />;
|
||||||
|
} else if (type === "Line") {
|
||||||
|
return <LineLoginButton text={text} align={"center"} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
return text;
|
return text;
|
||||||
|
@ -95,7 +95,7 @@ class SamlCallback extends React.Component {
|
|||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<div style={{textAlign: "center"}}>
|
<div style={{display: "flex", justifyContent: "center", alignItems: "center"}}>
|
||||||
{
|
{
|
||||||
(this.state.msg === null) ? (
|
(this.state.msg === null) ? (
|
||||||
<Spin size="large" tip={i18next.t("login:Signing in...")} style={{paddingTop: "10%"}} />
|
<Spin size="large" tip={i18next.t("login:Signing in...")} style={{paddingTop: "10%"}} />
|
||||||
|
@ -22,7 +22,6 @@ class SelfForgetPage extends React.Component {
|
|||||||
<ForgetPage
|
<ForgetPage
|
||||||
type={"forgotPassword"}
|
type={"forgotPassword"}
|
||||||
applicationName={authConfig.appName}
|
applicationName={authConfig.appName}
|
||||||
account={this.props.account}
|
|
||||||
{...this.props}
|
{...this.props}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user