Compare commits

...

33 Commits

Author SHA1 Message Date
Yaodong Yu
db4ac60bb6 feat: fix LDAP mobile field incorrect mapped (#2206) 2023-08-12 13:45:26 +08:00
Yang Luo
33a922f026 Add custom HTTP SMS provider 2023-08-12 12:52:53 +08:00
Yang Luo
9f65053d04 Improve i18n 2023-08-12 02:44:38 +08:00
Yang Luo
be969e5efa Fix typo 2023-08-11 22:18:35 +08:00
Yang Luo
9156bd426b ci: Show provider.displayName in signin button 2023-08-11 16:29:52 +08:00
Yang Luo
fe4a4328aa feat: refactor code in InitApi() 2023-08-11 16:17:29 +08:00
Yaodong Yu
9899022bcd fix: check enforcer should not be nil (#2199)
* fix: check enforcer should not be nil

* fix: check enforcer should not be nil

* Update user.go

---------

Co-authored-by: hsluoyz <hsluoyz@qq.com>
2023-08-11 12:31:49 +08:00
Yaodong Yu
1a9d02be46 feat: use the casbin model to store relationships between users and groups (#2178)
* fix:reslove conflict

* fix: remove interface
2023-08-11 10:59:18 +08:00
Yang Luo
eafaa135b4 Change builtInAvailableField back to 5 2023-08-11 02:45:11 +08:00
Yang Luo
6746551447 Improve error message in InitEnforcer() 2023-08-11 02:36:29 +08:00
Yang Luo
3cb46c3628 Add isKey to syncer's table 2023-08-09 00:33:04 +08:00
Yaodong Yu
558bcf95d6 feat: save policy in adapter edit page (#2190)
* fix: save policy in adapter

* fix: disable edit for builtin adapter
2023-08-09 00:12:53 +08:00
Yang Luo
bb937c30c1 Fix empty cert in getPaymentProvider() 2023-08-08 22:37:48 +08:00
Baihhh
8dfdf7f767 ci: add GoogleCloud and QiNiu in Storage (#2188)
* feat: add GoogleCloud and QiNiu in Storage

Signed-off-by: baihhh <2542274498@qq.com>

* Update qiniu_cloud.go

* Update storage.go

---------

Signed-off-by: baihhh <2542274498@qq.com>
Co-authored-by: hsluoyz <hsluoyz@qq.com>
2023-08-08 22:34:55 +08:00
Yang Luo
62b2082e82 Add getUserOrganization() to user edit page 2023-08-08 21:58:27 +08:00
Yang Luo
a1806439f8 Add UserPrincipalName and MemberOf to get-ldap-users API 2023-08-08 20:18:47 +08:00
Yang Luo
01e58158b7 feat: Remove useless code 2023-08-08 19:16:55 +08:00
Yaodong Yu
15427ad9d6 fix: fix add provider error (#2184) 2023-08-07 17:22:32 +08:00
YunShu
d058f78dc6 fix: fix broken links (#2181) 2023-08-07 01:02:03 +08:00
UsherFall
fd9dbf8251 feat: add multiple SMS providers (#2182)
* feat: add amazon sns and azure acs provider

* feat: add msg91 sms provider

* feat: add infobip sms provider

* feat: add ucloud sms provider

* feat: add baidu cloud sms provider

* fix: fix logo and azure acs
2023-08-07 00:59:17 +08:00
Yaodong Yu
3220a04fa9 fix: use org/groupName replace groupName (#2180) 2023-08-06 20:16:44 +08:00
Yaodong Yu
f06a4990bd fix: rename in init.go (#2179)
* fix: rename in init.go

* fix: remove blank line

* fix: remove blank line

* Update init.go

---------

Co-authored-by: hsluoyz <hsluoyz@qq.com>
2023-08-06 13:07:30 +08:00
Yang Luo
9df7de5f27 Improve menu icons 2023-08-05 18:00:24 +08:00
Yang Luo
56c808c091 Improve menu 2023-08-05 17:41:35 +08:00
Yang Luo
9fd2421564 Update @ant-design/cssinjs dependency to avoid build error 2023-08-04 01:22:57 +08:00
Yang Luo
689d45c7fa feat: fix org name cannot be changed bug 2023-08-03 18:48:37 +08:00
Yang Luo
c24343bd53 Fix XxxChangeTrigger() doesn't return error bug 2023-08-03 18:45:49 +08:00
Yang Luo
979f43638d Change builtInAvailableField to 10 2023-08-03 18:17:15 +08:00
Yaodong Yu
685a4514cd fix: revert adapter port vartype to int (#2174) 2023-08-03 09:35:16 +08:00
Yaodong Yu
a05ca3af24 feat: use role ID to search in GetPermissionsAndRolesByUser() (#2170) 2023-08-02 20:58:06 +08:00
Yang Luo
c6f301ff9e Support svg in downloadImage() 2023-07-31 20:23:28 +08:00
haiwu
d7b2bcf288 feat: support payment cancel state (#2165) 2023-07-31 15:24:13 +08:00
Yang Luo
67ac3d6d21 Fix typo 2023-07-31 15:23:44 +08:00
65 changed files with 2644 additions and 589 deletions

View File

@@ -27,13 +27,7 @@ import (
var Enforcer *casbin.Enforcer
func InitApi() {
var err error
e, err := object.GetEnforcer(util.GetId("built-in", "api-enforcer-built-in"))
if err != nil {
panic(err)
}
err = e.InitEnforcer()
e, err := object.GetInitializedEnforcer(util.GetId("built-in", "api-enforcer-built-in"))
if err != nil {
panic(err)
}

View File

@@ -45,13 +45,7 @@ func (c *ApiController) Enforce() {
}
if enforcerId != "" {
enforcer, err := object.GetEnforcer(enforcerId)
if err != nil {
c.ResponseError(err.Error())
return
}
err = enforcer.InitEnforcer()
enforcer, err := object.GetInitializedEnforcer(enforcerId)
if err != nil {
c.ResponseError(err.Error())
return
@@ -155,13 +149,7 @@ func (c *ApiController) BatchEnforce() {
}
if enforcerId != "" {
enforcer, err := object.GetEnforcer(enforcerId)
if err != nil {
c.ResponseError(err.Error())
return
}
err = enforcer.InitEnforcer()
enforcer, err := object.GetInitializedEnforcer(enforcerId)
if err != nil {
c.ResponseError(err.Error())
return

View File

@@ -140,10 +140,12 @@ func (c *ApiController) SendSms() {
return
}
invalidReceivers := getInvalidSmsReceivers(smsForm)
if len(invalidReceivers) != 0 {
c.ResponseError(fmt.Sprintf(c.T("service:Invalid phone receivers: %s"), strings.Join(invalidReceivers, ", ")))
return
if provider.Type != "Custom HTTP SMS" {
invalidReceivers := getInvalidSmsReceivers(smsForm)
if len(invalidReceivers) != 0 {
c.ResponseError(fmt.Sprintf(c.T("service:Invalid phone receivers: %s"), strings.Join(invalidReceivers, ", ")))
return
}
}
err = object.SendSms(provider, smsForm.Content, smsForm.Receivers...)

View File

@@ -90,7 +90,7 @@ func (c *ApiController) GetUsers() {
if limit == "" || page == "" {
if groupName != "" {
maskedUsers, err := object.GetMaskedUsers(object.GetGroupUsers(groupName))
maskedUsers, err := object.GetMaskedUsers(object.GetGroupUsers(util.GetId(owner, groupName)))
if err != nil {
c.ResponseError(err.Error())
return
@@ -567,6 +567,22 @@ func (c *ApiController) RemoveUserFromGroup() {
name := c.Ctx.Request.Form.Get("name")
groupName := c.Ctx.Request.Form.Get("groupName")
c.Data["json"] = wrapActionResponse(object.RemoveUserFromGroup(owner, name, groupName))
c.ServeJSON()
organization, err := object.GetOrganization(util.GetId("admin", owner))
if err != nil {
return
}
item := object.GetAccountItemByName("Groups", organization)
res, msg := object.CheckAccountItemModifyRule(item, c.IsAdmin(), c.GetAcceptLanguage())
if !res {
c.ResponseError(msg)
return
}
affected, err := object.DeleteGroupForUser(util.GetId(owner, name), groupName)
if err != nil {
c.ResponseError(err.Error())
return
}
c.ResponseOk(affected)
}

20
go.mod
View File

@@ -12,9 +12,9 @@ require (
github.com/beevik/etree v1.1.0
github.com/casbin/casbin v1.9.1 // indirect
github.com/casbin/casbin/v2 v2.30.1
github.com/casdoor/go-sms-sender v0.6.1
github.com/casdoor/go-sms-sender v0.12.0
github.com/casdoor/gomail/v2 v2.0.1
github.com/casdoor/oss v1.2.1
github.com/casdoor/oss v1.3.0
github.com/casdoor/xorm-adapter/v3 v3.0.4
github.com/dchest/captcha v0.0.0-20200903113550-03f5f0333e1f
github.com/denisenkom/go-mssqldb v0.9.0
@@ -28,9 +28,6 @@ require (
github.com/go-sql-driver/mysql v1.6.0
github.com/go-webauthn/webauthn v0.6.0
github.com/golang-jwt/jwt/v4 v4.5.0
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/golang/snappy v0.0.4 // indirect
github.com/google/uuid v1.3.0
github.com/gorilla/mux v1.7.3 // indirect
github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0 // indirect
@@ -43,7 +40,7 @@ require (
github.com/nyaruka/phonenumbers v1.1.5
github.com/pquerna/otp v1.4.0
github.com/prometheus/client_golang v1.11.1
github.com/prometheus/client_model v0.2.0
github.com/prometheus/client_model v0.3.0
github.com/qiangmzsx/string-adapter/v2 v2.1.0
github.com/robfig/cron/v3 v3.0.1
github.com/russellhaering/gosaml2 v0.9.0
@@ -53,7 +50,7 @@ require (
github.com/shirou/gopsutil v3.21.11+incompatible
github.com/siddontang/go-log v0.0.0-20190221022429-1e957dd83bed
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e
github.com/stretchr/testify v1.8.2
github.com/stretchr/testify v1.8.3
github.com/tealeg/xlsx v1.0.5
github.com/thanhpk/randstr v1.0.4
github.com/tklauser/go-sysconf v0.3.10 // indirect
@@ -61,12 +58,11 @@ require (
github.com/xorm-io/core v0.7.4
github.com/xorm-io/xorm v1.1.6
github.com/yusufpapurcu/wmi v1.2.2 // indirect
golang.org/x/crypto v0.6.0
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 // indirect
golang.org/x/net v0.7.0
golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914
golang.org/x/crypto v0.11.0
golang.org/x/net v0.13.0
golang.org/x/oauth2 v0.10.0
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/square/go-jose.v2 v2.6.0
gopkg.in/yaml.v2 v2.4.0 // indirect
modernc.org/sqlite v1.10.1-0.20210314190707-798bbeb9bb84
modernc.org/sqlite v1.18.2
)

1420
go.sum

File diff suppressed because it is too large Load Diff

View File

@@ -132,7 +132,7 @@ func (idp *GiteeIdProvider) GetToken(code string) (*oauth2.Token, error) {
"type": "User",
"blog": null,
"weibo": null,
"bio": "个人博客https://gitee.com/xxx/xxx/pages",
"bio": "bio",
"public_repos": 2,
"public_gists": 0,
"followers": 0,

View File

@@ -49,6 +49,7 @@ func main() {
object.InitLdapAutoSynchronizer()
proxy.InitHttpClient()
authz.InitApi()
object.InitUserManager()
util.SafeGoroutine(func() { object.RunSyncUsersJob() })

View File

@@ -23,6 +23,7 @@ import (
"github.com/casdoor/casdoor/util"
xormadapter "github.com/casdoor/xorm-adapter/v3"
"github.com/xorm-io/core"
"github.com/xorm-io/xorm"
)
type Adapter struct {
@@ -33,7 +34,7 @@ type Adapter struct {
Type string `xorm:"varchar(100)" json:"type"`
DatabaseType string `xorm:"varchar(100)" json:"databaseType"`
Host string `xorm:"varchar(100)" json:"host"`
Port string `xorm:"varchar(20)" json:"port"`
Port int `json:"port"`
User string `xorm:"varchar(100)" json:"user"`
Password string `xorm:"varchar(100)" json:"password"`
Database string `xorm:"varchar(100)" json:"database"`
@@ -153,21 +154,24 @@ func (adapter *Adapter) initAdapter() error {
if adapter.Adapter == nil {
var dataSourceName string
if adapter.buildInAdapter() {
if adapter.builtInAdapter() {
dataSourceName = conf.GetConfigString("dataSourceName")
if adapter.DatabaseType == "mysql" {
dataSourceName = dataSourceName + adapter.Database
}
} else {
switch adapter.DatabaseType {
case "mssql":
dataSourceName = fmt.Sprintf("sqlserver://%s:%s@%s:%s?database=%s", adapter.User,
dataSourceName = fmt.Sprintf("sqlserver://%s:%s@%s:%d?database=%s", adapter.User,
adapter.Password, adapter.Host, adapter.Port, adapter.Database)
case "mysql":
dataSourceName = fmt.Sprintf("%s:%s@tcp(%s:%s)/", adapter.User,
adapter.Password, adapter.Host, adapter.Port)
dataSourceName = fmt.Sprintf("%s:%s@tcp(%s:%d)/%s", adapter.User,
adapter.Password, adapter.Host, adapter.Port, adapter.Database)
case "postgres":
dataSourceName = fmt.Sprintf("user=%s password=%s host=%s port=%s sslmode=disable dbname=%s", adapter.User,
dataSourceName = fmt.Sprintf("user=%s password=%s host=%s port=%d sslmode=disable dbname=%s", adapter.User,
adapter.Password, adapter.Host, adapter.Port, adapter.Database)
case "CockroachDB":
dataSourceName = fmt.Sprintf("user=%s password=%s host=%s port=%s sslmode=disable dbname=%s serial_normalization=virtual_sequence",
dataSourceName = fmt.Sprintf("user=%s password=%s host=%s port=%d sslmode=disable dbname=%s serial_normalization=virtual_sequence",
adapter.User, adapter.Password, adapter.Host, adapter.Port, adapter.Database)
case "sqlite3":
dataSourceName = fmt.Sprintf("file:%s", adapter.Host)
@@ -181,7 +185,8 @@ func (adapter *Adapter) initAdapter() error {
}
var err error
adapter.Adapter, err = xormadapter.NewAdapterByEngineWithTableName(NewAdapter(adapter.DatabaseType, dataSourceName, adapter.Database).Engine, adapter.getTable(), adapter.TableNamePrefix)
engine, err := xorm.NewEngine(adapter.DatabaseType, dataSourceName)
adapter.Adapter, err = xormadapter.NewAdapterByEngineWithTableName(engine, adapter.getTable(), adapter.TableNamePrefix)
if err != nil {
return err
}
@@ -269,6 +274,11 @@ func UpdatePolicy(oldPolicy, newPolicy []string, adapter *Adapter) (bool, error)
if err != nil {
return affected, err
}
err = adapter.SavePolicy(casbinModel)
if err != nil {
return false, err
}
return affected, nil
}
@@ -285,6 +295,10 @@ func AddPolicy(policy []string, adapter *Adapter) (bool, error) {
}
casbinModel.AddPolicy("p", "p", policy)
err = adapter.SavePolicy(casbinModel)
if err != nil {
return false, err
}
return true, nil
}
@@ -305,15 +319,20 @@ func RemovePolicy(policy []string, adapter *Adapter) (bool, error) {
if err != nil {
return affected, err
}
err = adapter.SavePolicy(casbinModel)
if err != nil {
return false, err
}
return affected, nil
}
func (adapter *Adapter) buildInAdapter() bool {
func (adapter *Adapter) builtInAdapter() bool {
if adapter.Owner != "built-in" {
return false
}
return adapter.Name == "permission-adapter-built-in" || adapter.Name == "api-adapter-built-in"
return adapter.Name == "user-adapter-built-in" || adapter.Name == "api-adapter-built-in"
}
func getModelDef() model.Model {

View File

@@ -162,7 +162,7 @@ func UpdateCert(id string, cert *Cert) (bool, error) {
if name != cert.Name {
err := certChangeTrigger(name, cert.Name)
if err != nil {
return false, nil
return false, err
}
}
affected, err := ormer.Engine.ID(core.PK{owner, name}).AllCols().Update(cert)

View File

@@ -15,7 +15,7 @@
package object
import (
"errors"
"fmt"
"github.com/casbin/casbin/v2"
"github.com/casdoor/casdoor/util"
@@ -120,45 +120,65 @@ func DeleteEnforcer(enforcer *Enforcer) (bool, error) {
return affected != 0, nil
}
func (p *Enforcer) GetId() string {
return fmt.Sprintf("%s/%s", p.Owner, p.Name)
}
func (enforcer *Enforcer) InitEnforcer() error {
if enforcer.Enforcer == nil {
if enforcer == nil {
return errors.New("enforcer is nil")
}
if enforcer.Model == "" || enforcer.Adapter == "" {
return errors.New("missing model or adapter")
}
var err error
var m *Model
var a *Adapter
if m, err = GetModel(enforcer.Model); err != nil {
return err
} else if m == nil {
return errors.New("model not found")
}
if a, err = GetAdapter(enforcer.Adapter); err != nil {
return err
} else if a == nil {
return errors.New("adapter not found")
}
err = m.initModel()
if err != nil {
return err
}
err = a.initAdapter()
if err != nil {
return err
}
casbinEnforcer, err := casbin.NewEnforcer(m.Model, a.Adapter)
if err != nil {
return err
}
enforcer.Enforcer = casbinEnforcer
if enforcer.Enforcer != nil {
return nil
}
if enforcer.Model == "" {
return fmt.Errorf("the model for enforcer: %s should not be empty", enforcer.GetId())
}
if enforcer.Adapter == "" {
return fmt.Errorf("the adapter for enforcer: %s should not be empty", enforcer.GetId())
}
m, err := GetModel(enforcer.Model)
if err != nil {
return err
} else if m == nil {
return fmt.Errorf("the model: %s for enforcer: %s is not found", enforcer.Model, enforcer.GetId())
}
a, err := GetAdapter(enforcer.Adapter)
if err != nil {
return err
} else if a == nil {
return fmt.Errorf("the adapter: %s for enforcer: %s is not found", enforcer.Adapter, enforcer.GetId())
}
err = m.initModel()
if err != nil {
return err
}
err = a.initAdapter()
if err != nil {
return err
}
casbinEnforcer, err := casbin.NewEnforcer(m.Model, a.Adapter)
if err != nil {
return err
}
enforcer.Enforcer = casbinEnforcer
return nil
}
func GetInitializedEnforcer(enforcerId string) (*Enforcer, error) {
enforcer, err := GetEnforcer(enforcerId)
if err != nil {
return nil, err
} else if enforcer == nil {
return nil, fmt.Errorf("the enforcer: %s is not found", enforcerId)
}
err = enforcer.InitEnforcer()
if err != nil {
return nil, err
}
return enforcer, nil
}

View File

@@ -164,7 +164,7 @@ func DeleteGroup(group *Group) (bool, error) {
return false, errors.New("group has children group")
}
if count, err := GetGroupUserCount(group.Name, "", ""); err != nil {
if count, err := GetGroupUserCount(group.GetId(), "", ""); err != nil {
return false, err
} else if count > 0 {
return false, errors.New("group has users")
@@ -214,39 +214,33 @@ func ConvertToTreeData(groups []*Group, parentId string) []*Group {
return treeData
}
func RemoveUserFromGroup(owner, name, groupName string) (bool, error) {
user, err := getUser(owner, name)
func GetGroupUserCount(groupId string, field, value string) (int64, error) {
owner, _ := util.GetOwnerAndNameFromId(groupId)
names, err := userEnforcer.GetUserNamesByGroupName(groupId)
if err != nil {
return false, err
}
if user == nil {
return false, errors.New("user not exist")
return 0, err
}
user.Groups = util.DeleteVal(user.Groups, groupName)
affected, err := updateUser(user.GetId(), user, []string{"groups"})
if err != nil {
return false, err
}
return affected != 0, err
}
func GetGroupUserCount(groupName string, field, value string) (int64, error) {
if field == "" && value == "" {
return ormer.Engine.Where(builder.Like{"`groups`", groupName}).
Count(&User{})
return int64(len(names)), nil
} else {
return ormer.Engine.Table("user").
Where(builder.Like{"`groups`", groupName}).
Where("owner = ?", owner).In("name", names).
And(fmt.Sprintf("user.%s LIKE ?", util.CamelToSnakeCase(field)), "%"+value+"%").
Count()
}
}
func GetPaginationGroupUsers(groupName string, offset, limit int, field, value, sortField, sortOrder string) ([]*User, error) {
func GetPaginationGroupUsers(groupId string, offset, limit int, field, value, sortField, sortOrder string) ([]*User, error) {
users := []*User{}
owner, _ := util.GetOwnerAndNameFromId(groupId)
names, err := userEnforcer.GetUserNamesByGroupName(groupId)
if err != nil {
return nil, err
}
session := ormer.Engine.Table("user").
Where(builder.Like{"`groups`", groupName + "\""})
Where("owner = ?", owner).In("name", names)
if offset != -1 && limit != -1 {
session.Limit(limit, offset)
@@ -265,7 +259,7 @@ func GetPaginationGroupUsers(groupName string, offset, limit int, field, value,
session = session.Desc(fmt.Sprintf("user.%s", util.SnakeString(sortField)))
}
err := session.Find(&users)
err = session.Find(&users)
if err != nil {
return nil, err
}
@@ -273,15 +267,15 @@ func GetPaginationGroupUsers(groupName string, offset, limit int, field, value,
return users, nil
}
func GetGroupUsers(groupName string) ([]*User, error) {
func GetGroupUsers(groupId string) ([]*User, error) {
users := []*User{}
err := ormer.Engine.Table("user").
Where(builder.Like{"`groups`", groupName + "\""}).
Find(&users)
owner, _ := util.GetOwnerAndNameFromId(groupId)
names, err := userEnforcer.GetUserNamesByGroupName(groupId)
err = ormer.Engine.Where("owner = ?", owner).In("name", names).Find(&users)
if err != nil {
return nil, err
}
return users, nil
}

View File

@@ -37,11 +37,11 @@ func InitDb() {
existed = initBuiltInApiModel()
if !existed {
initBuildInApiAdapter()
initBuiltInApiAdapter()
initBuiltInApiEnforcer()
initBuiltInPermissionModel()
initBuildInPermissionAdapter()
initBuiltInPermissionEnforcer()
initBuiltInUserModel()
initBuiltInUserAdapter()
initBuiltInUserEnforcer()
}
initWebAuthn()
@@ -303,8 +303,8 @@ func initWebAuthn() {
gob.Register(webauthn.SessionData{})
}
func initBuiltInPermissionModel() {
model, err := GetModel("built-in/permission-model-built-in")
func initBuiltInUserModel() {
model, err := GetModel("built-in/user-model-built-in")
if err != nil {
panic(err)
}
@@ -315,7 +315,7 @@ func initBuiltInPermissionModel() {
model = &Model{
Owner: "built-in",
Name: "permission-model-built-in",
Name: "user-model-built-in",
CreatedTime: util.GetCurrentTime(),
DisplayName: "Built-in Model",
IsEnabled: true,
@@ -325,11 +325,14 @@ r = sub, obj, act
[policy_definition]
p = sub, obj, act
[role_definition]
g = _, _
[policy_effect]
e = some(where (p.eft == allow))
[matchers]
m = r.sub == p.sub && r.obj == p.obj && r.act == p.act`,
m = g(r.sub, p.sub) && r.obj == p.obj && r.act == p.act`,
}
_, err = AddModel(model)
if err != nil {
@@ -347,8 +350,7 @@ func initBuiltInApiModel() bool {
return true
}
modelText := `
[request_definition]
modelText := `[request_definition]
r = subOwner, subName, method, urlPath, objOwner, objName
[policy_definition]
@@ -367,8 +369,7 @@ m = (r.subOwner == p.subOwner || p.subOwner == "*") && \
(r.urlPath == p.urlPath || p.urlPath == "*") && \
(r.objOwner == p.objOwner || p.objOwner == "*") && \
(r.objName == p.objName || p.objName == "*") || \
(r.subOwner == r.objOwner && r.subName == r.objName)
`
(r.subOwner == r.objOwner && r.subName == r.objName)`
model = &Model{
Owner: "built-in",
@@ -415,19 +416,19 @@ func initBuiltInPermission() {
}
}
func initBuildInPermissionAdapter() {
permissionAdapter, err := GetAdapter("built-in/permission-adapter-built-in")
func initBuiltInUserAdapter() {
adapter, err := GetAdapter("built-in/user-adapter-built-in")
if err != nil {
panic(err)
}
if permissionAdapter != nil {
if adapter != nil {
return
}
permissionAdapter = &Adapter{
adapter = &Adapter{
Owner: "built-in",
Name: "permission-adapter-built-in",
Name: "user-adapter-built-in",
CreatedTime: util.GetCurrentTime(),
Type: "Database",
DatabaseType: conf.GetConfigString("driverName"),
@@ -436,23 +437,23 @@ func initBuildInPermissionAdapter() {
Table: "casbin_user_rule",
IsEnabled: true,
}
_, err = AddAdapter(permissionAdapter)
_, err = AddAdapter(adapter)
if err != nil {
panic(err)
}
}
func initBuildInApiAdapter() {
apiAdapter, err := GetAdapter("built-in/api-adapter-built-in")
func initBuiltInApiAdapter() {
adapter, err := GetAdapter("built-in/api-adapter-built-in")
if err != nil {
panic(err)
}
if apiAdapter != nil {
if adapter != nil {
return
}
apiAdapter = &Adapter{
adapter = &Adapter{
Owner: "built-in",
Name: "api-adapter-built-in",
CreatedTime: util.GetCurrentTime(),
@@ -463,49 +464,49 @@ func initBuildInApiAdapter() {
Table: "casbin_api_rule",
IsEnabled: true,
}
_, err = AddAdapter(apiAdapter)
_, err = AddAdapter(adapter)
if err != nil {
panic(err)
}
}
func initBuiltInPermissionEnforcer() {
permissionEnforcer, err := GetEnforcer("built-in/permission-enforcer-built-in")
func initBuiltInUserEnforcer() {
enforcer, err := GetEnforcer("built-in/user-enforcer-built-in")
if err != nil {
panic(err)
}
if permissionEnforcer != nil {
if enforcer != nil {
return
}
permissionEnforcer = &Enforcer{
enforcer = &Enforcer{
Owner: "built-in",
Name: "permission-enforcer-built-in",
Name: "user-enforcer-built-in",
CreatedTime: util.GetCurrentTime(),
DisplayName: "Permission Enforcer",
Model: "built-in/permission-model-built-in",
Adapter: "built-in/permission-adapter-built-in",
DisplayName: "User Enforcer",
Model: "built-in/user-model-built-in",
Adapter: "built-in/user-adapter-built-in",
IsEnabled: true,
}
_, err = AddEnforcer(permissionEnforcer)
_, err = AddEnforcer(enforcer)
if err != nil {
panic(err)
}
}
func initBuiltInApiEnforcer() {
apiEnforcer, err := GetEnforcer("built-in/api-enforcer-built-in")
enforcer, err := GetEnforcer("built-in/api-enforcer-built-in")
if err != nil {
panic(err)
}
if apiEnforcer != nil {
if enforcer != nil {
return
}
apiEnforcer = &Enforcer{
enforcer = &Enforcer{
Owner: "built-in",
Name: "api-enforcer-built-in",
CreatedTime: util.GetCurrentTime(),
@@ -515,7 +516,7 @@ func initBuiltInApiEnforcer() {
IsEnabled: true,
}
_, err = AddEnforcer(apiEnforcer)
_, err = AddEnforcer(enforcer)
if err != nil {
panic(err)
}

View File

@@ -41,19 +41,20 @@ type LdapUser struct {
GidNumber string `json:"gidNumber"`
// Gcn string
Uuid string `json:"uuid"`
UserPrincipalName string `json:"userPrincipalName"`
DisplayName string `json:"displayName"`
Mail string
Email string `json:"email"`
EmailAddress string
TelephoneNumber string
Mobile string
Mobile string `json:"mobile"`
MobileTelephoneNumber string
RegisteredAddress string
PostalAddress string
GroupId string `json:"groupId"`
Phone string `json:"phone"`
Address string `json:"address"`
GroupId string `json:"groupId"`
Address string `json:"address"`
MemberOf string `json:"memberOf"`
}
func (ldap *Ldap) GetLdapConn() (c *LdapConn, err error) {
@@ -168,6 +169,8 @@ func (l *LdapConn) GetLdapUsers(ldapServer *Ldap) ([]LdapUser, error) {
user.Uuid = attribute.Values[0]
case "objectGUID":
user.Uuid = attribute.Values[0]
case "userPrincipalName":
user.UserPrincipalName = attribute.Values[0]
case "displayName":
user.DisplayName = attribute.Values[0]
case "mail":
@@ -186,6 +189,8 @@ func (l *LdapConn) GetLdapUsers(ldapServer *Ldap) ([]LdapUser, error) {
user.RegisteredAddress = attribute.Values[0]
case "postalAddress":
user.PostalAddress = attribute.Values[0]
case "memberOf":
user.MemberOf = attribute.Values[0]
}
}
ldapUsers = append(ldapUsers, user)
@@ -312,7 +317,7 @@ func SyncLdapUsers(owner string, syncUsers []LdapUser, ldapId string) (existUser
DisplayName: syncUser.buildLdapDisplayName(),
Avatar: organization.DefaultAvatar,
Email: syncUser.Email,
Phone: syncUser.Phone,
Phone: syncUser.Mobile,
Address: []string{syncUser.Address},
Affiliation: affiliation,
Tag: tag,

View File

@@ -189,7 +189,7 @@ func UpdateOrganization(id string, organization *Organization) (bool, error) {
if name != organization.Name {
err := organizationChangeTrigger(name, organization.Name)
if err != nil {
return false, nil
return false, err
}
}
@@ -432,7 +432,7 @@ func organizationChangeTrigger(oldName string, newName string) error {
payment := new(Payment)
payment.Owner = newName
_, err = session.Where("organization=?", oldName).Update(payment)
_, err = session.Where("owner=?", oldName).Update(payment)
if err != nil {
return err
}

View File

@@ -186,20 +186,23 @@ func notifyPayment(request *http.Request, body []byte, owner string, paymentName
notifyResult, err := pProvider.Notify(request, body, cert.AuthorityPublicKey, orderId)
if err != nil {
return payment, notifyResult, err
return payment, nil, err
}
if notifyResult.PaymentStatus != pp.PaymentStatePaid {
return payment, notifyResult, nil
}
// Only check paid payment
if notifyResult.ProductDisplayName != "" && notifyResult.ProductDisplayName != product.DisplayName {
err = fmt.Errorf("the payment's product name: %s doesn't equal to the expected product name: %s", notifyResult.ProductDisplayName, product.DisplayName)
return payment, notifyResult, err
return payment, nil, err
}
if notifyResult.Price != product.Price {
err = fmt.Errorf("the payment's price: %f doesn't equal to the expected price: %f", notifyResult.Price, product.Price)
return payment, notifyResult, err
return payment, nil, err
}
return payment, notifyResult, err
return payment, notifyResult, nil
}
func NotifyPayment(request *http.Request, body []byte, owner string, paymentName string, orderId string) (*Payment, error) {
@@ -210,6 +213,7 @@ func NotifyPayment(request *http.Request, body []byte, owner string, paymentName
payment.Message = err.Error()
} else {
payment.State = notifyResult.PaymentStatus
payment.Message = notifyResult.NotifyMessage
}
_, err = UpdatePayment(payment.GetId(), payment)
if err != nil {

View File

@@ -58,10 +58,7 @@ type PermissionRule struct {
Id string `xorm:"varchar(100) index not null default ''" json:"id"`
}
const (
builtInAvailableField = 5 // Casdoor built-in adapter, use V5 to filter permission, so has 5 available field
builtInAdapter = "permission_rule"
)
const builtInAvailableField = 5 // Casdoor built-in adapter, use V5 to filter permission, so has 5 available field
func (p *Permission) GetId() string {
return util.GetId(p.Owner, p.Name)
@@ -290,7 +287,7 @@ func GetPermissionsAndRolesByUser(userId string) ([]*Permission, []*Role, error)
for _, role := range roles {
perms := []*Permission{}
err := ormer.Engine.Where("roles like ?", "%"+role.Name+"\"%").Find(&perms)
err := ormer.Engine.Where("roles like ?", "%"+role.GetId()+"\"%").Find(&perms)
if err != nil {
return nil, nil, err
}

View File

@@ -335,7 +335,7 @@ m = g(r.sub, p.sub) && r.obj == p.obj && r.act == p.act`
policyDefinition := strings.Split(cfg.String("policy_definition::p"), ",")
fieldsNum := len(policyDefinition)
if fieldsNum > builtInAvailableField {
panic(fmt.Errorf("the maximum policy_definition field number cannot exceed %d", builtInAvailableField))
panic(fmt.Errorf("the maximum policy_definition field number cannot exceed %d, got %d", builtInAvailableField, fieldsNum))
}
// filled empty field with "" and V5 with "permissionId"
for i := builtInAvailableField - fieldsNum; i > 0; i-- {

View File

@@ -203,7 +203,7 @@ func UpdateProvider(id string, provider *Provider) (bool, error) {
if name != provider.Name {
err := providerChangeTrigger(name, provider.Name)
if err != nil {
return false, nil
return false, err
}
}
@@ -254,7 +254,8 @@ func DeleteProvider(provider *Provider) (bool, error) {
func (p *Provider) getPaymentProvider() (pp.PaymentProvider, *Cert, error) {
cert := &Cert{}
if p.Cert != "" {
cert, err := getCert(p.Owner, p.Cert)
var err error
cert, err = getCert(p.Owner, p.Cert)
if err != nil {
return nil, nil, err
}

View File

@@ -133,7 +133,7 @@ func UpdateRole(id string, role *Role) (bool, error) {
if name != role.Name {
err := roleChangeTrigger(name, role.Name)
if err != nil {
return false, nil
return false, err
}
}

View File

@@ -24,8 +24,10 @@ func getSmsClient(provider *Provider) (sender.SmsClient, error) {
var client sender.SmsClient
var err error
if provider.Type == sender.HuaweiCloud {
if provider.Type == sender.HuaweiCloud || provider.Type == sender.AzureACS {
client, err = sender.NewSmsClient(provider.Type, provider.ClientId, provider.ClientSecret, provider.SignName, provider.TemplateCode, provider.ProviderUrl, provider.AppId)
} else if provider.Type == "Custom HTTP SMS" {
client, err = newHttpSmsClient(provider.Endpoint, provider.Method, provider.ClientId, provider.Title)
} else {
client, err = sender.NewSmsClient(provider.Type, provider.ClientId, provider.ClientSecret, provider.SignName, provider.TemplateCode, provider.AppId)
}

75
object/sms_custom.go Normal file
View File

@@ -0,0 +1,75 @@
// 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 object
import (
"bytes"
"fmt"
"net/http"
"github.com/casdoor/casdoor/proxy"
)
type HttpSmsClient struct {
endpoint string
method string
paramName string
text string
}
func newHttpSmsClient(endpoint string, method string, paramName string, text string) (*HttpSmsClient, error) {
client := &HttpSmsClient{
endpoint: endpoint,
method: method,
paramName: paramName,
text: text,
}
return client, nil
}
func (c *HttpSmsClient) SendMessage(param map[string]string, targetPhoneNumber ...string) error {
var err error
content := param["code"]
httpClient := proxy.DefaultHttpClient
req, err := http.NewRequest(c.method, c.endpoint, bytes.NewBufferString(content))
if err != nil {
return err
}
if c.method == "POST" {
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
req.PostForm = map[string][]string{
c.paramName: {content},
}
} else if c.method == "GET" {
q := req.URL.Query()
q.Add(c.paramName, content)
req.URL.RawQuery = q.Encode()
}
resp, err := httpClient.Do(req)
if err != nil {
return err
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return fmt.Errorf("SendMessage() error, custom HTTP SMS request failed with status: %s", resp.Status)
}
return err
}

View File

@@ -25,6 +25,7 @@ type TableColumn struct {
Name string `json:"name"`
Type string `json:"type"`
CasdoorName string `json:"casdoorName"`
IsKey bool `json:"isKey"`
IsHashed bool `json:"isHashed"`
Values []string `json:"values"`
}

View File

@@ -29,6 +29,19 @@ const (
UserPropertiesWechatOpenId = "wechatOpenId"
)
const UserEnforcerId = "built-in/user-enforcer-built-in"
var userEnforcer *UserGroupEnforcer
func InitUserManager() {
enforcer, err := GetInitializedEnforcer(UserEnforcerId)
if err != nil {
panic(err)
}
userEnforcer = NewUserGroupEnforcer(enforcer.Enforcer)
}
type User struct {
Owner string `xorm:"varchar(100) notnull pk" json:"owner"`
Name string `xorm:"varchar(100) notnull pk" json:"name"`
@@ -230,7 +243,7 @@ func GetUserCount(owner, field, value string, groupName string) (int64, error) {
session := GetSession(owner, -1, -1, field, value, "", "")
if groupName != "" {
return GetGroupUserCount(groupName, field, value)
return GetGroupUserCount(util.GetId(owner, groupName), field, value)
}
return session.Count(&User{})
@@ -274,7 +287,7 @@ func GetPaginationUsers(owner string, offset, limit int, field, value, sortField
users := []*User{}
if groupName != "" {
return GetPaginationGroupUsers(groupName, offset, limit, field, value, sortField, sortOrder)
return GetPaginationGroupUsers(util.GetId(owner, groupName), offset, limit, field, value, sortField, sortOrder)
}
session := GetSessionForUser(owner, offset, limit, field, value, sortField, sortOrder)
@@ -531,6 +544,13 @@ func UpdateUser(id string, user *User, columns []string, isAdmin bool) (bool, er
columns = append(columns, "name", "email", "phone", "country_code")
}
if util.ContainsString(columns, "groups") {
_, err := userEnforcer.UpdateGroupsForUser(user.GetId(), user.Groups)
if err != nil {
return false, err
}
}
affected, err := updateUser(id, user, columns)
if err != nil {
return false, err
@@ -568,7 +588,7 @@ func UpdateUserForAllFields(id string, user *User) (bool, error) {
if name != user.Name {
err := userChangeTrigger(name, user.Name)
if err != nil {
return false, nil
return false, err
}
}
@@ -778,6 +798,10 @@ func ExtendUserWithRolesAndPermissions(user *User) (err error) {
return
}
func DeleteGroupForUser(user string, group string) (bool, error) {
return userEnforcer.DeleteGroupForUser(user, group)
}
func userChangeTrigger(oldName string, newName string) error {
session := ormer.Engine.NewSession()
defer session.Close()

View File

@@ -69,6 +69,8 @@ func downloadImage(client *http.Client, url string) (*bytes.Buffer, string, erro
fileExtension = ".ico"
case "image/x-icon":
fileExtension = ".ico"
case "image/svg+xml":
fileExtension = ".svg"
default:
return nil, "", fmt.Errorf("unsupported content type: %s", contentType)
}

95
object/user_enforcer.go Normal file
View File

@@ -0,0 +1,95 @@
package object
import (
"github.com/casbin/casbin/v2"
"github.com/casbin/casbin/v2/errors"
"github.com/casdoor/casdoor/util"
)
type UserGroupEnforcer struct {
// use rbac model implement use group, the enforcer can also implement user role
enforcer *casbin.Enforcer
}
func NewUserGroupEnforcer(enforcer *casbin.Enforcer) *UserGroupEnforcer {
return &UserGroupEnforcer{
enforcer: enforcer,
}
}
func (e *UserGroupEnforcer) AddGroupForUser(user string, group string) (bool, error) {
return e.enforcer.AddRoleForUser(user, GetGroupWithPrefix(group))
}
func (e *UserGroupEnforcer) AddGroupsForUser(user string, groups []string) (bool, error) {
g := make([]string, len(groups))
for i, group := range groups {
g[i] = GetGroupWithPrefix(group)
}
return e.enforcer.AddRolesForUser(user, g)
}
func (e *UserGroupEnforcer) DeleteGroupForUser(user string, group string) (bool, error) {
return e.enforcer.DeleteRoleForUser(user, GetGroupWithPrefix(group))
}
func (e *UserGroupEnforcer) DeleteGroupsForUser(user string) (bool, error) {
return e.enforcer.DeleteRolesForUser(user)
}
func (e *UserGroupEnforcer) GetGroupsForUser(user string) ([]string, error) {
groups, err := e.enforcer.GetRolesForUser(user)
for i, group := range groups {
groups[i] = GetGroupWithoutPrefix(group)
}
return groups, err
}
func (e *UserGroupEnforcer) GetAllUsersByGroup(group string) ([]string, error) {
users, err := e.enforcer.GetUsersForRole(GetGroupWithPrefix(group))
if err != nil {
if err == errors.ERR_NAME_NOT_FOUND {
return []string{}, nil
}
return nil, err
}
return users, nil
}
func GetGroupWithPrefix(group string) string {
return "group:" + group
}
func GetGroupWithoutPrefix(group string) string {
return group[len("group:"):]
}
func (e *UserGroupEnforcer) GetUserNamesByGroupName(groupName string) ([]string, error) {
var names []string
userIds, err := e.GetAllUsersByGroup(groupName)
if err != nil {
return nil, err
}
for _, userId := range userIds {
_, name := util.GetOwnerAndNameFromIdNoCheck(userId)
names = append(names, name)
}
return names, nil
}
func (e *UserGroupEnforcer) UpdateGroupsForUser(user string, groups []string) (bool, error) {
_, err := e.DeleteGroupsForUser(user)
if err != nil {
return false, err
}
affected, err := e.AddGroupsForUser(user, groups)
if err != nil {
return false, err
}
return affected, nil
}

View File

@@ -17,6 +17,7 @@ package pp
import (
"context"
"errors"
"fmt"
"net/http"
"strconv"
@@ -89,14 +90,24 @@ func (pp *PaypalPaymentProvider) Pay(providerName string, productName string, pa
}
func (pp *PaypalPaymentProvider) Notify(request *http.Request, body []byte, authorityPublicKey string, orderId string) (*NotifyResult, error) {
notifyResult := &NotifyResult{}
captureRsp, err := pp.Client.OrderCapture(context.Background(), orderId, nil)
if err != nil {
return nil, err
}
if captureRsp.Code != paypal.Success {
errDetail := captureRsp.ErrorResponse.Details[0]
switch errDetail.Issue {
// If order is already captured, just skip this type of error and check the order detail
if !(len(captureRsp.ErrorResponse.Details) == 1 && captureRsp.ErrorResponse.Details[0].Issue == "ORDER_ALREADY_CAPTURED") {
return nil, errors.New(captureRsp.ErrorResponse.Message)
case "ORDER_ALREADY_CAPTURED":
// skip
case "ORDER_NOT_APPROVED":
notifyResult.PaymentStatus = PaymentStateCanceled
notifyResult.NotifyMessage = errDetail.Description
return notifyResult, nil
default:
err = fmt.Errorf(errDetail.Description)
return nil, err
}
}
// Check the order detail
@@ -105,7 +116,16 @@ func (pp *PaypalPaymentProvider) Notify(request *http.Request, body []byte, auth
return nil, err
}
if captureRsp.Code != paypal.Success {
return nil, errors.New(captureRsp.ErrorResponse.Message)
errDetail := captureRsp.ErrorResponse.Details[0]
switch errDetail.Issue {
case "ORDER_NOT_APPROVED":
notifyResult.PaymentStatus = PaymentStateCanceled
notifyResult.NotifyMessage = errDetail.Description
return notifyResult, nil
default:
err = fmt.Errorf(errDetail.Description)
return nil, err
}
}
paymentName := detailRsp.Response.Id
@@ -126,7 +146,7 @@ func (pp *PaypalPaymentProvider) Notify(request *http.Request, body []byte, auth
default:
paymentStatus = PaymentStateError
}
notifyResult := &NotifyResult{
notifyResult = &NotifyResult{
PaymentStatus: paymentStatus,
PaymentName: paymentName,

View File

@@ -21,16 +21,18 @@ import (
type PaymentState string
const (
PaymentStatePaid PaymentState = "Paid"
PaymentStateCreated PaymentState = "Created"
PaymentStateError PaymentState = "Error"
PaymentStatePaid PaymentState = "Paid"
PaymentStateCreated PaymentState = "Created"
PaymentStateCanceled PaymentState = "Canceled"
PaymentStateError PaymentState = "Error"
)
type NotifyResult struct {
PaymentName string
PaymentStatus PaymentState
ProviderName string
NotifyMessage string
ProviderName string
ProductName string
ProductDisplayName string
Price float64

View File

@@ -55,12 +55,6 @@ func StaticFilter(ctx *context.Context) {
path += urlPath
}
path2 := strings.TrimPrefix(path, "web/build/images/")
if util.FileExist(path2) {
makeGzipResponse(ctx.ResponseWriter, ctx.Request, path2)
return
}
if !util.FileExist(path) {
path = "web/build/index.html"
}

31
storage/google_cloud.go Normal file
View File

@@ -0,0 +1,31 @@
// 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 storage
import (
"github.com/casdoor/oss"
"github.com/casdoor/oss/googlecloud"
)
func NewGoogleCloudStorageProvider(clientId string, clientSecret string, bucket string, endpoint string) oss.StorageInterface {
sp, _ := googlecloud.New(&googlecloud.Config{
AccessID: clientId,
AccessKey: clientSecret,
Bucket: bucket,
Endpoint: endpoint,
})
return sp
}

32
storage/qiniu_cloud.go Normal file
View File

@@ -0,0 +1,32 @@
// 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 storage
import (
"github.com/casdoor/oss"
"github.com/casdoor/oss/qiniu"
)
func NewQiniuCloudKodoStorageProvider(clientId string, clientSecret string, region string, bucket string, endpoint string) oss.StorageInterface {
sp := qiniu.New(&qiniu.Config{
AccessID: clientId,
AccessKey: clientSecret,
Region: region,
Bucket: bucket,
Endpoint: endpoint,
})
return sp
}

View File

@@ -30,6 +30,10 @@ func GetStorageProvider(providerType string, clientId string, clientSecret strin
return NewTencentCloudCosStorageProvider(clientId, clientSecret, region, bucket, endpoint)
case "Azure Blob":
return NewAzureBlobStorageProvider(clientId, clientSecret, region, bucket, endpoint)
case "Qiniu Cloud Kodo":
return NewQiniuCloudKodoStorageProvider(clientId, clientSecret, region, bucket, endpoint)
case "Google Cloud Storage":
return NewGoogleCloudStorageProvider(clientId, clientSecret, bucket, endpoint)
}
return nil

View File

@@ -25,5 +25,12 @@ func CasbinToSlice(casbinRule xormadapter.CasbinRule) []string {
casbinRule.V4,
casbinRule.V5,
}
// remove empty strings from end, for update model policy map
for i := len(s) - 1; i >= 0; i-- {
if s[i] != "" {
s = s[:i+1]
break
}
}
return s
}

View File

@@ -3,7 +3,7 @@
"version": "0.1.0",
"private": true,
"dependencies": {
"@ant-design/cssinjs": "^1.8.1",
"@ant-design/cssinjs": "1.16.1",
"@ant-design/icons": "^4.7.0",
"@craco/craco": "^6.4.5",
"@crowdin/cli": "^3.7.10",

View File

@@ -13,7 +13,7 @@
// limitations under the License.
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 AdapterBackend from "./backend/AdapterBackend";
import * as OrganizationBackend from "./backend/OrganizationBackend";
import * as Setting from "./Setting";
@@ -107,8 +107,8 @@ class AdapterEditPage extends React.Component {
{Setting.getLabel(i18next.t("provider:Port"), i18next.t("provider:Port - Tooltip"))} :
</Col>
<Col span={22} >
<Input value={this.state.adapter.port} onChange={e => {
this.updateAdapterField("port", e.target.value);
<InputNumber value={this.state.adapter.port} min={0} max={65535} onChange={value => {
this.updateAdapterField("port", value);
}} />
</Col>
</Row>

View File

@@ -32,7 +32,7 @@ class AdapterListPage extends BaseListPage {
createdTime: moment().format(),
type: "Database",
host: "localhost",
port: "3306",
port: 3306,
user: "root",
password: "123456",
databaseType: "mysql",

View File

@@ -18,7 +18,7 @@ import {Helmet} from "react-helmet";
import {MfaRuleRequired} from "./Setting";
import * as Setting from "./Setting";
import {StyleProvider, legacyLogicalPropertiesTransformer} from "@ant-design/cssinjs";
import {BarsOutlined, DownOutlined, InfoCircleFilled, LogoutOutlined, SettingOutlined} from "@ant-design/icons";
import {AppstoreTwoTone, BarsOutlined, DollarTwoTone, DownOutlined, HomeTwoTone, InfoCircleFilled, LockTwoTone, LogoutOutlined, SafetyCertificateTwoTone, SettingOutlined, SettingTwoTone, WalletTwoTone} from "@ant-design/icons";
import {Alert, Avatar, Button, Card, ConfigProvider, Drawer, Dropdown, FloatButton, Layout, Menu, Result} from "antd";
import {Link, Redirect, Route, Switch, withRouter} from "react-router-dom";
import OrganizationListPage from "./OrganizationListPage";
@@ -91,6 +91,10 @@ import AccountAvatar from "./account/AccountAvatar";
const {Header, Footer, Content} = Layout;
import {setTwoToneColor} from "@ant-design/icons";
setTwoToneColor("rgb(87,52,211)");
class App extends Component {
constructor(props) {
super(props);
@@ -147,58 +151,24 @@ class App extends Component {
});
if (uri === "/") {
this.setState({selectedMenuKey: "/"});
} else if (uri.includes("/organizations") || uri.includes("/trees")) {
this.setState({selectedMenuKey: "/organizations"});
} else if (uri.includes("/users")) {
this.setState({selectedMenuKey: "/users"});
} else if (uri.includes("/groups")) {
this.setState({selectedMenuKey: "/groups"});
} else if (uri.includes("/roles")) {
this.setState({selectedMenuKey: "/roles"});
} else if (uri.includes("/permissions")) {
this.setState({selectedMenuKey: "/permissions"});
} else if (uri.includes("/models")) {
this.setState({selectedMenuKey: "/models"});
} else if (uri.includes("/adapters")) {
this.setState({selectedMenuKey: "/adapters"});
} else if (uri.includes("/enforcers")) {
this.setState({selectedMenuKey: "/enforcers"});
} else if (uri.includes("/providers")) {
this.setState({selectedMenuKey: "/providers"});
} else if (uri.includes("/applications")) {
this.setState({selectedMenuKey: "/applications"});
} else if (uri.includes("/resources")) {
this.setState({selectedMenuKey: "/resources"});
} else if (uri.includes("/records")) {
this.setState({selectedMenuKey: "/records"});
} else if (uri.includes("/tokens")) {
this.setState({selectedMenuKey: "/tokens"});
} else if (uri.includes("/sessions")) {
this.setState({selectedMenuKey: "/sessions"});
} else if (uri.includes("/webhooks")) {
this.setState({selectedMenuKey: "/webhooks"});
} else if (uri.includes("/syncers")) {
this.setState({selectedMenuKey: "/syncers"});
} else if (uri.includes("/certs")) {
this.setState({selectedMenuKey: "/certs"});
} else if (uri.includes("/products")) {
this.setState({selectedMenuKey: "/products"});
} else if (uri.includes("/payments")) {
this.setState({selectedMenuKey: "/payments"});
} else if (uri.includes("/organizations") || uri.includes("/trees") || uri.includes("/users") || uri.includes("/groups")) {
this.setState({selectedMenuKey: "/orgs"});
} else if (uri.includes("/applications") || uri.includes("/providers") || uri.includes("/resources") || uri.includes("/certs")) {
this.setState({selectedMenuKey: "/identity"});
} else if (uri.includes("/roles") || uri.includes("/permissions") || uri.includes("/models") || uri.includes("/adapters") || uri.includes("/enforcers")) {
this.setState({selectedMenuKey: "/auth"});
} else if (uri.includes("/records") || uri.includes("/tokens") || uri.includes("/sessions")) {
this.setState({selectedMenuKey: "/logs"});
} else if (uri.includes("/products") || uri.includes("/payments") || uri.includes("/plans") || uri.includes("/pricings") || uri.includes("/subscriptions")) {
this.setState({selectedMenuKey: "/business"});
} else if (uri.includes("/sysinfo") || uri.includes("/syncers") || uri.includes("/webhooks")) {
this.setState({selectedMenuKey: "/admin"});
} else if (uri.includes("/signup")) {
this.setState({selectedMenuKey: "/signup"});
} else if (uri.includes("/login")) {
this.setState({selectedMenuKey: "/login"});
} else if (uri.includes("/result")) {
this.setState({selectedMenuKey: "/result"});
} else if (uri.includes("/sysinfo")) {
this.setState({selectedMenuKey: "/sysinfo"});
} else if (uri.includes("/subscriptions")) {
this.setState({selectedMenuKey: "/subscriptions"});
} else if (uri.includes("/plans")) {
this.setState({selectedMenuKey: "/plans"});
} else if (uri.includes("/pricings")) {
this.setState({selectedMenuKey: "/pricings"});
} else {
this.setState({selectedMenuKey: -1});
}
@@ -431,7 +401,7 @@ class App extends Component {
return [];
}
res.push(Setting.getItem(<Link to="/">{i18next.t("general:Home")}</Link>, "/"));
res.push(Setting.getItem(<Link to="/">{i18next.t("general:Home")}</Link>, "/", <HomeTwoTone />));
if (Setting.isLocalAdminUser(this.state.account)) {
if (Conf.ShowGithubCorner) {
@@ -442,109 +412,52 @@ class App extends Component {
</a>, "#"));
}
res.push(Setting.getItem(<Link to="/organizations">{i18next.t("general:Organizations")}</Link>,
"/organizations"));
res.push(Setting.getItem(<Link style={{color: "black"}} to="/organizations">{i18next.t("general:User Management")}</Link>, "/orgs", <AppstoreTwoTone />, [
Setting.getItem(<Link to="/organizations">{i18next.t("general:Organizations")}</Link>, "/organizations"),
Setting.getItem(<Link to="/groups">{i18next.t("general:Groups")}</Link>, "/groups"),
Setting.getItem(<Link to="/users">{i18next.t("general:Users")}</Link>, "/users"),
]));
res.push(Setting.getItem(<Link to="/groups">{i18next.t("general:Groups")}</Link>,
"/groups"));
res.push(Setting.getItem(<Link style={{color: "black"}} to="/applications">{i18next.t("general:Identity")}</Link>, "/identity", <LockTwoTone />, [
Setting.getItem(<Link to="/applications">{i18next.t("general:Applications")}</Link>, "/applications"),
Setting.getItem(<Link to="/providers">{i18next.t("general:Providers")}</Link>, "/providers"),
Setting.getItem(<Link to="/resources">{i18next.t("general:Resources")}</Link>, "/resources"),
Setting.getItem(<Link to="/certs">{i18next.t("general:Certs")}</Link>, "/certs"),
]));
res.push(Setting.getItem(<Link to="/users">{i18next.t("general:Users")}</Link>,
"/users"
));
res.push(Setting.getItem(<Link style={{color: "black"}} to="/roles">{i18next.t("general:Authorization")}</Link>, "/auth", <SafetyCertificateTwoTone />, [
Setting.getItem(<Link to="/roles">{i18next.t("general:Roles")}</Link>, "/roles"),
Setting.getItem(<Link to="/permissions">{i18next.t("general:Permissions")}</Link>, "/permissions"),
Setting.getItem(<Link to="/models">{i18next.t("general:Models")}</Link>, "/models"),
Setting.getItem(<Link to="/adapters">{i18next.t("general:Adapters")}</Link>, "/adapters"),
Setting.getItem(<Link to="/enforcers">{i18next.t("general:Enforcers")}</Link>, "/enforcers"),
].filter(item => {
if (!Setting.isLocalAdminUser(this.state.account) && ["/models", "/adapters", "/enforcers"].includes(item.key)) {
return false;
} else {
return true;
}
})));
res.push(Setting.getItem(<Link to="/roles">{i18next.t("general:Roles")}</Link>,
"/roles"
));
res.push(Setting.getItem(<Link style={{color: "black"}} to="/records">{i18next.t("general:Logging & Auditing")}</Link>, "/logs", <WalletTwoTone />, [
Setting.getItem(<Link to="/records">{i18next.t("general:Records")}</Link>, "/records"),
Setting.getItem(<Link to="/tokens">{i18next.t("general:Tokens")}</Link>, "/tokens"),
Setting.getItem(<Link to="/sessions">{i18next.t("general:Sessions")}</Link>, "/sessions"),
]));
res.push(Setting.getItem(<Link to="/permissions">{i18next.t("general:Permissions")}</Link>,
"/permissions"
));
}
res.push(Setting.getItem(<Link style={{color: "black"}} to="/products">{i18next.t("general:Business & Payments")}</Link>, "/business", <DollarTwoTone />, [
Setting.getItem(<Link to="/products">{i18next.t("general:Products")}</Link>, "/products"),
Setting.getItem(<Link to="/payments">{i18next.t("general:Payments")}</Link>, "/payments"),
Setting.getItem(<Link to="/plans">{i18next.t("general:Plans")}</Link>, "/plans"),
Setting.getItem(<Link to="/pricings">{i18next.t("general:Pricings")}</Link>, "/pricings"),
Setting.getItem(<Link to="/subscriptions">{i18next.t("general:Subscriptions")}</Link>, "/subscriptions"),
]));
if (Setting.isLocalAdminUser(this.state.account)) {
res.push(Setting.getItem(<Link to="/models">{i18next.t("general:Models")}</Link>,
"/models"
));
res.push(Setting.getItem(<Link to="/adapters">{i18next.t("general:Adapters")}</Link>,
"/adapters"
));
res.push(Setting.getItem(<Link to="/enforcers">{i18next.t("general:Enforcers")}</Link>,
"/enforcers"
));
}
if (Setting.isLocalAdminUser(this.state.account)) {
res.push(Setting.getItem(<Link to="/applications">{i18next.t("general:Applications")}</Link>,
"/applications"
));
res.push(Setting.getItem(<Link to="/providers">{i18next.t("general:Providers")}</Link>,
"/providers"
));
res.push(Setting.getItem(<Link to="/resources">{i18next.t("general:Resources")}</Link>,
"/resources"
));
res.push(Setting.getItem(<Link to="/records">{i18next.t("general:Records")}</Link>,
"/records"
));
res.push(Setting.getItem(<Link to="/plans">{i18next.t("general:Plans")}</Link>,
"/plans"
));
res.push(Setting.getItem(<Link to="/pricings">{i18next.t("general:Pricings")}</Link>,
"/pricings"
));
res.push(Setting.getItem(<Link to="/subscriptions">{i18next.t("general:Subscriptions")}</Link>,
"/subscriptions"
));
}
if (Setting.isLocalAdminUser(this.state.account)) {
res.push(Setting.getItem(<Link to="/tokens">{i18next.t("general:Tokens")}</Link>,
"/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>,
"/webhooks"
));
res.push(Setting.getItem(<Link to="/syncers">{i18next.t("general:Syncers")}</Link>,
"/syncers"
));
res.push(Setting.getItem(<Link to="/certs">{i18next.t("general:Certs")}</Link>,
"/certs"
));
if (Conf.EnableExtraPages) {
res.push(Setting.getItem(<Link to="/products">{i18next.t("general:Products")}</Link>,
"/products"
));
res.push(Setting.getItem(<Link to="/payments">{i18next.t("general:Payments")}</Link>,
"/payments"
));
}
}
if (Setting.isAdminUser(this.state.account)) {
res.push(Setting.getItem(<Link to="/sysinfo">{i18next.t("general:System Info")}</Link>,
"/sysinfo"
));
res.push(Setting.getItem(<a target="_blank" rel="noreferrer"
href={Setting.isLocalhost() ? `${Setting.ServerUrl}/swagger` : "/swagger"}>{i18next.t("general:Swagger")}</a>,
"/swagger"
));
res.push(Setting.getItem(<Link style={{color: "black"}} to="/sysinfo">{i18next.t("general:Admin")}</Link>, "/admin", <SettingTwoTone />, [
Setting.getItem(<Link to="/sysinfo">{i18next.t("general:System Info")}</Link>, "/sysinfo"),
Setting.getItem(<Link to="/syncers">{i18next.t("general:Syncers")}</Link>, "/syncers"),
Setting.getItem(<Link to="/webhooks">{i18next.t("general:Webhooks")}</Link>, "/webhooks"),
Setting.getItem(<a target="_blank" rel="noreferrer" href={Setting.isLocalhost() ? `${Setting.ServerUrl}/swagger` : "/swagger"}>{i18next.t("general:Swagger")}</a>, "/swagger")]));
}
return res;

View File

@@ -20,8 +20,6 @@ export const IsDemoMode = false;
export const ForceLanguage = "";
export const DefaultLanguage = "en";
export const EnableExtraPages = true;
export const InitThemeAlgorithm = true;
export const ThemeDefault = {
themeType: "default",

View File

@@ -221,6 +221,7 @@ class GroupTreePage extends React.Component {
onChange={(value) => {
this.setState({
organizationName: value,
groupName: "",
});
this.props.history.push(`/trees/${value}`);
}}

View File

@@ -191,8 +191,8 @@ class LdapSyncPage extends React.Component {
},
{
title: i18next.t("general:Phone"),
dataIndex: "phone",
key: "phone",
dataIndex: "mobile",
key: "mobile",
sorter: (a, b) => a.phone.localeCompare(b.phone),
},
{

View File

@@ -163,7 +163,7 @@ class PaymentEditPage extends React.Component {
{Setting.getLabel(i18next.t("general:Organization"), i18next.t("general:Organization - Tooltip"))} :
</Col>
<Col span={22} >
<Input disabled={true} value={this.state.payment.organization} onChange={e => {
<Input disabled={true} value={this.state.payment.owner} onChange={e => {
// this.updatePaymentField('organization', e.target.value);
}} />
</Col>

View File

@@ -115,6 +115,26 @@ class PaymentResultPage extends React.Component {
/>
</div>
);
} else if (payment.state === "Canceled") {
return (
<div>
{
Setting.renderHelmet(payment)
}
<Result
status="warning"
title={`${i18next.t("payment:The payment has been canceled")}: ${payment.productDisplayName}, ${i18next.t("payment:the current state is")}: ${payment.state}`}
subTitle={i18next.t("payment:Please click the below button to return to the original website")}
extra={[
<Button type="primary" key="returnUrl" onClick={() => {
this.goToPaymentUrl(payment);
}}>
{i18next.t("payment:Return to Website")}
</Button>,
]}
/>
</div>
);
} else {
return (
<div>
@@ -124,7 +144,7 @@ class PaymentResultPage extends React.Component {
<Result
status="error"
title={`${i18next.t("payment:The payment has failed")}: ${payment.productDisplayName}, ${i18next.t("payment:the current state is")}: ${payment.state}`}
subTitle={i18next.t("payment:Please click the below button to return to the original website")}
subTitle={`${i18next.t("payment:Failed reason")}: ${payment.message}`}
extra={[
<Button type="primary" key="returnUrl" onClick={() => {
this.goToPaymentUrl(payment);

View File

@@ -134,10 +134,14 @@ class ProviderEditPage extends React.Component {
case "Email":
return Setting.getLabel(i18next.t("signup:Username"), i18next.t("signup:Username - Tooltip"));
case "SMS":
if (provider.type === "Volc Engine SMS") {
if (provider.type === "Volc Engine SMS" || provider.type === "Amazon SNS" || provider.type === "Baidu Cloud SMS") {
return Setting.getLabel(i18next.t("provider:Access key"), i18next.t("provider:Access key - Tooltip"));
} else if (provider.type === "Huawei Cloud SMS") {
return Setting.getLabel(i18next.t("provider:App key"), i18next.t("provider:App key - Tooltip"));
} else if (provider.type === "UCloud SMS") {
return Setting.getLabel(i18next.t("provider:Public key"), i18next.t("provider:Public key - Tooltip"));
} else if (provider.type === "Msg91 SMS" || provider.type === "Infobip SMS") {
return Setting.getLabel(i18next.t("provider:Sender Id"), i18next.t("provider:Sender Id - Tooltip"));
} else {
return Setting.getLabel(i18next.t("provider:Client ID"), i18next.t("provider:Client ID - Tooltip"));
}
@@ -157,10 +161,16 @@ class ProviderEditPage extends React.Component {
case "Email":
return Setting.getLabel(i18next.t("general:Password"), i18next.t("general:Password - Tooltip"));
case "SMS":
if (provider.type === "Volc Engine SMS") {
if (provider.type === "Volc Engine SMS" || provider.type === "Amazon SNS" || provider.type === "Baidu Cloud SMS") {
return Setting.getLabel(i18next.t("provider:Secret access key"), i18next.t("provider:Secret access key - Tooltip"));
} else if (provider.type === "Huawei Cloud SMS") {
return Setting.getLabel(i18next.t("provider:App secret"), i18next.t("provider:AppSecret - Tooltip"));
} else if (provider.type === "UCloud SMS") {
return Setting.getLabel(i18next.t("provider:Private Key"), i18next.t("provider:Private Key - Tooltip"));
} else if (provider.type === "Msg91 SMS") {
return Setting.getLabel(i18next.t("provider:Auth Key"), i18next.t("provider:Auth Key - Tooltip"));
} else if (provider.type === "Infobip SMS") {
return Setting.getLabel(i18next.t("provider:Api Key"), i18next.t("provider:Api Key - Tooltip"));
} else {
return Setting.getLabel(i18next.t("provider:Client secret"), i18next.t("provider:Client secret - Tooltip"));
}
@@ -234,7 +244,7 @@ class ProviderEditPage extends React.Component {
tooltip = i18next.t("provider:Agent ID - Tooltip");
}
} else if (provider.category === "SMS") {
if (provider.type === "Twilio SMS") {
if (provider.type === "Twilio SMS" || provider.type === "Azure ACS") {
text = i18next.t("provider:Sender number");
tooltip = i18next.t("provider:Sender number - Tooltip");
} else if (provider.type === "Tencent Cloud SMS") {
@@ -246,6 +256,18 @@ class ProviderEditPage extends React.Component {
} else if (provider.type === "Huawei Cloud SMS") {
text = i18next.t("provider:Channel No.");
tooltip = i18next.t("provider:Channel No. - Tooltip");
} else if (provider.type === "Amazon SNS") {
text = i18next.t("provider:Region");
tooltip = i18next.t("provider:Region - Tooltip");
} else if (provider.type === "Baidu Cloud SMS") {
text = i18next.t("provider:Endpoint");
tooltip = i18next.t("provider:Endpoint - Tooltip");
} else if (provider.type === "Infobip SMS") {
text = i18next.t("provider:Base URL");
tooltip = i18next.t("provider:Base URL - Tooltip");
} else if (provider.type === "UCloud SMS") {
text = i18next.t("provider:Project Id");
tooltip = i18next.t("provider:Project Id - Tooltip");
}
} else if (provider.category === "Email") {
if (provider.type === "SUBMAIL") {
@@ -334,7 +356,7 @@ class ProviderEditPage extends React.Component {
<Select virtual={false} style={{width: "100%"}} value={this.state.provider.category} onChange={(value => {
this.updateProviderField("category", value);
if (value === "OAuth") {
this.updateProviderField("type", "GitHub");
this.updateProviderField("type", "Google");
} else if (value === "Email") {
this.updateProviderField("type", "Default");
this.updateProviderField("host", "smtp.example.com");
@@ -344,12 +366,12 @@ class ProviderEditPage extends React.Component {
this.updateProviderField("content", "You have requested a verification code at Casdoor. Here is your code: %s, please enter in 5 minutes.");
this.updateProviderField("receiver", this.props.account.email);
} else if (value === "SMS") {
this.updateProviderField("type", "Aliyun SMS");
this.updateProviderField("type", "Twilio SMS");
} else if (value === "Storage") {
this.updateProviderField("type", "Local File System");
this.updateProviderField("type", "AWS S3");
this.updateProviderField("domain", Setting.getFullServerUrl());
} else if (value === "SAML") {
this.updateProviderField("type", "Aliyun IDaaS");
this.updateProviderField("type", "Keycloak");
} else if (value === "Payment") {
this.updateProviderField("type", "PayPal");
} else if (value === "Captcha") {
@@ -384,12 +406,16 @@ class ProviderEditPage extends React.Component {
this.updateProviderField("type", value);
if (value === "Local File System") {
this.updateProviderField("domain", Setting.getFullServerUrl());
}
if (value === "Custom") {
} else if (value === "Custom") {
this.updateProviderField("customAuthUrl", "https://door.casdoor.com/login/oauth/authorize");
this.updateProviderField("scopes", "openid profile email");
this.updateProviderField("customTokenUrl", "https://door.casdoor.com/api/login/oauth/access_token");
this.updateProviderField("customUserInfoUrl", "https://door.casdoor.com/api/userinfo");
} else if (value === "Custom HTTP SMS") {
this.updateProviderField("endpoint", "https://door.casdoor.com/api/get-account");
this.updateProviderField("method", "GET");
this.updateProviderField("clientId", "param1");
this.updateProviderField("title", "");
}
})}>
{
@@ -525,30 +551,33 @@ class ProviderEditPage extends React.Component {
)
}
{
(this.state.provider.category === "Captcha" && this.state.provider.type === "Default") || (this.state.provider.category === "Web3") || (this.state.provider.category === "Storage" && this.state.provider.type === "Local File System") ? null : (
<React.Fragment>
<Row style={{marginTop: "20px"}} >
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
{this.getClientIdLabel(this.state.provider)} :
</Col>
<Col span={22} >
<Input value={this.state.provider.clientId} onChange={e => {
this.updateProviderField("clientId", e.target.value);
}} />
</Col>
</Row>
<Row style={{marginTop: "20px"}} >
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
{this.getClientSecretLabel(this.state.provider)} :
</Col>
<Col span={22} >
<Input value={this.state.provider.clientSecret} onChange={e => {
this.updateProviderField("clientSecret", e.target.value);
}} />
</Col>
</Row>
</React.Fragment>
)
(this.state.provider.category === "Captcha" && this.state.provider.type === "Default") ||
(this.state.provider.category === "SMS" && this.state.provider.type === "Custom HTTP SMS") ||
(this.state.provider.category === "Web3") ||
(this.state.provider.category === "Storage" && this.state.provider.type === "Local File System") ? null : (
<React.Fragment>
<Row style={{marginTop: "20px"}} >
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
{this.getClientIdLabel(this.state.provider)} :
</Col>
<Col span={22} >
<Input value={this.state.provider.clientId} onChange={e => {
this.updateProviderField("clientId", e.target.value);
}} />
</Col>
</Row>
<Row style={{marginTop: "20px"}} >
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
{this.getClientSecretLabel(this.state.provider)} :
</Col>
<Col span={22} >
<Input value={this.state.provider.clientSecret} onChange={e => {
this.updateProviderField("clientSecret", e.target.value);
}} />
</Col>
</Row>
</React.Fragment>
)
}
{
this.state.provider.category !== "Email" && this.state.provider.type !== "WeChat" && this.state.provider.type !== "Aliyun Captcha" && this.state.provider.type !== "WeChat Pay" ? null : (
@@ -601,14 +630,14 @@ class ProviderEditPage extends React.Component {
{Setting.getLabel(i18next.t("provider:Domain"), i18next.t("provider:Domain - Tooltip"))} :
</Col>
<Col span={22} >
<Input value={this.state.provider.domain} onChange={e => {
<Input prefix={<LinkOutlined />} value={this.state.provider.domain} onChange={e => {
this.updateProviderField("domain", e.target.value);
}} />
</Col>
</Row>
)
}
{this.state.provider.category === "Storage" ? (
{this.state.provider.category === "Storage" || this.state.provider.type === "Custom HTTP SMS" ? (
<div>
{["Local File System"].includes(this.state.provider.type) ? null : (
<Row style={{marginTop: "20px"}} >
@@ -616,25 +645,25 @@ class ProviderEditPage extends React.Component {
{Setting.getLabel(i18next.t("provider:Endpoint"), i18next.t("provider:Region endpoint for Internet"))} :
</Col>
<Col span={22} >
<Input value={this.state.provider.endpoint} onChange={e => {
<Input prefix={<LinkOutlined />} value={this.state.provider.endpoint} onChange={e => {
this.updateProviderField("endpoint", e.target.value);
}} />
</Col>
</Row>
)}
{["Local File System", "MinIO", "Tencent Cloud COS"].includes(this.state.provider.type) ? null : (
{["Custom HTTP SMS", "Local File System", "MinIO", "Tencent Cloud COS", "Google Cloud Storage", "Qiniu Cloud Kodo"].includes(this.state.provider.type) ? null : (
<Row style={{marginTop: "20px"}} >
<Col style={{marginTop: "5px"}} span={2}>
{Setting.getLabel(i18next.t("provider:Endpoint (Intranet)"), i18next.t("provider:Region endpoint for Intranet"))} :
</Col>
<Col span={22} >
<Input value={this.state.provider.intranetEndpoint} onChange={e => {
<Input prefix={<LinkOutlined />} value={this.state.provider.intranetEndpoint} onChange={e => {
this.updateProviderField("intranetEndpoint", e.target.value);
}} />
</Col>
</Row>
)}
{["Local File System"].includes(this.state.provider.type) ? null : (
{["Custom HTTP SMS", "Local File System"].includes(this.state.provider.type) ? null : (
<Row style={{marginTop: "20px"}} >
<Col style={{marginTop: "5px"}} span={2}>
{Setting.getLabel(i18next.t("provider:Bucket"), i18next.t("provider:Bucket - Tooltip"))} :
@@ -646,29 +675,31 @@ class ProviderEditPage extends React.Component {
</Col>
</Row>
)}
<Row style={{marginTop: "20px"}} >
<Col style={{marginTop: "5px"}} span={2}>
{Setting.getLabel(i18next.t("provider:Path prefix"), i18next.t("provider:Path prefix - Tooltip"))} :
</Col>
<Col span={22} >
<Input value={this.state.provider.pathPrefix} onChange={e => {
this.updateProviderField("pathPrefix", e.target.value);
}} />
</Col>
</Row>
{["MinIO"].includes(this.state.provider.type) ? null : (
{["Custom HTTP SMS"].includes(this.state.provider.type) ? null : (
<Row style={{marginTop: "20px"}} >
<Col style={{marginTop: "5px"}} span={2}>
{Setting.getLabel(i18next.t("provider:Path prefix"), i18next.t("provider:Path prefix - Tooltip"))} :
</Col>
<Col span={22} >
<Input value={this.state.provider.pathPrefix} onChange={e => {
this.updateProviderField("pathPrefix", e.target.value);
}} />
</Col>
</Row>
)}
{["Custom HTTP SMS", "MinIO", "Google Cloud Storage", "Qiniu Cloud Kodo"].includes(this.state.provider.type) ? null : (
<Row style={{marginTop: "20px"}} >
<Col style={{marginTop: "5px"}} span={2}>
{Setting.getLabel(i18next.t("provider:Domain"), i18next.t("provider:Domain - Tooltip"))} :
</Col>
<Col span={22} >
<Input value={this.state.provider.domain} disabled={this.state.provider.type === "Local File System"} onChange={e => {
<Input prefix={<LinkOutlined />} value={this.state.provider.domain} disabled={this.state.provider.type === "Local File System"} onChange={e => {
this.updateProviderField("domain", e.target.value);
}} />
</Col>
</Row>
)}
{["AWS S3", "Tencent Cloud COS"].includes(this.state.provider.type) ? (
{["AWS S3", "Tencent Cloud COS", "Qiniu Cloud Kodo"].includes(this.state.provider.type) ? (
<Row style={{marginTop: "20px"}} >
<Col style={{marginTop: "5px"}} span={2}>
{Setting.getLabel(i18next.t("provider:Region ID"), i18next.t("provider:Region ID - Tooltip"))} :
@@ -682,6 +713,49 @@ class ProviderEditPage extends React.Component {
) : null}
</div>
) : null}
{
this.state.provider.type !== "Custom HTTP SMS" ? null : (
<React.Fragment>
<Row style={{marginTop: "20px"}} >
<Col style={{marginTop: "5px"}} span={2}>
{Setting.getLabel(i18next.t("general:Method"), i18next.t("provider:Method - Tooltip"))} :
</Col>
<Col span={22} >
<Select virtual={false} style={{width: "100%"}} value={this.state.provider.method} onChange={value => {
this.updateProviderField("method", value);
}}>
{
[
{id: "GET", name: "GET"},
{id: "POST", name: "POST"},
].map((method, index) => <Option key={index} value={method.id}>{method.name}</Option>)
}
</Select>
</Col>
</Row>
<Row style={{marginTop: "20px"}} >
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
{Setting.getLabel(i18next.t("provider:Parameter name"), i18next.t("provider:Parameter name - Tooltip"))} :
</Col>
<Col span={22} >
<Input value={this.state.provider.clientId} onChange={e => {
this.updateProviderField("clientId", e.target.value);
}} />
</Col>
</Row>
<Row style={{marginTop: "20px"}} >
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
{Setting.getLabel(i18next.t("provider:Content"), i18next.t("provider:Content - Tooltip"))} :
</Col>
<Col span={22} >
<TextArea autoSize={{minRows: 3, maxRows: 100}} value={this.state.provider.title} onChange={e => {
this.updateProviderField("title", e.target.value);
}} />
</Col>
</Row>
</React.Fragment>
)
}
{this.getAppIdRow(this.state.provider)}
{
this.state.provider.category === "Email" ? (
@@ -757,7 +831,7 @@ class ProviderEditPage extends React.Component {
</React.Fragment>
) : this.state.provider.category === "SMS" ? (
<React.Fragment>
{this.state.provider.type === "Twilio SMS" ?
{["Custom HTTP SMS", "Twilio SMS", "Amazon SNS", "Azure ACS", "Msg91 SMS", "Infobip SMS"].includes(this.state.provider.type) ?
null :
(<Row style={{marginTop: "20px"}} >
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
@@ -771,41 +845,50 @@ class ProviderEditPage extends React.Component {
</Row>
)
}
<Row style={{marginTop: "20px"}} >
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
{Setting.getLabel(i18next.t("provider:Template code"), i18next.t("provider:Template code - Tooltip"))} :
</Col>
<Col span={22} >
<Input value={this.state.provider.templateCode} onChange={e => {
this.updateProviderField("templateCode", e.target.value);
}} />
</Col>
</Row>
{["Custom HTTP SMS", "Infobip SMS"].includes(this.state.provider.type) ?
null :
(<Row style={{marginTop: "20px"}} >
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
{Setting.getLabel(i18next.t("provider:Template code"), i18next.t("provider:Template code - Tooltip"))} :
</Col>
<Col span={22} >
<Input value={this.state.provider.templateCode} onChange={e => {
this.updateProviderField("templateCode", e.target.value);
}} />
</Col>
</Row>
)
}
<Row style={{marginTop: "20px"}} >
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
{Setting.getLabel(i18next.t("provider:SMS Test"), i18next.t("provider:SMS Test - Tooltip"))} :
</Col>
<Col span={4} >
<Input.Group compact>
<CountryCodeSelect
style={{width: "30%"}}
value={this.state.provider.content}
onChange={(value) => {
this.updateProviderField("content", value);
}}
countryCodes={this.props.account.organization.countryCodes}
/>
<Input value={this.state.provider.receiver}
style={{width: "70%"}}
placeholder = {i18next.t("user:Input your phone number")}
onChange={e => {
this.updateProviderField("receiver", e.target.value);
}} />
</Input.Group>
</Col>
{["Custom HTTP SMS"].includes(this.state.provider.type) ?
null :
(
<Col span={4} >
<Input.Group compact>
<CountryCodeSelect
style={{width: "30%"}}
value={this.state.provider.content}
onChange={(value) => {
this.updateProviderField("content", value);
}}
countryCodes={this.props.account.organization.countryCodes}
/>
<Input value={this.state.provider.receiver}
style={{width: "70%"}}
placeholder = {i18next.t("user:Input your phone number")}
onChange={e => {
this.updateProviderField("receiver", e.target.value);
}} />
</Input.Group>
</Col>
)
}
<Col span={2} >
<Button style={{marginLeft: "10px", marginBottom: "5px"}} type="primary"
disabled={!Setting.isValidPhone(this.state.provider.receiver)}
disabled={!Setting.isValidPhone(this.state.provider.receiver) && (this.state.provider.type !== "Custom HTTP SMS" || this.state.provider.endpoint === "")}
onClick={() => ProviderEditTestSms.sendTestSms(this.state.provider, "+" + Setting.getCountryCode(this.state.provider.content) + this.state.provider.receiver)} >
{i18next.t("provider:Send Testing SMS")}
</Button>

View File

@@ -37,7 +37,7 @@ class ProviderListPage extends BaseListPage {
newProvider() {
const randomName = Setting.getRandomName();
const owner = Setting.isDefaultOrganizationSelected(this.props.account) ? this.state.owner : Setting.getRequestOrganization();
const owner = Setting.isDefaultOrganizationSelected(this.props.account) ? this.state.owner : Setting.getRequestOrganization(this.props.account);
return {
owner: owner,
name: `provider_${randomName}`,

View File

@@ -85,10 +85,30 @@ export const OtherProviderInfo = {
logo: `${StaticBaseUrl}/img/social_aliyun.png`,
url: "https://aliyun.com/product/sms",
},
"Amazon SNS": {
logo: `${StaticBaseUrl}/img/social_aws.png`,
url: "https://aws.amazon.com/cn/sns/",
},
"Azure ACS": {
logo: `${StaticBaseUrl}/img/social_azure.png`,
url: "https://azure.microsoft.com/en-us/products/communication-services",
},
"Custom HTTP SMS": {
logo: `${StaticBaseUrl}/img/email_default.png`,
url: "https://casdoor.org/docs/provider/sms/overview",
},
"Infobip SMS": {
logo: `${StaticBaseUrl}/img/social_infobip.png`,
url: "https://portal.infobip.com/homepage/",
},
"Tencent Cloud SMS": {
logo: `${StaticBaseUrl}/img/social_tencent_cloud.jpg`,
url: "https://cloud.tencent.com/product/sms",
},
"Baidu Cloud SMS": {
logo: `${StaticBaseUrl}/img/social_baidu_cloud.png`,
url: "https://cloud.baidu.com/product/sms.html",
},
"Volc Engine SMS": {
logo: `${StaticBaseUrl}/img/social_volc_engine.jpg`,
url: "https://www.volcengine.com/products/cloud-sms",
@@ -97,6 +117,10 @@ export const OtherProviderInfo = {
logo: `${StaticBaseUrl}/img/social_huawei.png`,
url: "https://www.huaweicloud.com/product/msgsms.html",
},
"UCloud SMS": {
logo: `${StaticBaseUrl}/img/social_ucloud.png`,
url: "https://www.ucloud.cn/site/product/usms.html",
},
"Twilio SMS": {
logo: `${StaticBaseUrl}/img/social_twilio.svg`,
url: "https://www.twilio.com/messaging",
@@ -109,6 +133,10 @@ export const OtherProviderInfo = {
logo: `${StaticBaseUrl}/img/social_submail.svg`,
url: "https://www.mysubmail.com",
},
"Msg91 SMS": {
logo: `${StaticBaseUrl}/img/social_msg91.ico`,
url: "https://control.msg91.com/app/",
},
"Mock SMS": {
logo: `${StaticBaseUrl}/img/social_default.png`,
url: "",
@@ -153,6 +181,14 @@ export const OtherProviderInfo = {
logo: `${StaticBaseUrl}/img/social_azure.png`,
url: "https://azure.microsoft.com/en-us/services/storage/blobs/",
},
"Qiniu Cloud Kodo": {
logo: `${StaticBaseUrl}/img/social_qiniu_cloud.png`,
url: "https://www.qiniu.com/solutions/storage",
},
"Google Cloud Storage": {
logo: `${StaticBaseUrl}/img/social_google_cloud.png`,
url: "https://cloud.google.com/storage",
},
},
SAML: {
"Aliyun IDaaS": {
@@ -853,13 +889,20 @@ export function getProviderTypeOptions(category) {
} else if (category === "SMS") {
return (
[
{id: "Aliyun SMS", name: "Aliyun SMS"},
{id: "Aliyun SMS", name: "Alibaba Cloud SMS"},
{id: "Amazon SNS", name: "Amazon SNS"},
{id: "Azure ACS", name: "Azure ACS"},
{id: "Custom HTTP SMS", name: "Custom HTTP SMS"},
{id: "Infobip SMS", name: "Infobip SMS"},
{id: "Tencent Cloud SMS", name: "Tencent Cloud SMS"},
{id: "Baidu Cloud SMS", name: "Baidu Cloud SMS"},
{id: "Volc Engine SMS", name: "Volc Engine SMS"},
{id: "Huawei Cloud SMS", name: "Huawei Cloud SMS"},
{id: "UCloud SMS", name: "UCloud SMS"},
{id: "Twilio SMS", name: "Twilio SMS"},
{id: "SmsBao SMS", name: "SmsBao SMS"},
{id: "SUBMAIL SMS", name: "SUBMAIL SMS"},
{id: "Msg91 SMS", name: "Msg91 SMS"},
]
);
} else if (category === "Storage") {
@@ -871,6 +914,8 @@ export function getProviderTypeOptions(category) {
{id: "Aliyun OSS", name: "Aliyun OSS"},
{id: "Tencent Cloud COS", name: "Tencent Cloud COS"},
{id: "Azure Blob", name: "Azure Blob"},
{id: "Qiniu Cloud Kodo", name: "Qiniu Cloud Kodo"},
{id: "Google Cloud Storage", name: "Google Cloud Storage"},
]
);
} else if (category === "SAML") {
@@ -1043,13 +1088,7 @@ export function getLabel(text, tooltip) {
}
export function getItem(label, key, icon, children, type) {
return {
key,
icon,
children,
label,
type,
};
return {label: label, key: key, icon: icon, children: children, type: type};
}
export function getOption(label, value) {
@@ -1179,11 +1218,11 @@ export function isDefaultOrganizationSelected(account) {
const BuiltInObjects = [
"api-enforcer-built-in",
"permission-enforcer-built-in",
"user-enforcer-built-in",
"api-model-built-in",
"permission-model-built-in",
"user-model-built-in",
"api-adapter-built-in",
"permission-adapter-built-in",
"user-adapter-built-in",
];
export function builtInObject(obj) {

View File

@@ -133,13 +133,25 @@ class UserEditPage extends React.Component {
this.setState({
application: res.data,
isGroupsVisible: res.data?.organizationObj.accountItems?.some((item) => item.name === "Groups" && item.visible),
});
});
}
getUserOrganization() {
return this.state.organizations.filter(organization => organization.name === this.state.user.owner)[0];
}
isGroupsVisible() {
const organization = this.getUserOrganization();
if (!organization) {
return false;
} else {
return organization.accountItems?.some((item) => item.name === "Groups" && item.visible);
}
}
getGroups(organizationName) {
if (this.state.isGroupsVisible) {
if (this.isGroupsVisible()) {
GroupBackend.getGroups(organizationName)
.then((res) => {
if (res.status === "ok") {
@@ -319,7 +331,7 @@ class UserEditPage extends React.Component {
})}
>
{
this.state.groups?.map((group) => <Option key={group.name} value={group.name}>
this.state.groups?.map((group) => <Option key={group.name} value={`${group.owner}/${group.name}`}>
<Space>
{group.type === "Physical" ? <UsergroupAddOutlined /> : <HolderOutlined />}
{group.displayName}
@@ -401,7 +413,7 @@ class UserEditPage extends React.Component {
{Setting.getLabel(i18next.t("general:Password"), i18next.t("general:Password - Tooltip"))} :
</Col>
<Col span={22} >
<PasswordModal user={this.state.user} organization={this.state.application?.organizationObj} account={this.props.account} disabled={disabled} />
<PasswordModal user={this.state.user} organization={this.getUserOrganization()} account={this.props.account} disabled={disabled} />
</Col>
</Row>
);
@@ -442,7 +454,7 @@ class UserEditPage extends React.Component {
onChange={(value) => {
this.updateUserField("countryCode", value);
}}
countryCodes={this.state.application?.organizationObj.countryCodes}
countryCodes={this.getUserOrganization()?.countryCodes}
/>
<Input value={this.state.user.phone}
style={{width: "70%"}}
@@ -599,10 +611,10 @@ class UserEditPage extends React.Component {
</Col>
<Col span={22} >
{
this.state.application?.organizationObj.tags?.length > 0 ? (
this.getUserOrganization()?.tags?.length > 0 ? (
<Select virtual={false} style={{width: "100%"}} value={this.state.user.tag}
onChange={(value => {this.updateUserField("tag", value);})}
options={this.state.application.organizationObj.tags?.map((tag) => {
options={this.getUserOrganization()?.tags?.map((tag) => {
const tokens = tag.split("|");
const value = tokens[0];
const displayValue = Setting.getLanguage() !== "zh" ? tokens[0] : tokens[1];
@@ -888,7 +900,7 @@ class UserEditPage extends React.Component {
{Setting.getLabel(i18next.t("mfa:Multi-factor authentication"), i18next.t("mfa:Multi-factor authentication - Tooltip "))} :
</Col>
<Col span={22} >
<Card title={i18next.t("mfa:Multi-factor methods")}
<Card size="small" title={i18next.t("mfa:Multi-factor methods")}
extra={this.state.multiFactorAuths?.some(mfaProps => mfaProps.enabled) ?
<PopconfirmModal
text={i18next.t("general:Disable")}
@@ -1008,7 +1020,7 @@ class UserEditPage extends React.Component {
</div>
} style={(Setting.isMobile()) ? {margin: "5px"} : {}} type="inner">
{
this.state.application?.organizationObj.accountItems?.map(accountItem => {
this.getUserOrganization()?.accountItems?.map(accountItem => {
return (
<React.Fragment key={accountItem.name}>
{

View File

@@ -76,7 +76,7 @@ class UserListPage extends BaseListPage {
phone: Setting.getRandomNumber(),
countryCode: this.state.organization.countryCodes?.length > 0 ? this.state.organization.countryCodes[0] : "",
address: [],
groups: this.props.groupName ? [this.props.groupName] : [],
groups: this.props.groupName ? [`${owner}/${this.props.groupName}`] : [],
affiliation: "Example Inc.",
tag: "staff",
region: "",

View File

@@ -46,7 +46,7 @@ import {getEvent} from "./Util";
import {Modal} from "antd";
function getSigninButton(provider) {
const text = i18next.t("login:Sign in with {type}").replace("{type}", provider.type);
const text = i18next.t("login:Sign in with {type}").replace("{type}", provider.displayName !== "" ? provider.displayName : provider.type);
if (provider.type === "GitHub") {
return <GithubLoginButton text={text} align={"center"} />;
} else if (provider.type === "Google") {

View File

@@ -165,16 +165,19 @@
"Adapter - Tooltip": "Tabellenname des Policy Stores",
"Adapters": "Adapter",
"Add": "Hinzufügen",
"Admin": "Admin",
"Affiliation URL": "Affiliation-URL",
"Affiliation URL - Tooltip": "Die Homepage-URL für die Zugehörigkeit",
"Application": "Applikation",
"Application - Tooltip": "Application - Tooltip",
"Applications": "Anwendungen",
"Applications that require authentication": "Anwendungen, die eine Authentifizierung erfordern",
"Authorization": "Authorization",
"Avatar": "Avatar",
"Avatar - Tooltip": "Öffentliches Avatarbild für den Benutzer",
"Back": "Back",
"Back Home": "Zurück nach Hause",
"Business & Payments": "Business & Payments",
"Cancel": "Abbrechen",
"Captcha": "Captcha",
"Cert": "Zertifikat",
@@ -226,6 +229,7 @@
"Home - Tooltip": "Homepage der Anwendung",
"ID": "ID",
"ID - Tooltip": "Einzigartiger Zufallsstring",
"Identity": "Identity",
"Is enabled": "Ist aktiviert",
"Is enabled - Tooltip": "Festlegen, ob es verwendet werden kann",
"LDAPs": "LDAPs",
@@ -234,6 +238,7 @@
"Languages - Tooltip": "Verfügbare Sprachen",
"Last name": "Nachname",
"Later": "Later",
"Logging & Auditing": "Logging & Auditing",
"Logo": "Logo",
"Logo - Tooltip": "Symbole, die die Anwendung der Außenwelt präsentiert",
"MFA items": "MFA items",
@@ -327,6 +332,7 @@
"Updated time": "Updated time",
"User": "Nutzer",
"User - Tooltip": "Stellen Sie sicher, dass der Benutzername korrekt ist",
"User Management": "User Management",
"User containers": "Nutzerpools",
"User type": "Benutzertyp",
"User type - Tooltip": "Tags, denen der Benutzer angehört, standardmäßig auf \"normaler Benutzer\" festgelegt",
@@ -481,6 +487,7 @@
"Currency - Tooltip": "Wie USD, CNY usw.",
"Download Invoice": "Rechnung herunterladen",
"Edit Payment": "Zahlung bearbeiten",
"Failed reason": "Failed reason",
"Individual": "individuell",
"Invoice URL": "Rechnungs-URL",
"Invoice URL - Tooltip": "URL für den Download der Rechnung",
@@ -514,6 +521,7 @@
"Product - Tooltip": "Produktname",
"Result": "Ergebnis",
"Return to Website": "Zurück zur Website",
"The payment has been canceled": "The payment has been canceled",
"The payment has failed": "Die Zahlung ist fehlgeschlagen",
"The payment is still under processing": "Die Zahlung wird immer noch bearbeitet",
"Type - Tooltip": "Zahlungsmethode, die beim Kauf des Produkts verwendet wurde",
@@ -608,14 +616,20 @@
"Access key - Tooltip": "Zugriffsschlüssel",
"Agent ID": "Agenten-ID",
"Agent ID - Tooltip": "Agenten-ID",
"Api Key": "Api Key",
"Api Key - Tooltip": "Api Key - Tooltip",
"App ID": "App ID",
"App ID - Tooltip": "App-ID",
"App key": "App-Key",
"App key - Tooltip": "App-Schlüssel",
"App secret": "App-Secret",
"AppSecret - Tooltip": "App-Geheimnis",
"Auth Key": "Auth Key",
"Auth Key - Tooltip": "Auth Key - Tooltip",
"Auth URL": "Auth-URL",
"Auth URL - Tooltip": "Auth-URL",
"Base URL": "Base URL",
"Base URL - Tooltip": "Base URL - Tooltip",
"Bucket": "Bucket",
"Bucket - Tooltip": "Name des Buckets",
"Can not parse metadata": "Kann Metadaten nicht durchsuchen / auswerten",
@@ -649,6 +663,7 @@
"Enable QR code - Tooltip": "Ob das Scannen von QR-Codes zum Einloggen aktiviert werden soll",
"Endpoint": "Endpoint",
"Endpoint (Intranet)": "Endpoint (Intranet)",
"Endpoint - Tooltip": "Endpoint - Tooltip",
"From address": "From address",
"From address - Tooltip": "From address - Tooltip",
"From name": "From name",
@@ -674,9 +689,17 @@
"Please use WeChat and scan the QR code to sign in": "Bitte verwenden Sie WeChat und scanne den QR-Code ein, um dich anzumelden",
"Port": "Port",
"Port - Tooltip": "Stellen Sie sicher, dass der Port offen ist",
"Private Key": "Private Key",
"Private Key - Tooltip": "Private Key - Tooltip",
"Project Id": "Project Id",
"Project Id - Tooltip": "Project Id - Tooltip",
"Prompted": "ausgelöst",
"Provider URL": "Provider-URL",
"Provider URL - Tooltip": "URL zur Konfiguration des Dienstanbieters, dieses Feld dient nur als Referenz und wird in Casdoor nicht verwendet",
"Public key": "Public key",
"Public key - Tooltip": "Public key - Tooltip",
"Region": "Region",
"Region - Tooltip": "Region - Tooltip",
"Region ID": "Regions-ID",
"Region ID - Tooltip": "Regions-ID für den Dienstleister",
"Region endpoint for Internet": "Regionsendpunkt für das Internet",
@@ -701,6 +724,8 @@
"Secret key - Tooltip": "Vom Server verwendet, um die API des Verifizierungscodes-Providers für die Verifizierung aufzurufen",
"Send Testing Email": "Senden Sie eine Test-E-Mail",
"Send Testing SMS": "Sende Test-SMS",
"Sender Id": "Sender Id",
"Sender Id - Tooltip": "Sender Id - Tooltip",
"Sender number": "Sender number",
"Sender number - Tooltip": "Sender number - Tooltip",
"Sign Name": "Signatur Namen",
@@ -815,6 +840,7 @@
"Error text": "Fehlermeldung",
"Error text - Tooltip": "Fehler Text",
"Is hashed": "ist gehasht",
"Is key": "Is key",
"Is read-only": "Is read-only",
"Is read-only - Tooltip": "Is read-only - Tooltip",
"New Syncer": "Neuer Syncer",

View File

@@ -165,16 +165,19 @@
"Adapter - Tooltip": "Table name of the policy store",
"Adapters": "Adapters",
"Add": "Add",
"Admin": "Admin",
"Affiliation URL": "Affiliation URL",
"Affiliation URL - Tooltip": "The homepage URL for the affiliation",
"Application": "Application",
"Application - Tooltip": "Application - Tooltip",
"Applications": "Applications",
"Applications that require authentication": "Applications that require authentication",
"Authorization": "Authorization",
"Avatar": "Avatar",
"Avatar - Tooltip": "Public avatar image for the user",
"Back": "Back",
"Back Home": "Back Home",
"Business & Payments": "Business & Payments",
"Cancel": "Cancel",
"Captcha": "Captcha",
"Cert": "Cert",
@@ -226,6 +229,7 @@
"Home - Tooltip": "Home page of the application",
"ID": "ID",
"ID - Tooltip": "Unique random string",
"Identity": "Identity",
"Is enabled": "Is enabled",
"Is enabled - Tooltip": "Set whether it can use",
"LDAPs": "LDAPs",
@@ -234,6 +238,7 @@
"Languages - Tooltip": "Available languages",
"Last name": "Last name",
"Later": "Later",
"Logging & Auditing": "Logging & Auditing",
"Logo": "Logo",
"Logo - Tooltip": "Icons that the application presents to the outside world",
"MFA items": "MFA items",
@@ -327,6 +332,7 @@
"Updated time": "Updated time",
"User": "User",
"User - Tooltip": "Make sure the username is correct",
"User Management": "User Management",
"User containers": "User pools",
"User type": "User type",
"User type - Tooltip": "Tags that the user belongs to, defaulting to \"normal-user\"",
@@ -481,6 +487,7 @@
"Currency - Tooltip": "Like USD, CNY, etc.",
"Download Invoice": "Download Invoice",
"Edit Payment": "Edit Payment",
"Failed reason": "Failed reason",
"Individual": "Individual",
"Invoice URL": "Invoice URL",
"Invoice URL - Tooltip": "URL for downloading the invoice",
@@ -514,6 +521,7 @@
"Product - Tooltip": "Product Name",
"Result": "Result",
"Return to Website": "Return to Website",
"The payment has been canceled": "The payment has been canceled",
"The payment has failed": "The payment has failed",
"The payment is still under processing": "The payment is still under processing",
"Type - Tooltip": "Payment method used when purchasing the product",
@@ -608,14 +616,20 @@
"Access key - Tooltip": "Access key",
"Agent ID": "Agent ID",
"Agent ID - Tooltip": "Agent ID",
"Api Key": "Api Key",
"Api Key - Tooltip": "Api Key - Tooltip",
"App ID": "App ID",
"App ID - Tooltip": "App ID",
"App key": "App key",
"App key - Tooltip": "App key",
"App secret": "App secret",
"AppSecret - Tooltip": "App secret",
"Auth Key": "Auth Key",
"Auth Key - Tooltip": "Auth Key - Tooltip",
"Auth URL": "Auth URL",
"Auth URL - Tooltip": "Auth URL",
"Base URL": "Base URL",
"Base URL - Tooltip": "Base URL - Tooltip",
"Bucket": "Bucket",
"Bucket - Tooltip": "Name of bucket",
"Can not parse metadata": "Can not parse metadata",
@@ -649,6 +663,7 @@
"Enable QR code - Tooltip": "Whether to allow scanning QR code to login",
"Endpoint": "Endpoint",
"Endpoint (Intranet)": "Endpoint (Intranet)",
"Endpoint - Tooltip": "Endpoint - Tooltip",
"From address": "From address",
"From address - Tooltip": "Email address of \"From\"",
"From name": "From name",
@@ -674,9 +689,17 @@
"Please use WeChat and scan the QR code to sign in": "Please use WeChat and scan the QR code to sign in",
"Port": "Port",
"Port - Tooltip": "Make sure the port is open",
"Private Key": "Private Key",
"Private Key - Tooltip": "Private Key - Tooltip",
"Project Id": "Project Id",
"Project Id - Tooltip": "Project Id - Tooltip",
"Prompted": "Prompted",
"Provider URL": "Provider URL",
"Provider URL - Tooltip": "URL for configuring the service provider, this field is only used for reference and is not used in Casdoor",
"Public key": "Public key",
"Public key - Tooltip": "Public key - Tooltip",
"Region": "Region",
"Region - Tooltip": "Region - Tooltip",
"Region ID": "Region ID",
"Region ID - Tooltip": "Region ID for the service provider",
"Region endpoint for Internet": "Region endpoint for Internet",
@@ -701,6 +724,8 @@
"Secret key - Tooltip": "Used by the server to call the verification code provider API for verification",
"Send Testing Email": "Send Testing Email",
"Send Testing SMS": "Send Testing SMS",
"Sender Id": "Sender Id",
"Sender Id - Tooltip": "Sender Id - Tooltip",
"Sender number": "Sender number",
"Sender number - Tooltip": "Sender number - Tooltip",
"Sign Name": "Sign Name",
@@ -815,6 +840,7 @@
"Error text": "Error text",
"Error text - Tooltip": "Error text",
"Is hashed": "Is hashed",
"Is key": "Is key",
"Is read-only": "Is read-only",
"Is read-only - Tooltip": "Is read-only - Tooltip",
"New Syncer": "New Syncer",

View File

@@ -165,16 +165,19 @@
"Adapter - Tooltip": "Nombre de la tabla de la tienda de políticas",
"Adapters": "Adaptadores",
"Add": "Añadir",
"Admin": "Admin",
"Affiliation URL": "URL de afiliación",
"Affiliation URL - Tooltip": "La URL de la página de inicio para la afiliación",
"Application": "Aplicación",
"Application - Tooltip": "Application - Tooltip",
"Applications": "Aplicaciones",
"Applications that require authentication": "Aplicaciones que requieren autenticación",
"Authorization": "Authorization",
"Avatar": "Avatar",
"Avatar - Tooltip": "Imagen de avatar pública para el usuario",
"Back": "Back",
"Back Home": "Regreso a casa",
"Business & Payments": "Business & Payments",
"Cancel": "Cancelar",
"Captcha": "Captcha",
"Cert": "ificado",
@@ -226,6 +229,7 @@
"Home - Tooltip": "Página de inicio de la aplicación",
"ID": "identificación",
"ID - Tooltip": "Cadena aleatoria única",
"Identity": "Identity",
"Is enabled": "Está habilitado",
"Is enabled - Tooltip": "Establecer si se puede usar",
"LDAPs": "LDAPs",
@@ -234,6 +238,7 @@
"Languages - Tooltip": "Idiomas disponibles",
"Last name": "Apellido",
"Later": "Later",
"Logging & Auditing": "Logging & Auditing",
"Logo": "Logotipo",
"Logo - Tooltip": "Iconos que la aplicación presenta al mundo exterior",
"MFA items": "MFA items",
@@ -327,6 +332,7 @@
"Updated time": "Updated time",
"User": "Usuario",
"User - Tooltip": "Asegúrate de que el nombre de usuario sea correcto",
"User Management": "User Management",
"User containers": "Piscinas de usuarios",
"User type": "Tipo de usuario",
"User type - Tooltip": "Etiquetas a las que el usuario pertenece, con una configuración predeterminada en \"usuario-normal\"",
@@ -481,6 +487,7 @@
"Currency - Tooltip": "Como USD, CNY, etc.",
"Download Invoice": "Descargar factura",
"Edit Payment": "Editar pago",
"Failed reason": "Failed reason",
"Individual": "Individuo",
"Invoice URL": "URL de factura",
"Invoice URL - Tooltip": "URL para descargar la factura",
@@ -514,6 +521,7 @@
"Product - Tooltip": "Nombre del producto",
"Result": "Resultado",
"Return to Website": "Regresar al sitio web",
"The payment has been canceled": "The payment has been canceled",
"The payment has failed": "El pago ha fallado",
"The payment is still under processing": "El pago aún está en proceso",
"Type - Tooltip": "Método de pago utilizado al comprar el producto",
@@ -608,14 +616,20 @@
"Access key - Tooltip": "Clave de acceso",
"Agent ID": "Identificador de agente",
"Agent ID - Tooltip": "Identificador de agente",
"Api Key": "Api Key",
"Api Key - Tooltip": "Api Key - Tooltip",
"App ID": "ID de aplicación",
"App ID - Tooltip": "Identificador de la aplicación",
"App key": "Clave de aplicación",
"App key - Tooltip": "Clave de aplicación",
"App secret": "Secreto de la aplicación",
"AppSecret - Tooltip": "Secreto de aplicación",
"Auth Key": "Auth Key",
"Auth Key - Tooltip": "Auth Key - Tooltip",
"Auth URL": "URL de autenticación",
"Auth URL - Tooltip": "URL de autenticación",
"Base URL": "Base URL",
"Base URL - Tooltip": "Base URL - Tooltip",
"Bucket": "Cubo",
"Bucket - Tooltip": "Nombre del balde",
"Can not parse metadata": "No se puede analizar los metadatos",
@@ -649,6 +663,7 @@
"Enable QR code - Tooltip": "Si permitir el escaneo de códigos QR para acceder",
"Endpoint": "Punto final",
"Endpoint (Intranet)": "Punto final (intranet)",
"Endpoint - Tooltip": "Endpoint - Tooltip",
"From address": "From address",
"From address - Tooltip": "From address - Tooltip",
"From name": "From name",
@@ -674,9 +689,17 @@
"Please use WeChat and scan the QR code to sign in": "Por favor, utiliza WeChat y escanea el código QR para iniciar sesión",
"Port": "Puerto",
"Port - Tooltip": "Asegúrate de que el puerto esté abierto",
"Private Key": "Private Key",
"Private Key - Tooltip": "Private Key - Tooltip",
"Project Id": "Project Id",
"Project Id - Tooltip": "Project Id - Tooltip",
"Prompted": "Estimulado",
"Provider URL": "URL del proveedor",
"Provider URL - Tooltip": "Dirección URL para configurar el proveedor de servicios, este campo sólo se utiliza como referencia y no se utiliza en Casdoor",
"Public key": "Public key",
"Public key - Tooltip": "Public key - Tooltip",
"Region": "Region",
"Region - Tooltip": "Region - Tooltip",
"Region ID": "ID de región",
"Region ID - Tooltip": "Identificación de región para el proveedor de servicios",
"Region endpoint for Internet": "Punto final de la región para Internet",
@@ -701,6 +724,8 @@
"Secret key - Tooltip": "Utilizado por el servidor para llamar a la API del proveedor de códigos de verificación para verificar",
"Send Testing Email": "Enviar correo electrónico de prueba",
"Send Testing SMS": "Enviar SMS de prueba",
"Sender Id": "Sender Id",
"Sender Id - Tooltip": "Sender Id - Tooltip",
"Sender number": "Sender number",
"Sender number - Tooltip": "Sender number - Tooltip",
"Sign Name": "Firma de Nombre",
@@ -815,6 +840,7 @@
"Error text": "Texto de error",
"Error text - Tooltip": "Texto de error",
"Is hashed": "Está encriptado",
"Is key": "Is key",
"Is read-only": "Is read-only",
"Is read-only - Tooltip": "Is read-only - Tooltip",
"New Syncer": "Nuevo Syncer",

View File

@@ -165,16 +165,19 @@
"Adapter - Tooltip": "Nom de la table du magasin de politique",
"Adapters": "Adaptateurs",
"Add": "Ajouter",
"Admin": "Admin",
"Affiliation URL": "URL d'affiliation",
"Affiliation URL - Tooltip": "La URL de la page d'accueil pour l'affiliation",
"Application": "Application",
"Application - Tooltip": "Application - Tooltip",
"Applications": "Applications",
"Applications that require authentication": "Applications qui nécessitent une authentification",
"Authorization": "Authorization",
"Avatar": "Avatar",
"Avatar - Tooltip": "Image d'avatar public pour l'utilisateur",
"Back": "Back",
"Back Home": "Retour à la maison",
"Business & Payments": "Business & Payments",
"Cancel": "Annuler",
"Captcha": "Captcha (prononcé « kæptʃə » en anglais) est un acronyme qui signifie « Completely Automated Public Turing test to tell Computers and Humans Apart ». En français, le terme est souvent traduit par « test de Turing complètement automatisé et public pour différencier les ordinateurs et les humains ». Le système est utilisé pour empêcher les spammeurs, les robots et les logiciels malveillants d'accéder aux sites Web en leur demandant de résoudre une tâche de reconnaissance de caractères ou d'images, qui peut être difficile pour les machines à comprendre mais facile pour les humains",
"Cert": "ainement",
@@ -226,6 +229,7 @@
"Home - Tooltip": "Page d'accueil de l'application",
"ID": "Identité",
"ID - Tooltip": "Chaîne unique aléatoire",
"Identity": "Identity",
"Is enabled": "Est activé",
"Is enabled - Tooltip": "Définir s'il peut être utilisé",
"LDAPs": "LDAPs",
@@ -234,6 +238,7 @@
"Languages - Tooltip": "Langues disponibles",
"Last name": "Nom de famille",
"Later": "Later",
"Logging & Auditing": "Logging & Auditing",
"Logo": "Logo",
"Logo - Tooltip": "Icônes que l'application présente au monde extérieur",
"MFA items": "MFA items",
@@ -327,6 +332,7 @@
"Updated time": "Updated time",
"User": "Utilisateur",
"User - Tooltip": "Assurez-vous que le nom d'utilisateur est correct",
"User Management": "User Management",
"User containers": "Piscines d'utilisateurs",
"User type": "Type d'utilisateur",
"User type - Tooltip": "Balises auxquelles l'utilisateur appartient, avec une valeur par défaut \"utilisateur-normal\"",
@@ -481,6 +487,7 @@
"Currency - Tooltip": "Comme USD, CNY, etc.",
"Download Invoice": "Télécharger la facture",
"Edit Payment": "Modifier le paiement",
"Failed reason": "Failed reason",
"Individual": "Individu",
"Invoice URL": "URL de facture",
"Invoice URL - Tooltip": "URL pour télécharger la facture",
@@ -514,6 +521,7 @@
"Product - Tooltip": "Nom du produit",
"Result": "Résultat",
"Return to Website": "Retourner sur le site web",
"The payment has been canceled": "The payment has been canceled",
"The payment has failed": "Le paiement a échoué",
"The payment is still under processing": "Le paiement est encore en cours de traitement",
"Type - Tooltip": "Méthode de paiement utilisée lors de l'achat du produit",
@@ -608,14 +616,20 @@
"Access key - Tooltip": "Clé d'accès",
"Agent ID": "Identifiant d'agent",
"Agent ID - Tooltip": "Identifiant d'agent",
"Api Key": "Api Key",
"Api Key - Tooltip": "Api Key - Tooltip",
"App ID": "Identifiant d'application",
"App ID - Tooltip": "Identifiant d'application",
"App key": "Clé d'application",
"App key - Tooltip": "Clé d'application",
"App secret": "Secret d'application",
"AppSecret - Tooltip": "Secret de l'application",
"Auth Key": "Auth Key",
"Auth Key - Tooltip": "Auth Key - Tooltip",
"Auth URL": "URL d'authentification",
"Auth URL - Tooltip": "URL d'authentification",
"Base URL": "Base URL",
"Base URL - Tooltip": "Base URL - Tooltip",
"Bucket": "seau",
"Bucket - Tooltip": "Nom du seau",
"Can not parse metadata": "Impossible d'analyser les métadonnées",
@@ -649,6 +663,7 @@
"Enable QR code - Tooltip": "Doit-on autoriser la numérisation de QR code pour se connecter ?",
"Endpoint": "Point final",
"Endpoint (Intranet)": "Point final (intranet)",
"Endpoint - Tooltip": "Endpoint - Tooltip",
"From address": "From address",
"From address - Tooltip": "From address - Tooltip",
"From name": "From name",
@@ -674,9 +689,17 @@
"Please use WeChat and scan the QR code to sign in": "Veuillez utiliser WeChat et scanner le code QR pour vous connecter",
"Port": "Port",
"Port - Tooltip": "Assurez-vous que le port est ouvert",
"Private Key": "Private Key",
"Private Key - Tooltip": "Private Key - Tooltip",
"Project Id": "Project Id",
"Project Id - Tooltip": "Project Id - Tooltip",
"Prompted": "Incité",
"Provider URL": "URL du fournisseur",
"Provider URL - Tooltip": "URL pour configurer le fournisseur de services, ce champ est uniquement utilisé à titre de référence et n'est pas utilisé dans Casdoor",
"Public key": "Public key",
"Public key - Tooltip": "Public key - Tooltip",
"Region": "Region",
"Region - Tooltip": "Region - Tooltip",
"Region ID": "Identifiant de région",
"Region ID - Tooltip": "Identifiant de région pour le fournisseur de services",
"Region endpoint for Internet": "Point de terminaison de région pour Internet",
@@ -701,6 +724,8 @@
"Secret key - Tooltip": "Utilisé par le serveur pour appeler l'API du fournisseur de code de vérification pour vérifier",
"Send Testing Email": "Envoyer un e-mail de test",
"Send Testing SMS": "Envoyer des messages SMS de tests",
"Sender Id": "Sender Id",
"Sender Id - Tooltip": "Sender Id - Tooltip",
"Sender number": "Sender number",
"Sender number - Tooltip": "Sender number - Tooltip",
"Sign Name": "Nom de signature",
@@ -815,6 +840,7 @@
"Error text": "Texte d'erreur",
"Error text - Tooltip": "Texte d'erreur",
"Is hashed": "Est-haché",
"Is key": "Is key",
"Is read-only": "Is read-only",
"Is read-only - Tooltip": "Is read-only - Tooltip",
"New Syncer": "Nouveau synchroniseur",

View File

@@ -165,16 +165,19 @@
"Adapter - Tooltip": "Nama tabel dari penyimpanan kebijakan",
"Adapters": "Adaptor",
"Add": "Tambahkan",
"Admin": "Admin",
"Affiliation URL": "URL Afiliasi",
"Affiliation URL - Tooltip": "URL halaman depan untuk afiliasi",
"Application": "Aplikasi",
"Application - Tooltip": "Application - Tooltip",
"Applications": "Aplikasi",
"Applications that require authentication": "Aplikasi yang memerlukan autentikasi",
"Authorization": "Authorization",
"Avatar": "Avatar",
"Avatar - Tooltip": "Gambar avatar publik untuk pengguna",
"Back": "Back",
"Back Home": "Kembali ke Rumah",
"Business & Payments": "Business & Payments",
"Cancel": "Membatalkan",
"Captcha": "Captcha",
"Cert": "Sertifikat",
@@ -226,6 +229,7 @@
"Home - Tooltip": "Halaman utama aplikasi",
"ID": "ID",
"ID - Tooltip": "Karakter acak unik",
"Identity": "Identity",
"Is enabled": "Diaktifkan",
"Is enabled - Tooltip": "Atur apakah itu dapat digunakan",
"LDAPs": "LDAPs",
@@ -234,6 +238,7 @@
"Languages - Tooltip": "Bahasa yang tersedia",
"Last name": "Nama belakang",
"Later": "Later",
"Logging & Auditing": "Logging & Auditing",
"Logo": "Logo",
"Logo - Tooltip": "Ikon-ikon yang disajikan aplikasi ke dunia luar",
"MFA items": "MFA items",
@@ -327,6 +332,7 @@
"Updated time": "Updated time",
"User": "Pengguna",
"User - Tooltip": "Pastikan username-nya benar",
"User Management": "User Management",
"User containers": "User pools",
"User type": "Jenis pengguna",
"User type - Tooltip": "Tag yang dimiliki oleh pengguna, defaultnya adalah \"normal-user\"",
@@ -481,6 +487,7 @@
"Currency - Tooltip": "Seperti USD, CNY, dll.",
"Download Invoice": "Unduh Faktur",
"Edit Payment": "Edit Pembayaran",
"Failed reason": "Failed reason",
"Individual": "Individu",
"Invoice URL": "URL Faktur",
"Invoice URL - Tooltip": "URL untuk mengunduh faktur",
@@ -514,6 +521,7 @@
"Product - Tooltip": "Nama Produk",
"Result": "Hasil",
"Return to Website": "Kembali ke Situs Web",
"The payment has been canceled": "The payment has been canceled",
"The payment has failed": "Pembayaran gagal",
"The payment is still under processing": "Pembayaran masih dalam proses",
"Type - Tooltip": "Metode pembayaran yang digunakan saat membeli produk",
@@ -608,14 +616,20 @@
"Access key - Tooltip": "Kunci akses",
"Agent ID": "ID agen",
"Agent ID - Tooltip": "ID Agen",
"Api Key": "Api Key",
"Api Key - Tooltip": "Api Key - Tooltip",
"App ID": "ID Aplikasi",
"App ID - Tooltip": "ID Aplikasi",
"App key": "Kunci aplikasi",
"App key - Tooltip": "Kunci aplikasi",
"App secret": "Rahasia aplikasi",
"AppSecret - Tooltip": "Rahasia aplikasi",
"Auth Key": "Auth Key",
"Auth Key - Tooltip": "Auth Key - Tooltip",
"Auth URL": "URL Otorisasi",
"Auth URL - Tooltip": "URL terautentikasi",
"Base URL": "Base URL",
"Base URL - Tooltip": "Base URL - Tooltip",
"Bucket": "Ember",
"Bucket - Tooltip": "Nama ember",
"Can not parse metadata": "Tidak dapat mengurai metadata",
@@ -649,6 +663,7 @@
"Enable QR code - Tooltip": "Apakah diizinkan untuk memindai kode QR untuk masuk?",
"Endpoint": "Titik akhir",
"Endpoint (Intranet)": "Titik Akhir (Intranet)",
"Endpoint - Tooltip": "Endpoint - Tooltip",
"From address": "From address",
"From address - Tooltip": "From address - Tooltip",
"From name": "From name",
@@ -674,9 +689,17 @@
"Please use WeChat and scan the QR code to sign in": "Silakan gunakan WeChat dan pindai kode QR untuk masuk",
"Port": "Pelabuhan",
"Port - Tooltip": "Pastikan port terbuka",
"Private Key": "Private Key",
"Private Key - Tooltip": "Private Key - Tooltip",
"Project Id": "Project Id",
"Project Id - Tooltip": "Project Id - Tooltip",
"Prompted": "Mendorong",
"Provider URL": "URL penyedia",
"Provider URL - Tooltip": "URL untuk melakukan konfigurasi service provider, kolom ini hanya digunakan sebagai referensi dan tidak digunakan dalam Casdoor",
"Public key": "Public key",
"Public key - Tooltip": "Public key - Tooltip",
"Region": "Region",
"Region - Tooltip": "Region - Tooltip",
"Region ID": "Daerah ID",
"Region ID - Tooltip": "Daerah ID untuk penyedia layanan",
"Region endpoint for Internet": "Titik akhir wilayah untuk Internet",
@@ -701,6 +724,8 @@
"Secret key - Tooltip": "Digunakan oleh server untuk memanggil API penyedia kode verifikasi untuk melakukan verifikasi",
"Send Testing Email": "Kirim Email Uji Coba",
"Send Testing SMS": "Kirim SMS Uji Coba",
"Sender Id": "Sender Id",
"Sender Id - Tooltip": "Sender Id - Tooltip",
"Sender number": "Sender number",
"Sender number - Tooltip": "Sender number - Tooltip",
"Sign Name": "Tanda Tangan",
@@ -815,6 +840,7 @@
"Error text": "Teks kesalahan",
"Error text - Tooltip": "Teks kesalahan",
"Is hashed": "Apakah di-hash?",
"Is key": "Is key",
"Is read-only": "Is read-only",
"Is read-only - Tooltip": "Is read-only - Tooltip",
"New Syncer": "Sinkronisasi Baru",

View File

@@ -1,6 +1,5 @@
{
"account": {
"Chats & Messages": "Chats & Messages",
"Logout": "Logout",
"My Account": "My Account",
"Sign Up": "Sign Up"
@@ -127,19 +126,6 @@
"Scope - Tooltip": "Usage scenarios of the certificate",
"Type - Tooltip": "Type of certificate"
},
"chat": {
"AI": "AI",
"Edit Chat": "Edit Chat",
"Group": "Group",
"Message count": "Message count",
"New Chat": "New Chat",
"Single": "Single",
"User1": "User1",
"User1 - Tooltip": "User1 - Tooltip",
"User2": "User2",
"User2 - Tooltip": "User2 - Tooltip",
"Users - Tooltip": "Users - Tooltip"
},
"code": {
"Code you received": "Code you received",
"Email code": "Email code",
@@ -179,22 +165,24 @@
"Adapter - Tooltip": "Table name of the policy store",
"Adapters": "Adapters",
"Add": "Add",
"Admin": "Admin",
"Affiliation URL": "Affiliation URL",
"Affiliation URL - Tooltip": "The homepage URL for the affiliation",
"Application": "Application",
"Application - Tooltip": "Application - Tooltip",
"Applications": "Applications",
"Applications that require authentication": "Applications that require authentication",
"Authorization": "Authorization",
"Avatar": "Avatar",
"Avatar - Tooltip": "Public avatar image for the user",
"Back": "Back",
"Back Home": "Back Home",
"Business & Payments": "Business & Payments",
"Cancel": "Cancel",
"Captcha": "Captcha",
"Cert": "Cert",
"Cert - Tooltip": "The public key certificate that needs to be verified by the client SDK corresponding to this application",
"Certs": "Certs",
"Chats": "Chats",
"Click to Upload": "Click to Upload",
"Client IP": "Client IP",
"Close": "Close",
@@ -224,7 +212,6 @@
"Failed to connect to server": "Failed to connect to server",
"Failed to delete": "Failed to delete",
"Failed to enable": "Failed to enable",
"Failed to get answer": "Failed to get answer",
"Failed to remove": "Failed to remove",
"Failed to save": "Failed to save",
"Failed to verify": "Failed to verify",
@@ -242,6 +229,7 @@
"Home - Tooltip": "Home page of the application",
"ID": "ID",
"ID - Tooltip": "Unique random string",
"Identity": "Identity",
"Is enabled": "Is enabled",
"Is enabled - Tooltip": "Set whether it can use",
"LDAPs": "LDAPs",
@@ -250,6 +238,7 @@
"Languages - Tooltip": "Available languages",
"Last name": "Last name",
"Later": "Later",
"Logging & Auditing": "Logging & Auditing",
"Logo": "Logo",
"Logo - Tooltip": "Icons that the application presents to the outside world",
"MFA items": "MFA items",
@@ -257,7 +246,6 @@
"Master password": "Master password",
"Master password - Tooltip": "Can be used to log in to all users under this organization, making it convenient for administrators to log in as this user to solve technical issues",
"Menu": "Menu",
"Messages": "Messages",
"Method": "Method",
"Model": "Model",
"Model - Tooltip": "Casbin access control model",
@@ -344,6 +332,7 @@
"Updated time": "Updated time",
"User": "User",
"User - Tooltip": "Make sure the username is correct",
"User Management": "User Management",
"User containers": "User pools",
"User type": "User type",
"User type - Tooltip": "Tags that the user belongs to, defaulting to \"normal-user\"",
@@ -425,16 +414,6 @@
"sign up now": "sign up now",
"username, Email or phone": "username, Email or phone"
},
"message": {
"Author": "Author",
"Author - Tooltip": "Author - Tooltip",
"Chat": "Chat",
"Chat - Tooltip": "Chat - Tooltip",
"Edit Message": "Edit Message",
"New Message": "New Message",
"Text": "Text",
"Text - Tooltip": "Text - Tooltip"
},
"mfa": {
"Each time you sign in to your Account, you'll need your password and a authentication code": "Each time you sign in to your Account, you'll need your password and a authentication code",
"Enable multi-factor authentication": "Enable multi-factor authentication",
@@ -508,6 +487,7 @@
"Currency - Tooltip": "Like USD, CNY, etc.",
"Download Invoice": "Download Invoice",
"Edit Payment": "Edit Payment",
"Failed reason": "Failed reason",
"Individual": "Individual",
"Invoice URL": "Invoice URL",
"Invoice URL - Tooltip": "URL for downloading the invoice",
@@ -541,6 +521,7 @@
"Product - Tooltip": "Product Name",
"Result": "Result",
"Return to Website": "Return to Website",
"The payment has been canceled": "The payment has been canceled",
"The payment has failed": "The payment has failed",
"The payment is still under processing": "The payment is still under processing",
"Type - Tooltip": "Payment method used when purchasing the product",
@@ -635,14 +616,20 @@
"Access key - Tooltip": "Access key",
"Agent ID": "Agent ID",
"Agent ID - Tooltip": "Agent ID",
"Api Key": "Api Key",
"Api Key - Tooltip": "Api Key - Tooltip",
"App ID": "App ID",
"App ID - Tooltip": "App ID",
"App key": "App key",
"App key - Tooltip": "App key",
"App secret": "App secret",
"AppSecret - Tooltip": "App secret",
"Auth Key": "Auth Key",
"Auth Key - Tooltip": "Auth Key - Tooltip",
"Auth URL": "Auth URL",
"Auth URL - Tooltip": "Auth URL",
"Base URL": "Base URL",
"Base URL - Tooltip": "Base URL - Tooltip",
"Bucket": "Bucket",
"Bucket - Tooltip": "Name of bucket",
"Can not parse metadata": "Can not parse metadata",
@@ -676,6 +663,7 @@
"Enable QR code - Tooltip": "Whether to allow scanning QR code to login",
"Endpoint": "Endpoint",
"Endpoint (Intranet)": "Endpoint (Intranet)",
"Endpoint - Tooltip": "Endpoint - Tooltip",
"From address": "From address",
"From address - Tooltip": "Email address of \"From\"",
"From name": "From name",
@@ -701,9 +689,17 @@
"Please use WeChat and scan the QR code to sign in": "Please use WeChat and scan the QR code to sign in",
"Port": "Port",
"Port - Tooltip": "Make sure the port is open",
"Private Key": "Private Key",
"Private Key - Tooltip": "Private Key - Tooltip",
"Project Id": "Project Id",
"Project Id - Tooltip": "Project Id - Tooltip",
"Prompted": "Prompted",
"Provider URL": "Provider URL",
"Provider URL - Tooltip": "URL for configuring the service provider, this field is only used for reference and is not used in Casdoor",
"Public key": "Public key",
"Public key - Tooltip": "Public key - Tooltip",
"Region": "Region",
"Region - Tooltip": "Region - Tooltip",
"Region ID": "Region ID",
"Region ID - Tooltip": "Region ID for the service provider",
"Region endpoint for Internet": "Region endpoint for Internet",
@@ -728,6 +724,8 @@
"Secret key - Tooltip": "Used by the server to call the verification code provider API for verification",
"Send Testing Email": "Send Testing Email",
"Send Testing SMS": "Send Testing SMS",
"Sender Id": "Sender Id",
"Sender Id - Tooltip": "Sender Id - Tooltip",
"Sender number": "Sender number",
"Sender number - Tooltip": "Sender number - Tooltip",
"Sign Name": "Sign Name",
@@ -842,6 +840,7 @@
"Error text": "Error text",
"Error text - Tooltip": "Error text",
"Is hashed": "Is hashed",
"Is key": "Is key",
"Is read-only": "Is read-only",
"Is read-only - Tooltip": "Is read-only - Tooltip",
"New Syncer": "New Syncer",

View File

@@ -165,16 +165,19 @@
"Adapter - Tooltip": "ポリシー・ストアのテーブル名",
"Adapters": "アダプター",
"Add": "追加",
"Admin": "Admin",
"Affiliation URL": "所属するURL",
"Affiliation URL - Tooltip": "所属先のホームページURL",
"Application": "アプリケーション",
"Application - Tooltip": "Application - Tooltip",
"Applications": "アプリケーション",
"Applications that require authentication": "認証が必要なアプリケーション",
"Authorization": "Authorization",
"Avatar": "アバター",
"Avatar - Tooltip": "ユーザーのパブリックアバター画像",
"Back": "Back",
"Back Home": "帰宅",
"Business & Payments": "Business & Payments",
"Cancel": "キャンセルします",
"Captcha": "キャプチャ",
"Cert": "証明書",
@@ -226,6 +229,7 @@
"Home - Tooltip": "アプリケーションのホームページ",
"ID": "ID",
"ID - Tooltip": "ユニークなランダム文字列",
"Identity": "Identity",
"Is enabled": "可能になっています",
"Is enabled - Tooltip": "使用可能かどうかを設定してください",
"LDAPs": "LDAPs",
@@ -234,6 +238,7 @@
"Languages - Tooltip": "利用可能な言語",
"Last name": "苗字",
"Later": "Later",
"Logging & Auditing": "Logging & Auditing",
"Logo": "ロゴ",
"Logo - Tooltip": "アプリケーションが外部世界に示すアイコン",
"MFA items": "MFA items",
@@ -327,6 +332,7 @@
"Updated time": "Updated time",
"User": "ユーザー",
"User - Tooltip": "ユーザー名が正しいことを確認してください",
"User Management": "User Management",
"User containers": "ユーザープール",
"User type": "ユーザータイプ",
"User type - Tooltip": "ユーザーが属するタグは、デフォルトでは「通常ユーザー」となります",
@@ -481,6 +487,7 @@
"Currency - Tooltip": "米ドル、人民元など。",
"Download Invoice": "請求書のダウンロード",
"Edit Payment": "支払い編集",
"Failed reason": "Failed reason",
"Individual": "個人",
"Invoice URL": "請求書のURL",
"Invoice URL - Tooltip": "請求書のダウンロード用のURL",
@@ -514,6 +521,7 @@
"Product - Tooltip": "製品名",
"Result": "結果",
"Return to Website": "ウェブサイトに戻る",
"The payment has been canceled": "The payment has been canceled",
"The payment has failed": "支払いに失敗しました",
"The payment is still under processing": "支払いはまだ処理中です",
"Type - Tooltip": "製品を購入する際に使用される支払方法",
@@ -608,14 +616,20 @@
"Access key - Tooltip": "アクセスキー",
"Agent ID": "エージェントID",
"Agent ID - Tooltip": "エージェントID",
"Api Key": "Api Key",
"Api Key - Tooltip": "Api Key - Tooltip",
"App ID": "アプリID",
"App ID - Tooltip": "アプリID",
"App key": "アプリキー",
"App key - Tooltip": "アプリキー",
"App secret": "アプリの秘密鍵",
"AppSecret - Tooltip": "アプリの秘密鍵",
"Auth Key": "Auth Key",
"Auth Key - Tooltip": "Auth Key - Tooltip",
"Auth URL": "認証URL",
"Auth URL - Tooltip": "認証URL",
"Base URL": "Base URL",
"Base URL - Tooltip": "Base URL - Tooltip",
"Bucket": "バケツ",
"Bucket - Tooltip": "バケットの名前",
"Can not parse metadata": "メタデータを解析できません",
@@ -649,6 +663,7 @@
"Enable QR code - Tooltip": "ログインするためにQRコードをスキャンすることを許可するかどうか",
"Endpoint": "エンドポイント",
"Endpoint (Intranet)": "エンドポイント(イントラネット)",
"Endpoint - Tooltip": "Endpoint - Tooltip",
"From address": "From address",
"From address - Tooltip": "From address - Tooltip",
"From name": "From name",
@@ -674,9 +689,17 @@
"Please use WeChat and scan the QR code to sign in": "WeChatを使用し、QRコードをスキャンしてサインインしてください",
"Port": "ポート",
"Port - Tooltip": "ポートが開いていることを確認してください",
"Private Key": "Private Key",
"Private Key - Tooltip": "Private Key - Tooltip",
"Project Id": "Project Id",
"Project Id - Tooltip": "Project Id - Tooltip",
"Prompted": "促された",
"Provider URL": "プロバイダーURL",
"Provider URL - Tooltip": "サービスプロバイダーの設定用URL。このフィールドは参照用にのみ使用され、Casdoorでは使用されません",
"Public key": "Public key",
"Public key - Tooltip": "Public key - Tooltip",
"Region": "Region",
"Region - Tooltip": "Region - Tooltip",
"Region ID": "地域ID",
"Region ID - Tooltip": "サービスプロバイダの地域ID",
"Region endpoint for Internet": "インターネットのリージョンエンドポイント",
@@ -701,6 +724,8 @@
"Secret key - Tooltip": "認証のためにサーバーによって使用され、認証コードプロバイダAPIを呼び出すためのもの",
"Send Testing Email": "テスト用メールを送信する",
"Send Testing SMS": "テストSMSを送信してください",
"Sender Id": "Sender Id",
"Sender Id - Tooltip": "Sender Id - Tooltip",
"Sender number": "Sender number",
"Sender number - Tooltip": "Sender number - Tooltip",
"Sign Name": "署名",
@@ -815,6 +840,7 @@
"Error text": "エラーテキスト",
"Error text - Tooltip": "エラーテキスト",
"Is hashed": "ハッシュ化されました",
"Is key": "Is key",
"Is read-only": "Is read-only",
"Is read-only - Tooltip": "Is read-only - Tooltip",
"New Syncer": "新しいシンクロナイザー",

View File

@@ -165,16 +165,19 @@
"Adapter - Tooltip": "정책 저장소의 테이블 이름",
"Adapters": "어댑터",
"Add": "추가하다",
"Admin": "Admin",
"Affiliation URL": "소속 URL",
"Affiliation URL - Tooltip": "소속 홈페이지 URL",
"Application": "응용 프로그램",
"Application - Tooltip": "Application - Tooltip",
"Applications": "응용 프로그램",
"Applications that require authentication": "인증이 필요한 애플리케이션들",
"Authorization": "Authorization",
"Avatar": "아바타",
"Avatar - Tooltip": "사용자를 위한 공개 아바타 이미지",
"Back": "Back",
"Back Home": "집으로 돌아오기",
"Business & Payments": "Business & Payments",
"Cancel": "취소",
"Captcha": "캡차",
"Cert": "인증서",
@@ -226,6 +229,7 @@
"Home - Tooltip": "어플리케이션 홈 페이지",
"ID": "ID",
"ID - Tooltip": "유일한 랜덤 문자열",
"Identity": "Identity",
"Is enabled": "활성화됩니다",
"Is enabled - Tooltip": "사용 가능한 지 여부를 설정하세요",
"LDAPs": "LDAPs",
@@ -234,6 +238,7 @@
"Languages - Tooltip": "사용 가능한 언어",
"Last name": "성",
"Later": "Later",
"Logging & Auditing": "Logging & Auditing",
"Logo": "로고",
"Logo - Tooltip": "애플리케이션이 외부 세계에 제시하는 아이콘들",
"MFA items": "MFA items",
@@ -327,6 +332,7 @@
"Updated time": "Updated time",
"User": "사용자",
"User - Tooltip": "사용자 이름이 정확한지 확인하세요",
"User Management": "User Management",
"User containers": "사용자 풀",
"User type": "사용자 유형",
"User type - Tooltip": "사용자가 속한 태그는 기본적으로 \"보통 사용자\"로 설정됩니다",
@@ -481,6 +487,7 @@
"Currency - Tooltip": "USD, CNY 등과 같이.",
"Download Invoice": "인보이스 다운로드",
"Edit Payment": "결제 수정",
"Failed reason": "Failed reason",
"Individual": "개인",
"Invoice URL": "송장 URL",
"Invoice URL - Tooltip": "송장 다운로드를 위한 URL",
@@ -514,6 +521,7 @@
"Product - Tooltip": "제품 이름",
"Result": "결과",
"Return to Website": "웹 사이트로 돌아가기",
"The payment has been canceled": "The payment has been canceled",
"The payment has failed": "결제가 실패했습니다",
"The payment is still under processing": "지불은 아직 처리 중입니다",
"Type - Tooltip": "제품을 구매할 때 사용되는 결제 방법",
@@ -608,14 +616,20 @@
"Access key - Tooltip": "액세스 키",
"Agent ID": "에이전트 ID",
"Agent ID - Tooltip": "에이전트 ID",
"Api Key": "Api Key",
"Api Key - Tooltip": "Api Key - Tooltip",
"App ID": "앱 ID",
"App ID - Tooltip": "앱 식별자",
"App key": "앱 키",
"App key - Tooltip": "앱 키",
"App secret": "앱 비밀키",
"AppSecret - Tooltip": "앱 비밀번호",
"Auth Key": "Auth Key",
"Auth Key - Tooltip": "Auth Key - Tooltip",
"Auth URL": "인증 URL",
"Auth URL - Tooltip": "인증 URL",
"Base URL": "Base URL",
"Base URL - Tooltip": "Base URL - Tooltip",
"Bucket": "양동이",
"Bucket - Tooltip": "양동이의 이름",
"Can not parse metadata": "메타데이터를 구문 분석할 수 없습니다",
@@ -649,6 +663,7 @@
"Enable QR code - Tooltip": "QR 코드를 스캔해서 로그인할 수 있는지 여부",
"Endpoint": "엔드포인트",
"Endpoint (Intranet)": "엔드포인트 (Intranet)",
"Endpoint - Tooltip": "Endpoint - Tooltip",
"From address": "From address",
"From address - Tooltip": "From address - Tooltip",
"From name": "From name",
@@ -674,9 +689,17 @@
"Please use WeChat and scan the QR code to sign in": "WeChat를 사용하시고 QR 코드를 스캔하여 로그인해주세요",
"Port": "포트",
"Port - Tooltip": "포트가 열려 있는지 확인하세요",
"Private Key": "Private Key",
"Private Key - Tooltip": "Private Key - Tooltip",
"Project Id": "Project Id",
"Project Id - Tooltip": "Project Id - Tooltip",
"Prompted": "자극 받은",
"Provider URL": "제공자 URL",
"Provider URL - Tooltip": "서비스 제공 업체 구성을 위한 URL이며, 이 필드는 참조 용도로만 사용되며 Casdoor에서 사용되지 않습니다",
"Public key": "Public key",
"Public key - Tooltip": "Public key - Tooltip",
"Region": "Region",
"Region - Tooltip": "Region - Tooltip",
"Region ID": "지역 ID",
"Region ID - Tooltip": "서비스 제공업체의 지역 ID",
"Region endpoint for Internet": "인터넷 지역 엔드포인트",
@@ -701,6 +724,8 @@
"Secret key - Tooltip": "검증을 위해 서버에서 인증 코드 공급자 API를 호출하는 데 사용됩니다",
"Send Testing Email": "테스트 이메일을 보내기",
"Send Testing SMS": "테스트 SMS를 보내세요",
"Sender Id": "Sender Id",
"Sender Id - Tooltip": "Sender Id - Tooltip",
"Sender number": "Sender number",
"Sender number - Tooltip": "Sender number - Tooltip",
"Sign Name": "신명서",
@@ -815,6 +840,7 @@
"Error text": "오류 메시지",
"Error text - Tooltip": "에러 텍스트",
"Is hashed": "해시화 되었습니다",
"Is key": "Is key",
"Is read-only": "Is read-only",
"Is read-only - Tooltip": "Is read-only - Tooltip",
"New Syncer": "신규 싱크어",

View File

@@ -1,6 +1,5 @@
{
"account": {
"Chats & Messages": "Chats & Messages",
"Logout": "Logout",
"My Account": "My Account",
"Sign Up": "Sign Up"
@@ -127,19 +126,6 @@
"Scope - Tooltip": "Usage scenarios of the certificate",
"Type - Tooltip": "Type of certificate"
},
"chat": {
"AI": "AI",
"Edit Chat": "Edit Chat",
"Group": "Group",
"Message count": "Message count",
"New Chat": "New Chat",
"Single": "Single",
"User1": "User1",
"User1 - Tooltip": "User1 - Tooltip",
"User2": "User2",
"User2 - Tooltip": "User2 - Tooltip",
"Users - Tooltip": "Users - Tooltip"
},
"code": {
"Code you received": "Code you received",
"Email code": "Email code",
@@ -179,22 +165,24 @@
"Adapter - Tooltip": "Table name of the policy store",
"Adapters": "Adapters",
"Add": "Add",
"Admin": "Admin",
"Affiliation URL": "Affiliation URL",
"Affiliation URL - Tooltip": "The homepage URL for the affiliation",
"Application": "Application",
"Application - Tooltip": "Application - Tooltip",
"Applications": "Applications",
"Applications that require authentication": "Applications that require authentication",
"Authorization": "Authorization",
"Avatar": "Avatar",
"Avatar - Tooltip": "Public avatar image for the user",
"Back": "Back",
"Back Home": "Back Home",
"Business & Payments": "Business & Payments",
"Cancel": "Cancel",
"Captcha": "Captcha",
"Cert": "Cert",
"Cert - Tooltip": "The public key certificate that needs to be verified by the client SDK corresponding to this application",
"Certs": "Certs",
"Chats": "Chats",
"Click to Upload": "Click to Upload",
"Client IP": "Client IP",
"Close": "Close",
@@ -224,7 +212,6 @@
"Failed to connect to server": "Failed to connect to server",
"Failed to delete": "Failed to delete",
"Failed to enable": "Failed to enable",
"Failed to get answer": "Failed to get answer",
"Failed to remove": "Failed to remove",
"Failed to save": "Failed to save",
"Failed to verify": "Failed to verify",
@@ -242,6 +229,7 @@
"Home - Tooltip": "Home page of the application",
"ID": "ID",
"ID - Tooltip": "Unique random string",
"Identity": "Identity",
"Is enabled": "Is enabled",
"Is enabled - Tooltip": "Set whether it can use",
"LDAPs": "LDAPs",
@@ -250,6 +238,7 @@
"Languages - Tooltip": "Available languages",
"Last name": "Last name",
"Later": "Later",
"Logging & Auditing": "Logging & Auditing",
"Logo": "Logo",
"Logo - Tooltip": "Icons that the application presents to the outside world",
"MFA items": "MFA items",
@@ -257,7 +246,6 @@
"Master password": "Master password",
"Master password - Tooltip": "Can be used to log in to all users under this organization, making it convenient for administrators to log in as this user to solve technical issues",
"Menu": "Menu",
"Messages": "Messages",
"Method": "Method",
"Model": "Model",
"Model - Tooltip": "Casbin access control model",
@@ -344,6 +332,7 @@
"Updated time": "Updated time",
"User": "User",
"User - Tooltip": "Make sure the username is correct",
"User Management": "User Management",
"User containers": "User pools",
"User type": "User type",
"User type - Tooltip": "Tags that the user belongs to, defaulting to \"normal-user\"",
@@ -425,16 +414,6 @@
"sign up now": "sign up now",
"username, Email or phone": "username, Email or phone"
},
"message": {
"Author": "Author",
"Author - Tooltip": "Author - Tooltip",
"Chat": "Chat",
"Chat - Tooltip": "Chat - Tooltip",
"Edit Message": "Edit Message",
"New Message": "New Message",
"Text": "Text",
"Text - Tooltip": "Text - Tooltip"
},
"mfa": {
"Each time you sign in to your Account, you'll need your password and a authentication code": "Each time you sign in to your Account, you'll need your password and a authentication code",
"Enable multi-factor authentication": "Enable multi-factor authentication",
@@ -508,6 +487,7 @@
"Currency - Tooltip": "Like USD, CNY, etc.",
"Download Invoice": "Download Invoice",
"Edit Payment": "Edit Payment",
"Failed reason": "Failed reason",
"Individual": "Individual",
"Invoice URL": "Invoice URL",
"Invoice URL - Tooltip": "URL for downloading the invoice",
@@ -541,6 +521,7 @@
"Product - Tooltip": "Product Name",
"Result": "Result",
"Return to Website": "Return to Website",
"The payment has been canceled": "The payment has been canceled",
"The payment has failed": "The payment has failed",
"The payment is still under processing": "The payment is still under processing",
"Type - Tooltip": "Payment method used when purchasing the product",
@@ -635,14 +616,20 @@
"Access key - Tooltip": "Access key",
"Agent ID": "Agent ID",
"Agent ID - Tooltip": "Agent ID",
"Api Key": "Api Key",
"Api Key - Tooltip": "Api Key - Tooltip",
"App ID": "App ID",
"App ID - Tooltip": "App ID",
"App key": "App key",
"App key - Tooltip": "App key",
"App secret": "App secret",
"AppSecret - Tooltip": "App secret",
"Auth Key": "Auth Key",
"Auth Key - Tooltip": "Auth Key - Tooltip",
"Auth URL": "Auth URL",
"Auth URL - Tooltip": "Auth URL",
"Base URL": "Base URL",
"Base URL - Tooltip": "Base URL - Tooltip",
"Bucket": "Bucket",
"Bucket - Tooltip": "Name of bucket",
"Can not parse metadata": "Can not parse metadata",
@@ -676,6 +663,7 @@
"Enable QR code - Tooltip": "Whether to allow scanning QR code to login",
"Endpoint": "Endpoint",
"Endpoint (Intranet)": "Endpoint (Intranet)",
"Endpoint - Tooltip": "Endpoint - Tooltip",
"From address": "From address",
"From address - Tooltip": "Email address of \"From\"",
"From name": "From name",
@@ -701,9 +689,17 @@
"Please use WeChat and scan the QR code to sign in": "Please use WeChat and scan the QR code to sign in",
"Port": "Port",
"Port - Tooltip": "Make sure the port is open",
"Private Key": "Private Key",
"Private Key - Tooltip": "Private Key - Tooltip",
"Project Id": "Project Id",
"Project Id - Tooltip": "Project Id - Tooltip",
"Prompted": "Prompted",
"Provider URL": "Provider URL",
"Provider URL - Tooltip": "URL for configuring the service provider, this field is only used for reference and is not used in Casdoor",
"Public key": "Public key",
"Public key - Tooltip": "Public key - Tooltip",
"Region": "Region",
"Region - Tooltip": "Region - Tooltip",
"Region ID": "Region ID",
"Region ID - Tooltip": "Region ID for the service provider",
"Region endpoint for Internet": "Region endpoint for Internet",
@@ -728,6 +724,8 @@
"Secret key - Tooltip": "Used by the server to call the verification code provider API for verification",
"Send Testing Email": "Send Testing Email",
"Send Testing SMS": "Send Testing SMS",
"Sender Id": "Sender Id",
"Sender Id - Tooltip": "Sender Id - Tooltip",
"Sender number": "Sender number",
"Sender number - Tooltip": "Sender number - Tooltip",
"Sign Name": "Sign Name",
@@ -842,6 +840,7 @@
"Error text": "Error text",
"Error text - Tooltip": "Error text",
"Is hashed": "Is hashed",
"Is key": "Is key",
"Is read-only": "Is read-only",
"Is read-only - Tooltip": "Is read-only - Tooltip",
"New Syncer": "New Syncer",

View File

@@ -165,16 +165,19 @@
"Adapter - Tooltip": "Nome da tabela do armazenamento de políticas",
"Adapters": "Adaptadores",
"Add": "Adicionar",
"Admin": "Admin",
"Affiliation URL": "URL da Afiliação",
"Affiliation URL - Tooltip": "A URL da página inicial para a afiliação",
"Application": "Aplicação",
"Application - Tooltip": "Application - Tooltip",
"Applications": "Aplicações",
"Applications that require authentication": "Aplicações que requerem autenticação",
"Authorization": "Authorization",
"Avatar": "Avatar",
"Avatar - Tooltip": "Imagem de avatar pública do usuário",
"Back": "Voltar",
"Back Home": "Voltar para a Página Inicial",
"Business & Payments": "Business & Payments",
"Cancel": "Cancelar",
"Captcha": "Captcha",
"Cert": "Certificado",
@@ -226,6 +229,7 @@
"Home - Tooltip": "Página inicial do aplicativo",
"ID": "ID",
"ID - Tooltip": "String única aleatória",
"Identity": "Identity",
"Is enabled": "Está habilitado",
"Is enabled - Tooltip": "Define se está habilitado",
"LDAPs": "LDAPs",
@@ -234,6 +238,7 @@
"Languages - Tooltip": "Idiomas disponíveis",
"Last name": "Sobrenome",
"Later": "Later",
"Logging & Auditing": "Logging & Auditing",
"Logo": "Logo",
"Logo - Tooltip": "Ícones que o aplicativo apresenta para o mundo externo",
"MFA items": "MFA items",
@@ -327,6 +332,7 @@
"Updated time": "Hora de Atualização",
"User": "Usuário",
"User - Tooltip": "Certifique-se de que o nome de usuário esteja correto",
"User Management": "User Management",
"User containers": "Pools de Usuários",
"User type": "Tipo de Usuário",
"User type - Tooltip": "Tags às quais o usuário pertence, com valor padrão de \"usuário-normal\"",
@@ -481,6 +487,7 @@
"Currency - Tooltip": "Como USD, CNY, etc.",
"Download Invoice": "Baixar Fatura",
"Edit Payment": "Editar Pagamento",
"Failed reason": "Failed reason",
"Individual": "Individual",
"Invoice URL": "URL da Fatura",
"Invoice URL - Tooltip": "URL para baixar a fatura",
@@ -514,6 +521,7 @@
"Product - Tooltip": "Nome do Produto",
"Result": "Resultado",
"Return to Website": "Retornar ao Website",
"The payment has been canceled": "The payment has been canceled",
"The payment has failed": "O pagamento falhou",
"The payment is still under processing": "O pagamento ainda está sendo processado",
"Type - Tooltip": "Método de pagamento utilizado ao comprar o produto",
@@ -608,14 +616,20 @@
"Access key - Tooltip": "Chave de acesso",
"Agent ID": "ID do Agente",
"Agent ID - Tooltip": "ID do Agente",
"Api Key": "Api Key",
"Api Key - Tooltip": "Api Key - Tooltip",
"App ID": "ID do aplicativo",
"App ID - Tooltip": "ID do aplicativo",
"App key": "Chave do aplicativo",
"App key - Tooltip": "Chave do aplicativo",
"App secret": "Segredo do aplicativo",
"AppSecret - Tooltip": "Segredo do aplicativo",
"Auth Key": "Auth Key",
"Auth Key - Tooltip": "Auth Key - Tooltip",
"Auth URL": "URL de autenticação",
"Auth URL - Tooltip": "URL de autenticação",
"Base URL": "Base URL",
"Base URL - Tooltip": "Base URL - Tooltip",
"Bucket": "Bucket",
"Bucket - Tooltip": "Nome do bucket",
"Can not parse metadata": "Não é possível analisar metadados",
@@ -649,6 +663,7 @@
"Enable QR code - Tooltip": "Se permite escanear código QR para fazer login",
"Endpoint": "Endpoint",
"Endpoint (Intranet)": "Endpoint (Intranet)",
"Endpoint - Tooltip": "Endpoint - Tooltip",
"From address": "Endereço do remetente",
"From address - Tooltip": "Endereço de e-mail do remetente",
"From name": "Nome do remetente",
@@ -674,9 +689,17 @@
"Please use WeChat and scan the QR code to sign in": "Por favor, use o WeChat e escaneie o código QR para fazer login",
"Port": "Porta",
"Port - Tooltip": "Certifique-se de que a porta esteja aberta",
"Private Key": "Private Key",
"Private Key - Tooltip": "Private Key - Tooltip",
"Project Id": "Project Id",
"Project Id - Tooltip": "Project Id - Tooltip",
"Prompted": "Solicitado",
"Provider URL": "URL do Provedor",
"Provider URL - Tooltip": "URL para configurar o provedor de serviço, este campo é apenas usado para referência e não é usado no Casdoor",
"Public key": "Public key",
"Public key - Tooltip": "Public key - Tooltip",
"Region": "Region",
"Region - Tooltip": "Region - Tooltip",
"Region ID": "ID da Região",
"Region ID - Tooltip": "ID da região para o provedor de serviços",
"Region endpoint for Internet": "Endpoint da região para a Internet",
@@ -701,6 +724,8 @@
"Secret key - Tooltip": "Usada pelo servidor para chamar a API do fornecedor de código de verificação para verificação",
"Send Testing Email": "Enviar E-mail de Teste",
"Send Testing SMS": "Enviar SMS de Teste",
"Sender Id": "Sender Id",
"Sender Id - Tooltip": "Sender Id - Tooltip",
"Sender number": "Sender number",
"Sender number - Tooltip": "Sender number - Tooltip",
"Sign Name": "Nome do Sinal",
@@ -815,6 +840,7 @@
"Error text": "Texto de erro",
"Error text - Tooltip": "Texto de erro",
"Is hashed": "Está criptografado",
"Is key": "Is key",
"Is read-only": "Is read-only",
"Is read-only - Tooltip": "Is read-only - Tooltip",
"New Syncer": "Novo Syncer",

View File

@@ -165,16 +165,19 @@
"Adapter - Tooltip": "Имя таблицы хранилища политик",
"Adapters": "Адаптеры",
"Add": "Добавить",
"Admin": "Admin",
"Affiliation URL": "URL принадлежности",
"Affiliation URL - Tooltip": "URL домашней страницы для аффилированности",
"Application": "Приложение",
"Application - Tooltip": "Application - Tooltip",
"Applications": "Приложения",
"Applications that require authentication": "Приложения, которые требуют аутентификации",
"Authorization": "Authorization",
"Avatar": "Аватар",
"Avatar - Tooltip": "Публичное изображение аватара пользователя",
"Back": "Back",
"Back Home": "Домой",
"Business & Payments": "Business & Payments",
"Cancel": "Отменить",
"Captcha": "Капча",
"Cert": "Сертификат",
@@ -226,6 +229,7 @@
"Home - Tooltip": "Главная страница приложения",
"ID": "ID",
"ID - Tooltip": "Уникальная случайная строка",
"Identity": "Identity",
"Is enabled": "Включен",
"Is enabled - Tooltip": "Установить, может ли использоваться",
"LDAPs": "LDAPs",
@@ -234,6 +238,7 @@
"Languages - Tooltip": "Доступные языки",
"Last name": "Фамилия",
"Later": "Later",
"Logging & Auditing": "Logging & Auditing",
"Logo": "Логотип",
"Logo - Tooltip": "Иконки, которые приложение представляет во внешний мир",
"MFA items": "MFA items",
@@ -327,6 +332,7 @@
"Updated time": "Updated time",
"User": "Пользователь",
"User - Tooltip": "Убедитесь, что имя пользователя правильное",
"User Management": "User Management",
"User containers": "Пользовательские пулы",
"User type": "Тип пользователя",
"User type - Tooltip": "Теги, к которым принадлежит пользователь, по умолчанию \"обычный пользователь\"",
@@ -481,6 +487,7 @@
"Currency - Tooltip": "Как и USD, CNY и т.д.",
"Download Invoice": "Загрузить счет-фактуру",
"Edit Payment": "Редактировать оплату",
"Failed reason": "Failed reason",
"Individual": "Индивидуальный",
"Invoice URL": "URL счета-фактуры",
"Invoice URL - Tooltip": "URL для загрузки счета-фактуры",
@@ -514,6 +521,7 @@
"Product - Tooltip": "Название продукта",
"Result": "Результат",
"Return to Website": "Вернуться на веб-сайт",
"The payment has been canceled": "The payment has been canceled",
"The payment has failed": "Оплата не удалась",
"The payment is still under processing": "Оплата все еще обрабатывается",
"Type - Tooltip": "Способ оплаты, используемый при покупке товара",
@@ -608,14 +616,20 @@
"Access key - Tooltip": "Ключ доступа",
"Agent ID": "Идентификатор агента",
"Agent ID - Tooltip": "Агент ID",
"Api Key": "Api Key",
"Api Key - Tooltip": "Api Key - Tooltip",
"App ID": "Идентификатор приложения",
"App ID - Tooltip": "Идентификатор приложения",
"App key": "Ключ приложения",
"App key - Tooltip": "Ключ приложения",
"App secret": "Секрет приложения",
"AppSecret - Tooltip": "Секрет приложения",
"Auth Key": "Auth Key",
"Auth Key - Tooltip": "Auth Key - Tooltip",
"Auth URL": "Адрес авторизации",
"Auth URL - Tooltip": "URL авторизации",
"Base URL": "Base URL",
"Base URL - Tooltip": "Base URL - Tooltip",
"Bucket": "Ведро",
"Bucket - Tooltip": "Название ведра",
"Can not parse metadata": "Невозможно проанализировать метаданные",
@@ -649,6 +663,7 @@
"Enable QR code - Tooltip": "Разрешить ли сканирование QR-кода для входа в систему",
"Endpoint": "Конечная точка",
"Endpoint (Intranet)": "Конечная точка (интранет)",
"Endpoint - Tooltip": "Endpoint - Tooltip",
"From address": "From address",
"From address - Tooltip": "From address - Tooltip",
"From name": "From name",
@@ -674,9 +689,17 @@
"Please use WeChat and scan the QR code to sign in": "Пожалуйста, используйте WeChat и отсканируйте QR-код для входа в систему",
"Port": "Порт",
"Port - Tooltip": "Убедитесь, что порт открыт",
"Private Key": "Private Key",
"Private Key - Tooltip": "Private Key - Tooltip",
"Project Id": "Project Id",
"Project Id - Tooltip": "Project Id - Tooltip",
"Prompted": "Побудил",
"Provider URL": "URL поставщика",
"Provider URL - Tooltip": "URL для настройки поставщика услуг, это поле используется только для ссылки и не используется в Casdoor",
"Public key": "Public key",
"Public key - Tooltip": "Public key - Tooltip",
"Region": "Region",
"Region - Tooltip": "Region - Tooltip",
"Region ID": "Идентификатор региона",
"Region ID - Tooltip": "Идентификатор региона для провайдера услуг",
"Region endpoint for Internet": "Региональный конечная точка для Интернета",
@@ -701,6 +724,8 @@
"Secret key - Tooltip": "Используется сервером для вызова API-интерфейса поставщика кода подтверждения для проверки",
"Send Testing Email": "Отправить тестовое письмо",
"Send Testing SMS": "Отправить тестовое SMS-сообщение",
"Sender Id": "Sender Id",
"Sender Id - Tooltip": "Sender Id - Tooltip",
"Sender number": "Sender number",
"Sender number - Tooltip": "Sender number - Tooltip",
"Sign Name": "Подпись имени",
@@ -815,6 +840,7 @@
"Error text": "Текст ошибки",
"Error text - Tooltip": "Текст ошибки",
"Is hashed": "Хешировано",
"Is key": "Is key",
"Is read-only": "Is read-only",
"Is read-only - Tooltip": "Is read-only - Tooltip",
"New Syncer": "Новый синхронизатор",

View File

@@ -1,6 +1,5 @@
{
"account": {
"Chats & Messages": "Chats & Messages",
"Logout": "Logout",
"My Account": "My Account",
"Sign Up": "Sign Up"
@@ -127,19 +126,6 @@
"Scope - Tooltip": "Usage scenarios of the certificate",
"Type - Tooltip": "Type of certificate"
},
"chat": {
"AI": "AI",
"Edit Chat": "Edit Chat",
"Group": "Group",
"Message count": "Message count",
"New Chat": "New Chat",
"Single": "Single",
"User1": "User1",
"User1 - Tooltip": "User1 - Tooltip",
"User2": "User2",
"User2 - Tooltip": "User2 - Tooltip",
"Users - Tooltip": "Users - Tooltip"
},
"code": {
"Code you received": "Code you received",
"Email code": "Email code",
@@ -179,22 +165,24 @@
"Adapter - Tooltip": "Table name of the policy store",
"Adapters": "Adapters",
"Add": "Add",
"Admin": "Admin",
"Affiliation URL": "Affiliation URL",
"Affiliation URL - Tooltip": "The homepage URL for the affiliation",
"Application": "Application",
"Application - Tooltip": "Application - Tooltip",
"Applications": "Applications",
"Applications that require authentication": "Applications that require authentication",
"Authorization": "Authorization",
"Avatar": "Avatar",
"Avatar - Tooltip": "Public avatar image for the user",
"Back": "Back",
"Back Home": "Back Home",
"Business & Payments": "Business & Payments",
"Cancel": "Cancel",
"Captcha": "Captcha",
"Cert": "Cert",
"Cert - Tooltip": "The public key certificate that needs to be verified by the client SDK corresponding to this application",
"Certs": "Certs",
"Chats": "Chats",
"Click to Upload": "Click to Upload",
"Client IP": "Client IP",
"Close": "Close",
@@ -224,7 +212,6 @@
"Failed to connect to server": "Failed to connect to server",
"Failed to delete": "Failed to delete",
"Failed to enable": "Failed to enable",
"Failed to get answer": "Failed to get answer",
"Failed to remove": "Failed to remove",
"Failed to save": "Failed to save",
"Failed to verify": "Failed to verify",
@@ -242,6 +229,7 @@
"Home - Tooltip": "Home page of the application",
"ID": "ID",
"ID - Tooltip": "Unique random string",
"Identity": "Identity",
"Is enabled": "Is enabled",
"Is enabled - Tooltip": "Set whether it can use",
"LDAPs": "LDAPs",
@@ -250,6 +238,7 @@
"Languages - Tooltip": "Available languages",
"Last name": "Last name",
"Later": "Later",
"Logging & Auditing": "Logging & Auditing",
"Logo": "Logo",
"Logo - Tooltip": "Icons that the application presents to the outside world",
"MFA items": "MFA items",
@@ -257,7 +246,6 @@
"Master password": "Master password",
"Master password - Tooltip": "Can be used to log in to all users under this organization, making it convenient for administrators to log in as this user to solve technical issues",
"Menu": "Menu",
"Messages": "Messages",
"Method": "Method",
"Model": "Model",
"Model - Tooltip": "Casbin access control model",
@@ -344,6 +332,7 @@
"Updated time": "Updated time",
"User": "User",
"User - Tooltip": "Make sure the username is correct",
"User Management": "User Management",
"User containers": "User pools",
"User type": "User type",
"User type - Tooltip": "Tags that the user belongs to, defaulting to \"normal-user\"",
@@ -425,16 +414,6 @@
"sign up now": "sign up now",
"username, Email or phone": "username, Email or phone"
},
"message": {
"Author": "Author",
"Author - Tooltip": "Author - Tooltip",
"Chat": "Chat",
"Chat - Tooltip": "Chat - Tooltip",
"Edit Message": "Edit Message",
"New Message": "New Message",
"Text": "Text",
"Text - Tooltip": "Text - Tooltip"
},
"mfa": {
"Each time you sign in to your Account, you'll need your password and a authentication code": "Each time you sign in to your Account, you'll need your password and a authentication code",
"Enable multi-factor authentication": "Enable multi-factor authentication",
@@ -508,6 +487,7 @@
"Currency - Tooltip": "Like USD, CNY, etc.",
"Download Invoice": "Download Invoice",
"Edit Payment": "Edit Payment",
"Failed reason": "Failed reason",
"Individual": "Individual",
"Invoice URL": "Invoice URL",
"Invoice URL - Tooltip": "URL for downloading the invoice",
@@ -541,6 +521,7 @@
"Product - Tooltip": "Product Name",
"Result": "Result",
"Return to Website": "Return to Website",
"The payment has been canceled": "The payment has been canceled",
"The payment has failed": "The payment has failed",
"The payment is still under processing": "The payment is still under processing",
"Type - Tooltip": "Payment method used when purchasing the product",
@@ -635,14 +616,20 @@
"Access key - Tooltip": "Access key",
"Agent ID": "Agent ID",
"Agent ID - Tooltip": "Agent ID",
"Api Key": "Api Key",
"Api Key - Tooltip": "Api Key - Tooltip",
"App ID": "App ID",
"App ID - Tooltip": "App ID",
"App key": "App key",
"App key - Tooltip": "App key",
"App secret": "App secret",
"AppSecret - Tooltip": "App secret",
"Auth Key": "Auth Key",
"Auth Key - Tooltip": "Auth Key - Tooltip",
"Auth URL": "Auth URL",
"Auth URL - Tooltip": "Auth URL",
"Base URL": "Base URL",
"Base URL - Tooltip": "Base URL - Tooltip",
"Bucket": "Bucket",
"Bucket - Tooltip": "Name of bucket",
"Can not parse metadata": "Can not parse metadata",
@@ -676,6 +663,7 @@
"Enable QR code - Tooltip": "Whether to allow scanning QR code to login",
"Endpoint": "Endpoint",
"Endpoint (Intranet)": "Endpoint (Intranet)",
"Endpoint - Tooltip": "Endpoint - Tooltip",
"From address": "From address",
"From address - Tooltip": "Email address of \"From\"",
"From name": "From name",
@@ -701,9 +689,17 @@
"Please use WeChat and scan the QR code to sign in": "Please use WeChat and scan the QR code to sign in",
"Port": "Port",
"Port - Tooltip": "Make sure the port is open",
"Private Key": "Private Key",
"Private Key - Tooltip": "Private Key - Tooltip",
"Project Id": "Project Id",
"Project Id - Tooltip": "Project Id - Tooltip",
"Prompted": "Prompted",
"Provider URL": "Provider URL",
"Provider URL - Tooltip": "URL for configuring the service provider, this field is only used for reference and is not used in Casdoor",
"Public key": "Public key",
"Public key - Tooltip": "Public key - Tooltip",
"Region": "Region",
"Region - Tooltip": "Region - Tooltip",
"Region ID": "Region ID",
"Region ID - Tooltip": "Region ID for the service provider",
"Region endpoint for Internet": "Region endpoint for Internet",
@@ -728,6 +724,8 @@
"Secret key - Tooltip": "Used by the server to call the verification code provider API for verification",
"Send Testing Email": "Send Testing Email",
"Send Testing SMS": "Send Testing SMS",
"Sender Id": "Sender Id",
"Sender Id - Tooltip": "Sender Id - Tooltip",
"Sender number": "Sender number",
"Sender number - Tooltip": "Sender number - Tooltip",
"Sign Name": "Sign Name",
@@ -842,6 +840,7 @@
"Error text": "Error text",
"Error text - Tooltip": "Error text",
"Is hashed": "Is hashed",
"Is key": "Is key",
"Is read-only": "Is read-only",
"Is read-only - Tooltip": "Is read-only - Tooltip",
"New Syncer": "New Syncer",

View File

@@ -165,16 +165,19 @@
"Adapter - Tooltip": "Tên bảng của kho lưu trữ chính sách",
"Adapters": "Bộ chuyển đổi",
"Add": "Thêm vào",
"Admin": "Admin",
"Affiliation URL": "Đường dẫn liên kết liên kết",
"Affiliation URL - Tooltip": "Đường dẫn URL trang chủ của liên kết",
"Application": "Ứng dụng",
"Application - Tooltip": "Application - Tooltip",
"Applications": "Ứng dụng",
"Applications that require authentication": "Các ứng dụng yêu cầu xác thực",
"Authorization": "Authorization",
"Avatar": "Ảnh đại diện",
"Avatar - Tooltip": "Ảnh đại diện công khai cho người dùng",
"Back": "Back",
"Back Home": "Trở về nhà",
"Business & Payments": "Business & Payments",
"Cancel": "Hủy bỏ",
"Captcha": "Captcha",
"Cert": "Chứng chỉ",
@@ -226,6 +229,7 @@
"Home - Tooltip": "Trang chủ của ứng dụng",
"ID": "ID",
"ID - Tooltip": "Chuỗi ngẫu nhiên độc nhất",
"Identity": "Identity",
"Is enabled": "Đã được kích hoạt",
"Is enabled - Tooltip": "Đặt liệu nó có thể sử dụng hay không",
"LDAPs": "LDAPs",
@@ -234,6 +238,7 @@
"Languages - Tooltip": "Các ngôn ngữ hiện có",
"Last name": "Họ",
"Later": "Later",
"Logging & Auditing": "Logging & Auditing",
"Logo": "Logo",
"Logo - Tooltip": "Biểu tượng mà ứng dụng hiển thị ra ngoài thế giới",
"MFA items": "MFA items",
@@ -327,6 +332,7 @@
"Updated time": "Updated time",
"User": "Người dùng",
"User - Tooltip": "Hãy đảm bảo tên đăng nhập chính xác",
"User Management": "User Management",
"User containers": "Nhóm người dùng",
"User type": "Loại người dùng",
"User type - Tooltip": "Các thẻ mà người dùng thuộc vào, mặc định là \"người dùng bình thường\"",
@@ -481,6 +487,7 @@
"Currency - Tooltip": "Như USD, CNY, v.v.",
"Download Invoice": "Tải hóa đơn",
"Edit Payment": "Chỉnh sửa thanh toán",
"Failed reason": "Failed reason",
"Individual": "Cá nhân",
"Invoice URL": "Đường link hoá đơn",
"Invoice URL - Tooltip": "Đường link để tải hóa đơn xuống",
@@ -514,6 +521,7 @@
"Product - Tooltip": "Tên sản phẩm",
"Result": "Kết quả",
"Return to Website": "Trở lại trang web",
"The payment has been canceled": "The payment has been canceled",
"The payment has failed": "Thanh toán đã thất bại",
"The payment is still under processing": "Thanh toán vẫn đang được xử lý",
"Type - Tooltip": "Phương thức thanh toán được sử dụng khi mua sản phẩm",
@@ -608,14 +616,20 @@
"Access key - Tooltip": "Khóa truy cập",
"Agent ID": "Mã đại lý",
"Agent ID - Tooltip": "Mã đại lý",
"Api Key": "Api Key",
"Api Key - Tooltip": "Api Key - Tooltip",
"App ID": "ID ứng dụng",
"App ID - Tooltip": "Định danh ứng dụng",
"App key": "Khóa ứng dụng",
"App key - Tooltip": "Khóa ứng dụng",
"App secret": "Mã bí mật ứng dụng",
"AppSecret - Tooltip": "Bí mật ứng dụng",
"Auth Key": "Auth Key",
"Auth Key - Tooltip": "Auth Key - Tooltip",
"Auth URL": "URL xác thực",
"Auth URL - Tooltip": "URL chứng thực",
"Base URL": "Base URL",
"Base URL - Tooltip": "Base URL - Tooltip",
"Bucket": "Thùng đựng nước",
"Bucket - Tooltip": "Tên của cái xô",
"Can not parse metadata": "Không thể phân tích siêu dữ liệu",
@@ -649,6 +663,7 @@
"Enable QR code - Tooltip": "Cho phép quét mã QR để đăng nhập",
"Endpoint": "Điểm cuối",
"Endpoint (Intranet)": "Điểm kết thúc (mạng nội bộ)",
"Endpoint - Tooltip": "Endpoint - Tooltip",
"From address": "From address",
"From address - Tooltip": "From address - Tooltip",
"From name": "From name",
@@ -674,9 +689,17 @@
"Please use WeChat and scan the QR code to sign in": "Vui lòng sử dụng WeChat và quét mã QR để đăng nhập",
"Port": "Cảng",
"Port - Tooltip": "Chắc chắn rằng cổng đang mở",
"Private Key": "Private Key",
"Private Key - Tooltip": "Private Key - Tooltip",
"Project Id": "Project Id",
"Project Id - Tooltip": "Project Id - Tooltip",
"Prompted": "Thúc đẩy",
"Provider URL": "Địa chỉ URL nhà cung cấp",
"Provider URL - Tooltip": "URL để cấu hình nhà cung cấp dịch vụ, trường này chỉ được sử dụng để tham khảo và không được sử dụng trong Casdoor",
"Public key": "Public key",
"Public key - Tooltip": "Public key - Tooltip",
"Region": "Region",
"Region - Tooltip": "Region - Tooltip",
"Region ID": "Định danh khu vực",
"Region ID - Tooltip": "Định danh khu vực cho nhà cung cấp dịch vụ",
"Region endpoint for Internet": "Điểm cuối khu vực cho Internet",
@@ -701,6 +724,8 @@
"Secret key - Tooltip": "Được sử dụng bởi máy chủ để gọi API nhà cung cấp mã xác minh để xác minh",
"Send Testing Email": "Gửi Email kiểm tra",
"Send Testing SMS": "Gửi SMS kiểm tra",
"Sender Id": "Sender Id",
"Sender Id - Tooltip": "Sender Id - Tooltip",
"Sender number": "Sender number",
"Sender number - Tooltip": "Sender number - Tooltip",
"Sign Name": "Ký tên",
@@ -815,6 +840,7 @@
"Error text": "Văn bản lỗi",
"Error text - Tooltip": "Văn bản lỗi",
"Is hashed": "Đã được băm mã hóa",
"Is key": "Is key",
"Is read-only": "Is read-only",
"Is read-only - Tooltip": "Is read-only - Tooltip",
"New Syncer": "New Syncer: Đồng bộ mới",

View File

@@ -139,8 +139,8 @@
"Submit and complete": "完成提交"
},
"enforcer": {
"Edit Enforcer": "Edit Enforcer",
"New Enforcer": "New Enforcer"
"Edit Enforcer": "编辑Casbin执行器",
"New Enforcer": "新建Casbin执行器"
},
"forget": {
"Account": "账号",
@@ -163,18 +163,21 @@
"Action": "操作",
"Adapter": "适配器",
"Adapter - Tooltip": "策略存储的表名",
"Adapters": "适配器",
"Adapters": "Casbin适配器",
"Add": "添加",
"Admin": "管理工具",
"Affiliation URL": "工作单位URL",
"Affiliation URL - Tooltip": "工作单位的官网URL",
"Application": "应用",
"Application - Tooltip": "Application - Tooltip",
"Applications": "应用",
"Applications that require authentication": "需要认证和鉴权的应用",
"Authorization": "Casbin权限管理",
"Avatar": "头像",
"Avatar - Tooltip": "公开展示的用户头像",
"Back": "返回",
"Back Home": "返回到首页",
"Business & Payments": "商业 & 付款",
"Cancel": "取消",
"Captcha": "人机验证码",
"Cert": "证书",
@@ -204,7 +207,7 @@
"Enable": "启用",
"Enabled": "已开启",
"Enabled successfully": "启用成功",
"Enforcers": "Enforcers",
"Enforcers": "Casbin执行器",
"Failed to add": "添加失败",
"Failed to connect to server": "连接服务器失败",
"Failed to delete": "删除失败",
@@ -226,6 +229,7 @@
"Home - Tooltip": "应用的首页",
"ID": "ID",
"ID - Tooltip": "唯一的随机字符串",
"Identity": "身份认证",
"Is enabled": "已启用",
"Is enabled - Tooltip": "是否启用",
"LDAPs": "LDAP",
@@ -234,6 +238,7 @@
"Languages - Tooltip": "可选语言",
"Last name": "姓氏",
"Later": "稍后",
"Logging & Auditing": "日志 & 审计",
"Logo": "Logo",
"Logo - Tooltip": "应用程序向外展示的图标",
"MFA items": "MFA 项",
@@ -244,7 +249,7 @@
"Method": "方法",
"Model": "模型",
"Model - Tooltip": "Casbin的访问控制模型",
"Models": "模型",
"Models": "Casbin模型",
"Name": "名称",
"Name - Tooltip": "唯一的、字符串式的ID",
"None": "无",
@@ -327,6 +332,7 @@
"Updated time": "更新时间",
"User": "用户",
"User - Tooltip": "请确保用户名正确",
"User Management": "用户管理",
"User containers": "用户池",
"User type": "用户类型",
"User type - Tooltip": "用户所属的标签,默认为\"normal-user\"",
@@ -481,6 +487,7 @@
"Currency - Tooltip": "如USD美元CNY人民币等",
"Download Invoice": "下载发票",
"Edit Payment": "编辑付款",
"Failed reason": "失败原因",
"Individual": "个人",
"Invoice URL": "发票URL",
"Invoice URL - Tooltip": "发票的下载地址URL",
@@ -514,6 +521,7 @@
"Product - Tooltip": "商品名称",
"Result": "结果",
"Return to Website": "返回原网站",
"The payment has been canceled": "付款已取消",
"The payment has failed": "支付失败",
"The payment is still under processing": "支付正在处理",
"Type - Tooltip": "商品购买时的支付方式",
@@ -608,14 +616,20 @@
"Access key - Tooltip": "Access key",
"Agent ID": "Agent ID",
"Agent ID - Tooltip": "Agent ID",
"Api Key": "Api Key",
"Api Key - Tooltip": "Api Key - Tooltip",
"App ID": "App ID",
"App ID - Tooltip": "App ID",
"App key": "App key",
"App key - Tooltip": "App key",
"App secret": "App secret",
"AppSecret - Tooltip": "App secret",
"Auth Key": "Auth Key",
"Auth Key - Tooltip": "Auth Key - Tooltip",
"Auth URL": "Auth URL",
"Auth URL - Tooltip": "Auth URL",
"Base URL": "Base URL",
"Base URL - Tooltip": "Base URL - Tooltip",
"Bucket": "存储桶",
"Bucket - Tooltip": "Bucket名称",
"Can not parse metadata": "无法解析元数据",
@@ -649,6 +663,7 @@
"Enable QR code - Tooltip": "是否允许扫描二维码登录",
"Endpoint": "地域节点 (外网)",
"Endpoint (Intranet)": "地域节点 (内网)",
"Endpoint - Tooltip": "Endpoint - Tooltip",
"From address": "发件人地址",
"From address - Tooltip": "邮件里发件人的邮箱地址",
"From name": "发件人名称",
@@ -674,9 +689,17 @@
"Please use WeChat and scan the QR code to sign in": "请使用微信扫描二维码登录",
"Port": "端口",
"Port - Tooltip": "请确保端口号打开",
"Private Key": "Private Key",
"Private Key - Tooltip": "Private Key - Tooltip",
"Project Id": "Project Id",
"Project Id - Tooltip": "Project Id - Tooltip",
"Prompted": "注册后提醒绑定",
"Provider URL": "提供商URL",
"Provider URL - Tooltip": "提供商网址配置对应的URL该字段仅用来方便跳转在Casdoor平台中未使用",
"Public key": "Public key",
"Public key - Tooltip": "Public key - Tooltip",
"Region": "Region",
"Region - Tooltip": "Region - Tooltip",
"Region ID": "地域ID",
"Region ID - Tooltip": "提供商服务所属的地域ID",
"Region endpoint for Internet": "地域节点 (外网)",
@@ -701,6 +724,8 @@
"Secret key - Tooltip": "用于服务端调用验证码提供商API进行验证",
"Send Testing Email": "发送测试邮件",
"Send Testing SMS": "发送测试短信",
"Sender Id": "Sender Id",
"Sender Id - Tooltip": "Sender Id - Tooltip",
"Sender number": "Sender number",
"Sender number - Tooltip": "Sender number - Tooltip",
"Sign Name": "签名名称",
@@ -815,7 +840,8 @@
"Error text": "错误信息",
"Error text - Tooltip": "错误信息",
"Is hashed": "是否参与哈希计算",
"Is read-only": "Is read-only",
"Is key": "是否为主键",
"Is read-only": "是否只读",
"Is read-only - Tooltip": "Is read-only - Tooltip",
"New Syncer": "添加同步器",
"Sync interval": "同步间隔",

View File

@@ -287,10 +287,10 @@ class PolicyTable extends React.Component {
) : (
<div>
<Tooltip placement="topLeft" title="Edit">
<Button disabled={this.state.editingIndex !== ""} style={{marginRight: "5px"}} icon={<EditOutlined />} size="small" onClick={() => this.edit(record, index)} />
<Button disabled={this.state.editingIndex !== "" || Setting.builtInObject({owner: this.props.owner, name: this.props.name})} style={{marginRight: "5px"}} icon={<EditOutlined />} size="small" onClick={() => this.edit(record, index)} />
</Tooltip>
<Tooltip placement="topLeft" title="Delete">
<Button disabled={this.state.editingIndex !== ""} style={{marginRight: "5px"}} icon={<DeleteOutlined />} size="small" onClick={() => this.deletePolicy(table, index)} />
<Button disabled={this.state.editingIndex !== "" || Setting.builtInObject({owner: this.props.owner, name: this.props.name})} style={{marginRight: "5px"}} icon={<DeleteOutlined />} size="small" onClick={() => this.deletePolicy(table, index)} />
</Tooltip>
</div>
);
@@ -304,14 +304,14 @@ class PolicyTable extends React.Component {
onChange: (page) => this.setState({
page: page,
}),
disabled: this.state.editingIndex !== "",
disabled: this.state.editingIndex !== "" || Setting.builtInObject({owner: this.props.owner, name: this.props.name}),
current: this.state.page,
}}
columns={columns} dataSource={table} rowKey="key" size="middle" bordered
loading={this.state.loading}
title={() => (
<div>
<Button disabled={this.state.editingIndex !== ""} style={{marginRight: "5px"}} type="primary" size="small" onClick={() => this.addRow(table)}>{i18next.t("general:Add")}</Button>
<Button disabled={this.state.editingIndex !== "" || Setting.builtInObject({owner: this.props.owner, name: this.props.name})} style={{marginRight: "5px"}} type="primary" size="small" onClick={() => this.addRow(table)}>{i18next.t("general:Add")}</Button>
</div>
)}
/>

View File

@@ -38,7 +38,7 @@ class SyncerTableColumnTable extends React.Component {
}
addRow(table) {
const row = {name: `column${table.length}`, type: "string", values: []};
const row = {name: `column${table.length}`, type: "string", values: [], isKey: table.filter(row => row.isKey).length === 0};
if (table === undefined) {
table = [];
}
@@ -107,6 +107,26 @@ class SyncerTableColumnTable extends React.Component {
);
},
},
{
title: i18next.t("syncer:Is key"),
dataIndex: "isKey",
key: "isKey",
render: (text, record, index) => {
return (
<Switch checked={text} onChange={checked => {
if (!record.isKey && checked) {
table.forEach((row, i) => {
this.updateField(table, i, "isKey", false);
});
} else if (record.isKey && !checked) {
return;
}
this.updateField(table, index, "isKey", checked);
}} />
);
},
},
{
title: i18next.t("syncer:Is hashed"),
dataIndex: "isHashed",
@@ -133,7 +153,7 @@ class SyncerTableColumnTable extends React.Component {
<Button style={{marginRight: "5px"}} disabled={index === table.length - 1} icon={<DownOutlined />} size="small" onClick={() => this.downRow(table, index)} />
</Tooltip>
<Tooltip placement="topLeft" title={i18next.t("general:Delete")}>
<Button icon={<DeleteOutlined />} size="small" onClick={() => this.deleteRow(table, index)} />
<Button icon={<DeleteOutlined />} disabled={record.isKey && table.length > 1} size="small" onClick={() => this.deleteRow(table, index)} />
</Tooltip>
</div>
);

View File

@@ -29,7 +29,20 @@
dependencies:
"@ctrl/tinycolor" "^3.4.0"
"@ant-design/cssinjs@^1", "@ant-design/cssinjs@^1.10.1", "@ant-design/cssinjs@^1.5.6", "@ant-design/cssinjs@^1.8.1":
"@ant-design/cssinjs@1.16.1":
version "1.16.1"
resolved "https://registry.yarnpkg.com/@ant-design/cssinjs/-/cssinjs-1.16.1.tgz#0032044db5678dd25ac12def1abb1d52e6a4d583"
integrity sha512-KKVB5Or6BDC1Bo3Y4KMlOkyQU0P+6GTodubrQ9YfrtXG1TgO4wpaEfg9I4ZA49R7M+Ij2KKNwb+5abvmXy6K8w==
dependencies:
"@babel/runtime" "^7.11.1"
"@emotion/hash" "^0.8.0"
"@emotion/unitless" "^0.7.5"
classnames "^2.3.1"
csstype "^3.0.10"
rc-util "^5.35.0"
stylis "^4.0.13"
"@ant-design/cssinjs@^1", "@ant-design/cssinjs@^1.10.1", "@ant-design/cssinjs@^1.5.6":
version "1.10.1"
resolved "https://registry.yarnpkg.com/@ant-design/cssinjs/-/cssinjs-1.10.1.tgz#c9173f38e3d61f0883ca3c17d7cf1e30784e0dd7"
integrity sha512-PSoJS8RMzn95ZRg007dJGr6AU0Zim/O+tTN0xmXmh9CkIl4y3wuOr2Zhehaj7s130wPSYDVvahf3DKT50w/Zhw==
@@ -10100,6 +10113,14 @@ rc-util@^5.0.1, rc-util@^5.0.6, rc-util@^5.15.0, rc-util@^5.16.0, rc-util@^5.16.
"@babel/runtime" "^7.18.3"
react-is "^16.12.0"
rc-util@^5.35.0:
version "5.35.0"
resolved "https://registry.yarnpkg.com/rc-util/-/rc-util-5.35.0.tgz#bed1986248b7be525cc0894109e609ac60207f29"
integrity sha512-MTXlixb3EoSTEchsOc7XWsVyoUQqoCsh2Z1a2IptwNgqleMF6ZgQeY52UzUbNj5CcVBg9YljOWjuOV07jSSm4Q==
dependencies:
"@babel/runtime" "^7.18.3"
react-is "^16.12.0"
rc-virtual-list@^3.4.13, rc-virtual-list@^3.5.1, rc-virtual-list@^3.5.2:
version "3.5.2"
resolved "https://registry.yarnpkg.com/rc-virtual-list/-/rc-virtual-list-3.5.2.tgz#5e1028869bae900eacbae6788d4eca7210736006"