mirror of
https://github.com/casdoor/casdoor.git
synced 2025-07-30 08:10:29 +08:00
Compare commits
13 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
d92b072ed0 | ||
![]() |
1161310f81 | ||
![]() |
48ba5f91ed | ||
![]() |
53df2c2704 | ||
![]() |
78066da208 | ||
![]() |
60096468fe | ||
![]() |
39d6bc10f7 | ||
![]() |
177f2f2f11 | ||
![]() |
79b393afee | ||
![]() |
5bb12a30d4 | ||
![]() |
fdb68bf9c8 | ||
![]() |
37748850c8 | ||
![]() |
8968396ae5 |
13
.github/workflows/build.yml
vendored
13
.github/workflows/build.yml
vendored
@@ -217,13 +217,9 @@ jobs:
|
||||
- name: Update Helm Chart
|
||||
if: steps.should_push.outputs.push=='true'
|
||||
run: |
|
||||
# Set the appVersion of the chart to the current tag
|
||||
# Set the appVersion and version of the chart to the current tag
|
||||
sed -i "s/appVersion: .*/appVersion: ${{steps.get-current-tag.outputs.tag }}/g" ./charts/casdoor/Chart.yaml
|
||||
|
||||
# increase the patch version of the chart
|
||||
currentChartVersion=$(cat ./charts/casdoor/Chart.yaml | grep ^version | awk '{print $2}')
|
||||
newChartVersion=$(echo $currentChartVersion | awk -F. -v OFS=. '{$NF++;print}')
|
||||
sed -i "s/version: .*/version: $newChartVersion/g" ./charts/casdoor/Chart.yaml
|
||||
sed -i "s/version: .*/version: ${{steps.get-current-tag.outputs.tag }}/g" ./charts/casdoor/Chart.yaml
|
||||
|
||||
REGISTRY=oci://registry-1.docker.io/casbin
|
||||
cd charts/casdoor
|
||||
@@ -235,7 +231,8 @@ jobs:
|
||||
|
||||
# Commit and push the changes back to the repository
|
||||
git config --global user.name "casbin-bot"
|
||||
git config --global user.email "casbin-bot@github.com"
|
||||
git config --global user.email "bot@casbin.org"
|
||||
git add Chart.yaml index.yaml
|
||||
git commit -m "chore(helm): bump helm charts appVersion to ${{steps.get-current-tag.outputs.tag }}"
|
||||
git push origin HEAD:master
|
||||
git tag ${{steps.get-current-tag.outputs.tag }}
|
||||
git push origin HEAD:master --follow-tags
|
||||
|
@@ -69,6 +69,7 @@ https://casdoor.org
|
||||
|
||||
- By source code: https://casdoor.org/docs/basic/server-installation
|
||||
- By Docker: https://casdoor.org/docs/basic/try-with-docker
|
||||
- By Kubernetes Helm: https://casdoor.org/docs/basic/try-with-helm
|
||||
|
||||
## How to connect to Casdoor?
|
||||
|
||||
|
@@ -973,23 +973,27 @@ func (c *ApiController) GetWebhookEventType() {
|
||||
// @router /api/get-captcha-status [get]
|
||||
func (c *ApiController) GetCaptchaStatus() {
|
||||
organization := c.Input().Get("organization")
|
||||
userId := c.Input().Get("user_id")
|
||||
userId := c.Input().Get("userId")
|
||||
user, err := object.GetUserByFields(organization, userId)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
failedSigninLimit, _, err := object.GetFailedSigninConfigByUser(user)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
captchaEnabled := false
|
||||
if user != nil {
|
||||
var failedSigninLimit int
|
||||
failedSigninLimit, _, err = object.GetFailedSigninConfigByUser(user)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
if user.SigninWrongTimes >= failedSigninLimit {
|
||||
captchaEnabled = true
|
||||
}
|
||||
}
|
||||
|
||||
var captchaEnabled bool
|
||||
if user != nil && user.SigninWrongTimes >= failedSigninLimit {
|
||||
captchaEnabled = true
|
||||
}
|
||||
c.ResponseOk(captchaEnabled)
|
||||
}
|
||||
|
||||
|
@@ -264,10 +264,13 @@ func (c *ApiController) BatchEnforce() {
|
||||
}
|
||||
|
||||
func (c *ApiController) GetAllObjects() {
|
||||
userId := c.GetSessionUsername()
|
||||
userId := c.Input().Get("userId")
|
||||
if userId == "" {
|
||||
c.ResponseError(c.T("general:Please login first"))
|
||||
return
|
||||
userId = c.GetSessionUsername()
|
||||
if userId == "" {
|
||||
c.ResponseError(c.T("general:Please login first"))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
objects, err := object.GetAllObjects(userId)
|
||||
@@ -280,10 +283,13 @@ func (c *ApiController) GetAllObjects() {
|
||||
}
|
||||
|
||||
func (c *ApiController) GetAllActions() {
|
||||
userId := c.GetSessionUsername()
|
||||
userId := c.Input().Get("userId")
|
||||
if userId == "" {
|
||||
c.ResponseError(c.T("general:Please login first"))
|
||||
return
|
||||
userId = c.GetSessionUsername()
|
||||
if userId == "" {
|
||||
c.ResponseError(c.T("general:Please login first"))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
actions, err := object.GetAllActions(userId)
|
||||
@@ -296,10 +302,13 @@ func (c *ApiController) GetAllActions() {
|
||||
}
|
||||
|
||||
func (c *ApiController) GetAllRoles() {
|
||||
userId := c.GetSessionUsername()
|
||||
userId := c.Input().Get("userId")
|
||||
if userId == "" {
|
||||
c.ResponseError(c.T("general:Please login first"))
|
||||
return
|
||||
userId = c.GetSessionUsername()
|
||||
if userId == "" {
|
||||
c.ResponseError(c.T("general:Please login first"))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
roles, err := object.GetAllRoles(userId)
|
||||
|
2
go.mod
2
go.mod
@@ -12,7 +12,7 @@ require (
|
||||
github.com/casdoor/go-sms-sender v0.19.0
|
||||
github.com/casdoor/gomail/v2 v2.0.1
|
||||
github.com/casdoor/notify v0.45.0
|
||||
github.com/casdoor/oss v1.4.1
|
||||
github.com/casdoor/oss v1.5.0
|
||||
github.com/casdoor/xorm-adapter/v3 v3.1.0
|
||||
github.com/casvisor/casvisor-go-sdk v1.0.3
|
||||
github.com/dchest/captcha v0.0.0-20200903113550-03f5f0333e1f
|
||||
|
2
go.sum
2
go.sum
@@ -1091,6 +1091,8 @@ github.com/casdoor/notify v0.45.0 h1:OlaFvcQFjGOgA4mRx07M8AH1gvb5xNo21mcqrVGlLgk
|
||||
github.com/casdoor/notify v0.45.0/go.mod h1:wNHQu0tiDROMBIvz0j3Om3Lhd5yZ+AIfnFb8MYb8OLQ=
|
||||
github.com/casdoor/oss v1.4.1 h1:/P2JCyGzB2TtpJ3LocKocI1VAme2YdvVau2wpMQGt7I=
|
||||
github.com/casdoor/oss v1.4.1/go.mod h1:rJAWA0hLhtu94t6IRpotLUkXO1NWMASirywQYaGizJE=
|
||||
github.com/casdoor/oss v1.5.0 h1:mi1htaXR5fynskDry1S3wk+Dd2nRY1z1pVcnGsqMqP4=
|
||||
github.com/casdoor/oss v1.5.0/go.mod h1:rJAWA0hLhtu94t6IRpotLUkXO1NWMASirywQYaGizJE=
|
||||
github.com/casdoor/xorm-adapter/v3 v3.1.0 h1:NodWayRtSLVSeCvL9H3Hc61k0G17KhV9IymTCNfh3kk=
|
||||
github.com/casdoor/xorm-adapter/v3 v3.1.0/go.mod h1:4WTcUw+bTgBylGHeGHzTtBvuTXRS23dtwzFLl9tsgFM=
|
||||
github.com/casvisor/casvisor-go-sdk v1.0.3 h1:TKJQWKnhtznEBhzLPEdNsp7nJK2GgdD8JsB0lFPMW7U=
|
||||
|
149
ldap/server.go
149
ldap/server.go
@@ -18,7 +18,6 @@ import (
|
||||
"fmt"
|
||||
"hash/fnv"
|
||||
"log"
|
||||
"strings"
|
||||
|
||||
"github.com/casdoor/casdoor/conf"
|
||||
"github.com/casdoor/casdoor/object"
|
||||
@@ -50,17 +49,7 @@ func handleBind(w ldap.ResponseWriter, m *ldap.Message) {
|
||||
res := ldap.NewBindResponse(ldap.LDAPResultSuccess)
|
||||
|
||||
if r.AuthenticationChoice() == "simple" {
|
||||
bindDN := string(r.Name())
|
||||
bindPassword := string(r.AuthenticationSimple())
|
||||
|
||||
if bindDN == "" && bindPassword == "" {
|
||||
res.SetResultCode(ldap.LDAPResultInappropriateAuthentication)
|
||||
res.SetDiagnosticMessage("Anonymous bind disallowed")
|
||||
w.Write(res)
|
||||
return
|
||||
}
|
||||
|
||||
bindUsername, bindOrg, err := getNameAndOrgFromDN(bindDN)
|
||||
bindUsername, bindOrg, err := getNameAndOrgFromDN(string(r.Name()))
|
||||
if err != nil {
|
||||
log.Printf("getNameAndOrgFromDN() error: %s", err.Error())
|
||||
res.SetResultCode(ldap.LDAPResultInvalidDNSyntax)
|
||||
@@ -69,6 +58,7 @@ func handleBind(w ldap.ResponseWriter, m *ldap.Message) {
|
||||
return
|
||||
}
|
||||
|
||||
bindPassword := string(r.AuthenticationSimple())
|
||||
bindUser, err := object.CheckUserPassword(bindOrg, bindUsername, bindPassword, "en")
|
||||
if err != nil {
|
||||
log.Printf("Bind failed User=%s, Pass=%#v, ErrMsg=%s", string(r.Name()), r.Authentication(), err)
|
||||
@@ -103,46 +93,7 @@ func handleSearch(w ldap.ResponseWriter, m *ldap.Message) {
|
||||
}
|
||||
|
||||
r := m.GetSearchRequest()
|
||||
|
||||
// case insensitive match
|
||||
if strings.EqualFold(r.FilterString(), "(objectClass=*)") {
|
||||
if len(r.Attributes()) == 0 {
|
||||
w.Write(res)
|
||||
return
|
||||
}
|
||||
first_attr := string(r.Attributes()[0])
|
||||
|
||||
if string(r.BaseObject()) == "" {
|
||||
// handle special search requests
|
||||
|
||||
if first_attr == "namingContexts" {
|
||||
orgs, code := GetFilteredOrganizations(m)
|
||||
if code != ldap.LDAPResultSuccess {
|
||||
res.SetResultCode(code)
|
||||
w.Write(res)
|
||||
return
|
||||
}
|
||||
e := ldap.NewSearchResultEntry(string(r.BaseObject()))
|
||||
dnlist := make([]message.AttributeValue, len(orgs))
|
||||
for i, org := range orgs {
|
||||
dnlist[i] = message.AttributeValue(fmt.Sprintf("ou=%s", org.Name))
|
||||
}
|
||||
e.AddAttribute("namingContexts", dnlist...)
|
||||
w.Write(e)
|
||||
} else if first_attr == "subschemaSubentry" {
|
||||
e := ldap.NewSearchResultEntry(string(r.BaseObject()))
|
||||
e.AddAttribute("subschemaSubentry", message.AttributeValue("cn=Subschema"))
|
||||
w.Write(e)
|
||||
}
|
||||
} else if strings.EqualFold(first_attr, "objectclasses") && string(r.BaseObject()) == "cn=Subschema" {
|
||||
e := ldap.NewSearchResultEntry(string(r.BaseObject()))
|
||||
e.AddAttribute("objectClasses", []message.AttributeValue{
|
||||
"( 1.3.6.1.1.1.2.0 NAME 'posixAccount' DESC 'Abstraction of an account with POSIX attributes' SUP top AUXILIARY MUST ( cn $ uid $ uidNumber $ gidNumber $ homeDirectory ) MAY ( userPassword $ loginShell $ gecos $ description ) )",
|
||||
"( 1.3.6.1.1.1.2.2 NAME 'posixGroup' DESC 'Abstraction of a group of accounts' SUP top STRUCTURAL MUST ( cn $ gidNumber ) MAY ( userPassword $ memberUid $ description ) )",
|
||||
}...)
|
||||
w.Write(e)
|
||||
}
|
||||
|
||||
if r.FilterString() == "(objectClass=*)" {
|
||||
w.Write(res)
|
||||
return
|
||||
}
|
||||
@@ -155,72 +106,38 @@ func handleSearch(w ldap.ResponseWriter, m *ldap.Message) {
|
||||
default:
|
||||
}
|
||||
|
||||
objectClass := searchFilterForEquality(r.Filter(), "objectClass", "posixAccount", "posixGroup")
|
||||
switch objectClass {
|
||||
case "posixAccount":
|
||||
users, code := GetFilteredUsers(m)
|
||||
if code != ldap.LDAPResultSuccess {
|
||||
res.SetResultCode(code)
|
||||
w.Write(res)
|
||||
return
|
||||
}
|
||||
|
||||
// log.Printf("Handling posixAccount filter=%s", r.FilterString())
|
||||
for _, user := range users {
|
||||
dn := fmt.Sprintf("uid=%s,cn=users,%s", user.Name, string(r.BaseObject()))
|
||||
e := ldap.NewSearchResultEntry(dn)
|
||||
attrs := r.Attributes()
|
||||
for _, attr := range attrs {
|
||||
if string(attr) == "*" {
|
||||
attrs = AdditionalLdapUserAttributes
|
||||
break
|
||||
}
|
||||
}
|
||||
for _, attr := range attrs {
|
||||
if strings.HasSuffix(string(attr), ";binary") {
|
||||
// unsupported: userCertificate;binary
|
||||
continue
|
||||
}
|
||||
field, ok := ldapUserAttributesMapping.CaseInsensitiveGet(string(attr))
|
||||
if ok {
|
||||
e.AddAttribute(message.AttributeDescription(attr), field.GetAttributeValues(user)...)
|
||||
}
|
||||
}
|
||||
w.Write(e)
|
||||
}
|
||||
|
||||
case "posixGroup":
|
||||
// log.Printf("Handling posixGroup filter=%s", r.FilterString())
|
||||
groups, code := GetFilteredGroups(m)
|
||||
if code != ldap.LDAPResultSuccess {
|
||||
res.SetResultCode(code)
|
||||
w.Write(res)
|
||||
return
|
||||
}
|
||||
|
||||
for _, group := range groups {
|
||||
dn := fmt.Sprintf("cn=%s,cn=groups,%s", group.Name, string(r.BaseObject()))
|
||||
e := ldap.NewSearchResultEntry(dn)
|
||||
attrs := r.Attributes()
|
||||
for _, attr := range attrs {
|
||||
if string(attr) == "*" {
|
||||
attrs = AdditionalLdapGroupAttributes
|
||||
break
|
||||
}
|
||||
}
|
||||
for _, attr := range attrs {
|
||||
field, ok := ldapGroupAttributesMapping.CaseInsensitiveGet(string(attr))
|
||||
if ok {
|
||||
e.AddAttribute(message.AttributeDescription(attr), field.GetAttributeValues(group)...)
|
||||
}
|
||||
}
|
||||
w.Write(e)
|
||||
}
|
||||
|
||||
case "":
|
||||
log.Printf("Unmatched search request. filter=%s", r.FilterString())
|
||||
users, code := GetFilteredUsers(m)
|
||||
if code != ldap.LDAPResultSuccess {
|
||||
res.SetResultCode(code)
|
||||
w.Write(res)
|
||||
return
|
||||
}
|
||||
|
||||
for _, user := range users {
|
||||
dn := fmt.Sprintf("uid=%s,cn=%s,%s", user.Id, user.Name, string(r.BaseObject()))
|
||||
e := ldap.NewSearchResultEntry(dn)
|
||||
uidNumberStr := fmt.Sprintf("%v", hash(user.Name))
|
||||
e.AddAttribute("uidNumber", message.AttributeValue(uidNumberStr))
|
||||
e.AddAttribute("gidNumber", message.AttributeValue(uidNumberStr))
|
||||
e.AddAttribute("homeDirectory", message.AttributeValue("/home/"+user.Name))
|
||||
e.AddAttribute("cn", message.AttributeValue(user.Name))
|
||||
e.AddAttribute("uid", message.AttributeValue(user.Id))
|
||||
attrs := r.Attributes()
|
||||
for _, attr := range attrs {
|
||||
if string(attr) == "*" {
|
||||
attrs = AdditionalLdapAttributes
|
||||
break
|
||||
}
|
||||
}
|
||||
for _, attr := range attrs {
|
||||
e.AddAttribute(message.AttributeDescription(attr), getAttribute(string(attr), user))
|
||||
if string(attr) == "cn" {
|
||||
e.AddAttribute(message.AttributeDescription(attr), getAttribute("title", user))
|
||||
}
|
||||
}
|
||||
|
||||
w.Write(e)
|
||||
}
|
||||
w.Write(res)
|
||||
}
|
||||
|
||||
|
342
ldap/util.go
342
ldap/util.go
@@ -18,7 +18,6 @@ import (
|
||||
"fmt"
|
||||
"log"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/casdoor/casdoor/object"
|
||||
"github.com/casdoor/casdoor/util"
|
||||
@@ -29,259 +28,65 @@ import (
|
||||
"github.com/xorm-io/builder"
|
||||
)
|
||||
|
||||
type V = message.AttributeValue
|
||||
type AttributeMapper func(user *object.User) message.AttributeValue
|
||||
|
||||
type UserAttributeMapper func(user *object.User) []V
|
||||
|
||||
type UserFieldRelation struct {
|
||||
type FieldRelation struct {
|
||||
userField string
|
||||
ldapField string
|
||||
notSearchable bool
|
||||
hideOnStarOp bool
|
||||
fieldMapper UserAttributeMapper
|
||||
constantValue []V
|
||||
fieldMapper AttributeMapper
|
||||
}
|
||||
|
||||
func (rel UserFieldRelation) GetField() (string, error) {
|
||||
func (rel FieldRelation) GetField() (string, error) {
|
||||
if rel.notSearchable {
|
||||
return "", fmt.Errorf("attribute %s not supported", rel.userField)
|
||||
}
|
||||
return rel.userField, nil
|
||||
}
|
||||
|
||||
func (rel UserFieldRelation) GetAttributeValues(user *object.User) []V {
|
||||
if rel.constantValue != nil && rel.fieldMapper == nil {
|
||||
return rel.constantValue
|
||||
}
|
||||
func (rel FieldRelation) GetAttributeValue(user *object.User) message.AttributeValue {
|
||||
return rel.fieldMapper(user)
|
||||
}
|
||||
|
||||
type UserFieldRelationMap map[string]UserFieldRelation
|
||||
|
||||
func (m UserFieldRelationMap) CaseInsensitiveGet(key string) (UserFieldRelation, bool) {
|
||||
lowerKey := strings.ToLower(key)
|
||||
ret, ok := m[lowerKey]
|
||||
return ret, ok
|
||||
}
|
||||
|
||||
type GroupAttributeMapper func(group *object.Group) []V
|
||||
|
||||
type GroupFieldRelation struct {
|
||||
groupField string
|
||||
ldapField string
|
||||
notSearchable bool
|
||||
hideOnStarOp bool
|
||||
fieldMapper GroupAttributeMapper
|
||||
constantValue []V
|
||||
}
|
||||
|
||||
func (rel GroupFieldRelation) GetField() (string, error) {
|
||||
if rel.notSearchable {
|
||||
return "", fmt.Errorf("attribute %s not supported", rel.groupField)
|
||||
}
|
||||
return rel.groupField, nil
|
||||
}
|
||||
|
||||
func (rel GroupFieldRelation) GetAttributeValues(group *object.Group) []V {
|
||||
if rel.constantValue != nil && rel.fieldMapper == nil {
|
||||
return rel.constantValue
|
||||
}
|
||||
return rel.fieldMapper(group)
|
||||
}
|
||||
|
||||
type GroupFieldRelationMap map[string]GroupFieldRelation
|
||||
|
||||
func (m GroupFieldRelationMap) CaseInsensitiveGet(key string) (GroupFieldRelation, bool) {
|
||||
lowerKey := strings.ToLower(key)
|
||||
ret, ok := m[lowerKey]
|
||||
return ret, ok
|
||||
}
|
||||
|
||||
var ldapUserAttributesMapping = UserFieldRelationMap{
|
||||
"cn": {ldapField: "cn", userField: "name", hideOnStarOp: true, fieldMapper: func(user *object.User) []V {
|
||||
return []V{V(user.Name)}
|
||||
var ldapAttributesMapping = map[string]FieldRelation{
|
||||
"cn": {userField: "name", hideOnStarOp: true, fieldMapper: func(user *object.User) message.AttributeValue {
|
||||
return message.AttributeValue(user.Name)
|
||||
}},
|
||||
"uid": {ldapField: "uid", userField: "name", hideOnStarOp: true, fieldMapper: func(user *object.User) []V {
|
||||
return []V{V(user.Name)}
|
||||
"uid": {userField: "name", hideOnStarOp: true, fieldMapper: func(user *object.User) message.AttributeValue {
|
||||
return message.AttributeValue(user.Name)
|
||||
}},
|
||||
"displayname": {ldapField: "displayName", userField: "displayName", fieldMapper: func(user *object.User) []V {
|
||||
return []V{V(user.DisplayName)}
|
||||
"displayname": {userField: "displayName", fieldMapper: func(user *object.User) message.AttributeValue {
|
||||
return message.AttributeValue(user.DisplayName)
|
||||
}},
|
||||
"email": {ldapField: "email", userField: "email", fieldMapper: func(user *object.User) []V {
|
||||
return []V{V(user.Email)}
|
||||
"email": {userField: "email", fieldMapper: func(user *object.User) message.AttributeValue {
|
||||
return message.AttributeValue(user.Email)
|
||||
}},
|
||||
"mail": {ldapField: "mail", userField: "email", fieldMapper: func(user *object.User) []V {
|
||||
return []V{V(user.Email)}
|
||||
"mail": {userField: "email", fieldMapper: func(user *object.User) message.AttributeValue {
|
||||
return message.AttributeValue(user.Email)
|
||||
}},
|
||||
"mobile": {ldapField: "mobile", userField: "phone", fieldMapper: func(user *object.User) []V {
|
||||
return []V{V(user.Phone)}
|
||||
"mobile": {userField: "phone", fieldMapper: func(user *object.User) message.AttributeValue {
|
||||
return message.AttributeValue(user.Phone)
|
||||
}},
|
||||
"telephonenumber": {ldapField: "telephoneNumber", userField: "phone", fieldMapper: func(user *object.User) []V {
|
||||
return []V{V(user.Phone)}
|
||||
"title": {userField: "tag", fieldMapper: func(user *object.User) message.AttributeValue {
|
||||
return message.AttributeValue(user.Tag)
|
||||
}},
|
||||
"postaladdress": {ldapField: "postalAddress", userField: "address", fieldMapper: func(user *object.User) []V {
|
||||
return []V{V(strings.Join(user.Address, " "))}
|
||||
}},
|
||||
"title": {ldapField: "title", userField: "title", fieldMapper: func(user *object.User) []V {
|
||||
return []V{V(user.Title)}
|
||||
}},
|
||||
"gecos": {ldapField: "gecos", userField: "displayName", fieldMapper: func(user *object.User) []V {
|
||||
return []V{V(user.DisplayName)}
|
||||
}},
|
||||
"description": {ldapField: "description", userField: "displayName", fieldMapper: func(user *object.User) []V {
|
||||
return []V{V(user.DisplayName)}
|
||||
}},
|
||||
"logindisabled": {ldapField: "loginDisabled", userField: "isForbidden", fieldMapper: func(user *object.User) []V {
|
||||
if user.IsForbidden {
|
||||
return []V{V("1")}
|
||||
} else {
|
||||
return []V{V("0")}
|
||||
}
|
||||
}},
|
||||
"userpassword": {
|
||||
ldapField: "userPassword",
|
||||
"userPassword": {
|
||||
userField: "userPassword",
|
||||
notSearchable: true,
|
||||
fieldMapper: func(user *object.User) []V {
|
||||
return []V{V(getUserPasswordWithType(user))}
|
||||
fieldMapper: func(user *object.User) message.AttributeValue {
|
||||
return message.AttributeValue(getUserPasswordWithType(user))
|
||||
},
|
||||
},
|
||||
"uidnumber": {ldapField: "uidNumber", notSearchable: true, fieldMapper: func(user *object.User) []V {
|
||||
return []V{V(fmt.Sprintf("%v", hash(user.Name)))}
|
||||
}},
|
||||
"gidnumber": {ldapField: "gidNumber", notSearchable: true, fieldMapper: func(user *object.User) []V {
|
||||
if len(user.Groups) == 0 {
|
||||
return []V{V("")}
|
||||
}
|
||||
group, err := object.GetGroup(user.Groups[0])
|
||||
if err != nil {
|
||||
log.Printf("gidnumber object.GetGroup error: %s", err)
|
||||
return []V{V("")}
|
||||
}
|
||||
return []V{V(fmt.Sprintf("%v", hash(group.Name)))}
|
||||
}},
|
||||
"homedirectory": {ldapField: "homeDirectory", notSearchable: true, fieldMapper: func(user *object.User) []V {
|
||||
return []V{V("/home/" + user.Name)}
|
||||
}},
|
||||
"loginshell": {ldapField: "loginShell", notSearchable: true, fieldMapper: func(user *object.User) []V {
|
||||
if user.IsForbidden || user.IsDeleted {
|
||||
return []V{V("/sbin/nologin")}
|
||||
} else {
|
||||
return []V{V("/bin/bash")}
|
||||
}
|
||||
}},
|
||||
"shadowlastchange": {ldapField: "shadowLastChange", notSearchable: true, fieldMapper: func(user *object.User) []V {
|
||||
// "this attribute specifies number of days between January 1, 1970, and the date that the password was last modified"
|
||||
updatedTime, err := time.Parse(time.RFC3339, user.UpdatedTime)
|
||||
if err != nil {
|
||||
log.Printf("shadowlastchange time.Parse error: %s", err)
|
||||
updatedTime = time.Now()
|
||||
}
|
||||
return []V{V(fmt.Sprint(updatedTime.Unix() / 86400))}
|
||||
}},
|
||||
"pwdchangedtime": {ldapField: "pwdChangedTime", notSearchable: true, fieldMapper: func(user *object.User) []V {
|
||||
updatedTime, err := time.Parse(time.RFC3339, user.UpdatedTime)
|
||||
if err != nil {
|
||||
log.Printf("pwdchangedtime time.Parse error: %s", err)
|
||||
updatedTime = time.Now()
|
||||
}
|
||||
return []V{V(updatedTime.UTC().Format("20060102030405Z"))}
|
||||
}},
|
||||
"shadowmin": {ldapField: "shadowMin", notSearchable: true, constantValue: []V{V("0")}},
|
||||
"shadowmax": {ldapField: "shadowMax", notSearchable: true, constantValue: []V{V("99999")}},
|
||||
"shadowwarning": {ldapField: "shadowWarning", notSearchable: true, constantValue: []V{V("7")}},
|
||||
"shadowexpire": {ldapField: "shadowExpire", notSearchable: true, fieldMapper: func(user *object.User) []V {
|
||||
if user.IsForbidden {
|
||||
return []V{V("1")}
|
||||
} else {
|
||||
return []V{V("-1")}
|
||||
}
|
||||
}},
|
||||
"shadowinactive": {ldapField: "shadowInactive", notSearchable: true, constantValue: []V{V("0")}},
|
||||
"shadowflag": {ldapField: "shadowFlag", notSearchable: true, constantValue: []V{V("0")}},
|
||||
"memberof": {ldapField: "memberOf", notSearchable: true, fieldMapper: func(user *object.User) []V {
|
||||
var groupdn []V
|
||||
for _, groupId := range user.Groups {
|
||||
group, err := object.GetGroup(groupId)
|
||||
if err != nil {
|
||||
log.Printf("memberOf object.GetGroup error: %s", err)
|
||||
continue
|
||||
}
|
||||
groupdn = append(groupdn, V(fmt.Sprintf("cn=%s,cn=groups,ou=%s", group.Name, group.Owner)))
|
||||
}
|
||||
return groupdn
|
||||
}},
|
||||
"objectclass": {ldapField: "objectClass", notSearchable: true, constantValue: []V{
|
||||
V("top"),
|
||||
V("posixAccount"),
|
||||
V("shadowAccount"),
|
||||
V("person"),
|
||||
V("organizationalPerson"),
|
||||
V("inetOrgPerson"),
|
||||
V("apple-user"),
|
||||
V("sambaSamAccount"),
|
||||
V("sambaIdmapEntry"),
|
||||
V("extensibleObject"),
|
||||
}},
|
||||
}
|
||||
|
||||
var ldapGroupAttributesMapping = GroupFieldRelationMap{
|
||||
"cn": {ldapField: "cn", hideOnStarOp: true, fieldMapper: func(group *object.Group) []V {
|
||||
return []V{V(group.Name)}
|
||||
}},
|
||||
"gidnumber": {ldapField: "gidNumber", hideOnStarOp: true, fieldMapper: func(group *object.Group) []V {
|
||||
return []V{V(fmt.Sprintf("%v", hash(group.Name)))}
|
||||
}},
|
||||
"member": {ldapField: "member", fieldMapper: func(group *object.Group) []V {
|
||||
users, err := object.GetGroupUsers(group.GetId())
|
||||
if err != nil {
|
||||
log.Printf("member object.GetGroupUsers error: %s", err)
|
||||
return []V{V("")}
|
||||
}
|
||||
var members []V
|
||||
for _, user := range users {
|
||||
members = append(members, V(fmt.Sprintf("uid=%s,cn=users,ou=%s", user.Name, user.Owner)))
|
||||
}
|
||||
return members
|
||||
}},
|
||||
"memberuid": {ldapField: "memberUid", fieldMapper: func(group *object.Group) []V {
|
||||
users, err := object.GetGroupUsers(group.GetId())
|
||||
if err != nil {
|
||||
log.Printf("member object.GetGroupUsers error: %s", err)
|
||||
return []V{V("")}
|
||||
}
|
||||
var members []message.AttributeValue
|
||||
for _, user := range users {
|
||||
members = append(members, message.AttributeValue(user.Name))
|
||||
}
|
||||
return members
|
||||
}},
|
||||
"description": {ldapField: "description", hideOnStarOp: true, fieldMapper: func(group *object.Group) []V {
|
||||
return []V{V(group.DisplayName)}
|
||||
}},
|
||||
"objectclass": {ldapField: "objectClass", hideOnStarOp: true, constantValue: []V{
|
||||
V("top"),
|
||||
V("posixGroup"),
|
||||
}},
|
||||
}
|
||||
|
||||
var (
|
||||
AdditionalLdapUserAttributes []message.LDAPString
|
||||
AdditionalLdapGroupAttributes []message.LDAPString
|
||||
)
|
||||
var AdditionalLdapAttributes []message.LDAPString
|
||||
|
||||
func init() {
|
||||
for _, v := range ldapUserAttributesMapping {
|
||||
for k, v := range ldapAttributesMapping {
|
||||
if v.hideOnStarOp {
|
||||
continue
|
||||
}
|
||||
AdditionalLdapUserAttributes = append(AdditionalLdapUserAttributes, message.LDAPString(v.ldapField))
|
||||
}
|
||||
for _, v := range ldapGroupAttributesMapping {
|
||||
if v.hideOnStarOp {
|
||||
continue
|
||||
}
|
||||
AdditionalLdapGroupAttributes = append(AdditionalLdapGroupAttributes, message.LDAPString(v.ldapField))
|
||||
AdditionalLdapAttributes = append(AdditionalLdapAttributes, message.LDAPString(k))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -502,52 +307,6 @@ func GetFilteredUsers(m *ldap.Message) (filteredUsers []*object.User, code int)
|
||||
}
|
||||
}
|
||||
|
||||
func GetFilteredOrganizations(m *ldap.Message) ([]*object.Organization, int) {
|
||||
if m.Client.IsGlobalAdmin {
|
||||
organizations, err := object.GetOrganizations("")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return organizations, ldap.LDAPResultSuccess
|
||||
} else if m.Client.IsOrgAdmin {
|
||||
requestUserId := util.GetId(m.Client.OrgName, m.Client.UserName)
|
||||
user, err := object.GetUser(requestUserId)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
organization, err := object.GetOrganizationByUser(user)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return []*object.Organization{organization}, ldap.LDAPResultSuccess
|
||||
} else {
|
||||
return nil, ldap.LDAPResultInsufficientAccessRights
|
||||
}
|
||||
}
|
||||
|
||||
func GetFilteredGroups(m *ldap.Message) ([]*object.Group, int) {
|
||||
if m.Client.IsGlobalAdmin {
|
||||
groups, err := object.GetGroups("")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return groups, ldap.LDAPResultSuccess
|
||||
} else if m.Client.IsOrgAdmin {
|
||||
requestUserId := util.GetId(m.Client.OrgName, m.Client.UserName)
|
||||
user, err := object.GetUser(requestUserId)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
groups, err := object.GetGroups(user.Owner)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return groups, ldap.LDAPResultSuccess
|
||||
} else {
|
||||
return nil, ldap.LDAPResultInsufficientAccessRights
|
||||
}
|
||||
}
|
||||
|
||||
// get user password with hash type prefix
|
||||
// TODO not handle salt yet
|
||||
// @return {md5}5f4dcc3b5aa765d61d8327deb882cf99
|
||||
@@ -571,49 +330,18 @@ func getUserPasswordWithType(user *object.User) string {
|
||||
return fmt.Sprintf("{%s}%s", prefix, user.Password)
|
||||
}
|
||||
|
||||
func getAttribute(attributeName string, user *object.User) message.AttributeValue {
|
||||
v, ok := ldapAttributesMapping[attributeName]
|
||||
if !ok {
|
||||
return ""
|
||||
}
|
||||
return v.GetAttributeValue(user)
|
||||
}
|
||||
|
||||
func getUserFieldFromAttribute(attributeName string) (string, error) {
|
||||
v, ok := ldapUserAttributesMapping.CaseInsensitiveGet(attributeName)
|
||||
v, ok := ldapAttributesMapping[attributeName]
|
||||
if !ok {
|
||||
return "", fmt.Errorf("attribute %s not supported", attributeName)
|
||||
}
|
||||
return v.GetField()
|
||||
}
|
||||
|
||||
func searchFilterForEquality(filter message.Filter, desc string, values ...string) string {
|
||||
switch f := filter.(type) {
|
||||
case message.FilterAnd:
|
||||
for _, child := range f {
|
||||
if val := searchFilterForEquality(child, desc, values...); val != "" {
|
||||
return val
|
||||
}
|
||||
}
|
||||
case message.FilterOr:
|
||||
for _, child := range f {
|
||||
if val := searchFilterForEquality(child, desc, values...); val != "" {
|
||||
return val
|
||||
}
|
||||
}
|
||||
case message.FilterNot:
|
||||
return searchFilterForEquality(f.Filter, desc, values...)
|
||||
case message.FilterSubstrings:
|
||||
// Handle FilterSubstrings case if needed
|
||||
case message.FilterEqualityMatch:
|
||||
if strings.EqualFold(string(f.AttributeDesc()), desc) {
|
||||
for _, value := range values {
|
||||
if val := string(f.AssertionValue()); val == value {
|
||||
return val
|
||||
}
|
||||
}
|
||||
}
|
||||
case message.FilterGreaterOrEqual:
|
||||
// Handle FilterGreaterOrEqual case if needed
|
||||
case message.FilterLessOrEqual:
|
||||
// Handle FilterLessOrEqual case if needed
|
||||
case message.FilterPresent:
|
||||
// Handle FilterPresent case if needed
|
||||
case message.FilterApproxMatch:
|
||||
// Handle FilterApproxMatch case if needed
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
@@ -37,12 +37,13 @@ type SignupItem struct {
|
||||
Prompted bool `json:"prompted"`
|
||||
Label string `json:"label"`
|
||||
Placeholder string `json:"placeholder"`
|
||||
Regex string `json:"regex"`
|
||||
Rule string `json:"rule"`
|
||||
}
|
||||
|
||||
type SamlItem struct {
|
||||
Name string `json:"name"`
|
||||
NameFormat string `json:"nameformat"`
|
||||
NameFormat string `json:"nameFormat"`
|
||||
Value string `json:"value"`
|
||||
}
|
||||
|
||||
@@ -347,6 +348,17 @@ func GetMaskedApplication(application *Application, userId string) *Application
|
||||
return nil
|
||||
}
|
||||
|
||||
if application.TokenFields == nil {
|
||||
application.TokenFields = []string{}
|
||||
}
|
||||
|
||||
if application.FailedSigninLimit == 0 {
|
||||
application.FailedSigninLimit = DefaultFailedSigninLimit
|
||||
}
|
||||
if application.FailedSigninFrozenTime == 0 {
|
||||
application.FailedSigninFrozenTime = DefaultFailedSigninFrozenTime
|
||||
}
|
||||
|
||||
if userId != "" {
|
||||
if isUserIdGlobalAdmin(userId) {
|
||||
return application
|
||||
@@ -384,13 +396,6 @@ func GetMaskedApplication(application *Application, userId string) *Application
|
||||
application.InvitationCodes = []string{"***"}
|
||||
}
|
||||
|
||||
if application.FailedSigninLimit == 0 {
|
||||
application.FailedSigninLimit = DefaultFailedSigninLimit
|
||||
}
|
||||
if application.FailedSigninFrozenTime == 0 {
|
||||
application.FailedSigninFrozenTime = DefaultFailedSigninFrozenTime
|
||||
}
|
||||
|
||||
return application
|
||||
}
|
||||
|
||||
|
@@ -24,16 +24,18 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
headerOrigin = "Origin"
|
||||
headerAllowOrigin = "Access-Control-Allow-Origin"
|
||||
headerAllowMethods = "Access-Control-Allow-Methods"
|
||||
headerAllowHeaders = "Access-Control-Allow-Headers"
|
||||
headerOrigin = "Origin"
|
||||
headerAllowOrigin = "Access-Control-Allow-Origin"
|
||||
headerAllowMethods = "Access-Control-Allow-Methods"
|
||||
headerAllowHeaders = "Access-Control-Allow-Headers"
|
||||
headerAllowCredentials = "Access-Control-Allow-Credentials"
|
||||
)
|
||||
|
||||
func setCorsHeaders(ctx *context.Context, origin string) {
|
||||
ctx.Output.Header(headerAllowOrigin, origin)
|
||||
ctx.Output.Header(headerAllowMethods, "POST, GET, OPTIONS, DELETE")
|
||||
ctx.Output.Header(headerAllowHeaders, "Content-Type, Authorization")
|
||||
ctx.Output.Header(headerAllowCredentials, "true")
|
||||
|
||||
if ctx.Input.Method() == "OPTIONS" {
|
||||
ctx.ResponseWriter.WriteHeader(http.StatusOK)
|
||||
|
@@ -34,6 +34,8 @@ func GetStorageProvider(providerType string, clientId string, clientSecret strin
|
||||
return NewQiniuCloudKodoStorageProvider(clientId, clientSecret, region, bucket, endpoint)
|
||||
case "Google Cloud Storage":
|
||||
return NewGoogleCloudStorageProvider(clientSecret, bucket, endpoint)
|
||||
case "Synology":
|
||||
return NewSynologyNasStorageProvider(clientId, clientSecret, endpoint)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
31
storage/synology_nas.go
Normal file
31
storage/synology_nas.go
Normal file
@@ -0,0 +1,31 @@
|
||||
// Copyright 2023 The Casdoor Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package storage
|
||||
|
||||
import (
|
||||
"github.com/casdoor/oss"
|
||||
"github.com/casdoor/oss/synology"
|
||||
)
|
||||
|
||||
func NewSynologyNasStorageProvider(clientId string, clientSecret string, endpoint string) oss.StorageInterface {
|
||||
sp := synology.New(&synology.Config{
|
||||
AccessID: clientId,
|
||||
AccessKey: clientSecret,
|
||||
Endpoint: endpoint,
|
||||
SharedFolder: "/home",
|
||||
})
|
||||
|
||||
return sp
|
||||
}
|
@@ -6761,7 +6761,7 @@
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"nameformat": {
|
||||
"nameFormat": {
|
||||
"type": "string"
|
||||
},
|
||||
"value": {
|
||||
|
@@ -4451,7 +4451,7 @@ definitions:
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
nameformat:
|
||||
nameFormat:
|
||||
type: string
|
||||
value:
|
||||
type: string
|
||||
|
@@ -27,7 +27,7 @@ import LoginPage from "./auth/LoginPage";
|
||||
import i18next from "i18next";
|
||||
import UrlTable from "./table/UrlTable";
|
||||
import ProviderTable from "./table/ProviderTable";
|
||||
import SigninTable from "./table/SigninTable";
|
||||
import SigninMethodTable from "./table/SigninMethodTable";
|
||||
import SignupTable from "./table/SignupTable";
|
||||
import SamlAttributeTable from "./table/SamlAttributeTable";
|
||||
import PromptPage from "./auth/PromptPage";
|
||||
@@ -487,7 +487,7 @@ class ApplicationEditPage extends React.Component {
|
||||
{Setting.getLabel(i18next.t("application:Signin methods"), i18next.t("application:Signin methods - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<SigninTable
|
||||
<SigninMethodTable
|
||||
title={i18next.t("application:Signin methods")}
|
||||
table={this.state.application.signinMethods}
|
||||
onUpdateTable={(value) => {
|
||||
@@ -797,7 +797,7 @@ class ApplicationEditPage extends React.Component {
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Radio.Group onChange={e => {this.updateApplicationField("formOffset", e.target.value);}} value={this.state.application.formOffset}>
|
||||
<Radio.Group buttonStyle="solid" onChange={e => {this.updateApplicationField("formOffset", e.target.value);}} value={this.state.application.formOffset}>
|
||||
<Radio.Button value={1}>{i18next.t("application:Left")}</Radio.Button>
|
||||
<Radio.Button value={2}>{i18next.t("application:Center")}</Radio.Button>
|
||||
<Radio.Button value={3}>{i18next.t("application:Right")}</Radio.Button>
|
||||
@@ -837,7 +837,7 @@ class ApplicationEditPage extends React.Component {
|
||||
</Col>
|
||||
<Col span={22} style={{marginTop: "5px"}}>
|
||||
<Row>
|
||||
<Radio.Group value={this.state.application.themeData?.isEnabled ?? false} onChange={e => {
|
||||
<Radio.Group buttonStyle="solid" value={this.state.application.themeData?.isEnabled ?? false} onChange={e => {
|
||||
const {_, ...theme} = this.state.application.themeData ?? {...Conf.ThemeDefault, isEnabled: false};
|
||||
this.updateApplicationField("themeData", {...theme, isEnabled: e.target.value});
|
||||
}} >
|
||||
|
@@ -393,7 +393,7 @@ class OrganizationEditPage extends React.Component {
|
||||
</Col>
|
||||
<Col span={22} style={{marginTop: "5px"}}>
|
||||
<Row>
|
||||
<Radio.Group value={this.state.organization.themeData?.isEnabled ?? false} onChange={e => {
|
||||
<Radio.Group buttonStyle="solid" value={this.state.organization.themeData?.isEnabled ?? false} onChange={e => {
|
||||
const {_, ...theme} = this.state.organization.themeData ?? {...Conf.ThemeDefault, isEnabled: false};
|
||||
this.updateOrganizationField("themeData", {...theme, isEnabled: e.target.value});
|
||||
}} >
|
||||
|
@@ -796,7 +796,7 @@ class ProviderEditPage extends React.Component {
|
||||
</Col>
|
||||
</Row>
|
||||
)}
|
||||
{["Custom HTTP SMS", "Local File System", "MinIO", "Tencent Cloud COS", "Google Cloud Storage", "Qiniu Cloud Kodo"].includes(this.state.provider.type) ? null : (
|
||||
{["Custom HTTP SMS", "Local File System", "MinIO", "Tencent Cloud COS", "Google Cloud Storage", "Qiniu Cloud Kodo", "Synology"].includes(this.state.provider.type) ? null : (
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={2}>
|
||||
{Setting.getLabel(i18next.t("provider:Endpoint (Intranet)"), i18next.t("provider:Region endpoint for Intranet"))} :
|
||||
@@ -832,7 +832,7 @@ class ProviderEditPage extends React.Component {
|
||||
</Col>
|
||||
</Row>
|
||||
)}
|
||||
{["Custom HTTP SMS", "MinIO", "Google Cloud Storage", "Qiniu Cloud Kodo"].includes(this.state.provider.type) ? null : (
|
||||
{["Custom HTTP SMS", "MinIO", "Google Cloud Storage", "Qiniu Cloud Kodo", "Synology"].includes(this.state.provider.type) ? null : (
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={2}>
|
||||
{Setting.getLabel(i18next.t("provider:Domain"), i18next.t("provider:Domain - Tooltip"))} :
|
||||
|
@@ -207,6 +207,10 @@ export const OtherProviderInfo = {
|
||||
logo: `${StaticBaseUrl}/img/social_google_cloud.png`,
|
||||
url: "https://cloud.google.com/storage",
|
||||
},
|
||||
"Synology": {
|
||||
logo: `${StaticBaseUrl}/img/social_synology.png`,
|
||||
url: "https://www.synology.com/en-global/dsm/feature/file_sharing",
|
||||
},
|
||||
},
|
||||
SAML: {
|
||||
"Aliyun IDaaS": {
|
||||
@@ -1024,6 +1028,7 @@ export function getProviderTypeOptions(category) {
|
||||
{id: "Azure Blob", name: "Azure Blob"},
|
||||
{id: "Qiniu Cloud Kodo", name: "Qiniu Cloud Kodo"},
|
||||
{id: "Google Cloud Storage", name: "Google Cloud Storage"},
|
||||
{id: "Synology", name: "Synology"},
|
||||
]
|
||||
);
|
||||
} else if (category === "SAML") {
|
||||
|
@@ -146,7 +146,7 @@ export function getWechatMessageEvent() {
|
||||
}
|
||||
|
||||
export function getCaptchaStatus(values) {
|
||||
return fetch(`${Setting.ServerUrl}/api/get-captcha-status?organization=${values["organization"]}&user_id=${values["username"]}`, {
|
||||
return fetch(`${Setting.ServerUrl}/api/get-captcha-status?organization=${values["organization"]}&userId=${values["username"]}`, {
|
||||
method: "GET",
|
||||
credentials: "include",
|
||||
headers: {
|
||||
|
@@ -201,7 +201,7 @@ class LoginPage extends React.Component {
|
||||
}
|
||||
|
||||
getDefaultLoginMethod(application) {
|
||||
if (application?.signinMethods.length > 0) {
|
||||
if (application?.signinMethods?.length > 0) {
|
||||
switch (application?.signinMethods[0].name) {
|
||||
case "Password": return "password";
|
||||
case "Verification code": {
|
||||
@@ -588,6 +588,10 @@ class LoginPage extends React.Component {
|
||||
},
|
||||
{
|
||||
validator: (_, value) => {
|
||||
if (value === "") {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
if (this.state.loginMethod === "verificationCode") {
|
||||
if (!Setting.isValidEmail(value) && !Setting.isValidPhone(value)) {
|
||||
this.setState({validEmailOrPhone: false});
|
||||
@@ -937,7 +941,7 @@ class LoginPage extends React.Component {
|
||||
[generateItemKey("LDAP", "None"), {label: i18next.t("login:LDAP"), key: "ldap"}],
|
||||
]);
|
||||
|
||||
application?.signinMethods.forEach((signinMethod) => {
|
||||
application?.signinMethods?.forEach((signinMethod) => {
|
||||
const item = itemsMap.get(generateItemKey(signinMethod.name, signinMethod.rule));
|
||||
if (item) {
|
||||
const label = signinMethod.name === signinMethod.displayName ? item.label : signinMethod.displayName;
|
||||
|
@@ -267,6 +267,7 @@
|
||||
"Models": "Models",
|
||||
"Name": "Name",
|
||||
"Name - Tooltip": "Unique, string-based ID",
|
||||
"Name format": "Name format",
|
||||
"Non-LDAP": "Non-LDAP",
|
||||
"None": "None",
|
||||
"OAuth providers": "OAuth providers",
|
||||
@@ -887,6 +888,7 @@
|
||||
"Please input your real name!": "Please input your real name!",
|
||||
"Please select your country code!": "Please select your country code!",
|
||||
"Please select your country/region!": "Please select your country/region!",
|
||||
"Regex": "Regex",
|
||||
"Terms of Use": "Terms of Use",
|
||||
"Terms of Use - Tooltip": "Terms of use that users need to read and agree to during registration",
|
||||
"Text 1": "Text 1",
|
||||
@@ -1053,8 +1055,6 @@
|
||||
"Managed accounts": "Managed accounts",
|
||||
"Modify password...": "Modify password...",
|
||||
"Multi-factor authentication": "Multi-factor authentication",
|
||||
"Name": "Name",
|
||||
"Name format": "Name format",
|
||||
"New Email": "New Email",
|
||||
"New Password": "New Password",
|
||||
"New User": "New User",
|
||||
@@ -1092,7 +1092,6 @@
|
||||
"Upload ID card front picture": "Upload ID card front picture",
|
||||
"Upload ID card with person picture": "Upload ID card with person picture",
|
||||
"Upload a photo": "Upload a photo",
|
||||
"Value": "Value",
|
||||
"Values": "Values",
|
||||
"Verification code sent": "Verification code sent",
|
||||
"WebAuthn credentials": "WebAuthn credentials",
|
||||
|
@@ -267,6 +267,7 @@
|
||||
"Models": "Modelle",
|
||||
"Name": "Name",
|
||||
"Name - Tooltip": "Eindeutige, auf Strings basierende ID",
|
||||
"Name format": "Name format",
|
||||
"Non-LDAP": "Non-LDAP",
|
||||
"None": "None",
|
||||
"OAuth providers": "OAuth-Provider",
|
||||
@@ -887,6 +888,7 @@
|
||||
"Please input your real name!": "Bitte geben Sie Ihren richtigen Namen ein!",
|
||||
"Please select your country code!": "Bitte wählen Sie Ihren Ländercode aus!",
|
||||
"Please select your country/region!": "Bitte wählen Sie Ihr Land/Ihre Region aus!",
|
||||
"Regex": "Regex",
|
||||
"Terms of Use": "Nutzungsbedingungen",
|
||||
"Terms of Use - Tooltip": "Nutzungsbedingungen, die Benutzer während der Registrierung lesen und akzeptieren müssen",
|
||||
"Text 1": "Text 1",
|
||||
@@ -1053,8 +1055,6 @@
|
||||
"Managed accounts": "Verwaltete Konten",
|
||||
"Modify password...": "Passwort ändern...",
|
||||
"Multi-factor authentication": "Multi-factor authentication",
|
||||
"Name": "Name",
|
||||
"Name format": "Name format",
|
||||
"New Email": "Neue E-Mail",
|
||||
"New Password": "Neues Passwort",
|
||||
"New User": "Neuer Benutzer",
|
||||
@@ -1092,7 +1092,6 @@
|
||||
"Upload ID card front picture": "Upload ID card front picture",
|
||||
"Upload ID card with person picture": "Upload ID card with person picture",
|
||||
"Upload a photo": "Lade ein Foto hoch",
|
||||
"Value": "Value",
|
||||
"Values": "Werte",
|
||||
"Verification code sent": "Bestätigungscode gesendet",
|
||||
"WebAuthn credentials": "WebAuthn-Anmeldeinformationen",
|
||||
|
@@ -267,6 +267,7 @@
|
||||
"Models": "Models",
|
||||
"Name": "Name",
|
||||
"Name - Tooltip": "Unique, string-based ID",
|
||||
"Name format": "Name format",
|
||||
"Non-LDAP": "Non-LDAP",
|
||||
"None": "None",
|
||||
"OAuth providers": "OAuth providers",
|
||||
@@ -887,6 +888,7 @@
|
||||
"Please input your real name!": "Please input your real name!",
|
||||
"Please select your country code!": "Please select your country code!",
|
||||
"Please select your country/region!": "Please select your country/region!",
|
||||
"Regex": "Regex",
|
||||
"Terms of Use": "Terms of Use",
|
||||
"Terms of Use - Tooltip": "Terms of use that users need to read and agree to during registration",
|
||||
"Text 1": "Text 1",
|
||||
@@ -1053,8 +1055,6 @@
|
||||
"Managed accounts": "Managed accounts",
|
||||
"Modify password...": "Modify password...",
|
||||
"Multi-factor authentication": "Multi-factor authentication",
|
||||
"Name": "Name",
|
||||
"Name format": "Name format",
|
||||
"New Email": "New Email",
|
||||
"New Password": "New Password",
|
||||
"New User": "New User",
|
||||
@@ -1092,7 +1092,6 @@
|
||||
"Upload ID card front picture": "Upload ID card front picture",
|
||||
"Upload ID card with person picture": "Upload ID card with person picture",
|
||||
"Upload a photo": "Upload a photo",
|
||||
"Value": "Value",
|
||||
"Values": "Values",
|
||||
"Verification code sent": "Verification code sent",
|
||||
"WebAuthn credentials": "WebAuthn credentials",
|
||||
|
@@ -267,6 +267,7 @@
|
||||
"Models": "Modelos",
|
||||
"Name": "Nombre",
|
||||
"Name - Tooltip": "ID único basado en cadenas",
|
||||
"Name format": "Name format",
|
||||
"Non-LDAP": "Non-LDAP",
|
||||
"None": "None",
|
||||
"OAuth providers": "Proveedores de OAuth",
|
||||
@@ -887,6 +888,7 @@
|
||||
"Please input your real name!": "¡Por favor, ingresa tu nombre real!",
|
||||
"Please select your country code!": "¡Por favor seleccione su código de país!",
|
||||
"Please select your country/region!": "¡Por favor seleccione su país/región!",
|
||||
"Regex": "Regex",
|
||||
"Terms of Use": "Términos de uso",
|
||||
"Terms of Use - Tooltip": "Términos de uso que los usuarios necesitan leer y aceptar durante el registro",
|
||||
"Text 1": "Text 1",
|
||||
@@ -1053,8 +1055,6 @@
|
||||
"Managed accounts": "Cuentas gestionadas",
|
||||
"Modify password...": "Modificar contraseña...",
|
||||
"Multi-factor authentication": "Multi-factor authentication",
|
||||
"Name": "Name",
|
||||
"Name format": "Name format",
|
||||
"New Email": "Nuevo correo electrónico",
|
||||
"New Password": "Nueva contraseña",
|
||||
"New User": "Nuevo Usuario",
|
||||
@@ -1092,7 +1092,6 @@
|
||||
"Upload ID card front picture": "Upload ID card front picture",
|
||||
"Upload ID card with person picture": "Upload ID card with person picture",
|
||||
"Upload a photo": "Subir una foto",
|
||||
"Value": "Value",
|
||||
"Values": "Valores",
|
||||
"Verification code sent": "Código de verificación enviado",
|
||||
"WebAuthn credentials": "Credenciales de WebAuthn",
|
||||
|
@@ -267,6 +267,7 @@
|
||||
"Models": "Models",
|
||||
"Name": "Name",
|
||||
"Name - Tooltip": "Unique, string-based ID",
|
||||
"Name format": "Name format",
|
||||
"Non-LDAP": "Non-LDAP",
|
||||
"None": "None",
|
||||
"OAuth providers": "OAuth providers",
|
||||
@@ -887,6 +888,7 @@
|
||||
"Please input your real name!": "Please input your real name!",
|
||||
"Please select your country code!": "Please select your country code!",
|
||||
"Please select your country/region!": "Please select your country/region!",
|
||||
"Regex": "Regex",
|
||||
"Terms of Use": "Terms of Use",
|
||||
"Terms of Use - Tooltip": "Terms of use that users need to read and agree to during registration",
|
||||
"Text 1": "Text 1",
|
||||
@@ -1053,8 +1055,6 @@
|
||||
"Managed accounts": "Managed accounts",
|
||||
"Modify password...": "Modify password...",
|
||||
"Multi-factor authentication": "Multi-factor authentication",
|
||||
"Name": "Name",
|
||||
"Name format": "Name format",
|
||||
"New Email": "New Email",
|
||||
"New Password": "New Password",
|
||||
"New User": "New User",
|
||||
@@ -1092,7 +1092,6 @@
|
||||
"Upload ID card front picture": "Upload ID card front picture",
|
||||
"Upload ID card with person picture": "Upload ID card with person picture",
|
||||
"Upload a photo": "Upload a photo",
|
||||
"Value": "Value",
|
||||
"Values": "Values",
|
||||
"Verification code sent": "Verification code sent",
|
||||
"WebAuthn credentials": "WebAuthn credentials",
|
||||
|
@@ -267,6 +267,7 @@
|
||||
"Models": "Models",
|
||||
"Name": "Name",
|
||||
"Name - Tooltip": "Unique, string-based ID",
|
||||
"Name format": "Name format",
|
||||
"Non-LDAP": "Non-LDAP",
|
||||
"None": "None",
|
||||
"OAuth providers": "OAuth providers",
|
||||
@@ -887,6 +888,7 @@
|
||||
"Please input your real name!": "Please input your real name!",
|
||||
"Please select your country code!": "Please select your country code!",
|
||||
"Please select your country/region!": "Please select your country/region!",
|
||||
"Regex": "Regex",
|
||||
"Terms of Use": "Terms of Use",
|
||||
"Terms of Use - Tooltip": "Terms of use that users need to read and agree to during registration",
|
||||
"Text 1": "Text 1",
|
||||
@@ -1053,8 +1055,6 @@
|
||||
"Managed accounts": "Managed accounts",
|
||||
"Modify password...": "Modify password...",
|
||||
"Multi-factor authentication": "Multi-factor authentication",
|
||||
"Name": "Name",
|
||||
"Name format": "Name format",
|
||||
"New Email": "New Email",
|
||||
"New Password": "New Password",
|
||||
"New User": "New User",
|
||||
@@ -1092,7 +1092,6 @@
|
||||
"Upload ID card front picture": "Upload ID card front picture",
|
||||
"Upload ID card with person picture": "Upload ID card with person picture",
|
||||
"Upload a photo": "Upload a photo",
|
||||
"Value": "Value",
|
||||
"Values": "Values",
|
||||
"Verification code sent": "Verification code sent",
|
||||
"WebAuthn credentials": "WebAuthn credentials",
|
||||
|
@@ -267,6 +267,7 @@
|
||||
"Models": "Modèles",
|
||||
"Name": "Nom",
|
||||
"Name - Tooltip": "Identifiant unique à base de chaîne",
|
||||
"Name format": "Name format",
|
||||
"Non-LDAP": "Non-LDAP",
|
||||
"None": "Aucun",
|
||||
"OAuth providers": "Fournisseurs OAuth",
|
||||
@@ -887,6 +888,7 @@
|
||||
"Please input your real name!": "Veuillez saisir votre nom complet !",
|
||||
"Please select your country code!": "Sélectionnez votre code de pays, s'il vous plaît !",
|
||||
"Please select your country/region!": "Veuillez sélectionner votre pays/région !",
|
||||
"Regex": "Regex",
|
||||
"Terms of Use": "Conditions d'utilisation",
|
||||
"Terms of Use - Tooltip": "Conditions d'utilisation qui doivent être lus acceptés lors de l'enregistrement du compte",
|
||||
"Text 1": "Text 1",
|
||||
@@ -1053,8 +1055,6 @@
|
||||
"Managed accounts": "Comptes gérés",
|
||||
"Modify password...": "Modifier le mot de passe...",
|
||||
"Multi-factor authentication": "Authentification multifacteur",
|
||||
"Name": "Name",
|
||||
"Name format": "Name format",
|
||||
"New Email": "Nouvelle adresse e-mail",
|
||||
"New Password": "Nouveau mot de passe",
|
||||
"New User": "Nouveau compte",
|
||||
@@ -1092,7 +1092,6 @@
|
||||
"Upload ID card front picture": "Télécharger une photo de l'endroit de la pièce d'identité",
|
||||
"Upload ID card with person picture": "Télécharger une photo la pièce d'identité avec une personne",
|
||||
"Upload a photo": "Télécharger une photo",
|
||||
"Value": "Value",
|
||||
"Values": "Valeurs",
|
||||
"Verification code sent": "Code de vérification envoyé",
|
||||
"WebAuthn credentials": "Identifiants WebAuthn",
|
||||
|
@@ -267,6 +267,7 @@
|
||||
"Models": "Models",
|
||||
"Name": "Name",
|
||||
"Name - Tooltip": "Unique, string-based ID",
|
||||
"Name format": "Name format",
|
||||
"Non-LDAP": "Non-LDAP",
|
||||
"None": "None",
|
||||
"OAuth providers": "OAuth providers",
|
||||
@@ -887,6 +888,7 @@
|
||||
"Please input your real name!": "Please input your real name!",
|
||||
"Please select your country code!": "Please select your country code!",
|
||||
"Please select your country/region!": "Please select your country/region!",
|
||||
"Regex": "Regex",
|
||||
"Terms of Use": "Terms of Use",
|
||||
"Terms of Use - Tooltip": "Terms of use that users need to read and agree to during registration",
|
||||
"Text 1": "Text 1",
|
||||
@@ -1053,8 +1055,6 @@
|
||||
"Managed accounts": "Managed accounts",
|
||||
"Modify password...": "Modify password...",
|
||||
"Multi-factor authentication": "Multi-factor authentication",
|
||||
"Name": "Name",
|
||||
"Name format": "Name format",
|
||||
"New Email": "New Email",
|
||||
"New Password": "New Password",
|
||||
"New User": "New User",
|
||||
@@ -1092,7 +1092,6 @@
|
||||
"Upload ID card front picture": "Upload ID card front picture",
|
||||
"Upload ID card with person picture": "Upload ID card with person picture",
|
||||
"Upload a photo": "Upload a photo",
|
||||
"Value": "Value",
|
||||
"Values": "Values",
|
||||
"Verification code sent": "Verification code sent",
|
||||
"WebAuthn credentials": "WebAuthn credentials",
|
||||
|
@@ -267,6 +267,7 @@
|
||||
"Models": "Model-model",
|
||||
"Name": "Nama",
|
||||
"Name - Tooltip": "ID unik berbasis string",
|
||||
"Name format": "Name format",
|
||||
"Non-LDAP": "Non-LDAP",
|
||||
"None": "None",
|
||||
"OAuth providers": "Penyedia OAuth",
|
||||
@@ -887,6 +888,7 @@
|
||||
"Please input your real name!": "Silakan masukkan nama asli Anda!",
|
||||
"Please select your country code!": "Tolong pilih kode negara Anda!",
|
||||
"Please select your country/region!": "Silakan pilih negara/region Anda!",
|
||||
"Regex": "Regex",
|
||||
"Terms of Use": "Syarat Penggunaan",
|
||||
"Terms of Use - Tooltip": "Syarat penggunaan yang harus dibaca dan disetujui oleh pengguna selama proses registrasi",
|
||||
"Text 1": "Text 1",
|
||||
@@ -1053,8 +1055,6 @@
|
||||
"Managed accounts": "Akun yang dikelola",
|
||||
"Modify password...": "Mengubah kata sandi...",
|
||||
"Multi-factor authentication": "Multi-factor authentication",
|
||||
"Name": "Name",
|
||||
"Name format": "Name format",
|
||||
"New Email": "Email baru",
|
||||
"New Password": "Kata Sandi Baru",
|
||||
"New User": "Pengguna Baru",
|
||||
@@ -1092,7 +1092,6 @@
|
||||
"Upload ID card front picture": "Upload ID card front picture",
|
||||
"Upload ID card with person picture": "Upload ID card with person picture",
|
||||
"Upload a photo": "Unggah foto",
|
||||
"Value": "Value",
|
||||
"Values": "Nilai-nilai",
|
||||
"Verification code sent": "Kode verifikasi telah dikirim",
|
||||
"WebAuthn credentials": "Kredensial WebAuthn",
|
||||
|
@@ -267,6 +267,7 @@
|
||||
"Models": "Models",
|
||||
"Name": "Name",
|
||||
"Name - Tooltip": "Unique, string-based ID",
|
||||
"Name format": "Name format",
|
||||
"Non-LDAP": "Non-LDAP",
|
||||
"None": "None",
|
||||
"OAuth providers": "OAuth providers",
|
||||
@@ -887,6 +888,7 @@
|
||||
"Please input your real name!": "Please input your real name!",
|
||||
"Please select your country code!": "Please select your country code!",
|
||||
"Please select your country/region!": "Please select your country/region!",
|
||||
"Regex": "Regex",
|
||||
"Terms of Use": "Terms of Use",
|
||||
"Terms of Use - Tooltip": "Terms of use that users need to read and agree to during registration",
|
||||
"Text 1": "Text 1",
|
||||
@@ -1053,8 +1055,6 @@
|
||||
"Managed accounts": "Managed accounts",
|
||||
"Modify password...": "Modify password...",
|
||||
"Multi-factor authentication": "Multi-factor authentication",
|
||||
"Name": "Name",
|
||||
"Name format": "Name format",
|
||||
"New Email": "New Email",
|
||||
"New Password": "New Password",
|
||||
"New User": "New User",
|
||||
@@ -1092,7 +1092,6 @@
|
||||
"Upload ID card front picture": "Upload ID card front picture",
|
||||
"Upload ID card with person picture": "Upload ID card with person picture",
|
||||
"Upload a photo": "Upload a photo",
|
||||
"Value": "Value",
|
||||
"Values": "Values",
|
||||
"Verification code sent": "Verification code sent",
|
||||
"WebAuthn credentials": "WebAuthn credentials",
|
||||
|
@@ -267,6 +267,7 @@
|
||||
"Models": "モデル",
|
||||
"Name": "名前",
|
||||
"Name - Tooltip": "ユニークで文字列ベースのID",
|
||||
"Name format": "Name format",
|
||||
"Non-LDAP": "Non-LDAP",
|
||||
"None": "None",
|
||||
"OAuth providers": "OAuthプロバイダー",
|
||||
@@ -887,6 +888,7 @@
|
||||
"Please input your real name!": "正しい名前を入力してください!",
|
||||
"Please select your country code!": "あなたの国コードを選択してください!",
|
||||
"Please select your country/region!": "あなたの国/地域を選択してください!",
|
||||
"Regex": "Regex",
|
||||
"Terms of Use": "利用規約",
|
||||
"Terms of Use - Tooltip": "ユーザーが登録する際に読んで同意する必要がある利用規約",
|
||||
"Text 1": "Text 1",
|
||||
@@ -1053,8 +1055,6 @@
|
||||
"Managed accounts": "管理アカウント",
|
||||
"Modify password...": "パスワードを変更する...",
|
||||
"Multi-factor authentication": "Multi-factor authentication",
|
||||
"Name": "Name",
|
||||
"Name format": "Name format",
|
||||
"New Email": "新しいメール",
|
||||
"New Password": "新しいパスワード",
|
||||
"New User": "新しいユーザー",
|
||||
@@ -1092,7 +1092,6 @@
|
||||
"Upload ID card front picture": "Upload ID card front picture",
|
||||
"Upload ID card with person picture": "Upload ID card with person picture",
|
||||
"Upload a photo": "写真をアップロードしてください",
|
||||
"Value": "Value",
|
||||
"Values": "価値観",
|
||||
"Verification code sent": "確認コードを送信しました",
|
||||
"WebAuthn credentials": "WebAuthnの資格情報",
|
||||
|
@@ -267,6 +267,7 @@
|
||||
"Models": "Models",
|
||||
"Name": "Name",
|
||||
"Name - Tooltip": "Unique, string-based ID",
|
||||
"Name format": "Name format",
|
||||
"Non-LDAP": "Non-LDAP",
|
||||
"None": "None",
|
||||
"OAuth providers": "OAuth providers",
|
||||
@@ -887,6 +888,7 @@
|
||||
"Please input your real name!": "Please input your real name!",
|
||||
"Please select your country code!": "Please select your country code!",
|
||||
"Please select your country/region!": "Please select your country/region!",
|
||||
"Regex": "Regex",
|
||||
"Terms of Use": "Terms of Use",
|
||||
"Terms of Use - Tooltip": "Terms of use that users need to read and agree to during registration",
|
||||
"Text 1": "Text 1",
|
||||
@@ -1053,8 +1055,6 @@
|
||||
"Managed accounts": "Managed accounts",
|
||||
"Modify password...": "Modify password...",
|
||||
"Multi-factor authentication": "Multi-factor authentication",
|
||||
"Name": "Name",
|
||||
"Name format": "Name format",
|
||||
"New Email": "New Email",
|
||||
"New Password": "New Password",
|
||||
"New User": "New User",
|
||||
@@ -1092,7 +1092,6 @@
|
||||
"Upload ID card front picture": "Upload ID card front picture",
|
||||
"Upload ID card with person picture": "Upload ID card with person picture",
|
||||
"Upload a photo": "Upload a photo",
|
||||
"Value": "Value",
|
||||
"Values": "Values",
|
||||
"Verification code sent": "Verification code sent",
|
||||
"WebAuthn credentials": "WebAuthn credentials",
|
||||
|
@@ -267,6 +267,7 @@
|
||||
"Models": "모델들",
|
||||
"Name": "이름",
|
||||
"Name - Tooltip": "고유한 문자열 기반 ID",
|
||||
"Name format": "Name format",
|
||||
"Non-LDAP": "Non-LDAP",
|
||||
"None": "None",
|
||||
"OAuth providers": "OAuth 공급자",
|
||||
@@ -887,6 +888,7 @@
|
||||
"Please input your real name!": "진짜 이름을 입력해주세요!",
|
||||
"Please select your country code!": "국가 코드를 선택해 주세요!",
|
||||
"Please select your country/region!": "국가 / 지역을 선택해주세요!",
|
||||
"Regex": "Regex",
|
||||
"Terms of Use": "사용 약관",
|
||||
"Terms of Use - Tooltip": "등록 중 사용자가 읽어야 하고 동의해야하는 이용 약관",
|
||||
"Text 1": "Text 1",
|
||||
@@ -1053,8 +1055,6 @@
|
||||
"Managed accounts": "관리 계정",
|
||||
"Modify password...": "비밀번호 수정하기...",
|
||||
"Multi-factor authentication": "Multi-factor authentication",
|
||||
"Name": "Name",
|
||||
"Name format": "Name format",
|
||||
"New Email": "새 이메일",
|
||||
"New Password": "새로운 비밀번호",
|
||||
"New User": "새로운 사용자",
|
||||
@@ -1092,7 +1092,6 @@
|
||||
"Upload ID card front picture": "Upload ID card front picture",
|
||||
"Upload ID card with person picture": "Upload ID card with person picture",
|
||||
"Upload a photo": "사진을 업로드하세요",
|
||||
"Value": "Value",
|
||||
"Values": "가치들",
|
||||
"Verification code sent": "인증 코드가 전송되었습니다",
|
||||
"WebAuthn credentials": "웹 인증 자격증명",
|
||||
|
@@ -267,6 +267,7 @@
|
||||
"Models": "Models",
|
||||
"Name": "Name",
|
||||
"Name - Tooltip": "Unique, string-based ID",
|
||||
"Name format": "Name format",
|
||||
"Non-LDAP": "Non-LDAP",
|
||||
"None": "None",
|
||||
"OAuth providers": "OAuth providers",
|
||||
@@ -887,6 +888,7 @@
|
||||
"Please input your real name!": "Please input your real name!",
|
||||
"Please select your country code!": "Please select your country code!",
|
||||
"Please select your country/region!": "Please select your country/region!",
|
||||
"Regex": "Regex",
|
||||
"Terms of Use": "Terms of Use",
|
||||
"Terms of Use - Tooltip": "Terms of use that users need to read and agree to during registration",
|
||||
"Text 1": "Text 1",
|
||||
@@ -1053,8 +1055,6 @@
|
||||
"Managed accounts": "Managed accounts",
|
||||
"Modify password...": "Modify password...",
|
||||
"Multi-factor authentication": "Multi-factor authentication",
|
||||
"Name": "Name",
|
||||
"Name format": "Name format",
|
||||
"New Email": "New Email",
|
||||
"New Password": "New Password",
|
||||
"New User": "New User",
|
||||
@@ -1092,7 +1092,6 @@
|
||||
"Upload ID card front picture": "Upload ID card front picture",
|
||||
"Upload ID card with person picture": "Upload ID card with person picture",
|
||||
"Upload a photo": "Upload a photo",
|
||||
"Value": "Value",
|
||||
"Values": "Values",
|
||||
"Verification code sent": "Verification code sent",
|
||||
"WebAuthn credentials": "WebAuthn credentials",
|
||||
|
@@ -267,6 +267,7 @@
|
||||
"Models": "Models",
|
||||
"Name": "Name",
|
||||
"Name - Tooltip": "Unique, string-based ID",
|
||||
"Name format": "Name format",
|
||||
"Non-LDAP": "Non-LDAP",
|
||||
"None": "None",
|
||||
"OAuth providers": "OAuth providers",
|
||||
@@ -887,6 +888,7 @@
|
||||
"Please input your real name!": "Please input your real name!",
|
||||
"Please select your country code!": "Please select your country code!",
|
||||
"Please select your country/region!": "Please select your country/region!",
|
||||
"Regex": "Regex",
|
||||
"Terms of Use": "Terms of Use",
|
||||
"Terms of Use - Tooltip": "Terms of use that users need to read and agree to during registration",
|
||||
"Text 1": "Text 1",
|
||||
@@ -1053,8 +1055,6 @@
|
||||
"Managed accounts": "Managed accounts",
|
||||
"Modify password...": "Modify password...",
|
||||
"Multi-factor authentication": "Multi-factor authentication",
|
||||
"Name": "Name",
|
||||
"Name format": "Name format",
|
||||
"New Email": "New Email",
|
||||
"New Password": "New Password",
|
||||
"New User": "New User",
|
||||
@@ -1092,7 +1092,6 @@
|
||||
"Upload ID card front picture": "Upload ID card front picture",
|
||||
"Upload ID card with person picture": "Upload ID card with person picture",
|
||||
"Upload a photo": "Upload a photo",
|
||||
"Value": "Value",
|
||||
"Values": "Values",
|
||||
"Verification code sent": "Verification code sent",
|
||||
"WebAuthn credentials": "WebAuthn credentials",
|
||||
|
@@ -267,6 +267,7 @@
|
||||
"Models": "Models",
|
||||
"Name": "Name",
|
||||
"Name - Tooltip": "Unique, string-based ID",
|
||||
"Name format": "Name format",
|
||||
"Non-LDAP": "Non-LDAP",
|
||||
"None": "None",
|
||||
"OAuth providers": "OAuth providers",
|
||||
@@ -887,6 +888,7 @@
|
||||
"Please input your real name!": "Please input your real name!",
|
||||
"Please select your country code!": "Please select your country code!",
|
||||
"Please select your country/region!": "Please select your country/region!",
|
||||
"Regex": "Regex",
|
||||
"Terms of Use": "Terms of Use",
|
||||
"Terms of Use - Tooltip": "Terms of use that users need to read and agree to during registration",
|
||||
"Text 1": "Text 1",
|
||||
@@ -1053,8 +1055,6 @@
|
||||
"Managed accounts": "Managed accounts",
|
||||
"Modify password...": "Modify password...",
|
||||
"Multi-factor authentication": "Multi-factor authentication",
|
||||
"Name": "Name",
|
||||
"Name format": "Name format",
|
||||
"New Email": "New Email",
|
||||
"New Password": "New Password",
|
||||
"New User": "New User",
|
||||
@@ -1092,7 +1092,6 @@
|
||||
"Upload ID card front picture": "Upload ID card front picture",
|
||||
"Upload ID card with person picture": "Upload ID card with person picture",
|
||||
"Upload a photo": "Upload a photo",
|
||||
"Value": "Value",
|
||||
"Values": "Values",
|
||||
"Verification code sent": "Verification code sent",
|
||||
"WebAuthn credentials": "WebAuthn credentials",
|
||||
|
@@ -267,6 +267,7 @@
|
||||
"Models": "Modelos",
|
||||
"Name": "Nome",
|
||||
"Name - Tooltip": "ID único em formato de string",
|
||||
"Name format": "Name format",
|
||||
"Non-LDAP": "Non-LDAP",
|
||||
"None": "None",
|
||||
"OAuth providers": "Provedores OAuth",
|
||||
@@ -887,6 +888,7 @@
|
||||
"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!",
|
||||
"Regex": "Regex",
|
||||
"Terms of Use": "Termos de Uso",
|
||||
"Terms of Use - Tooltip": "Termos de uso que os usuários precisam ler e concordar durante o registro",
|
||||
"Text 1": "Text 1",
|
||||
@@ -1053,8 +1055,6 @@
|
||||
"Managed accounts": "Contas gerenciadas",
|
||||
"Modify password...": "Modificar senha...",
|
||||
"Multi-factor authentication": "Autenticação de vários fatores",
|
||||
"Name": "Name",
|
||||
"Name format": "Name format",
|
||||
"New Email": "Novo E-mail",
|
||||
"New Password": "Nova Senha",
|
||||
"New User": "Novo Usuário",
|
||||
@@ -1092,7 +1092,6 @@
|
||||
"Upload ID card front picture": "Upload ID card front picture",
|
||||
"Upload ID card with person picture": "Upload ID card with person picture",
|
||||
"Upload a photo": "Enviar uma foto",
|
||||
"Value": "Value",
|
||||
"Values": "Valores",
|
||||
"Verification code sent": "Código de verificação enviado",
|
||||
"WebAuthn credentials": "Credenciais WebAuthn",
|
||||
|
@@ -267,6 +267,7 @@
|
||||
"Models": "Модели",
|
||||
"Name": "Имя",
|
||||
"Name - Tooltip": "Уникальный идентификатор на основе строки",
|
||||
"Name format": "Name format",
|
||||
"Non-LDAP": "Non-LDAP",
|
||||
"None": "None",
|
||||
"OAuth providers": "Провайдеры OAuth",
|
||||
@@ -887,6 +888,7 @@
|
||||
"Please input your real name!": "Пожалуйста, введите своё настоящее имя!",
|
||||
"Please select your country code!": "Пожалуйста, выберите код своей страны!",
|
||||
"Please select your country/region!": "Пожалуйста, выберите свою страну / регион!",
|
||||
"Regex": "Regex",
|
||||
"Terms of Use": "Условия использования",
|
||||
"Terms of Use - Tooltip": "Условия использования, которые пользователи должны прочитать и согласиться с ними при регистрации",
|
||||
"Text 1": "Text 1",
|
||||
@@ -1053,8 +1055,6 @@
|
||||
"Managed accounts": "Управляемые счета",
|
||||
"Modify password...": "Изменить пароль...",
|
||||
"Multi-factor authentication": "Multi-factor authentication",
|
||||
"Name": "Name",
|
||||
"Name format": "Name format",
|
||||
"New Email": "Новое электронное письмо",
|
||||
"New Password": "Новый пароль",
|
||||
"New User": "Новый пользователь",
|
||||
@@ -1092,7 +1092,6 @@
|
||||
"Upload ID card front picture": "Upload ID card front picture",
|
||||
"Upload ID card with person picture": "Upload ID card with person picture",
|
||||
"Upload a photo": "Загрузить фото",
|
||||
"Value": "Value",
|
||||
"Values": "Значения",
|
||||
"Verification code sent": "Код подтверждения отправлен",
|
||||
"WebAuthn credentials": "WebAuthn удостоверения",
|
||||
|
@@ -267,6 +267,7 @@
|
||||
"Models": "Models",
|
||||
"Name": "Name",
|
||||
"Name - Tooltip": "Unique, string-based ID",
|
||||
"Name format": "Name format",
|
||||
"Non-LDAP": "Non-LDAP",
|
||||
"None": "None",
|
||||
"OAuth providers": "OAuth providers",
|
||||
@@ -887,6 +888,7 @@
|
||||
"Please input your real name!": "Please input your real name!",
|
||||
"Please select your country code!": "Please select your country code!",
|
||||
"Please select your country/region!": "Please select your country/region!",
|
||||
"Regex": "Regex",
|
||||
"Terms of Use": "Terms of Use",
|
||||
"Terms of Use - Tooltip": "Terms of use that users need to read and agree to during registration",
|
||||
"Text 1": "Text 1",
|
||||
@@ -1053,8 +1055,6 @@
|
||||
"Managed accounts": "Managed accounts",
|
||||
"Modify password...": "Modify password...",
|
||||
"Multi-factor authentication": "Multi-factor authentication",
|
||||
"Name": "Name",
|
||||
"Name format": "Name format",
|
||||
"New Email": "New Email",
|
||||
"New Password": "New Password",
|
||||
"New User": "New User",
|
||||
@@ -1092,7 +1092,6 @@
|
||||
"Upload ID card front picture": "Upload ID card front picture",
|
||||
"Upload ID card with person picture": "Upload ID card with person picture",
|
||||
"Upload a photo": "Upload a photo",
|
||||
"Value": "Value",
|
||||
"Values": "Values",
|
||||
"Verification code sent": "Verification code sent",
|
||||
"WebAuthn credentials": "WebAuthn credentials",
|
||||
|
@@ -267,6 +267,7 @@
|
||||
"Models": "Models",
|
||||
"Name": "Name",
|
||||
"Name - Tooltip": "Unique, string-based ID",
|
||||
"Name format": "Name format",
|
||||
"Non-LDAP": "Non-LDAP",
|
||||
"None": "None",
|
||||
"OAuth providers": "OAuth providers",
|
||||
@@ -887,6 +888,7 @@
|
||||
"Please input your real name!": "Please input your real name!",
|
||||
"Please select your country code!": "Please select your country code!",
|
||||
"Please select your country/region!": "Please select your country/region!",
|
||||
"Regex": "Regex",
|
||||
"Terms of Use": "Terms of Use",
|
||||
"Terms of Use - Tooltip": "Terms of use that users need to read and agree to during registration",
|
||||
"Text 1": "Text 1",
|
||||
@@ -1053,8 +1055,6 @@
|
||||
"Managed accounts": "Managed accounts",
|
||||
"Modify password...": "Modify password...",
|
||||
"Multi-factor authentication": "Multi-factor authentication",
|
||||
"Name": "Name",
|
||||
"Name format": "Name format",
|
||||
"New Email": "New Email",
|
||||
"New Password": "New Password",
|
||||
"New User": "New User",
|
||||
@@ -1092,7 +1092,6 @@
|
||||
"Upload ID card front picture": "Upload ID card front picture",
|
||||
"Upload ID card with person picture": "Upload ID card with person picture",
|
||||
"Upload a photo": "Upload a photo",
|
||||
"Value": "Value",
|
||||
"Values": "Values",
|
||||
"Verification code sent": "Verification code sent",
|
||||
"WebAuthn credentials": "WebAuthn credentials",
|
||||
|
@@ -267,6 +267,7 @@
|
||||
"Models": "Models",
|
||||
"Name": "Name",
|
||||
"Name - Tooltip": "Unique, string-based ID",
|
||||
"Name format": "Name format",
|
||||
"Non-LDAP": "Non-LDAP",
|
||||
"None": "None",
|
||||
"OAuth providers": "OAuth providers",
|
||||
@@ -887,6 +888,7 @@
|
||||
"Please input your real name!": "Please input your real name!",
|
||||
"Please select your country code!": "Please select your country code!",
|
||||
"Please select your country/region!": "Please select your country/region!",
|
||||
"Regex": "Regex",
|
||||
"Terms of Use": "Terms of Use",
|
||||
"Terms of Use - Tooltip": "Terms of use that users need to read and agree to during registration",
|
||||
"Text 1": "Text 1",
|
||||
@@ -1053,8 +1055,6 @@
|
||||
"Managed accounts": "Managed accounts",
|
||||
"Modify password...": "Modify password...",
|
||||
"Multi-factor authentication": "Multi-factor authentication",
|
||||
"Name": "Name",
|
||||
"Name format": "Name format",
|
||||
"New Email": "New Email",
|
||||
"New Password": "New Password",
|
||||
"New User": "New User",
|
||||
@@ -1092,7 +1092,6 @@
|
||||
"Upload ID card front picture": "Upload ID card front picture",
|
||||
"Upload ID card with person picture": "Upload ID card with person picture",
|
||||
"Upload a photo": "Upload a photo",
|
||||
"Value": "Value",
|
||||
"Values": "Values",
|
||||
"Verification code sent": "Verification code sent",
|
||||
"WebAuthn credentials": "WebAuthn credentials",
|
||||
|
@@ -267,6 +267,7 @@
|
||||
"Models": "Mô hình",
|
||||
"Name": "Tên",
|
||||
"Name - Tooltip": "ID duy nhất dựa trên chuỗi",
|
||||
"Name format": "Name format",
|
||||
"Non-LDAP": "Non-LDAP",
|
||||
"None": "None",
|
||||
"OAuth providers": "Nhà cung cấp OAuth",
|
||||
@@ -887,6 +888,7 @@
|
||||
"Please input your real name!": "Vui lòng nhập tên thật của bạn!",
|
||||
"Please select your country code!": "Vui lòng chọn mã quốc gia của bạn!",
|
||||
"Please select your country/region!": "Vui lòng chọn quốc gia/vùng của bạn!",
|
||||
"Regex": "Regex",
|
||||
"Terms of Use": "Điều khoản sử dụng",
|
||||
"Terms of Use - Tooltip": "Điều khoản sử dụng mà người dùng cần đọc và đồng ý trong quá trình đăng ký",
|
||||
"Text 1": "Text 1",
|
||||
@@ -1053,8 +1055,6 @@
|
||||
"Managed accounts": "Quản lý tài khoản",
|
||||
"Modify password...": "Sửa đổi mật khẩu...",
|
||||
"Multi-factor authentication": "Multi-factor authentication",
|
||||
"Name": "Name",
|
||||
"Name format": "Name format",
|
||||
"New Email": "Email mới",
|
||||
"New Password": "Mật khẩu mới",
|
||||
"New User": "Người dùng mới",
|
||||
@@ -1092,7 +1092,6 @@
|
||||
"Upload ID card front picture": "Upload ID card front picture",
|
||||
"Upload ID card with person picture": "Upload ID card with person picture",
|
||||
"Upload a photo": "Tải lên một bức ảnh",
|
||||
"Value": "Value",
|
||||
"Values": "Giá trị",
|
||||
"Verification code sent": "Mã xác minh đã được gửi",
|
||||
"WebAuthn credentials": "Chứng chỉ WebAuthn",
|
||||
|
@@ -267,6 +267,7 @@
|
||||
"Models": "Casbin模型",
|
||||
"Name": "名称",
|
||||
"Name - Tooltip": "唯一的、字符串式的ID",
|
||||
"Name format": "名称格式",
|
||||
"Non-LDAP": "禁用LDAP",
|
||||
"None": "无",
|
||||
"OAuth providers": "OAuth提供方",
|
||||
@@ -887,6 +888,7 @@
|
||||
"Please input your real name!": "请输入您的姓名!",
|
||||
"Please select your country code!": "请选择国家代码!",
|
||||
"Please select your country/region!": "请选择您的国家或地区",
|
||||
"Regex": "正则表达式",
|
||||
"Terms of Use": "《用户协议》",
|
||||
"Terms of Use - Tooltip": "用户注册时需要阅读并同意的使用条款",
|
||||
"Text 1": "文本1",
|
||||
@@ -1053,8 +1055,6 @@
|
||||
"Managed accounts": "托管账户",
|
||||
"Modify password...": "编辑密码...",
|
||||
"Multi-factor authentication": "多因素认证",
|
||||
"Name": "Name",
|
||||
"Name format": "Name format",
|
||||
"New Email": "新邮箱",
|
||||
"New Password": "新密码",
|
||||
"New User": "添加用户",
|
||||
@@ -1092,7 +1092,6 @@
|
||||
"Upload ID card front picture": "上传身份证正面照片",
|
||||
"Upload ID card with person picture": "上传手持身份证照片",
|
||||
"Upload a photo": "上传头像",
|
||||
"Value": "值",
|
||||
"Values": "值",
|
||||
"Verification code sent": "验证码已发送",
|
||||
"WebAuthn credentials": "WebAuthn凭据",
|
||||
|
@@ -193,7 +193,7 @@ class ProviderTable extends React.Component {
|
||||
title: i18next.t("application:Rule"),
|
||||
dataIndex: "rule",
|
||||
key: "rule",
|
||||
width: "100px",
|
||||
width: "120px",
|
||||
render: (text, record, index) => {
|
||||
if (record.provider?.type === "Google") {
|
||||
if (text === "None") {
|
||||
|
@@ -38,7 +38,7 @@ class SamlAttributeTable extends React.Component {
|
||||
}
|
||||
|
||||
addRow(table) {
|
||||
const row = {Name: "", nameformat: "", value: ""};
|
||||
const row = {Name: "", nameFormat: "", value: ""};
|
||||
if (table === undefined || table === null) {
|
||||
table = [];
|
||||
}
|
||||
@@ -64,7 +64,7 @@ class SamlAttributeTable extends React.Component {
|
||||
renderTable(table) {
|
||||
const columns = [
|
||||
{
|
||||
title: i18next.t("user:Name"),
|
||||
title: i18next.t("general:Name"),
|
||||
dataIndex: "name",
|
||||
key: "name",
|
||||
width: "200px",
|
||||
@@ -77,9 +77,9 @@ class SamlAttributeTable extends React.Component {
|
||||
},
|
||||
},
|
||||
{
|
||||
title: i18next.t("user:Name format"),
|
||||
dataIndex: "nameformat",
|
||||
key: "nameformat",
|
||||
title: i18next.t("general:Name format"),
|
||||
dataIndex: "nameFormat",
|
||||
key: "nameFormat",
|
||||
width: "200px",
|
||||
render: (text, record, index) => {
|
||||
return (
|
||||
@@ -87,7 +87,7 @@ class SamlAttributeTable extends React.Component {
|
||||
value={text}
|
||||
defaultValue="urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified"
|
||||
onChange={value => {
|
||||
this.updateField(table, index, "nameformat", value);
|
||||
this.updateField(table, index, "nameFormat", value);
|
||||
}} >
|
||||
<Option key="Unspecified" value="urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified">Unspecified</Option>
|
||||
<Option key="Basic" value="urn:oasis:names:tc:SAML:2.0:attrname-format:basic">Basic</Option>
|
||||
@@ -98,7 +98,7 @@ class SamlAttributeTable extends React.Component {
|
||||
},
|
||||
},
|
||||
{
|
||||
title: i18next.t("user:Value"),
|
||||
title: i18next.t("webhook:Value"),
|
||||
dataIndex: "value",
|
||||
key: "value",
|
||||
width: "200px",
|
||||
|
@@ -20,7 +20,7 @@ import i18next from "i18next";
|
||||
|
||||
const {Option} = Select;
|
||||
|
||||
class SigninTable extends React.Component {
|
||||
class SigninMethodTable extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
@@ -163,7 +163,7 @@ class SigninTable extends React.Component {
|
||||
<Button style={{marginRight: "5px"}} disabled={index === table.length - 1} icon={<DownOutlined />} size="small" onClick={() => this.downRow(table, index)} />
|
||||
</Tooltip>
|
||||
<Tooltip placement="topLeft" title={i18next.t("general:Delete")}>
|
||||
<Button icon={<DeleteOutlined />} size="small" disabled={Setting.getDeduplicatedArray(items, table, "name").length >= items.length - 1} onClick={() => this.deleteRow(items, table, index)} />
|
||||
<Button icon={<DeleteOutlined />} size="small" disabled={table.length <= 1} onClick={() => this.deleteRow(items, table, index)} />
|
||||
</Tooltip>
|
||||
</div>
|
||||
);
|
||||
@@ -198,4 +198,4 @@ class SigninTable extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
export default SigninTable;
|
||||
export default SigninMethodTable;
|
@@ -224,6 +224,23 @@ class SignupTable extends React.Component {
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: i18next.t("signup:Regex"),
|
||||
dataIndex: "regex",
|
||||
key: "regex",
|
||||
width: "200px",
|
||||
render: (text, record, index) => {
|
||||
if (record.name.startsWith("Text ") || record.name === "Password" || record.name === "Confirm password") {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<Input value={text} onChange={e => {
|
||||
this.updateField(table, index, "regex", e.target.value);
|
||||
}} />
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: i18next.t("application:Rule"),
|
||||
dataIndex: "rule",
|
||||
|
Reference in New Issue
Block a user