mirror of
https://github.com/casdoor/casdoor.git
synced 2025-07-25 17:00:29 +08:00
Compare commits
28 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
fd5ccd8d41 | ||
![]() |
a439c5195d | ||
![]() |
ba2e997d54 | ||
![]() |
0818de85d1 | ||
![]() |
457c6098a4 | ||
![]() |
60f979fbb5 | ||
![]() |
ff53e44fa6 | ||
![]() |
1832de47db | ||
![]() |
535eb0c465 | ||
![]() |
c190634cf3 | ||
![]() |
f7559aa040 | ||
![]() |
1e0b709c73 | ||
![]() |
c0800b7fb3 | ||
![]() |
6fcdad2100 | ||
![]() |
69d26d5c21 | ||
![]() |
94e6b5ecb8 | ||
![]() |
95e8bdcd36 | ||
![]() |
6f1f93725e | ||
![]() |
7ae067e369 | ||
![]() |
dde936e935 | ||
![]() |
fb561a98c8 | ||
![]() |
7cd8f030ee | ||
![]() |
a3f8ded10c | ||
![]() |
e3d135bc6e | ||
![]() |
fc864b0de4 | ||
![]() |
3211bcc777 | ||
![]() |
9f4430ed04 | ||
![]() |
05830b9ff6 |
@@ -29,5 +29,6 @@ radiusServerPort = 1812
|
|||||||
radiusSecret = "secret"
|
radiusSecret = "secret"
|
||||||
quota = {"organization": -1, "user": -1, "application": -1, "provider": -1}
|
quota = {"organization": -1, "user": -1, "application": -1, "provider": -1}
|
||||||
logConfig = {"filename": "logs/casdoor.log", "maxdays":99999, "perm":"0770"}
|
logConfig = {"filename": "logs/casdoor.log", "maxdays":99999, "perm":"0770"}
|
||||||
|
initDataNewOnly = false
|
||||||
initDataFile = "./init_data.json"
|
initDataFile = "./init_data.json"
|
||||||
frontendBaseDir = "../casdoor"
|
frontendBaseDir = "../cc_0"
|
@@ -116,6 +116,13 @@ func (c *ApiController) Signup() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
clientIp := util.GetClientIpFromRequest(c.Ctx.Request)
|
||||||
|
err = object.CheckEntryIp(clientIp, nil, application, organization, c.GetAcceptLanguage())
|
||||||
|
if err != nil {
|
||||||
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
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)
|
||||||
|
@@ -110,6 +110,9 @@ func (c *ApiController) GetApplication() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
clientIp := util.GetClientIpFromRequest(c.Ctx.Request)
|
||||||
|
object.CheckEntryIp(clientIp, nil, application, nil, c.GetAcceptLanguage())
|
||||||
|
|
||||||
c.ResponseOk(object.GetMaskedApplication(application, userId))
|
c.ResponseOk(object.GetMaskedApplication(application, userId))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -229,6 +232,11 @@ func (c *ApiController) UpdateApplication() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err = object.CheckIpWhitelist(application.IpWhitelist, c.GetAcceptLanguage()); err != nil {
|
||||||
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
c.Data["json"] = wrapActionResponse(object.UpdateApplication(id, &application))
|
c.Data["json"] = wrapActionResponse(object.UpdateApplication(id, &application))
|
||||||
c.ServeJSON()
|
c.ServeJSON()
|
||||||
}
|
}
|
||||||
@@ -259,6 +267,11 @@ func (c *ApiController) AddApplication() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err = object.CheckIpWhitelist(application.IpWhitelist, c.GetAcceptLanguage()); err != nil {
|
||||||
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
c.Data["json"] = wrapActionResponse(object.AddApplication(&application))
|
c.Data["json"] = wrapActionResponse(object.AddApplication(&application))
|
||||||
c.ServeJSON()
|
c.ServeJSON()
|
||||||
}
|
}
|
||||||
|
@@ -55,6 +55,13 @@ func tokenToResponse(token *object.Token) *Response {
|
|||||||
func (c *ApiController) HandleLoggedIn(application *object.Application, user *object.User, form *form.AuthForm) (resp *Response) {
|
func (c *ApiController) HandleLoggedIn(application *object.Application, user *object.User, form *form.AuthForm) (resp *Response) {
|
||||||
userId := user.GetId()
|
userId := user.GetId()
|
||||||
|
|
||||||
|
clientIp := util.GetClientIpFromRequest(c.Ctx.Request)
|
||||||
|
err := object.CheckEntryIp(clientIp, user, application, application.OrganizationObj, c.GetAcceptLanguage())
|
||||||
|
if err != nil {
|
||||||
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
allowed, err := object.CheckLoginPermission(userId, application)
|
allowed, err := object.CheckLoginPermission(userId, application)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.ResponseError(err.Error(), nil)
|
c.ResponseError(err.Error(), nil)
|
||||||
@@ -256,6 +263,9 @@ func (c *ApiController) GetApplicationLogin() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
clientIp := util.GetClientIpFromRequest(c.Ctx.Request)
|
||||||
|
object.CheckEntryIp(clientIp, nil, application, nil, c.GetAcceptLanguage())
|
||||||
|
|
||||||
application = object.GetMaskedApplication(application, "")
|
application = object.GetMaskedApplication(application, "")
|
||||||
if msg != "" {
|
if msg != "" {
|
||||||
c.ResponseError(msg, application)
|
c.ResponseError(msg, application)
|
||||||
@@ -844,6 +854,7 @@ func (c *ApiController) Login() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if authForm.Passcode != "" {
|
if authForm.Passcode != "" {
|
||||||
|
user.CountryCode = user.GetCountryCode(user.CountryCode)
|
||||||
mfaUtil := object.GetMfaUtil(authForm.MfaType, user.GetPreferredMfaProps(false))
|
mfaUtil := object.GetMfaUtil(authForm.MfaType, user.GetPreferredMfaProps(false))
|
||||||
if mfaUtil == nil {
|
if mfaUtil == nil {
|
||||||
c.ResponseError("Invalid multi-factor authentication type")
|
c.ResponseError("Invalid multi-factor authentication type")
|
||||||
|
@@ -119,6 +119,11 @@ func (c *ApiController) UpdateOrganization() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err = object.CheckIpWhitelist(organization.IpWhitelist, c.GetAcceptLanguage()); err != nil {
|
||||||
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
c.Data["json"] = wrapActionResponse(object.UpdateOrganization(id, &organization))
|
c.Data["json"] = wrapActionResponse(object.UpdateOrganization(id, &organization))
|
||||||
c.ServeJSON()
|
c.ServeJSON()
|
||||||
}
|
}
|
||||||
@@ -149,6 +154,11 @@ func (c *ApiController) AddOrganization() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err = object.CheckIpWhitelist(organization.IpWhitelist, c.GetAcceptLanguage()); err != nil {
|
||||||
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
c.Data["json"] = wrapActionResponse(object.AddOrganization(&organization))
|
c.Data["json"] = wrapActionResponse(object.AddOrganization(&organization))
|
||||||
c.ServeJSON()
|
c.ServeJSON()
|
||||||
}
|
}
|
||||||
|
@@ -182,6 +182,10 @@ func (c *ApiController) BuyProduct() {
|
|||||||
paidUserName := c.Input().Get("userName")
|
paidUserName := c.Input().Get("userName")
|
||||||
owner, _ := util.GetOwnerAndNameFromId(id)
|
owner, _ := util.GetOwnerAndNameFromId(id)
|
||||||
userId := util.GetId(owner, paidUserName)
|
userId := util.GetId(owner, paidUserName)
|
||||||
|
if paidUserName != "" && !c.IsAdmin() {
|
||||||
|
c.ResponseError(c.T("general:Only admin user can specify user"))
|
||||||
|
return
|
||||||
|
}
|
||||||
if paidUserName == "" {
|
if paidUserName == "" {
|
||||||
userId = c.GetSessionUsername()
|
userId = c.GetSessionUsername()
|
||||||
}
|
}
|
||||||
|
@@ -364,7 +364,8 @@ func (c *ApiController) AddUser() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
msg := object.CheckUsername(user.Name, c.GetAcceptLanguage())
|
emptyUser := object.User{}
|
||||||
|
msg := object.CheckUpdateUser(&emptyUser, &user, c.GetAcceptLanguage())
|
||||||
if msg != "" {
|
if msg != "" {
|
||||||
c.ResponseError(msg)
|
c.ResponseError(msg)
|
||||||
return
|
return
|
||||||
@@ -489,7 +490,12 @@ func (c *ApiController) SetPassword() {
|
|||||||
c.ResponseError(c.T("general:Missing parameter"))
|
c.ResponseError(c.T("general:Missing parameter"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if userId != c.GetSession("verifiedUserId") {
|
||||||
|
c.ResponseError(c.T("general:Wrong userId"))
|
||||||
|
return
|
||||||
|
}
|
||||||
c.SetSession("verifiedCode", "")
|
c.SetSession("verifiedCode", "")
|
||||||
|
c.SetSession("verifiedUserId", "")
|
||||||
}
|
}
|
||||||
|
|
||||||
targetUser, err := object.GetUser(userId)
|
targetUser, err := object.GetUser(userId)
|
||||||
@@ -535,6 +541,23 @@ func (c *ApiController) SetPassword() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
application, err := object.GetApplicationByUser(targetUser)
|
||||||
|
if err != nil {
|
||||||
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if application == nil {
|
||||||
|
c.ResponseError(fmt.Sprintf(c.T("auth:the application for user %s is not found"), userId))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
clientIp := util.GetClientIpFromRequest(c.Ctx.Request)
|
||||||
|
err = object.CheckEntryIp(clientIp, targetUser, application, organization, c.GetAcceptLanguage())
|
||||||
|
if err != nil {
|
||||||
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
targetUser.Password = newPassword
|
targetUser.Password = newPassword
|
||||||
targetUser.UpdateUserPassword(organization)
|
targetUser.UpdateUserPassword(organization)
|
||||||
targetUser.NeedUpdatePassword = false
|
targetUser.NeedUpdatePassword = false
|
||||||
|
@@ -132,7 +132,8 @@ func (c *ApiController) SendVerificationCode() {
|
|||||||
c.ResponseError(err.Error())
|
c.ResponseError(err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
remoteAddr := util.GetIPFromRequest(c.Ctx.Request)
|
|
||||||
|
clientIp := util.GetClientIpFromRequest(c.Ctx.Request)
|
||||||
|
|
||||||
if msg := vform.CheckParameter(form.SendVerifyCode, c.GetAcceptLanguage()); msg != "" {
|
if msg := vform.CheckParameter(form.SendVerifyCode, c.GetAcceptLanguage()); msg != "" {
|
||||||
c.ResponseError(msg)
|
c.ResponseError(msg)
|
||||||
@@ -259,7 +260,7 @@ func (c *ApiController) SendVerificationCode() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
sendResp = object.SendVerificationCodeToEmail(organization, user, provider, remoteAddr, vform.Dest)
|
sendResp = object.SendVerificationCodeToEmail(organization, user, provider, clientIp, vform.Dest)
|
||||||
case object.VerifyTypePhone:
|
case object.VerifyTypePhone:
|
||||||
if vform.Method == LoginVerification || vform.Method == ForgetVerification {
|
if vform.Method == LoginVerification || vform.Method == ForgetVerification {
|
||||||
if user != nil && util.GetMaskedPhone(user.Phone) == vform.Dest {
|
if user != nil && util.GetMaskedPhone(user.Phone) == vform.Dest {
|
||||||
@@ -293,6 +294,7 @@ func (c *ApiController) SendVerificationCode() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
vform.CountryCode = mfaProps.CountryCode
|
vform.CountryCode = mfaProps.CountryCode
|
||||||
|
vform.CountryCode = user.GetCountryCode(vform.CountryCode)
|
||||||
}
|
}
|
||||||
|
|
||||||
provider, err = application.GetSmsProvider(vform.Method, vform.CountryCode)
|
provider, err = application.GetSmsProvider(vform.Method, vform.CountryCode)
|
||||||
@@ -309,7 +311,7 @@ func (c *ApiController) SendVerificationCode() {
|
|||||||
c.ResponseError(fmt.Sprintf(c.T("verification:Phone number is invalid in your region %s"), vform.CountryCode))
|
c.ResponseError(fmt.Sprintf(c.T("verification:Phone number is invalid in your region %s"), vform.CountryCode))
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
sendResp = object.SendVerificationCodeToPhone(organization, user, provider, remoteAddr, phone)
|
sendResp = object.SendVerificationCodeToPhone(organization, user, provider, clientIp, phone)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -532,5 +534,6 @@ func (c *ApiController) VerifyCode() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
c.SetSession("verifiedCode", authForm.Code)
|
c.SetSession("verifiedCode", authForm.Code)
|
||||||
|
c.SetSession("verifiedUserId", user.GetId())
|
||||||
c.ResponseOk()
|
c.ResponseOk()
|
||||||
}
|
}
|
||||||
|
2
go.mod
2
go.mod
@@ -11,6 +11,7 @@ require (
|
|||||||
github.com/casbin/casbin/v2 v2.77.2
|
github.com/casbin/casbin/v2 v2.77.2
|
||||||
github.com/casdoor/go-sms-sender v0.24.0
|
github.com/casdoor/go-sms-sender v0.24.0
|
||||||
github.com/casdoor/gomail/v2 v2.0.1
|
github.com/casdoor/gomail/v2 v2.0.1
|
||||||
|
github.com/casdoor/ldapserver v1.2.0
|
||||||
github.com/casdoor/notify v0.45.0
|
github.com/casdoor/notify v0.45.0
|
||||||
github.com/casdoor/oss v1.8.0
|
github.com/casdoor/oss v1.8.0
|
||||||
github.com/casdoor/xorm-adapter/v3 v3.1.0
|
github.com/casdoor/xorm-adapter/v3 v3.1.0
|
||||||
@@ -20,7 +21,6 @@ require (
|
|||||||
github.com/elazarl/go-bindata-assetfs v1.0.1 // indirect
|
github.com/elazarl/go-bindata-assetfs v1.0.1 // indirect
|
||||||
github.com/elimity-com/scim v0.0.0-20230426070224-941a5eac92f3
|
github.com/elimity-com/scim v0.0.0-20230426070224-941a5eac92f3
|
||||||
github.com/fogleman/gg v1.3.0
|
github.com/fogleman/gg v1.3.0
|
||||||
github.com/forestmgy/ldapserver v1.1.0
|
|
||||||
github.com/go-asn1-ber/asn1-ber v1.5.5
|
github.com/go-asn1-ber/asn1-ber v1.5.5
|
||||||
github.com/go-git/go-git/v5 v5.11.0
|
github.com/go-git/go-git/v5 v5.11.0
|
||||||
github.com/go-ldap/ldap/v3 v3.4.6
|
github.com/go-ldap/ldap/v3 v3.4.6
|
||||||
|
4
go.sum
4
go.sum
@@ -1091,6 +1091,8 @@ github.com/casdoor/go-sms-sender v0.24.0 h1:LNLsce3EG/87I3JS6UiajF3LlQmdIiCgebEu
|
|||||||
github.com/casdoor/go-sms-sender v0.24.0/go.mod h1:bOm4H8/YfJmEHjBatEVQFOnAf0OOn1B0Wi5B7zDhws0=
|
github.com/casdoor/go-sms-sender v0.24.0/go.mod h1:bOm4H8/YfJmEHjBatEVQFOnAf0OOn1B0Wi5B7zDhws0=
|
||||||
github.com/casdoor/gomail/v2 v2.0.1 h1:J+FG6x80s9e5lBHUn8Sv0Y56mud34KiWih5YdmudR/w=
|
github.com/casdoor/gomail/v2 v2.0.1 h1:J+FG6x80s9e5lBHUn8Sv0Y56mud34KiWih5YdmudR/w=
|
||||||
github.com/casdoor/gomail/v2 v2.0.1/go.mod h1:VnGPslEAtpix5FjHisR/WKB1qvZDBaujbikxDe9d+2Q=
|
github.com/casdoor/gomail/v2 v2.0.1/go.mod h1:VnGPslEAtpix5FjHisR/WKB1qvZDBaujbikxDe9d+2Q=
|
||||||
|
github.com/casdoor/ldapserver v1.2.0 h1:HdSYe+ULU6z9K+2BqgTrJKQRR4//ERAXB64ttOun6Ow=
|
||||||
|
github.com/casdoor/ldapserver v1.2.0/go.mod h1:VwYU2vqQ2pA8sa00PRekH71R2XmgfzMKhmp1XrrDu2s=
|
||||||
github.com/casdoor/notify v0.45.0 h1:OlaFvcQFjGOgA4mRx07M8AH1gvb5xNo21mcqrVGlLgk=
|
github.com/casdoor/notify v0.45.0 h1:OlaFvcQFjGOgA4mRx07M8AH1gvb5xNo21mcqrVGlLgk=
|
||||||
github.com/casdoor/notify v0.45.0/go.mod h1:wNHQu0tiDROMBIvz0j3Om3Lhd5yZ+AIfnFb8MYb8OLQ=
|
github.com/casdoor/notify v0.45.0/go.mod h1:wNHQu0tiDROMBIvz0j3Om3Lhd5yZ+AIfnFb8MYb8OLQ=
|
||||||
github.com/casdoor/oss v1.8.0 h1:uuyKhDIp7ydOtV4lpqhAY23Ban2Ln8La8+QT36CwylM=
|
github.com/casdoor/oss v1.8.0 h1:uuyKhDIp7ydOtV4lpqhAY23Ban2Ln8La8+QT36CwylM=
|
||||||
@@ -1237,8 +1239,6 @@ github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga
|
|||||||
github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k=
|
github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k=
|
||||||
github.com/fogleman/gg v1.3.0 h1:/7zJX8F6AaYQc57WQCyN9cAIz+4bCJGO9B+dyW29am8=
|
github.com/fogleman/gg v1.3.0 h1:/7zJX8F6AaYQc57WQCyN9cAIz+4bCJGO9B+dyW29am8=
|
||||||
github.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k=
|
github.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k=
|
||||||
github.com/forestmgy/ldapserver v1.1.0 h1:gvil4nuLhqPEL8SugCkFhRyA0/lIvRdwZSqlrw63ll4=
|
|
||||||
github.com/forestmgy/ldapserver v1.1.0/go.mod h1:1RZ8lox1QSY7rmbjdmy+sYQXY4Lp7SpGzpdE3+j3IyM=
|
|
||||||
github.com/form3tech-oss/jwt-go v3.2.2+incompatible h1:TcekIExNqud5crz4xD2pavyTgWiPvpYe4Xau31I0PRk=
|
github.com/form3tech-oss/jwt-go v3.2.2+incompatible h1:TcekIExNqud5crz4xD2pavyTgWiPvpYe4Xau31I0PRk=
|
||||||
github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
|
github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
|
||||||
github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=
|
github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=
|
||||||
|
@@ -15,10 +15,10 @@
|
|||||||
"The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support": "Аккаунт для провайдера: %s и имя пользователя: %s (%s) не существует и не может быть зарегистрирован как новый аккаунт. Пожалуйста, обратитесь в службу поддержки IT",
|
"The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support": "Аккаунт для провайдера: %s и имя пользователя: %s (%s) не существует и не может быть зарегистрирован как новый аккаунт. Пожалуйста, обратитесь в службу поддержки IT",
|
||||||
"The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)": "Аккаунт поставщика: %s и имя пользователя: %s (%s) уже связаны с другим аккаунтом: %s (%s)",
|
"The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)": "Аккаунт поставщика: %s и имя пользователя: %s (%s) уже связаны с другим аккаунтом: %s (%s)",
|
||||||
"The application: %s does not exist": "Приложение: %s не существует",
|
"The application: %s does not exist": "Приложение: %s не существует",
|
||||||
"The login method: login with LDAP is not enabled for the application": "The login method: login with LDAP is not enabled for the application",
|
"The login method: login with LDAP is not enabled for the application": "Метод входа в систему: вход с помощью LDAP не включен для приложения",
|
||||||
"The login method: login with SMS is not enabled for the application": "The login method: login with SMS is not enabled for the application",
|
"The login method: login with SMS is not enabled for the application": "Метод входа: вход с помощью SMS не включен для приложения",
|
||||||
"The login method: login with email is not enabled for the application": "The login method: login with email is not enabled for the application",
|
"The login method: login with email is not enabled for the application": "Метод входа: вход с помощью электронной почты не включен для приложения",
|
||||||
"The login method: login with face is not enabled for the application": "The login method: login with face is not enabled for the application",
|
"The login method: login with face is not enabled for the application": "Метод входа: вход с помощью лица не включен для приложения",
|
||||||
"The login method: login with password is not enabled for the application": "Метод входа: вход с паролем не включен для приложения",
|
"The login method: login with password is not enabled for the application": "Метод входа: вход с паролем не включен для приложения",
|
||||||
"The organization: %s does not exist": "The organization: %s does not exist",
|
"The organization: %s does not exist": "The organization: %s does not exist",
|
||||||
"The provider: %s is not enabled for the application": "Провайдер: %s не включен для приложения",
|
"The provider: %s is not enabled for the application": "Провайдер: %s не включен для приложения",
|
||||||
@@ -53,16 +53,16 @@
|
|||||||
"Phone already exists": "Телефон уже существует",
|
"Phone already exists": "Телефон уже существует",
|
||||||
"Phone cannot be empty": "Телефон не может быть пустым",
|
"Phone cannot be empty": "Телефон не может быть пустым",
|
||||||
"Phone number is invalid": "Номер телефона является недействительным",
|
"Phone number is invalid": "Номер телефона является недействительным",
|
||||||
"Please register using the email corresponding to the invitation code": "Please register using the email corresponding to the invitation code",
|
"Please register using the email corresponding to the invitation code": "Пожалуйста, зарегистрируйтесь, используя электронную почту, соответствующую коду приглашения",
|
||||||
"Please register using the phone corresponding to the invitation code": "Please register using the phone corresponding to the invitation code",
|
"Please register using the phone corresponding to the invitation code": "Пожалуйста, зарегистрируйтесь по телефону, соответствующему коду приглашения",
|
||||||
"Please register using the username corresponding to the invitation code": "Please register using the username corresponding to the invitation code",
|
"Please register using the username corresponding to the invitation code": "Пожалуйста, зарегистрируйтесь, используя имя пользователя, соответствующее коду приглашения",
|
||||||
"Session outdated, please login again": "Сессия устарела, пожалуйста, войдите снова",
|
"Session outdated, please login again": "Сессия устарела, пожалуйста, войдите снова",
|
||||||
"The invitation code has already been used": "The invitation code has already been used",
|
"The invitation code has already been used": "The invitation code has already been used",
|
||||||
"The user is forbidden to sign in, please contact the administrator": "Пользователю запрещен вход, пожалуйста, обратитесь к администратору",
|
"The user is forbidden to sign in, please contact the administrator": "Пользователю запрещен вход, пожалуйста, обратитесь к администратору",
|
||||||
"The user: %s doesn't exist in LDAP server": "Пользователь %s не существует на LDAP сервере",
|
"The user: %s doesn't exist in LDAP server": "Пользователь %s не существует на LDAP сервере",
|
||||||
"The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline.": "Имя пользователя может состоять только из буквенно-цифровых символов, нижних подчеркиваний или дефисов, не может содержать последовательные дефисы или подчеркивания, а также не может начинаться или заканчиваться на дефис или подчеркивание.",
|
"The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline.": "Имя пользователя может состоять только из буквенно-цифровых символов, нижних подчеркиваний или дефисов, не может содержать последовательные дефисы или подчеркивания, а также не может начинаться или заканчиваться на дефис или подчеркивание.",
|
||||||
"The value \\\"%s\\\" for account field \\\"%s\\\" doesn't match the account item regex": "The value \\\"%s\\\" for account field \\\"%s\\\" doesn't match the account item regex",
|
"The value \\\"%s\\\" for account field \\\"%s\\\" doesn't match the account item regex": "Значение \\\"%s\\\" для поля аккаунта \\\"%s\\\" не соответствует регулярному значению",
|
||||||
"The value \\\"%s\\\" for signup field \\\"%s\\\" doesn't match the signup item regex of the application \\\"%s\\\"": "The value \\\"%s\\\" for signup field \\\"%s\\\" doesn't match the signup item regex of the application \\\"%s\\\"",
|
"The value \\\"%s\\\" for signup field \\\"%s\\\" doesn't match the signup item regex of the application \\\"%s\\\"": "Значение \\\"%s\\\" поля регистрации \\\"%s\\\" не соответствует регулярному выражению приложения \\\"%s\\\"",
|
||||||
"Username already exists": "Имя пользователя уже существует",
|
"Username already exists": "Имя пользователя уже существует",
|
||||||
"Username cannot be an email address": "Имя пользователя не может быть адресом электронной почты",
|
"Username cannot be an email address": "Имя пользователя не может быть адресом электронной почты",
|
||||||
"Username cannot contain white spaces": "Имя пользователя не может содержать пробелы",
|
"Username cannot contain white spaces": "Имя пользователя не может содержать пробелы",
|
||||||
@@ -78,11 +78,11 @@
|
|||||||
"general": {
|
"general": {
|
||||||
"Missing parameter": "Отсутствующий параметр",
|
"Missing parameter": "Отсутствующий параметр",
|
||||||
"Please login first": "Пожалуйста, сначала войдите в систему",
|
"Please login first": "Пожалуйста, сначала войдите в систему",
|
||||||
"The organization: %s should have one application at least": "The organization: %s should have one application at least",
|
"The organization: %s should have one application at least": "Организация: %s должна иметь хотя бы одно приложение",
|
||||||
"The user: %s doesn't exist": "Пользователь %s не существует",
|
"The user: %s doesn't exist": "Пользователь %s не существует",
|
||||||
"don't support captchaProvider: ": "неподдерживаемый captchaProvider: ",
|
"don't support captchaProvider: ": "неподдерживаемый captchaProvider: ",
|
||||||
"this operation is not allowed in demo mode": "эта операция не разрешена в демо-режиме",
|
"this operation is not allowed in demo mode": "эта операция не разрешена в демо-режиме",
|
||||||
"this operation requires administrator to perform": "this operation requires administrator to perform"
|
"this operation requires administrator to perform": "для выполнения этой операции требуется администратор"
|
||||||
},
|
},
|
||||||
"ldap": {
|
"ldap": {
|
||||||
"Ldap server exist": "LDAP-сервер существует"
|
"Ldap server exist": "LDAP-сервер существует"
|
||||||
@@ -101,11 +101,11 @@
|
|||||||
"Unknown modify rule %s.": "Неизвестное изменение правила %s."
|
"Unknown modify rule %s.": "Неизвестное изменение правила %s."
|
||||||
},
|
},
|
||||||
"permission": {
|
"permission": {
|
||||||
"The permission: \\\"%s\\\" doesn't exist": "The permission: \\\"%s\\\" doesn't exist"
|
"The permission: \\\"%s\\\" doesn't exist": "Разрешение: \\\"%s\\\" не существует"
|
||||||
},
|
},
|
||||||
"provider": {
|
"provider": {
|
||||||
"Invalid application id": "Неверный идентификатор приложения",
|
"Invalid application id": "Неверный идентификатор приложения",
|
||||||
"the provider: %s does not exist": "провайдер: %s не существует"
|
"the provider: %s does not exist": "Провайдер: %s не существует"
|
||||||
},
|
},
|
||||||
"resource": {
|
"resource": {
|
||||||
"User is nil for tag: avatar": "Пользователь равен нулю для тега: аватар",
|
"User is nil for tag: avatar": "Пользователь равен нулю для тега: аватар",
|
||||||
@@ -115,7 +115,7 @@
|
|||||||
"Application %s not found": "Приложение %s не найдено"
|
"Application %s not found": "Приложение %s не найдено"
|
||||||
},
|
},
|
||||||
"saml_sp": {
|
"saml_sp": {
|
||||||
"provider %s's category is not SAML": "категория провайдера %s не является SAML"
|
"provider %s's category is not SAML": "Категория провайдера %s не является SAML"
|
||||||
},
|
},
|
||||||
"service": {
|
"service": {
|
||||||
"Empty parameters for emailForm: %v": "Пустые параметры для emailForm: %v",
|
"Empty parameters for emailForm: %v": "Пустые параметры для emailForm: %v",
|
||||||
@@ -148,7 +148,7 @@
|
|||||||
"verification": {
|
"verification": {
|
||||||
"Invalid captcha provider.": "Недействительный поставщик CAPTCHA.",
|
"Invalid captcha provider.": "Недействительный поставщик CAPTCHA.",
|
||||||
"Phone number is invalid in your region %s": "Номер телефона недействителен в вашем регионе %s",
|
"Phone number is invalid in your region %s": "Номер телефона недействителен в вашем регионе %s",
|
||||||
"The verification code has not been sent yet!": "The verification code has not been sent yet!",
|
"The verification code has not been sent yet!": "Код проверки еще не отправлен!",
|
||||||
"The verification code has not been sent yet, or has already been used!": "The verification code has not been sent yet, or has already been used!",
|
"The verification code has not been sent yet, or has already been used!": "The verification code has not been sent yet, or has already been used!",
|
||||||
"Turing test failed.": "Тест Тьюринга не удался.",
|
"Turing test failed.": "Тест Тьюринга не удался.",
|
||||||
"Unable to get the email modify rule.": "Невозможно получить правило изменения электронной почты.",
|
"Unable to get the email modify rule.": "Невозможно получить правило изменения электронной почты.",
|
||||||
@@ -156,8 +156,8 @@
|
|||||||
"Unknown type": "Неизвестный тип",
|
"Unknown type": "Неизвестный тип",
|
||||||
"Wrong verification code!": "Неправильный код подтверждения!",
|
"Wrong verification code!": "Неправильный код подтверждения!",
|
||||||
"You should verify your code in %d min!": "Вы должны проверить свой код через %d минут!",
|
"You should verify your code in %d min!": "Вы должны проверить свой код через %d минут!",
|
||||||
"please add a SMS provider to the \\\"Providers\\\" list for the application: %s": "please add a SMS provider to the \\\"Providers\\\" list for the application: %s",
|
"please add a SMS provider to the \\\"Providers\\\" list for the application: %s": "Пожалуйста, добавьте поставщика SMS в список \\\"Провайдеры\\\" для приложения: %s",
|
||||||
"please add an Email provider to the \\\"Providers\\\" list for the application: %s": "please add an Email provider to the \\\"Providers\\\" list for the application: %s",
|
"please add an Email provider to the \\\"Providers\\\" list for the application: %s": "Пожалуйста, добавьте поставщика электронной почты в список \\\"Провайдеры\\\" для приложения: %s",
|
||||||
"the user does not exist, please sign up first": "Пользователь не существует, пожалуйста, сначала зарегистрируйтесь"
|
"the user does not exist, please sign up first": "Пользователь не существует, пожалуйста, сначала зарегистрируйтесь"
|
||||||
},
|
},
|
||||||
"webauthn": {
|
"webauthn": {
|
||||||
|
@@ -21,7 +21,7 @@ import (
|
|||||||
|
|
||||||
"github.com/casdoor/casdoor/conf"
|
"github.com/casdoor/casdoor/conf"
|
||||||
"github.com/casdoor/casdoor/object"
|
"github.com/casdoor/casdoor/object"
|
||||||
ldap "github.com/forestmgy/ldapserver"
|
ldap "github.com/casdoor/ldapserver"
|
||||||
"github.com/lor00x/goldap/message"
|
"github.com/lor00x/goldap/message"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@@ -23,7 +23,7 @@ import (
|
|||||||
"github.com/casdoor/casdoor/util"
|
"github.com/casdoor/casdoor/util"
|
||||||
"github.com/lor00x/goldap/message"
|
"github.com/lor00x/goldap/message"
|
||||||
|
|
||||||
ldap "github.com/forestmgy/ldapserver"
|
ldap "github.com/casdoor/ldapserver"
|
||||||
|
|
||||||
"github.com/xorm-io/builder"
|
"github.com/xorm-io/builder"
|
||||||
)
|
)
|
||||||
|
@@ -95,6 +95,7 @@ type Application struct {
|
|||||||
Tags []string `xorm:"mediumtext" json:"tags"`
|
Tags []string `xorm:"mediumtext" json:"tags"`
|
||||||
SamlAttributes []*SamlItem `xorm:"varchar(1000)" json:"samlAttributes"`
|
SamlAttributes []*SamlItem `xorm:"varchar(1000)" json:"samlAttributes"`
|
||||||
IsShared bool `json:"isShared"`
|
IsShared bool `json:"isShared"`
|
||||||
|
IpRestriction string `json:"ipRestriction"`
|
||||||
|
|
||||||
ClientId string `xorm:"varchar(100)" json:"clientId"`
|
ClientId string `xorm:"varchar(100)" json:"clientId"`
|
||||||
ClientSecret string `xorm:"varchar(100)" json:"clientSecret"`
|
ClientSecret string `xorm:"varchar(100)" json:"clientSecret"`
|
||||||
@@ -108,6 +109,7 @@ type Application struct {
|
|||||||
SigninUrl string `xorm:"varchar(200)" json:"signinUrl"`
|
SigninUrl string `xorm:"varchar(200)" json:"signinUrl"`
|
||||||
ForgetUrl string `xorm:"varchar(200)" json:"forgetUrl"`
|
ForgetUrl string `xorm:"varchar(200)" json:"forgetUrl"`
|
||||||
AffiliationUrl string `xorm:"varchar(100)" json:"affiliationUrl"`
|
AffiliationUrl string `xorm:"varchar(100)" json:"affiliationUrl"`
|
||||||
|
IpWhitelist string `xorm:"varchar(200)" json:"ipWhitelist"`
|
||||||
TermsOfUse string `xorm:"varchar(100)" json:"termsOfUse"`
|
TermsOfUse string `xorm:"varchar(100)" json:"termsOfUse"`
|
||||||
SignupHtml string `xorm:"mediumtext" json:"signupHtml"`
|
SignupHtml string `xorm:"mediumtext" json:"signupHtml"`
|
||||||
SigninHtml string `xorm:"mediumtext" json:"signinHtml"`
|
SigninHtml string `xorm:"mediumtext" json:"signinHtml"`
|
||||||
@@ -721,8 +723,15 @@ func (application *Application) GetId() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (application *Application) IsRedirectUriValid(redirectUri string) bool {
|
func (application *Application) IsRedirectUriValid(redirectUri string) bool {
|
||||||
redirectUris := append([]string{"http://localhost:", "https://localhost:", "http://127.0.0.1:", "http://casdoor-app", ".chromiumapp.org"}, application.RedirectUris...)
|
isValid, err := util.IsValidOrigin(redirectUri)
|
||||||
for _, targetUri := range redirectUris {
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
if isValid {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, targetUri := range application.RedirectUris {
|
||||||
targetUriRegex := regexp.MustCompile(targetUri)
|
targetUriRegex := regexp.MustCompile(targetUri)
|
||||||
if targetUriRegex.MatchString(redirectUri) || strings.Contains(redirectUri, targetUri) {
|
if targetUriRegex.MatchString(redirectUri) || strings.Contains(redirectUri, targetUri) {
|
||||||
return true
|
return true
|
||||||
|
@@ -520,11 +520,46 @@ func CheckUsername(username string, lang string) string {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func CheckUsernameWithEmail(username string, lang string) string {
|
||||||
|
if username == "" {
|
||||||
|
return i18n.Translate(lang, "check:Empty username.")
|
||||||
|
} else if len(username) > 39 {
|
||||||
|
return i18n.Translate(lang, "check:Username is too long (maximum is 39 characters).")
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://stackoverflow.com/questions/58726546/github-username-convention-using-regex
|
||||||
|
|
||||||
|
if !util.ReUserNameWithEmail.MatchString(username) {
|
||||||
|
return i18n.Translate(lang, "check:Username supports email format. Also The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline. Also pay attention to the email format.")
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
func CheckUpdateUser(oldUser, user *User, lang string) string {
|
func CheckUpdateUser(oldUser, user *User, lang string) string {
|
||||||
if oldUser.Name != user.Name {
|
if oldUser.Name != user.Name {
|
||||||
if msg := CheckUsername(user.Name, lang); msg != "" {
|
organizationName := oldUser.Owner
|
||||||
return msg
|
if organizationName == "" {
|
||||||
|
organizationName = user.Owner
|
||||||
}
|
}
|
||||||
|
|
||||||
|
organization, err := getOrganization("admin", organizationName)
|
||||||
|
if err != nil {
|
||||||
|
return err.Error()
|
||||||
|
}
|
||||||
|
if organization == nil {
|
||||||
|
return fmt.Sprintf(i18n.Translate(lang, "auth:The organization: %s does not exist"), organizationName)
|
||||||
|
}
|
||||||
|
|
||||||
|
if organization.UseEmailAsUsername {
|
||||||
|
if msg := CheckUsernameWithEmail(user.Name, lang); msg != "" {
|
||||||
|
return msg
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if msg := CheckUsername(user.Name, lang); msg != "" {
|
||||||
|
return msg
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if HasUserByField(user.Owner, "name", user.Name) {
|
if HasUserByField(user.Owner, "name", user.Name) {
|
||||||
return i18n.Translate(lang, "check:Username already exists")
|
return i18n.Translate(lang, "check:Username already exists")
|
||||||
}
|
}
|
||||||
@@ -539,6 +574,11 @@ func CheckUpdateUser(oldUser, user *User, lang string) string {
|
|||||||
return i18n.Translate(lang, "check:Phone already exists")
|
return i18n.Translate(lang, "check:Phone already exists")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if oldUser.IpWhitelist != user.IpWhitelist {
|
||||||
|
if err := CheckIpWhitelist(user.IpWhitelist, lang); err != nil {
|
||||||
|
return err.Error()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
104
object/check_ip.go
Normal file
104
object/check_ip.go
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
// Copyright 2024 The Casdoor Authors. All Rights Reserved.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package object
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/casdoor/casdoor/i18n"
|
||||||
|
)
|
||||||
|
|
||||||
|
func CheckEntryIp(clientIp string, user *User, application *Application, organization *Organization, lang string) error {
|
||||||
|
entryIp := net.ParseIP(clientIp)
|
||||||
|
if entryIp == nil {
|
||||||
|
return fmt.Errorf(i18n.Translate(lang, "check:Failed to parse client IP: %s"), clientIp)
|
||||||
|
} else if entryIp.IsLoopback() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var err error
|
||||||
|
if user != nil {
|
||||||
|
err = isEntryIpAllowd(user.IpWhitelist, entryIp, lang)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf(err.Error() + user.Name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if application != nil {
|
||||||
|
err = isEntryIpAllowd(application.IpWhitelist, entryIp, lang)
|
||||||
|
if err != nil {
|
||||||
|
application.IpRestriction = err.Error() + application.Name
|
||||||
|
return fmt.Errorf(err.Error() + application.Name)
|
||||||
|
} else {
|
||||||
|
application.IpRestriction = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
if organization == nil && application.OrganizationObj != nil {
|
||||||
|
organization = application.OrganizationObj
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if organization != nil {
|
||||||
|
err = isEntryIpAllowd(organization.IpWhitelist, entryIp, lang)
|
||||||
|
if err != nil {
|
||||||
|
organization.IpRestriction = err.Error() + organization.Name
|
||||||
|
return fmt.Errorf(err.Error() + organization.Name)
|
||||||
|
} else {
|
||||||
|
organization.IpRestriction = ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func isEntryIpAllowd(ipWhitelistStr string, entryIp net.IP, lang string) error {
|
||||||
|
if ipWhitelistStr == "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
ipWhitelist := strings.Split(ipWhitelistStr, ",")
|
||||||
|
for _, ip := range ipWhitelist {
|
||||||
|
_, ipNet, err := net.ParseCIDR(ip)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if ipNet == nil {
|
||||||
|
return fmt.Errorf(i18n.Translate(lang, "check:CIDR for IP: %s should not be empty"), entryIp.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
if ipNet.Contains(entryIp) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Errorf(i18n.Translate(lang, "check:Your IP address: %s has been banned according to the configuration of: "), entryIp.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
func CheckIpWhitelist(ipWhitelistStr string, lang string) error {
|
||||||
|
if ipWhitelistStr == "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
ipWhiteList := strings.Split(ipWhitelistStr, ",")
|
||||||
|
for _, ip := range ipWhiteList {
|
||||||
|
if _, _, err := net.ParseCIDR(ip); err != nil {
|
||||||
|
return fmt.Errorf(i18n.Translate(lang, "check:%s does not meet the CIDR format requirements: %s"), ip, err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
@@ -48,12 +48,16 @@ type InitData struct {
|
|||||||
Transactions []*Transaction `json:"transactions"`
|
Transactions []*Transaction `json:"transactions"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var initDataNewOnly bool
|
||||||
|
|
||||||
func InitFromFile() {
|
func InitFromFile() {
|
||||||
initDataFile := conf.GetConfigString("initDataFile")
|
initDataFile := conf.GetConfigString("initDataFile")
|
||||||
if initDataFile == "" {
|
if initDataFile == "" {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
initDataNewOnly = conf.GetConfigBool("initDataNewOnly")
|
||||||
|
|
||||||
initData, err := readInitDataFromFile(initDataFile)
|
initData, err := readInitDataFromFile(initDataFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
@@ -269,6 +273,9 @@ func initDefinedOrganization(organization *Organization) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if existed != nil {
|
if existed != nil {
|
||||||
|
if initDataNewOnly {
|
||||||
|
return
|
||||||
|
}
|
||||||
affected, err := deleteOrganization(organization)
|
affected, err := deleteOrganization(organization)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
@@ -295,6 +302,9 @@ func initDefinedApplication(application *Application) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if existed != nil {
|
if existed != nil {
|
||||||
|
if initDataNewOnly {
|
||||||
|
return
|
||||||
|
}
|
||||||
affected, err := deleteApplication(application)
|
affected, err := deleteApplication(application)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
@@ -316,6 +326,9 @@ func initDefinedUser(user *User) {
|
|||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
if existed != nil {
|
if existed != nil {
|
||||||
|
if initDataNewOnly {
|
||||||
|
return
|
||||||
|
}
|
||||||
affected, err := deleteUser(user)
|
affected, err := deleteUser(user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
@@ -342,6 +355,9 @@ func initDefinedCert(cert *Cert) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if existed != nil {
|
if existed != nil {
|
||||||
|
if initDataNewOnly {
|
||||||
|
return
|
||||||
|
}
|
||||||
affected, err := DeleteCert(cert)
|
affected, err := DeleteCert(cert)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
@@ -364,6 +380,9 @@ func initDefinedLdap(ldap *Ldap) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if existed != nil {
|
if existed != nil {
|
||||||
|
if initDataNewOnly {
|
||||||
|
return
|
||||||
|
}
|
||||||
affected, err := DeleteLdap(ldap)
|
affected, err := DeleteLdap(ldap)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
@@ -385,6 +404,9 @@ func initDefinedProvider(provider *Provider) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if existed != nil {
|
if existed != nil {
|
||||||
|
if initDataNewOnly {
|
||||||
|
return
|
||||||
|
}
|
||||||
affected, err := DeleteProvider(provider)
|
affected, err := DeleteProvider(provider)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
@@ -406,6 +428,9 @@ func initDefinedModel(model *Model) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if existed != nil {
|
if existed != nil {
|
||||||
|
if initDataNewOnly {
|
||||||
|
return
|
||||||
|
}
|
||||||
affected, err := DeleteModel(model)
|
affected, err := DeleteModel(model)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
@@ -428,6 +453,9 @@ func initDefinedPermission(permission *Permission) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if existed != nil {
|
if existed != nil {
|
||||||
|
if initDataNewOnly {
|
||||||
|
return
|
||||||
|
}
|
||||||
affected, err := deletePermission(permission)
|
affected, err := deletePermission(permission)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
@@ -450,6 +478,9 @@ func initDefinedPayment(payment *Payment) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if existed != nil {
|
if existed != nil {
|
||||||
|
if initDataNewOnly {
|
||||||
|
return
|
||||||
|
}
|
||||||
affected, err := DeletePayment(payment)
|
affected, err := DeletePayment(payment)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
@@ -472,6 +503,9 @@ func initDefinedProduct(product *Product) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if existed != nil {
|
if existed != nil {
|
||||||
|
if initDataNewOnly {
|
||||||
|
return
|
||||||
|
}
|
||||||
affected, err := DeleteProduct(product)
|
affected, err := DeleteProduct(product)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
@@ -494,6 +528,9 @@ func initDefinedResource(resource *Resource) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if existed != nil {
|
if existed != nil {
|
||||||
|
if initDataNewOnly {
|
||||||
|
return
|
||||||
|
}
|
||||||
affected, err := DeleteResource(resource)
|
affected, err := DeleteResource(resource)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
@@ -516,6 +553,9 @@ func initDefinedRole(role *Role) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if existed != nil {
|
if existed != nil {
|
||||||
|
if initDataNewOnly {
|
||||||
|
return
|
||||||
|
}
|
||||||
affected, err := deleteRole(role)
|
affected, err := deleteRole(role)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
@@ -538,6 +578,9 @@ func initDefinedSyncer(syncer *Syncer) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if existed != nil {
|
if existed != nil {
|
||||||
|
if initDataNewOnly {
|
||||||
|
return
|
||||||
|
}
|
||||||
affected, err := DeleteSyncer(syncer)
|
affected, err := DeleteSyncer(syncer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
@@ -560,6 +603,9 @@ func initDefinedToken(token *Token) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if existed != nil {
|
if existed != nil {
|
||||||
|
if initDataNewOnly {
|
||||||
|
return
|
||||||
|
}
|
||||||
affected, err := DeleteToken(token)
|
affected, err := DeleteToken(token)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
@@ -582,6 +628,9 @@ func initDefinedWebhook(webhook *Webhook) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if existed != nil {
|
if existed != nil {
|
||||||
|
if initDataNewOnly {
|
||||||
|
return
|
||||||
|
}
|
||||||
affected, err := DeleteWebhook(webhook)
|
affected, err := DeleteWebhook(webhook)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
@@ -603,6 +652,9 @@ func initDefinedGroup(group *Group) {
|
|||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
if existed != nil {
|
if existed != nil {
|
||||||
|
if initDataNewOnly {
|
||||||
|
return
|
||||||
|
}
|
||||||
affected, err := deleteGroup(group)
|
affected, err := deleteGroup(group)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
@@ -624,6 +676,9 @@ func initDefinedAdapter(adapter *Adapter) {
|
|||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
if existed != nil {
|
if existed != nil {
|
||||||
|
if initDataNewOnly {
|
||||||
|
return
|
||||||
|
}
|
||||||
affected, err := DeleteAdapter(adapter)
|
affected, err := DeleteAdapter(adapter)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
@@ -645,6 +700,9 @@ func initDefinedEnforcer(enforcer *Enforcer) {
|
|||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
if existed != nil {
|
if existed != nil {
|
||||||
|
if initDataNewOnly {
|
||||||
|
return
|
||||||
|
}
|
||||||
affected, err := DeleteEnforcer(enforcer)
|
affected, err := DeleteEnforcer(enforcer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
@@ -666,6 +724,9 @@ func initDefinedPlan(plan *Plan) {
|
|||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
if existed != nil {
|
if existed != nil {
|
||||||
|
if initDataNewOnly {
|
||||||
|
return
|
||||||
|
}
|
||||||
affected, err := DeletePlan(plan)
|
affected, err := DeletePlan(plan)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
@@ -687,6 +748,9 @@ func initDefinedPricing(pricing *Pricing) {
|
|||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
if existed != nil {
|
if existed != nil {
|
||||||
|
if initDataNewOnly {
|
||||||
|
return
|
||||||
|
}
|
||||||
affected, err := DeletePricing(pricing)
|
affected, err := DeletePricing(pricing)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
@@ -708,6 +772,9 @@ func initDefinedInvitation(invitation *Invitation) {
|
|||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
if existed != nil {
|
if existed != nil {
|
||||||
|
if initDataNewOnly {
|
||||||
|
return
|
||||||
|
}
|
||||||
affected, err := DeleteInvitation(invitation)
|
affected, err := DeleteInvitation(invitation)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
@@ -743,6 +810,9 @@ func initDefinedSubscription(subscription *Subscription) {
|
|||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
if existed != nil {
|
if existed != nil {
|
||||||
|
if initDataNewOnly {
|
||||||
|
return
|
||||||
|
}
|
||||||
affected, err := DeleteSubscription(subscription)
|
affected, err := DeleteSubscription(subscription)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
@@ -764,6 +834,9 @@ func initDefinedTransaction(transaction *Transaction) {
|
|||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
if existed != nil {
|
if existed != nil {
|
||||||
|
if initDataNewOnly {
|
||||||
|
return
|
||||||
|
}
|
||||||
affected, err := DeleteTransaction(transaction)
|
affected, err := DeleteTransaction(transaction)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
|
@@ -71,11 +71,13 @@ type Organization struct {
|
|||||||
MasterPassword string `xorm:"varchar(100)" json:"masterPassword"`
|
MasterPassword string `xorm:"varchar(100)" json:"masterPassword"`
|
||||||
DefaultPassword string `xorm:"varchar(100)" json:"defaultPassword"`
|
DefaultPassword string `xorm:"varchar(100)" json:"defaultPassword"`
|
||||||
MasterVerificationCode string `xorm:"varchar(100)" json:"masterVerificationCode"`
|
MasterVerificationCode string `xorm:"varchar(100)" json:"masterVerificationCode"`
|
||||||
|
IpWhitelist string `xorm:"varchar(200)" json:"ipWhitelist"`
|
||||||
InitScore int `json:"initScore"`
|
InitScore int `json:"initScore"`
|
||||||
EnableSoftDeletion bool `json:"enableSoftDeletion"`
|
EnableSoftDeletion bool `json:"enableSoftDeletion"`
|
||||||
IsProfilePublic bool `json:"isProfilePublic"`
|
IsProfilePublic bool `json:"isProfilePublic"`
|
||||||
UseEmailAsUsername bool `json:"useEmailAsUsername"`
|
UseEmailAsUsername bool `json:"useEmailAsUsername"`
|
||||||
EnableTour bool `json:"enableTour"`
|
EnableTour bool `json:"enableTour"`
|
||||||
|
IpRestriction string `json:"ipRestriction"`
|
||||||
|
|
||||||
MfaItems []*MfaItem `xorm:"varchar(300)" json:"mfaItems"`
|
MfaItems []*MfaItem `xorm:"varchar(300)" json:"mfaItems"`
|
||||||
AccountItems []*AccountItem `xorm:"varchar(5000)" json:"accountItems"`
|
AccountItems []*AccountItem `xorm:"varchar(5000)" json:"accountItems"`
|
||||||
|
@@ -364,7 +364,7 @@ func GetAllActions(userId string) ([]string, error) {
|
|||||||
|
|
||||||
res := []string{}
|
res := []string{}
|
||||||
for _, enforcer := range enforcers {
|
for _, enforcer := range enforcers {
|
||||||
items := enforcer.GetAllObjects()
|
items := enforcer.GetAllActions()
|
||||||
res = append(res, items...)
|
res = append(res, items...)
|
||||||
}
|
}
|
||||||
return res, nil
|
return res, nil
|
||||||
|
@@ -50,7 +50,7 @@ func maskPassword(recordString string) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func NewRecord(ctx *context.Context) (*casvisorsdk.Record, error) {
|
func NewRecord(ctx *context.Context) (*casvisorsdk.Record, error) {
|
||||||
ip := strings.Replace(util.GetIPFromRequest(ctx.Request), ": ", "", -1)
|
clientIp := strings.Replace(util.GetClientIpFromRequest(ctx.Request), ": ", "", -1)
|
||||||
action := strings.Replace(ctx.Request.URL.Path, "/api/", "", -1)
|
action := strings.Replace(ctx.Request.URL.Path, "/api/", "", -1)
|
||||||
requestUri := util.FilterQuery(ctx.Request.RequestURI, []string{"accessToken"})
|
requestUri := util.FilterQuery(ctx.Request.RequestURI, []string{"accessToken"})
|
||||||
if len(requestUri) > 1000 {
|
if len(requestUri) > 1000 {
|
||||||
@@ -83,7 +83,7 @@ func NewRecord(ctx *context.Context) (*casvisorsdk.Record, error) {
|
|||||||
record := casvisorsdk.Record{
|
record := casvisorsdk.Record{
|
||||||
Name: util.GenerateId(),
|
Name: util.GenerateId(),
|
||||||
CreatedTime: util.GetCurrentTime(),
|
CreatedTime: util.GetCurrentTime(),
|
||||||
ClientIp: ip,
|
ClientIp: clientIp,
|
||||||
User: "",
|
User: "",
|
||||||
Method: ctx.Request.Method,
|
Method: ctx.Request.Method,
|
||||||
RequestUri: requestUri,
|
RequestUri: requestUri,
|
||||||
|
@@ -102,14 +102,6 @@ func GetTokenByAccessToken(accessToken string) (*Token, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if !existed {
|
|
||||||
token = Token{AccessToken: accessToken}
|
|
||||||
existed, err = ormer.Engine.Get(&token)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !existed {
|
if !existed {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
@@ -123,14 +115,6 @@ func GetTokenByRefreshToken(refreshToken string) (*Token, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if !existed {
|
|
||||||
token = Token{RefreshToken: refreshToken}
|
|
||||||
existed, err = ormer.Engine.Get(&token)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !existed {
|
if !existed {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
@@ -332,6 +332,9 @@ func RefreshToken(grantType string, refreshToken string, scope string, clientId
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
if user == nil {
|
||||||
|
return "", fmt.Errorf("The user: %s doesn't exist", util.GetId(application.Organization, token.User))
|
||||||
|
}
|
||||||
|
|
||||||
if user.IsForbidden {
|
if user.IsForbidden {
|
||||||
return &TokenError{
|
return &TokenError{
|
||||||
|
@@ -206,6 +206,7 @@ type User struct {
|
|||||||
ManagedAccounts []ManagedAccount `xorm:"managedAccounts blob" json:"managedAccounts"`
|
ManagedAccounts []ManagedAccount `xorm:"managedAccounts blob" json:"managedAccounts"`
|
||||||
MfaAccounts []MfaAccount `xorm:"mfaAccounts blob" json:"mfaAccounts"`
|
MfaAccounts []MfaAccount `xorm:"mfaAccounts blob" json:"mfaAccounts"`
|
||||||
NeedUpdatePassword bool `json:"needUpdatePassword"`
|
NeedUpdatePassword bool `json:"needUpdatePassword"`
|
||||||
|
IpWhitelist string `xorm:"varchar(200)" json:"ipWhitelist"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Userinfo struct {
|
type Userinfo struct {
|
||||||
@@ -696,7 +697,7 @@ func UpdateUser(id string, user *User, columns []string, isAdmin bool) (bool, er
|
|||||||
"eveonline", "fitbit", "gitea", "heroku", "influxcloud", "instagram", "intercom", "kakao", "lastfm", "mailru", "meetup",
|
"eveonline", "fitbit", "gitea", "heroku", "influxcloud", "instagram", "intercom", "kakao", "lastfm", "mailru", "meetup",
|
||||||
"microsoftonline", "naver", "nextcloud", "onedrive", "oura", "patreon", "paypal", "salesforce", "shopify", "soundcloud",
|
"microsoftonline", "naver", "nextcloud", "onedrive", "oura", "patreon", "paypal", "salesforce", "shopify", "soundcloud",
|
||||||
"spotify", "strava", "stripe", "type", "tiktok", "tumblr", "twitch", "twitter", "typetalk", "uber", "vk", "wepay", "xero", "yahoo",
|
"spotify", "strava", "stripe", "type", "tiktok", "tumblr", "twitch", "twitter", "typetalk", "uber", "vk", "wepay", "xero", "yahoo",
|
||||||
"yammer", "yandex", "zoom", "custom", "need_update_password",
|
"yammer", "yandex", "zoom", "custom", "need_update_password", "ip_whitelist",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if isAdmin {
|
if isAdmin {
|
||||||
@@ -815,6 +816,10 @@ func AddUser(user *User) (bool, error) {
|
|||||||
user.UpdateUserPassword(organization)
|
user.UpdateUserPassword(organization)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if user.CreatedTime == "" {
|
||||||
|
user.CreatedTime = util.GetCurrentTime()
|
||||||
|
}
|
||||||
|
|
||||||
err = user.UpdateUserHash()
|
err = user.UpdateUserHash()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
|
@@ -557,6 +557,14 @@ func CheckPermissionForUpdateUser(oldUser, newUser *User, isAdmin bool, lang str
|
|||||||
itemsChanged = append(itemsChanged, item)
|
itemsChanged = append(itemsChanged, item)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if oldUser.IpWhitelist != newUser.IpWhitelist {
|
||||||
|
item := GetAccountItemByName("IP whitelist", organization)
|
||||||
|
if item == nil {
|
||||||
|
newUser.IpWhitelist = oldUser.IpWhitelist
|
||||||
|
} else {
|
||||||
|
itemsChanged = append(itemsChanged, item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if oldUser.Balance != newUser.Balance {
|
if oldUser.Balance != newUser.Balance {
|
||||||
item := GetAccountItemByName("Balance", organization)
|
item := GetAccountItemByName("Balance", organization)
|
||||||
|
@@ -16,11 +16,11 @@ package routers
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/beego/beego/context"
|
"github.com/beego/beego/context"
|
||||||
"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"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -52,7 +52,13 @@ func CorsFilter(ctx *context.Context) {
|
|||||||
origin = ""
|
origin = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
if strings.HasPrefix(origin, "http://localhost") || strings.HasPrefix(origin, "https://localhost") || strings.HasPrefix(origin, "http://127.0.0.1") || strings.HasPrefix(origin, "http://casdoor-app") || strings.Contains(origin, ".chromiumapp.org") {
|
isValid, err := util.IsValidOrigin(origin)
|
||||||
|
if err != nil {
|
||||||
|
ctx.ResponseWriter.WriteHeader(http.StatusForbidden)
|
||||||
|
responseError(ctx, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if isValid {
|
||||||
setCorsHeaders(ctx, origin)
|
setCorsHeaders(ctx, origin)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
48
util/log.go
48
util/log.go
@@ -23,50 +23,50 @@ import (
|
|||||||
"github.com/beego/beego/logs"
|
"github.com/beego/beego/logs"
|
||||||
)
|
)
|
||||||
|
|
||||||
func GetIPInfo(clientIP string) string {
|
func getIpInfo(clientIp string) string {
|
||||||
if clientIP == "" {
|
if clientIp == "" {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
ips := strings.Split(clientIP, ",")
|
ips := strings.Split(clientIp, ",")
|
||||||
res := ""
|
res := strings.TrimSpace(ips[0])
|
||||||
for i := range ips {
|
//res := ""
|
||||||
ip := strings.TrimSpace(ips[i])
|
//for i := range ips {
|
||||||
// desc := GetDescFromIP(ip)
|
// ip := strings.TrimSpace(ips[i])
|
||||||
ipstr := fmt.Sprintf("%s: %s", ip, "")
|
// ipstr := fmt.Sprintf("%s: %s", ip, "")
|
||||||
if i != len(ips)-1 {
|
// if i != len(ips)-1 {
|
||||||
res += ipstr + " -> "
|
// res += ipstr + " -> "
|
||||||
} else {
|
// } else {
|
||||||
res += ipstr
|
// res += ipstr
|
||||||
}
|
// }
|
||||||
}
|
//}
|
||||||
|
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetIPFromRequest(req *http.Request) string {
|
func GetClientIpFromRequest(req *http.Request) string {
|
||||||
clientIP := req.Header.Get("x-forwarded-for")
|
clientIp := req.Header.Get("x-forwarded-for")
|
||||||
if clientIP == "" {
|
if clientIp == "" {
|
||||||
ipPort := strings.Split(req.RemoteAddr, ":")
|
ipPort := strings.Split(req.RemoteAddr, ":")
|
||||||
if len(ipPort) >= 1 && len(ipPort) <= 2 {
|
if len(ipPort) >= 1 && len(ipPort) <= 2 {
|
||||||
clientIP = ipPort[0]
|
clientIp = ipPort[0]
|
||||||
} else if len(ipPort) > 2 {
|
} else if len(ipPort) > 2 {
|
||||||
idx := strings.LastIndex(req.RemoteAddr, ":")
|
idx := strings.LastIndex(req.RemoteAddr, ":")
|
||||||
clientIP = req.RemoteAddr[0:idx]
|
clientIp = req.RemoteAddr[0:idx]
|
||||||
clientIP = strings.TrimLeft(clientIP, "[")
|
clientIp = strings.TrimLeft(clientIp, "[")
|
||||||
clientIP = strings.TrimRight(clientIP, "]")
|
clientIp = strings.TrimRight(clientIp, "]")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return GetIPInfo(clientIP)
|
return getIpInfo(clientIp)
|
||||||
}
|
}
|
||||||
|
|
||||||
func LogInfo(ctx *context.Context, f string, v ...interface{}) {
|
func LogInfo(ctx *context.Context, f string, v ...interface{}) {
|
||||||
ipString := fmt.Sprintf("(%s) ", GetIPFromRequest(ctx.Request))
|
ipString := fmt.Sprintf("(%s) ", GetClientIpFromRequest(ctx.Request))
|
||||||
logs.Info(ipString+f, v...)
|
logs.Info(ipString+f, v...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func LogWarning(ctx *context.Context, f string, v ...interface{}) {
|
func LogWarning(ctx *context.Context, f string, v ...interface{}) {
|
||||||
ipString := fmt.Sprintf("(%s) ", GetIPFromRequest(ctx.Request))
|
ipString := fmt.Sprintf("(%s) ", GetClientIpFromRequest(ctx.Request))
|
||||||
logs.Warning(ipString+f, v...)
|
logs.Warning(ipString+f, v...)
|
||||||
}
|
}
|
||||||
|
@@ -17,6 +17,7 @@ package util
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/mail"
|
"net/mail"
|
||||||
|
"net/url"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@@ -24,10 +25,11 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
rePhone *regexp.Regexp
|
rePhone *regexp.Regexp
|
||||||
ReWhiteSpace *regexp.Regexp
|
ReWhiteSpace *regexp.Regexp
|
||||||
ReFieldWhiteList *regexp.Regexp
|
ReFieldWhiteList *regexp.Regexp
|
||||||
ReUserName *regexp.Regexp
|
ReUserName *regexp.Regexp
|
||||||
|
ReUserNameWithEmail *regexp.Regexp
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@@ -35,6 +37,7 @@ func init() {
|
|||||||
ReWhiteSpace, _ = regexp.Compile(`\s`)
|
ReWhiteSpace, _ = regexp.Compile(`\s`)
|
||||||
ReFieldWhiteList, _ = regexp.Compile(`^[A-Za-z0-9]+$`)
|
ReFieldWhiteList, _ = regexp.Compile(`^[A-Za-z0-9]+$`)
|
||||||
ReUserName, _ = regexp.Compile("^[a-zA-Z0-9]+([-._][a-zA-Z0-9]+)*$")
|
ReUserName, _ = regexp.Compile("^[a-zA-Z0-9]+([-._][a-zA-Z0-9]+)*$")
|
||||||
|
ReUserNameWithEmail, _ = regexp.Compile(`^([a-zA-Z0-9]+([-._][a-zA-Z0-9]+)*)|([a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,})$`) // Add support for email formats
|
||||||
}
|
}
|
||||||
|
|
||||||
func IsEmailValid(email string) bool {
|
func IsEmailValid(email string) bool {
|
||||||
@@ -100,3 +103,21 @@ func GetCountryCode(prefix string, phone string) (string, error) {
|
|||||||
func FilterField(field string) bool {
|
func FilterField(field string) bool {
|
||||||
return ReFieldWhiteList.MatchString(field)
|
return ReFieldWhiteList.MatchString(field)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func IsValidOrigin(origin string) (bool, error) {
|
||||||
|
urlObj, err := url.Parse(origin)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
if urlObj == nil {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
originHostOnly := ""
|
||||||
|
if urlObj.Host != "" {
|
||||||
|
originHostOnly = fmt.Sprintf("%s://%s", urlObj.Scheme, urlObj.Hostname())
|
||||||
|
}
|
||||||
|
|
||||||
|
res := originHostOnly == "http://localhost" || originHostOnly == "https://localhost" || originHostOnly == "http://127.0.0.1" || originHostOnly == "http://casdoor-app" || strings.HasSuffix(originHostOnly, ".chromiumapp.org")
|
||||||
|
return res, nil
|
||||||
|
}
|
||||||
|
@@ -46,12 +46,18 @@ require("codemirror/mode/css/css");
|
|||||||
const {Option} = Select;
|
const {Option} = Select;
|
||||||
|
|
||||||
const template = `<style>
|
const template = `<style>
|
||||||
.login-panel{
|
.login-panel {
|
||||||
padding: 40px 70px 0 70px;
|
padding: 40px 70px 0 70px;
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
background-color: #ffffff;
|
background-color: #ffffff;
|
||||||
box-shadow: 0 0 30px 20px rgba(0, 0, 0, 0.20);
|
box-shadow: 0 0 30px 20px rgba(0, 0, 0, 0.20);
|
||||||
}
|
}
|
||||||
|
.login-panel-dark {
|
||||||
|
padding: 40px 70px 0 70px;
|
||||||
|
border-radius: 10px;
|
||||||
|
background-color: #333333;
|
||||||
|
box-shadow: 0 0 30px 20px rgba(255, 255, 255, 0.20);
|
||||||
|
}
|
||||||
</style>`;
|
</style>`;
|
||||||
|
|
||||||
const previewGrid = Setting.isMobile() ? 22 : 11;
|
const previewGrid = Setting.isMobile() ? 22 : 11;
|
||||||
@@ -592,6 +598,16 @@ class ApplicationEditPage 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:IP whitelist"), i18next.t("general:IP whitelist - Tooltip"))} :
|
||||||
|
</Col>
|
||||||
|
<Col span={22} >
|
||||||
|
<Input placeholder = {this.state.application.organizationObj?.ipWhitelist} value={this.state.application.ipWhitelist} onChange={e => {
|
||||||
|
this.updateApplicationField("ipWhitelist", e.target.value);
|
||||||
|
}} />
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
<Row style={{marginTop: "20px"}} >
|
<Row style={{marginTop: "20px"}} >
|
||||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||||
{Setting.getLabel(i18next.t("signup:Terms of Use"), i18next.t("signup:Terms of Use - Tooltip"))} :
|
{Setting.getLabel(i18next.t("signup:Terms of Use"), i18next.t("signup:Terms of Use - Tooltip"))} :
|
||||||
|
@@ -34,6 +34,7 @@ import PaymentResultPage from "./PaymentResultPage";
|
|||||||
import QrCodePage from "./QrCodePage";
|
import QrCodePage from "./QrCodePage";
|
||||||
import CaptchaPage from "./CaptchaPage";
|
import CaptchaPage from "./CaptchaPage";
|
||||||
import CustomHead from "./basic/CustomHead";
|
import CustomHead from "./basic/CustomHead";
|
||||||
|
import * as Util from "./auth/Util";
|
||||||
|
|
||||||
class EntryPage extends React.Component {
|
class EntryPage extends React.Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
@@ -94,6 +95,14 @@ class EntryPage extends React.Component {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (this.state.application?.ipRestriction) {
|
||||||
|
return Util.renderMessageLarge(this, this.state.application.ipRestriction);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.state.application?.organizationObj?.ipRestriction) {
|
||||||
|
return Util.renderMessageLarge(this, this.state.application.organizationObj.ipRestriction);
|
||||||
|
}
|
||||||
|
|
||||||
const isDarkMode = this.props.themeAlgorithm.includes("dark");
|
const isDarkMode = this.props.themeAlgorithm.includes("dark");
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@@ -452,6 +452,16 @@ 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:IP whitelist"), i18next.t("general:IP whitelist - Tooltip"))} :
|
||||||
|
</Col>
|
||||||
|
<Col span={22} >
|
||||||
|
<Input value={this.state.organization.ipWhitelist} onChange={e => {
|
||||||
|
this.updateOrganizationField("ipWhitelist", e.target.value);
|
||||||
|
}} />
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
<Row style={{marginTop: "20px"}} >
|
<Row style={{marginTop: "20px"}} >
|
||||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 19 : 2}>
|
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 19 : 2}>
|
||||||
{Setting.getLabel(i18next.t("organization:Init score"), i18next.t("organization:Init score - Tooltip"))} :
|
{Setting.getLabel(i18next.t("organization:Init score"), i18next.t("organization:Init score - Tooltip"))} :
|
||||||
|
@@ -908,7 +908,7 @@ class ProviderEditPage extends React.Component {
|
|||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
)}
|
)}
|
||||||
{["Custom HTTP SMS", "Qiniu Cloud Kodo", "Synology", "Casdoor"].includes(this.state.provider.type) ? null : (
|
{["Custom HTTP SMS", "Synology", "Casdoor"].includes(this.state.provider.type) ? null : (
|
||||||
<Row style={{marginTop: "20px"}} >
|
<Row style={{marginTop: "20px"}} >
|
||||||
<Col style={{marginTop: "5px"}} span={2}>
|
<Col style={{marginTop: "5px"}} span={2}>
|
||||||
{Setting.getLabel(i18next.t("provider:Domain"), i18next.t("provider:Domain - Tooltip"))} :
|
{Setting.getLabel(i18next.t("provider:Domain"), i18next.t("provider:Domain - Tooltip"))} :
|
||||||
|
@@ -187,7 +187,7 @@ class RoleEditPage extends React.Component {
|
|||||||
{Setting.getLabel(i18next.t("role:Sub users"), i18next.t("role:Sub users - Tooltip"))} :
|
{Setting.getLabel(i18next.t("role:Sub users"), i18next.t("role:Sub users - Tooltip"))} :
|
||||||
</Col>
|
</Col>
|
||||||
<Col span={22} >
|
<Col span={22} >
|
||||||
<Select virtual={false} mode="multiple" style={{width: "100%"}} value={this.state.role.users}
|
<Select virtual={true} mode="multiple" style={{width: "100%"}} value={this.state.role.users}
|
||||||
onChange={(value => {this.updateRoleField("users", value);})}
|
onChange={(value => {this.updateRoleField("users", value);})}
|
||||||
options={this.state.users.map((user) => Setting.getOption(`${user.owner}/${user.name}`, `${user.owner}/${user.name}`))}
|
options={this.state.users.map((user) => Setting.getOption(`${user.owner}/${user.name}`, `${user.owner}/${user.name}`))}
|
||||||
/>
|
/>
|
||||||
|
@@ -1557,3 +1557,7 @@ export function getCurrencyText(product) {
|
|||||||
return "(Unknown currency)";
|
return "(Unknown currency)";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function isDarkTheme(themeAlgorithm) {
|
||||||
|
return themeAlgorithm && themeAlgorithm.includes("dark");
|
||||||
|
}
|
||||||
|
@@ -1070,6 +1070,19 @@ class UserEditPage extends React.Component {
|
|||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
);
|
);
|
||||||
|
} else if (accountItem.name === "IP whitelist") {
|
||||||
|
return (
|
||||||
|
<Row style={{marginTop: "20px"}} >
|
||||||
|
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||||
|
{Setting.getLabel(i18next.t("general:IP whitelist"), i18next.t("general:IP whitelist - Tooltip"))} :
|
||||||
|
</Col>
|
||||||
|
<Col span={22}>
|
||||||
|
<Input value={this.state.user.ipWhitelist} onChange={e => {
|
||||||
|
this.updateUserField("ipWhitelist", e.target.value);
|
||||||
|
}} />
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -52,7 +52,6 @@ class LoginPage extends React.Component {
|
|||||||
username: null,
|
username: null,
|
||||||
validEmailOrPhone: false,
|
validEmailOrPhone: false,
|
||||||
validEmail: false,
|
validEmail: false,
|
||||||
enableCaptchaModal: CaptchaRule.Never,
|
|
||||||
openCaptchaModal: false,
|
openCaptchaModal: false,
|
||||||
openFaceRecognitionModal: false,
|
openFaceRecognitionModal: false,
|
||||||
verifyCaptcha: undefined,
|
verifyCaptcha: undefined,
|
||||||
@@ -93,17 +92,6 @@ class LoginPage extends React.Component {
|
|||||||
}
|
}
|
||||||
if (prevProps.application !== this.props.application) {
|
if (prevProps.application !== this.props.application) {
|
||||||
this.setState({loginMethod: this.getDefaultLoginMethod(this.props.application)});
|
this.setState({loginMethod: this.getDefaultLoginMethod(this.props.application)});
|
||||||
|
|
||||||
const captchaProviderItems = this.getCaptchaProviderItems(this.props.application);
|
|
||||||
if (captchaProviderItems) {
|
|
||||||
if (captchaProviderItems.some(providerItem => providerItem.rule === "Always")) {
|
|
||||||
this.setState({enableCaptchaModal: CaptchaRule.Always});
|
|
||||||
} else if (captchaProviderItems.some(providerItem => providerItem.rule === "Dynamic")) {
|
|
||||||
this.setState({enableCaptchaModal: CaptchaRule.Dynamic});
|
|
||||||
} else {
|
|
||||||
this.setState({enableCaptchaModal: CaptchaRule.Never});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (prevProps.account !== this.props.account && this.props.account !== undefined) {
|
if (prevProps.account !== this.props.account && this.props.account !== undefined) {
|
||||||
@@ -133,6 +121,19 @@ class LoginPage extends React.Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getCaptchaRule(application) {
|
||||||
|
const captchaProviderItems = this.getCaptchaProviderItems(application);
|
||||||
|
if (captchaProviderItems) {
|
||||||
|
if (captchaProviderItems.some(providerItem => providerItem.rule === "Always")) {
|
||||||
|
return CaptchaRule.Always;
|
||||||
|
} else if (captchaProviderItems.some(providerItem => providerItem.rule === "Dynamic")) {
|
||||||
|
return CaptchaRule.Dynamic;
|
||||||
|
} else {
|
||||||
|
return CaptchaRule.Never;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
checkCaptchaStatus(values) {
|
checkCaptchaStatus(values) {
|
||||||
AuthBackend.getCaptchaStatus(values)
|
AuthBackend.getCaptchaStatus(values)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
@@ -226,6 +227,22 @@ class LoginPage extends React.Component {
|
|||||||
return "password";
|
return "password";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getCurrentLoginMethod() {
|
||||||
|
if (this.state.loginMethod === "password") {
|
||||||
|
return "Password";
|
||||||
|
} else if (this.state.loginMethod?.includes("verificationCode")) {
|
||||||
|
return "Verification code";
|
||||||
|
} else if (this.state.loginMethod === "webAuthn") {
|
||||||
|
return "WebAuthn";
|
||||||
|
} else if (this.state.loginMethod === "ldap") {
|
||||||
|
return "LDAP";
|
||||||
|
} else if (this.state.loginMethod === "faceId") {
|
||||||
|
return "Face ID";
|
||||||
|
} else {
|
||||||
|
return "Password";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
getPlaceholder() {
|
getPlaceholder() {
|
||||||
switch (this.state.loginMethod) {
|
switch (this.state.loginMethod) {
|
||||||
case "verificationCode": return i18next.t("login:Email or phone");
|
case "verificationCode": return i18next.t("login:Email or phone");
|
||||||
@@ -261,17 +278,7 @@ class LoginPage extends React.Component {
|
|||||||
values["organization"] = this.getApplicationObj().organization;
|
values["organization"] = this.getApplicationObj().organization;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.state.loginMethod === "password") {
|
values["signinMethod"] = this.getCurrentLoginMethod();
|
||||||
values["signinMethod"] = "Password";
|
|
||||||
} else if (this.state.loginMethod?.includes("verificationCode")) {
|
|
||||||
values["signinMethod"] = "Verification code";
|
|
||||||
} else if (this.state.loginMethod === "webAuthn") {
|
|
||||||
values["signinMethod"] = "WebAuthn";
|
|
||||||
} else if (this.state.loginMethod === "ldap") {
|
|
||||||
values["signinMethod"] = "LDAP";
|
|
||||||
} else if (this.state.loginMethod === "faceId") {
|
|
||||||
values["signinMethod"] = "Face ID";
|
|
||||||
}
|
|
||||||
const oAuthParams = Util.getOAuthGetParameters();
|
const oAuthParams = Util.getOAuthGetParameters();
|
||||||
|
|
||||||
values["type"] = oAuthParams?.responseType ?? this.state.type;
|
values["type"] = oAuthParams?.responseType ?? this.state.type;
|
||||||
@@ -388,13 +395,14 @@ class LoginPage extends React.Component {
|
|||||||
} else {
|
} else {
|
||||||
values["password"] = passwordCipher;
|
values["password"] = passwordCipher;
|
||||||
}
|
}
|
||||||
if (this.state.enableCaptchaModal === CaptchaRule.Always) {
|
const captchaRule = this.getCaptchaRule(this.getApplicationObj());
|
||||||
|
if (captchaRule === CaptchaRule.Always) {
|
||||||
this.setState({
|
this.setState({
|
||||||
openCaptchaModal: true,
|
openCaptchaModal: true,
|
||||||
values: values,
|
values: values,
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
} else if (this.state.enableCaptchaModal === CaptchaRule.Dynamic) {
|
} else if (captchaRule === CaptchaRule.Dynamic) {
|
||||||
this.checkCaptchaStatus(values);
|
this.checkCaptchaStatus(values);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -407,6 +415,7 @@ class LoginPage extends React.Component {
|
|||||||
if (this.state.type === "cas") {
|
if (this.state.type === "cas") {
|
||||||
// CAS
|
// CAS
|
||||||
const casParams = Util.getCasParameters();
|
const casParams = Util.getCasParameters();
|
||||||
|
values["signinMethod"] = this.getCurrentLoginMethod();
|
||||||
values["type"] = this.state.type;
|
values["type"] = this.state.type;
|
||||||
AuthBackend.loginCas(values, casParams).then((res) => {
|
AuthBackend.loginCas(values, casParams).then((res) => {
|
||||||
const loginHandler = (res) => {
|
const loginHandler = (res) => {
|
||||||
@@ -435,8 +444,8 @@ class LoginPage extends React.Component {
|
|||||||
formValues={values}
|
formValues={values}
|
||||||
authParams={casParams}
|
authParams={casParams}
|
||||||
application={this.getApplicationObj()}
|
application={this.getApplicationObj()}
|
||||||
onFail={() => {
|
onFail={(errorMessage) => {
|
||||||
Setting.showMessage("error", i18next.t("mfa:Verification failed"));
|
Setting.showMessage("error", errorMessage);
|
||||||
}}
|
}}
|
||||||
onSuccess={(res) => loginHandler(res)}
|
onSuccess={(res) => loginHandler(res)}
|
||||||
/>);
|
/>);
|
||||||
@@ -504,8 +513,8 @@ class LoginPage extends React.Component {
|
|||||||
formValues={values}
|
formValues={values}
|
||||||
authParams={oAuthParams}
|
authParams={oAuthParams}
|
||||||
application={this.getApplicationObj()}
|
application={this.getApplicationObj()}
|
||||||
onFail={() => {
|
onFail={(errorMessage) => {
|
||||||
Setting.showMessage("error", i18next.t("mfa:Verification failed"));
|
Setting.showMessage("error", errorMessage);
|
||||||
}}
|
}}
|
||||||
onSuccess={(res) => loginHandler(res)}
|
onSuccess={(res) => loginHandler(res)}
|
||||||
/>);
|
/>);
|
||||||
@@ -911,7 +920,7 @@ class LoginPage extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
renderCaptchaModal(application) {
|
renderCaptchaModal(application) {
|
||||||
if (this.state.enableCaptchaModal === CaptchaRule.Never) {
|
if (this.getCaptchaRule(this.getApplicationObj()) === CaptchaRule.Never) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
const captchaProviderItems = this.getCaptchaProviderItems(application);
|
const captchaProviderItems = this.getCaptchaProviderItems(application);
|
||||||
@@ -1291,7 +1300,7 @@ class LoginPage extends React.Component {
|
|||||||
<div className="login-content" style={{margin: this.props.preview ?? this.parseOffset(application.formOffset)}}>
|
<div className="login-content" style={{margin: this.props.preview ?? this.parseOffset(application.formOffset)}}>
|
||||||
{Setting.inIframe() || Setting.isMobile() ? null : <div dangerouslySetInnerHTML={{__html: application.formCss}} />}
|
{Setting.inIframe() || Setting.isMobile() ? null : <div dangerouslySetInnerHTML={{__html: application.formCss}} />}
|
||||||
{Setting.inIframe() || !Setting.isMobile() ? null : <div dangerouslySetInnerHTML={{__html: application.formCssMobile}} />}
|
{Setting.inIframe() || !Setting.isMobile() ? null : <div dangerouslySetInnerHTML={{__html: application.formCssMobile}} />}
|
||||||
<div className="login-panel">
|
<div className={Setting.isDarkTheme(this.props.themeAlgorithm) ? "login-panel-dark" : "login-panel"}>
|
||||||
<div className="side-image" style={{display: application.formOffset !== 4 ? "none" : null}}>
|
<div className="side-image" style={{display: application.formOffset !== 4 ? "none" : null}}>
|
||||||
<div dangerouslySetInnerHTML={{__html: application.formSideHtml}} />
|
<div dangerouslySetInnerHTML={{__html: application.formSideHtml}} />
|
||||||
</div>
|
</div>
|
||||||
|
@@ -37,7 +37,7 @@ class MfaSetupPage extends React.Component {
|
|||||||
this.state = {
|
this.state = {
|
||||||
account: props.account,
|
account: props.account,
|
||||||
application: null,
|
application: null,
|
||||||
applicationName: props.account.signupApplication ?? "",
|
applicationName: props.account.signupApplication ?? localStorage.getItem("applicationName") ?? "",
|
||||||
current: location.state?.from !== undefined ? 1 : 0,
|
current: location.state?.from !== undefined ? 1 : 0,
|
||||||
mfaProps: null,
|
mfaProps: null,
|
||||||
mfaType: params.get("mfaType") ?? SmsMfaType,
|
mfaType: params.get("mfaType") ?? SmsMfaType,
|
||||||
|
@@ -14,6 +14,7 @@
|
|||||||
|
|
||||||
import CryptoJS from "crypto-js";
|
import CryptoJS from "crypto-js";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
|
import {Buffer} from "buffer";
|
||||||
|
|
||||||
export function getRandomKeyForObfuscator(obfuscatorType) {
|
export function getRandomKeyForObfuscator(obfuscatorType) {
|
||||||
if (obfuscatorType === "DES") {
|
if (obfuscatorType === "DES") {
|
||||||
|
@@ -842,7 +842,7 @@ class SignupPage extends React.Component {
|
|||||||
<div className="login-content" style={{margin: this.props.preview ?? this.parseOffset(application.formOffset)}}>
|
<div className="login-content" style={{margin: this.props.preview ?? this.parseOffset(application.formOffset)}}>
|
||||||
{Setting.inIframe() || Setting.isMobile() ? null : <div dangerouslySetInnerHTML={{__html: application.formCss}} />}
|
{Setting.inIframe() || Setting.isMobile() ? null : <div dangerouslySetInnerHTML={{__html: application.formCss}} />}
|
||||||
{Setting.inIframe() || !Setting.isMobile() ? null : <div dangerouslySetInnerHTML={{__html: application.formCssMobile}} />}
|
{Setting.inIframe() || !Setting.isMobile() ? null : <div dangerouslySetInnerHTML={{__html: application.formCssMobile}} />}
|
||||||
<div className="login-panel" >
|
<div className={Setting.isDarkTheme(this.props.themeAlgorithm) ? "login-panel-dark" : "login-panel"}>
|
||||||
<div className="side-image" style={{display: application.formOffset !== 4 ? "none" : null}}>
|
<div className="side-image" style={{display: application.formOffset !== 4 ? "none" : null}}>
|
||||||
<div dangerouslySetInnerHTML={{__html: application.formSideHtml}} />
|
<div dangerouslySetInnerHTML={{__html: application.formSideHtml}} />
|
||||||
</div>
|
</div>
|
||||||
|
@@ -12,7 +12,7 @@
|
|||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
import React, {useState} from "react";
|
import React, {Fragment, useState} from "react";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
import {Button, Input} from "antd";
|
import {Button, Input} from "antd";
|
||||||
import * as AuthBackend from "../AuthBackend";
|
import * as AuthBackend from "../AuthBackend";
|
||||||
@@ -67,24 +67,32 @@ export function MfaAuthVerifyForm({formValues, authParams, mfaProps, application
|
|||||||
|
|
||||||
if (mfaType !== RecoveryMfaType) {
|
if (mfaType !== RecoveryMfaType) {
|
||||||
return (
|
return (
|
||||||
<div style={{width: 300, height: 350}}>
|
<div style={{width: 320, height: 350}}>
|
||||||
<div style={{marginBottom: 24, textAlign: "center", fontSize: "24px"}}>
|
<div style={{marginBottom: 24, textAlign: "center", fontSize: "24px"}}>
|
||||||
{i18next.t("mfa:Multi-factor authentication")}
|
{i18next.t("mfa:Multi-factor authentication")}
|
||||||
</div>
|
</div>
|
||||||
<div style={{marginBottom: 24}}>
|
|
||||||
{i18next.t("mfa:Multi-factor authentication description")}
|
|
||||||
</div>
|
|
||||||
{mfaType === SmsMfaType || mfaType === EmailMfaType ? (
|
{mfaType === SmsMfaType || mfaType === EmailMfaType ? (
|
||||||
<MfaVerifySmsForm
|
<Fragment>
|
||||||
mfaProps={mfaProps}
|
<div style={{marginBottom: 24}}>
|
||||||
method={mfaAuth}
|
{i18next.t("mfa:You have enabled Multi-Factor Authentication, Please click 'Send Code' to continue")}
|
||||||
onFinish={verify}
|
</div>
|
||||||
application={application}
|
<MfaVerifySmsForm
|
||||||
/>) : (
|
mfaProps={mfaProps}
|
||||||
<MfaVerifyTotpForm
|
method={mfaAuth}
|
||||||
mfaProps={mfaProps}
|
onFinish={verify}
|
||||||
onFinish={verify}
|
application={application}
|
||||||
/>
|
/>
|
||||||
|
</Fragment>
|
||||||
|
) : (
|
||||||
|
<Fragment>
|
||||||
|
<div style={{marginBottom: 24}}>
|
||||||
|
{i18next.t("mfa:You have enabled Multi-Factor Authentication, please enter the TOTP code")}
|
||||||
|
</div>
|
||||||
|
<MfaVerifyTotpForm
|
||||||
|
mfaProps={mfaProps}
|
||||||
|
onFinish={verify}
|
||||||
|
/>
|
||||||
|
</Fragment>
|
||||||
)}
|
)}
|
||||||
<span style={{float: "right"}}>
|
<span style={{float: "right"}}>
|
||||||
{i18next.t("mfa:Have problems?")}
|
{i18next.t("mfa:Have problems?")}
|
||||||
|
121
web/src/common/CasdoorAppConnector.js
Normal file
121
web/src/common/CasdoorAppConnector.js
Normal file
@@ -0,0 +1,121 @@
|
|||||||
|
// Copyright 2024 The Casdoor Authors. All Rights Reserved.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
import React from "react";
|
||||||
|
import {Alert, Button, QRCode} from "antd";
|
||||||
|
import * as Setting from "../Setting";
|
||||||
|
import i18next from "i18next";
|
||||||
|
|
||||||
|
export const generateCasdoorAppUrl = (accessToken, forQrCode = true) => {
|
||||||
|
let qrUrl = "";
|
||||||
|
let error = null;
|
||||||
|
|
||||||
|
if (!accessToken) {
|
||||||
|
error = i18next.t("general:Access token is empty");
|
||||||
|
return {qrUrl, error};
|
||||||
|
}
|
||||||
|
|
||||||
|
qrUrl = `casdoor-app://login?serverUrl=${window.location.origin}&accessToken=${accessToken}`;
|
||||||
|
|
||||||
|
if (forQrCode && qrUrl.length >= 2000) {
|
||||||
|
qrUrl = "";
|
||||||
|
error = i18next.t("general:QR code is too large");
|
||||||
|
}
|
||||||
|
|
||||||
|
return {qrUrl, error};
|
||||||
|
};
|
||||||
|
|
||||||
|
export const CasdoorAppQrCode = ({accessToken, icon}) => {
|
||||||
|
const {qrUrl, error} = generateCasdoorAppUrl(accessToken, true);
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
return <Alert message={error} type="error" showIcon />;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<QRCode
|
||||||
|
value={qrUrl}
|
||||||
|
icon={icon}
|
||||||
|
errorLevel="M"
|
||||||
|
size={230}
|
||||||
|
bordered={false}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const CasdoorAppUrl = ({accessToken}) => {
|
||||||
|
const {qrUrl, error} = generateCasdoorAppUrl(accessToken, false);
|
||||||
|
|
||||||
|
const handleCopyUrl = async() => {
|
||||||
|
if (!window.isSecureContext) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
await navigator.clipboard.writeText(qrUrl);
|
||||||
|
Setting.showMessage("success", i18next.t("general:Copied to clipboard"));
|
||||||
|
} catch (err) {
|
||||||
|
Setting.showMessage("error", i18next.t("general:Failed to copy"));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
return <Alert message={error} type="error" showIcon />;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<div style={{
|
||||||
|
display: "flex",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
alignItems: "center",
|
||||||
|
marginBottom: "10px",
|
||||||
|
}}>
|
||||||
|
<span>{i18next.t("general:URL String")}</span>
|
||||||
|
{window.isSecureContext && (
|
||||||
|
<Button
|
||||||
|
size="small"
|
||||||
|
onClick={handleCopyUrl}
|
||||||
|
style={{marginLeft: "10px"}}
|
||||||
|
>
|
||||||
|
{i18next.t("general:Copy URL")}
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
padding: "10px",
|
||||||
|
maxWidth: "400px",
|
||||||
|
maxHeight: "100px",
|
||||||
|
overflow: "auto",
|
||||||
|
wordBreak: "break-all",
|
||||||
|
whiteSpace: "pre-wrap",
|
||||||
|
cursor: "pointer",
|
||||||
|
userSelect: "all",
|
||||||
|
backgroundColor: "#f5f5f5",
|
||||||
|
borderRadius: "4px",
|
||||||
|
}}
|
||||||
|
onClick={(e) => {
|
||||||
|
const selection = window.getSelection();
|
||||||
|
const range = document.createRange();
|
||||||
|
range.selectNodeContents(e.target);
|
||||||
|
selection.removeAllRanges();
|
||||||
|
selection.addRange(range);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{qrUrl}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
@@ -538,7 +538,6 @@
|
|||||||
"Have problems?": "Have problems?",
|
"Have problems?": "Have problems?",
|
||||||
"Multi-factor authentication": "Multi-factor authentication",
|
"Multi-factor authentication": "Multi-factor authentication",
|
||||||
"Multi-factor authentication - Tooltip ": "Multi-factor authentication - Tooltip ",
|
"Multi-factor authentication - Tooltip ": "Multi-factor authentication - Tooltip ",
|
||||||
"Multi-factor authentication description": "Multi-factor authentication description",
|
|
||||||
"Multi-factor methods": "Multi-factor methods",
|
"Multi-factor methods": "Multi-factor methods",
|
||||||
"Multi-factor recover": "Multi-factor recover",
|
"Multi-factor recover": "Multi-factor recover",
|
||||||
"Multi-factor recover description": "Multi-factor recover description",
|
"Multi-factor recover description": "Multi-factor recover description",
|
||||||
@@ -563,6 +562,8 @@
|
|||||||
"Verification failed": "Verification failed",
|
"Verification failed": "Verification failed",
|
||||||
"Verify Code": "Verify Code",
|
"Verify Code": "Verify Code",
|
||||||
"Verify Password": "Verify Password",
|
"Verify Password": "Verify Password",
|
||||||
|
"You have enabled Multi-Factor Authentication, Please click 'Send Code' to continue": "You have enabled Multi-Factor Authentication, Please click 'Send Code' to continue",
|
||||||
|
"You have enabled Multi-Factor Authentication, please enter the TOTP code": "You have enabled Multi-Factor Authentication, please enter the TOTP code",
|
||||||
"Your email is": "Your email is",
|
"Your email is": "Your email is",
|
||||||
"Your phone is": "Your phone is",
|
"Your phone is": "Your phone is",
|
||||||
"preferred": "preferred"
|
"preferred": "preferred"
|
||||||
|
@@ -538,7 +538,6 @@
|
|||||||
"Have problems?": "Máte problémy?",
|
"Have problems?": "Máte problémy?",
|
||||||
"Multi-factor authentication": "Vícefaktorové ověřování",
|
"Multi-factor authentication": "Vícefaktorové ověřování",
|
||||||
"Multi-factor authentication - Tooltip ": "Dvoufaktorové ověřování - Tooltip",
|
"Multi-factor authentication - Tooltip ": "Dvoufaktorové ověřování - Tooltip",
|
||||||
"Multi-factor authentication description": "Popis dvoufaktorového ověřování",
|
|
||||||
"Multi-factor methods": "Metody dvoufaktorového ověřování",
|
"Multi-factor methods": "Metody dvoufaktorového ověřování",
|
||||||
"Multi-factor recover": "Obnovení dvoufaktorového ověřování",
|
"Multi-factor recover": "Obnovení dvoufaktorového ověřování",
|
||||||
"Multi-factor recover description": "Popis obnovení dvoufaktorového ověřování",
|
"Multi-factor recover description": "Popis obnovení dvoufaktorového ověřování",
|
||||||
@@ -563,6 +562,8 @@
|
|||||||
"Verification failed": "Ověření selhalo",
|
"Verification failed": "Ověření selhalo",
|
||||||
"Verify Code": "Ověřit kód",
|
"Verify Code": "Ověřit kód",
|
||||||
"Verify Password": "Ověřit heslo",
|
"Verify Password": "Ověřit heslo",
|
||||||
|
"You have enabled Multi-Factor Authentication, Please click 'Send Code' to continue": "You have enabled Multi-Factor Authentication, Please click 'Send Code' to continue",
|
||||||
|
"You have enabled Multi-Factor Authentication, please enter the TOTP code": "You have enabled Multi-Factor Authentication, please enter the TOTP code",
|
||||||
"Your email is": "Váš email je",
|
"Your email is": "Váš email je",
|
||||||
"Your phone is": "Váš telefon je",
|
"Your phone is": "Váš telefon je",
|
||||||
"preferred": "preferované"
|
"preferred": "preferované"
|
||||||
|
@@ -538,7 +538,6 @@
|
|||||||
"Have problems?": "Have problems?",
|
"Have problems?": "Have problems?",
|
||||||
"Multi-factor authentication": "Multi-factor authentication",
|
"Multi-factor authentication": "Multi-factor authentication",
|
||||||
"Multi-factor authentication - Tooltip ": "Multi-factor authentication - Tooltip ",
|
"Multi-factor authentication - Tooltip ": "Multi-factor authentication - Tooltip ",
|
||||||
"Multi-factor authentication description": "Multi-factor authentication description",
|
|
||||||
"Multi-factor methods": "Multi-factor methods",
|
"Multi-factor methods": "Multi-factor methods",
|
||||||
"Multi-factor recover": "Multi-factor recover",
|
"Multi-factor recover": "Multi-factor recover",
|
||||||
"Multi-factor recover description": "Multi-factor recover description",
|
"Multi-factor recover description": "Multi-factor recover description",
|
||||||
@@ -563,6 +562,8 @@
|
|||||||
"Verification failed": "Verification failed",
|
"Verification failed": "Verification failed",
|
||||||
"Verify Code": "Verify Code",
|
"Verify Code": "Verify Code",
|
||||||
"Verify Password": "Verify Password",
|
"Verify Password": "Verify Password",
|
||||||
|
"You have enabled Multi-Factor Authentication, Please click 'Send Code' to continue": "You have enabled Multi-Factor Authentication, Please click 'Send Code' to continue",
|
||||||
|
"You have enabled Multi-Factor Authentication, please enter the TOTP code": "You have enabled Multi-Factor Authentication, please enter the TOTP code",
|
||||||
"Your email is": "Your email is",
|
"Your email is": "Your email is",
|
||||||
"Your phone is": "Your phone is",
|
"Your phone is": "Your phone is",
|
||||||
"preferred": "preferred"
|
"preferred": "preferred"
|
||||||
|
@@ -538,7 +538,6 @@
|
|||||||
"Have problems?": "Have problems?",
|
"Have problems?": "Have problems?",
|
||||||
"Multi-factor authentication": "Multi-factor authentication",
|
"Multi-factor authentication": "Multi-factor authentication",
|
||||||
"Multi-factor authentication - Tooltip ": "Multi-factor authentication - Tooltip ",
|
"Multi-factor authentication - Tooltip ": "Multi-factor authentication - Tooltip ",
|
||||||
"Multi-factor authentication description": "Multi-factor authentication description",
|
|
||||||
"Multi-factor methods": "Multi-factor methods",
|
"Multi-factor methods": "Multi-factor methods",
|
||||||
"Multi-factor recover": "Multi-factor recover",
|
"Multi-factor recover": "Multi-factor recover",
|
||||||
"Multi-factor recover description": "Multi-factor recover description",
|
"Multi-factor recover description": "Multi-factor recover description",
|
||||||
@@ -563,6 +562,8 @@
|
|||||||
"Verification failed": "Verification failed",
|
"Verification failed": "Verification failed",
|
||||||
"Verify Code": "Verify Code",
|
"Verify Code": "Verify Code",
|
||||||
"Verify Password": "Verify Password",
|
"Verify Password": "Verify Password",
|
||||||
|
"You have enabled Multi-Factor Authentication, Please click 'Send Code' to continue": "You have enabled Multi-Factor Authentication, Please click 'Send Code' to continue",
|
||||||
|
"You have enabled Multi-Factor Authentication, please enter the TOTP code": "You have enabled Multi-Factor Authentication, please enter the TOTP code",
|
||||||
"Your email is": "Your email is",
|
"Your email is": "Your email is",
|
||||||
"Your phone is": "Your phone is",
|
"Your phone is": "Your phone is",
|
||||||
"preferred": "preferred"
|
"preferred": "preferred"
|
||||||
|
@@ -538,7 +538,6 @@
|
|||||||
"Have problems?": "Have problems?",
|
"Have problems?": "Have problems?",
|
||||||
"Multi-factor authentication": "Multi-factor authentication",
|
"Multi-factor authentication": "Multi-factor authentication",
|
||||||
"Multi-factor authentication - Tooltip ": "Multi-factor authentication - Tooltip ",
|
"Multi-factor authentication - Tooltip ": "Multi-factor authentication - Tooltip ",
|
||||||
"Multi-factor authentication description": "Multi-factor authentication description",
|
|
||||||
"Multi-factor methods": "Multi-factor methods",
|
"Multi-factor methods": "Multi-factor methods",
|
||||||
"Multi-factor recover": "Multi-factor recover",
|
"Multi-factor recover": "Multi-factor recover",
|
||||||
"Multi-factor recover description": "Multi-factor recover description",
|
"Multi-factor recover description": "Multi-factor recover description",
|
||||||
@@ -563,6 +562,8 @@
|
|||||||
"Verification failed": "Verification failed",
|
"Verification failed": "Verification failed",
|
||||||
"Verify Code": "Verify Code",
|
"Verify Code": "Verify Code",
|
||||||
"Verify Password": "Verify Password",
|
"Verify Password": "Verify Password",
|
||||||
|
"You have enabled Multi-Factor Authentication, Please click 'Send Code' to continue": "You have enabled Multi-Factor Authentication, Please click 'Send Code' to continue",
|
||||||
|
"You have enabled Multi-Factor Authentication, please enter the TOTP code": "You have enabled Multi-Factor Authentication, please enter the TOTP code",
|
||||||
"Your email is": "Your email is",
|
"Your email is": "Your email is",
|
||||||
"Your phone is": "Your phone is",
|
"Your phone is": "Your phone is",
|
||||||
"preferred": "preferred"
|
"preferred": "preferred"
|
||||||
|
@@ -538,7 +538,6 @@
|
|||||||
"Have problems?": "Have problems?",
|
"Have problems?": "Have problems?",
|
||||||
"Multi-factor authentication": "Multi-factor authentication",
|
"Multi-factor authentication": "Multi-factor authentication",
|
||||||
"Multi-factor authentication - Tooltip ": "Multi-factor authentication - Tooltip ",
|
"Multi-factor authentication - Tooltip ": "Multi-factor authentication - Tooltip ",
|
||||||
"Multi-factor authentication description": "Multi-factor authentication description",
|
|
||||||
"Multi-factor methods": "Multi-factor methods",
|
"Multi-factor methods": "Multi-factor methods",
|
||||||
"Multi-factor recover": "Multi-factor recover",
|
"Multi-factor recover": "Multi-factor recover",
|
||||||
"Multi-factor recover description": "Multi-factor recover description",
|
"Multi-factor recover description": "Multi-factor recover description",
|
||||||
@@ -563,6 +562,8 @@
|
|||||||
"Verification failed": "Verification failed",
|
"Verification failed": "Verification failed",
|
||||||
"Verify Code": "Verify Code",
|
"Verify Code": "Verify Code",
|
||||||
"Verify Password": "Verify Password",
|
"Verify Password": "Verify Password",
|
||||||
|
"You have enabled Multi-Factor Authentication, Please click 'Send Code' to continue": "You have enabled Multi-Factor Authentication, Please click 'Send Code' to continue",
|
||||||
|
"You have enabled Multi-Factor Authentication, please enter the TOTP code": "You have enabled Multi-Factor Authentication, please enter the TOTP code",
|
||||||
"Your email is": "Your email is",
|
"Your email is": "Your email is",
|
||||||
"Your phone is": "Your phone is",
|
"Your phone is": "Your phone is",
|
||||||
"preferred": "preferred"
|
"preferred": "preferred"
|
||||||
|
@@ -538,7 +538,6 @@
|
|||||||
"Have problems?": "Have problems?",
|
"Have problems?": "Have problems?",
|
||||||
"Multi-factor authentication": "Multi-factor authentication",
|
"Multi-factor authentication": "Multi-factor authentication",
|
||||||
"Multi-factor authentication - Tooltip ": "Multi-factor authentication - Tooltip ",
|
"Multi-factor authentication - Tooltip ": "Multi-factor authentication - Tooltip ",
|
||||||
"Multi-factor authentication description": "Multi-factor authentication description",
|
|
||||||
"Multi-factor methods": "Multi-factor methods",
|
"Multi-factor methods": "Multi-factor methods",
|
||||||
"Multi-factor recover": "Multi-factor recover",
|
"Multi-factor recover": "Multi-factor recover",
|
||||||
"Multi-factor recover description": "Multi-factor recover description",
|
"Multi-factor recover description": "Multi-factor recover description",
|
||||||
@@ -563,6 +562,8 @@
|
|||||||
"Verification failed": "Verification failed",
|
"Verification failed": "Verification failed",
|
||||||
"Verify Code": "Verify Code",
|
"Verify Code": "Verify Code",
|
||||||
"Verify Password": "Verify Password",
|
"Verify Password": "Verify Password",
|
||||||
|
"You have enabled Multi-Factor Authentication, Please click 'Send Code' to continue": "You have enabled Multi-Factor Authentication, Please click 'Send Code' to continue",
|
||||||
|
"You have enabled Multi-Factor Authentication, please enter the TOTP code": "You have enabled Multi-Factor Authentication, please enter the TOTP code",
|
||||||
"Your email is": "Your email is",
|
"Your email is": "Your email is",
|
||||||
"Your phone is": "Your phone is",
|
"Your phone is": "Your phone is",
|
||||||
"preferred": "preferred"
|
"preferred": "preferred"
|
||||||
|
@@ -538,7 +538,6 @@
|
|||||||
"Have problems?": "Des problèmes ?",
|
"Have problems?": "Des problèmes ?",
|
||||||
"Multi-factor authentication": "Authentification multifacteur",
|
"Multi-factor authentication": "Authentification multifacteur",
|
||||||
"Multi-factor authentication - Tooltip ": "Authentification multifacteur - infobulle ",
|
"Multi-factor authentication - Tooltip ": "Authentification multifacteur - infobulle ",
|
||||||
"Multi-factor authentication description": "Description de l'authentification multifacteur",
|
|
||||||
"Multi-factor methods": "Méthodes d'authentification multifacteur",
|
"Multi-factor methods": "Méthodes d'authentification multifacteur",
|
||||||
"Multi-factor recover": "Restauration de l'authentification multifacteur",
|
"Multi-factor recover": "Restauration de l'authentification multifacteur",
|
||||||
"Multi-factor recover description": "Description de la restauration de l'authentification multifacteur",
|
"Multi-factor recover description": "Description de la restauration de l'authentification multifacteur",
|
||||||
@@ -563,6 +562,8 @@
|
|||||||
"Verification failed": "Échec de la vérification",
|
"Verification failed": "Échec de la vérification",
|
||||||
"Verify Code": "Vérifier le code",
|
"Verify Code": "Vérifier le code",
|
||||||
"Verify Password": "Confirmez le mot de passe",
|
"Verify Password": "Confirmez le mot de passe",
|
||||||
|
"You have enabled Multi-Factor Authentication, Please click 'Send Code' to continue": "You have enabled Multi-Factor Authentication, Please click 'Send Code' to continue",
|
||||||
|
"You have enabled Multi-Factor Authentication, please enter the TOTP code": "You have enabled Multi-Factor Authentication, please enter the TOTP code",
|
||||||
"Your email is": "Votre e-mail est",
|
"Your email is": "Votre e-mail est",
|
||||||
"Your phone is": "Votre téléphone est",
|
"Your phone is": "Votre téléphone est",
|
||||||
"preferred": "préféré"
|
"preferred": "préféré"
|
||||||
|
@@ -538,7 +538,6 @@
|
|||||||
"Have problems?": "Have problems?",
|
"Have problems?": "Have problems?",
|
||||||
"Multi-factor authentication": "Multi-factor authentication",
|
"Multi-factor authentication": "Multi-factor authentication",
|
||||||
"Multi-factor authentication - Tooltip ": "Multi-factor authentication - Tooltip ",
|
"Multi-factor authentication - Tooltip ": "Multi-factor authentication - Tooltip ",
|
||||||
"Multi-factor authentication description": "Multi-factor authentication description",
|
|
||||||
"Multi-factor methods": "Multi-factor methods",
|
"Multi-factor methods": "Multi-factor methods",
|
||||||
"Multi-factor recover": "Multi-factor recover",
|
"Multi-factor recover": "Multi-factor recover",
|
||||||
"Multi-factor recover description": "Multi-factor recover description",
|
"Multi-factor recover description": "Multi-factor recover description",
|
||||||
@@ -563,6 +562,8 @@
|
|||||||
"Verification failed": "Verification failed",
|
"Verification failed": "Verification failed",
|
||||||
"Verify Code": "Verify Code",
|
"Verify Code": "Verify Code",
|
||||||
"Verify Password": "Verify Password",
|
"Verify Password": "Verify Password",
|
||||||
|
"You have enabled Multi-Factor Authentication, Please click 'Send Code' to continue": "You have enabled Multi-Factor Authentication, Please click 'Send Code' to continue",
|
||||||
|
"You have enabled Multi-Factor Authentication, please enter the TOTP code": "You have enabled Multi-Factor Authentication, please enter the TOTP code",
|
||||||
"Your email is": "Your email is",
|
"Your email is": "Your email is",
|
||||||
"Your phone is": "Your phone is",
|
"Your phone is": "Your phone is",
|
||||||
"preferred": "preferred"
|
"preferred": "preferred"
|
||||||
|
@@ -538,7 +538,6 @@
|
|||||||
"Have problems?": "Have problems?",
|
"Have problems?": "Have problems?",
|
||||||
"Multi-factor authentication": "Multi-factor authentication",
|
"Multi-factor authentication": "Multi-factor authentication",
|
||||||
"Multi-factor authentication - Tooltip ": "Multi-factor authentication - Tooltip ",
|
"Multi-factor authentication - Tooltip ": "Multi-factor authentication - Tooltip ",
|
||||||
"Multi-factor authentication description": "Multi-factor authentication description",
|
|
||||||
"Multi-factor methods": "Multi-factor methods",
|
"Multi-factor methods": "Multi-factor methods",
|
||||||
"Multi-factor recover": "Multi-factor recover",
|
"Multi-factor recover": "Multi-factor recover",
|
||||||
"Multi-factor recover description": "Multi-factor recover description",
|
"Multi-factor recover description": "Multi-factor recover description",
|
||||||
@@ -563,6 +562,8 @@
|
|||||||
"Verification failed": "Verification failed",
|
"Verification failed": "Verification failed",
|
||||||
"Verify Code": "Verify Code",
|
"Verify Code": "Verify Code",
|
||||||
"Verify Password": "Verify Password",
|
"Verify Password": "Verify Password",
|
||||||
|
"You have enabled Multi-Factor Authentication, Please click 'Send Code' to continue": "You have enabled Multi-Factor Authentication, Please click 'Send Code' to continue",
|
||||||
|
"You have enabled Multi-Factor Authentication, please enter the TOTP code": "You have enabled Multi-Factor Authentication, please enter the TOTP code",
|
||||||
"Your email is": "Your email is",
|
"Your email is": "Your email is",
|
||||||
"Your phone is": "Your phone is",
|
"Your phone is": "Your phone is",
|
||||||
"preferred": "preferred"
|
"preferred": "preferred"
|
||||||
|
@@ -538,7 +538,6 @@
|
|||||||
"Have problems?": "Have problems?",
|
"Have problems?": "Have problems?",
|
||||||
"Multi-factor authentication": "Multi-factor authentication",
|
"Multi-factor authentication": "Multi-factor authentication",
|
||||||
"Multi-factor authentication - Tooltip ": "Multi-factor authentication - Tooltip ",
|
"Multi-factor authentication - Tooltip ": "Multi-factor authentication - Tooltip ",
|
||||||
"Multi-factor authentication description": "Multi-factor authentication description",
|
|
||||||
"Multi-factor methods": "Multi-factor methods",
|
"Multi-factor methods": "Multi-factor methods",
|
||||||
"Multi-factor recover": "Multi-factor recover",
|
"Multi-factor recover": "Multi-factor recover",
|
||||||
"Multi-factor recover description": "Multi-factor recover description",
|
"Multi-factor recover description": "Multi-factor recover description",
|
||||||
@@ -563,6 +562,8 @@
|
|||||||
"Verification failed": "Verification failed",
|
"Verification failed": "Verification failed",
|
||||||
"Verify Code": "Verify Code",
|
"Verify Code": "Verify Code",
|
||||||
"Verify Password": "Verify Password",
|
"Verify Password": "Verify Password",
|
||||||
|
"You have enabled Multi-Factor Authentication, Please click 'Send Code' to continue": "You have enabled Multi-Factor Authentication, Please click 'Send Code' to continue",
|
||||||
|
"You have enabled Multi-Factor Authentication, please enter the TOTP code": "You have enabled Multi-Factor Authentication, please enter the TOTP code",
|
||||||
"Your email is": "Your email is",
|
"Your email is": "Your email is",
|
||||||
"Your phone is": "Your phone is",
|
"Your phone is": "Your phone is",
|
||||||
"preferred": "preferred"
|
"preferred": "preferred"
|
||||||
|
@@ -538,7 +538,6 @@
|
|||||||
"Have problems?": "Have problems?",
|
"Have problems?": "Have problems?",
|
||||||
"Multi-factor authentication": "Multi-factor authentication",
|
"Multi-factor authentication": "Multi-factor authentication",
|
||||||
"Multi-factor authentication - Tooltip ": "Multi-factor authentication - Tooltip ",
|
"Multi-factor authentication - Tooltip ": "Multi-factor authentication - Tooltip ",
|
||||||
"Multi-factor authentication description": "Multi-factor authentication description",
|
|
||||||
"Multi-factor methods": "Multi-factor methods",
|
"Multi-factor methods": "Multi-factor methods",
|
||||||
"Multi-factor recover": "Multi-factor recover",
|
"Multi-factor recover": "Multi-factor recover",
|
||||||
"Multi-factor recover description": "Multi-factor recover description",
|
"Multi-factor recover description": "Multi-factor recover description",
|
||||||
@@ -563,6 +562,8 @@
|
|||||||
"Verification failed": "Verification failed",
|
"Verification failed": "Verification failed",
|
||||||
"Verify Code": "Verify Code",
|
"Verify Code": "Verify Code",
|
||||||
"Verify Password": "Verify Password",
|
"Verify Password": "Verify Password",
|
||||||
|
"You have enabled Multi-Factor Authentication, Please click 'Send Code' to continue": "You have enabled Multi-Factor Authentication, Please click 'Send Code' to continue",
|
||||||
|
"You have enabled Multi-Factor Authentication, please enter the TOTP code": "You have enabled Multi-Factor Authentication, please enter the TOTP code",
|
||||||
"Your email is": "Your email is",
|
"Your email is": "Your email is",
|
||||||
"Your phone is": "Your phone is",
|
"Your phone is": "Your phone is",
|
||||||
"preferred": "preferred"
|
"preferred": "preferred"
|
||||||
|
@@ -538,7 +538,6 @@
|
|||||||
"Have problems?": "Have problems?",
|
"Have problems?": "Have problems?",
|
||||||
"Multi-factor authentication": "Multi-factor authentication",
|
"Multi-factor authentication": "Multi-factor authentication",
|
||||||
"Multi-factor authentication - Tooltip ": "Multi-factor authentication - Tooltip ",
|
"Multi-factor authentication - Tooltip ": "Multi-factor authentication - Tooltip ",
|
||||||
"Multi-factor authentication description": "Multi-factor authentication description",
|
|
||||||
"Multi-factor methods": "Multi-factor methods",
|
"Multi-factor methods": "Multi-factor methods",
|
||||||
"Multi-factor recover": "Multi-factor recover",
|
"Multi-factor recover": "Multi-factor recover",
|
||||||
"Multi-factor recover description": "Multi-factor recover description",
|
"Multi-factor recover description": "Multi-factor recover description",
|
||||||
@@ -563,6 +562,8 @@
|
|||||||
"Verification failed": "Verification failed",
|
"Verification failed": "Verification failed",
|
||||||
"Verify Code": "Verify Code",
|
"Verify Code": "Verify Code",
|
||||||
"Verify Password": "Verify Password",
|
"Verify Password": "Verify Password",
|
||||||
|
"You have enabled Multi-Factor Authentication, Please click 'Send Code' to continue": "You have enabled Multi-Factor Authentication, Please click 'Send Code' to continue",
|
||||||
|
"You have enabled Multi-Factor Authentication, please enter the TOTP code": "You have enabled Multi-Factor Authentication, please enter the TOTP code",
|
||||||
"Your email is": "Your email is",
|
"Your email is": "Your email is",
|
||||||
"Your phone is": "Your phone is",
|
"Your phone is": "Your phone is",
|
||||||
"preferred": "preferred"
|
"preferred": "preferred"
|
||||||
|
@@ -538,7 +538,6 @@
|
|||||||
"Have problems?": "Have problems?",
|
"Have problems?": "Have problems?",
|
||||||
"Multi-factor authentication": "Multi-factor authentication",
|
"Multi-factor authentication": "Multi-factor authentication",
|
||||||
"Multi-factor authentication - Tooltip ": "Multi-factor authentication - Tooltip ",
|
"Multi-factor authentication - Tooltip ": "Multi-factor authentication - Tooltip ",
|
||||||
"Multi-factor authentication description": "Multi-factor authentication description",
|
|
||||||
"Multi-factor methods": "Multi-factor methods",
|
"Multi-factor methods": "Multi-factor methods",
|
||||||
"Multi-factor recover": "Multi-factor recover",
|
"Multi-factor recover": "Multi-factor recover",
|
||||||
"Multi-factor recover description": "Multi-factor recover description",
|
"Multi-factor recover description": "Multi-factor recover description",
|
||||||
@@ -563,6 +562,8 @@
|
|||||||
"Verification failed": "Verification failed",
|
"Verification failed": "Verification failed",
|
||||||
"Verify Code": "Verify Code",
|
"Verify Code": "Verify Code",
|
||||||
"Verify Password": "Verify Password",
|
"Verify Password": "Verify Password",
|
||||||
|
"You have enabled Multi-Factor Authentication, Please click 'Send Code' to continue": "You have enabled Multi-Factor Authentication, Please click 'Send Code' to continue",
|
||||||
|
"You have enabled Multi-Factor Authentication, please enter the TOTP code": "You have enabled Multi-Factor Authentication, please enter the TOTP code",
|
||||||
"Your email is": "Your email is",
|
"Your email is": "Your email is",
|
||||||
"Your phone is": "Your phone is",
|
"Your phone is": "Your phone is",
|
||||||
"preferred": "preferred"
|
"preferred": "preferred"
|
||||||
|
@@ -538,7 +538,6 @@
|
|||||||
"Have problems?": "Have problems?",
|
"Have problems?": "Have problems?",
|
||||||
"Multi-factor authentication": "Multi-factor authentication",
|
"Multi-factor authentication": "Multi-factor authentication",
|
||||||
"Multi-factor authentication - Tooltip ": "Multi-factor authentication - Tooltip ",
|
"Multi-factor authentication - Tooltip ": "Multi-factor authentication - Tooltip ",
|
||||||
"Multi-factor authentication description": "Multi-factor authentication description",
|
|
||||||
"Multi-factor methods": "Multi-factor methods",
|
"Multi-factor methods": "Multi-factor methods",
|
||||||
"Multi-factor recover": "Multi-factor recover",
|
"Multi-factor recover": "Multi-factor recover",
|
||||||
"Multi-factor recover description": "Multi-factor recover description",
|
"Multi-factor recover description": "Multi-factor recover description",
|
||||||
@@ -563,6 +562,8 @@
|
|||||||
"Verification failed": "Verification failed",
|
"Verification failed": "Verification failed",
|
||||||
"Verify Code": "Verify Code",
|
"Verify Code": "Verify Code",
|
||||||
"Verify Password": "Verify Password",
|
"Verify Password": "Verify Password",
|
||||||
|
"You have enabled Multi-Factor Authentication, Please click 'Send Code' to continue": "You have enabled Multi-Factor Authentication, Please click 'Send Code' to continue",
|
||||||
|
"You have enabled Multi-Factor Authentication, please enter the TOTP code": "You have enabled Multi-Factor Authentication, please enter the TOTP code",
|
||||||
"Your email is": "Your email is",
|
"Your email is": "Your email is",
|
||||||
"Your phone is": "Your phone is",
|
"Your phone is": "Your phone is",
|
||||||
"preferred": "preferred"
|
"preferred": "preferred"
|
||||||
|
@@ -538,7 +538,6 @@
|
|||||||
"Have problems?": "Have problems?",
|
"Have problems?": "Have problems?",
|
||||||
"Multi-factor authentication": "Multi-factor authentication",
|
"Multi-factor authentication": "Multi-factor authentication",
|
||||||
"Multi-factor authentication - Tooltip ": "Multi-factor authentication - Tooltip ",
|
"Multi-factor authentication - Tooltip ": "Multi-factor authentication - Tooltip ",
|
||||||
"Multi-factor authentication description": "Multi-factor authentication description",
|
|
||||||
"Multi-factor methods": "Multi-factor methods",
|
"Multi-factor methods": "Multi-factor methods",
|
||||||
"Multi-factor recover": "Multi-factor recover",
|
"Multi-factor recover": "Multi-factor recover",
|
||||||
"Multi-factor recover description": "Multi-factor recover description",
|
"Multi-factor recover description": "Multi-factor recover description",
|
||||||
@@ -563,6 +562,8 @@
|
|||||||
"Verification failed": "Verification failed",
|
"Verification failed": "Verification failed",
|
||||||
"Verify Code": "Verify Code",
|
"Verify Code": "Verify Code",
|
||||||
"Verify Password": "Verify Password",
|
"Verify Password": "Verify Password",
|
||||||
|
"You have enabled Multi-Factor Authentication, Please click 'Send Code' to continue": "You have enabled Multi-Factor Authentication, Please click 'Send Code' to continue",
|
||||||
|
"You have enabled Multi-Factor Authentication, please enter the TOTP code": "You have enabled Multi-Factor Authentication, please enter the TOTP code",
|
||||||
"Your email is": "Your email is",
|
"Your email is": "Your email is",
|
||||||
"Your phone is": "Your phone is",
|
"Your phone is": "Your phone is",
|
||||||
"preferred": "preferred"
|
"preferred": "preferred"
|
||||||
|
@@ -538,7 +538,6 @@
|
|||||||
"Have problems?": "Have problems?",
|
"Have problems?": "Have problems?",
|
||||||
"Multi-factor authentication": "Multi-factor authentication",
|
"Multi-factor authentication": "Multi-factor authentication",
|
||||||
"Multi-factor authentication - Tooltip ": "Multi-factor authentication - Tooltip ",
|
"Multi-factor authentication - Tooltip ": "Multi-factor authentication - Tooltip ",
|
||||||
"Multi-factor authentication description": "Multi-factor authentication description",
|
|
||||||
"Multi-factor methods": "Multi-factor methods",
|
"Multi-factor methods": "Multi-factor methods",
|
||||||
"Multi-factor recover": "Multi-factor recover",
|
"Multi-factor recover": "Multi-factor recover",
|
||||||
"Multi-factor recover description": "Multi-factor recover description",
|
"Multi-factor recover description": "Multi-factor recover description",
|
||||||
@@ -563,6 +562,8 @@
|
|||||||
"Verification failed": "Verification failed",
|
"Verification failed": "Verification failed",
|
||||||
"Verify Code": "Verify Code",
|
"Verify Code": "Verify Code",
|
||||||
"Verify Password": "Verify Password",
|
"Verify Password": "Verify Password",
|
||||||
|
"You have enabled Multi-Factor Authentication, Please click 'Send Code' to continue": "You have enabled Multi-Factor Authentication, Please click 'Send Code' to continue",
|
||||||
|
"You have enabled Multi-Factor Authentication, please enter the TOTP code": "You have enabled Multi-Factor Authentication, please enter the TOTP code",
|
||||||
"Your email is": "Your email is",
|
"Your email is": "Your email is",
|
||||||
"Your phone is": "Your phone is",
|
"Your phone is": "Your phone is",
|
||||||
"preferred": "preferred"
|
"preferred": "preferred"
|
||||||
|
@@ -538,7 +538,6 @@
|
|||||||
"Have problems?": "Tem problemas?",
|
"Have problems?": "Tem problemas?",
|
||||||
"Multi-factor authentication": "Autenticação de vários fatores",
|
"Multi-factor authentication": "Autenticação de vários fatores",
|
||||||
"Multi-factor authentication - Tooltip ": "Autenticação de múltiplos fatores - Tooltip ",
|
"Multi-factor authentication - Tooltip ": "Autenticação de múltiplos fatores - Tooltip ",
|
||||||
"Multi-factor authentication description": "Multi-factor authentication description",
|
|
||||||
"Multi-factor methods": "Multi-factor methods",
|
"Multi-factor methods": "Multi-factor methods",
|
||||||
"Multi-factor recover": "Multi-factor recover",
|
"Multi-factor recover": "Multi-factor recover",
|
||||||
"Multi-factor recover description": "Multi-factor recover description",
|
"Multi-factor recover description": "Multi-factor recover description",
|
||||||
@@ -563,6 +562,8 @@
|
|||||||
"Verification failed": "Verification failed",
|
"Verification failed": "Verification failed",
|
||||||
"Verify Code": "Verify Code",
|
"Verify Code": "Verify Code",
|
||||||
"Verify Password": "Verify Password",
|
"Verify Password": "Verify Password",
|
||||||
|
"You have enabled Multi-Factor Authentication, Please click 'Send Code' to continue": "You have enabled Multi-Factor Authentication, Please click 'Send Code' to continue",
|
||||||
|
"You have enabled Multi-Factor Authentication, please enter the TOTP code": "You have enabled Multi-Factor Authentication, please enter the TOTP code",
|
||||||
"Your email is": "Your email is",
|
"Your email is": "Your email is",
|
||||||
"Your phone is": "Your phone is",
|
"Your phone is": "Your phone is",
|
||||||
"preferred": "preferred"
|
"preferred": "preferred"
|
||||||
|
@@ -538,7 +538,6 @@
|
|||||||
"Have problems?": "Возникли проблемы?",
|
"Have problems?": "Возникли проблемы?",
|
||||||
"Multi-factor authentication": "Многофакторная аутентификация",
|
"Multi-factor authentication": "Многофакторная аутентификация",
|
||||||
"Multi-factor authentication - Tooltip ": "Multi-factor authentication - Tooltip ",
|
"Multi-factor authentication - Tooltip ": "Multi-factor authentication - Tooltip ",
|
||||||
"Multi-factor authentication description": "Multi-factor authentication description",
|
|
||||||
"Multi-factor methods": "Multi-factor methods",
|
"Multi-factor methods": "Multi-factor methods",
|
||||||
"Multi-factor recover": "Multi-factor recover",
|
"Multi-factor recover": "Multi-factor recover",
|
||||||
"Multi-factor recover description": "Multi-factor recover description",
|
"Multi-factor recover description": "Multi-factor recover description",
|
||||||
@@ -563,6 +562,8 @@
|
|||||||
"Verification failed": "Проверка не удалась",
|
"Verification failed": "Проверка не удалась",
|
||||||
"Verify Code": "Verify Code",
|
"Verify Code": "Verify Code",
|
||||||
"Verify Password": "Verify Password",
|
"Verify Password": "Verify Password",
|
||||||
|
"You have enabled Multi-Factor Authentication, Please click 'Send Code' to continue": "You have enabled Multi-Factor Authentication, Please click 'Send Code' to continue",
|
||||||
|
"You have enabled Multi-Factor Authentication, please enter the TOTP code": "You have enabled Multi-Factor Authentication, please enter the TOTP code",
|
||||||
"Your email is": "Ваш email",
|
"Your email is": "Ваш email",
|
||||||
"Your phone is": "Ваш телефон",
|
"Your phone is": "Ваш телефон",
|
||||||
"preferred": "preferred"
|
"preferred": "preferred"
|
||||||
@@ -971,7 +972,7 @@
|
|||||||
"Please input your affiliation!": "Пожалуйста, укажите свою принадлежность!",
|
"Please input your affiliation!": "Пожалуйста, укажите свою принадлежность!",
|
||||||
"Please input your display name!": "Пожалуйста, введите своё отображаемое имя!",
|
"Please input your display name!": "Пожалуйста, введите своё отображаемое имя!",
|
||||||
"Please input your first name!": "Пожалуйста, введите свое имя!",
|
"Please input your first name!": "Пожалуйста, введите свое имя!",
|
||||||
"Please input your invitation code!": "Please input your invitation code!",
|
"Please input your invitation code!": "Пожалуйста, введите код приглашения!",
|
||||||
"Please input your last name!": "Введите свою фамилию!",
|
"Please input your last name!": "Введите свою фамилию!",
|
||||||
"Please input your phone number!": "Пожалуйста, введите свой номер телефона!",
|
"Please input your phone number!": "Пожалуйста, введите свой номер телефона!",
|
||||||
"Please input your real name!": "Пожалуйста, введите своё настоящее имя!",
|
"Please input your real name!": "Пожалуйста, введите своё настоящее имя!",
|
||||||
@@ -1162,9 +1163,9 @@
|
|||||||
"MFA accounts": "MFA accounts",
|
"MFA accounts": "MFA accounts",
|
||||||
"Managed accounts": "Управляемые аккаунты",
|
"Managed accounts": "Управляемые аккаунты",
|
||||||
"Modify password...": "Изменить пароль...",
|
"Modify password...": "Изменить пароль...",
|
||||||
"Multi-factor authentication": "Multi-factor authentication",
|
"Multi-factor authentication": "Многофакторная аутентификация",
|
||||||
"Need update password": "Need update password",
|
"Need update password": "Необходимо обновить пароль",
|
||||||
"Need update password - Tooltip": "Force user update password after login",
|
"Need update password - Tooltip": "Заставить пользователя обновить пароль после входа в систему",
|
||||||
"New Email": "Новое электронное письмо",
|
"New Email": "Новое электронное письмо",
|
||||||
"New Password": "Новый пароль",
|
"New Password": "Новый пароль",
|
||||||
"New User": "Новый пользователь",
|
"New User": "Новый пользователь",
|
||||||
@@ -1188,26 +1189,26 @@
|
|||||||
"Set password...": "Установить пароль...",
|
"Set password...": "Установить пароль...",
|
||||||
"Tag": "Метка",
|
"Tag": "Метка",
|
||||||
"Tag - Tooltip": "Тег пользователя",
|
"Tag - Tooltip": "Тег пользователя",
|
||||||
"The password must contain at least one special character": "The password must contain at least one special character",
|
"The password must contain at least one special character": "Пароль должен содержать хотя бы один специальный символ",
|
||||||
"The password must contain at least one uppercase letter, one lowercase letter and one digit": "The password must contain at least one uppercase letter, one lowercase letter and one digit",
|
"The password must contain at least one uppercase letter, one lowercase letter and one digit": "Пароль должен содержать как минимум одну заглавную букву, одну строчную букву и одну цифру",
|
||||||
"The password must have at least 6 characters": "The password must have at least 6 characters",
|
"The password must have at least 6 characters": "Пароль должен быть минимум 6 символов",
|
||||||
"The password must have at least 8 characters": "The password must have at least 8 characters",
|
"The password must have at least 8 characters": "Пароль должен быть минимум 8 символов",
|
||||||
"The password must not contain any repeated characters": "The password must not contain any repeated characters",
|
"The password must not contain any repeated characters": "Пароль не должен содержать повторяющиеся символы",
|
||||||
"This field value doesn't match the pattern rule": "This field value doesn't match the pattern rule",
|
"This field value doesn't match the pattern rule": "Значение поля не соответствует шаблону",
|
||||||
"Title": "Заголовок",
|
"Title": "Заголовок",
|
||||||
"Title - Tooltip": "Положение в аффилиации",
|
"Title - Tooltip": "Положение в аффилиации",
|
||||||
"Two passwords you typed do not match.": "Два введенных вами пароля не совпадают.",
|
"Two passwords you typed do not match.": "Два введенных вами пароля не совпадают.",
|
||||||
"Unlink": "Отсоединить",
|
"Unlink": "Отсоединить",
|
||||||
"Upload (.xlsx)": "Загрузить (.xlsx)",
|
"Upload (.xlsx)": "Загрузить (.xlsx)",
|
||||||
"Upload ID card back picture": "Upload ID card back picture",
|
"Upload ID card back picture": "Загрузите заднюю сторону удостоверения личности",
|
||||||
"Upload ID card front picture": "Upload ID card front picture",
|
"Upload ID card front picture": "Загрузите переднюю сторону удостоверения личности",
|
||||||
"Upload ID card with person picture": "Upload ID card with person picture",
|
"Upload ID card with person picture": "Загрузите удостоверение личности с фотографией",
|
||||||
"Upload a photo": "Загрузить фото",
|
"Upload a photo": "Загрузить фото",
|
||||||
"User Profile": "User Profile",
|
"User Profile": "Профиль пользователя",
|
||||||
"Values": "Значения",
|
"Values": "Значения",
|
||||||
"Verification code sent": "Код подтверждения отправлен",
|
"Verification code sent": "Код подтверждения отправлен",
|
||||||
"WebAuthn credentials": "WebAuthn удостоверения",
|
"WebAuthn credentials": "WebAuthn удостоверения",
|
||||||
"You have changed the username, please save your change first before modifying the password": "You have changed the username, please save your change first before modifying the password",
|
"You have changed the username, please save your change first before modifying the password": "Имя было изменено, сохраните изменения перед сменой пароля",
|
||||||
"input password": "введите пароль"
|
"input password": "введите пароль"
|
||||||
},
|
},
|
||||||
"verification": {
|
"verification": {
|
||||||
|
@@ -538,7 +538,6 @@
|
|||||||
"Have problems?": "Máte problémy?",
|
"Have problems?": "Máte problémy?",
|
||||||
"Multi-factor authentication": "Viacfaktorová autentifikácia",
|
"Multi-factor authentication": "Viacfaktorová autentifikácia",
|
||||||
"Multi-factor authentication - Tooltip ": "Viacfaktorová autentifikácia - Nápoveda ",
|
"Multi-factor authentication - Tooltip ": "Viacfaktorová autentifikácia - Nápoveda ",
|
||||||
"Multi-factor authentication description": "Popis viacfaktorovej autentifikácie",
|
|
||||||
"Multi-factor methods": "Metódy viacfaktorovej autentifikácie",
|
"Multi-factor methods": "Metódy viacfaktorovej autentifikácie",
|
||||||
"Multi-factor recover": "Obnova viacfaktorovej autentifikácie",
|
"Multi-factor recover": "Obnova viacfaktorovej autentifikácie",
|
||||||
"Multi-factor recover description": "Popis obnovy viacfaktorovej autentifikácie",
|
"Multi-factor recover description": "Popis obnovy viacfaktorovej autentifikácie",
|
||||||
@@ -563,6 +562,8 @@
|
|||||||
"Verification failed": "Overenie zlyhalo",
|
"Verification failed": "Overenie zlyhalo",
|
||||||
"Verify Code": "Overiť kód",
|
"Verify Code": "Overiť kód",
|
||||||
"Verify Password": "Overiť heslo",
|
"Verify Password": "Overiť heslo",
|
||||||
|
"You have enabled Multi-Factor Authentication, Please click 'Send Code' to continue": "You have enabled Multi-Factor Authentication, Please click 'Send Code' to continue",
|
||||||
|
"You have enabled Multi-Factor Authentication, please enter the TOTP code": "You have enabled Multi-Factor Authentication, please enter the TOTP code",
|
||||||
"Your email is": "Váš email je",
|
"Your email is": "Váš email je",
|
||||||
"Your phone is": "Váš telefón je",
|
"Your phone is": "Váš telefón je",
|
||||||
"preferred": "preferované"
|
"preferred": "preferované"
|
||||||
|
@@ -538,7 +538,6 @@
|
|||||||
"Have problems?": "Have problems?",
|
"Have problems?": "Have problems?",
|
||||||
"Multi-factor authentication": "Multi-factor authentication",
|
"Multi-factor authentication": "Multi-factor authentication",
|
||||||
"Multi-factor authentication - Tooltip ": "Multi-factor authentication - Tooltip ",
|
"Multi-factor authentication - Tooltip ": "Multi-factor authentication - Tooltip ",
|
||||||
"Multi-factor authentication description": "Multi-factor authentication description",
|
|
||||||
"Multi-factor methods": "Multi-factor methods",
|
"Multi-factor methods": "Multi-factor methods",
|
||||||
"Multi-factor recover": "Multi-factor recover",
|
"Multi-factor recover": "Multi-factor recover",
|
||||||
"Multi-factor recover description": "Multi-factor recover description",
|
"Multi-factor recover description": "Multi-factor recover description",
|
||||||
@@ -563,6 +562,8 @@
|
|||||||
"Verification failed": "Verification failed",
|
"Verification failed": "Verification failed",
|
||||||
"Verify Code": "Verify Code",
|
"Verify Code": "Verify Code",
|
||||||
"Verify Password": "Verify Password",
|
"Verify Password": "Verify Password",
|
||||||
|
"You have enabled Multi-Factor Authentication, Please click 'Send Code' to continue": "You have enabled Multi-Factor Authentication, Please click 'Send Code' to continue",
|
||||||
|
"You have enabled Multi-Factor Authentication, please enter the TOTP code": "You have enabled Multi-Factor Authentication, please enter the TOTP code",
|
||||||
"Your email is": "Your email is",
|
"Your email is": "Your email is",
|
||||||
"Your phone is": "Your phone is",
|
"Your phone is": "Your phone is",
|
||||||
"preferred": "preferred"
|
"preferred": "preferred"
|
||||||
|
@@ -538,7 +538,6 @@
|
|||||||
"Have problems?": "Have problems?",
|
"Have problems?": "Have problems?",
|
||||||
"Multi-factor authentication": "Multi-factor authentication",
|
"Multi-factor authentication": "Multi-factor authentication",
|
||||||
"Multi-factor authentication - Tooltip ": "Multi-factor authentication - Tooltip ",
|
"Multi-factor authentication - Tooltip ": "Multi-factor authentication - Tooltip ",
|
||||||
"Multi-factor authentication description": "Multi-factor authentication description",
|
|
||||||
"Multi-factor methods": "Multi-factor methods",
|
"Multi-factor methods": "Multi-factor methods",
|
||||||
"Multi-factor recover": "Multi-factor recover",
|
"Multi-factor recover": "Multi-factor recover",
|
||||||
"Multi-factor recover description": "Multi-factor recover description",
|
"Multi-factor recover description": "Multi-factor recover description",
|
||||||
@@ -563,6 +562,8 @@
|
|||||||
"Verification failed": "Doğrulama başarısız",
|
"Verification failed": "Doğrulama başarısız",
|
||||||
"Verify Code": "Kodu doğrula",
|
"Verify Code": "Kodu doğrula",
|
||||||
"Verify Password": "Parolayı Doğrula",
|
"Verify Password": "Parolayı Doğrula",
|
||||||
|
"You have enabled Multi-Factor Authentication, Please click 'Send Code' to continue": "You have enabled Multi-Factor Authentication, Please click 'Send Code' to continue",
|
||||||
|
"You have enabled Multi-Factor Authentication, please enter the TOTP code": "You have enabled Multi-Factor Authentication, please enter the TOTP code",
|
||||||
"Your email is": "E-postanız",
|
"Your email is": "E-postanız",
|
||||||
"Your phone is": "Telefon numaranız",
|
"Your phone is": "Telefon numaranız",
|
||||||
"preferred": "tercih edilen"
|
"preferred": "tercih edilen"
|
||||||
|
@@ -538,7 +538,6 @@
|
|||||||
"Have problems?": "Є проблеми?",
|
"Have problems?": "Є проблеми?",
|
||||||
"Multi-factor authentication": "Багатофакторна аутентифікація",
|
"Multi-factor authentication": "Багатофакторна аутентифікація",
|
||||||
"Multi-factor authentication - Tooltip ": "Багатофакторна автентифікація – підказка ",
|
"Multi-factor authentication - Tooltip ": "Багатофакторна автентифікація – підказка ",
|
||||||
"Multi-factor authentication description": "Опис багатофакторної автентифікації",
|
|
||||||
"Multi-factor methods": "Багатофакторні методи",
|
"Multi-factor methods": "Багатофакторні методи",
|
||||||
"Multi-factor recover": "Багатофакторне відновлення",
|
"Multi-factor recover": "Багатофакторне відновлення",
|
||||||
"Multi-factor recover description": "Опис багатофакторного відновлення",
|
"Multi-factor recover description": "Опис багатофакторного відновлення",
|
||||||
@@ -563,6 +562,8 @@
|
|||||||
"Verification failed": "Не вдалося перевірити",
|
"Verification failed": "Не вдалося перевірити",
|
||||||
"Verify Code": "Підтвердити код",
|
"Verify Code": "Підтвердити код",
|
||||||
"Verify Password": "Підтвердіть пароль",
|
"Verify Password": "Підтвердіть пароль",
|
||||||
|
"You have enabled Multi-Factor Authentication, Please click 'Send Code' to continue": "You have enabled Multi-Factor Authentication, Please click 'Send Code' to continue",
|
||||||
|
"You have enabled Multi-Factor Authentication, please enter the TOTP code": "You have enabled Multi-Factor Authentication, please enter the TOTP code",
|
||||||
"Your email is": "Ваша електронна адреса",
|
"Your email is": "Ваша електронна адреса",
|
||||||
"Your phone is": "Ваш телефон",
|
"Your phone is": "Ваш телефон",
|
||||||
"preferred": "бажаний"
|
"preferred": "бажаний"
|
||||||
|
@@ -538,7 +538,6 @@
|
|||||||
"Have problems?": "Have problems?",
|
"Have problems?": "Have problems?",
|
||||||
"Multi-factor authentication": "Multi-factor authentication",
|
"Multi-factor authentication": "Multi-factor authentication",
|
||||||
"Multi-factor authentication - Tooltip ": "Multi-factor authentication - Tooltip ",
|
"Multi-factor authentication - Tooltip ": "Multi-factor authentication - Tooltip ",
|
||||||
"Multi-factor authentication description": "Multi-factor authentication description",
|
|
||||||
"Multi-factor methods": "Multi-factor methods",
|
"Multi-factor methods": "Multi-factor methods",
|
||||||
"Multi-factor recover": "Multi-factor recover",
|
"Multi-factor recover": "Multi-factor recover",
|
||||||
"Multi-factor recover description": "Multi-factor recover description",
|
"Multi-factor recover description": "Multi-factor recover description",
|
||||||
@@ -563,6 +562,8 @@
|
|||||||
"Verification failed": "Verification failed",
|
"Verification failed": "Verification failed",
|
||||||
"Verify Code": "Verify Code",
|
"Verify Code": "Verify Code",
|
||||||
"Verify Password": "Verify Password",
|
"Verify Password": "Verify Password",
|
||||||
|
"You have enabled Multi-Factor Authentication, Please click 'Send Code' to continue": "You have enabled Multi-Factor Authentication, Please click 'Send Code' to continue",
|
||||||
|
"You have enabled Multi-Factor Authentication, please enter the TOTP code": "You have enabled Multi-Factor Authentication, please enter the TOTP code",
|
||||||
"Your email is": "Your email is",
|
"Your email is": "Your email is",
|
||||||
"Your phone is": "Your phone is",
|
"Your phone is": "Your phone is",
|
||||||
"preferred": "preferred"
|
"preferred": "preferred"
|
||||||
|
@@ -538,7 +538,6 @@
|
|||||||
"Have problems?": "遇到问题?",
|
"Have problems?": "遇到问题?",
|
||||||
"Multi-factor authentication": "多因素认证",
|
"Multi-factor authentication": "多因素认证",
|
||||||
"Multi-factor authentication - Tooltip ": "多因素认证 - Tooltip ",
|
"Multi-factor authentication - Tooltip ": "多因素认证 - Tooltip ",
|
||||||
"Multi-factor authentication description": "您已经启用多因素认证,请输入认证码",
|
|
||||||
"Multi-factor methods": "多因素认证方式",
|
"Multi-factor methods": "多因素认证方式",
|
||||||
"Multi-factor recover": "重置多因素认证",
|
"Multi-factor recover": "重置多因素认证",
|
||||||
"Multi-factor recover description": "如果您无法访问您的设备,输入您的多因素认证恢复代码来确认您的身份",
|
"Multi-factor recover description": "如果您无法访问您的设备,输入您的多因素认证恢复代码来确认您的身份",
|
||||||
@@ -563,6 +562,8 @@
|
|||||||
"Verification failed": "验证失败",
|
"Verification failed": "验证失败",
|
||||||
"Verify Code": "验证码",
|
"Verify Code": "验证码",
|
||||||
"Verify Password": "验证密码",
|
"Verify Password": "验证密码",
|
||||||
|
"You have enabled Multi-Factor Authentication, Please click 'Send Code' to continue": "您已经启用多因素认证, 请点击 '发送验证码' 继续",
|
||||||
|
"You have enabled Multi-Factor Authentication, please enter the TOTP code": "您已经启用多因素认证,请输入TOTP认证码",
|
||||||
"Your email is": "你的电子邮件",
|
"Your email is": "你的电子邮件",
|
||||||
"Your phone is": "你的手机号",
|
"Your phone is": "你的手机号",
|
||||||
"preferred": "首选"
|
"preferred": "首选"
|
||||||
|
@@ -104,6 +104,7 @@ class AccountTable extends React.Component {
|
|||||||
{name: "Is forbidden", label: i18next.t("user:Is forbidden")},
|
{name: "Is forbidden", label: i18next.t("user:Is forbidden")},
|
||||||
{name: "Is deleted", label: i18next.t("user:Is deleted")},
|
{name: "Is deleted", label: i18next.t("user:Is deleted")},
|
||||||
{name: "Need update password", label: i18next.t("user:Need update password")},
|
{name: "Need update password", label: i18next.t("user:Need update password")},
|
||||||
|
{name: "IP whitelist", label: i18next.t("general:IP whitelist")},
|
||||||
{name: "Multi-factor authentication", label: i18next.t("user:Multi-factor authentication")},
|
{name: "Multi-factor authentication", label: i18next.t("user:Multi-factor authentication")},
|
||||||
{name: "WebAuthn credentials", label: i18next.t("user:WebAuthn credentials")},
|
{name: "WebAuthn credentials", label: i18next.t("user:WebAuthn credentials")},
|
||||||
{name: "Managed accounts", label: i18next.t("user:Managed accounts")},
|
{name: "Managed accounts", label: i18next.t("user:Managed accounts")},
|
||||||
|
@@ -14,9 +14,10 @@
|
|||||||
|
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import {DeleteOutlined, DownOutlined, UpOutlined} from "@ant-design/icons";
|
import {DeleteOutlined, DownOutlined, UpOutlined} from "@ant-design/icons";
|
||||||
import {Alert, Button, Col, Image, Input, Popover, QRCode, Row, Table, Tooltip} from "antd";
|
import {Button, Col, Image, Input, Popover, Row, Table, Tooltip} from "antd";
|
||||||
import * as Setting from "../Setting";
|
import * as Setting from "../Setting";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
|
import {CasdoorAppQrCode, CasdoorAppUrl} from "../common/CasdoorAppConnector";
|
||||||
|
|
||||||
class MfaAccountTable extends React.Component {
|
class MfaAccountTable extends React.Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
@@ -76,42 +77,6 @@ class MfaAccountTable extends React.Component {
|
|||||||
this.updateTable(table);
|
this.updateTable(table);
|
||||||
}
|
}
|
||||||
|
|
||||||
getQrUrl() {
|
|
||||||
const {accessToken} = this.props;
|
|
||||||
let qrUrl = `casdoor-app://login?serverUrl=${window.location.origin}&accessToken=${accessToken}`;
|
|
||||||
let error = null;
|
|
||||||
|
|
||||||
if (!accessToken) {
|
|
||||||
qrUrl = "";
|
|
||||||
error = i18next.t("general:Access token is empty");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (qrUrl.length >= 2000) {
|
|
||||||
qrUrl = "";
|
|
||||||
error = i18next.t("general:QR code is too large");
|
|
||||||
}
|
|
||||||
|
|
||||||
return {qrUrl, error};
|
|
||||||
}
|
|
||||||
|
|
||||||
renderQrCode() {
|
|
||||||
const {qrUrl, error} = this.getQrUrl();
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
return <Alert message={error} type="error" showIcon />;
|
|
||||||
} else {
|
|
||||||
return (
|
|
||||||
<QRCode
|
|
||||||
value={qrUrl}
|
|
||||||
icon={this.state.icon}
|
|
||||||
errorLevel="M"
|
|
||||||
size={230}
|
|
||||||
bordered={false}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
renderTable(table) {
|
renderTable(table) {
|
||||||
const columns = [
|
const columns = [
|
||||||
{
|
{
|
||||||
@@ -194,10 +159,25 @@ class MfaAccountTable extends React.Component {
|
|||||||
title={() => (
|
title={() => (
|
||||||
<div>
|
<div>
|
||||||
{this.props.title}
|
{this.props.title}
|
||||||
<Button style={{marginRight: "10px"}} type="primary" size="small" onClick={() => this.addRow(table)}>{i18next.t("general:Add")}</Button>
|
<Button style={{marginRight: "10px"}} type="primary" size="small" onClick={() => this.addRow(table)}>
|
||||||
<Popover trigger="focus" overlayInnerStyle={{padding: 0}}
|
{i18next.t("general:Add")}
|
||||||
content={this.renderQrCode()}>
|
</Button>
|
||||||
<Button style={{marginLeft: "5px"}} type="primary" size="small">{i18next.t("general:QR Code")}</Button>
|
<Popover
|
||||||
|
trigger="focus"
|
||||||
|
overlayInnerStyle={{padding: 0}}
|
||||||
|
content={<CasdoorAppQrCode accessToken={this.props.accessToken} icon={this.state.icon} />}
|
||||||
|
>
|
||||||
|
<Button style={{marginRight: "10px"}} type="primary" size="small">
|
||||||
|
{i18next.t("general:QR Code")}
|
||||||
|
</Button>
|
||||||
|
</Popover>
|
||||||
|
<Popover
|
||||||
|
trigger="click"
|
||||||
|
content={<CasdoorAppUrl accessToken={this.props.accessToken} />}
|
||||||
|
>
|
||||||
|
<Button type="primary" size="small">
|
||||||
|
{i18next.t("general:Show URL")}
|
||||||
|
</Button>
|
||||||
</Popover>
|
</Popover>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
Reference in New Issue
Block a user