mirror of
https://github.com/casdoor/casdoor.git
synced 2025-08-03 19:40:30 +08:00
Compare commits
17 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
af79fdedf2 | ||
![]() |
02333f2f0c | ||
![]() |
79bd58e0e6 | ||
![]() |
de73ff0e60 | ||
![]() |
a9d662f1bd | ||
![]() |
65dcbd2236 | ||
![]() |
6455734807 | ||
![]() |
2eefeaffa7 | ||
![]() |
04eaad1c80 | ||
![]() |
9f084a0799 | ||
![]() |
293b9f1036 | ||
![]() |
437376c472 | ||
![]() |
cc528c5d8c | ||
![]() |
54e2055ffb | ||
![]() |
983a30a2e0 | ||
![]() |
37d0157d41 | ||
![]() |
d4dc236770 |
@@ -15,13 +15,13 @@
|
|||||||
package authz
|
package authz
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/casbin/casbin/v2"
|
"github.com/casbin/casbin/v2"
|
||||||
"github.com/casbin/casbin/v2/model"
|
"github.com/casbin/casbin/v2/model"
|
||||||
"github.com/casdoor/casdoor/conf"
|
"github.com/casdoor/casdoor/conf"
|
||||||
"github.com/casdoor/casdoor/object"
|
"github.com/casdoor/casdoor/object"
|
||||||
|
"github.com/casdoor/casdoor/util"
|
||||||
xormadapter "github.com/casdoor/xorm-adapter/v3"
|
xormadapter "github.com/casdoor/xorm-adapter/v3"
|
||||||
stringadapter "github.com/qiangmzsx/string-adapter/v2"
|
stringadapter "github.com/qiangmzsx/string-adapter/v2"
|
||||||
)
|
)
|
||||||
@@ -150,8 +150,7 @@ func IsAllowed(subOwner string, subName string, method string, urlPath string, o
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
userId := fmt.Sprintf("%s/%s", subOwner, subName)
|
user := object.GetUser(util.GetId(subOwner, subName))
|
||||||
user := object.GetUser(userId)
|
|
||||||
if user != nil && user.IsAdmin && (subOwner == objOwner || (objOwner == "admin")) {
|
if user != nil && user.IsAdmin && (subOwner == objOwner || (objOwner == "admin")) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
@@ -20,5 +20,4 @@ staticBaseUrl = "https://cdn.casbin.org"
|
|||||||
isDemoMode = false
|
isDemoMode = false
|
||||||
batchSize = 100
|
batchSize = 100
|
||||||
ldapServerPort = 389
|
ldapServerPort = 389
|
||||||
languages = en,zh,es,fr,de,id,ja,ko,ru,vi
|
|
||||||
quota = {"organization": -1, "user": -1, "application": -1, "provider": -1}
|
quota = {"organization": -1, "user": -1, "application": -1, "provider": -1}
|
||||||
|
@@ -112,13 +112,8 @@ func GetLanguage(language string) string {
|
|||||||
|
|
||||||
if len(language) < 2 {
|
if len(language) < 2 {
|
||||||
return "en"
|
return "en"
|
||||||
}
|
|
||||||
|
|
||||||
language = language[0:2]
|
|
||||||
if strings.Contains(GetConfigString("languages"), language) {
|
|
||||||
return language
|
|
||||||
} else {
|
} else {
|
||||||
return "en"
|
return language[0:2]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -84,7 +84,7 @@ func (c *ApiController) Signup() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
organization := object.GetOrganization(fmt.Sprintf("%s/%s", "admin", authForm.Organization))
|
organization := object.GetOrganization(util.GetId("admin", authForm.Organization))
|
||||||
msg := object.CheckUserSignup(application, organization, &authForm, c.GetAcceptLanguage())
|
msg := object.CheckUserSignup(application, organization, &authForm, c.GetAcceptLanguage())
|
||||||
if msg != "" {
|
if msg != "" {
|
||||||
c.ResponseError(msg)
|
c.ResponseError(msg)
|
||||||
@@ -126,7 +126,7 @@ func (c *ApiController) Signup() {
|
|||||||
username = id
|
username = id
|
||||||
}
|
}
|
||||||
|
|
||||||
initScore, err := getInitScore(organization)
|
initScore, err := organization.GetInitScore()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.ResponseError(fmt.Errorf(c.T("account:Get init score failed, error: %w"), err).Error())
|
c.ResponseError(fmt.Errorf(c.T("account:Get init score failed, error: %w"), err).Error())
|
||||||
return
|
return
|
||||||
|
@@ -335,7 +335,7 @@ func (c *ApiController) Login() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
organization := object.GetOrganization(fmt.Sprintf("%s/%s", "admin", application.Organization))
|
organization := object.GetOrganization(util.GetId("admin", application.Organization))
|
||||||
provider := object.GetProvider(util.GetId("admin", authForm.Provider))
|
provider := object.GetProvider(util.GetId("admin", authForm.Provider))
|
||||||
providerItem := application.GetProviderItem(provider.Name)
|
providerItem := application.GetProviderItem(provider.Name)
|
||||||
if !providerItem.IsProviderVisible() {
|
if !providerItem.IsProviderVisible() {
|
||||||
@@ -396,7 +396,7 @@ func (c *ApiController) Login() {
|
|||||||
if authForm.Method == "signup" {
|
if authForm.Method == "signup" {
|
||||||
user := &object.User{}
|
user := &object.User{}
|
||||||
if provider.Category == "SAML" {
|
if provider.Category == "SAML" {
|
||||||
user = object.GetUser(fmt.Sprintf("%s/%s", application.Organization, userInfo.Id))
|
user = object.GetUser(util.GetId(application.Organization, userInfo.Id))
|
||||||
} else if provider.Category == "OAuth" {
|
} else if provider.Category == "OAuth" {
|
||||||
user = object.GetUserByField(application.Organization, provider.Type, userInfo.Id)
|
user = object.GetUserByField(application.Organization, provider.Type, userInfo.Id)
|
||||||
}
|
}
|
||||||
@@ -416,24 +416,31 @@ func (c *ApiController) Login() {
|
|||||||
util.SafeGoroutine(func() { object.AddRecord(record) })
|
util.SafeGoroutine(func() { object.AddRecord(record) })
|
||||||
} else if provider.Category == "OAuth" {
|
} else if provider.Category == "OAuth" {
|
||||||
// Sign up via OAuth
|
// Sign up via OAuth
|
||||||
if !application.EnableSignUp {
|
|
||||||
c.ResponseError(fmt.Sprintf(c.T("auth:The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support"), provider.Type, userInfo.Username, userInfo.DisplayName))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if !providerItem.CanSignUp {
|
|
||||||
c.ResponseError(fmt.Sprintf(c.T("auth:The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account via %%s, please use another way to sign up"), provider.Type, userInfo.Username, userInfo.DisplayName, provider.Type))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if application.EnableLinkWithEmail {
|
if application.EnableLinkWithEmail {
|
||||||
// find user that has the same email
|
if userInfo.Email != "" {
|
||||||
user = object.GetUserByField(application.Organization, "email", userInfo.Email)
|
// Find existing user with Email
|
||||||
|
user = object.GetUserByField(application.Organization, "email", userInfo.Email)
|
||||||
|
}
|
||||||
|
|
||||||
|
if user == nil && userInfo.Phone != "" {
|
||||||
|
// Find existing user with phone number
|
||||||
|
user = object.GetUserByField(application.Organization, "phone", userInfo.Phone)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if user == nil || user.IsDeleted {
|
if user == nil || user.IsDeleted {
|
||||||
|
if !application.EnableSignUp {
|
||||||
|
c.ResponseError(fmt.Sprintf(c.T("auth:The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support"), provider.Type, userInfo.Username, userInfo.DisplayName))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if !providerItem.CanSignUp {
|
||||||
|
c.ResponseError(fmt.Sprintf(c.T("auth:The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account via %%s, please use another way to sign up"), provider.Type, userInfo.Username, userInfo.DisplayName, provider.Type))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Handle username conflicts
|
// Handle username conflicts
|
||||||
tmpUser := object.GetUser(fmt.Sprintf("%s/%s", application.Organization, userInfo.Username))
|
tmpUser := object.GetUser(util.GetId(application.Organization, userInfo.Username))
|
||||||
if tmpUser != nil {
|
if tmpUser != nil {
|
||||||
uid, err := uuid.NewRandom()
|
uid, err := uuid.NewRandom()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -447,7 +454,7 @@ func (c *ApiController) Login() {
|
|||||||
|
|
||||||
properties := map[string]string{}
|
properties := map[string]string{}
|
||||||
properties["no"] = strconv.Itoa(object.GetUserCount(application.Organization, "", "") + 2)
|
properties["no"] = strconv.Itoa(object.GetUserCount(application.Organization, "", "") + 2)
|
||||||
initScore, err := getInitScore(organization)
|
initScore, err := organization.GetInitScore()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.ResponseError(fmt.Errorf(c.T("account:Get init score failed, error: %w"), err).Error())
|
c.ResponseError(fmt.Errorf(c.T("account:Get init score failed, error: %w"), err).Error())
|
||||||
return
|
return
|
||||||
|
@@ -24,6 +24,7 @@ import (
|
|||||||
func (c *ApiController) Enforce() {
|
func (c *ApiController) Enforce() {
|
||||||
permissionId := c.Input().Get("permissionId")
|
permissionId := c.Input().Get("permissionId")
|
||||||
modelId := c.Input().Get("modelId")
|
modelId := c.Input().Get("modelId")
|
||||||
|
resourceId := c.Input().Get("resourceId")
|
||||||
|
|
||||||
var request object.CasbinRequest
|
var request object.CasbinRequest
|
||||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &request)
|
err := json.Unmarshal(c.Ctx.Input.RequestBody, &request)
|
||||||
@@ -35,17 +36,24 @@ func (c *ApiController) Enforce() {
|
|||||||
if permissionId != "" {
|
if permissionId != "" {
|
||||||
c.Data["json"] = object.Enforce(permissionId, &request)
|
c.Data["json"] = object.Enforce(permissionId, &request)
|
||||||
c.ServeJSON()
|
c.ServeJSON()
|
||||||
} else {
|
return
|
||||||
owner, modelName := util.GetOwnerAndNameFromId(modelId)
|
|
||||||
permissions := object.GetPermissionsByModel(owner, modelName)
|
|
||||||
|
|
||||||
res := []bool{}
|
|
||||||
for _, permission := range permissions {
|
|
||||||
res = append(res, object.Enforce(permission.GetId(), &request))
|
|
||||||
}
|
|
||||||
c.Data["json"] = res
|
|
||||||
c.ServeJSON()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
permissions := make([]*object.Permission, 0)
|
||||||
|
res := []bool{}
|
||||||
|
|
||||||
|
if modelId != "" {
|
||||||
|
owner, modelName := util.GetOwnerAndNameFromId(modelId)
|
||||||
|
permissions = object.GetPermissionsByModel(owner, modelName)
|
||||||
|
} else {
|
||||||
|
permissions = object.GetPermissionsByResource(resourceId)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, permission := range permissions {
|
||||||
|
res = append(res, object.Enforce(permission.GetId(), &request))
|
||||||
|
}
|
||||||
|
c.Data["json"] = res
|
||||||
|
c.ServeJSON()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ApiController) BatchEnforce() {
|
func (c *ApiController) BatchEnforce() {
|
||||||
|
@@ -23,7 +23,8 @@ import (
|
|||||||
|
|
||||||
type LdapResp struct {
|
type LdapResp struct {
|
||||||
// Groups []LdapRespGroup `json:"groups"`
|
// Groups []LdapRespGroup `json:"groups"`
|
||||||
Users []object.LdapRespUser `json:"users"`
|
Users []object.LdapUser `json:"users"`
|
||||||
|
ExistUuids []string `json:"existUuids"`
|
||||||
}
|
}
|
||||||
|
|
||||||
//type LdapRespGroup struct {
|
//type LdapRespGroup struct {
|
||||||
@@ -32,8 +33,8 @@ type LdapResp struct {
|
|||||||
//}
|
//}
|
||||||
|
|
||||||
type LdapSyncResp struct {
|
type LdapSyncResp struct {
|
||||||
Exist []object.LdapRespUser `json:"exist"`
|
Exist []object.LdapUser `json:"exist"`
|
||||||
Failed []object.LdapRespUser `json:"failed"`
|
Failed []object.LdapUser `json:"failed"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetLdapUsers
|
// GetLdapUsers
|
||||||
@@ -71,27 +72,17 @@ func (c *ApiController) GetLdapUsers() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var resp LdapResp
|
|
||||||
uuids := make([]string, len(users))
|
uuids := make([]string, len(users))
|
||||||
for _, user := range users {
|
for i, user := range users {
|
||||||
resp.Users = append(resp.Users, object.LdapRespUser{
|
uuids[i] = user.GetLdapUuid()
|
||||||
UidNumber: user.UidNumber,
|
|
||||||
Uid: user.Uid,
|
|
||||||
Cn: user.Cn,
|
|
||||||
GroupId: user.GidNumber,
|
|
||||||
// GroupName: groupsMap[user.GidNumber].Cn,
|
|
||||||
Uuid: user.Uuid,
|
|
||||||
DisplayName: user.DisplayName,
|
|
||||||
Email: util.GetMaxLenStr(user.Mail, user.Email, user.EmailAddress),
|
|
||||||
Phone: util.GetMaxLenStr(user.TelephoneNumber, user.Mobile, user.MobileTelephoneNumber),
|
|
||||||
Address: util.GetMaxLenStr(user.RegisteredAddress, user.PostalAddress),
|
|
||||||
})
|
|
||||||
uuids = append(uuids, user.Uuid)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
existUuids := object.GetExistUuids(ldapServer.Owner, uuids)
|
existUuids := object.GetExistUuids(ldapServer.Owner, uuids)
|
||||||
|
|
||||||
c.ResponseOk(resp, existUuids)
|
resp := LdapResp{
|
||||||
|
Users: object.AutoAdjustLdapUser(users),
|
||||||
|
ExistUuids: existUuids,
|
||||||
|
}
|
||||||
|
c.ResponseOk(resp)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetLdaps
|
// GetLdaps
|
||||||
@@ -206,7 +197,7 @@ func (c *ApiController) DeleteLdap() {
|
|||||||
func (c *ApiController) SyncLdapUsers() {
|
func (c *ApiController) SyncLdapUsers() {
|
||||||
owner := c.Input().Get("owner")
|
owner := c.Input().Get("owner")
|
||||||
ldapId := c.Input().Get("ldapId")
|
ldapId := c.Input().Get("ldapId")
|
||||||
var users []object.LdapRespUser
|
var users []object.LdapUser
|
||||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &users)
|
err := json.Unmarshal(c.Ctx.Input.RequestBody, &users)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.ResponseError(err.Error())
|
c.ResponseError(err.Error())
|
||||||
@@ -215,10 +206,10 @@ func (c *ApiController) SyncLdapUsers() {
|
|||||||
|
|
||||||
object.UpdateLdapSyncTime(ldapId)
|
object.UpdateLdapSyncTime(ldapId)
|
||||||
|
|
||||||
exist, failed := object.SyncLdapUsers(owner, users, ldapId)
|
exist, failed, _ := object.SyncLdapUsers(owner, users, ldapId)
|
||||||
|
|
||||||
c.ResponseOk(&LdapSyncResp{
|
c.ResponseOk(&LdapSyncResp{
|
||||||
Exist: *exist,
|
Exist: exist,
|
||||||
Failed: *failed,
|
Failed: failed,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@@ -37,13 +37,19 @@ func (c *ApiController) GetProviders() {
|
|||||||
value := c.Input().Get("value")
|
value := c.Input().Get("value")
|
||||||
sortField := c.Input().Get("sortField")
|
sortField := c.Input().Get("sortField")
|
||||||
sortOrder := c.Input().Get("sortOrder")
|
sortOrder := c.Input().Get("sortOrder")
|
||||||
|
|
||||||
|
ok, isMaskEnabled := c.IsMaskedEnabled()
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if limit == "" || page == "" {
|
if limit == "" || page == "" {
|
||||||
c.Data["json"] = object.GetMaskedProviders(object.GetProviders(owner))
|
c.Data["json"] = object.GetMaskedProviders(object.GetProviders(owner), isMaskEnabled)
|
||||||
c.ServeJSON()
|
c.ServeJSON()
|
||||||
} else {
|
} else {
|
||||||
limit := util.ParseInt(limit)
|
limit := util.ParseInt(limit)
|
||||||
paginator := pagination.SetPaginator(c.Ctx, limit, int64(object.GetProviderCount(owner, field, value)))
|
paginator := pagination.SetPaginator(c.Ctx, limit, int64(object.GetProviderCount(owner, field, value)))
|
||||||
providers := object.GetMaskedProviders(object.GetPaginationProviders(owner, paginator.Offset(), limit, field, value, sortField, sortOrder))
|
providers := object.GetMaskedProviders(object.GetPaginationProviders(owner, paginator.Offset(), limit, field, value, sortField, sortOrder), isMaskEnabled)
|
||||||
c.ResponseOk(providers, paginator.Nums())
|
c.ResponseOk(providers, paginator.Nums())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -61,13 +67,19 @@ func (c *ApiController) GetGlobalProviders() {
|
|||||||
value := c.Input().Get("value")
|
value := c.Input().Get("value")
|
||||||
sortField := c.Input().Get("sortField")
|
sortField := c.Input().Get("sortField")
|
||||||
sortOrder := c.Input().Get("sortOrder")
|
sortOrder := c.Input().Get("sortOrder")
|
||||||
|
|
||||||
|
ok, isMaskEnabled := c.IsMaskedEnabled()
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if limit == "" || page == "" {
|
if limit == "" || page == "" {
|
||||||
c.Data["json"] = object.GetMaskedProviders(object.GetGlobalProviders())
|
c.Data["json"] = object.GetMaskedProviders(object.GetGlobalProviders(), isMaskEnabled)
|
||||||
c.ServeJSON()
|
c.ServeJSON()
|
||||||
} else {
|
} else {
|
||||||
limit := util.ParseInt(limit)
|
limit := util.ParseInt(limit)
|
||||||
paginator := pagination.SetPaginator(c.Ctx, limit, int64(object.GetGlobalProviderCount(field, value)))
|
paginator := pagination.SetPaginator(c.Ctx, limit, int64(object.GetGlobalProviderCount(field, value)))
|
||||||
providers := object.GetMaskedProviders(object.GetPaginationGlobalProviders(paginator.Offset(), limit, field, value, sortField, sortOrder))
|
providers := object.GetMaskedProviders(object.GetPaginationGlobalProviders(paginator.Offset(), limit, field, value, sortField, sortOrder), isMaskEnabled)
|
||||||
c.ResponseOk(providers, paginator.Nums())
|
c.ResponseOk(providers, paginator.Nums())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -81,7 +93,13 @@ func (c *ApiController) GetGlobalProviders() {
|
|||||||
// @router /get-provider [get]
|
// @router /get-provider [get]
|
||||||
func (c *ApiController) GetProvider() {
|
func (c *ApiController) GetProvider() {
|
||||||
id := c.Input().Get("id")
|
id := c.Input().Get("id")
|
||||||
c.Data["json"] = object.GetMaskedProvider(object.GetProvider(id))
|
|
||||||
|
ok, isMaskEnabled := c.IsMaskedEnabled()
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c.Data["json"] = object.GetMaskedProvider(object.GetProvider(id), isMaskEnabled)
|
||||||
c.ServeJSON()
|
c.ServeJSON()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -98,7 +98,7 @@ func (c *ApiController) GetUser() {
|
|||||||
owner = util.GetOwnerFromId(id)
|
owner = util.GetOwnerFromId(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
organization := object.GetOrganization(fmt.Sprintf("%s/%s", "admin", owner))
|
organization := object.GetOrganization(util.GetId("admin", owner))
|
||||||
if !organization.IsProfilePublic {
|
if !organization.IsProfilePublic {
|
||||||
requestUserId := c.GetSessionUsername()
|
requestUserId := c.GetSessionUsername()
|
||||||
hasPermission, err := object.CheckUserPermission(requestUserId, id, false, c.GetAcceptLanguage())
|
hasPermission, err := object.CheckUserPermission(requestUserId, id, false, c.GetAcceptLanguage())
|
||||||
|
@@ -16,7 +16,6 @@ package controllers
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"strconv"
|
|
||||||
|
|
||||||
"github.com/casdoor/casdoor/conf"
|
"github.com/casdoor/casdoor/conf"
|
||||||
"github.com/casdoor/casdoor/i18n"
|
"github.com/casdoor/casdoor/i18n"
|
||||||
@@ -115,12 +114,25 @@ func (c *ApiController) RequireAdmin() (string, bool) {
|
|||||||
return user.Owner, true
|
return user.Owner, true
|
||||||
}
|
}
|
||||||
|
|
||||||
func getInitScore(organization *object.Organization) (int, error) {
|
// IsMaskedEnabled ...
|
||||||
if organization != nil {
|
func (c *ApiController) IsMaskedEnabled() (bool, bool) {
|
||||||
return organization.InitScore, nil
|
isMaskEnabled := true
|
||||||
} else {
|
withSecret := c.Input().Get("withSecret")
|
||||||
return strconv.Atoi(conf.GetConfigString("initScore"))
|
if withSecret == "1" {
|
||||||
|
isMaskEnabled = false
|
||||||
|
|
||||||
|
if conf.IsDemoMode() {
|
||||||
|
c.ResponseError(c.T("general:this operation is not allowed in demo mode"))
|
||||||
|
return false, isMaskEnabled
|
||||||
|
}
|
||||||
|
|
||||||
|
_, ok := c.RequireAdmin()
|
||||||
|
if !ok {
|
||||||
|
return false, isMaskEnabled
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true, isMaskEnabled
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ApiController) GetProviderFromContext(category string) (*object.Provider, *object.User, bool) {
|
func (c *ApiController) GetProviderFromContext(category string) (*object.Provider, *object.User, bool) {
|
||||||
|
@@ -32,6 +32,7 @@ func TestGenerateI18nFrontend(t *testing.T) {
|
|||||||
applyToOtherLanguage("frontend", "ko", data)
|
applyToOtherLanguage("frontend", "ko", data)
|
||||||
applyToOtherLanguage("frontend", "ru", data)
|
applyToOtherLanguage("frontend", "ru", data)
|
||||||
applyToOtherLanguage("frontend", "vi", data)
|
applyToOtherLanguage("frontend", "vi", data)
|
||||||
|
applyToOtherLanguage("frontend", "pt", data)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGenerateI18nBackend(t *testing.T) {
|
func TestGenerateI18nBackend(t *testing.T) {
|
||||||
@@ -47,4 +48,5 @@ func TestGenerateI18nBackend(t *testing.T) {
|
|||||||
applyToOtherLanguage("backend", "ko", data)
|
applyToOtherLanguage("backend", "ko", data)
|
||||||
applyToOtherLanguage("backend", "ru", data)
|
applyToOtherLanguage("backend", "ru", data)
|
||||||
applyToOtherLanguage("backend", "vi", data)
|
applyToOtherLanguage("backend", "vi", data)
|
||||||
|
applyToOtherLanguage("backend", "pt", data)
|
||||||
}
|
}
|
||||||
|
22
i18n/util.go
22
i18n/util.go
@@ -73,23 +73,27 @@ func applyData(data1 *I18nData, data2 *I18nData) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func Translate(lang string, error string) string {
|
func Translate(language string, errorText string) string {
|
||||||
tokens := strings.SplitN(error, ":", 2)
|
tokens := strings.SplitN(errorText, ":", 2)
|
||||||
if !strings.Contains(error, ":") || len(tokens) != 2 {
|
if !strings.Contains(errorText, ":") || len(tokens) != 2 {
|
||||||
return "Translate Error: " + error
|
return fmt.Sprintf("Translate error: the error text doesn't contain \":\", errorText = %s", errorText)
|
||||||
}
|
}
|
||||||
|
|
||||||
if langMap[lang] == nil {
|
if langMap[language] == nil {
|
||||||
file, _ := f.ReadFile("locales/" + lang + "/data.json")
|
file, err := f.ReadFile(fmt.Sprintf("locales/%s/data.json", language))
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Sprintf("Translate error: the language \"%s\" is not supported, err = %s", language, err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
data := I18nData{}
|
data := I18nData{}
|
||||||
err := util.JsonToStruct(string(file), &data)
|
err = util.JsonToStruct(string(file), &data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
langMap[lang] = data
|
langMap[language] = data
|
||||||
}
|
}
|
||||||
|
|
||||||
res := langMap[lang][tokens[0]][tokens[1]]
|
res := langMap[language][tokens[0]][tokens[1]]
|
||||||
if res == "" {
|
if res == "" {
|
||||||
res = tokens[1]
|
res = tokens[1]
|
||||||
}
|
}
|
||||||
|
@@ -179,8 +179,12 @@ func (idp *DingTalkIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo, erro
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
corpEmail, jobNumber, err := idp.getUserCorpEmail(userId, corpAccessToken)
|
corpMobile, corpEmail, jobNumber, err := idp.getUserCorpEmail(userId, corpAccessToken)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
|
if corpMobile != "" {
|
||||||
|
userInfo.Phone = corpMobile
|
||||||
|
}
|
||||||
|
|
||||||
if corpEmail != "" {
|
if corpEmail != "" {
|
||||||
userInfo.Email = corpEmail
|
userInfo.Email = corpEmail
|
||||||
}
|
}
|
||||||
@@ -264,27 +268,29 @@ func (idp *DingTalkIdProvider) getUserId(unionId string, accessToken string) (st
|
|||||||
return data.Result.UserId, nil
|
return data.Result.UserId, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (idp *DingTalkIdProvider) getUserCorpEmail(userId string, accessToken string) (string, string, error) {
|
func (idp *DingTalkIdProvider) getUserCorpEmail(userId string, accessToken string) (string, string, string, error) {
|
||||||
|
// https://open.dingtalk.com/document/isvapp/query-user-details
|
||||||
body := make(map[string]string)
|
body := make(map[string]string)
|
||||||
body["userid"] = userId
|
body["userid"] = userId
|
||||||
respBytes, err := idp.postWithBody(body, "https://oapi.dingtalk.com/topapi/v2/user/get?access_token="+accessToken)
|
respBytes, err := idp.postWithBody(body, "https://oapi.dingtalk.com/topapi/v2/user/get?access_token="+accessToken)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", "", err
|
return "", "", "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
var data struct {
|
var data struct {
|
||||||
ErrMessage string `json:"errmsg"`
|
ErrMessage string `json:"errmsg"`
|
||||||
Result struct {
|
Result struct {
|
||||||
|
Mobile string `json:"mobile"`
|
||||||
Email string `json:"email"`
|
Email string `json:"email"`
|
||||||
JobNumber string `json:"job_number"`
|
JobNumber string `json:"job_number"`
|
||||||
} `json:"result"`
|
} `json:"result"`
|
||||||
}
|
}
|
||||||
err = json.Unmarshal(respBytes, &data)
|
err = json.Unmarshal(respBytes, &data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", "", err
|
return "", "", "", err
|
||||||
}
|
}
|
||||||
if data.ErrMessage != "ok" {
|
if data.ErrMessage != "ok" {
|
||||||
return "", "", fmt.Errorf(data.ErrMessage)
|
return "", "", "", fmt.Errorf(data.ErrMessage)
|
||||||
}
|
}
|
||||||
return data.Result.Email, data.Result.JobNumber, nil
|
return data.Result.Mobile, data.Result.Email, data.Result.JobNumber, nil
|
||||||
}
|
}
|
||||||
|
2
main.go
2
main.go
@@ -60,7 +60,7 @@ func main() {
|
|||||||
beego.InsertFilter("*", beego.BeforeRouter, routers.CorsFilter)
|
beego.InsertFilter("*", beego.BeforeRouter, routers.CorsFilter)
|
||||||
beego.InsertFilter("*", beego.BeforeRouter, routers.AuthzFilter)
|
beego.InsertFilter("*", beego.BeforeRouter, routers.AuthzFilter)
|
||||||
beego.InsertFilter("*", beego.BeforeRouter, routers.PrometheusFilter)
|
beego.InsertFilter("*", beego.BeforeRouter, routers.PrometheusFilter)
|
||||||
beego.InsertFilter("*", beego.FinishRouter, routers.RecordMessage)
|
beego.InsertFilter("*", beego.BeforeRouter, routers.RecordMessage)
|
||||||
|
|
||||||
beego.BConfig.WebConfig.Session.SessionOn = true
|
beego.BConfig.WebConfig.Session.SessionOn = true
|
||||||
beego.BConfig.WebConfig.Session.SessionName = "casdoor_session_id"
|
beego.BConfig.WebConfig.Session.SessionName = "casdoor_session_id"
|
||||||
|
@@ -150,7 +150,7 @@ func getProviderMap(owner string) map[string]*Provider {
|
|||||||
UpdateProvider(provider.Owner+"/"+provider.Name, provider)
|
UpdateProvider(provider.Owner+"/"+provider.Name, provider)
|
||||||
}
|
}
|
||||||
|
|
||||||
m[provider.Name] = GetMaskedProvider(provider)
|
m[provider.Name] = GetMaskedProvider(provider, true)
|
||||||
}
|
}
|
||||||
return m
|
return m
|
||||||
}
|
}
|
||||||
|
@@ -134,6 +134,24 @@ func getCert(owner string, name string) *Cert {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getCertByName(name string) *Cert {
|
||||||
|
if name == "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
cert := Cert{Name: name}
|
||||||
|
existed, err := adapter.Engine.Get(&cert)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if existed {
|
||||||
|
return &cert
|
||||||
|
} else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func GetCert(id string) *Cert {
|
func GetCert(id string) *Cert {
|
||||||
owner, name := util.GetOwnerAndNameFromId(id)
|
owner, name := util.GetOwnerAndNameFromId(id)
|
||||||
return getCert(owner, name)
|
return getCert(owner, name)
|
||||||
@@ -189,7 +207,7 @@ func (p *Cert) GetId() string {
|
|||||||
|
|
||||||
func getCertByApplication(application *Application) *Cert {
|
func getCertByApplication(application *Application) *Cert {
|
||||||
if application.Cert != "" {
|
if application.Cert != "" {
|
||||||
return getCert("admin", application.Cert)
|
return getCertByName(application.Cert)
|
||||||
} else {
|
} else {
|
||||||
return GetDefaultCert()
|
return GetDefaultCert()
|
||||||
}
|
}
|
||||||
|
@@ -321,6 +321,10 @@ func CheckUserPermission(requestUserId, userId string, strict bool, lang string)
|
|||||||
}
|
}
|
||||||
|
|
||||||
func CheckAccessPermission(userId string, application *Application) (bool, error) {
|
func CheckAccessPermission(userId string, application *Application) (bool, error) {
|
||||||
|
if userId == "built-in/admin" {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
permissions := GetPermissions(application.Organization)
|
permissions := GetPermissions(application.Organization)
|
||||||
allowed := true
|
allowed := true
|
||||||
var err error
|
var err error
|
||||||
|
@@ -90,7 +90,7 @@ func initBuiltInOrganization() bool {
|
|||||||
CountryCodes: []string{"US", "ES", "CN", "FR", "DE", "GB", "JP", "KR", "VN", "ID", "SG", "IN"},
|
CountryCodes: []string{"US", "ES", "CN", "FR", "DE", "GB", "JP", "KR", "VN", "ID", "SG", "IN"},
|
||||||
DefaultAvatar: fmt.Sprintf("%s/img/casbin.svg", conf.GetConfigString("staticBaseUrl")),
|
DefaultAvatar: fmt.Sprintf("%s/img/casbin.svg", conf.GetConfigString("staticBaseUrl")),
|
||||||
Tags: []string{},
|
Tags: []string{},
|
||||||
Languages: []string{"en", "zh", "es", "fr", "de", "id", "ja", "ko", "ru", "vi"},
|
Languages: []string{"en", "zh", "es", "fr", "de", "id", "ja", "ko", "ru", "vi", "pt"},
|
||||||
InitScore: 2000,
|
InitScore: 2000,
|
||||||
AccountItems: getBuiltInAccountItems(),
|
AccountItems: getBuiltInAccountItems(),
|
||||||
EnableSoftDeletion: false,
|
EnableSoftDeletion: false,
|
||||||
|
@@ -87,11 +87,13 @@ func (l *LdapAutoSynchronizer) syncRoutine(ldap *Ldap, stopChan chan struct{}) {
|
|||||||
logs.Warning(fmt.Sprintf("autoSync failed for %s, error %s", ldap.Id, err))
|
logs.Warning(fmt.Sprintf("autoSync failed for %s, error %s", ldap.Id, err))
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
existed, failed := SyncLdapUsers(ldap.Owner, LdapUsersToLdapRespUsers(users), ldap.Id)
|
|
||||||
if len(*failed) != 0 {
|
existed, failed, err := SyncLdapUsers(ldap.Owner, AutoAdjustLdapUser(users), ldap.Id)
|
||||||
logs.Warning(fmt.Sprintf("ldap autosync,%d new users,but %d user failed during :", len(users)-len(*existed)-len(*failed), len(*failed)), *failed)
|
if len(failed) != 0 {
|
||||||
|
logs.Warning(fmt.Sprintf("ldap autosync,%d new users,but %d user failed during :", len(users)-len(existed)-len(failed), len(failed)), failed)
|
||||||
|
logs.Warning(err.Error())
|
||||||
} else {
|
} else {
|
||||||
logs.Info(fmt.Sprintf("ldap autosync success, %d new users, %d existing users", len(users)-len(*existed), len(*existed)))
|
logs.Info(fmt.Sprintf("ldap autosync success, %d new users, %d existing users", len(users)-len(existed), len(existed)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -19,7 +19,6 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/beego/beego"
|
|
||||||
"github.com/casdoor/casdoor/util"
|
"github.com/casdoor/casdoor/util"
|
||||||
goldap "github.com/go-ldap/ldap/v3"
|
goldap "github.com/go-ldap/ldap/v3"
|
||||||
"github.com/thanhpk/randstr"
|
"github.com/thanhpk/randstr"
|
||||||
@@ -35,35 +34,26 @@ type LdapConn struct {
|
|||||||
// Cn string
|
// Cn string
|
||||||
//}
|
//}
|
||||||
|
|
||||||
type ldapUser struct {
|
type LdapUser struct {
|
||||||
UidNumber string
|
UidNumber string `json:"uidNumber"`
|
||||||
Uid string
|
Uid string `json:"uid"`
|
||||||
Cn string
|
Cn string `json:"cn"`
|
||||||
GidNumber string
|
GidNumber string `json:"gidNumber"`
|
||||||
// Gcn string
|
// Gcn string
|
||||||
Uuid string
|
Uuid string `json:"uuid"`
|
||||||
DisplayName string
|
DisplayName string `json:"displayName"`
|
||||||
Mail string
|
Mail string
|
||||||
Email string
|
Email string `json:"email"`
|
||||||
EmailAddress string
|
EmailAddress string
|
||||||
TelephoneNumber string
|
TelephoneNumber string
|
||||||
Mobile string
|
Mobile string
|
||||||
MobileTelephoneNumber string
|
MobileTelephoneNumber string
|
||||||
RegisteredAddress string
|
RegisteredAddress string
|
||||||
PostalAddress string
|
PostalAddress string
|
||||||
}
|
|
||||||
|
|
||||||
type LdapRespUser struct {
|
GroupId string `json:"groupId"`
|
||||||
UidNumber string `json:"uidNumber"`
|
Phone string `json:"phone"`
|
||||||
Uid string `json:"uid"`
|
Address string `json:"address"`
|
||||||
Cn string `json:"cn"`
|
|
||||||
GroupId string `json:"groupId"`
|
|
||||||
// GroupName string `json:"groupName"`
|
|
||||||
Uuid string `json:"uuid"`
|
|
||||||
DisplayName string `json:"displayName"`
|
|
||||||
Email string `json:"email"`
|
|
||||||
Phone string `json:"phone"`
|
|
||||||
Address string `json:"address"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ldap *Ldap) GetLdapConn() (c *LdapConn, err error) {
|
func (ldap *Ldap) GetLdapConn() (c *LdapConn, err error) {
|
||||||
@@ -136,7 +126,7 @@ func isMicrosoftAD(Conn *goldap.Conn) (bool, error) {
|
|||||||
return isMicrosoft, err
|
return isMicrosoft, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *LdapConn) GetLdapUsers(ldapServer *Ldap) ([]ldapUser, error) {
|
func (l *LdapConn) GetLdapUsers(ldapServer *Ldap) ([]LdapUser, error) {
|
||||||
SearchAttributes := []string{
|
SearchAttributes := []string{
|
||||||
"uidNumber", "cn", "sn", "gidNumber", "entryUUID", "displayName", "mail", "email",
|
"uidNumber", "cn", "sn", "gidNumber", "entryUUID", "displayName", "mail", "email",
|
||||||
"emailAddress", "telephoneNumber", "mobile", "mobileTelephoneNumber", "registeredAddress", "postalAddress",
|
"emailAddress", "telephoneNumber", "mobile", "mobileTelephoneNumber", "registeredAddress", "postalAddress",
|
||||||
@@ -159,9 +149,9 @@ func (l *LdapConn) GetLdapUsers(ldapServer *Ldap) ([]ldapUser, error) {
|
|||||||
return nil, errors.New("no result")
|
return nil, errors.New("no result")
|
||||||
}
|
}
|
||||||
|
|
||||||
var ldapUsers []ldapUser
|
var ldapUsers []LdapUser
|
||||||
for _, entry := range searchResult.Entries {
|
for _, entry := range searchResult.Entries {
|
||||||
var user ldapUser
|
var user LdapUser
|
||||||
for _, attribute := range entry.Attributes {
|
for _, attribute := range entry.Attributes {
|
||||||
switch attribute.Name {
|
switch attribute.Name {
|
||||||
case "uidNumber":
|
case "uidNumber":
|
||||||
@@ -241,35 +231,30 @@ func (l *LdapConn) GetLdapUsers(ldapServer *Ldap) ([]ldapUser, error) {
|
|||||||
// return groupMap, nil
|
// return groupMap, nil
|
||||||
// }
|
// }
|
||||||
|
|
||||||
func LdapUsersToLdapRespUsers(users []ldapUser) []LdapRespUser {
|
func AutoAdjustLdapUser(users []LdapUser) []LdapUser {
|
||||||
res := make([]LdapRespUser, 0)
|
res := make([]LdapUser, len(users))
|
||||||
for _, user := range users {
|
for i, user := range users {
|
||||||
res = append(res, LdapRespUser{
|
res[i] = LdapUser{
|
||||||
UidNumber: user.UidNumber,
|
UidNumber: user.UidNumber,
|
||||||
Uid: user.Uid,
|
Uid: user.Uid,
|
||||||
Cn: user.Cn,
|
Cn: user.Cn,
|
||||||
GroupId: user.GidNumber,
|
GroupId: user.GidNumber,
|
||||||
Uuid: user.Uuid,
|
Uuid: user.GetLdapUuid(),
|
||||||
DisplayName: user.DisplayName,
|
DisplayName: user.DisplayName,
|
||||||
Email: util.ReturnAnyNotEmpty(user.Email, user.EmailAddress, user.Mail),
|
Email: util.ReturnAnyNotEmpty(user.Email, user.EmailAddress, user.Mail),
|
||||||
Phone: util.ReturnAnyNotEmpty(user.Mobile, user.MobileTelephoneNumber, user.TelephoneNumber),
|
Mobile: util.ReturnAnyNotEmpty(user.Mobile, user.MobileTelephoneNumber, user.TelephoneNumber),
|
||||||
Address: util.ReturnAnyNotEmpty(user.PostalAddress, user.RegisteredAddress),
|
RegisteredAddress: util.ReturnAnyNotEmpty(user.PostalAddress, user.RegisteredAddress),
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
func SyncLdapUsers(owner string, respUsers []LdapRespUser, ldapId string) (*[]LdapRespUser, *[]LdapRespUser) {
|
func SyncLdapUsers(owner string, syncUsers []LdapUser, ldapId string) (existUsers []LdapUser, failedUsers []LdapUser, err error) {
|
||||||
var existUsers []LdapRespUser
|
|
||||||
var failedUsers []LdapRespUser
|
|
||||||
var uuids []string
|
var uuids []string
|
||||||
|
for _, user := range syncUsers {
|
||||||
for _, user := range respUsers {
|
|
||||||
uuids = append(uuids, user.Uuid)
|
uuids = append(uuids, user.Uuid)
|
||||||
}
|
}
|
||||||
|
|
||||||
existUuids := GetExistUuids(owner, uuids)
|
|
||||||
|
|
||||||
organization := getOrganization("admin", owner)
|
organization := getOrganization("admin", owner)
|
||||||
ldap := GetLdap(ldapId)
|
ldap := GetLdap(ldapId)
|
||||||
|
|
||||||
@@ -289,67 +274,59 @@ func SyncLdapUsers(owner string, respUsers []LdapRespUser, ldapId string) (*[]Ld
|
|||||||
}
|
}
|
||||||
tag := strings.Join(ou, ".")
|
tag := strings.Join(ou, ".")
|
||||||
|
|
||||||
for _, respUser := range respUsers {
|
for _, syncUser := range syncUsers {
|
||||||
|
existUuids := GetExistUuids(owner, uuids)
|
||||||
found := false
|
found := false
|
||||||
if len(existUuids) > 0 {
|
if len(existUuids) > 0 {
|
||||||
for _, existUuid := range existUuids {
|
for _, existUuid := range existUuids {
|
||||||
if respUser.Uuid == existUuid {
|
if syncUser.Uuid == existUuid {
|
||||||
existUsers = append(existUsers, respUser)
|
existUsers = append(existUsers, syncUser)
|
||||||
found = true
|
found = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !found {
|
if !found {
|
||||||
|
score, _ := organization.GetInitScore()
|
||||||
newUser := &User{
|
newUser := &User{
|
||||||
Owner: owner,
|
Owner: owner,
|
||||||
Name: respUser.buildLdapUserName(),
|
Name: syncUser.buildLdapUserName(),
|
||||||
CreatedTime: util.GetCurrentTime(),
|
CreatedTime: util.GetCurrentTime(),
|
||||||
DisplayName: respUser.buildLdapDisplayName(),
|
DisplayName: syncUser.buildLdapDisplayName(),
|
||||||
Avatar: organization.DefaultAvatar,
|
Avatar: organization.DefaultAvatar,
|
||||||
Email: respUser.Email,
|
Email: syncUser.Email,
|
||||||
Phone: respUser.Phone,
|
Phone: syncUser.Phone,
|
||||||
Address: []string{respUser.Address},
|
Address: []string{syncUser.Address},
|
||||||
Affiliation: affiliation,
|
Affiliation: affiliation,
|
||||||
Tag: tag,
|
Tag: tag,
|
||||||
Score: beego.AppConfig.DefaultInt("initScore", 2000),
|
Score: score,
|
||||||
Ldap: respUser.Uuid,
|
Ldap: syncUser.Uuid,
|
||||||
}
|
}
|
||||||
|
|
||||||
affected := AddUser(newUser)
|
affected := AddUser(newUser)
|
||||||
if !affected {
|
if !affected {
|
||||||
failedUsers = append(failedUsers, respUser)
|
failedUsers = append(failedUsers, syncUser)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return &existUsers, &failedUsers
|
return existUsers, failedUsers, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetExistUuids(owner string, uuids []string) []string {
|
func GetExistUuids(owner string, uuids []string) []string {
|
||||||
var users []User
|
|
||||||
var existUuids []string
|
var existUuids []string
|
||||||
existUuidSet := make(map[string]struct{})
|
|
||||||
|
|
||||||
err := adapter.Engine.Where(fmt.Sprintf("ldap IN (%s) AND owner = ?", "'"+strings.Join(uuids, "','")+"'"), owner).Find(&users)
|
err := adapter.Engine.Table("user").Where("owner = ?", owner).Cols("ldap").
|
||||||
|
In("ldap", uuids).Select("DISTINCT ldap").Find(&existUuids)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(users) > 0 {
|
|
||||||
for _, result := range users {
|
|
||||||
existUuidSet[result.Ldap] = struct{}{}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for uuid := range existUuidSet {
|
|
||||||
existUuids = append(existUuids, uuid)
|
|
||||||
}
|
|
||||||
return existUuids
|
return existUuids
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ldapUser *LdapRespUser) buildLdapUserName() string {
|
func (ldapUser *LdapUser) buildLdapUserName() string {
|
||||||
user := User{}
|
user := User{}
|
||||||
uidWithNumber := fmt.Sprintf("%s_%s", ldapUser.Uid, ldapUser.UidNumber)
|
uidWithNumber := fmt.Sprintf("%s_%s", ldapUser.Uid, ldapUser.UidNumber)
|
||||||
has, err := adapter.Engine.Where("name = ? or name = ?", ldapUser.Uid, uidWithNumber).Get(&user)
|
has, err := adapter.Engine.Where("name = ? or name = ?", ldapUser.Uid, uidWithNumber).Get(&user)
|
||||||
@@ -364,10 +341,14 @@ func (ldapUser *LdapRespUser) buildLdapUserName() string {
|
|||||||
return fmt.Sprintf("%s_%s", uidWithNumber, randstr.Hex(6))
|
return fmt.Sprintf("%s_%s", uidWithNumber, randstr.Hex(6))
|
||||||
}
|
}
|
||||||
|
|
||||||
return ldapUser.Uid
|
if ldapUser.Uid != "" {
|
||||||
|
return ldapUser.Uid
|
||||||
|
}
|
||||||
|
|
||||||
|
return ldapUser.Cn
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ldapUser *LdapRespUser) buildLdapDisplayName() string {
|
func (ldapUser *LdapUser) buildLdapDisplayName() string {
|
||||||
if ldapUser.DisplayName != "" {
|
if ldapUser.DisplayName != "" {
|
||||||
return ldapUser.DisplayName
|
return ldapUser.DisplayName
|
||||||
}
|
}
|
||||||
@@ -375,6 +356,17 @@ func (ldapUser *LdapRespUser) buildLdapDisplayName() string {
|
|||||||
return ldapUser.Cn
|
return ldapUser.Cn
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ldapUser *LdapUser) GetLdapUuid() string {
|
||||||
|
if ldapUser.Uuid != "" {
|
||||||
|
return ldapUser.Uuid
|
||||||
|
}
|
||||||
|
if ldapUser.Uid != "" {
|
||||||
|
return ldapUser.Uid
|
||||||
|
}
|
||||||
|
|
||||||
|
return ldapUser.Cn
|
||||||
|
}
|
||||||
|
|
||||||
func (ldap *Ldap) buildFilterString(user *User) string {
|
func (ldap *Ldap) buildFilterString(user *User) string {
|
||||||
if len(ldap.FilterFields) == 0 {
|
if len(ldap.FilterFields) == 0 {
|
||||||
return fmt.Sprintf("(&%s(uid=%s))", ldap.Filter, user.Name)
|
return fmt.Sprintf("(&%s(uid=%s))", ldap.Filter, user.Name)
|
||||||
|
@@ -15,7 +15,6 @@
|
|||||||
package object
|
package object
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/xorm-io/core"
|
|
||||||
"github.com/xorm-io/xorm"
|
"github.com/xorm-io/xorm"
|
||||||
"github.com/xorm-io/xorm/migrate"
|
"github.com/xorm-io/xorm/migrate"
|
||||||
)
|
)
|
||||||
@@ -52,32 +51,15 @@ func (*Migrator_1_314_0_PR_1841) DoMigration() *migrate.Migration {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
users := []*User{}
|
|
||||||
organizations := []*Organization{}
|
organizations := []*Organization{}
|
||||||
|
|
||||||
err = tx.Table("user").Find(&users)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
err = tx.Table("organization").Find(&organizations)
|
err = tx.Table("organization").Find(&organizations)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
passwordTypes := make(map[string]string)
|
for _, organization := range organizations {
|
||||||
for _, org := range organizations {
|
user := &User{PasswordType: organization.PasswordType}
|
||||||
passwordTypes[org.Name] = org.PasswordType
|
_, err = tx.Where("owner = ?", organization.Name).Cols("password_type").Update(user)
|
||||||
}
|
|
||||||
|
|
||||||
columns := []string{
|
|
||||||
"password_type",
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, u := range users {
|
|
||||||
u.PasswordType = passwordTypes[u.Owner]
|
|
||||||
|
|
||||||
_, err := tx.ID(core.PK{u.Owner, u.Name}).Cols(columns...).Update(u)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@@ -16,7 +16,9 @@ package object
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/casdoor/casdoor/conf"
|
||||||
"github.com/casdoor/casdoor/cred"
|
"github.com/casdoor/casdoor/cred"
|
||||||
"github.com/casdoor/casdoor/i18n"
|
"github.com/casdoor/casdoor/i18n"
|
||||||
"github.com/casdoor/casdoor/util"
|
"github.com/casdoor/casdoor/util"
|
||||||
@@ -423,3 +425,11 @@ func (org *Organization) HasRequiredMfa() bool {
|
|||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (org *Organization) GetInitScore() (int, error) {
|
||||||
|
if org != nil {
|
||||||
|
return org.InitScore, nil
|
||||||
|
} else {
|
||||||
|
return strconv.Atoi(conf.GetConfigString("initScore"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -235,6 +235,16 @@ func GetPermissionsByRole(roleId string) []*Permission {
|
|||||||
return permissions
|
return permissions
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GetPermissionsByResource(resourceId string) []*Permission {
|
||||||
|
permissions := []*Permission{}
|
||||||
|
err := adapter.Engine.Where("resources like ?", "%"+resourceId+"\"%").Find(&permissions)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return permissions
|
||||||
|
}
|
||||||
|
|
||||||
func GetPermissionsBySubmitter(owner string, submitter string) []*Permission {
|
func GetPermissionsBySubmitter(owner string, submitter string) []*Permission {
|
||||||
permissions := []*Permission{}
|
permissions := []*Permission{}
|
||||||
err := adapter.Engine.Desc("created_time").Find(&permissions, &Permission{Owner: owner, Submitter: submitter})
|
err := adapter.Engine.Desc("created_time").Find(&permissions, &Permission{Owner: owner, Submitter: submitter})
|
||||||
|
@@ -70,7 +70,11 @@ type Provider struct {
|
|||||||
ProviderUrl string `xorm:"varchar(200)" json:"providerUrl"`
|
ProviderUrl string `xorm:"varchar(200)" json:"providerUrl"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetMaskedProvider(provider *Provider) *Provider {
|
func GetMaskedProvider(provider *Provider, isMaskEnabled bool) *Provider {
|
||||||
|
if !isMaskEnabled {
|
||||||
|
return provider
|
||||||
|
}
|
||||||
|
|
||||||
if provider == nil {
|
if provider == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -88,9 +92,13 @@ func GetMaskedProvider(provider *Provider) *Provider {
|
|||||||
return provider
|
return provider
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetMaskedProviders(providers []*Provider) []*Provider {
|
func GetMaskedProviders(providers []*Provider, isMaskEnabled bool) []*Provider {
|
||||||
|
if !isMaskEnabled {
|
||||||
|
return providers
|
||||||
|
}
|
||||||
|
|
||||||
for _, provider := range providers {
|
for _, provider := range providers {
|
||||||
provider = GetMaskedProvider(provider)
|
provider = GetMaskedProvider(provider, isMaskEnabled)
|
||||||
}
|
}
|
||||||
return providers
|
return providers
|
||||||
}
|
}
|
||||||
@@ -310,7 +318,7 @@ func GetCaptchaProviderByApplication(applicationId, isCurrentProvider, lang stri
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if provider.Provider.Category == "Captcha" {
|
if provider.Provider.Category == "Captcha" {
|
||||||
return GetCaptchaProviderByOwnerName(fmt.Sprintf("%s/%s", provider.Provider.Owner, provider.Provider.Name), lang)
|
return GetCaptchaProviderByOwnerName(util.GetId(provider.Provider.Owner, provider.Provider.Name), lang)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil, nil
|
return nil, nil
|
||||||
|
@@ -47,7 +47,8 @@ type Record struct {
|
|||||||
RequestUri string `xorm:"varchar(1000)" json:"requestUri"`
|
RequestUri string `xorm:"varchar(1000)" json:"requestUri"`
|
||||||
Action string `xorm:"varchar(1000)" json:"action"`
|
Action string `xorm:"varchar(1000)" json:"action"`
|
||||||
|
|
||||||
ExtendedUser *User `xorm:"-" json:"extendedUser"`
|
Object string `xorm:"-" json:"object"`
|
||||||
|
ExtendedUser *User `xorm:"-" json:"extendedUser"`
|
||||||
|
|
||||||
IsTriggered bool `json:"isTriggered"`
|
IsTriggered bool `json:"isTriggered"`
|
||||||
}
|
}
|
||||||
@@ -60,6 +61,11 @@ func NewRecord(ctx *context.Context) *Record {
|
|||||||
requestUri = requestUri[0:1000]
|
requestUri = requestUri[0:1000]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
object := ""
|
||||||
|
if ctx.Input.RequestBody != nil && len(ctx.Input.RequestBody) != 0 {
|
||||||
|
object = string(ctx.Input.RequestBody)
|
||||||
|
}
|
||||||
|
|
||||||
record := Record{
|
record := Record{
|
||||||
Name: util.GenerateId(),
|
Name: util.GenerateId(),
|
||||||
CreatedTime: util.GetCurrentTime(),
|
CreatedTime: util.GetCurrentTime(),
|
||||||
@@ -68,6 +74,7 @@ func NewRecord(ctx *context.Context) *Record {
|
|||||||
Method: ctx.Request.Method,
|
Method: ctx.Request.Method,
|
||||||
RequestUri: requestUri,
|
RequestUri: requestUri,
|
||||||
Action: action,
|
Action: action,
|
||||||
|
Object: object,
|
||||||
IsTriggered: false,
|
IsTriggered: false,
|
||||||
}
|
}
|
||||||
return &record
|
return &record
|
||||||
@@ -159,7 +166,7 @@ func SendWebhooks(record *Record) error {
|
|||||||
|
|
||||||
if matched {
|
if matched {
|
||||||
if webhook.IsUserExtended {
|
if webhook.IsUserExtended {
|
||||||
user := getUser(record.Organization, record.User)
|
user := GetMaskedUser(getUser(record.Organization, record.User))
|
||||||
record.ExtendedUser = user
|
record.ExtendedUser = user
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -224,13 +224,16 @@ func generateJwtToken(application *Application, user *User, nonce string, scope
|
|||||||
nowTime := time.Now()
|
nowTime := time.Now()
|
||||||
expireTime := nowTime.Add(time.Duration(application.ExpireInHours) * time.Hour)
|
expireTime := nowTime.Add(time.Duration(application.ExpireInHours) * time.Hour)
|
||||||
refreshExpireTime := nowTime.Add(time.Duration(application.RefreshExpireInHours) * time.Hour)
|
refreshExpireTime := nowTime.Add(time.Duration(application.RefreshExpireInHours) * time.Hour)
|
||||||
|
if application.RefreshExpireInHours == 0 {
|
||||||
|
refreshExpireTime = expireTime
|
||||||
|
}
|
||||||
|
|
||||||
user = refineUser(user)
|
user = refineUser(user)
|
||||||
|
|
||||||
_, originBackend := getOriginFromHost(host)
|
_, originBackend := getOriginFromHost(host)
|
||||||
|
|
||||||
name := util.GenerateId()
|
name := util.GenerateId()
|
||||||
jti := fmt.Sprintf("%s/%s", application.Owner, name)
|
jti := util.GetId(application.Owner, name)
|
||||||
|
|
||||||
claims := Claims{
|
claims := Claims{
|
||||||
User: user,
|
User: user,
|
||||||
|
@@ -472,6 +472,13 @@ func UpdateUser(id string, user *User, columns []string, isAdmin bool) bool {
|
|||||||
"location", "address", "country_code", "region", "language", "affiliation", "title", "homepage", "bio", "tag", "language", "gender", "birthday", "education", "score", "karma", "ranking", "signup_application",
|
"location", "address", "country_code", "region", "language", "affiliation", "title", "homepage", "bio", "tag", "language", "gender", "birthday", "education", "score", "karma", "ranking", "signup_application",
|
||||||
"is_admin", "is_global_admin", "is_forbidden", "is_deleted", "hash", "is_default_avatar", "properties", "webauthnCredentials", "managedAccounts",
|
"is_admin", "is_global_admin", "is_forbidden", "is_deleted", "hash", "is_default_avatar", "properties", "webauthnCredentials", "managedAccounts",
|
||||||
"signin_wrong_times", "last_signin_wrong_time",
|
"signin_wrong_times", "last_signin_wrong_time",
|
||||||
|
"github", "google", "qq", "wechat", "facebook", "dingtalk", "weibo", "gitee", "linkedin", "wecom", "lark", "gitlab", "adfs",
|
||||||
|
"baidu", "alipay", "casdoor", "infoflow", "apple", "azuread", "slack", "steam", "bilibili", "okta", "douyin", "line", "amazon",
|
||||||
|
"auth0", "battlenet", "bitbucket", "box", "cloudfoundry", "dailymotion", "deezer", "digitalocean", "discord", "dropbox",
|
||||||
|
"eveonline", "fitbit", "gitea", "heroku", "influxcloud", "instagram", "intercom", "kakao", "lastfm", "mailru", "meetup",
|
||||||
|
"microsoftonline", "naver", "nextcloud", "onedrive", "oura", "patreon", "paypal", "salesforce", "shopify", "soundcloud",
|
||||||
|
"spotify", "strava", "stripe", "tiktok", "tumblr", "twitch", "twitter", "typetalk", "uber", "vk", "wepay", "xero", "yahoo",
|
||||||
|
"yammer", "yandex", "zoom", "custom",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if isAdmin {
|
if isAdmin {
|
||||||
|
@@ -43,7 +43,7 @@ func AutoSigninFilter(ctx *context.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
userId := fmt.Sprintf("%s/%s", token.Organization, token.User)
|
userId := util.GetId(token.Organization, token.User)
|
||||||
application, _ := object.GetApplicationByUserId(fmt.Sprintf("app/%s", token.Application))
|
application, _ := object.GetApplicationByUserId(fmt.Sprintf("app/%s", token.Application))
|
||||||
setSessionUser(ctx, userId)
|
setSessionUser(ctx, userId)
|
||||||
setSessionOidc(ctx, token.Scope, application.ClientId)
|
setSessionOidc(ctx, token.Scope, application.ClientId)
|
||||||
|
@@ -15,8 +15,6 @@
|
|||||||
package routers
|
package routers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/beego/beego/context"
|
"github.com/beego/beego/context"
|
||||||
"github.com/casdoor/casdoor/object"
|
"github.com/casdoor/casdoor/object"
|
||||||
"github.com/casdoor/casdoor/util"
|
"github.com/casdoor/casdoor/util"
|
||||||
@@ -50,7 +48,7 @@ func getUserByClientIdSecret(ctx *context.Context) string {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
return fmt.Sprintf("%s/%s", application.Organization, application.Name)
|
return util.GetId(application.Organization, application.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
func RecordMessage(ctx *context.Context) {
|
func RecordMessage(ctx *context.Context) {
|
||||||
|
@@ -65,6 +65,7 @@ class ApplicationListPage extends BaseListPage {
|
|||||||
redirectUris: ["http://localhost:9000/callback"],
|
redirectUris: ["http://localhost:9000/callback"],
|
||||||
tokenFormat: "JWT",
|
tokenFormat: "JWT",
|
||||||
expireInHours: 24 * 7,
|
expireInHours: 24 * 7,
|
||||||
|
refreshExpireInHours: 24 * 7,
|
||||||
formOffset: 2,
|
formOffset: 2,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@@ -23,10 +23,20 @@ import BaseListPage from "./BaseListPage";
|
|||||||
import PopconfirmModal from "./common/modal/PopconfirmModal";
|
import PopconfirmModal from "./common/modal/PopconfirmModal";
|
||||||
|
|
||||||
class CertListPage extends BaseListPage {
|
class CertListPage extends BaseListPage {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
this.setState({
|
||||||
|
owner: Setting.isAdminUser(this.props.account) ? "admin" : this.props.account.owner,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
newCert() {
|
newCert() {
|
||||||
const randomName = Setting.getRandomName();
|
const randomName = Setting.getRandomName();
|
||||||
return {
|
return {
|
||||||
owner: this.props.account.owner, // this.props.account.certname,
|
owner: this.state.owner,
|
||||||
name: `cert_${randomName}`,
|
name: `cert_${randomName}`,
|
||||||
createdTime: moment().format(),
|
createdTime: moment().format(),
|
||||||
displayName: `New Cert - ${randomName}`,
|
displayName: `New Cert - ${randomName}`,
|
||||||
|
@@ -94,7 +94,7 @@ class LdapSyncPage extends React.Component {
|
|||||||
if (res.status === "ok") {
|
if (res.status === "ok") {
|
||||||
this.setState((prevState) => {
|
this.setState((prevState) => {
|
||||||
prevState.users = res.data.users;
|
prevState.users = res.data.users;
|
||||||
prevState.existUuids = res.data2?.length > 0 ? res.data2 : [];
|
prevState.existUuids = res.data.existUuids?.length > 0 ? res.data.existUuids.filter(uuid => uuid !== "") : [];
|
||||||
return prevState;
|
return prevState;
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
@@ -200,6 +200,22 @@ class OrganizationEditPage extends React.Component {
|
|||||||
</Select>
|
</Select>
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
|
<Row style={{marginTop: "20px"}} >
|
||||||
|
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||||
|
{Setting.getLabel(i18next.t("general:Languages"), i18next.t("general:Languages - Tooltip"))} :
|
||||||
|
</Col>
|
||||||
|
<Col span={22} >
|
||||||
|
<Select virtual={false} mode="tags" style={{width: "100%"}}
|
||||||
|
options={Setting.Countries.map((item) => {
|
||||||
|
return Setting.getOption(item.label, item.key);
|
||||||
|
})}
|
||||||
|
value={this.state.organization.languages ?? []}
|
||||||
|
onChange={(value => {
|
||||||
|
this.updateOrganizationField("languages", value);
|
||||||
|
})} >
|
||||||
|
</Select>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
<Row style={{marginTop: "20px"}} >
|
<Row style={{marginTop: "20px"}} >
|
||||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||||
{Setting.getLabel(i18next.t("general:Default avatar"), i18next.t("general:Default avatar - Tooltip"))} :
|
{Setting.getLabel(i18next.t("general:Default avatar"), i18next.t("general:Default avatar - Tooltip"))} :
|
||||||
@@ -259,22 +275,6 @@ class OrganizationEditPage extends React.Component {
|
|||||||
}} />
|
}} />
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
<Row style={{marginTop: "20px"}} >
|
|
||||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
|
||||||
{Setting.getLabel(i18next.t("general:Languages"), i18next.t("general:Languages - Tooltip"))} :
|
|
||||||
</Col>
|
|
||||||
<Col span={22} >
|
|
||||||
<Select virtual={false} mode="tags" style={{width: "100%"}}
|
|
||||||
options={Setting.Countries.map((item) => {
|
|
||||||
return Setting.getOption(item.label, item.key);
|
|
||||||
})}
|
|
||||||
value={this.state.organization.languages ?? []}
|
|
||||||
onChange={(value => {
|
|
||||||
this.updateOrganizationField("languages", value);
|
|
||||||
})} >
|
|
||||||
</Select>
|
|
||||||
</Col>
|
|
||||||
</Row>
|
|
||||||
<Row style={{marginTop: "20px"}} >
|
<Row style={{marginTop: "20px"}} >
|
||||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 19 : 2}>
|
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 19 : 2}>
|
||||||
{Setting.getLabel(i18next.t("organization:Init score"), i18next.t("organization:Init score - Tooltip"))} :
|
{Setting.getLabel(i18next.t("organization:Init score"), i18next.t("organization:Init score - Tooltip"))} :
|
||||||
|
@@ -42,6 +42,7 @@ export const Countries = [{label: "English", key: "en", country: "US", alt: "Eng
|
|||||||
{label: "한국어", key: "ko", country: "KR", alt: "한국어"},
|
{label: "한국어", key: "ko", country: "KR", alt: "한국어"},
|
||||||
{label: "Русский", key: "ru", country: "RU", alt: "Русский"},
|
{label: "Русский", key: "ru", country: "RU", alt: "Русский"},
|
||||||
{label: "TiếngViệt", key: "vi", country: "VN", alt: "TiếngViệt"},
|
{label: "TiếngViệt", key: "vi", country: "VN", alt: "TiếngViệt"},
|
||||||
|
{label: "Português", key: "pt", country: "BR", alt: "Português"},
|
||||||
];
|
];
|
||||||
|
|
||||||
export function getThemeData(organization, application) {
|
export function getThemeData(organization, application) {
|
||||||
|
@@ -28,6 +28,20 @@ require("codemirror/mode/javascript/javascript");
|
|||||||
|
|
||||||
const {Option} = Select;
|
const {Option} = Select;
|
||||||
|
|
||||||
|
const applicationTemplate = {
|
||||||
|
owner: "admin", // this.props.account.applicationName,
|
||||||
|
name: "application_123",
|
||||||
|
organization: "built-in",
|
||||||
|
createdTime: "2022-01-01T01:03:42+08:00",
|
||||||
|
displayName: "New Application - 123",
|
||||||
|
logo: `${Setting.StaticBaseUrl}/img/casdoor-logo_1185x256.png`,
|
||||||
|
enablePassword: true,
|
||||||
|
enableSignUp: true,
|
||||||
|
enableSigninSession: false,
|
||||||
|
enableCodeSignin: false,
|
||||||
|
enableSamlCompress: false,
|
||||||
|
};
|
||||||
|
|
||||||
const previewTemplate = {
|
const previewTemplate = {
|
||||||
"id": 9078,
|
"id": 9078,
|
||||||
"owner": "built-in",
|
"owner": "built-in",
|
||||||
@@ -37,9 +51,10 @@ const previewTemplate = {
|
|||||||
"clientIp": "159.89.126.192",
|
"clientIp": "159.89.126.192",
|
||||||
"user": "admin",
|
"user": "admin",
|
||||||
"method": "POST",
|
"method": "POST",
|
||||||
"requestUri": "/api/login",
|
"requestUri": "/api/add-application",
|
||||||
"action": "login",
|
"action": "login",
|
||||||
"isTriggered": false,
|
"isTriggered": false,
|
||||||
|
"object": JSON.stringify(applicationTemplate),
|
||||||
};
|
};
|
||||||
|
|
||||||
const userTemplate = {
|
const userTemplate = {
|
||||||
@@ -49,7 +64,7 @@ const userTemplate = {
|
|||||||
"updatedTime": "",
|
"updatedTime": "",
|
||||||
"id": "9eb20f79-3bb5-4e74-99ac-39e3b9a171e8",
|
"id": "9eb20f79-3bb5-4e74-99ac-39e3b9a171e8",
|
||||||
"type": "normal-user",
|
"type": "normal-user",
|
||||||
"password": "123",
|
"password": "***",
|
||||||
"passwordSalt": "",
|
"passwordSalt": "",
|
||||||
"displayName": "Admin",
|
"displayName": "Admin",
|
||||||
"avatar": "https://cdn.casbin.com/usercontent/admin/avatar/1596241359.png",
|
"avatar": "https://cdn.casbin.com/usercontent/admin/avatar/1596241359.png",
|
||||||
|
@@ -242,6 +242,7 @@ class LoginPage extends React.Component {
|
|||||||
|
|
||||||
if (resp.msg === RequiredMfa) {
|
if (resp.msg === RequiredMfa) {
|
||||||
Setting.goToLink(`/prompt/${application.name}?redirectUri=${oAuthParams.redirectUri}&code=${code}&state=${oAuthParams.state}&promptType=mfa`);
|
Setting.goToLink(`/prompt/${application.name}?redirectUri=${oAuthParams.redirectUri}&code=${code}&state=${oAuthParams.state}&promptType=mfa`);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Setting.isPromptAnswered(account, application)) {
|
if (Setting.isPromptAnswered(account, application)) {
|
||||||
|
@@ -23,6 +23,7 @@ import ja from "./locales/ja/data.json";
|
|||||||
import ko from "./locales/ko/data.json";
|
import ko from "./locales/ko/data.json";
|
||||||
import ru from "./locales/ru/data.json";
|
import ru from "./locales/ru/data.json";
|
||||||
import vi from "./locales/vi/data.json";
|
import vi from "./locales/vi/data.json";
|
||||||
|
import pt from "./locales/pt/data.json";
|
||||||
import * as Conf from "./Conf";
|
import * as Conf from "./Conf";
|
||||||
import {initReactI18next} from "react-i18next";
|
import {initReactI18next} from "react-i18next";
|
||||||
|
|
||||||
@@ -37,6 +38,7 @@ const resources = {
|
|||||||
ko: ko,
|
ko: ko,
|
||||||
ru: ru,
|
ru: ru,
|
||||||
vi: vi,
|
vi: vi,
|
||||||
|
pt: pt,
|
||||||
};
|
};
|
||||||
|
|
||||||
function initLanguage() {
|
function initLanguage() {
|
||||||
@@ -83,6 +85,9 @@ function initLanguage() {
|
|||||||
case "vi":
|
case "vi":
|
||||||
language = "vi";
|
language = "vi";
|
||||||
break;
|
break;
|
||||||
|
case "pt":
|
||||||
|
language = "pt";
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
language = Conf.DefaultLanguage;
|
language = Conf.DefaultLanguage;
|
||||||
}
|
}
|
||||||
|
889
web/src/locales/pt/data.json
Normal file
889
web/src/locales/pt/data.json
Normal file
@@ -0,0 +1,889 @@
|
|||||||
|
{
|
||||||
|
"account": {
|
||||||
|
"Chats & Messages": "Conversas e Mensagens",
|
||||||
|
"Logout": "Sair",
|
||||||
|
"My Account": "Minha Conta",
|
||||||
|
"Sign Up": "Cadastrar-se"
|
||||||
|
},
|
||||||
|
"adapter": {
|
||||||
|
"Duplicated policy rules": "Regras de política duplicadas",
|
||||||
|
"Edit Adapter": "Editar Adaptador",
|
||||||
|
"Failed to sync policies": "Falha ao sincronizar as políticas",
|
||||||
|
"New Adapter": "Novo Adaptador",
|
||||||
|
"Policies": "Políticas",
|
||||||
|
"Policies - Tooltip": "Regras de política do Casbin",
|
||||||
|
"Sync policies successfully": "Políticas sincronizadas com sucesso"
|
||||||
|
},
|
||||||
|
"application": {
|
||||||
|
"Always": "Sempre",
|
||||||
|
"Auto signin": "Login automático",
|
||||||
|
"Auto signin - Tooltip": "Quando uma sessão logada existe no Casdoor, ela é automaticamente usada para o login no lado da aplicação",
|
||||||
|
"Background URL": "URL de Fundo",
|
||||||
|
"Background URL - Tooltip": "URL da imagem de fundo usada na página de login",
|
||||||
|
"Center": "Centro",
|
||||||
|
"Copy SAML metadata URL": "Copiar URL de metadados SAML",
|
||||||
|
"Copy prompt page URL": "Copiar URL da página de prompt",
|
||||||
|
"Copy signin page URL": "Copiar URL da página de login",
|
||||||
|
"Copy signup page URL": "Copiar URL da página de registro",
|
||||||
|
"Dynamic": "Dinâmico",
|
||||||
|
"Edit Application": "Editar Aplicação",
|
||||||
|
"Enable Email linking": "Ativar vinculação de e-mail",
|
||||||
|
"Enable Email linking - Tooltip": "Ao usar provedores de terceiros para fazer login, se houver um usuário na organização com o mesmo e-mail, o método de login de terceiros será automaticamente associado a esse usuário",
|
||||||
|
"Enable SAML compression": "Ativar compressão SAML",
|
||||||
|
"Enable SAML compression - Tooltip": "Se deve comprimir as mensagens de resposta SAML quando o Casdoor é usado como provedor de identidade SAML",
|
||||||
|
"Enable WebAuthn signin": "Ativar login WebAuthn",
|
||||||
|
"Enable WebAuthn signin - Tooltip": "Se permite que os usuários façam login com WebAuthn",
|
||||||
|
"Enable code signin": "Ativar login com código",
|
||||||
|
"Enable code signin - Tooltip": "Se permite que os usuários façam login com código de verificação de telefone ou e-mail",
|
||||||
|
"Enable password": "Ativar senha",
|
||||||
|
"Enable password - Tooltip": "Se permite que os usuários façam login com senha",
|
||||||
|
"Enable side panel": "Ativar painel lateral",
|
||||||
|
"Enable signin session - Tooltip": "Se o Casdoor mantém uma sessão depois de fazer login no Casdoor a partir da aplicação",
|
||||||
|
"Enable signup": "Ativar registro",
|
||||||
|
"Enable signup - Tooltip": "Se permite que os usuários registrem uma nova conta",
|
||||||
|
"Failed to sign in": "Falha ao fazer login",
|
||||||
|
"File uploaded successfully": "Arquivo enviado com sucesso",
|
||||||
|
"First, last": "Primeiro, último",
|
||||||
|
"Follow organization theme": "Seguir tema da organização",
|
||||||
|
"Form CSS": "CSS do formulário",
|
||||||
|
"Form CSS - Edit": "Editar CSS do formulário",
|
||||||
|
"Form CSS - Tooltip": "Estilização CSS dos formulários de registro, login e recuperação de senha (por exemplo, adicionando bordas e sombras)",
|
||||||
|
"Form CSS Mobile": "CSS do formulário em dispositivos móveis",
|
||||||
|
"Form CSS Mobile - Edit": "Editar CSS do formulário em dispositivos móveis",
|
||||||
|
"Form CSS Mobile - Tooltip": "CSS do formulário em dispositivos móveis - Dica",
|
||||||
|
"Form position": "Posição do formulário",
|
||||||
|
"Form position - Tooltip": "Localização dos formulários de registro, login e recuperação de senha",
|
||||||
|
"Grant types": "Tipos de concessão",
|
||||||
|
"Grant types - Tooltip": "Selecione quais tipos de concessão são permitidos no protocolo OAuth",
|
||||||
|
"Incremental": "Incremental",
|
||||||
|
"Left": "Esquerda",
|
||||||
|
"Logged in successfully": "Login realizado com sucesso",
|
||||||
|
"Logged out successfully": "Logout realizado com sucesso",
|
||||||
|
"New Application": "Nova Aplicação",
|
||||||
|
"No verification": "Sem verificação",
|
||||||
|
"None": "Nenhum",
|
||||||
|
"Normal": "Normal",
|
||||||
|
"Only signup": "Apenas registro",
|
||||||
|
"Please input your application!": "Por favor, insira o nome da sua aplicação!",
|
||||||
|
"Please input your organization!": "Por favor, insira o nome da sua organização!",
|
||||||
|
"Please select a HTML file": "Por favor, selecione um arquivo HTML",
|
||||||
|
"Prompt page URL copied to clipboard successfully, please paste it into the incognito window or another browser": "URL da página de prompt copiada para a área de transferência com sucesso. Cole-a na janela anônima ou em outro navegador",
|
||||||
|
"Random": "Aleatório",
|
||||||
|
"Real name": "Nome real",
|
||||||
|
"Redirect URL": "URL de redirecionamento",
|
||||||
|
"Redirect URL (Assertion Consumer Service POST Binding URL) - Tooltip": "URL de redirecionamento (URL de ligação de postagem de serviço do consumidor de afirmação)",
|
||||||
|
"Redirect URLs": "URLs de redirecionamento",
|
||||||
|
"Redirect URLs - Tooltip": "Lista de URLs de redirecionamento permitidos, com suporte à correspondência por expressões regulares; URLs que não estão na lista falharão ao redirecionar",
|
||||||
|
"Refresh token expire": "Expiração do token de atualização",
|
||||||
|
"Refresh token expire - Tooltip": "Tempo de expiração do token de atualização",
|
||||||
|
"Right": "Direita",
|
||||||
|
"Rule": "Regra",
|
||||||
|
"SAML metadata": "Metadados do SAML",
|
||||||
|
"SAML metadata - Tooltip": "Os metadados do protocolo SAML",
|
||||||
|
"SAML metadata URL copied to clipboard successfully": "URL dos metadados do SAML copiada para a área de transferência com sucesso",
|
||||||
|
"SAML reply URL": "URL de resposta do SAML",
|
||||||
|
"Side panel HTML": "HTML do painel lateral",
|
||||||
|
"Side panel HTML - Edit": "Editar HTML do painel lateral",
|
||||||
|
"Side panel HTML - Tooltip": "Personalize o código HTML para o painel lateral da página de login",
|
||||||
|
"Sign Up Error": "Erro ao Registrar",
|
||||||
|
"Signin": "Login",
|
||||||
|
"Signin (Default True)": "Login (Padrão Verdadeiro)",
|
||||||
|
"Signin page URL copied to clipboard successfully, please paste it into the incognito window or another browser": "URL da página de login copiada para a área de transferência com sucesso. Cole-a na janela anônima ou em outro navegador",
|
||||||
|
"Signin session": "Sessão de login",
|
||||||
|
"Signup items": "Itens de registro",
|
||||||
|
"Signup items - Tooltip": "Itens para os usuários preencherem ao registrar novas contas",
|
||||||
|
"Signup page URL copied to clipboard successfully, please paste it into the incognito window or another browser": "URL da página de registro copiada para a área de transferência com sucesso. Cole-a na janela anônima ou em outro navegador",
|
||||||
|
"The application does not allow to sign up new account": "A aplicação não permite o registro de novas contas",
|
||||||
|
"Token expire": "Expiração do Token",
|
||||||
|
"Token expire - Tooltip": "Tempo de expiração do token de acesso",
|
||||||
|
"Token format": "Formato do token",
|
||||||
|
"Token format - Tooltip": "O formato do token de acesso",
|
||||||
|
"You are unexpected to see this prompt page": "Você não deveria ver esta página de prompt"
|
||||||
|
},
|
||||||
|
"cert": {
|
||||||
|
"Bit size": "Tamanho do bit",
|
||||||
|
"Bit size - Tooltip": "Comprimento da chave secreta",
|
||||||
|
"Certificate": "Certificado",
|
||||||
|
"Certificate - Tooltip": "Certificado de chave pública, usado para descriptografar a assinatura JWT do Token de Acesso. Este certificado geralmente precisa ser implantado no lado do SDK do Casdoor (ou seja, no aplicativo) para analisar o JWT",
|
||||||
|
"Certificate copied to clipboard successfully": "Certificado copiado para a área de transferência com sucesso",
|
||||||
|
"Copy certificate": "Copiar certificado",
|
||||||
|
"Copy private key": "Copiar chave privada",
|
||||||
|
"Crypto algorithm": "Algoritmo criptográfico",
|
||||||
|
"Crypto algorithm - Tooltip": "Algoritmo de criptografia usado pelo certificado",
|
||||||
|
"Download certificate": "Baixar certificado",
|
||||||
|
"Download private key": "Baixar chave privada",
|
||||||
|
"Edit Cert": "Editar Certificado",
|
||||||
|
"Expire in years": "Expirar em anos",
|
||||||
|
"Expire in years - Tooltip": "Período de validade do certificado, em anos",
|
||||||
|
"New Cert": "Novo Certificado",
|
||||||
|
"Private key": "Chave privada",
|
||||||
|
"Private key - Tooltip": "Chave privada correspondente ao certificado de chave pública",
|
||||||
|
"Private key copied to clipboard successfully": "Chave privada copiada para a área de transferência com sucesso",
|
||||||
|
"Scope - Tooltip": "Cenários de uso do certificado",
|
||||||
|
"Type - Tooltip": "Tipo de certificado"
|
||||||
|
},
|
||||||
|
"chat": {
|
||||||
|
"AI": "IA",
|
||||||
|
"Edit Chat": "Editar Chat",
|
||||||
|
"Group": "Grupo",
|
||||||
|
"Message count": "Contagem de Mensagens",
|
||||||
|
"New Chat": "Novo Chat",
|
||||||
|
"Single": "Individual",
|
||||||
|
"User1": "Usuário 1",
|
||||||
|
"User1 - Tooltip": "Usuário 1 - Tooltip",
|
||||||
|
"User2": "Usuário 2",
|
||||||
|
"User2 - Tooltip": "Usuário 2 - Tooltip",
|
||||||
|
"Users - Tooltip": "Usuários - Tooltip"
|
||||||
|
},
|
||||||
|
"code": {
|
||||||
|
"Code you received": "Código que você recebeu",
|
||||||
|
"Email code": "Código de e-mail",
|
||||||
|
"Empty code": "Código vazio",
|
||||||
|
"Enter your code": "Digite seu código",
|
||||||
|
"Phone code": "Código de telefone",
|
||||||
|
"Please input your phone verification code!": "Por favor, insira o código de verificação do telefone!",
|
||||||
|
"Please input your verification code!": "Por favor, insira o seu código de verificação!",
|
||||||
|
"Send Code": "Enviar Código",
|
||||||
|
"Sending": "Enviando",
|
||||||
|
"Submit and complete": "Enviar e concluir"
|
||||||
|
},
|
||||||
|
"forget": {
|
||||||
|
"Account": "Conta",
|
||||||
|
"Change Password": "Alterar Senha",
|
||||||
|
"Choose email or phone": "Escolha e-mail ou telefone",
|
||||||
|
"Next Step": "Próxima Etapa",
|
||||||
|
"Please input your username!": "Por favor, insira seu nome de usuário!",
|
||||||
|
"Reset": "Redefinir",
|
||||||
|
"Retrieve password": "Recuperar senha",
|
||||||
|
"Unknown forget type": "Tipo de recuperação desconhecido",
|
||||||
|
"Verify": "Verificar"
|
||||||
|
},
|
||||||
|
"general": {
|
||||||
|
"Action": "Ação",
|
||||||
|
"Adapter": "Adaptador",
|
||||||
|
"Adapter - Tooltip": "Nome da tabela do armazenamento de políticas",
|
||||||
|
"Adapters": "Adaptadores",
|
||||||
|
"Add": "Adicionar",
|
||||||
|
"Affiliation URL": "URL da Afiliação",
|
||||||
|
"Affiliation URL - Tooltip": "A URL da página inicial para a afiliação",
|
||||||
|
"Application": "Aplicação",
|
||||||
|
"Applications": "Aplicações",
|
||||||
|
"Applications that require authentication": "Aplicações que requerem autenticação",
|
||||||
|
"Avatar": "Avatar",
|
||||||
|
"Avatar - Tooltip": "Imagem de avatar pública do usuário",
|
||||||
|
"Back": "Voltar",
|
||||||
|
"Back Home": "Voltar para a Página Inicial",
|
||||||
|
"Cancel": "Cancelar",
|
||||||
|
"Captcha": "Captcha",
|
||||||
|
"Cert": "Certificado",
|
||||||
|
"Cert - Tooltip": "O certificado da chave pública que precisa ser verificado pelo SDK do cliente correspondente a esta aplicação",
|
||||||
|
"Certs": "Certificados",
|
||||||
|
"Chats": "Chats",
|
||||||
|
"Click to Upload": "Clique para Enviar",
|
||||||
|
"Client IP": "IP do Cliente",
|
||||||
|
"Close": "Fechar",
|
||||||
|
"Created time": "Hora de Criação",
|
||||||
|
"Default application": "Aplicação padrão",
|
||||||
|
"Default application - Tooltip": "Aplicação padrão para usuários registrados diretamente na página da organização",
|
||||||
|
"Default avatar": "Avatar padrão",
|
||||||
|
"Default avatar - Tooltip": "Avatar padrão usado quando usuários recém-registrados não definem uma imagem de avatar",
|
||||||
|
"Delete": "Excluir",
|
||||||
|
"Description": "Descrição",
|
||||||
|
"Description - Tooltip": "Informações de descrição detalhadas para referência, o Casdoor em si não irá utilizá-las",
|
||||||
|
"Display name": "Nome de exibição",
|
||||||
|
"Display name - Tooltip": "Um nome amigável e facilmente legível exibido publicamente na interface do usuário",
|
||||||
|
"Down": "Descer",
|
||||||
|
"Edit": "Editar",
|
||||||
|
"Email": "E-mail",
|
||||||
|
"Email - Tooltip": "Endereço de e-mail válido",
|
||||||
|
"Enable": "Habilitar",
|
||||||
|
"Enabled": "Habilitado",
|
||||||
|
"Enabled successfully": "Habilitado com sucesso",
|
||||||
|
"Failed to add": "Falha ao adicionar",
|
||||||
|
"Failed to connect to server": "Falha ao conectar ao servidor",
|
||||||
|
"Failed to delete": "Falha ao excluir",
|
||||||
|
"Failed to enable": "Falha ao habilitar",
|
||||||
|
"Failed to get answer": "Falha ao obter resposta",
|
||||||
|
"Failed to save": "Falha ao salvar",
|
||||||
|
"Failed to verify": "Falha ao verificar",
|
||||||
|
"Favicon": "Favicon",
|
||||||
|
"Favicon - Tooltip": "URL do ícone de favicon usado em todas as páginas do Casdoor da organização",
|
||||||
|
"First name": "Nome",
|
||||||
|
"Forget URL": "URL de Esqueci a Senha",
|
||||||
|
"Forget URL - Tooltip": "URL personalizada para a página de \"Esqueci a senha\". Se não definido, será usada a página padrão de \"Esqueci a senha\" do Casdoor. Quando definido, o link de \"Esqueci a senha\" na página de login será redirecionado para esta URL",
|
||||||
|
"Found some texts still not translated? Please help us translate at": "Encontrou algum texto ainda não traduzido? Ajude-nos a traduzir em",
|
||||||
|
"Go to writable demo site?": "Acessar o site de demonstração gravável?",
|
||||||
|
"Home": "Página Inicial",
|
||||||
|
"Home - Tooltip": "Página inicial do aplicativo",
|
||||||
|
"ID": "ID",
|
||||||
|
"ID - Tooltip": "String única aleatória",
|
||||||
|
"Is enabled": "Está habilitado",
|
||||||
|
"Is enabled - Tooltip": "Define se está habilitado",
|
||||||
|
"LDAPs": "LDAPs",
|
||||||
|
"LDAPs - Tooltip": "Servidores LDAP",
|
||||||
|
"Languages": "Idiomas",
|
||||||
|
"Languages - Tooltip": "Idiomas disponíveis",
|
||||||
|
"Last name": "Sobrenome",
|
||||||
|
"Logo": "Logo",
|
||||||
|
"Logo - Tooltip": "Ícones que o aplicativo apresenta para o mundo externo",
|
||||||
|
"Master password": "Senha mestra",
|
||||||
|
"Master password - Tooltip": "Pode ser usada para fazer login em todos os usuários desta organização, facilitando para os administradores fazerem login como este usuário para resolver problemas técnicos",
|
||||||
|
"Menu": "Menu",
|
||||||
|
"Messages": "Mensagens",
|
||||||
|
"Method": "Método",
|
||||||
|
"Model": "Modelo",
|
||||||
|
"Model - Tooltip": "Modelo de controle de acesso do Casbin",
|
||||||
|
"Models": "Modelos",
|
||||||
|
"Name": "Nome",
|
||||||
|
"Name - Tooltip": "ID único em formato de string",
|
||||||
|
"OAuth providers": "Provedores OAuth",
|
||||||
|
"OK": "OK",
|
||||||
|
"Organization": "Organização",
|
||||||
|
"Organization - Tooltip": "Semelhante a conceitos como inquilinos ou grupos de usuários, cada usuário e aplicativo pertence a uma organização",
|
||||||
|
"Organizations": "Organizações",
|
||||||
|
"Password": "Senha",
|
||||||
|
"Password - Tooltip": "Certifique-se de que a senha está correta",
|
||||||
|
"Password salt": "Salt de senha",
|
||||||
|
"Password salt - Tooltip": "Parâmetro aleatório usado para criptografia de senha",
|
||||||
|
"Password type": "Tipo de senha",
|
||||||
|
"Password type - Tooltip": "Formato de armazenamento de senhas no banco de dados",
|
||||||
|
"Payments": "Pagamentos",
|
||||||
|
"Permissions": "Permissões",
|
||||||
|
"Permissions - Tooltip": "Permissões pertencentes a este usuário",
|
||||||
|
"Phone": "Telefone",
|
||||||
|
"Phone - Tooltip": "Número de telefone",
|
||||||
|
"Phone or email": "Telefone ou email",
|
||||||
|
"Preview": "Visualizar",
|
||||||
|
"Preview - Tooltip": "Visualizar os efeitos configurados",
|
||||||
|
"Products": "Produtos",
|
||||||
|
"Provider": "Provedor",
|
||||||
|
"Provider - Tooltip": "Provedores de pagamento a serem configurados, incluindo PayPal, Alipay, WeChat Pay, etc.",
|
||||||
|
"Providers": "Provedores",
|
||||||
|
"Providers - Tooltip": "Provedores a serem configurados, incluindo login de terceiros, armazenamento de objetos, código de verificação, etc.",
|
||||||
|
"Real name": "Nome real",
|
||||||
|
"Records": "Registros",
|
||||||
|
"Request URI": "URI da solicitação",
|
||||||
|
"Resources": "Recursos",
|
||||||
|
"Roles": "Funções",
|
||||||
|
"Roles - Tooltip": "Funções às quais o usuário pertence",
|
||||||
|
"Save": "Salvar",
|
||||||
|
"Save & Exit": "Salvar e Sair",
|
||||||
|
"Session ID": "ID da sessão",
|
||||||
|
"Sessions": "Sessões",
|
||||||
|
"Signin URL": "URL de login",
|
||||||
|
"Signin URL - Tooltip": "URL personalizada para a página de login. Se não definido, será usada a página padrão de login do Casdoor. Quando definido, os links de login em várias páginas do Casdoor serão redirecionados para esta URL",
|
||||||
|
"Signup URL": "URL de registro",
|
||||||
|
"Signup URL - Tooltip": "URL personalizada para a página de registro. Se não definido, será usada a página padrão de registro do Casdoor. Quando definido, os links de registro em várias páginas do Casdoor serão redirecionados para esta URL",
|
||||||
|
"Signup application": "Aplicativo de registro",
|
||||||
|
"Signup application - Tooltip": "Qual aplicativo o usuário usou para se registrar quando se inscreveu",
|
||||||
|
"Sorry, the page you visited does not exist.": "Desculpe, a página que você visitou não existe.",
|
||||||
|
"Sorry, the user you visited does not exist or you are not authorized to access this user.": "Desculpe, o usuário que você visitou não existe ou você não está autorizado a acessar este usuário.",
|
||||||
|
"Sorry, you do not have permission to access this page or logged in status invalid.": "Desculpe, você não tem permissão para acessar esta página ou o status de login é inválido.",
|
||||||
|
"State": "Estado",
|
||||||
|
"State - Tooltip": "Estado",
|
||||||
|
"Successfully added": "Adicionado com sucesso",
|
||||||
|
"Successfully deleted": "Excluído com sucesso",
|
||||||
|
"Successfully saved": "Salvo com sucesso",
|
||||||
|
"Supported country codes": "Códigos de país suportados",
|
||||||
|
"Supported country codes - Tooltip": "Códigos de país suportados pela organização. Esses códigos podem ser selecionados como prefixo ao enviar códigos de verificação SMS",
|
||||||
|
"Sure to delete": "Tem certeza que deseja excluir",
|
||||||
|
"Swagger": "Swagger",
|
||||||
|
"Sync": "Sincronizar",
|
||||||
|
"Syncers": "Sincronizadores",
|
||||||
|
"System Info": "Informações do Sistema",
|
||||||
|
"There was a problem signing you in..": "Ocorreu um problema ao fazer o login.",
|
||||||
|
"This is a read-only demo site!": "Este é um site de demonstração apenas para leitura!",
|
||||||
|
"Timestamp": "Carimbo de Data/Hora",
|
||||||
|
"Tokens": "Tokens",
|
||||||
|
"URL": "URL",
|
||||||
|
"URL - Tooltip": "Link da URL",
|
||||||
|
"Up": "Acima",
|
||||||
|
"Updated time": "Hora de Atualização",
|
||||||
|
"User": "Usuário",
|
||||||
|
"User - Tooltip": "Certifique-se de que o nome de usuário esteja correto",
|
||||||
|
"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\"",
|
||||||
|
"Users": "Usuários",
|
||||||
|
"Users under all organizations": "Usuários em todas as organizações",
|
||||||
|
"Webhooks": "Webhooks",
|
||||||
|
"empty": "vazio",
|
||||||
|
"{total} in total": "{total} no total"
|
||||||
|
},
|
||||||
|
"ldap": {
|
||||||
|
"Admin": "Administrador",
|
||||||
|
"Admin - Tooltip": "CN ou ID do administrador do servidor LDAP",
|
||||||
|
"Admin Password": "Senha do Administrador",
|
||||||
|
"Admin Password - Tooltip": "Senha do administrador do servidor LDAP",
|
||||||
|
"Auto Sync": "Sincronização Automática",
|
||||||
|
"Auto Sync - Tooltip": "Configuração de sincronização automática, desativada em 0",
|
||||||
|
"Base DN": "Base DN",
|
||||||
|
"Base DN - Tooltip": "Base DN durante a busca LDAP",
|
||||||
|
"CN": "CN",
|
||||||
|
"Edit LDAP": "Editar LDAP",
|
||||||
|
"Enable SSL": "Habilitar SSL",
|
||||||
|
"Enable SSL - Tooltip": "Se habilitar o SSL",
|
||||||
|
"Filter fields": "Campos de Filtro",
|
||||||
|
"Filter fields - Tooltip": "Campos de filtro - Tooltip",
|
||||||
|
"Group ID": "ID do Grupo",
|
||||||
|
"Last Sync": "Última Sincronização",
|
||||||
|
"Search Filter": "Filtro de Busca",
|
||||||
|
"Search Filter - Tooltip": "Filtro de busca - Tooltip",
|
||||||
|
"Server": "Servidor",
|
||||||
|
"Server host": "Host do Servidor",
|
||||||
|
"Server host - Tooltip": "Endereço do servidor LDAP",
|
||||||
|
"Server name": "Nome do Servidor",
|
||||||
|
"Server name - Tooltip": "Nome de exibição da configuração do servidor LDAP",
|
||||||
|
"Server port": "Porta do Servidor",
|
||||||
|
"Server port - Tooltip": "Porta do servidor LDAP",
|
||||||
|
"The Auto Sync option will sync all users to specify organization": "A opção de Sincronização Automática irá sincronizar todos os usuários para a organização especificada",
|
||||||
|
"synced": "Sincronizado",
|
||||||
|
"unsynced": "Não sincronizado"
|
||||||
|
},
|
||||||
|
"login": {
|
||||||
|
"Auto sign in": "Entrar automaticamente",
|
||||||
|
"Continue with": "Continuar com",
|
||||||
|
"Email or phone": "Email ou telefone",
|
||||||
|
"Forgot password?": "Esqueceu a senha?",
|
||||||
|
"Loading": "Carregando",
|
||||||
|
"Logging out...": "Saindo...",
|
||||||
|
"No account?": "Não possui uma conta?",
|
||||||
|
"Or sign in with another account": "Ou entre com outra conta",
|
||||||
|
"Please input your Email or Phone!": "Por favor, informe seu email ou telefone!",
|
||||||
|
"Please input your code!": "Por favor, informe o código!",
|
||||||
|
"Please input your password!": "Por favor, informe sua senha!",
|
||||||
|
"Please input your password, at least 6 characters!": "Por favor, informe sua senha, pelo menos 6 caracteres!",
|
||||||
|
"Redirecting, please wait.": "Redirecionando, por favor aguarde.",
|
||||||
|
"Sign In": "Entrar",
|
||||||
|
"Sign in with WebAuthn": "Entrar com WebAuthn",
|
||||||
|
"Sign in with {type}": "Entrar com {type}",
|
||||||
|
"Signing in...": "Entrando...",
|
||||||
|
"Successfully logged in with WebAuthn credentials": "Logado com sucesso usando credenciais WebAuthn",
|
||||||
|
"The input is not valid Email or phone number!": "O valor inserido não é um email ou número de telefone válido!",
|
||||||
|
"To access": "Para acessar",
|
||||||
|
"Verification code": "Código de verificação",
|
||||||
|
"WebAuthn": "WebAuthn",
|
||||||
|
"sign up now": "Inscreva-se agora",
|
||||||
|
"username, Email or phone": "Nome de usuário, email ou telefone"
|
||||||
|
},
|
||||||
|
"message": {
|
||||||
|
"Author": "Autor",
|
||||||
|
"Author - Tooltip": "Autor - Dica de ferramenta",
|
||||||
|
"Chat": "Chat",
|
||||||
|
"Chat - Tooltip": "Chat - Dica de ferramenta",
|
||||||
|
"Edit Message": "Editar Mensagem",
|
||||||
|
"New Message": "Nova Mensagem",
|
||||||
|
"Text": "Texto",
|
||||||
|
"Text - Tooltip": "Texto - Dica de ferramenta"
|
||||||
|
},
|
||||||
|
"mfa": {
|
||||||
|
"Each time you sign in to your Account, you'll need your password and a authentication code": "Cada vez que você entrar na sua Conta, você precisará da sua senha e de um código de autenticação",
|
||||||
|
"Failed to get application": "Falha ao obter o aplicativo",
|
||||||
|
"Failed to initiate MFA": "Falha ao iniciar MFA",
|
||||||
|
"Have problems?": "Está com problemas?",
|
||||||
|
"Multi-factor authentication": "Autenticação de vários fatores",
|
||||||
|
"Multi-factor authentication - Tooltip ": "Autenticação de vários fatores - Dica de ferramenta",
|
||||||
|
"Multi-factor authentication description": "Configurar autenticação de vários fatores",
|
||||||
|
"Multi-factor methods": "Métodos de vários fatores",
|
||||||
|
"Multi-factor recover": "Recuperação de vários fatores",
|
||||||
|
"Multi-factor recover description": "Se você não conseguir acessar seu dispositivo, insira seu código de recuperação para verificar sua identidade",
|
||||||
|
"Multi-factor secret": "Segredo de vários fatores",
|
||||||
|
"Multi-factor secret - Tooltip": "Segredo de vários fatores - Dica de ferramenta",
|
||||||
|
"Multi-factor secret to clipboard successfully": "Segredo de vários fatores copiado para a área de transferência com sucesso",
|
||||||
|
"Passcode": "Código de acesso",
|
||||||
|
"Please save this recovery code. Once your device cannot provide an authentication code, you can reset mfa authentication by this recovery code": "Guarde este código de recuperação. Quando o seu dispositivo não puder fornecer um código de autenticação, você poderá redefinir a autenticação mfa usando este código de recuperação",
|
||||||
|
"Protect your account with Multi-factor authentication": "Proteja sua conta com autenticação de vários fatores",
|
||||||
|
"Recovery code": "Código de recuperação",
|
||||||
|
"SMS/Email message": "Mensagem SMS/E-mail",
|
||||||
|
"Set preferred": "Definir preferido",
|
||||||
|
"Setup": "Configuração",
|
||||||
|
"Use SMS verification code": "Usar código de verificação SMS",
|
||||||
|
"Use a recovery code": "Usar um código de recuperação",
|
||||||
|
"Verification failed": "Verificação falhou",
|
||||||
|
"Verify Code": "Verificar Código",
|
||||||
|
"Verify Password": "Verificar Senha",
|
||||||
|
"Your email is": "Seu e-mail é",
|
||||||
|
"Your phone is": "Seu telefone é",
|
||||||
|
"preferred": "Preferido"
|
||||||
|
},
|
||||||
|
"model": {
|
||||||
|
"Edit Model": "Editar Modelo",
|
||||||
|
"Model text": "Texto do Modelo",
|
||||||
|
"Model text - Tooltip": "Modelo de controle de acesso Casbin, incluindo modelos incorporados como ACL, RBAC, ABAC, RESTful, etc. Você também pode criar modelos personalizados. Para obter mais informações, visite o site do Casbin",
|
||||||
|
"New Model": "Novo Modelo"
|
||||||
|
},
|
||||||
|
"organization": {
|
||||||
|
"Account items": "Itens da Conta",
|
||||||
|
"Account items - Tooltip": "Itens na página de Configurações Pessoais",
|
||||||
|
"Edit Organization": "Editar Organização",
|
||||||
|
"Follow global theme": "Seguir tema global",
|
||||||
|
"Init score": "Pontuação inicial",
|
||||||
|
"Init score - Tooltip": "Pontos de pontuação inicial concedidos aos usuários no momento do registro",
|
||||||
|
"Is profile public": "Perfil é público",
|
||||||
|
"Is profile public - Tooltip": "Após ser fechado, apenas administradores globais ou usuários na mesma organização podem acessar a página de perfil do usuário",
|
||||||
|
"Modify rule": "Modificar regra",
|
||||||
|
"New Organization": "Nova Organização",
|
||||||
|
"Soft deletion": "Exclusão suave",
|
||||||
|
"Soft deletion - Tooltip": "Quando ativada, a exclusão de usuários não os removerá completamente do banco de dados. Em vez disso, eles serão marcados como excluídos",
|
||||||
|
"Tags": "Tags",
|
||||||
|
"Tags - Tooltip": "Coleção de tags disponíveis para os usuários escolherem",
|
||||||
|
"View rule": "Ver regra",
|
||||||
|
"Visible": "Visível",
|
||||||
|
"Website URL": "URL do website",
|
||||||
|
"Website URL - Tooltip": "A URL da página inicial da organização. Este campo não é utilizado no Casdoor"
|
||||||
|
},
|
||||||
|
"payment": {
|
||||||
|
"Confirm your invoice information": "Confirme as informações da sua fatura",
|
||||||
|
"Currency": "Moeda",
|
||||||
|
"Currency - Tooltip": "Como USD, CNY, etc.",
|
||||||
|
"Download Invoice": "Baixar Fatura",
|
||||||
|
"Edit Payment": "Editar Pagamento",
|
||||||
|
"Individual": "Individual",
|
||||||
|
"Invoice URL": "URL da Fatura",
|
||||||
|
"Invoice URL - Tooltip": "URL para baixar a fatura",
|
||||||
|
"Invoice actions": "Ações da Fatura",
|
||||||
|
"Invoice actions - Tooltip": "Operações incluem emissão de faturas e download de faturas",
|
||||||
|
"Invoice remark": "Observação da Fatura",
|
||||||
|
"Invoice remark - Tooltip": "A observação não deve exceder 50 caracteres",
|
||||||
|
"Invoice tax ID": "ID Fiscal da Fatura",
|
||||||
|
"Invoice tax ID - Tooltip": "Quando o tipo de fatura é para uma organização, é necessário informar o número de identificação fiscal da organização; quando o tipo de fatura é para uma pessoa física, não é necessário preencher esta informação",
|
||||||
|
"Invoice title": "Título da Fatura",
|
||||||
|
"Invoice title - Tooltip": "Quando o tipo de fatura é para uma organização, pode ser inserido o nome da organização como título da fatura; quando o tipo de fatura é para uma pessoa física, o sistema preencherá automaticamente o nome do pagador",
|
||||||
|
"Invoice type": "Tipo de Fatura",
|
||||||
|
"Invoice type - Tooltip": "O tipo de fatura pode ser para uma pessoa física ou uma organização",
|
||||||
|
"Issue Invoice": "Emitir Fatura",
|
||||||
|
"Message": "Mensagem",
|
||||||
|
"Message - Tooltip": "Mensagem de resultado do processamento do pagamento",
|
||||||
|
"New Payment": "Novo Pagamento",
|
||||||
|
"Person Email": "Email da Pessoa",
|
||||||
|
"Person Email - Tooltip": "Email do pagador",
|
||||||
|
"Person ID card": "Documento de Identificação",
|
||||||
|
"Person ID card - Tooltip": "Número do documento de identificação do pagador",
|
||||||
|
"Person name": "Nome da Pessoa",
|
||||||
|
"Person name - Tooltip": "Nome real do pagador",
|
||||||
|
"Person phone": "Telefone da Pessoa",
|
||||||
|
"Person phone - Tooltip": "Número de telefone do pagador",
|
||||||
|
"Please carefully check your invoice information. Once the invoice is issued, it cannot be withdrawn or modified.": "Por favor, verifique cuidadosamente as informações da sua fatura. Uma vez emitida, a fatura não pode ser cancelada ou modificada.",
|
||||||
|
"Please click the below button to return to the original website": "Por favor, clique no botão abaixo para retornar ao site original",
|
||||||
|
"Please pay the order first!": "Por favor, faça o pagamento do pedido primeiro!",
|
||||||
|
"Processing...": "Processando...",
|
||||||
|
"Product": "Produto",
|
||||||
|
"Product - Tooltip": "Nome do Produto",
|
||||||
|
"Result": "Resultado",
|
||||||
|
"Return to Website": "Retornar ao Website",
|
||||||
|
"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",
|
||||||
|
"You have successfully completed the payment": "Você concluiu o pagamento com sucesso",
|
||||||
|
"please wait for a few seconds...": "por favor, aguarde alguns segundos...",
|
||||||
|
"the current state is": "o estado atual é"
|
||||||
|
},
|
||||||
|
"permission": {
|
||||||
|
"Actions": "Ações",
|
||||||
|
"Actions - Tooltip": "Ações permitidas",
|
||||||
|
"Admin": "Administrador",
|
||||||
|
"Allow": "Permitir",
|
||||||
|
"Approve time": "Horário de Aprovação",
|
||||||
|
"Approve time - Tooltip": "O horário de aprovação desta permissão",
|
||||||
|
"Approved": "Aprovado",
|
||||||
|
"Approver": "Aprovador",
|
||||||
|
"Approver - Tooltip": "A pessoa que aprovou a permissão",
|
||||||
|
"Deny": "Negar",
|
||||||
|
"Edit Permission": "Editar Permissão",
|
||||||
|
"Effect": "Efeito",
|
||||||
|
"Effect - Tooltip": "Permitir ou rejeitar",
|
||||||
|
"New Permission": "Nova Permissão",
|
||||||
|
"Pending": "Pendente",
|
||||||
|
"Read": "Ler",
|
||||||
|
"Resource type": "Tipo de Recurso",
|
||||||
|
"Resource type - Tooltip": "Tipo de recurso",
|
||||||
|
"Resources - Tooltip": "Recursos autorizados",
|
||||||
|
"Submitter": "Requerente",
|
||||||
|
"Submitter - Tooltip": "A pessoa que está solicitando esta permissão",
|
||||||
|
"TreeNode": "Nó da Árvore",
|
||||||
|
"Write": "Escrever"
|
||||||
|
},
|
||||||
|
"product": {
|
||||||
|
"Alipay": "Alipay",
|
||||||
|
"Buy": "Comprar",
|
||||||
|
"Buy Product": "Comprar Produto",
|
||||||
|
"CNY": "CNY",
|
||||||
|
"Detail": "Detalhe",
|
||||||
|
"Detail - Tooltip": "Detalhes do produto",
|
||||||
|
"Edit Product": "Editar Produto",
|
||||||
|
"I have completed the payment": "Eu concluí o pagamento",
|
||||||
|
"Image": "Imagem",
|
||||||
|
"Image - Tooltip": "Imagem do produto",
|
||||||
|
"New Product": "Novo Produto",
|
||||||
|
"Pay": "Pagar",
|
||||||
|
"PayPal": "PayPal",
|
||||||
|
"Payment providers": "Provedores de Pagamento",
|
||||||
|
"Payment providers - Tooltip": "Fornecedores de serviços de pagamento",
|
||||||
|
"Placing order...": "Processando pedido...",
|
||||||
|
"Please provide your username in the remark": "Por favor, forneça seu nome de usuário na observação",
|
||||||
|
"Please scan the QR code to pay": "Por favor, escaneie o código QR para pagar",
|
||||||
|
"Price": "Preço",
|
||||||
|
"Price - Tooltip": "Preço do produto",
|
||||||
|
"Quantity": "Quantidade",
|
||||||
|
"Quantity - Tooltip": "Quantidade do produto",
|
||||||
|
"Return URL": "URL de Retorno",
|
||||||
|
"Return URL - Tooltip": "URL para retornar após a compra bem-sucedida",
|
||||||
|
"SKU": "SKU",
|
||||||
|
"Sold": "Vendido",
|
||||||
|
"Sold - Tooltip": "Quantidade vendida",
|
||||||
|
"Tag - Tooltip": "Tag do produto",
|
||||||
|
"Test buy page..": "Página de teste de compra...",
|
||||||
|
"There is no payment channel for this product.": "Não há canal de pagamento disponível para este produto.",
|
||||||
|
"This product is currently not in sale.": "Este produto não está disponível para venda no momento.",
|
||||||
|
"USD": "USD",
|
||||||
|
"WeChat Pay": "WeChat Pay"
|
||||||
|
},
|
||||||
|
"provider": {
|
||||||
|
"Access key": "Chave de acesso",
|
||||||
|
"Access key - Tooltip": "Chave de acesso",
|
||||||
|
"Agent ID": "ID do Agente",
|
||||||
|
"Agent ID - Tooltip": "ID do Agente",
|
||||||
|
"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 URL": "URL de autenticação",
|
||||||
|
"Auth URL - Tooltip": "URL de autenticação",
|
||||||
|
"Bucket": "Bucket",
|
||||||
|
"Bucket - Tooltip": "Nome do bucket",
|
||||||
|
"Can not parse metadata": "Não é possível analisar metadados",
|
||||||
|
"Can signin": "Pode fazer login",
|
||||||
|
"Can signup": "Pode se inscrever",
|
||||||
|
"Can unlink": "Pode desvincular",
|
||||||
|
"Category": "Categoria",
|
||||||
|
"Category - Tooltip": "Selecione uma categoria",
|
||||||
|
"Channel No.": "Número do canal",
|
||||||
|
"Channel No. - Tooltip": "Número do canal",
|
||||||
|
"Client ID": "ID do cliente",
|
||||||
|
"Client ID - Tooltip": "ID do cliente",
|
||||||
|
"Client ID 2": "ID do cliente 2",
|
||||||
|
"Client ID 2 - Tooltip": "O segundo ID do cliente",
|
||||||
|
"Client secret": "Segredo do cliente",
|
||||||
|
"Client secret - Tooltip": "Segredo do cliente",
|
||||||
|
"Client secret 2": "Segredo do cliente 2",
|
||||||
|
"Client secret 2 - Tooltip": "A segunda chave secreta do cliente",
|
||||||
|
"Copy": "Copiar",
|
||||||
|
"Disable SSL": "Desabilitar SSL",
|
||||||
|
"Disable SSL - Tooltip": "Se deve desabilitar o protocolo SSL ao comunicar com o servidor SMTP",
|
||||||
|
"Domain": "Domínio",
|
||||||
|
"Domain - Tooltip": "Domínio personalizado para armazenamento de objetos",
|
||||||
|
"Edit Provider": "Editar Provedor",
|
||||||
|
"Email content": "Conteúdo do e-mail",
|
||||||
|
"Email content - Tooltip": "Conteúdo do e-mail",
|
||||||
|
"Email sent successfully": "E-mail enviado com sucesso",
|
||||||
|
"Email title": "Título do e-mail",
|
||||||
|
"Email title - Tooltip": "Título do e-mail",
|
||||||
|
"Enable QR code": "Habilitar código QR",
|
||||||
|
"Enable QR code - Tooltip": "Se permite escanear código QR para fazer login",
|
||||||
|
"Endpoint": "Endpoint",
|
||||||
|
"Endpoint (Intranet)": "Endpoint (Intranet)",
|
||||||
|
"From address": "Endereço do remetente",
|
||||||
|
"From address - Tooltip": "Endereço de e-mail do remetente",
|
||||||
|
"From name": "Nome do remetente",
|
||||||
|
"From name - Tooltip": "Nome do remetente",
|
||||||
|
"Host": "Host",
|
||||||
|
"Host - Tooltip": "Nome do host",
|
||||||
|
"IdP": "IdP",
|
||||||
|
"IdP certificate": "Certificado IdP",
|
||||||
|
"Intelligent Validation": "Validação inteligente",
|
||||||
|
"Internal": "Interno",
|
||||||
|
"Issuer URL": "URL do Emissor",
|
||||||
|
"Issuer URL - Tooltip": "URL do Emissor",
|
||||||
|
"Link copied to clipboard successfully": "Link copiado para a área de transferência com sucesso",
|
||||||
|
"Metadata": "Metadados",
|
||||||
|
"Metadata - Tooltip": "Metadados SAML",
|
||||||
|
"Method - Tooltip": "Método de login, código QR ou login silencioso",
|
||||||
|
"New Provider": "Novo Provedor",
|
||||||
|
"Normal": "Normal",
|
||||||
|
"Parse": "Analisar",
|
||||||
|
"Parse metadata successfully": "Metadados analisados com sucesso",
|
||||||
|
"Path prefix": "Prefixo do caminho",
|
||||||
|
"Path prefix - Tooltip": "Prefixo do caminho do bucket para armazenamento de objetos",
|
||||||
|
"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",
|
||||||
|
"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",
|
||||||
|
"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",
|
||||||
|
"Region endpoint for Intranet": "Endpoint da região para Intranet",
|
||||||
|
"Required": "Obrigatório",
|
||||||
|
"SAML 2.0 Endpoint (HTTP)": "Ponto de extremidade SAML 2.0 (HTTP)",
|
||||||
|
"SMS Test": "Teste de SMS",
|
||||||
|
"SMS Test - Tooltip": "Número de telefone para enviar SMS de teste",
|
||||||
|
"SMS account": "Conta SMS",
|
||||||
|
"SMS account - Tooltip": "Conta SMS",
|
||||||
|
"SMS sent successfully": "SMS enviado com sucesso",
|
||||||
|
"SP ACS URL": "URL SP ACS",
|
||||||
|
"SP ACS URL - Tooltip": "URL SP ACS",
|
||||||
|
"SP Entity ID": "ID da Entidade SP",
|
||||||
|
"Scene": "Cenário",
|
||||||
|
"Scene - Tooltip": "Cenário",
|
||||||
|
"Scope": "Escopo",
|
||||||
|
"Scope - Tooltip": "Escopo",
|
||||||
|
"Secret access key": "Chave de acesso secreta",
|
||||||
|
"Secret access key - Tooltip": "Chave de acesso secreta",
|
||||||
|
"Secret key": "Chave secreta",
|
||||||
|
"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",
|
||||||
|
"Sign Name": "Nome do Sinal",
|
||||||
|
"Sign Name - Tooltip": "Nome da assinatura a ser usada",
|
||||||
|
"Sign request": "Solicitação de assinatura",
|
||||||
|
"Sign request - Tooltip": "Se a solicitação requer uma assinatura",
|
||||||
|
"Signin HTML": "HTML de login",
|
||||||
|
"Signin HTML - Edit": "Editar HTML de login",
|
||||||
|
"Signin HTML - Tooltip": "HTML personalizado para substituir o estilo padrão da página de login",
|
||||||
|
"Signup HTML": "HTML de inscrição",
|
||||||
|
"Signup HTML - Edit": "Editar HTML de inscrição",
|
||||||
|
"Signup HTML - Tooltip": "HTML personalizado para substituir o estilo padrão da página de inscrição",
|
||||||
|
"Silent": "Silencioso",
|
||||||
|
"Site key": "Chave do site",
|
||||||
|
"Site key - Tooltip": "Chave do site",
|
||||||
|
"Sliding Validation": "Validação deslizante",
|
||||||
|
"Sub type": "Subtipo",
|
||||||
|
"Sub type - Tooltip": "Subtipo",
|
||||||
|
"Template code": "Código do modelo",
|
||||||
|
"Template code - Tooltip": "Código do modelo",
|
||||||
|
"Test Email": "Testar E-mail",
|
||||||
|
"Test Email - Tooltip": "Endereço de e-mail para receber e-mails de teste",
|
||||||
|
"Test SMTP Connection": "Testar Conexão SMTP",
|
||||||
|
"Third-party": "Terceiros",
|
||||||
|
"Token URL": "URL do Token",
|
||||||
|
"Token URL - Tooltip": "URL do Token",
|
||||||
|
"Type": "Tipo",
|
||||||
|
"Type - Tooltip": "Selecione um tipo",
|
||||||
|
"UserInfo URL": "URL do UserInfo",
|
||||||
|
"UserInfo URL - Tooltip": "URL do UserInfo",
|
||||||
|
"admin (Shared)": "admin (Compartilhado)"
|
||||||
|
},
|
||||||
|
"record": {
|
||||||
|
"Is triggered": "Foi acionado"
|
||||||
|
},
|
||||||
|
"resource": {
|
||||||
|
"Copy Link": "Copiar Link",
|
||||||
|
"File name": "Nome do arquivo",
|
||||||
|
"File size": "Tamanho do arquivo",
|
||||||
|
"Format": "Formato",
|
||||||
|
"Parent": "Pai",
|
||||||
|
"Upload a file...": "Enviar um arquivo..."
|
||||||
|
},
|
||||||
|
"role": {
|
||||||
|
"Edit Role": "Editar Função",
|
||||||
|
"New Role": "Nova Função",
|
||||||
|
"Sub domains": "Subdomínios",
|
||||||
|
"Sub domains - Tooltip": "Domínios incluídos na função atual",
|
||||||
|
"Sub roles": "Subfunções",
|
||||||
|
"Sub roles - Tooltip": "Funções incluídas na função atual",
|
||||||
|
"Sub users": "Subusuários",
|
||||||
|
"Sub users - Tooltip": "Usuários incluídos na função atual"
|
||||||
|
},
|
||||||
|
"signup": {
|
||||||
|
"Accept": "Aceitar",
|
||||||
|
"Agreement": "Acordo",
|
||||||
|
"Confirm": "Confirmar",
|
||||||
|
"Decline": "Recusar",
|
||||||
|
"Have account?": "Já possui uma conta?",
|
||||||
|
"Please accept the agreement!": "Por favor, aceite o acordo!",
|
||||||
|
"Please click the below button to sign in": "Por favor, clique no botão abaixo para fazer login",
|
||||||
|
"Please confirm your password!": "Por favor, confirme sua senha!",
|
||||||
|
"Please input the correct ID card number!": "Por favor, insira o número correto do seu cartão de identificação!",
|
||||||
|
"Please input your Email!": "Por favor, insira seu Email!",
|
||||||
|
"Please input your ID card number!": "Por favor, insira o número do seu cartão de identificação!",
|
||||||
|
"Please input your address!": "Por favor, insira seu endereço!",
|
||||||
|
"Please input your affiliation!": "Por favor, insira sua afiliação!",
|
||||||
|
"Please input your display name!": "Por favor, insira seu nome de exibição!",
|
||||||
|
"Please input your first name!": "Por favor, insira seu primeiro nome!",
|
||||||
|
"Please input your last name!": "Por favor, insira seu sobrenome!",
|
||||||
|
"Please input your phone number!": "Por favor, insira seu número de telefone!",
|
||||||
|
"Please input your real name!": "Por favor, insira seu nome real!",
|
||||||
|
"Please select your country code!": "Por favor, selecione o código do seu país!",
|
||||||
|
"Please select your country/region!": "Por favor, selecione seu país/região!",
|
||||||
|
"Terms of Use": "Termos de Uso",
|
||||||
|
"Terms of Use - Tooltip": "Termos de uso que os usuários precisam ler e concordar durante o registro",
|
||||||
|
"The input is not invoice Tax ID!": "A entrada não é um ID fiscal de fatura válido!",
|
||||||
|
"The input is not invoice title!": "A entrada não é um título de fatura válido!",
|
||||||
|
"The input is not valid Email!": "A entrada não é um Email válido!",
|
||||||
|
"The input is not valid Phone!": "A entrada não é um número de telefone válido!",
|
||||||
|
"Username": "Nome de usuário",
|
||||||
|
"Username - Tooltip": "Nome de usuário - Tooltip",
|
||||||
|
"Your account has been created!": "Sua conta foi criada!",
|
||||||
|
"Your confirmed password is inconsistent with the password!": "Sua senha confirmada não é consistente com a senha!",
|
||||||
|
"sign in now": "Faça login agora"
|
||||||
|
},
|
||||||
|
"syncer": {
|
||||||
|
"Affiliation table": "Tabela de Afiliação",
|
||||||
|
"Affiliation table - Tooltip": "Nome da tabela no banco de dados da unidade de trabalho",
|
||||||
|
"Avatar base URL": "URL base do Avatar",
|
||||||
|
"Avatar base URL - Tooltip": "Prefixo URL para as imagens de avatar",
|
||||||
|
"Casdoor column": "Coluna Casdoor",
|
||||||
|
"Column name": "Nome da coluna",
|
||||||
|
"Column type": "Tipo de coluna",
|
||||||
|
"Database": "Banco de dados",
|
||||||
|
"Database - Tooltip": "Nome original do banco de dados",
|
||||||
|
"Database type": "Tipo de banco de dados",
|
||||||
|
"Database type - Tooltip": "Tipo de banco de dados, suportando todos os bancos de dados suportados pelo XORM, como MySQL, PostgreSQL, SQL Server, Oracle, SQLite, etc.",
|
||||||
|
"Edit Syncer": "Editar Syncer",
|
||||||
|
"Error text": "Texto de erro",
|
||||||
|
"Error text - Tooltip": "Texto de erro",
|
||||||
|
"Is hashed": "Está criptografado",
|
||||||
|
"New Syncer": "Novo Syncer",
|
||||||
|
"Sync interval": "Intervalo de sincronização",
|
||||||
|
"Sync interval - Tooltip": "Unidade em segundos",
|
||||||
|
"Table": "Tabela",
|
||||||
|
"Table - Tooltip": "Nome da tabela no banco de dados",
|
||||||
|
"Table columns": "Colunas da tabela",
|
||||||
|
"Table columns - Tooltip": "Colunas na tabela envolvidas na sincronização de dados. Colunas que não estão envolvidas na sincronização não precisam ser adicionadas",
|
||||||
|
"Table primary key": "Chave primária da tabela",
|
||||||
|
"Table primary key - Tooltip": "Chave primária da tabela, como id"
|
||||||
|
},
|
||||||
|
"system": {
|
||||||
|
"API Latency": "Latência da API",
|
||||||
|
"API Throughput": "Throughput da API",
|
||||||
|
"About Casdoor": "Sobre o Casdoor",
|
||||||
|
"An Identity and Access Management (IAM) / Single-Sign-On (SSO) platform with web UI supporting OAuth 2.0, OIDC, SAML and CAS": "Uma plataforma de Gerenciamento de Identidade e Acesso (IAM) / Single-Sign-On (SSO) com interface web que suporta OAuth 2.0, OIDC, SAML e CAS",
|
||||||
|
"CPU Usage": "Uso da CPU",
|
||||||
|
"Community": "Comunidade",
|
||||||
|
"Count": "Contagem",
|
||||||
|
"Failed to get CPU usage": "Falha ao obter o uso da CPU",
|
||||||
|
"Failed to get memory usage": "Falha ao obter o uso da memória",
|
||||||
|
"Latency": "Latência",
|
||||||
|
"Memory Usage": "Uso da Memória",
|
||||||
|
"Official website": "Website oficial",
|
||||||
|
"Throughput": "Throughput",
|
||||||
|
"Total Throughput": "Total de Throughput",
|
||||||
|
"Unknown version": "Versão desconhecida",
|
||||||
|
"Version": "Versão"
|
||||||
|
},
|
||||||
|
"theme": {
|
||||||
|
"Blossom": "Blossom",
|
||||||
|
"Border radius": "Raio da borda",
|
||||||
|
"Compact": "Compacto",
|
||||||
|
"Customize theme": "Personalizar tema",
|
||||||
|
"Dark": "Escuro",
|
||||||
|
"Default": "Padrão",
|
||||||
|
"Document": "Documento",
|
||||||
|
"Is compact": "É compacto",
|
||||||
|
"Primary color": "Cor primária",
|
||||||
|
"Theme": "Tema",
|
||||||
|
"Theme - Tooltip": "Tema de estilo do aplicativo"
|
||||||
|
},
|
||||||
|
"token": {
|
||||||
|
"Access token": "Token de acesso",
|
||||||
|
"Authorization code": "Código de autorização",
|
||||||
|
"Edit Token": "Editar Token",
|
||||||
|
"Expires in": "Expira em",
|
||||||
|
"New Token": "Novo Token",
|
||||||
|
"Token type": "Tipo de Token"
|
||||||
|
},
|
||||||
|
"user":
|
||||||
|
{
|
||||||
|
"3rd-party logins": "Logins de terceiros",
|
||||||
|
"3rd-party logins - Tooltip": "Logins sociais vinculados pelo usuário",
|
||||||
|
"Address": "Endereço",
|
||||||
|
"Address - Tooltip": "Endereço residencial",
|
||||||
|
"Affiliation": "Afiliação",
|
||||||
|
"Affiliation - Tooltip": "Empregador, como nome da empresa ou organização",
|
||||||
|
"Bio": "Biografia",
|
||||||
|
"Bio - Tooltip": "Autoapresentação do usuário",
|
||||||
|
"Birthday": "Aniversário",
|
||||||
|
"Birthday - Tooltip": "Aniversário - Tooltip",
|
||||||
|
"Captcha Verify Failed": "Falha na verificação de captcha",
|
||||||
|
"Captcha Verify Success": "Verificação de captcha bem-sucedida",
|
||||||
|
"Country code": "Código do país",
|
||||||
|
"Country/Region": "País/Região",
|
||||||
|
"Country/Region - Tooltip": "País ou região",
|
||||||
|
"Edit User": "Editar Usuário",
|
||||||
|
"Education": "Educação",
|
||||||
|
"Education - Tooltip": "Educação - Tooltip",
|
||||||
|
"Email cannot be empty": "O e-mail não pode ficar em branco",
|
||||||
|
"Email/phone reset successfully": "Redefinição de e-mail/telefone com sucesso",
|
||||||
|
"Empty input!": "Entrada vazia!",
|
||||||
|
"Gender": "Gênero",
|
||||||
|
"Gender - Tooltip": "Gênero - Tooltip",
|
||||||
|
"Homepage": "Página inicial",
|
||||||
|
"Homepage - Tooltip": "URL da página inicial do usuário",
|
||||||
|
"ID card": "Cartão de identidade",
|
||||||
|
"ID card - Tooltip": "Cartão de identidade - Tooltip",
|
||||||
|
"ID card type": "Tipo de cartão de identidade",
|
||||||
|
"ID card type - Tooltip": "Tipo de cartão de identidade - Tooltip",
|
||||||
|
"Input your email": "Digite seu e-mail",
|
||||||
|
"Input your phone number": "Digite seu número de telefone",
|
||||||
|
"Is admin": "É administrador",
|
||||||
|
"Is admin - Tooltip": "É um administrador da organização à qual o usuário pertence",
|
||||||
|
"Is deleted": "Foi excluído",
|
||||||
|
"Is deleted - Tooltip": "Usuários excluídos somente mantêm registros no banco de dados e não podem realizar nenhuma operação",
|
||||||
|
"Is forbidden": "Está proibido",
|
||||||
|
"Is forbidden - Tooltip": "Usuários proibidos não podem fazer login novamente",
|
||||||
|
"Is global admin": "É administrador global",
|
||||||
|
"Is global admin - Tooltip": "É um administrador do Casdoor",
|
||||||
|
"Is online": "Está online",
|
||||||
|
"Karma": "Karma",
|
||||||
|
"Karma - Tooltip": "Karma - Tooltip",
|
||||||
|
"Keys": "Chaves",
|
||||||
|
"Language": "Idioma",
|
||||||
|
"Language - Tooltip": "Idioma - Tooltip",
|
||||||
|
"Link": "Link",
|
||||||
|
"Location": "Localização",
|
||||||
|
"Location - Tooltip": "Cidade de residência",
|
||||||
|
"Managed accounts": "Contas gerenciadas",
|
||||||
|
"Modify password...": "Modificar senha...",
|
||||||
|
"Multi-factor authentication": "Autenticação de vários fatores",
|
||||||
|
"New Email": "Novo E-mail",
|
||||||
|
"New Password": "Nova Senha",
|
||||||
|
"New User": "Novo Usuário",
|
||||||
|
"New phone": "Novo telefone",
|
||||||
|
"Old Password": "Senha Antiga",
|
||||||
|
"Password set successfully": "Senha definida com sucesso",
|
||||||
|
"Phone cannot be empty": "O telefone não pode ficar vazio",
|
||||||
|
"Please select avatar from resources": "Selecione um avatar dos recursos",
|
||||||
|
"Properties": "Propriedades",
|
||||||
|
"Properties - Tooltip": "Propriedades do usuário",
|
||||||
|
"Ranking": "Classificação",
|
||||||
|
"Ranking - Tooltip": "Classificação - Tooltip",
|
||||||
|
"Re-enter New": "Digite Novamente",
|
||||||
|
"Reset Email...": "Redefinir E-mail...",
|
||||||
|
"Reset Phone...": "Redefinir Telefone...",
|
||||||
|
"Score": "Pontuação",
|
||||||
|
"Score - Tooltip": "Pontuação - Tooltip",
|
||||||
|
"Select a photo...": "Selecionar uma foto...",
|
||||||
|
"Set Password": "Definir Senha",
|
||||||
|
"Set new profile picture": "Definir nova foto de perfil",
|
||||||
|
"Set password...": "Definir senha...",
|
||||||
|
"Tag": "Tag",
|
||||||
|
"Tag - Tooltip": "Tag do usuário",
|
||||||
|
"Title": "Título",
|
||||||
|
"Title - Tooltip": "Cargo na afiliação",
|
||||||
|
"Two passwords you typed do not match.": "As duas senhas digitadas não coincidem.",
|
||||||
|
"Unlink": "Desvincular",
|
||||||
|
"Upload (.xlsx)": "Enviar (.xlsx)",
|
||||||
|
"Upload a photo": "Enviar uma foto",
|
||||||
|
"Values": "Valores",
|
||||||
|
"Verification code sent": "Código de verificação enviado",
|
||||||
|
"WebAuthn credentials": "Credenciais WebAuthn",
|
||||||
|
"input password": "Digite a senha"
|
||||||
|
},
|
||||||
|
"webhook": {
|
||||||
|
"Content type": "Tipo de conteúdo",
|
||||||
|
"Content type - Tooltip": "Tipo de conteúdo",
|
||||||
|
"Edit Webhook": "Editar Webhook",
|
||||||
|
"Events": "Eventos",
|
||||||
|
"Events - Tooltip": "Eventos",
|
||||||
|
"Headers": "Cabeçalhos",
|
||||||
|
"Headers - Tooltip": "Cabeçalhos HTTP (pares chave-valor)",
|
||||||
|
"Is user extended": "É usuário estendido",
|
||||||
|
"Is user extended - Tooltip": "Se incluir os campos estendidos do usuário no JSON",
|
||||||
|
"Method - Tooltip": "Método HTTP",
|
||||||
|
"New Webhook": "Novo Webhook",
|
||||||
|
"Value": "Valor"
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user