mirror of
https://github.com/casdoor/casdoor.git
synced 2025-07-16 07:33:50 +08:00
Compare commits
9 Commits
Author | SHA1 | Date | |
---|---|---|---|
91cb5f393a | |||
807aea5ec7 | |||
1c42b6e395 | |||
49a73f8138 | |||
55784c68a3 | |||
8080b10b3b | |||
cd7589775c | |||
0a8c2a35fe | |||
d1e734e4ce |
@ -50,7 +50,8 @@ func (c *ApiController) GetApplications() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Data["json"] = object.GetMaskedApplications(applications, userId)
|
c.Data["json"] = object.GetMaskedApplications(applications, userId)
|
||||||
@ -59,13 +60,15 @@ func (c *ApiController) GetApplications() {
|
|||||||
limit := util.ParseInt(limit)
|
limit := util.ParseInt(limit)
|
||||||
count, err := object.GetApplicationCount(owner, field, value)
|
count, err := object.GetApplicationCount(owner, field, value)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
paginator := pagination.SetPaginator(c.Ctx, limit, count)
|
paginator := pagination.SetPaginator(c.Ctx, limit, count)
|
||||||
app, err := object.GetPaginationApplications(owner, paginator.Offset(), limit, field, value, sortField, sortOrder)
|
app, err := object.GetPaginationApplications(owner, paginator.Offset(), limit, field, value, sortField, sortOrder)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
applications := object.GetMaskedApplications(app, userId)
|
applications := object.GetMaskedApplications(app, userId)
|
||||||
@ -85,7 +88,8 @@ func (c *ApiController) GetApplication() {
|
|||||||
id := c.Input().Get("id")
|
id := c.Input().Get("id")
|
||||||
app, err := object.GetApplication(id)
|
app, err := object.GetApplication(id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Data["json"] = object.GetMaskedApplication(app, userId)
|
c.Data["json"] = object.GetMaskedApplication(app, userId)
|
||||||
@ -104,7 +108,8 @@ func (c *ApiController) GetUserApplication() {
|
|||||||
id := c.Input().Get("id")
|
id := c.Input().Get("id")
|
||||||
user, err := object.GetUser(id)
|
user, err := object.GetUser(id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if user == nil {
|
if user == nil {
|
||||||
@ -114,7 +119,8 @@ func (c *ApiController) GetUserApplication() {
|
|||||||
|
|
||||||
app, err := object.GetApplicationByUser(user)
|
app, err := object.GetApplicationByUser(user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Data["json"] = object.GetMaskedApplication(app, userId)
|
c.Data["json"] = object.GetMaskedApplication(app, userId)
|
||||||
@ -147,7 +153,8 @@ func (c *ApiController) GetOrganizationApplications() {
|
|||||||
if limit == "" || page == "" {
|
if limit == "" || page == "" {
|
||||||
applications, err := object.GetOrganizationApplications(owner, organization)
|
applications, err := object.GetOrganizationApplications(owner, organization)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Data["json"] = object.GetMaskedApplications(applications, userId)
|
c.Data["json"] = object.GetMaskedApplications(applications, userId)
|
||||||
|
@ -69,6 +69,15 @@ func (c *ApiController) HandleLoggedIn(application *object.Application, user *ob
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check user's tag
|
||||||
|
if !user.IsGlobalAdmin && !user.IsAdmin && len(application.Tags) > 0 {
|
||||||
|
// only users with the tag that is listed in the application tags can login
|
||||||
|
if !util.InSlice(application.Tags, user.Tag) {
|
||||||
|
c.ResponseError(fmt.Sprintf(c.T("auth:User's tag: %s is not listed in the application's tags"), user.Tag))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if form.Password != "" && user.IsMfaEnabled() {
|
if form.Password != "" && user.IsMfaEnabled() {
|
||||||
c.setMfaSessionData(&object.MfaSessionData{UserId: userId})
|
c.setMfaSessionData(&object.MfaSessionData{UserId: userId})
|
||||||
resp = &Response{Status: object.NextMfa, Data: user.GetPreferredMfaProps(true)}
|
resp = &Response{Status: object.NextMfa, Data: user.GetPreferredMfaProps(true)}
|
||||||
@ -238,7 +247,7 @@ func isProxyProviderType(providerType string) bool {
|
|||||||
// @Param code_challenge_method query string false code_challenge_method
|
// @Param code_challenge_method query string false code_challenge_method
|
||||||
// @Param code_challenge query string false code_challenge
|
// @Param code_challenge query string false code_challenge
|
||||||
// @Param form body controllers.AuthForm true "Login information"
|
// @Param form body controllers.AuthForm true "Login information"
|
||||||
// @Success 200 {object} Response The Response object
|
// @Success 200 {object} controllers.Response The Response object
|
||||||
// @router /login [post]
|
// @router /login [post]
|
||||||
func (c *ApiController) Login() {
|
func (c *ApiController) Login() {
|
||||||
resp := &Response{}
|
resp := &Response{}
|
||||||
@ -756,7 +765,8 @@ func (c *ApiController) HandleSamlLogin() {
|
|||||||
func (c *ApiController) HandleOfficialAccountEvent() {
|
func (c *ApiController) HandleOfficialAccountEvent() {
|
||||||
respBytes, err := ioutil.ReadAll(c.Ctx.Request.Body)
|
respBytes, err := ioutil.ReadAll(c.Ctx.Request.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var data struct {
|
var data struct {
|
||||||
@ -766,7 +776,8 @@ func (c *ApiController) HandleOfficialAccountEvent() {
|
|||||||
}
|
}
|
||||||
err = xml.Unmarshal(respBytes, &data)
|
err = xml.Unmarshal(respBytes, &data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
lock.Lock()
|
lock.Lock()
|
||||||
|
@ -79,7 +79,8 @@ func (c *ApiController) getCurrentUser() *object.User {
|
|||||||
} else {
|
} else {
|
||||||
user, err = object.GetUser(userId)
|
user, err = object.GetUser(userId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
c.ResponseError(err.Error())
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return user
|
return user
|
||||||
@ -112,7 +113,8 @@ func (c *ApiController) GetSessionApplication() *object.Application {
|
|||||||
}
|
}
|
||||||
application, err := object.GetApplicationByClientId(clientId.(string))
|
application, err := object.GetApplicationByClientId(clientId.(string))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
c.ResponseError(err.Error())
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return application
|
return application
|
||||||
|
@ -41,7 +41,8 @@ func (c *ApiController) GetCerts() {
|
|||||||
if limit == "" || page == "" {
|
if limit == "" || page == "" {
|
||||||
maskedCerts, err := object.GetMaskedCerts(object.GetCerts(owner))
|
maskedCerts, err := object.GetMaskedCerts(object.GetCerts(owner))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Data["json"] = maskedCerts
|
c.Data["json"] = maskedCerts
|
||||||
@ -50,13 +51,15 @@ func (c *ApiController) GetCerts() {
|
|||||||
limit := util.ParseInt(limit)
|
limit := util.ParseInt(limit)
|
||||||
count, err := object.GetCertCount(owner, field, value)
|
count, err := object.GetCertCount(owner, field, value)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
paginator := pagination.SetPaginator(c.Ctx, limit, count)
|
paginator := pagination.SetPaginator(c.Ctx, limit, count)
|
||||||
certs, err := object.GetMaskedCerts(object.GetPaginationCerts(owner, paginator.Offset(), limit, field, value, sortField, sortOrder))
|
certs, err := object.GetMaskedCerts(object.GetPaginationCerts(owner, paginator.Offset(), limit, field, value, sortField, sortOrder))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.ResponseOk(certs, paginator.Nums())
|
c.ResponseOk(certs, paginator.Nums())
|
||||||
@ -80,7 +83,8 @@ func (c *ApiController) GetGlobleCerts() {
|
|||||||
if limit == "" || page == "" {
|
if limit == "" || page == "" {
|
||||||
maskedCerts, err := object.GetMaskedCerts(object.GetGlobleCerts())
|
maskedCerts, err := object.GetMaskedCerts(object.GetGlobleCerts())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Data["json"] = maskedCerts
|
c.Data["json"] = maskedCerts
|
||||||
@ -89,13 +93,15 @@ func (c *ApiController) GetGlobleCerts() {
|
|||||||
limit := util.ParseInt(limit)
|
limit := util.ParseInt(limit)
|
||||||
count, err := object.GetGlobalCertsCount(field, value)
|
count, err := object.GetGlobalCertsCount(field, value)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
paginator := pagination.SetPaginator(c.Ctx, limit, count)
|
paginator := pagination.SetPaginator(c.Ctx, limit, count)
|
||||||
certs, err := object.GetMaskedCerts(object.GetPaginationGlobalCerts(paginator.Offset(), limit, field, value, sortField, sortOrder))
|
certs, err := object.GetMaskedCerts(object.GetPaginationGlobalCerts(paginator.Offset(), limit, field, value, sortField, sortOrder))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.ResponseOk(certs, paginator.Nums())
|
c.ResponseOk(certs, paginator.Nums())
|
||||||
@ -113,7 +119,8 @@ func (c *ApiController) GetCert() {
|
|||||||
id := c.Input().Get("id")
|
id := c.Input().Get("id")
|
||||||
cert, err := object.GetCert(id)
|
cert, err := object.GetCert(id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Data["json"] = object.GetMaskedCert(cert)
|
c.Data["json"] = object.GetMaskedCert(cert)
|
||||||
|
@ -41,7 +41,8 @@ func (c *ApiController) GetChats() {
|
|||||||
if limit == "" || page == "" {
|
if limit == "" || page == "" {
|
||||||
maskedChats, err := object.GetMaskedChats(object.GetChats(owner))
|
maskedChats, err := object.GetMaskedChats(object.GetChats(owner))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Data["json"] = maskedChats
|
c.Data["json"] = maskedChats
|
||||||
@ -77,7 +78,8 @@ func (c *ApiController) GetChat() {
|
|||||||
|
|
||||||
maskedChat, err := object.GetMaskedChat(object.GetChat(id))
|
maskedChat, err := object.GetMaskedChat(object.GetChat(id))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Data["json"] = maskedChat
|
c.Data["json"] = maskedChat
|
||||||
|
@ -53,7 +53,8 @@ func (c *ApiController) GetMessages() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Data["json"] = object.GetMaskedMessages(messages)
|
c.Data["json"] = object.GetMaskedMessages(messages)
|
||||||
@ -89,7 +90,8 @@ func (c *ApiController) GetMessage() {
|
|||||||
id := c.Input().Get("id")
|
id := c.Input().Get("id")
|
||||||
message, err := object.GetMessage(id)
|
message, err := object.GetMessage(id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Data["json"] = object.GetMaskedMessage(message)
|
c.Data["json"] = object.GetMaskedMessage(message)
|
||||||
@ -100,7 +102,8 @@ func (c *ApiController) ResponseErrorStream(errorText string) {
|
|||||||
event := fmt.Sprintf("event: myerror\ndata: %s\n\n", errorText)
|
event := fmt.Sprintf("event: myerror\ndata: %s\n\n", errorText)
|
||||||
_, err := c.Ctx.ResponseWriter.Write([]byte(event))
|
_, err := c.Ctx.ResponseWriter.Write([]byte(event))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -196,7 +199,8 @@ func (c *ApiController) GetMessageAnswer() {
|
|||||||
event := fmt.Sprintf("event: end\ndata: %s\n\n", "end")
|
event := fmt.Sprintf("event: end\ndata: %s\n\n", "end")
|
||||||
_, err = c.Ctx.ResponseWriter.Write([]byte(event))
|
_, err = c.Ctx.ResponseWriter.Write([]byte(event))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
answer := stringBuilder.String()
|
answer := stringBuilder.String()
|
||||||
@ -204,7 +208,8 @@ func (c *ApiController) GetMessageAnswer() {
|
|||||||
message.Text = answer
|
message.Text = answer
|
||||||
_, err = object.UpdateMessage(message.GetId(), message)
|
_, err = object.UpdateMessage(message.GetId(), message)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,7 +17,6 @@ package controllers
|
|||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/beego/beego"
|
|
||||||
"github.com/casdoor/casdoor/object"
|
"github.com/casdoor/casdoor/object"
|
||||||
"github.com/casdoor/casdoor/util"
|
"github.com/casdoor/casdoor/util"
|
||||||
)
|
)
|
||||||
@ -29,7 +28,7 @@ import (
|
|||||||
// @param owner form string true "owner of user"
|
// @param owner form string true "owner of user"
|
||||||
// @param name form string true "name of user"
|
// @param name form string true "name of user"
|
||||||
// @param type form string true "MFA auth type"
|
// @param type form string true "MFA auth type"
|
||||||
// @Success 200 {object} The Response object
|
// @Success 200 {object} controllers.Response The Response object
|
||||||
// @router /mfa/setup/initiate [post]
|
// @router /mfa/setup/initiate [post]
|
||||||
func (c *ApiController) MfaSetupInitiate() {
|
func (c *ApiController) MfaSetupInitiate() {
|
||||||
owner := c.Ctx.Request.Form.Get("owner")
|
owner := c.Ctx.Request.Form.Get("owner")
|
||||||
@ -58,10 +57,7 @@ func (c *ApiController) MfaSetupInitiate() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
issuer := beego.AppConfig.String("appname")
|
mfaProps, err := MfaUtil.Initiate(c.Ctx, user.GetId())
|
||||||
accountName := user.GetId()
|
|
||||||
|
|
||||||
mfaProps, err := MfaUtil.Initiate(c.Ctx, issuer, accountName)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.ResponseError(err.Error())
|
c.ResponseError(err.Error())
|
||||||
return
|
return
|
||||||
|
@ -41,7 +41,8 @@ func (c *ApiController) GetModels() {
|
|||||||
if limit == "" || page == "" {
|
if limit == "" || page == "" {
|
||||||
models, err := object.GetModels(owner)
|
models, err := object.GetModels(owner)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Data["json"] = models
|
c.Data["json"] = models
|
||||||
@ -77,7 +78,8 @@ func (c *ApiController) GetModel() {
|
|||||||
|
|
||||||
model, err := object.GetModel(id)
|
model, err := object.GetModel(id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Data["json"] = model
|
c.Data["json"] = model
|
||||||
|
@ -38,16 +38,25 @@ func (c *ApiController) GetOrganizations() {
|
|||||||
sortField := c.Input().Get("sortField")
|
sortField := c.Input().Get("sortField")
|
||||||
sortOrder := c.Input().Get("sortOrder")
|
sortOrder := c.Input().Get("sortOrder")
|
||||||
|
|
||||||
|
isGlobalAdmin := c.IsGlobalAdmin()
|
||||||
if limit == "" || page == "" {
|
if limit == "" || page == "" {
|
||||||
maskedOrganizations, err := object.GetMaskedOrganizations(object.GetOrganizations(owner))
|
var maskedOrganizations []*object.Organization
|
||||||
|
var err error
|
||||||
|
|
||||||
|
if isGlobalAdmin {
|
||||||
|
maskedOrganizations, err = object.GetMaskedOrganizations(object.GetOrganizations(owner))
|
||||||
|
} else {
|
||||||
|
maskedOrganizations, err = object.GetMaskedOrganizations(object.GetOrganizations(owner, c.getCurrentUser().Owner))
|
||||||
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Data["json"] = maskedOrganizations
|
c.Data["json"] = maskedOrganizations
|
||||||
c.ServeJSON()
|
c.ServeJSON()
|
||||||
} else {
|
} else {
|
||||||
isGlobalAdmin := c.IsGlobalAdmin()
|
|
||||||
if !isGlobalAdmin {
|
if !isGlobalAdmin {
|
||||||
maskedOrganizations, err := object.GetMaskedOrganizations(object.GetOrganizations(owner, c.getCurrentUser().Owner))
|
maskedOrganizations, err := object.GetMaskedOrganizations(object.GetOrganizations(owner, c.getCurrentUser().Owner))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -42,7 +42,8 @@ func (c *ApiController) GetPayments() {
|
|||||||
if limit == "" || page == "" {
|
if limit == "" || page == "" {
|
||||||
payments, err := object.GetPayments(owner)
|
payments, err := object.GetPayments(owner)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Data["json"] = payments
|
c.Data["json"] = payments
|
||||||
@ -51,13 +52,15 @@ func (c *ApiController) GetPayments() {
|
|||||||
limit := util.ParseInt(limit)
|
limit := util.ParseInt(limit)
|
||||||
count, err := object.GetPaymentCount(owner, organization, field, value)
|
count, err := object.GetPaymentCount(owner, organization, field, value)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
paginator := pagination.SetPaginator(c.Ctx, limit, count)
|
paginator := pagination.SetPaginator(c.Ctx, limit, count)
|
||||||
payments, err := object.GetPaginationPayments(owner, organization, paginator.Offset(), limit, field, value, sortField, sortOrder)
|
payments, err := object.GetPaginationPayments(owner, organization, paginator.Offset(), limit, field, value, sortField, sortOrder)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.ResponseOk(payments, paginator.Nums())
|
c.ResponseOk(payments, paginator.Nums())
|
||||||
@ -99,7 +102,8 @@ func (c *ApiController) GetPayment() {
|
|||||||
|
|
||||||
payment, err := object.GetPayment(id)
|
payment, err := object.GetPayment(id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Data["json"] = payment
|
c.Data["json"] = payment
|
||||||
@ -190,7 +194,8 @@ func (c *ApiController) NotifyPayment() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,7 +41,8 @@ func (c *ApiController) GetPermissions() {
|
|||||||
if limit == "" || page == "" {
|
if limit == "" || page == "" {
|
||||||
permissions, err := object.GetPermissions(owner)
|
permissions, err := object.GetPermissions(owner)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Data["json"] = permissions
|
c.Data["json"] = permissions
|
||||||
@ -50,13 +51,15 @@ func (c *ApiController) GetPermissions() {
|
|||||||
limit := util.ParseInt(limit)
|
limit := util.ParseInt(limit)
|
||||||
count, err := object.GetPermissionCount(owner, field, value)
|
count, err := object.GetPermissionCount(owner, field, value)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
paginator := pagination.SetPaginator(c.Ctx, limit, count)
|
paginator := pagination.SetPaginator(c.Ctx, limit, count)
|
||||||
permissions, err := object.GetPaginationPermissions(owner, paginator.Offset(), limit, field, value, sortField, sortOrder)
|
permissions, err := object.GetPaginationPermissions(owner, paginator.Offset(), limit, field, value, sortField, sortOrder)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.ResponseOk(permissions, paginator.Nums())
|
c.ResponseOk(permissions, paginator.Nums())
|
||||||
@ -116,7 +119,8 @@ func (c *ApiController) GetPermission() {
|
|||||||
|
|
||||||
permission, err := object.GetPermission(id)
|
permission, err := object.GetPermission(id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Data["json"] = permission
|
c.Data["json"] = permission
|
||||||
|
@ -41,7 +41,8 @@ func (c *ApiController) GetPlans() {
|
|||||||
if limit == "" || page == "" {
|
if limit == "" || page == "" {
|
||||||
plans, err := object.GetPlans(owner)
|
plans, err := object.GetPlans(owner)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Data["json"] = plans
|
c.Data["json"] = plans
|
||||||
@ -79,13 +80,15 @@ func (c *ApiController) GetPlan() {
|
|||||||
|
|
||||||
plan, err := object.GetPlan(id)
|
plan, err := object.GetPlan(id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if includeOption {
|
if includeOption {
|
||||||
options, err := object.GetPermissionsByRole(plan.Role)
|
options, err := object.GetPermissionsByRole(plan.Role)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, option := range options {
|
for _, option := range options {
|
||||||
|
@ -41,7 +41,8 @@ func (c *ApiController) GetPricings() {
|
|||||||
if limit == "" || page == "" {
|
if limit == "" || page == "" {
|
||||||
pricings, err := object.GetPricings(owner)
|
pricings, err := object.GetPricings(owner)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Data["json"] = pricings
|
c.Data["json"] = pricings
|
||||||
@ -70,14 +71,15 @@ func (c *ApiController) GetPricings() {
|
|||||||
// @Tag Pricing API
|
// @Tag Pricing API
|
||||||
// @Description get pricing
|
// @Description get pricing
|
||||||
// @Param id query string true "The id ( owner/name ) of the pricing"
|
// @Param id query string true "The id ( owner/name ) of the pricing"
|
||||||
// @Success 200 {object} object.pricing The Response object
|
// @Success 200 {object} object.Pricing The Response object
|
||||||
// @router /get-pricing [get]
|
// @router /get-pricing [get]
|
||||||
func (c *ApiController) GetPricing() {
|
func (c *ApiController) GetPricing() {
|
||||||
id := c.Input().Get("id")
|
id := c.Input().Get("id")
|
||||||
|
|
||||||
pricing, err := object.GetPricing(id)
|
pricing, err := object.GetPricing(id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Data["json"] = pricing
|
c.Data["json"] = pricing
|
||||||
|
@ -42,7 +42,8 @@ func (c *ApiController) GetProducts() {
|
|||||||
if limit == "" || page == "" {
|
if limit == "" || page == "" {
|
||||||
products, err := object.GetProducts(owner)
|
products, err := object.GetProducts(owner)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Data["json"] = products
|
c.Data["json"] = products
|
||||||
@ -78,12 +79,14 @@ func (c *ApiController) GetProduct() {
|
|||||||
|
|
||||||
product, err := object.GetProduct(id)
|
product, err := object.GetProduct(id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err = object.ExtendProductWithProviders(product)
|
err = object.ExtendProductWithProviders(product)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Data["json"] = product
|
c.Data["json"] = product
|
||||||
|
@ -46,7 +46,8 @@ func (c *ApiController) GetProviders() {
|
|||||||
if limit == "" || page == "" {
|
if limit == "" || page == "" {
|
||||||
providers, err := object.GetProviders(owner)
|
providers, err := object.GetProviders(owner)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.ResponseOk(object.GetMaskedProviders(providers, isMaskEnabled))
|
c.ResponseOk(object.GetMaskedProviders(providers, isMaskEnabled))
|
||||||
@ -92,7 +93,8 @@ func (c *ApiController) GetGlobalProviders() {
|
|||||||
if limit == "" || page == "" {
|
if limit == "" || page == "" {
|
||||||
globalProviders, err := object.GetGlobalProviders()
|
globalProviders, err := object.GetGlobalProviders()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.ResponseOk(object.GetMaskedProviders(globalProviders, isMaskEnabled))
|
c.ResponseOk(object.GetMaskedProviders(globalProviders, isMaskEnabled))
|
||||||
|
@ -46,7 +46,8 @@ func (c *ApiController) GetRecords() {
|
|||||||
if limit == "" || page == "" {
|
if limit == "" || page == "" {
|
||||||
records, err := object.GetRecords()
|
records, err := object.GetRecords()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Data["json"] = records
|
c.Data["json"] = records
|
||||||
@ -84,12 +85,14 @@ func (c *ApiController) GetRecordsByFilter() {
|
|||||||
record := &object.Record{}
|
record := &object.Record{}
|
||||||
err := util.JsonToStruct(body, record)
|
err := util.JsonToStruct(body, record)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
records, err := object.GetRecordsByField(record)
|
records, err := object.GetRecordsByField(record)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Data["json"] = records
|
c.Data["json"] = records
|
||||||
|
@ -53,7 +53,8 @@ func (c *ApiController) GetResources() {
|
|||||||
if limit == "" || page == "" {
|
if limit == "" || page == "" {
|
||||||
resources, err := object.GetResources(owner, user)
|
resources, err := object.GetResources(owner, user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Data["json"] = resources
|
c.Data["json"] = resources
|
||||||
@ -86,7 +87,8 @@ func (c *ApiController) GetResource() {
|
|||||||
|
|
||||||
resource, err := object.GetResource(id)
|
resource, err := object.GetResource(id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Data["json"] = resource
|
c.Data["json"] = resource
|
||||||
|
@ -41,7 +41,8 @@ func (c *ApiController) GetRoles() {
|
|||||||
if limit == "" || page == "" {
|
if limit == "" || page == "" {
|
||||||
roles, err := object.GetRoles(owner)
|
roles, err := object.GetRoles(owner)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Data["json"] = roles
|
c.Data["json"] = roles
|
||||||
@ -77,7 +78,8 @@ func (c *ApiController) GetRole() {
|
|||||||
|
|
||||||
role, err := object.GetRole(id)
|
role, err := object.GetRole(id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Data["json"] = role
|
c.Data["json"] = role
|
||||||
|
@ -41,7 +41,8 @@ func (c *ApiController) GetSessions() {
|
|||||||
if limit == "" || page == "" {
|
if limit == "" || page == "" {
|
||||||
sessions, err := object.GetSessions(owner)
|
sessions, err := object.GetSessions(owner)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Data["json"] = sessions
|
c.Data["json"] = sessions
|
||||||
@ -76,7 +77,8 @@ func (c *ApiController) GetSingleSession() {
|
|||||||
|
|
||||||
session, err := object.GetSingleSession(id)
|
session, err := object.GetSingleSession(id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Data["json"] = session
|
c.Data["json"] = session
|
||||||
@ -155,7 +157,8 @@ func (c *ApiController) IsSessionDuplicated() {
|
|||||||
|
|
||||||
isUserSessionDuplicated, err := object.IsSessionDuplicated(id, sessionId)
|
isUserSessionDuplicated, err := object.IsSessionDuplicated(id, sessionId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Data["json"] = &Response{Status: "ok", Msg: "", Data: isUserSessionDuplicated}
|
c.Data["json"] = &Response{Status: "ok", Msg: "", Data: isUserSessionDuplicated}
|
||||||
|
@ -41,7 +41,8 @@ func (c *ApiController) GetSubscriptions() {
|
|||||||
if limit == "" || page == "" {
|
if limit == "" || page == "" {
|
||||||
subscriptions, err := object.GetSubscriptions(owner)
|
subscriptions, err := object.GetSubscriptions(owner)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Data["json"] = subscriptions
|
c.Data["json"] = subscriptions
|
||||||
@ -70,14 +71,15 @@ func (c *ApiController) GetSubscriptions() {
|
|||||||
// @Tag Subscription API
|
// @Tag Subscription API
|
||||||
// @Description get subscription
|
// @Description get subscription
|
||||||
// @Param id query string true "The id ( owner/name ) of the subscription"
|
// @Param id query string true "The id ( owner/name ) of the subscription"
|
||||||
// @Success 200 {object} object.subscription The Response object
|
// @Success 200 {object} object.Subscription The Response object
|
||||||
// @router /get-subscription [get]
|
// @router /get-subscription [get]
|
||||||
func (c *ApiController) GetSubscription() {
|
func (c *ApiController) GetSubscription() {
|
||||||
id := c.Input().Get("id")
|
id := c.Input().Get("id")
|
||||||
|
|
||||||
subscription, err := object.GetSubscription(id)
|
subscription, err := object.GetSubscription(id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Data["json"] = subscription
|
c.Data["json"] = subscription
|
||||||
|
@ -42,7 +42,8 @@ func (c *ApiController) GetSyncers() {
|
|||||||
if limit == "" || page == "" {
|
if limit == "" || page == "" {
|
||||||
organizationSyncers, err := object.GetOrganizationSyncers(owner, organization)
|
organizationSyncers, err := object.GetOrganizationSyncers(owner, organization)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Data["json"] = organizationSyncers
|
c.Data["json"] = organizationSyncers
|
||||||
@ -78,7 +79,8 @@ func (c *ApiController) GetSyncer() {
|
|||||||
|
|
||||||
syncer, err := object.GetSyncer(id)
|
syncer, err := object.GetSyncer(id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Data["json"] = syncer
|
c.Data["json"] = syncer
|
||||||
|
@ -43,7 +43,8 @@ func (c *ApiController) GetTokens() {
|
|||||||
if limit == "" || page == "" {
|
if limit == "" || page == "" {
|
||||||
token, err := object.GetTokens(owner, organization)
|
token, err := object.GetTokens(owner, organization)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Data["json"] = token
|
c.Data["json"] = token
|
||||||
@ -78,7 +79,8 @@ func (c *ApiController) GetToken() {
|
|||||||
id := c.Input().Get("id")
|
id := c.Input().Get("id")
|
||||||
token, err := object.GetToken(id)
|
token, err := object.GetToken(id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Data["json"] = token
|
c.Data["json"] = token
|
||||||
@ -193,7 +195,8 @@ func (c *ApiController) GetOAuthToken() {
|
|||||||
host := c.Ctx.Request.Host
|
host := c.Ctx.Request.Host
|
||||||
oAuthtoken, err := object.GetOAuthToken(grantType, clientId, clientSecret, code, verifier, scope, username, password, host, refreshToken, tag, avatar, c.GetAcceptLanguage())
|
oAuthtoken, err := object.GetOAuthToken(grantType, clientId, clientSecret, code, verifier, scope, username, password, host, refreshToken, tag, avatar, c.GetAcceptLanguage())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Data["json"] = oAuthtoken
|
c.Data["json"] = oAuthtoken
|
||||||
@ -236,7 +239,8 @@ func (c *ApiController) RefreshToken() {
|
|||||||
|
|
||||||
refreshToken2, err := object.RefreshToken(grantType, refreshToken, scope, clientId, clientSecret, host)
|
refreshToken2, err := object.RefreshToken(grantType, refreshToken, scope, clientId, clientSecret, host)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Data["json"] = refreshToken2
|
c.Data["json"] = refreshToken2
|
||||||
@ -276,7 +280,8 @@ func (c *ApiController) IntrospectToken() {
|
|||||||
}
|
}
|
||||||
application, err := object.GetApplicationByClientId(clientId)
|
application, err := object.GetApplicationByClientId(clientId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if application == nil || application.ClientSecret != clientSecret {
|
if application == nil || application.ClientSecret != clientSecret {
|
||||||
@ -289,7 +294,8 @@ func (c *ApiController) IntrospectToken() {
|
|||||||
}
|
}
|
||||||
token, err := object.GetTokenByTokenAndApplication(tokenValue, application.Name)
|
token, err := object.GetTokenByTokenAndApplication(tokenValue, application.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if token == nil {
|
if token == nil {
|
||||||
|
@ -41,7 +41,8 @@ func (c *ApiController) GetGlobalUsers() {
|
|||||||
if limit == "" || page == "" {
|
if limit == "" || page == "" {
|
||||||
maskedUsers, err := object.GetMaskedUsers(object.GetGlobalUsers())
|
maskedUsers, err := object.GetMaskedUsers(object.GetGlobalUsers())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Data["json"] = maskedUsers
|
c.Data["json"] = maskedUsers
|
||||||
@ -101,7 +102,8 @@ func (c *ApiController) GetUsers() {
|
|||||||
|
|
||||||
maskedUsers, err := object.GetMaskedUsers(object.GetUsers(owner))
|
maskedUsers, err := object.GetMaskedUsers(object.GetUsers(owner))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Data["json"] = maskedUsers
|
c.Data["json"] = maskedUsers
|
||||||
@ -153,7 +155,8 @@ func (c *ApiController) GetUser() {
|
|||||||
if userId != "" && owner != "" {
|
if userId != "" && owner != "" {
|
||||||
userFromUserId, err = object.GetUserByUserId(owner, userId)
|
userFromUserId, err = object.GetUserByUserId(owner, userId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
id = util.GetId(userFromUserId.Owner, userFromUserId.Name)
|
id = util.GetId(userFromUserId.Owner, userFromUserId.Name)
|
||||||
@ -165,7 +168,8 @@ func (c *ApiController) GetUser() {
|
|||||||
|
|
||||||
organization, err := object.GetOrganization(util.GetId("admin", owner))
|
organization, err := object.GetOrganization(util.GetId("admin", owner))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if !organization.IsProfilePublic {
|
if !organization.IsProfilePublic {
|
||||||
@ -190,18 +194,21 @@ func (c *ApiController) GetUser() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
user.MultiFactorAuths = object.GetAllMfaProps(user, true)
|
user.MultiFactorAuths = object.GetAllMfaProps(user, true)
|
||||||
err = object.ExtendUserWithRolesAndPermissions(user)
|
err = object.ExtendUserWithRolesAndPermissions(user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
maskedUser, err := object.GetMaskedUser(user)
|
maskedUser, err := object.GetMaskedUser(user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Data["json"] = maskedUser
|
c.Data["json"] = maskedUser
|
||||||
@ -498,7 +505,8 @@ func (c *ApiController) GetSortedUsers() {
|
|||||||
|
|
||||||
maskedUsers, err := object.GetMaskedUsers(object.GetSortedUsers(owner, sorter, limit))
|
maskedUsers, err := object.GetMaskedUsers(object.GetSortedUsers(owner, sorter, limit))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Data["json"] = maskedUsers
|
c.Data["json"] = maskedUsers
|
||||||
|
@ -97,7 +97,8 @@ func (c *ApiController) RequireSignedInUser() (*object.User, bool) {
|
|||||||
|
|
||||||
user, err := object.GetUser(userId)
|
user, err := object.GetUser(userId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
c.ResponseError(err.Error())
|
||||||
|
return nil, false
|
||||||
}
|
}
|
||||||
|
|
||||||
if user == nil {
|
if user == nil {
|
||||||
|
@ -66,7 +66,7 @@ func (c *ApiController) WebAuthnSignupBegin() {
|
|||||||
// @Tag User API
|
// @Tag User API
|
||||||
// @Description WebAuthn Registration Flow 2nd stage
|
// @Description WebAuthn Registration Flow 2nd stage
|
||||||
// @Param body body protocol.CredentialCreationResponse true "authenticator attestation Response"
|
// @Param body body protocol.CredentialCreationResponse true "authenticator attestation Response"
|
||||||
// @Success 200 {object} Response "The Response object"
|
// @Success 200 {object} controllers.Response "The Response object"
|
||||||
// @router /webauthn/signup/finish [post]
|
// @router /webauthn/signup/finish [post]
|
||||||
func (c *ApiController) WebAuthnSignupFinish() {
|
func (c *ApiController) WebAuthnSignupFinish() {
|
||||||
webauthnObj, err := object.GetWebAuthnObject(c.Ctx.Request.Host)
|
webauthnObj, err := object.GetWebAuthnObject(c.Ctx.Request.Host)
|
||||||
@ -150,7 +150,7 @@ func (c *ApiController) WebAuthnSigninBegin() {
|
|||||||
// @Tag Login API
|
// @Tag Login API
|
||||||
// @Description WebAuthn Login Flow 2nd stage
|
// @Description WebAuthn Login Flow 2nd stage
|
||||||
// @Param body body protocol.CredentialAssertionResponse true "authenticator assertion Response"
|
// @Param body body protocol.CredentialAssertionResponse true "authenticator assertion Response"
|
||||||
// @Success 200 {object} Response "The Response object"
|
// @Success 200 {object} controllers.Response "The Response object"
|
||||||
// @router /webauthn/signin/finish [post]
|
// @router /webauthn/signin/finish [post]
|
||||||
func (c *ApiController) WebAuthnSigninFinish() {
|
func (c *ApiController) WebAuthnSigninFinish() {
|
||||||
responseType := c.Input().Get("responseType")
|
responseType := c.Input().Get("responseType")
|
||||||
|
@ -42,7 +42,8 @@ func (c *ApiController) GetWebhooks() {
|
|||||||
if limit == "" || page == "" {
|
if limit == "" || page == "" {
|
||||||
webhooks, err := object.GetWebhooks(owner, organization)
|
webhooks, err := object.GetWebhooks(owner, organization)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Data["json"] = webhooks
|
c.Data["json"] = webhooks
|
||||||
@ -79,7 +80,8 @@ func (c *ApiController) GetWebhook() {
|
|||||||
|
|
||||||
webhook, err := object.GetWebhook(id)
|
webhook, err := object.GetWebhook(id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Data["json"] = webhook
|
c.Data["json"] = webhook
|
||||||
|
6
go.mod
6
go.mod
@ -42,14 +42,14 @@ require (
|
|||||||
github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d // indirect
|
github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d // indirect
|
||||||
github.com/nyaruka/phonenumbers v1.1.5
|
github.com/nyaruka/phonenumbers v1.1.5
|
||||||
github.com/pkoukk/tiktoken-go v0.1.1
|
github.com/pkoukk/tiktoken-go v0.1.1
|
||||||
github.com/plutov/paypal/v4 v4.7.0
|
github.com/pquerna/otp v1.4.0
|
||||||
github.com/prometheus/client_golang v1.11.1
|
github.com/prometheus/client_golang v1.11.1
|
||||||
github.com/prometheus/client_model v0.2.0
|
github.com/prometheus/client_model v0.2.0
|
||||||
github.com/qiangmzsx/string-adapter/v2 v2.1.0
|
github.com/qiangmzsx/string-adapter/v2 v2.1.0
|
||||||
github.com/robfig/cron/v3 v3.0.1
|
github.com/robfig/cron/v3 v3.0.1
|
||||||
github.com/russellhaering/gosaml2 v0.9.0
|
github.com/russellhaering/gosaml2 v0.9.0
|
||||||
github.com/russellhaering/goxmldsig v1.2.0
|
github.com/russellhaering/goxmldsig v1.2.0
|
||||||
github.com/sashabaranov/go-openai v1.9.1
|
github.com/sashabaranov/go-openai v1.12.0
|
||||||
github.com/satori/go.uuid v1.2.0
|
github.com/satori/go.uuid v1.2.0
|
||||||
github.com/shiena/ansicolor v0.0.0-20200904210342-c7312218db18 // indirect
|
github.com/shiena/ansicolor v0.0.0-20200904210342-c7312218db18 // indirect
|
||||||
github.com/shirou/gopsutil v3.21.11+incompatible
|
github.com/shirou/gopsutil v3.21.11+incompatible
|
||||||
@ -59,7 +59,7 @@ require (
|
|||||||
github.com/tealeg/xlsx v1.0.5
|
github.com/tealeg/xlsx v1.0.5
|
||||||
github.com/thanhpk/randstr v1.0.4
|
github.com/thanhpk/randstr v1.0.4
|
||||||
github.com/tklauser/go-sysconf v0.3.10 // indirect
|
github.com/tklauser/go-sysconf v0.3.10 // indirect
|
||||||
github.com/xorm-io/builder v0.3.13 // indirect
|
github.com/xorm-io/builder v0.3.13
|
||||||
github.com/xorm-io/core v0.7.4
|
github.com/xorm-io/core v0.7.4
|
||||||
github.com/xorm-io/xorm v1.1.6
|
github.com/xorm-io/xorm v1.1.6
|
||||||
github.com/yusufpapurcu/wmi v1.2.2 // indirect
|
github.com/yusufpapurcu/wmi v1.2.2 // indirect
|
||||||
|
9
go.sum
9
go.sum
@ -105,6 +105,8 @@ github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24
|
|||||||
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||||
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||||
|
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc h1:biVzkmvwrH8WK8raXaxBx6fRVTlJILwEwQGL1I/ByEI=
|
||||||
|
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
|
||||||
github.com/bradfitz/gomemcache v0.0.0-20180710155616-bc664df96737/go.mod h1:PmM6Mmwb0LSuEubjR8N7PtNe1KxZLtOUHtbeikc5h60=
|
github.com/bradfitz/gomemcache v0.0.0-20180710155616-bc664df96737/go.mod h1:PmM6Mmwb0LSuEubjR8N7PtNe1KxZLtOUHtbeikc5h60=
|
||||||
github.com/bwesterb/go-ristretto v1.2.0/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0=
|
github.com/bwesterb/go-ristretto v1.2.0/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0=
|
||||||
github.com/casbin/casbin v1.7.0/go.mod h1:c67qKN6Oum3UF5Q1+BByfFxkwKvhwW57ITjqwtzR1KE=
|
github.com/casbin/casbin v1.7.0/go.mod h1:c67qKN6Oum3UF5Q1+BByfFxkwKvhwW57ITjqwtzR1KE=
|
||||||
@ -495,10 +497,10 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
|||||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pkoukk/tiktoken-go v0.1.1 h1:jtkYlIECjyM9OW1w4rjPmTohK4arORP9V25y6TM6nXo=
|
github.com/pkoukk/tiktoken-go v0.1.1 h1:jtkYlIECjyM9OW1w4rjPmTohK4arORP9V25y6TM6nXo=
|
||||||
github.com/pkoukk/tiktoken-go v0.1.1/go.mod h1:boMWvk9pQCOTx11pgu0DrIdrAKgQzzJKUP6vLXaz7Rw=
|
github.com/pkoukk/tiktoken-go v0.1.1/go.mod h1:boMWvk9pQCOTx11pgu0DrIdrAKgQzzJKUP6vLXaz7Rw=
|
||||||
github.com/plutov/paypal/v4 v4.7.0 h1:6TRvYD4ny6yQfHaABeStNf43GFM1wpW5jU/XEDGQmq0=
|
|
||||||
github.com/plutov/paypal/v4 v4.7.0/go.mod h1:D56boafCRGcF/fEM0w282kj0fCDKIyrwOPX/Te1jCmw=
|
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
github.com/pquerna/otp v1.4.0 h1:wZvl1TIVxKRThZIBiwOOHOGP/1+nZyWBil9Y2XNEDzg=
|
||||||
|
github.com/pquerna/otp v1.4.0/go.mod h1:dkJfzwRKNiegxyNb54X/3fLwhCynbMspSyWKnvi1AEg=
|
||||||
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
||||||
github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
|
github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
|
||||||
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
|
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
|
||||||
@ -546,6 +548,8 @@ github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR
|
|||||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||||
github.com/sashabaranov/go-openai v1.9.1 h1:3N52HkJKo9Zlo/oe1AVv5ZkCOny0ra58/ACvAxkN3MM=
|
github.com/sashabaranov/go-openai v1.9.1 h1:3N52HkJKo9Zlo/oe1AVv5ZkCOny0ra58/ACvAxkN3MM=
|
||||||
github.com/sashabaranov/go-openai v1.9.1/go.mod h1:lj5b/K+zjTSFxVLijLSTDZuP7adOgerWeFyZLUhAKRg=
|
github.com/sashabaranov/go-openai v1.9.1/go.mod h1:lj5b/K+zjTSFxVLijLSTDZuP7adOgerWeFyZLUhAKRg=
|
||||||
|
github.com/sashabaranov/go-openai v1.12.0 h1:aRNHH0gtVfrpIaEolD0sWrLLRnYQNK4cH/bIAHwL8Rk=
|
||||||
|
github.com/sashabaranov/go-openai v1.12.0/go.mod h1:lj5b/K+zjTSFxVLijLSTDZuP7adOgerWeFyZLUhAKRg=
|
||||||
github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww=
|
github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww=
|
||||||
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
|
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
|
||||||
github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
|
github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
|
||||||
@ -595,7 +599,6 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf
|
|||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||||
github.com/stretchr/testify v1.6.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
|
||||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
|
@ -18,7 +18,8 @@
|
|||||||
"The login method: login with password is not enabled for the application": "Die Anmeldeart \"Anmeldung mit Passwort\" ist für die Anwendung nicht aktiviert",
|
"The login method: login with password is not enabled for the application": "Die Anmeldeart \"Anmeldung mit Passwort\" ist für die Anwendung nicht aktiviert",
|
||||||
"The provider: %s is not enabled for the application": "Der Anbieter: %s ist nicht für die Anwendung aktiviert",
|
"The provider: %s is not enabled for the application": "Der Anbieter: %s ist nicht für die Anwendung aktiviert",
|
||||||
"Unauthorized operation": "Nicht autorisierte Operation",
|
"Unauthorized operation": "Nicht autorisierte Operation",
|
||||||
"Unknown authentication type (not password or provider), form = %s": "Unbekannter Authentifizierungstyp (nicht Passwort oder Anbieter), Formular = %s"
|
"Unknown authentication type (not password or provider), form = %s": "Unbekannter Authentifizierungstyp (nicht Passwort oder Anbieter), Formular = %s",
|
||||||
|
"User's tag: %s is not listed in the application's tags": "User's tag: %s is not listed in the application's tags"
|
||||||
},
|
},
|
||||||
"cas": {
|
"cas": {
|
||||||
"Service %s and %s do not match": "Service %s und %s stimmen nicht überein"
|
"Service %s and %s do not match": "Service %s und %s stimmen nicht überein"
|
||||||
|
@ -18,7 +18,8 @@
|
|||||||
"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 login method: login with password is not enabled for the application": "The login method: login with password is not enabled for the application",
|
||||||
"The provider: %s is not enabled for the application": "The provider: %s is not enabled for the application",
|
"The provider: %s is not enabled for the application": "The provider: %s is not enabled for the application",
|
||||||
"Unauthorized operation": "Unauthorized operation",
|
"Unauthorized operation": "Unauthorized operation",
|
||||||
"Unknown authentication type (not password or provider), form = %s": "Unknown authentication type (not password or provider), form = %s"
|
"Unknown authentication type (not password or provider), form = %s": "Unknown authentication type (not password or provider), form = %s",
|
||||||
|
"User's tag: %s is not listed in the application's tags": "User's tag: %s is not listed in the application's tags"
|
||||||
},
|
},
|
||||||
"cas": {
|
"cas": {
|
||||||
"Service %s and %s do not match": "Service %s and %s do not match"
|
"Service %s and %s do not match": "Service %s and %s do not match"
|
||||||
|
@ -18,7 +18,8 @@
|
|||||||
"The login method: login with password is not enabled for the application": "El método de inicio de sesión: inicio de sesión con contraseña no está habilitado para la aplicación",
|
"The login method: login with password is not enabled for the application": "El método de inicio de sesión: inicio de sesión con contraseña no está habilitado para la aplicación",
|
||||||
"The provider: %s is not enabled for the application": "El proveedor: %s no está habilitado para la aplicación",
|
"The provider: %s is not enabled for the application": "El proveedor: %s no está habilitado para la aplicación",
|
||||||
"Unauthorized operation": "Operación no autorizada",
|
"Unauthorized operation": "Operación no autorizada",
|
||||||
"Unknown authentication type (not password or provider), form = %s": "Tipo de autenticación desconocido (no es contraseña o proveedor), formulario = %s"
|
"Unknown authentication type (not password or provider), form = %s": "Tipo de autenticación desconocido (no es contraseña o proveedor), formulario = %s",
|
||||||
|
"User's tag: %s is not listed in the application's tags": "User's tag: %s is not listed in the application's tags"
|
||||||
},
|
},
|
||||||
"cas": {
|
"cas": {
|
||||||
"Service %s and %s do not match": "Los servicios %s y %s no coinciden"
|
"Service %s and %s do not match": "Los servicios %s y %s no coinciden"
|
||||||
|
@ -18,7 +18,8 @@
|
|||||||
"The login method: login with password is not enabled for the application": "La méthode de connexion : connexion avec mot de passe n'est pas activée pour l'application",
|
"The login method: login with password is not enabled for the application": "La méthode de connexion : connexion avec mot de passe n'est pas activée pour l'application",
|
||||||
"The provider: %s is not enabled for the application": "Le fournisseur :%s n'est pas activé pour l'application",
|
"The provider: %s is not enabled for the application": "Le fournisseur :%s n'est pas activé pour l'application",
|
||||||
"Unauthorized operation": "Opération non autorisée",
|
"Unauthorized operation": "Opération non autorisée",
|
||||||
"Unknown authentication type (not password or provider), form = %s": "Type d'authentification inconnu (pas de mot de passe ou de fournisseur), formulaire = %s"
|
"Unknown authentication type (not password or provider), form = %s": "Type d'authentification inconnu (pas de mot de passe ou de fournisseur), formulaire = %s",
|
||||||
|
"User's tag: %s is not listed in the application's tags": "User's tag: %s is not listed in the application's tags"
|
||||||
},
|
},
|
||||||
"cas": {
|
"cas": {
|
||||||
"Service %s and %s do not match": "Les services %s et %s ne correspondent pas"
|
"Service %s and %s do not match": "Les services %s et %s ne correspondent pas"
|
||||||
|
@ -18,7 +18,8 @@
|
|||||||
"The login method: login with password is not enabled for the application": "Metode login: login dengan kata sandi tidak diaktifkan untuk aplikasi tersebut",
|
"The login method: login with password is not enabled for the application": "Metode login: login dengan kata sandi tidak diaktifkan untuk aplikasi tersebut",
|
||||||
"The provider: %s is not enabled for the application": "Penyedia: %s tidak diaktifkan untuk aplikasi ini",
|
"The provider: %s is not enabled for the application": "Penyedia: %s tidak diaktifkan untuk aplikasi ini",
|
||||||
"Unauthorized operation": "Operasi tidak sah",
|
"Unauthorized operation": "Operasi tidak sah",
|
||||||
"Unknown authentication type (not password or provider), form = %s": "Jenis otentikasi tidak diketahui (bukan kata sandi atau pemberi), formulir = %s"
|
"Unknown authentication type (not password or provider), form = %s": "Jenis otentikasi tidak diketahui (bukan kata sandi atau pemberi), formulir = %s",
|
||||||
|
"User's tag: %s is not listed in the application's tags": "User's tag: %s is not listed in the application's tags"
|
||||||
},
|
},
|
||||||
"cas": {
|
"cas": {
|
||||||
"Service %s and %s do not match": "Layanan %s dan %s tidak cocok"
|
"Service %s and %s do not match": "Layanan %s dan %s tidak cocok"
|
||||||
|
@ -18,7 +18,8 @@
|
|||||||
"The login method: login with password is not enabled for the application": "ログイン方法:パスワードでのログインはアプリケーションで有効になっていません",
|
"The login method: login with password is not enabled for the application": "ログイン方法:パスワードでのログインはアプリケーションで有効になっていません",
|
||||||
"The provider: %s is not enabled for the application": "プロバイダー:%sはアプリケーションでは有効化されていません",
|
"The provider: %s is not enabled for the application": "プロバイダー:%sはアプリケーションでは有効化されていません",
|
||||||
"Unauthorized operation": "不正操作",
|
"Unauthorized operation": "不正操作",
|
||||||
"Unknown authentication type (not password or provider), form = %s": "不明な認証タイプ(パスワードまたはプロバイダーではない)フォーム=%s"
|
"Unknown authentication type (not password or provider), form = %s": "不明な認証タイプ(パスワードまたはプロバイダーではない)フォーム=%s",
|
||||||
|
"User's tag: %s is not listed in the application's tags": "User's tag: %s is not listed in the application's tags"
|
||||||
},
|
},
|
||||||
"cas": {
|
"cas": {
|
||||||
"Service %s and %s do not match": "サービス%sと%sは一致しません"
|
"Service %s and %s do not match": "サービス%sと%sは一致しません"
|
||||||
|
@ -18,7 +18,8 @@
|
|||||||
"The login method: login with password is not enabled for the application": "어플리케이션에서는 암호를 사용한 로그인 방법이 활성화되어 있지 않습니다",
|
"The login method: login with password is not enabled for the application": "어플리케이션에서는 암호를 사용한 로그인 방법이 활성화되어 있지 않습니다",
|
||||||
"The provider: %s is not enabled for the application": "제공자 %s은(는) 응용 프로그램에서 활성화되어 있지 않습니다",
|
"The provider: %s is not enabled for the application": "제공자 %s은(는) 응용 프로그램에서 활성화되어 있지 않습니다",
|
||||||
"Unauthorized operation": "무단 조작",
|
"Unauthorized operation": "무단 조작",
|
||||||
"Unknown authentication type (not password or provider), form = %s": "알 수 없는 인증 유형(암호 또는 공급자가 아님), 폼 = %s"
|
"Unknown authentication type (not password or provider), form = %s": "알 수 없는 인증 유형(암호 또는 공급자가 아님), 폼 = %s",
|
||||||
|
"User's tag: %s is not listed in the application's tags": "User's tag: %s is not listed in the application's tags"
|
||||||
},
|
},
|
||||||
"cas": {
|
"cas": {
|
||||||
"Service %s and %s do not match": "서비스 %s와 %s는 일치하지 않습니다"
|
"Service %s and %s do not match": "서비스 %s와 %s는 일치하지 않습니다"
|
||||||
|
@ -18,7 +18,8 @@
|
|||||||
"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 login method: login with password is not enabled for the application": "The login method: login with password is not enabled for the application",
|
||||||
"The provider: %s is not enabled for the application": "The provider: %s is not enabled for the application",
|
"The provider: %s is not enabled for the application": "The provider: %s is not enabled for the application",
|
||||||
"Unauthorized operation": "Unauthorized operation",
|
"Unauthorized operation": "Unauthorized operation",
|
||||||
"Unknown authentication type (not password or provider), form = %s": "Unknown authentication type (not password or provider), form = %s"
|
"Unknown authentication type (not password or provider), form = %s": "Unknown authentication type (not password or provider), form = %s",
|
||||||
|
"User's tag: %s is not listed in the application's tags": "User's tag: %s is not listed in the application's tags"
|
||||||
},
|
},
|
||||||
"cas": {
|
"cas": {
|
||||||
"Service %s and %s do not match": "Service %s and %s do not match"
|
"Service %s and %s do not match": "Service %s and %s do not match"
|
||||||
|
@ -18,7 +18,8 @@
|
|||||||
"The login method: login with password is not enabled for the application": "Метод входа: вход с паролем не включен для приложения",
|
"The login method: login with password is not enabled for the application": "Метод входа: вход с паролем не включен для приложения",
|
||||||
"The provider: %s is not enabled for the application": "Провайдер: %s не включен для приложения",
|
"The provider: %s is not enabled for the application": "Провайдер: %s не включен для приложения",
|
||||||
"Unauthorized operation": "Несанкционированная операция",
|
"Unauthorized operation": "Несанкционированная операция",
|
||||||
"Unknown authentication type (not password or provider), form = %s": "Неизвестный тип аутентификации (не пароль и не провайдер), форма = %s"
|
"Unknown authentication type (not password or provider), form = %s": "Неизвестный тип аутентификации (не пароль и не провайдер), форма = %s",
|
||||||
|
"User's tag: %s is not listed in the application's tags": "User's tag: %s is not listed in the application's tags"
|
||||||
},
|
},
|
||||||
"cas": {
|
"cas": {
|
||||||
"Service %s and %s do not match": "Сервисы %s и %s не совпадают"
|
"Service %s and %s do not match": "Сервисы %s и %s не совпадают"
|
||||||
|
@ -18,7 +18,8 @@
|
|||||||
"The login method: login with password is not enabled for the application": "Phương thức đăng nhập: đăng nhập bằng mật khẩu không được kích hoạt cho ứng dụng",
|
"The login method: login with password is not enabled for the application": "Phương thức đăng nhập: đăng nhập bằng mật khẩu không được kích hoạt cho ứng dụng",
|
||||||
"The provider: %s is not enabled for the application": "Nhà cung cấp: %s không được kích hoạt cho ứng dụng",
|
"The provider: %s is not enabled for the application": "Nhà cung cấp: %s không được kích hoạt cho ứng dụng",
|
||||||
"Unauthorized operation": "Hoạt động không được ủy quyền",
|
"Unauthorized operation": "Hoạt động không được ủy quyền",
|
||||||
"Unknown authentication type (not password or provider), form = %s": "Loại xác thực không xác định (không phải mật khẩu hoặc nhà cung cấp), biểu mẫu = %s"
|
"Unknown authentication type (not password or provider), form = %s": "Loại xác thực không xác định (không phải mật khẩu hoặc nhà cung cấp), biểu mẫu = %s",
|
||||||
|
"User's tag: %s is not listed in the application's tags": "User's tag: %s is not listed in the application's tags"
|
||||||
},
|
},
|
||||||
"cas": {
|
"cas": {
|
||||||
"Service %s and %s do not match": "Dịch sang tiếng Việt: Dịch vụ %s và %s không khớp"
|
"Service %s and %s do not match": "Dịch sang tiếng Việt: Dịch vụ %s và %s không khớp"
|
||||||
|
@ -18,7 +18,8 @@
|
|||||||
"The login method: login with password is not enabled for the application": "该应用禁止采用密码登录方式",
|
"The login method: login with password is not enabled for the application": "该应用禁止采用密码登录方式",
|
||||||
"The provider: %s is not enabled for the application": "该应用的提供商: %s未被启用",
|
"The provider: %s is not enabled for the application": "该应用的提供商: %s未被启用",
|
||||||
"Unauthorized operation": "未授权的操作",
|
"Unauthorized operation": "未授权的操作",
|
||||||
"Unknown authentication type (not password or provider), form = %s": "未知的认证类型(非密码或第三方提供商):%s"
|
"Unknown authentication type (not password or provider), form = %s": "未知的认证类型(非密码或第三方提供商):%s",
|
||||||
|
"User's tag: %s is not listed in the application's tags": "用户的标签: %s不在该应用的标签列表中"
|
||||||
},
|
},
|
||||||
"cas": {
|
"cas": {
|
||||||
"Service %s and %s do not match": "服务%s与%s不匹配"
|
"Service %s and %s do not match": "服务%s与%s不匹配"
|
||||||
|
@ -198,12 +198,22 @@ func (idp *WeChatIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo, error)
|
|||||||
func GetWechatOfficialAccountAccessToken(clientId string, clientSecret string) (string, error) {
|
func GetWechatOfficialAccountAccessToken(clientId string, clientSecret string) (string, error) {
|
||||||
accessTokenUrl := fmt.Sprintf("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s", clientId, clientSecret)
|
accessTokenUrl := fmt.Sprintf("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s", clientId, clientSecret)
|
||||||
request, err := http.NewRequest("GET", accessTokenUrl, nil)
|
request, err := http.NewRequest("GET", accessTokenUrl, nil)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
client := new(http.Client)
|
client := new(http.Client)
|
||||||
resp, err := client.Do(request)
|
resp, err := client.Do(request)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
respBytes, err := ioutil.ReadAll(resp.Body)
|
respBytes, err := ioutil.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
var data struct {
|
var data struct {
|
||||||
ExpireIn int `json:"expires_in"`
|
ExpireIn int `json:"expires_in"`
|
||||||
AccessToken string `json:"access_token"`
|
AccessToken string `json:"access_token"`
|
||||||
@ -212,20 +222,30 @@ func GetWechatOfficialAccountAccessToken(clientId string, clientSecret string) (
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
return data.AccessToken, nil
|
return data.AccessToken, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetWechatOfficialAccountQRCode(clientId string, clientSecret string) (string, error) {
|
func GetWechatOfficialAccountQRCode(clientId string, clientSecret string) (string, error) {
|
||||||
accessToken, err := GetWechatOfficialAccountAccessToken(clientId, clientSecret)
|
accessToken, err := GetWechatOfficialAccountAccessToken(clientId, clientSecret)
|
||||||
client := new(http.Client)
|
client := new(http.Client)
|
||||||
params := "{\"action_name\": \"QR_LIMIT_STR_SCENE\", \"action_info\": {\"scene\": {\"scene_str\": \"test\"}}}"
|
|
||||||
|
weChatEndpoint := "https://api.weixin.qq.com/cgi-bin/qrcode/create"
|
||||||
|
qrCodeUrl := fmt.Sprintf("%s?access_token=%s", weChatEndpoint, accessToken)
|
||||||
|
params := `{"action_name": "QR_LIMIT_STR_SCENE", "action_info": {"scene": {"scene_str": "test"}}}`
|
||||||
|
|
||||||
bodyData := bytes.NewReader([]byte(params))
|
bodyData := bytes.NewReader([]byte(params))
|
||||||
qrCodeUrl := fmt.Sprintf("https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=%s", accessToken)
|
|
||||||
requeset, err := http.NewRequest("POST", qrCodeUrl, bodyData)
|
requeset, err := http.NewRequest("POST", qrCodeUrl, bodyData)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
resp, err := client.Do(requeset)
|
resp, err := client.Do(requeset)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
respBytes, err := ioutil.ReadAll(resp.Body)
|
respBytes, err := ioutil.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
|
@ -275,7 +275,7 @@ func GetSession(owner string, offset, limit int, field, value, sortField, sortOr
|
|||||||
session = session.And("owner=?", owner)
|
session = session.And("owner=?", owner)
|
||||||
}
|
}
|
||||||
if field != "" && value != "" {
|
if field != "" && value != "" {
|
||||||
if filterField(field) {
|
if util.FilterField(field) {
|
||||||
session = session.And(fmt.Sprintf("%s like ?", util.SnakeString(field)), fmt.Sprintf("%%%s%%", value))
|
session = session.And(fmt.Sprintf("%s like ?", util.SnakeString(field)), fmt.Sprintf("%%%s%%", value))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -303,7 +303,7 @@ func GetSessionForUser(owner string, offset, limit int, field, value, sortField,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if field != "" && value != "" {
|
if field != "" && value != "" {
|
||||||
if filterField(field) {
|
if util.FilterField(field) {
|
||||||
if offset != -1 {
|
if offset != -1 {
|
||||||
field = fmt.Sprintf("a.%s", field)
|
field = fmt.Sprintf("a.%s", field)
|
||||||
}
|
}
|
||||||
|
@ -57,6 +57,7 @@ type Application struct {
|
|||||||
SignupItems []*SignupItem `xorm:"varchar(1000)" json:"signupItems"`
|
SignupItems []*SignupItem `xorm:"varchar(1000)" json:"signupItems"`
|
||||||
GrantTypes []string `xorm:"varchar(1000)" json:"grantTypes"`
|
GrantTypes []string `xorm:"varchar(1000)" json:"grantTypes"`
|
||||||
OrganizationObj *Organization `xorm:"-" json:"organizationObj"`
|
OrganizationObj *Organization `xorm:"-" json:"organizationObj"`
|
||||||
|
Tags []string `xorm:"mediumtext" json:"tags"`
|
||||||
|
|
||||||
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"`
|
||||||
|
@ -16,7 +16,6 @@ package object
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"regexp"
|
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
"unicode"
|
"unicode"
|
||||||
@ -28,21 +27,11 @@ import (
|
|||||||
goldap "github.com/go-ldap/ldap/v3"
|
goldap "github.com/go-ldap/ldap/v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
|
||||||
reWhiteSpace *regexp.Regexp
|
|
||||||
reFieldWhiteList *regexp.Regexp
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
const (
|
||||||
SigninWrongTimesLimit = 5
|
SigninWrongTimesLimit = 5
|
||||||
LastSignWrongTimeDuration = time.Minute * 15
|
LastSignWrongTimeDuration = time.Minute * 15
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
|
||||||
reWhiteSpace, _ = regexp.Compile(`\s`)
|
|
||||||
reFieldWhiteList, _ = regexp.Compile(`^[A-Za-z0-9]+$`)
|
|
||||||
}
|
|
||||||
|
|
||||||
func CheckUserSignup(application *Application, organization *Organization, form *form.AuthForm, lang string) string {
|
func CheckUserSignup(application *Application, organization *Organization, form *form.AuthForm, lang string) string {
|
||||||
if organization == nil {
|
if organization == nil {
|
||||||
return i18n.Translate(lang, "check:Organization does not exist")
|
return i18n.Translate(lang, "check:Organization does not exist")
|
||||||
@ -58,7 +47,7 @@ func CheckUserSignup(application *Application, organization *Organization, form
|
|||||||
if util.IsEmailValid(form.Username) {
|
if util.IsEmailValid(form.Username) {
|
||||||
return i18n.Translate(lang, "check:Username cannot be an email address")
|
return i18n.Translate(lang, "check:Username cannot be an email address")
|
||||||
}
|
}
|
||||||
if reWhiteSpace.MatchString(form.Username) {
|
if util.ReWhiteSpace.MatchString(form.Username) {
|
||||||
return i18n.Translate(lang, "check:Username cannot contain white spaces")
|
return i18n.Translate(lang, "check:Username cannot contain white spaces")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -294,10 +283,6 @@ func CheckUserPassword(organization string, username string, password string, la
|
|||||||
return user, ""
|
return user, ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func filterField(field string) bool {
|
|
||||||
return reFieldWhiteList.MatchString(field)
|
|
||||||
}
|
|
||||||
|
|
||||||
func CheckUserPermission(requestUserId, userId string, strict bool, lang string) (bool, error) {
|
func CheckUserPermission(requestUserId, userId string, strict bool, lang string) (bool, error) {
|
||||||
if requestUserId == "" {
|
if requestUserId == "" {
|
||||||
return false, fmt.Errorf(i18n.Translate(lang, "general:Please login first"))
|
return false, fmt.Errorf(i18n.Translate(lang, "general:Please login first"))
|
||||||
@ -397,8 +382,8 @@ func CheckUsername(username string, lang string) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// https://stackoverflow.com/questions/58726546/github-username-convention-using-regex
|
// https://stackoverflow.com/questions/58726546/github-username-convention-using-regex
|
||||||
re, _ := regexp.Compile("^[a-zA-Z0-9]+((?:-[a-zA-Z0-9]+)|(?:_[a-zA-Z0-9]+))*$")
|
|
||||||
if !re.MatchString(username) {
|
if !util.ReUserName.MatchString(username) {
|
||||||
return i18n.Translate(lang, "check: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.")
|
return i18n.Translate(lang, "check: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.")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -184,6 +184,7 @@ func initBuiltInApplication() {
|
|||||||
{Name: "Phone", Visible: true, Required: true, Prompted: false, Rule: "None"},
|
{Name: "Phone", Visible: true, Required: true, Prompted: false, Rule: "None"},
|
||||||
{Name: "Agreement", Visible: true, Required: true, Prompted: false, Rule: "None"},
|
{Name: "Agreement", Visible: true, Required: true, Prompted: false, Rule: "None"},
|
||||||
},
|
},
|
||||||
|
Tags: []string{},
|
||||||
RedirectUris: []string{},
|
RedirectUris: []string{},
|
||||||
ExpireInHours: 168,
|
ExpireInHours: 168,
|
||||||
FormOffset: 2,
|
FormOffset: 2,
|
||||||
|
@ -145,6 +145,9 @@ func readInitDataFromFile(filePath string) (*InitData, error) {
|
|||||||
if application.RedirectUris == nil {
|
if application.RedirectUris == nil {
|
||||||
application.RedirectUris = []string{}
|
application.RedirectUris = []string{}
|
||||||
}
|
}
|
||||||
|
if application.Tags == nil {
|
||||||
|
application.Tags = []string{}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
for _, permission := range data.Permissions {
|
for _, permission := range data.Permissions {
|
||||||
if permission.Actions == nil {
|
if permission.Actions == nil {
|
||||||
|
@ -22,6 +22,8 @@ import (
|
|||||||
"github.com/beego/beego/context"
|
"github.com/beego/beego/context"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const MfaRecoveryCodesSession = "mfa_recovery_codes"
|
||||||
|
|
||||||
type MfaSessionData struct {
|
type MfaSessionData struct {
|
||||||
UserId string
|
UserId string
|
||||||
}
|
}
|
||||||
@ -37,10 +39,10 @@ type MfaProps struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type MfaInterface interface {
|
type MfaInterface interface {
|
||||||
SetupVerify(ctx *context.Context, passCode string) error
|
Initiate(ctx *context.Context, userId string) (*MfaProps, error)
|
||||||
Verify(passCode string) error
|
SetupVerify(ctx *context.Context, passcode string) error
|
||||||
Initiate(ctx *context.Context, name1 string, name2 string) (*MfaProps, error)
|
|
||||||
Enable(ctx *context.Context, user *User) error
|
Enable(ctx *context.Context, user *User) error
|
||||||
|
Verify(passcode string) error
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -58,11 +60,11 @@ const (
|
|||||||
func GetMfaUtil(mfaType string, config *MfaProps) MfaInterface {
|
func GetMfaUtil(mfaType string, config *MfaProps) MfaInterface {
|
||||||
switch mfaType {
|
switch mfaType {
|
||||||
case SmsType:
|
case SmsType:
|
||||||
return NewSmsTwoFactor(config)
|
return NewSmsMfaUtil(config)
|
||||||
case EmailType:
|
case EmailType:
|
||||||
return NewEmailTwoFactor(config)
|
return NewEmailMfaUtil(config)
|
||||||
case TotpType:
|
case TotpType:
|
||||||
return nil
|
return NewTotpMfaUtil(config)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@ -97,23 +99,9 @@ func MfaRecover(user *User, recoveryCode string) error {
|
|||||||
func GetAllMfaProps(user *User, masked bool) []*MfaProps {
|
func GetAllMfaProps(user *User, masked bool) []*MfaProps {
|
||||||
mfaProps := []*MfaProps{}
|
mfaProps := []*MfaProps{}
|
||||||
|
|
||||||
if user.MfaPhoneEnabled {
|
for _, mfaType := range []string{SmsType, EmailType, TotpType} {
|
||||||
mfaProps = append(mfaProps, user.GetMfaProps(SmsType, masked))
|
mfaProps = append(mfaProps, user.GetMfaProps(mfaType, masked))
|
||||||
} else {
|
|
||||||
mfaProps = append(mfaProps, &MfaProps{
|
|
||||||
Enabled: false,
|
|
||||||
MfaType: SmsType,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
if user.MfaEmailEnabled {
|
|
||||||
mfaProps = append(mfaProps, user.GetMfaProps(EmailType, masked))
|
|
||||||
} else {
|
|
||||||
mfaProps = append(mfaProps, &MfaProps{
|
|
||||||
Enabled: false,
|
|
||||||
MfaType: EmailType,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
return mfaProps
|
return mfaProps
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -121,6 +109,13 @@ func (user *User) GetMfaProps(mfaType string, masked bool) *MfaProps {
|
|||||||
mfaProps := &MfaProps{}
|
mfaProps := &MfaProps{}
|
||||||
|
|
||||||
if mfaType == SmsType {
|
if mfaType == SmsType {
|
||||||
|
if !user.MfaPhoneEnabled {
|
||||||
|
return &MfaProps{
|
||||||
|
Enabled: false,
|
||||||
|
MfaType: mfaType,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
mfaProps = &MfaProps{
|
mfaProps = &MfaProps{
|
||||||
Enabled: user.MfaPhoneEnabled,
|
Enabled: user.MfaPhoneEnabled,
|
||||||
MfaType: mfaType,
|
MfaType: mfaType,
|
||||||
@ -132,6 +127,13 @@ func (user *User) GetMfaProps(mfaType string, masked bool) *MfaProps {
|
|||||||
mfaProps.Secret = user.Phone
|
mfaProps.Secret = user.Phone
|
||||||
}
|
}
|
||||||
} else if mfaType == EmailType {
|
} else if mfaType == EmailType {
|
||||||
|
if !user.MfaEmailEnabled {
|
||||||
|
return &MfaProps{
|
||||||
|
Enabled: false,
|
||||||
|
MfaType: mfaType,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
mfaProps = &MfaProps{
|
mfaProps = &MfaProps{
|
||||||
Enabled: user.MfaEmailEnabled,
|
Enabled: user.MfaEmailEnabled,
|
||||||
MfaType: mfaType,
|
MfaType: mfaType,
|
||||||
@ -142,9 +144,22 @@ func (user *User) GetMfaProps(mfaType string, masked bool) *MfaProps {
|
|||||||
mfaProps.Secret = user.Email
|
mfaProps.Secret = user.Email
|
||||||
}
|
}
|
||||||
} else if mfaType == TotpType {
|
} else if mfaType == TotpType {
|
||||||
|
if user.TotpSecret == "" {
|
||||||
|
return &MfaProps{
|
||||||
|
Enabled: false,
|
||||||
|
MfaType: mfaType,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
mfaProps = &MfaProps{
|
mfaProps = &MfaProps{
|
||||||
|
Enabled: true,
|
||||||
MfaType: mfaType,
|
MfaType: mfaType,
|
||||||
}
|
}
|
||||||
|
if masked {
|
||||||
|
mfaProps.Secret = ""
|
||||||
|
} else {
|
||||||
|
mfaProps.Secret = user.TotpSecret
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if user.PreferredMfaType == mfaType {
|
if user.PreferredMfaType == mfaType {
|
||||||
@ -158,8 +173,9 @@ func DisabledMultiFactorAuth(user *User) error {
|
|||||||
user.RecoveryCodes = []string{}
|
user.RecoveryCodes = []string{}
|
||||||
user.MfaPhoneEnabled = false
|
user.MfaPhoneEnabled = false
|
||||||
user.MfaEmailEnabled = false
|
user.MfaEmailEnabled = false
|
||||||
|
user.TotpSecret = ""
|
||||||
|
|
||||||
_, err := UpdateUser(user.GetId(), user, []string{"preferred_mfa_type", "recovery_codes", "mfa_phone_enabled", "mfa_email_enabled"}, user.IsAdminUser())
|
_, err := updateUser(user.GetId(), user, []string{"preferred_mfa_type", "recovery_codes", "mfa_phone_enabled", "mfa_email_enabled", "totp_secret"})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -18,26 +18,24 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/casdoor/casdoor/util"
|
|
||||||
|
|
||||||
"github.com/beego/beego/context"
|
"github.com/beego/beego/context"
|
||||||
|
"github.com/casdoor/casdoor/util"
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
MfaSmsCountryCodeSession = "mfa_country_code"
|
MfaSmsCountryCodeSession = "mfa_country_code"
|
||||||
MfaSmsDestSession = "mfa_dest"
|
MfaSmsDestSession = "mfa_dest"
|
||||||
MfaSmsRecoveryCodesSession = "mfa_recovery_codes"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type SmsMfa struct {
|
type SmsMfa struct {
|
||||||
Config *MfaProps
|
Config *MfaProps
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mfa *SmsMfa) Initiate(ctx *context.Context, name string, secret string) (*MfaProps, error) {
|
func (mfa *SmsMfa) Initiate(ctx *context.Context, userId string) (*MfaProps, error) {
|
||||||
recoveryCode := uuid.NewString()
|
recoveryCode := uuid.NewString()
|
||||||
|
|
||||||
err := ctx.Input.CruSession.Set(MfaSmsRecoveryCodesSession, []string{recoveryCode})
|
err := ctx.Input.CruSession.Set(MfaRecoveryCodesSession, []string{recoveryCode})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -63,9 +61,9 @@ func (mfa *SmsMfa) SetupVerify(ctx *context.Context, passCode string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (mfa *SmsMfa) Enable(ctx *context.Context, user *User) error {
|
func (mfa *SmsMfa) Enable(ctx *context.Context, user *User) error {
|
||||||
recoveryCodes := ctx.Input.CruSession.Get(MfaSmsRecoveryCodesSession).([]string)
|
recoveryCodes := ctx.Input.CruSession.Get(MfaRecoveryCodesSession).([]string)
|
||||||
if len(recoveryCodes) == 0 {
|
if len(recoveryCodes) == 0 {
|
||||||
return fmt.Errorf("recovery codes is empty")
|
return fmt.Errorf("recovery codes is missing")
|
||||||
}
|
}
|
||||||
|
|
||||||
columns := []string{"recovery_codes", "preferred_mfa_type"}
|
columns := []string{"recovery_codes", "preferred_mfa_type"}
|
||||||
@ -111,7 +109,7 @@ func (mfa *SmsMfa) Verify(passCode string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewSmsTwoFactor(config *MfaProps) *SmsMfa {
|
func NewSmsMfaUtil(config *MfaProps) *SmsMfa {
|
||||||
if config == nil {
|
if config == nil {
|
||||||
config = &MfaProps{
|
config = &MfaProps{
|
||||||
MfaType: SmsType,
|
MfaType: SmsType,
|
||||||
@ -122,7 +120,7 @@ func NewSmsTwoFactor(config *MfaProps) *SmsMfa {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewEmailTwoFactor(config *MfaProps) *SmsMfa {
|
func NewEmailMfaUtil(config *MfaProps) *SmsMfa {
|
||||||
if config == nil {
|
if config == nil {
|
||||||
config = &MfaProps{
|
config = &MfaProps{
|
||||||
MfaType: EmailType,
|
MfaType: EmailType,
|
||||||
|
133
object/mfa_totp.go
Normal file
133
object/mfa_totp.go
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
// Copyright 2023 The Casdoor Authors. All Rights Reserved.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package object
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/beego/beego"
|
||||||
|
"github.com/beego/beego/context"
|
||||||
|
"github.com/google/uuid"
|
||||||
|
"github.com/pquerna/otp"
|
||||||
|
"github.com/pquerna/otp/totp"
|
||||||
|
)
|
||||||
|
|
||||||
|
const MfaTotpSecretSession = "mfa_totp_secret"
|
||||||
|
|
||||||
|
type TotpMfa struct {
|
||||||
|
Config *MfaProps
|
||||||
|
period uint
|
||||||
|
secretSize uint
|
||||||
|
digits otp.Digits
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mfa *TotpMfa) Initiate(ctx *context.Context, userId string) (*MfaProps, error) {
|
||||||
|
issuer := beego.AppConfig.String("appname")
|
||||||
|
if issuer == "" {
|
||||||
|
issuer = "casdoor"
|
||||||
|
}
|
||||||
|
|
||||||
|
key, err := totp.Generate(totp.GenerateOpts{
|
||||||
|
Issuer: issuer,
|
||||||
|
AccountName: userId,
|
||||||
|
Period: mfa.period,
|
||||||
|
SecretSize: mfa.secretSize,
|
||||||
|
Digits: mfa.digits,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = ctx.Input.CruSession.Set(MfaTotpSecretSession, key.Secret())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
recoveryCode := uuid.NewString()
|
||||||
|
err = ctx.Input.CruSession.Set(MfaRecoveryCodesSession, []string{recoveryCode})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
mfaProps := MfaProps{
|
||||||
|
MfaType: mfa.Config.MfaType,
|
||||||
|
RecoveryCodes: []string{recoveryCode},
|
||||||
|
Secret: key.Secret(),
|
||||||
|
URL: key.URL(),
|
||||||
|
}
|
||||||
|
return &mfaProps, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mfa *TotpMfa) SetupVerify(ctx *context.Context, passcode string) error {
|
||||||
|
secret := ctx.Input.CruSession.Get(MfaTotpSecretSession).(string)
|
||||||
|
result := totp.Validate(passcode, secret)
|
||||||
|
|
||||||
|
if result {
|
||||||
|
return nil
|
||||||
|
} else {
|
||||||
|
return errors.New("totp passcode error")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mfa *TotpMfa) Enable(ctx *context.Context, user *User) error {
|
||||||
|
recoveryCodes := ctx.Input.CruSession.Get(MfaRecoveryCodesSession).([]string)
|
||||||
|
if len(recoveryCodes) == 0 {
|
||||||
|
return fmt.Errorf("recovery codes is missing")
|
||||||
|
}
|
||||||
|
secret := ctx.Input.CruSession.Get(MfaTotpSecretSession).(string)
|
||||||
|
if secret == "" {
|
||||||
|
return fmt.Errorf("totp secret is missing")
|
||||||
|
}
|
||||||
|
|
||||||
|
columns := []string{"recovery_codes", "preferred_mfa_type", "totp_secret"}
|
||||||
|
|
||||||
|
user.RecoveryCodes = append(user.RecoveryCodes, recoveryCodes...)
|
||||||
|
user.TotpSecret = secret
|
||||||
|
if user.PreferredMfaType == "" {
|
||||||
|
user.PreferredMfaType = mfa.Config.MfaType
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err := updateUser(user.GetId(), user, columns)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mfa *TotpMfa) Verify(passcode string) error {
|
||||||
|
result := totp.Validate(passcode, mfa.Config.Secret)
|
||||||
|
|
||||||
|
if result {
|
||||||
|
return nil
|
||||||
|
} else {
|
||||||
|
return errors.New("totp passcode error")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewTotpMfaUtil(config *MfaProps) *TotpMfa {
|
||||||
|
if config == nil {
|
||||||
|
config = &MfaProps{
|
||||||
|
MfaType: TotpType,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return &TotpMfa{
|
||||||
|
Config: config,
|
||||||
|
period: 30,
|
||||||
|
secretSize: 20,
|
||||||
|
digits: otp.DigitsSix,
|
||||||
|
}
|
||||||
|
}
|
@ -170,6 +170,7 @@ func (syncer *Syncer) getOriginalUsersFromMap(results []map[string]string) []*Or
|
|||||||
originalUser := &OriginalUser{
|
originalUser := &OriginalUser{
|
||||||
Address: []string{},
|
Address: []string{},
|
||||||
Properties: map[string]string{},
|
Properties: map[string]string{},
|
||||||
|
Groups: []string{},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tableColumn := range syncer.TableColumns {
|
for _, tableColumn := range syncer.TableColumns {
|
||||||
|
@ -161,6 +161,7 @@ type User struct {
|
|||||||
WebauthnCredentials []webauthn.Credential `xorm:"webauthnCredentials blob" json:"webauthnCredentials"`
|
WebauthnCredentials []webauthn.Credential `xorm:"webauthnCredentials blob" json:"webauthnCredentials"`
|
||||||
PreferredMfaType string `xorm:"varchar(100)" json:"preferredMfaType"`
|
PreferredMfaType string `xorm:"varchar(100)" json:"preferredMfaType"`
|
||||||
RecoveryCodes []string `xorm:"varchar(1000)" json:"recoveryCodes,omitempty"`
|
RecoveryCodes []string `xorm:"varchar(1000)" json:"recoveryCodes,omitempty"`
|
||||||
|
TotpSecret string `xorm:"varchar(100)" json:"totpSecret,omitempty"`
|
||||||
MfaPhoneEnabled bool `json:"mfaPhoneEnabled"`
|
MfaPhoneEnabled bool `json:"mfaPhoneEnabled"`
|
||||||
MfaEmailEnabled bool `json:"mfaEmailEnabled"`
|
MfaEmailEnabled bool `json:"mfaEmailEnabled"`
|
||||||
MultiFactorAuths []*MfaProps `xorm:"-" json:"multiFactorAuths,omitempty"`
|
MultiFactorAuths []*MfaProps `xorm:"-" json:"multiFactorAuths,omitempty"`
|
||||||
@ -432,16 +433,19 @@ func GetMaskedUser(user *User, errs ...error) (*User, error) {
|
|||||||
if user.AccessSecret != "" {
|
if user.AccessSecret != "" {
|
||||||
user.AccessSecret = "***"
|
user.AccessSecret = "***"
|
||||||
}
|
}
|
||||||
if user.RecoveryCodes != nil {
|
|
||||||
user.RecoveryCodes = nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if user.ManagedAccounts != nil {
|
if user.ManagedAccounts != nil {
|
||||||
for _, manageAccount := range user.ManagedAccounts {
|
for _, manageAccount := range user.ManagedAccounts {
|
||||||
manageAccount.Password = "***"
|
manageAccount.Password = "***"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if user.TotpSecret != "" {
|
||||||
|
user.TotpSecret = ""
|
||||||
|
}
|
||||||
|
if user.RecoveryCodes != nil {
|
||||||
|
user.RecoveryCodes = nil
|
||||||
|
}
|
||||||
|
|
||||||
return user, nil
|
return user, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,6 +43,34 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/api/add-adapter": {
|
||||||
|
"post": {
|
||||||
|
"tags": [
|
||||||
|
"Adapter API"
|
||||||
|
],
|
||||||
|
"description": "add adapter",
|
||||||
|
"operationId": "ApiController.AddCasbinAdapter",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"in": "body",
|
||||||
|
"name": "body",
|
||||||
|
"description": "The details of the adapter",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/object.Adapter"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "The Response object",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/controllers.Response"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"/api/add-application": {
|
"/api/add-application": {
|
||||||
"post": {
|
"post": {
|
||||||
"tags": [
|
"tags": [
|
||||||
@ -127,6 +155,34 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/api/add-group": {
|
||||||
|
"post": {
|
||||||
|
"tags": [
|
||||||
|
"Group API"
|
||||||
|
],
|
||||||
|
"description": "add group",
|
||||||
|
"operationId": "ApiController.AddGroup",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"in": "body",
|
||||||
|
"name": "body",
|
||||||
|
"description": "The details of the group",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/object.Group"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "The Response object",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/controllers.Response"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"/api/add-ldap": {
|
"/api/add-ldap": {
|
||||||
"post": {
|
"post": {
|
||||||
"tags": [
|
"tags": [
|
||||||
@ -599,6 +655,14 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/api/add-user-keys": {
|
||||||
|
"post": {
|
||||||
|
"tags": [
|
||||||
|
"User API"
|
||||||
|
],
|
||||||
|
"operationId": "ApiController.AddUserkeys"
|
||||||
|
}
|
||||||
|
},
|
||||||
"/api/add-webhook": {
|
"/api/add-webhook": {
|
||||||
"post": {
|
"post": {
|
||||||
"tags": [
|
"tags": [
|
||||||
@ -782,13 +846,13 @@
|
|||||||
"tags": [
|
"tags": [
|
||||||
"Enforce API"
|
"Enforce API"
|
||||||
],
|
],
|
||||||
"description": "perform enforce",
|
"description": "Call Casbin BatchEnforce API",
|
||||||
"operationId": "ApiController.BatchEnforce",
|
"operationId": "ApiController.BatchEnforce",
|
||||||
"parameters": [
|
"parameters": [
|
||||||
{
|
{
|
||||||
"in": "body",
|
"in": "body",
|
||||||
"name": "body",
|
"name": "body",
|
||||||
"description": "casbin request array",
|
"description": "array of casbin requests",
|
||||||
"required": true,
|
"required": true,
|
||||||
"schema": {
|
"schema": {
|
||||||
"$ref": "#/definitions/object.CasbinRequest"
|
"$ref": "#/definitions/object.CasbinRequest"
|
||||||
@ -858,6 +922,34 @@
|
|||||||
"operationId": "ApiController.CheckUserPassword"
|
"operationId": "ApiController.CheckUserPassword"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/api/delete-adapter": {
|
||||||
|
"post": {
|
||||||
|
"tags": [
|
||||||
|
"Adapter API"
|
||||||
|
],
|
||||||
|
"description": "delete adapter",
|
||||||
|
"operationId": "ApiController.DeleteCasbinAdapter",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"in": "body",
|
||||||
|
"name": "body",
|
||||||
|
"description": "The details of the adapter",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/object.Adapter"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "The Response object",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/controllers.Response"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"/api/delete-application": {
|
"/api/delete-application": {
|
||||||
"post": {
|
"post": {
|
||||||
"tags": [
|
"tags": [
|
||||||
@ -942,6 +1034,34 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/api/delete-group": {
|
||||||
|
"post": {
|
||||||
|
"tags": [
|
||||||
|
"Group API"
|
||||||
|
],
|
||||||
|
"description": "delete group",
|
||||||
|
"operationId": "ApiController.DeleteGroup",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"in": "body",
|
||||||
|
"name": "body",
|
||||||
|
"description": "The details of the group",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/object.Group"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "The Response object",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/controllers.Response"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"/api/delete-ldap": {
|
"/api/delete-ldap": {
|
||||||
"post": {
|
"post": {
|
||||||
"tags": [
|
"tags": [
|
||||||
@ -1429,13 +1549,13 @@
|
|||||||
"tags": [
|
"tags": [
|
||||||
"Enforce API"
|
"Enforce API"
|
||||||
],
|
],
|
||||||
"description": "perform enforce",
|
"description": "Call Casbin Enforce API",
|
||||||
"operationId": "ApiController.Enforce",
|
"operationId": "ApiController.Enforce",
|
||||||
"parameters": [
|
"parameters": [
|
||||||
{
|
{
|
||||||
"in": "body",
|
"in": "body",
|
||||||
"name": "body",
|
"name": "body",
|
||||||
"description": "casbin request",
|
"description": "Casbin request",
|
||||||
"required": true,
|
"required": true,
|
||||||
"schema": {
|
"schema": {
|
||||||
"$ref": "#/definitions/object.CasbinRequest"
|
"$ref": "#/definitions/object.CasbinRequest"
|
||||||
@ -1487,6 +1607,61 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/api/get-adapter": {
|
||||||
|
"get": {
|
||||||
|
"tags": [
|
||||||
|
"Adapter API"
|
||||||
|
],
|
||||||
|
"description": "get adapter",
|
||||||
|
"operationId": "ApiController.GetCasbinAdapter",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"in": "query",
|
||||||
|
"name": "id",
|
||||||
|
"description": "The id ( owner/name ) of the adapter",
|
||||||
|
"required": true,
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "The Response object",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/object.Adapter"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/api/get-adapters": {
|
||||||
|
"get": {
|
||||||
|
"tags": [
|
||||||
|
"Adapter API"
|
||||||
|
],
|
||||||
|
"description": "get adapters",
|
||||||
|
"operationId": "ApiController.GetCasbinAdapters",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"in": "query",
|
||||||
|
"name": "owner",
|
||||||
|
"description": "The owner of adapters",
|
||||||
|
"required": true,
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "The Response object",
|
||||||
|
"schema": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/definitions/object.Adapter"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"/api/get-app-login": {
|
"/api/get-app-login": {
|
||||||
"get": {
|
"get": {
|
||||||
"tags": [
|
"tags": [
|
||||||
@ -1825,6 +2000,61 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/api/get-group": {
|
||||||
|
"get": {
|
||||||
|
"tags": [
|
||||||
|
"Group API"
|
||||||
|
],
|
||||||
|
"description": "get group",
|
||||||
|
"operationId": "ApiController.GetGroup",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"in": "query",
|
||||||
|
"name": "id",
|
||||||
|
"description": "The id ( owner/name ) of the group",
|
||||||
|
"required": true,
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "The Response object",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/object.Group"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/api/get-groups": {
|
||||||
|
"get": {
|
||||||
|
"tags": [
|
||||||
|
"Group API"
|
||||||
|
],
|
||||||
|
"description": "get groups",
|
||||||
|
"operationId": "ApiController.GetGroups",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"in": "query",
|
||||||
|
"name": "owner",
|
||||||
|
"description": "The owner of groups",
|
||||||
|
"required": true,
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "The Response object",
|
||||||
|
"schema": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/definitions/object.Group"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"/api/get-ldap": {
|
"/api/get-ldap": {
|
||||||
"get": {
|
"get": {
|
||||||
"tags": [
|
"tags": [
|
||||||
@ -2045,7 +2275,7 @@
|
|||||||
"tags": [
|
"tags": [
|
||||||
"Organization API"
|
"Organization API"
|
||||||
],
|
],
|
||||||
"description": "get all organization names",
|
"description": "get all organization name and displayName",
|
||||||
"operationId": "ApiController.GetOrganizationNames",
|
"operationId": "ApiController.GetOrganizationNames",
|
||||||
"parameters": [
|
"parameters": [
|
||||||
{
|
{
|
||||||
@ -2338,7 +2568,7 @@
|
|||||||
"200": {
|
"200": {
|
||||||
"description": "The Response object",
|
"description": "The Response object",
|
||||||
"schema": {
|
"schema": {
|
||||||
"$ref": "#/definitions/object.pricing"
|
"$ref": "#/definitions/object.Pricing"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2753,7 +2983,7 @@
|
|||||||
"200": {
|
"200": {
|
||||||
"description": "The Response object",
|
"description": "The Response object",
|
||||||
"schema": {
|
"schema": {
|
||||||
"$ref": "#/definitions/object.subscription"
|
"$ref": "#/definitions/object.Subscription"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3328,7 +3558,7 @@
|
|||||||
"200": {
|
"200": {
|
||||||
"description": "The Response object",
|
"description": "The Response object",
|
||||||
"schema": {
|
"schema": {
|
||||||
"$ref": "#/definitions/Response"
|
"$ref": "#/definitions/controllers.Response"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3598,9 +3828,9 @@
|
|||||||
"operationId": "ApiController.MfaSetupInitiate",
|
"operationId": "ApiController.MfaSetupInitiate",
|
||||||
"responses": {
|
"responses": {
|
||||||
"200": {
|
"200": {
|
||||||
"description": "Response object",
|
"description": "The Response object",
|
||||||
"schema": {
|
"schema": {
|
||||||
"$ref": "#/definitions/The"
|
"$ref": "#/definitions/controllers.Response"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3799,6 +4029,41 @@
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/api/update-adapter": {
|
||||||
|
"post": {
|
||||||
|
"tags": [
|
||||||
|
"Adapter API"
|
||||||
|
],
|
||||||
|
"description": "update adapter",
|
||||||
|
"operationId": "ApiController.UpdateCasbinAdapter",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"in": "query",
|
||||||
|
"name": "id",
|
||||||
|
"description": "The id ( owner/name ) of the adapter",
|
||||||
|
"required": true,
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"in": "body",
|
||||||
|
"name": "body",
|
||||||
|
"description": "The details of the adapter",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/object.Adapter"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "The Response object",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/controllers.Response"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"/api/update-application": {
|
"/api/update-application": {
|
||||||
"post": {
|
"post": {
|
||||||
"tags": [
|
"tags": [
|
||||||
@ -3904,6 +4169,41 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/api/update-group": {
|
||||||
|
"post": {
|
||||||
|
"tags": [
|
||||||
|
"Group API"
|
||||||
|
],
|
||||||
|
"description": "update group",
|
||||||
|
"operationId": "ApiController.UpdateGroup",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"in": "query",
|
||||||
|
"name": "id",
|
||||||
|
"description": "The id ( owner/name ) of the group",
|
||||||
|
"required": true,
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"in": "body",
|
||||||
|
"name": "body",
|
||||||
|
"description": "The details of the group",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/object.Group"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "The Response object",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/controllers.Response"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"/api/update-ldap": {
|
"/api/update-ldap": {
|
||||||
"post": {
|
"post": {
|
||||||
"tags": [
|
"tags": [
|
||||||
@ -4579,7 +4879,7 @@
|
|||||||
"200": {
|
"200": {
|
||||||
"description": "\"The Response object\"",
|
"description": "\"The Response object\"",
|
||||||
"schema": {
|
"schema": {
|
||||||
"$ref": "#/definitions/Response"
|
"$ref": "#/definitions/controllers.Response"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -4624,7 +4924,7 @@
|
|||||||
"200": {
|
"200": {
|
||||||
"description": "\"The Response object\"",
|
"description": "\"The Response object\"",
|
||||||
"schema": {
|
"schema": {
|
||||||
"$ref": "#/definitions/Response"
|
"$ref": "#/definitions/controllers.Response"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -4632,14 +4932,6 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"definitions": {
|
"definitions": {
|
||||||
"1225.0xc0002e2ae0.false": {
|
|
||||||
"title": "false",
|
|
||||||
"type": "object"
|
|
||||||
},
|
|
||||||
"1260.0xc0002e2b10.false": {
|
|
||||||
"title": "false",
|
|
||||||
"type": "object"
|
|
||||||
},
|
|
||||||
"LaravelResponse": {
|
"LaravelResponse": {
|
||||||
"title": "LaravelResponse",
|
"title": "LaravelResponse",
|
||||||
"type": "object"
|
"type": "object"
|
||||||
@ -4648,10 +4940,6 @@
|
|||||||
"title": "Response",
|
"title": "Response",
|
||||||
"type": "object"
|
"type": "object"
|
||||||
},
|
},
|
||||||
"The": {
|
|
||||||
"title": "The",
|
|
||||||
"type": "object"
|
|
||||||
},
|
|
||||||
"controllers.AuthForm": {
|
"controllers.AuthForm": {
|
||||||
"title": "AuthForm",
|
"title": "AuthForm",
|
||||||
"type": "object"
|
"type": "object"
|
||||||
@ -4685,10 +4973,16 @@
|
|||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"data": {
|
"data": {
|
||||||
"$ref": "#/definitions/1225.0xc0002e2ae0.false"
|
"additionalProperties": {
|
||||||
|
"description": "support string | class | List\u003cclass\u003e and os on",
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"data2": {
|
"data2": {
|
||||||
"$ref": "#/definitions/1260.0xc0002e2b10.false"
|
"additionalProperties": {
|
||||||
|
"description": "support string | class | List\u003cclass\u003e and os on",
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"msg": {
|
"msg": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
@ -4726,8 +5020,8 @@
|
|||||||
"title": "JSONWebKey",
|
"title": "JSONWebKey",
|
||||||
"type": "object"
|
"type": "object"
|
||||||
},
|
},
|
||||||
"object.\u0026{179844 0xc000a02f90 false}": {
|
"object": {
|
||||||
"title": "\u0026{179844 0xc000a02f90 false}",
|
"title": "object",
|
||||||
"type": "object"
|
"type": "object"
|
||||||
},
|
},
|
||||||
"object.AccountItem": {
|
"object.AccountItem": {
|
||||||
@ -4917,7 +5211,7 @@
|
|||||||
"title": "CasbinRequest",
|
"title": "CasbinRequest",
|
||||||
"type": "array",
|
"type": "array",
|
||||||
"items": {
|
"items": {
|
||||||
"$ref": "#/definitions/object.\u0026{179844 0xc000a02f90 false}"
|
"$ref": "#/definitions/object.CasbinRequest"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"object.Cert": {
|
"object.Cert": {
|
||||||
@ -5029,6 +5323,63 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"object.Group": {
|
||||||
|
"title": "Group",
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"children": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/definitions/object.Group"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"contactEmail": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"createdTime": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"displayName": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"isEnabled": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"isTopGroup": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"key": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"manager": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"owner": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"parentId": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"title": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"type": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"updatedTime": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"users": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/definitions/object.User"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"object.Header": {
|
"object.Header": {
|
||||||
"title": "Header",
|
"title": "Header",
|
||||||
"type": "object",
|
"type": "object",
|
||||||
@ -5175,12 +5526,15 @@
|
|||||||
"countryCode": {
|
"countryCode": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"id": {
|
"enabled": {
|
||||||
"type": "string"
|
"type": "boolean"
|
||||||
},
|
},
|
||||||
"isPreferred": {
|
"isPreferred": {
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
},
|
},
|
||||||
|
"mfaType": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"recoveryCodes": {
|
"recoveryCodes": {
|
||||||
"type": "array",
|
"type": "array",
|
||||||
"items": {
|
"items": {
|
||||||
@ -5190,9 +5544,6 @@
|
|||||||
"secret": {
|
"secret": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"type": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"url": {
|
"url": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
}
|
}
|
||||||
@ -5205,6 +5556,9 @@
|
|||||||
"createdTime": {
|
"createdTime": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
"description": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"displayName": {
|
"displayName": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
@ -5362,6 +5716,12 @@
|
|||||||
"owner": {
|
"owner": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
"passwordOptions": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
"passwordSalt": {
|
"passwordSalt": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
@ -5492,6 +5852,9 @@
|
|||||||
"createdTime": {
|
"createdTime": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
"description": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"displayName": {
|
"displayName": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
@ -5611,9 +5974,6 @@
|
|||||||
"displayName": {
|
"displayName": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"hasTrial": {
|
|
||||||
"type": "boolean"
|
|
||||||
},
|
|
||||||
"isEnabled": {
|
"isEnabled": {
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
},
|
},
|
||||||
@ -5933,6 +6293,9 @@
|
|||||||
"createdTime": {
|
"createdTime": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
"description": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"displayName": {
|
"displayName": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
@ -6068,6 +6431,9 @@
|
|||||||
"isEnabled": {
|
"isEnabled": {
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
},
|
},
|
||||||
|
"isReadOnly": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
"name": {
|
"name": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
@ -6248,6 +6614,12 @@
|
|||||||
"title": "User",
|
"title": "User",
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
"accessKey": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"accessSecret": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"address": {
|
"address": {
|
||||||
"type": "array",
|
"type": "array",
|
||||||
"items": {
|
"items": {
|
||||||
@ -6275,6 +6647,9 @@
|
|||||||
"avatar": {
|
"avatar": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
"avatarType": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"azuread": {
|
"azuread": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
@ -6380,6 +6755,12 @@
|
|||||||
"google": {
|
"google": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
"groups": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
"hash": {
|
"hash": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
@ -6480,6 +6861,12 @@
|
|||||||
"meetup": {
|
"meetup": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
"mfaEmailEnabled": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"mfaPhoneEnabled": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
"microsoftonline": {
|
"microsoftonline": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
@ -6540,6 +6927,9 @@
|
|||||||
"preHash": {
|
"preHash": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
"preferredMfaType": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"properties": {
|
"properties": {
|
||||||
"additionalProperties": {
|
"additionalProperties": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
@ -6552,6 +6942,12 @@
|
|||||||
"type": "integer",
|
"type": "integer",
|
||||||
"format": "int64"
|
"format": "int64"
|
||||||
},
|
},
|
||||||
|
"recoveryCodes": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
"region": {
|
"region": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
@ -6605,6 +7001,9 @@
|
|||||||
"title": {
|
"title": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
"totpSecret": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"tumblr": {
|
"tumblr": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
@ -6677,15 +7076,18 @@
|
|||||||
"email": {
|
"email": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
"groups": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
"iss": {
|
"iss": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"name": {
|
"name": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"organization": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"phone": {
|
"phone": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
@ -6745,14 +7147,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"object.pricing": {
|
|
||||||
"title": "pricing",
|
|
||||||
"type": "object"
|
|
||||||
},
|
|
||||||
"object.subscription": {
|
|
||||||
"title": "subscription",
|
|
||||||
"type": "object"
|
|
||||||
},
|
|
||||||
"protocol.CredentialAssertion": {
|
"protocol.CredentialAssertion": {
|
||||||
"title": "CredentialAssertion",
|
"title": "CredentialAssertion",
|
||||||
"type": "object"
|
"type": "object"
|
||||||
|
@ -28,6 +28,24 @@ paths:
|
|||||||
description: ""
|
description: ""
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/definitions/object.OidcDiscovery'
|
$ref: '#/definitions/object.OidcDiscovery'
|
||||||
|
/api/add-adapter:
|
||||||
|
post:
|
||||||
|
tags:
|
||||||
|
- Adapter API
|
||||||
|
description: add adapter
|
||||||
|
operationId: ApiController.AddCasbinAdapter
|
||||||
|
parameters:
|
||||||
|
- in: body
|
||||||
|
name: body
|
||||||
|
description: The details of the adapter
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/object.Adapter'
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: The Response object
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/controllers.Response'
|
||||||
/api/add-application:
|
/api/add-application:
|
||||||
post:
|
post:
|
||||||
tags:
|
tags:
|
||||||
@ -82,6 +100,24 @@ paths:
|
|||||||
description: The Response object
|
description: The Response object
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/definitions/controllers.Response'
|
$ref: '#/definitions/controllers.Response'
|
||||||
|
/api/add-group:
|
||||||
|
post:
|
||||||
|
tags:
|
||||||
|
- Group API
|
||||||
|
description: add group
|
||||||
|
operationId: ApiController.AddGroup
|
||||||
|
parameters:
|
||||||
|
- in: body
|
||||||
|
name: body
|
||||||
|
description: The details of the group
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/object.Group'
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: The Response object
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/controllers.Response'
|
||||||
/api/add-ldap:
|
/api/add-ldap:
|
||||||
post:
|
post:
|
||||||
tags:
|
tags:
|
||||||
@ -386,6 +422,11 @@ paths:
|
|||||||
description: The Response object
|
description: The Response object
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/definitions/controllers.Response'
|
$ref: '#/definitions/controllers.Response'
|
||||||
|
/api/add-user-keys:
|
||||||
|
post:
|
||||||
|
tags:
|
||||||
|
- User API
|
||||||
|
operationId: ApiController.AddUserkeys
|
||||||
/api/add-webhook:
|
/api/add-webhook:
|
||||||
post:
|
post:
|
||||||
tags:
|
tags:
|
||||||
@ -506,12 +547,12 @@ paths:
|
|||||||
post:
|
post:
|
||||||
tags:
|
tags:
|
||||||
- Enforce API
|
- Enforce API
|
||||||
description: perform enforce
|
description: Call Casbin BatchEnforce API
|
||||||
operationId: ApiController.BatchEnforce
|
operationId: ApiController.BatchEnforce
|
||||||
parameters:
|
parameters:
|
||||||
- in: body
|
- in: body
|
||||||
name: body
|
name: body
|
||||||
description: casbin request array
|
description: array of casbin requests
|
||||||
required: true
|
required: true
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/definitions/object.CasbinRequest'
|
$ref: '#/definitions/object.CasbinRequest'
|
||||||
@ -555,6 +596,24 @@ paths:
|
|||||||
tags:
|
tags:
|
||||||
- User API
|
- User API
|
||||||
operationId: ApiController.CheckUserPassword
|
operationId: ApiController.CheckUserPassword
|
||||||
|
/api/delete-adapter:
|
||||||
|
post:
|
||||||
|
tags:
|
||||||
|
- Adapter API
|
||||||
|
description: delete adapter
|
||||||
|
operationId: ApiController.DeleteCasbinAdapter
|
||||||
|
parameters:
|
||||||
|
- in: body
|
||||||
|
name: body
|
||||||
|
description: The details of the adapter
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/object.Adapter'
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: The Response object
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/controllers.Response'
|
||||||
/api/delete-application:
|
/api/delete-application:
|
||||||
post:
|
post:
|
||||||
tags:
|
tags:
|
||||||
@ -609,6 +668,24 @@ paths:
|
|||||||
description: The Response object
|
description: The Response object
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/definitions/controllers.Response'
|
$ref: '#/definitions/controllers.Response'
|
||||||
|
/api/delete-group:
|
||||||
|
post:
|
||||||
|
tags:
|
||||||
|
- Group API
|
||||||
|
description: delete group
|
||||||
|
operationId: ApiController.DeleteGroup
|
||||||
|
parameters:
|
||||||
|
- in: body
|
||||||
|
name: body
|
||||||
|
description: The details of the group
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/object.Group'
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: The Response object
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/controllers.Response'
|
||||||
/api/delete-ldap:
|
/api/delete-ldap:
|
||||||
post:
|
post:
|
||||||
tags:
|
tags:
|
||||||
@ -923,12 +1000,12 @@ paths:
|
|||||||
post:
|
post:
|
||||||
tags:
|
tags:
|
||||||
- Enforce API
|
- Enforce API
|
||||||
description: perform enforce
|
description: Call Casbin Enforce API
|
||||||
operationId: ApiController.Enforce
|
operationId: ApiController.Enforce
|
||||||
parameters:
|
parameters:
|
||||||
- in: body
|
- in: body
|
||||||
name: body
|
name: body
|
||||||
description: casbin request
|
description: Casbin request
|
||||||
required: true
|
required: true
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/definitions/object.CasbinRequest'
|
$ref: '#/definitions/object.CasbinRequest'
|
||||||
@ -960,6 +1037,42 @@ paths:
|
|||||||
description: The Response object
|
description: The Response object
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/definitions/controllers.Response'
|
$ref: '#/definitions/controllers.Response'
|
||||||
|
/api/get-adapter:
|
||||||
|
get:
|
||||||
|
tags:
|
||||||
|
- Adapter API
|
||||||
|
description: get adapter
|
||||||
|
operationId: ApiController.GetCasbinAdapter
|
||||||
|
parameters:
|
||||||
|
- in: query
|
||||||
|
name: id
|
||||||
|
description: The id ( owner/name ) of the adapter
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: The Response object
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/object.Adapter'
|
||||||
|
/api/get-adapters:
|
||||||
|
get:
|
||||||
|
tags:
|
||||||
|
- Adapter API
|
||||||
|
description: get adapters
|
||||||
|
operationId: ApiController.GetCasbinAdapters
|
||||||
|
parameters:
|
||||||
|
- in: query
|
||||||
|
name: owner
|
||||||
|
description: The owner of adapters
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: The Response object
|
||||||
|
schema:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
$ref: '#/definitions/object.Adapter'
|
||||||
/api/get-app-login:
|
/api/get-app-login:
|
||||||
get:
|
get:
|
||||||
tags:
|
tags:
|
||||||
@ -1183,6 +1296,42 @@ paths:
|
|||||||
type: array
|
type: array
|
||||||
items:
|
items:
|
||||||
$ref: '#/definitions/object.Cert'
|
$ref: '#/definitions/object.Cert'
|
||||||
|
/api/get-group:
|
||||||
|
get:
|
||||||
|
tags:
|
||||||
|
- Group API
|
||||||
|
description: get group
|
||||||
|
operationId: ApiController.GetGroup
|
||||||
|
parameters:
|
||||||
|
- in: query
|
||||||
|
name: id
|
||||||
|
description: The id ( owner/name ) of the group
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: The Response object
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/object.Group'
|
||||||
|
/api/get-groups:
|
||||||
|
get:
|
||||||
|
tags:
|
||||||
|
- Group API
|
||||||
|
description: get groups
|
||||||
|
operationId: ApiController.GetGroups
|
||||||
|
parameters:
|
||||||
|
- in: query
|
||||||
|
name: owner
|
||||||
|
description: The owner of groups
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: The Response object
|
||||||
|
schema:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
$ref: '#/definitions/object.Group'
|
||||||
/api/get-ldap:
|
/api/get-ldap:
|
||||||
get:
|
get:
|
||||||
tags:
|
tags:
|
||||||
@ -1327,7 +1476,7 @@ paths:
|
|||||||
get:
|
get:
|
||||||
tags:
|
tags:
|
||||||
- Organization API
|
- Organization API
|
||||||
description: get all organization names
|
description: get all organization name and displayName
|
||||||
operationId: ApiController.GetOrganizationNames
|
operationId: ApiController.GetOrganizationNames
|
||||||
parameters:
|
parameters:
|
||||||
- in: query
|
- in: query
|
||||||
@ -1521,7 +1670,7 @@ paths:
|
|||||||
"200":
|
"200":
|
||||||
description: The Response object
|
description: The Response object
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/definitions/object.pricing'
|
$ref: '#/definitions/object.Pricing'
|
||||||
/api/get-pricings:
|
/api/get-pricings:
|
||||||
get:
|
get:
|
||||||
tags:
|
tags:
|
||||||
@ -1793,7 +1942,7 @@ paths:
|
|||||||
"200":
|
"200":
|
||||||
description: The Response object
|
description: The Response object
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/definitions/object.subscription'
|
$ref: '#/definitions/object.Subscription'
|
||||||
/api/get-subscriptions:
|
/api/get-subscriptions:
|
||||||
get:
|
get:
|
||||||
tags:
|
tags:
|
||||||
@ -2172,7 +2321,7 @@ paths:
|
|||||||
"200":
|
"200":
|
||||||
description: The Response object
|
description: The Response object
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/definitions/Response'
|
$ref: '#/definitions/controllers.Response'
|
||||||
/api/login/oauth/access_token:
|
/api/login/oauth/access_token:
|
||||||
post:
|
post:
|
||||||
tags:
|
tags:
|
||||||
@ -2351,9 +2500,9 @@ paths:
|
|||||||
operationId: ApiController.MfaSetupInitiate
|
operationId: ApiController.MfaSetupInitiate
|
||||||
responses:
|
responses:
|
||||||
"200":
|
"200":
|
||||||
description: Response object
|
description: The Response object
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/definitions/The'
|
$ref: '#/definitions/controllers.Response'
|
||||||
/api/mfa/setup/verify:
|
/api/mfa/setup/verify:
|
||||||
post:
|
post:
|
||||||
tags:
|
tags:
|
||||||
@ -2480,6 +2629,29 @@ paths:
|
|||||||
post:
|
post:
|
||||||
tags:
|
tags:
|
||||||
- Login API
|
- Login API
|
||||||
|
/api/update-adapter:
|
||||||
|
post:
|
||||||
|
tags:
|
||||||
|
- Adapter API
|
||||||
|
description: update adapter
|
||||||
|
operationId: ApiController.UpdateCasbinAdapter
|
||||||
|
parameters:
|
||||||
|
- in: query
|
||||||
|
name: id
|
||||||
|
description: The id ( owner/name ) of the adapter
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
- in: body
|
||||||
|
name: body
|
||||||
|
description: The details of the adapter
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/object.Adapter'
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: The Response object
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/controllers.Response'
|
||||||
/api/update-application:
|
/api/update-application:
|
||||||
post:
|
post:
|
||||||
tags:
|
tags:
|
||||||
@ -2549,6 +2721,29 @@ paths:
|
|||||||
description: The Response object
|
description: The Response object
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/definitions/controllers.Response'
|
$ref: '#/definitions/controllers.Response'
|
||||||
|
/api/update-group:
|
||||||
|
post:
|
||||||
|
tags:
|
||||||
|
- Group API
|
||||||
|
description: update group
|
||||||
|
operationId: ApiController.UpdateGroup
|
||||||
|
parameters:
|
||||||
|
- in: query
|
||||||
|
name: id
|
||||||
|
description: The id ( owner/name ) of the group
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
- in: body
|
||||||
|
name: body
|
||||||
|
description: The details of the group
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/object.Group'
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: The Response object
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/controllers.Response'
|
||||||
/api/update-ldap:
|
/api/update-ldap:
|
||||||
post:
|
post:
|
||||||
tags:
|
tags:
|
||||||
@ -2994,7 +3189,7 @@ paths:
|
|||||||
"200":
|
"200":
|
||||||
description: '"The Response object"'
|
description: '"The Response object"'
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/definitions/Response'
|
$ref: '#/definitions/controllers.Response'
|
||||||
/api/webauthn/signup/begin:
|
/api/webauthn/signup/begin:
|
||||||
get:
|
get:
|
||||||
tags:
|
tags:
|
||||||
@ -3023,23 +3218,14 @@ paths:
|
|||||||
"200":
|
"200":
|
||||||
description: '"The Response object"'
|
description: '"The Response object"'
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/definitions/Response'
|
$ref: '#/definitions/controllers.Response'
|
||||||
definitions:
|
definitions:
|
||||||
1225.0xc0002e2ae0.false:
|
|
||||||
title: "false"
|
|
||||||
type: object
|
|
||||||
1260.0xc0002e2b10.false:
|
|
||||||
title: "false"
|
|
||||||
type: object
|
|
||||||
LaravelResponse:
|
LaravelResponse:
|
||||||
title: LaravelResponse
|
title: LaravelResponse
|
||||||
type: object
|
type: object
|
||||||
Response:
|
Response:
|
||||||
title: Response
|
title: Response
|
||||||
type: object
|
type: object
|
||||||
The:
|
|
||||||
title: The
|
|
||||||
type: object
|
|
||||||
controllers.AuthForm:
|
controllers.AuthForm:
|
||||||
title: AuthForm
|
title: AuthForm
|
||||||
type: object
|
type: object
|
||||||
@ -3064,9 +3250,13 @@ definitions:
|
|||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
data:
|
data:
|
||||||
$ref: '#/definitions/1225.0xc0002e2ae0.false'
|
additionalProperties:
|
||||||
|
description: support string | class | List<class> and os on
|
||||||
|
type: string
|
||||||
data2:
|
data2:
|
||||||
$ref: '#/definitions/1260.0xc0002e2b10.false'
|
additionalProperties:
|
||||||
|
description: support string | class | List<class> and os on
|
||||||
|
type: string
|
||||||
msg:
|
msg:
|
||||||
type: string
|
type: string
|
||||||
name:
|
name:
|
||||||
@ -3090,8 +3280,8 @@ definitions:
|
|||||||
jose.JSONWebKey:
|
jose.JSONWebKey:
|
||||||
title: JSONWebKey
|
title: JSONWebKey
|
||||||
type: object
|
type: object
|
||||||
object.&{179844 0xc000a02f90 false}:
|
object:
|
||||||
title: '&{179844 0xc000a02f90 false}'
|
title: object
|
||||||
type: object
|
type: object
|
||||||
object.AccountItem:
|
object.AccountItem:
|
||||||
title: AccountItem
|
title: AccountItem
|
||||||
@ -3220,7 +3410,7 @@ definitions:
|
|||||||
title: CasbinRequest
|
title: CasbinRequest
|
||||||
type: array
|
type: array
|
||||||
items:
|
items:
|
||||||
$ref: '#/definitions/object.&{179844 0xc000a02f90 false}'
|
$ref: '#/definitions/object.CasbinRequest'
|
||||||
object.Cert:
|
object.Cert:
|
||||||
title: Cert
|
title: Cert
|
||||||
type: object
|
type: object
|
||||||
@ -3295,6 +3485,44 @@ definitions:
|
|||||||
throughput:
|
throughput:
|
||||||
type: number
|
type: number
|
||||||
format: double
|
format: double
|
||||||
|
object.Group:
|
||||||
|
title: Group
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
children:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
$ref: '#/definitions/object.Group'
|
||||||
|
contactEmail:
|
||||||
|
type: string
|
||||||
|
createdTime:
|
||||||
|
type: string
|
||||||
|
displayName:
|
||||||
|
type: string
|
||||||
|
isEnabled:
|
||||||
|
type: boolean
|
||||||
|
isTopGroup:
|
||||||
|
type: boolean
|
||||||
|
key:
|
||||||
|
type: string
|
||||||
|
manager:
|
||||||
|
type: string
|
||||||
|
name:
|
||||||
|
type: string
|
||||||
|
owner:
|
||||||
|
type: string
|
||||||
|
parentId:
|
||||||
|
type: string
|
||||||
|
title:
|
||||||
|
type: string
|
||||||
|
type:
|
||||||
|
type: string
|
||||||
|
updatedTime:
|
||||||
|
type: string
|
||||||
|
users:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
$ref: '#/definitions/object.User'
|
||||||
object.Header:
|
object.Header:
|
||||||
title: Header
|
title: Header
|
||||||
type: object
|
type: object
|
||||||
@ -3395,18 +3623,18 @@ definitions:
|
|||||||
properties:
|
properties:
|
||||||
countryCode:
|
countryCode:
|
||||||
type: string
|
type: string
|
||||||
id:
|
enabled:
|
||||||
type: string
|
type: boolean
|
||||||
isPreferred:
|
isPreferred:
|
||||||
type: boolean
|
type: boolean
|
||||||
|
mfaType:
|
||||||
|
type: string
|
||||||
recoveryCodes:
|
recoveryCodes:
|
||||||
type: array
|
type: array
|
||||||
items:
|
items:
|
||||||
type: string
|
type: string
|
||||||
secret:
|
secret:
|
||||||
type: string
|
type: string
|
||||||
type:
|
|
||||||
type: string
|
|
||||||
url:
|
url:
|
||||||
type: string
|
type: string
|
||||||
object.Model:
|
object.Model:
|
||||||
@ -3415,6 +3643,8 @@ definitions:
|
|||||||
properties:
|
properties:
|
||||||
createdTime:
|
createdTime:
|
||||||
type: string
|
type: string
|
||||||
|
description:
|
||||||
|
type: string
|
||||||
displayName:
|
displayName:
|
||||||
type: string
|
type: string
|
||||||
isEnabled:
|
isEnabled:
|
||||||
@ -3520,6 +3750,10 @@ definitions:
|
|||||||
type: string
|
type: string
|
||||||
owner:
|
owner:
|
||||||
type: string
|
type: string
|
||||||
|
passwordOptions:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
passwordSalt:
|
passwordSalt:
|
||||||
type: string
|
type: string
|
||||||
passwordType:
|
passwordType:
|
||||||
@ -3607,6 +3841,8 @@ definitions:
|
|||||||
type: string
|
type: string
|
||||||
createdTime:
|
createdTime:
|
||||||
type: string
|
type: string
|
||||||
|
description:
|
||||||
|
type: string
|
||||||
displayName:
|
displayName:
|
||||||
type: string
|
type: string
|
||||||
domains:
|
domains:
|
||||||
@ -3687,8 +3923,6 @@ definitions:
|
|||||||
type: string
|
type: string
|
||||||
displayName:
|
displayName:
|
||||||
type: string
|
type: string
|
||||||
hasTrial:
|
|
||||||
type: boolean
|
|
||||||
isEnabled:
|
isEnabled:
|
||||||
type: boolean
|
type: boolean
|
||||||
name:
|
name:
|
||||||
@ -3904,6 +4138,8 @@ definitions:
|
|||||||
properties:
|
properties:
|
||||||
createdTime:
|
createdTime:
|
||||||
type: string
|
type: string
|
||||||
|
description:
|
||||||
|
type: string
|
||||||
displayName:
|
displayName:
|
||||||
type: string
|
type: string
|
||||||
domains:
|
domains:
|
||||||
@ -3995,6 +4231,8 @@ definitions:
|
|||||||
type: string
|
type: string
|
||||||
isEnabled:
|
isEnabled:
|
||||||
type: boolean
|
type: boolean
|
||||||
|
isReadOnly:
|
||||||
|
type: boolean
|
||||||
name:
|
name:
|
||||||
type: string
|
type: string
|
||||||
organization:
|
organization:
|
||||||
@ -4117,6 +4355,10 @@ definitions:
|
|||||||
title: User
|
title: User
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
|
accessKey:
|
||||||
|
type: string
|
||||||
|
accessSecret:
|
||||||
|
type: string
|
||||||
address:
|
address:
|
||||||
type: array
|
type: array
|
||||||
items:
|
items:
|
||||||
@ -4135,6 +4377,8 @@ definitions:
|
|||||||
type: string
|
type: string
|
||||||
avatar:
|
avatar:
|
||||||
type: string
|
type: string
|
||||||
|
avatarType:
|
||||||
|
type: string
|
||||||
azuread:
|
azuread:
|
||||||
type: string
|
type: string
|
||||||
baidu:
|
baidu:
|
||||||
@ -4205,6 +4449,10 @@ definitions:
|
|||||||
type: string
|
type: string
|
||||||
google:
|
google:
|
||||||
type: string
|
type: string
|
||||||
|
groups:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
hash:
|
hash:
|
||||||
type: string
|
type: string
|
||||||
heroku:
|
heroku:
|
||||||
@ -4272,6 +4520,10 @@ definitions:
|
|||||||
$ref: '#/definitions/object.ManagedAccount'
|
$ref: '#/definitions/object.ManagedAccount'
|
||||||
meetup:
|
meetup:
|
||||||
type: string
|
type: string
|
||||||
|
mfaEmailEnabled:
|
||||||
|
type: boolean
|
||||||
|
mfaPhoneEnabled:
|
||||||
|
type: boolean
|
||||||
microsoftonline:
|
microsoftonline:
|
||||||
type: string
|
type: string
|
||||||
multiFactorAuths:
|
multiFactorAuths:
|
||||||
@ -4312,6 +4564,8 @@ definitions:
|
|||||||
type: string
|
type: string
|
||||||
preHash:
|
preHash:
|
||||||
type: string
|
type: string
|
||||||
|
preferredMfaType:
|
||||||
|
type: string
|
||||||
properties:
|
properties:
|
||||||
additionalProperties:
|
additionalProperties:
|
||||||
type: string
|
type: string
|
||||||
@ -4320,6 +4574,10 @@ definitions:
|
|||||||
ranking:
|
ranking:
|
||||||
type: integer
|
type: integer
|
||||||
format: int64
|
format: int64
|
||||||
|
recoveryCodes:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
region:
|
region:
|
||||||
type: string
|
type: string
|
||||||
roles:
|
roles:
|
||||||
@ -4356,6 +4614,8 @@ definitions:
|
|||||||
type: string
|
type: string
|
||||||
title:
|
title:
|
||||||
type: string
|
type: string
|
||||||
|
totpSecret:
|
||||||
|
type: string
|
||||||
tumblr:
|
tumblr:
|
||||||
type: string
|
type: string
|
||||||
twitch:
|
twitch:
|
||||||
@ -4404,12 +4664,14 @@ definitions:
|
|||||||
type: string
|
type: string
|
||||||
email:
|
email:
|
||||||
type: string
|
type: string
|
||||||
|
groups:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
iss:
|
iss:
|
||||||
type: string
|
type: string
|
||||||
name:
|
name:
|
||||||
type: string
|
type: string
|
||||||
organization:
|
|
||||||
type: string
|
|
||||||
phone:
|
phone:
|
||||||
type: string
|
type: string
|
||||||
picture:
|
picture:
|
||||||
@ -4448,12 +4710,6 @@ definitions:
|
|||||||
type: string
|
type: string
|
||||||
url:
|
url:
|
||||||
type: string
|
type: string
|
||||||
object.pricing:
|
|
||||||
title: pricing
|
|
||||||
type: object
|
|
||||||
object.subscription:
|
|
||||||
title: subscription
|
|
||||||
type: object
|
|
||||||
protocol.CredentialAssertion:
|
protocol.CredentialAssertion:
|
||||||
title: CredentialAssertion
|
title: CredentialAssertion
|
||||||
type: object
|
type: object
|
||||||
|
@ -43,6 +43,15 @@ func ContainsString(values []string, val string) bool {
|
|||||||
return sort.SearchStrings(values, val) != len(values)
|
return sort.SearchStrings(values, val) != len(values)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func InSlice(slice []string, elem string) bool {
|
||||||
|
for _, val := range slice {
|
||||||
|
if val == elem {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
func ReturnAnyNotEmpty(strs ...string) string {
|
func ReturnAnyNotEmpty(strs ...string) string {
|
||||||
for _, str := range strs {
|
for _, str := range strs {
|
||||||
if str != "" {
|
if str != "" {
|
||||||
|
@ -22,10 +22,18 @@ import (
|
|||||||
"github.com/nyaruka/phonenumbers"
|
"github.com/nyaruka/phonenumbers"
|
||||||
)
|
)
|
||||||
|
|
||||||
var rePhone *regexp.Regexp
|
var (
|
||||||
|
rePhone *regexp.Regexp
|
||||||
|
ReWhiteSpace *regexp.Regexp
|
||||||
|
ReFieldWhiteList *regexp.Regexp
|
||||||
|
ReUserName *regexp.Regexp
|
||||||
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
rePhone, _ = regexp.Compile(`(\d{3})\d*(\d{4})`)
|
rePhone, _ = regexp.Compile(`(\d{3})\d*(\d{4})`)
|
||||||
|
ReWhiteSpace, _ = regexp.Compile(`\s`)
|
||||||
|
ReFieldWhiteList, _ = regexp.Compile(`^[A-Za-z0-9]+$`)
|
||||||
|
ReUserName, _ = regexp.Compile("^[a-zA-Z0-9]+((?:-[a-zA-Z0-9]+)|(?:_[a-zA-Z0-9]+))*$")
|
||||||
}
|
}
|
||||||
|
|
||||||
func IsEmailValid(email string) bool {
|
func IsEmailValid(email string) bool {
|
||||||
@ -70,3 +78,7 @@ func GetCountryCode(prefix string, phone string) (string, error) {
|
|||||||
|
|
||||||
return countryCode, nil
|
return countryCode, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func FilterField(field string) bool {
|
||||||
|
return ReFieldWhiteList.MatchString(field)
|
||||||
|
}
|
||||||
|
@ -24,8 +24,6 @@
|
|||||||
"i18next": "^19.8.9",
|
"i18next": "^19.8.9",
|
||||||
"libphonenumber-js": "^1.10.19",
|
"libphonenumber-js": "^1.10.19",
|
||||||
"moment": "^2.29.1",
|
"moment": "^2.29.1",
|
||||||
"qrcode.react": "^3.1.0",
|
|
||||||
"qs": "^6.10.2",
|
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-app-polyfill": "^3.0.0",
|
"react-app-polyfill": "^3.0.0",
|
||||||
"react-codemirror2": "^7.2.1",
|
"react-codemirror2": "^7.2.1",
|
||||||
|
@ -76,6 +76,10 @@ class AdapterEditPage extends React.Component {
|
|||||||
getModels(organizationName) {
|
getModels(organizationName) {
|
||||||
ModelBackend.getModels(organizationName)
|
ModelBackend.getModels(organizationName)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
|
if (res.status === "error") {
|
||||||
|
Setting.showMessage("error", res.msg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
this.setState({
|
this.setState({
|
||||||
models: res,
|
models: res,
|
||||||
});
|
});
|
||||||
|
@ -118,20 +118,30 @@ class ApplicationEditPage extends React.Component {
|
|||||||
|
|
||||||
getApplication() {
|
getApplication() {
|
||||||
ApplicationBackend.getApplication("admin", this.state.applicationName)
|
ApplicationBackend.getApplication("admin", this.state.applicationName)
|
||||||
.then((application) => {
|
.then((res) => {
|
||||||
if (application === null) {
|
if (res === null) {
|
||||||
this.props.history.push("/404");
|
this.props.history.push("/404");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (application.grantTypes === null || application.grantTypes === undefined || application.grantTypes.length === 0) {
|
if (res.status === "error") {
|
||||||
application.grantTypes = ["authorization_code"];
|
Setting.showMessage("error", res.msg);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (res.grantTypes === null || res.grantTypes === undefined || res.grantTypes.length === 0) {
|
||||||
|
res.grantTypes = ["authorization_code"];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (res.tags === null || res.tags === undefined) {
|
||||||
|
res.tags = [];
|
||||||
|
}
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
application: application,
|
application: res,
|
||||||
});
|
});
|
||||||
|
|
||||||
this.getCerts(application.organization);
|
this.getCerts(res.organization);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -307,6 +317,18 @@ class ApplicationEditPage extends React.Component {
|
|||||||
</Select>
|
</Select>
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
|
<Row style={{marginTop: "20px"}} >
|
||||||
|
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||||
|
{Setting.getLabel(i18next.t("organization:Tags"), i18next.t("application:Tags - Tooltip"))} :
|
||||||
|
</Col>
|
||||||
|
<Col span={22} >
|
||||||
|
<Select virtual={false} mode="tags" style={{width: "100%"}} value={this.state.application.tags} onChange={(value => {this.updateApplicationField("tags", value);})}>
|
||||||
|
{
|
||||||
|
this.state.application.tags?.map((item, index) => <Option key={index} value={item}>{item}</Option>)
|
||||||
|
}
|
||||||
|
</Select>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
<Row style={{marginTop: "20px"}} >
|
<Row style={{marginTop: "20px"}} >
|
||||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||||
{Setting.getLabel(i18next.t("provider:Client ID"), i18next.t("provider:Client ID - Tooltip"))} :
|
{Setting.getLabel(i18next.t("provider:Client ID"), i18next.t("provider:Client ID - Tooltip"))} :
|
||||||
|
@ -44,14 +44,19 @@ class CertEditPage extends React.Component {
|
|||||||
|
|
||||||
getCert() {
|
getCert() {
|
||||||
CertBackend.getCert(this.state.owner, this.state.certName)
|
CertBackend.getCert(this.state.owner, this.state.certName)
|
||||||
.then((cert) => {
|
.then((res) => {
|
||||||
if (cert === null) {
|
if (res === null) {
|
||||||
this.props.history.push("/404");
|
this.props.history.push("/404");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (res.status === "error") {
|
||||||
|
Setting.showMessage("error", res.msg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
cert: cert,
|
cert: res,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -40,17 +40,21 @@ class ChatEditPage extends React.Component {
|
|||||||
|
|
||||||
getChat() {
|
getChat() {
|
||||||
ChatBackend.getChat("admin", this.state.chatName)
|
ChatBackend.getChat("admin", this.state.chatName)
|
||||||
.then((chat) => {
|
.then((res) => {
|
||||||
if (chat === null) {
|
if (res === null) {
|
||||||
this.props.history.push("/404");
|
this.props.history.push("/404");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (res.status === "error") {
|
||||||
|
Setting.showMessage("error", res.msg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
this.setState({
|
this.setState({
|
||||||
chat: chat,
|
chat: res,
|
||||||
});
|
});
|
||||||
|
|
||||||
this.getUsers(chat.organization);
|
this.getUsers(res.organization);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -66,6 +70,11 @@ class ChatEditPage extends React.Component {
|
|||||||
getUsers(organizationName) {
|
getUsers(organizationName) {
|
||||||
UserBackend.getUsers(organizationName)
|
UserBackend.getUsers(organizationName)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
|
if (res.status === "error") {
|
||||||
|
Setting.showMessage("error", res.msg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
users: res,
|
users: res,
|
||||||
});
|
});
|
||||||
|
@ -74,8 +74,12 @@ class EntryPage extends React.Component {
|
|||||||
});
|
});
|
||||||
|
|
||||||
ApplicationBackend.getApplication("admin", pricing.application)
|
ApplicationBackend.getApplication("admin", pricing.application)
|
||||||
.then((application) => {
|
.then((res) => {
|
||||||
const themeData = application !== null ? Setting.getThemeData(application.organizationObj, application) : Conf.ThemeDefault;
|
if (res.status === "error") {
|
||||||
|
Setting.showMessage("error", res.msg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const themeData = res !== null ? Setting.getThemeData(res.organizationObj, res) : Conf.ThemeDefault;
|
||||||
this.props.updataThemeData(themeData);
|
this.props.updataThemeData(themeData);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -45,17 +45,20 @@ class MessageEditPage extends React.Component {
|
|||||||
|
|
||||||
getMessage() {
|
getMessage() {
|
||||||
MessageBackend.getMessage("admin", this.state.messageName)
|
MessageBackend.getMessage("admin", this.state.messageName)
|
||||||
.then((message) => {
|
.then((res) => {
|
||||||
if (message === null) {
|
if (res === null) {
|
||||||
this.props.history.push("/404");
|
this.props.history.push("/404");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (res.status === "error") {
|
||||||
|
Setting.showMessage("error", res.msg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
this.setState({
|
this.setState({
|
||||||
message: message,
|
message: res,
|
||||||
});
|
});
|
||||||
|
|
||||||
this.getUsers(message.organization);
|
this.getUsers(res.organization);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -80,6 +83,10 @@ class MessageEditPage extends React.Component {
|
|||||||
getUsers(organizationName) {
|
getUsers(organizationName) {
|
||||||
UserBackend.getUsers(organizationName)
|
UserBackend.getUsers(organizationName)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
|
if (res.status === "error") {
|
||||||
|
Setting.showMessage("error", res.msg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
this.setState({
|
this.setState({
|
||||||
users: res,
|
users: res,
|
||||||
});
|
});
|
||||||
|
@ -47,14 +47,19 @@ class ModelEditPage extends React.Component {
|
|||||||
|
|
||||||
getModel() {
|
getModel() {
|
||||||
ModelBackend.getModel(this.state.organizationName, this.state.modelName)
|
ModelBackend.getModel(this.state.organizationName, this.state.modelName)
|
||||||
.then((model) => {
|
.then((res) => {
|
||||||
if (model === null) {
|
if (res === null) {
|
||||||
this.props.history.push("/404");
|
this.props.history.push("/404");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (res.status === "error") {
|
||||||
|
Setting.showMessage("error", res.msg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
model: model,
|
model: res,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -68,9 +68,14 @@ class OrganizationEditPage extends React.Component {
|
|||||||
|
|
||||||
getApplications() {
|
getApplications() {
|
||||||
ApplicationBackend.getApplicationsByOrganization("admin", this.state.organizationName)
|
ApplicationBackend.getApplicationsByOrganization("admin", this.state.organizationName)
|
||||||
.then((applications) => {
|
.then((res) => {
|
||||||
|
if (res.status === "error") {
|
||||||
|
Setting.showMessage("error", res.msg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
applications: applications,
|
applications: res,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -49,21 +49,26 @@ class PermissionEditPage extends React.Component {
|
|||||||
|
|
||||||
getPermission() {
|
getPermission() {
|
||||||
PermissionBackend.getPermission(this.state.organizationName, this.state.permissionName)
|
PermissionBackend.getPermission(this.state.organizationName, this.state.permissionName)
|
||||||
.then((permission) => {
|
.then((res) => {
|
||||||
if (permission === null) {
|
if (res === null) {
|
||||||
this.props.history.push("/404");
|
this.props.history.push("/404");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (res.status === "error") {
|
||||||
|
Setting.showMessage("error", res.msg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
permission: permission,
|
permission: res,
|
||||||
});
|
});
|
||||||
|
|
||||||
this.getUsers(permission.owner);
|
this.getUsers(res.owner);
|
||||||
this.getRoles(permission.owner);
|
this.getRoles(res.owner);
|
||||||
this.getModels(permission.owner);
|
this.getModels(res.owner);
|
||||||
this.getResources(permission.owner);
|
this.getResources(res.owner);
|
||||||
this.getModel(permission.owner, permission.model);
|
this.getModel(res.owner, res.model);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -79,6 +84,10 @@ class PermissionEditPage extends React.Component {
|
|||||||
getUsers(organizationName) {
|
getUsers(organizationName) {
|
||||||
UserBackend.getUsers(organizationName)
|
UserBackend.getUsers(organizationName)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
|
if (res.status === "error") {
|
||||||
|
Setting.showMessage("error", res.msg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
this.setState({
|
this.setState({
|
||||||
users: res,
|
users: res,
|
||||||
});
|
});
|
||||||
@ -88,6 +97,10 @@ class PermissionEditPage extends React.Component {
|
|||||||
getRoles(organizationName) {
|
getRoles(organizationName) {
|
||||||
RoleBackend.getRoles(organizationName)
|
RoleBackend.getRoles(organizationName)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
|
if (res.status === "error") {
|
||||||
|
Setting.showMessage("error", res.msg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
this.setState({
|
this.setState({
|
||||||
roles: res,
|
roles: res,
|
||||||
});
|
});
|
||||||
@ -97,6 +110,10 @@ class PermissionEditPage extends React.Component {
|
|||||||
getModels(organizationName) {
|
getModels(organizationName) {
|
||||||
ModelBackend.getModels(organizationName)
|
ModelBackend.getModels(organizationName)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
|
if (res.status === "error") {
|
||||||
|
Setting.showMessage("error", res.msg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
this.setState({
|
this.setState({
|
||||||
models: res,
|
models: res,
|
||||||
});
|
});
|
||||||
@ -106,6 +123,10 @@ class PermissionEditPage extends React.Component {
|
|||||||
getModel(organizationName, modelName) {
|
getModel(organizationName, modelName) {
|
||||||
ModelBackend.getModel(organizationName, modelName)
|
ModelBackend.getModel(organizationName, modelName)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
|
if (res.status === "error") {
|
||||||
|
Setting.showMessage("error", res.msg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
this.setState({
|
this.setState({
|
||||||
model: res,
|
model: res,
|
||||||
});
|
});
|
||||||
|
@ -64,6 +64,10 @@ class PlanEditPage extends React.Component {
|
|||||||
getRoles(organizationName) {
|
getRoles(organizationName) {
|
||||||
RoleBackend.getRoles(organizationName)
|
RoleBackend.getRoles(organizationName)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
|
if (res.status === "error") {
|
||||||
|
Setting.showMessage("error", res.msg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
this.setState({
|
this.setState({
|
||||||
roles: res,
|
roles: res,
|
||||||
});
|
});
|
||||||
@ -73,6 +77,10 @@ class PlanEditPage extends React.Component {
|
|||||||
getUsers(organizationName) {
|
getUsers(organizationName) {
|
||||||
UserBackend.getUsers(organizationName)
|
UserBackend.getUsers(organizationName)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
|
if (res.status === "error") {
|
||||||
|
Setting.showMessage("error", res.msg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
this.setState({
|
this.setState({
|
||||||
users: res,
|
users: res,
|
||||||
});
|
});
|
||||||
|
@ -49,22 +49,31 @@ class PricingEditPage extends React.Component {
|
|||||||
|
|
||||||
getPricing() {
|
getPricing() {
|
||||||
PricingBackend.getPricing(this.state.organizationName, this.state.pricingName)
|
PricingBackend.getPricing(this.state.organizationName, this.state.pricingName)
|
||||||
.then((pricing) => {
|
.then((res) => {
|
||||||
if (pricing === null) {
|
if (res === null) {
|
||||||
this.props.history.push("/404");
|
this.props.history.push("/404");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (res.status === "error") {
|
||||||
|
Setting.showMessage("error", res.msg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
pricing: pricing,
|
pricing: res,
|
||||||
});
|
});
|
||||||
this.getPlans(pricing.owner);
|
this.getPlans(res.owner);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
getPlans(organizationName) {
|
getPlans(organizationName) {
|
||||||
PlanBackend.getPlans(organizationName)
|
PlanBackend.getPlans(organizationName)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
|
if (res.status === "error") {
|
||||||
|
Setting.showMessage("error", res.msg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
this.setState({
|
this.setState({
|
||||||
plans: res,
|
plans: res,
|
||||||
});
|
});
|
||||||
@ -109,9 +118,13 @@ class PricingEditPage extends React.Component {
|
|||||||
|
|
||||||
getUserApplication() {
|
getUserApplication() {
|
||||||
ApplicationBackend.getUserApplication(this.state.organizationName, this.state.userName)
|
ApplicationBackend.getUserApplication(this.state.organizationName, this.state.userName)
|
||||||
.then((application) => {
|
.then((res) => {
|
||||||
|
if (res.status === "error") {
|
||||||
|
Setting.showMessage("error", res.msg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
this.setState({
|
this.setState({
|
||||||
application: application,
|
application: res,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -41,9 +41,14 @@ class ProductBuyPage extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ProductBackend.getProduct(this.props.account.owner, this.state.productName)
|
ProductBackend.getProduct(this.props.account.owner, this.state.productName)
|
||||||
.then((product) => {
|
.then((res) => {
|
||||||
|
if (res.status === "error") {
|
||||||
|
Setting.showMessage("error", res.msg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
product: product,
|
product: res,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -42,18 +42,22 @@ class RoleEditPage extends React.Component {
|
|||||||
|
|
||||||
getRole() {
|
getRole() {
|
||||||
RoleBackend.getRole(this.state.organizationName, this.state.roleName)
|
RoleBackend.getRole(this.state.organizationName, this.state.roleName)
|
||||||
.then((role) => {
|
.then((res) => {
|
||||||
if (role === null) {
|
if (res === null) {
|
||||||
this.props.history.push("/404");
|
this.props.history.push("/404");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (res.status === "error") {
|
||||||
|
Setting.showMessage("error", res.msg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
role: role,
|
role: res,
|
||||||
});
|
});
|
||||||
|
|
||||||
this.getUsers(role.owner);
|
this.getUsers(res.owner);
|
||||||
this.getRoles(role.owner);
|
this.getRoles(res.owner);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -69,6 +73,10 @@ class RoleEditPage extends React.Component {
|
|||||||
getUsers(organizationName) {
|
getUsers(organizationName) {
|
||||||
UserBackend.getUsers(organizationName)
|
UserBackend.getUsers(organizationName)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
|
if (res.status === "error") {
|
||||||
|
Setting.showMessage("error", res.msg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
this.setState({
|
this.setState({
|
||||||
users: res,
|
users: res,
|
||||||
});
|
});
|
||||||
@ -78,6 +86,10 @@ class RoleEditPage extends React.Component {
|
|||||||
getRoles(organizationName) {
|
getRoles(organizationName) {
|
||||||
RoleBackend.getRoles(organizationName)
|
RoleBackend.getRoles(organizationName)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
|
if (res.status === "error") {
|
||||||
|
Setting.showMessage("error", res.msg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
this.setState({
|
this.setState({
|
||||||
roles: res,
|
roles: res,
|
||||||
});
|
});
|
||||||
|
@ -46,18 +46,23 @@ class SubscriptionEditPage extends React.Component {
|
|||||||
|
|
||||||
getSubscription() {
|
getSubscription() {
|
||||||
SubscriptionBackend.getSubscription(this.state.organizationName, this.state.subscriptionName)
|
SubscriptionBackend.getSubscription(this.state.organizationName, this.state.subscriptionName)
|
||||||
.then((subscription) => {
|
.then((res) => {
|
||||||
if (subscription === null) {
|
if (res === null) {
|
||||||
this.props.history.push("/404");
|
this.props.history.push("/404");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (res.status === "error") {
|
||||||
|
Setting.showMessage("error", res.msg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
subscription: subscription,
|
subscription: res,
|
||||||
});
|
});
|
||||||
|
|
||||||
this.getUsers(subscription.owner);
|
this.getUsers(res.owner);
|
||||||
this.getPlanes(subscription.owner);
|
this.getPlanes(res.owner);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -73,6 +78,10 @@ class SubscriptionEditPage extends React.Component {
|
|||||||
getUsers(organizationName) {
|
getUsers(organizationName) {
|
||||||
UserBackend.getUsers(organizationName)
|
UserBackend.getUsers(organizationName)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
|
if (res.status === "error") {
|
||||||
|
Setting.showMessage("error", res.msg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
this.setState({
|
this.setState({
|
||||||
users: res,
|
users: res,
|
||||||
});
|
});
|
||||||
|
@ -47,14 +47,19 @@ class SyncerEditPage extends React.Component {
|
|||||||
|
|
||||||
getSyncer() {
|
getSyncer() {
|
||||||
SyncerBackend.getSyncer("admin", this.state.syncerName)
|
SyncerBackend.getSyncer("admin", this.state.syncerName)
|
||||||
.then((syncer) => {
|
.then((res) => {
|
||||||
if (syncer === null) {
|
if (res === null) {
|
||||||
this.props.history.push("/404");
|
this.props.history.push("/404");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (res.status === "error") {
|
||||||
|
Setting.showMessage("error", res.msg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
syncer: syncer,
|
syncer: res,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -35,14 +35,19 @@ class TokenEditPage extends React.Component {
|
|||||||
|
|
||||||
getToken() {
|
getToken() {
|
||||||
TokenBackend.getToken("admin", this.state.tokenName)
|
TokenBackend.getToken("admin", this.state.tokenName)
|
||||||
.then((token) => {
|
.then((res) => {
|
||||||
if (token === null) {
|
if (res === null) {
|
||||||
this.props.history.push("/404");
|
this.props.history.push("/404");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (res.status === "error") {
|
||||||
|
Setting.showMessage("error", res.msg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
token: token,
|
token: res,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -121,13 +121,17 @@ class UserEditPage extends React.Component {
|
|||||||
|
|
||||||
getUserApplication() {
|
getUserApplication() {
|
||||||
ApplicationBackend.getUserApplication(this.state.organizationName, this.state.userName)
|
ApplicationBackend.getUserApplication(this.state.organizationName, this.state.userName)
|
||||||
.then((application) => {
|
.then((res) => {
|
||||||
|
if (res.status === "error") {
|
||||||
|
Setting.showMessage("error", res.msg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
this.setState({
|
this.setState({
|
||||||
application: application,
|
application: res,
|
||||||
});
|
});
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
isGroupsVisible: application.organizationObj.accountItems?.some((item) => item.name === "Groups" && item.visible),
|
isGroupsVisible: res.organizationObj.accountItems?.some((item) => item.name === "Groups" && item.visible),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -63,8 +63,12 @@ class ForgetPage extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ApplicationBackend.getApplication("admin", this.state.applicationName)
|
ApplicationBackend.getApplication("admin", this.state.applicationName)
|
||||||
.then((application) => {
|
.then((res) => {
|
||||||
this.onUpdateApplication(application);
|
if (res.status === "error") {
|
||||||
|
Setting.showMessage("error", res.msg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.onUpdateApplication(res);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
getApplicationObj() {
|
getApplicationObj() {
|
||||||
|
@ -49,7 +49,6 @@ class LoginPage extends React.Component {
|
|||||||
username: null,
|
username: null,
|
||||||
validEmailOrPhone: false,
|
validEmailOrPhone: false,
|
||||||
validEmail: false,
|
validEmail: false,
|
||||||
loginMethod: "password",
|
|
||||||
enableCaptchaModal: CaptchaRule.Never,
|
enableCaptchaModal: CaptchaRule.Never,
|
||||||
openCaptchaModal: false,
|
openCaptchaModal: false,
|
||||||
verifyCaptcha: undefined,
|
verifyCaptcha: undefined,
|
||||||
@ -83,6 +82,8 @@ class LoginPage extends React.Component {
|
|||||||
|
|
||||||
componentDidUpdate(prevProps, prevState, snapshot) {
|
componentDidUpdate(prevProps, prevState, snapshot) {
|
||||||
if (prevProps.application !== this.props.application) {
|
if (prevProps.application !== this.props.application) {
|
||||||
|
this.setState({loginMethod: this.getDefaultLoginMethod(this.props.application)});
|
||||||
|
|
||||||
const captchaProviderItems = this.getCaptchaProviderItems(this.props.application);
|
const captchaProviderItems = this.getCaptchaProviderItems(this.props.application);
|
||||||
if (captchaProviderItems) {
|
if (captchaProviderItems) {
|
||||||
if (captchaProviderItems.some(providerItem => providerItem.rule === "Always")) {
|
if (captchaProviderItems.some(providerItem => providerItem.rule === "Always")) {
|
||||||
@ -159,8 +160,12 @@ class LoginPage extends React.Component {
|
|||||||
|
|
||||||
if (this.state.owner === null || this.state.type === "saml") {
|
if (this.state.owner === null || this.state.type === "saml") {
|
||||||
ApplicationBackend.getApplication("admin", this.state.applicationName)
|
ApplicationBackend.getApplication("admin", this.state.applicationName)
|
||||||
.then((application) => {
|
.then((res) => {
|
||||||
this.onUpdateApplication(application);
|
if (res.status === "error") {
|
||||||
|
Setting.showMessage("error", res.msg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.onUpdateApplication(res);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
OrganizationBackend.getDefaultApplication("admin", this.state.owner)
|
OrganizationBackend.getDefaultApplication("admin", this.state.owner)
|
||||||
@ -183,6 +188,20 @@ class LoginPage extends React.Component {
|
|||||||
return this.props.application;
|
return this.props.application;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getDefaultLoginMethod(application) {
|
||||||
|
if (application.enablePassword) {
|
||||||
|
return "password";
|
||||||
|
}
|
||||||
|
if (application.enableCodeSignin) {
|
||||||
|
return "verificationCode";
|
||||||
|
}
|
||||||
|
if (application.enableWebAuthn) {
|
||||||
|
return "webAuthn";
|
||||||
|
}
|
||||||
|
|
||||||
|
return "password";
|
||||||
|
}
|
||||||
|
|
||||||
onUpdateAccount(account) {
|
onUpdateAccount(account) {
|
||||||
this.props.onUpdateAccount(account);
|
this.props.onUpdateAccount(account);
|
||||||
}
|
}
|
||||||
@ -426,7 +445,8 @@ class LoginPage extends React.Component {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (application.enablePassword) {
|
const showForm = application.enablePassword || application.enableCodeSignin || application.enableWebAuthn;
|
||||||
|
if (showForm) {
|
||||||
let loginWidth = 320;
|
let loginWidth = 320;
|
||||||
if (Setting.getLanguage() === "fr") {
|
if (Setting.getLanguage() === "fr") {
|
||||||
loginWidth += 20;
|
loginWidth += 20;
|
||||||
@ -511,7 +531,6 @@ class LoginPage extends React.Component {
|
|||||||
id="input"
|
id="input"
|
||||||
prefix={<UserOutlined className="site-form-item-icon" />}
|
prefix={<UserOutlined className="site-form-item-icon" />}
|
||||||
placeholder={(this.state.loginMethod === "verificationCode") ? i18next.t("login:Email or phone") : i18next.t("login:username, Email or phone")}
|
placeholder={(this.state.loginMethod === "verificationCode") ? i18next.t("login:Email or phone") : i18next.t("login:username, Email or phone")}
|
||||||
disabled={!application.enablePassword}
|
|
||||||
onChange={e => {
|
onChange={e => {
|
||||||
this.setState({
|
this.setState({
|
||||||
username: e.target.value,
|
username: e.target.value,
|
||||||
@ -526,7 +545,7 @@ class LoginPage extends React.Component {
|
|||||||
</Row>
|
</Row>
|
||||||
<div style={{display: "inline-flex", justifyContent: "space-between", width: "320px", marginBottom: AgreementModal.isAgreementRequired(application) ? "5px" : "25px"}}>
|
<div style={{display: "inline-flex", justifyContent: "space-between", width: "320px", marginBottom: AgreementModal.isAgreementRequired(application) ? "5px" : "25px"}}>
|
||||||
<Form.Item name="autoSignin" valuePropName="checked" noStyle>
|
<Form.Item name="autoSignin" valuePropName="checked" noStyle>
|
||||||
<Checkbox style={{float: "left"}} disabled={!application.enablePassword}>
|
<Checkbox style={{float: "left"}}>
|
||||||
{i18next.t("login:Auto sign in")}
|
{i18next.t("login:Auto sign in")}
|
||||||
</Checkbox>
|
</Checkbox>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
@ -540,7 +559,6 @@ class LoginPage extends React.Component {
|
|||||||
type="primary"
|
type="primary"
|
||||||
htmlType="submit"
|
htmlType="submit"
|
||||||
style={{width: "100%", marginBottom: "5px"}}
|
style={{width: "100%", marginBottom: "5px"}}
|
||||||
disabled={!application.enablePassword}
|
|
||||||
>
|
>
|
||||||
{
|
{
|
||||||
this.state.loginMethod === "webAuthn" ? i18next.t("login:Sign in with WebAuthn") :
|
this.state.loginMethod === "webAuthn" ? i18next.t("login:Sign in with WebAuthn") :
|
||||||
@ -801,14 +819,14 @@ class LoginPage extends React.Component {
|
|||||||
renderMethodChoiceBox() {
|
renderMethodChoiceBox() {
|
||||||
const application = this.getApplicationObj();
|
const application = this.getApplicationObj();
|
||||||
const items = [];
|
const items = [];
|
||||||
items.push({label: i18next.t("general:Password"), key: "password"});
|
application.enablePassword ? items.push({label: i18next.t("general:Password"), key: "password"}) : null;
|
||||||
application.enableCodeSignin ? items.push({label: i18next.t("login:Verification code"), key: "verificationCode"}) : null;
|
application.enableCodeSignin ? items.push({label: i18next.t("login:Verification code"), key: "verificationCode"}) : null;
|
||||||
application.enableWebAuthn ? items.push({label: i18next.t("login:WebAuthn"), key: "webAuthn"}) : null;
|
application.enableWebAuthn ? items.push({label: i18next.t("login:WebAuthn"), key: "webAuthn"}) : null;
|
||||||
|
|
||||||
if (application.enableCodeSignin || application.enableWebAuthn) {
|
if (items.length > 1) {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Tabs items={items} size={"small"} defaultActiveKey="password" onChange={(key) => {
|
<Tabs items={items} size={"small"} defaultActiveKey={this.getDefaultLoginMethod(application)} onChange={(key) => {
|
||||||
this.setState({loginMethod: key});
|
this.setState({loginMethod: key});
|
||||||
}} centered>
|
}} centered>
|
||||||
</Tabs>
|
</Tabs>
|
||||||
@ -933,7 +951,7 @@ class LoginPage extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const visibleOAuthProviderItems = (application.providers === null) ? [] : application.providers.filter(providerItem => this.isProviderVisible(providerItem));
|
const visibleOAuthProviderItems = (application.providers === null) ? [] : application.providers.filter(providerItem => this.isProviderVisible(providerItem));
|
||||||
if (this.props.preview !== "auto" && !application.enablePassword && visibleOAuthProviderItems.length === 1) {
|
if (this.props.preview !== "auto" && !application.enablePassword && !application.enableCodeSignin && !application.enableWebAuthn && visibleOAuthProviderItems.length === 1) {
|
||||||
Setting.goToLink(Provider.getAuthUrl(application, visibleOAuthProviderItems[0].provider, "signup"));
|
Setting.goToLink(Provider.getAuthUrl(application, visibleOAuthProviderItems[0].provider, "signup"));
|
||||||
return (
|
return (
|
||||||
<div style={{display: "flex", justifyContent: "center", alignItems: "center", width: "100%"}}>
|
<div style={{display: "flex", justifyContent: "center", alignItems: "center", width: "100%"}}>
|
||||||
|
@ -16,8 +16,8 @@ import React, {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";
|
||||||
import {EmailMfaType, SmsMfaType} from "./MfaSetupPage";
|
import {EmailMfaType, RecoveryMfaType, SmsMfaType} from "./MfaSetupPage";
|
||||||
import {MfaSmsVerifyForm, mfaAuth} from "./MfaVerifyForm";
|
import {MfaSmsVerifyForm, MfaTotpVerifyForm, mfaAuth} from "./MfaVerifyForm";
|
||||||
|
|
||||||
export const NextMfa = "NextMfa";
|
export const NextMfa = "NextMfa";
|
||||||
export const RequiredMfa = "RequiredMfa";
|
export const RequiredMfa = "RequiredMfa";
|
||||||
@ -60,7 +60,7 @@ export function MfaAuthVerifyForm({formValues, oAuthParams, mfaProps, applicatio
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
if (mfaType === SmsMfaType || mfaType === EmailMfaType) {
|
if (mfaType !== RecoveryMfaType) {
|
||||||
return (
|
return (
|
||||||
<div style={{width: 300, height: 350}}>
|
<div style={{width: 300, height: 350}}>
|
||||||
<div style={{marginBottom: 24, textAlign: "center", fontSize: "24px"}}>
|
<div style={{marginBottom: 24, textAlign: "center", fontSize: "24px"}}>
|
||||||
@ -69,12 +69,18 @@ export function MfaAuthVerifyForm({formValues, oAuthParams, mfaProps, applicatio
|
|||||||
<div style={{marginBottom: 24}}>
|
<div style={{marginBottom: 24}}>
|
||||||
{i18next.t("mfa:Multi-factor authentication description")}
|
{i18next.t("mfa:Multi-factor authentication description")}
|
||||||
</div>
|
</div>
|
||||||
<MfaSmsVerifyForm
|
{mfaType === SmsMfaType || mfaType === EmailMfaType ? (
|
||||||
mfaProps={mfaProps}
|
<MfaSmsVerifyForm
|
||||||
method={mfaAuth}
|
mfaProps={mfaProps}
|
||||||
onFinish={verify}
|
method={mfaAuth}
|
||||||
application={application}
|
onFinish={verify}
|
||||||
/>
|
application={application}
|
||||||
|
/>) : (
|
||||||
|
<MfaTotpVerifyForm
|
||||||
|
mfaProps={mfaProps}
|
||||||
|
onFinish={verify}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
<span style={{float: "right"}}>
|
<span style={{float: "right"}}>
|
||||||
{i18next.t("mfa:Have problems?")}
|
{i18next.t("mfa:Have problems?")}
|
||||||
<a onClick={() => {
|
<a onClick={() => {
|
||||||
@ -85,7 +91,7 @@ export function MfaAuthVerifyForm({formValues, oAuthParams, mfaProps, applicatio
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
} else if (mfaType === "recovery") {
|
} else {
|
||||||
return (
|
return (
|
||||||
<div style={{width: 300, height: 350}}>
|
<div style={{width: 300, height: 350}}>
|
||||||
<div style={{marginBottom: 24, textAlign: "center", fontSize: "24px"}}>
|
<div style={{marginBottom: 24, textAlign: "center", fontSize: "24px"}}>
|
||||||
|
@ -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, {useEffect, useState} from "react";
|
import React, {useState} from "react";
|
||||||
import {Button, Col, Form, Input, Result, Row, Steps} from "antd";
|
import {Button, Col, Form, Input, Result, Row, Steps} from "antd";
|
||||||
import * as ApplicationBackend from "../backend/ApplicationBackend";
|
import * as ApplicationBackend from "../backend/ApplicationBackend";
|
||||||
import * as Setting from "../Setting";
|
import * as Setting from "../Setting";
|
||||||
@ -26,6 +26,7 @@ import {MfaSmsVerifyForm, MfaTotpVerifyForm, mfaSetup} from "./MfaVerifyForm";
|
|||||||
export const EmailMfaType = "email";
|
export const EmailMfaType = "email";
|
||||||
export const SmsMfaType = "sms";
|
export const SmsMfaType = "sms";
|
||||||
export const TotpMfaType = "app";
|
export const TotpMfaType = "app";
|
||||||
|
export const RecoveryMfaType = "recovery";
|
||||||
|
|
||||||
function CheckPasswordForm({user, onSuccess, onFail}) {
|
function CheckPasswordForm({user, onSuccess, onFail}) {
|
||||||
const [form] = Form.useForm();
|
const [form] = Form.useForm();
|
||||||
@ -76,29 +77,11 @@ function CheckPasswordForm({user, onSuccess, onFail}) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function MfaVerifyForm({mfaType, application, user, onSuccess, onFail}) {
|
export function MfaVerifyForm({mfaProps, application, user, onSuccess, onFail}) {
|
||||||
const [form] = Form.useForm();
|
const [form] = Form.useForm();
|
||||||
const [mfaProps, setMfaProps] = useState({mfaType: mfaType});
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (mfaType === SmsMfaType) {
|
|
||||||
setMfaProps({
|
|
||||||
mfaType: mfaType,
|
|
||||||
secret: user.phone,
|
|
||||||
countryCode: user.countryCode,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mfaType === EmailMfaType) {
|
|
||||||
setMfaProps({
|
|
||||||
mfaType: mfaType,
|
|
||||||
secret: user.email,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}, [mfaType]);
|
|
||||||
|
|
||||||
const onFinish = ({passcode}) => {
|
const onFinish = ({passcode}) => {
|
||||||
const data = {passcode, mfaType: mfaType, ...user};
|
const data = {passcode, mfaType: mfaProps.mfaType, ...user};
|
||||||
MfaBackend.MfaSetupVerify(data)
|
MfaBackend.MfaSetupVerify(data)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
if (res.status === "ok") {
|
if (res.status === "ok") {
|
||||||
@ -115,14 +98,14 @@ export function MfaVerifyForm({mfaType, application, user, onSuccess, onFail}) {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
if (mfaType === null || mfaType === undefined || mfaProps.secret === undefined) {
|
if (mfaProps === undefined || mfaProps === null) {
|
||||||
return <div></div>;
|
return <div></div>;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mfaType === SmsMfaType || mfaType === EmailMfaType) {
|
if (mfaProps.mfaType === SmsMfaType || mfaProps.mfaType === EmailMfaType) {
|
||||||
return <MfaSmsVerifyForm onFinish={onFinish} application={application} method={mfaSetup} mfaProps={mfaProps} />;
|
return <MfaSmsVerifyForm mfaProps={mfaProps} onFinish={onFinish} application={application} method={mfaSetup} user={user} />;
|
||||||
} else if (mfaType === TotpMfaType) {
|
} else if (mfaProps.mfaType === TotpMfaType) {
|
||||||
return <MfaTotpVerifyForm onFinish={onFinish} />;
|
return <MfaTotpVerifyForm mfaProps={mfaProps} onFinish={onFinish} />;
|
||||||
} else {
|
} else {
|
||||||
return <div></div>;
|
return <div></div>;
|
||||||
}
|
}
|
||||||
@ -183,7 +166,7 @@ class MfaSetupPage extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
componentDidUpdate(prevProps, prevState, snapshot) {
|
componentDidUpdate(prevProps, prevState, snapshot) {
|
||||||
if (this.state.isAuthenticated === true && this.state.mfaProps === null) {
|
if (this.state.isAuthenticated === true && (this.state.mfaProps === null || this.state.mfaType !== prevState.mfaType)) {
|
||||||
MfaBackend.MfaSetupInitiate({
|
MfaBackend.MfaSetupInitiate({
|
||||||
mfaType: this.state.mfaType,
|
mfaType: this.state.mfaType,
|
||||||
...this.getUser(),
|
...this.getUser(),
|
||||||
@ -205,10 +188,14 @@ class MfaSetupPage extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ApplicationBackend.getApplication("admin", this.state.applicationName)
|
ApplicationBackend.getApplication("admin", this.state.applicationName)
|
||||||
.then((application) => {
|
.then((res) => {
|
||||||
if (application !== null) {
|
if (res !== null) {
|
||||||
|
if (res.status === "error") {
|
||||||
|
Setting.showMessage("error", res.msg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
this.setState({
|
this.setState({
|
||||||
application: application,
|
application: res,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
Setting.showMessage("error", i18next.t("mfa:Failed to get application"));
|
Setting.showMessage("error", i18next.t("mfa:Failed to get application"));
|
||||||
@ -226,18 +213,20 @@ class MfaSetupPage extends React.Component {
|
|||||||
renderStep() {
|
renderStep() {
|
||||||
switch (this.state.current) {
|
switch (this.state.current) {
|
||||||
case 0:
|
case 0:
|
||||||
return <CheckPasswordForm
|
return (
|
||||||
user={this.getUser()}
|
<CheckPasswordForm
|
||||||
onSuccess={() => {
|
user={this.getUser()}
|
||||||
this.setState({
|
onSuccess={() => {
|
||||||
current: this.state.current + 1,
|
this.setState({
|
||||||
isAuthenticated: true,
|
current: this.state.current + 1,
|
||||||
});
|
isAuthenticated: true,
|
||||||
}}
|
});
|
||||||
onFail={(res) => {
|
}}
|
||||||
Setting.showMessage("error", i18next.t("mfa:Failed to initiate MFA"));
|
onFail={(res) => {
|
||||||
}}
|
Setting.showMessage("error", i18next.t("mfa:Failed to initiate MFA"));
|
||||||
/>;
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
case 1:
|
case 1:
|
||||||
if (!this.state.isAuthenticated) {
|
if (!this.state.isAuthenticated) {
|
||||||
return null;
|
return null;
|
||||||
@ -246,7 +235,7 @@ class MfaSetupPage extends React.Component {
|
|||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<MfaVerifyForm
|
<MfaVerifyForm
|
||||||
mfaType={this.state.mfaType}
|
mfaProps={this.state.mfaProps}
|
||||||
application={this.state.application}
|
application={this.state.application}
|
||||||
user={this.props.account}
|
user={this.props.account}
|
||||||
onSuccess={() => {
|
onSuccess={() => {
|
||||||
@ -261,11 +250,6 @@ class MfaSetupPage extends React.Component {
|
|||||||
<Col span={24} style={{display: "flex", justifyContent: "left"}}>
|
<Col span={24} style={{display: "flex", justifyContent: "left"}}>
|
||||||
{(this.state.mfaType === EmailMfaType || this.props.account.mfaEmailEnabled) ? null :
|
{(this.state.mfaType === EmailMfaType || this.props.account.mfaEmailEnabled) ? null :
|
||||||
<Button type={"link"} onClick={() => {
|
<Button type={"link"} onClick={() => {
|
||||||
if (this.state.isPromptPage) {
|
|
||||||
this.props.history.push(`/prompt/${this.state.application.name}?promptType=mfa&mfaType=${EmailMfaType}`);
|
|
||||||
} else {
|
|
||||||
this.props.history.push(`/mfa-authentication/setup?mfaType=${EmailMfaType}`);
|
|
||||||
}
|
|
||||||
this.setState({
|
this.setState({
|
||||||
mfaType: EmailMfaType,
|
mfaType: EmailMfaType,
|
||||||
});
|
});
|
||||||
@ -275,17 +259,21 @@ class MfaSetupPage extends React.Component {
|
|||||||
{
|
{
|
||||||
(this.state.mfaType === SmsMfaType || this.props.account.mfaPhoneEnabled) ? null :
|
(this.state.mfaType === SmsMfaType || this.props.account.mfaPhoneEnabled) ? null :
|
||||||
<Button type={"link"} onClick={() => {
|
<Button type={"link"} onClick={() => {
|
||||||
if (this.state.isPromptPage) {
|
|
||||||
this.props.history.push(`/prompt/${this.state.application.name}?promptType=mfa&mfaType=${SmsMfaType}`);
|
|
||||||
} else {
|
|
||||||
this.props.history.push(`/mfa-authentication/setup?mfaType=${SmsMfaType}`);
|
|
||||||
}
|
|
||||||
this.setState({
|
this.setState({
|
||||||
mfaType: SmsMfaType,
|
mfaType: SmsMfaType,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}>{i18next.t("mfa:Use SMS")}</Button>
|
}>{i18next.t("mfa:Use SMS")}</Button>
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
(this.state.mfaType === TotpMfaType) ? null :
|
||||||
|
<Button type={"link"} onClick={() => {
|
||||||
|
this.setState({
|
||||||
|
mfaType: TotpMfaType,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}>{i18next.t("mfa:Use Authenticator App")}</Button>
|
||||||
|
}
|
||||||
</Col>
|
</Col>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@ -294,18 +282,20 @@ class MfaSetupPage extends React.Component {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return <EnableMfaForm user={this.getUser()} mfaType={this.state.mfaType} recoveryCodes={this.state.mfaProps.recoveryCodes}
|
return (
|
||||||
onSuccess={() => {
|
<EnableMfaForm user={this.getUser()} mfaType={this.state.mfaType} recoveryCodes={this.state.mfaProps.recoveryCodes}
|
||||||
Setting.showMessage("success", i18next.t("general:Enabled successfully"));
|
onSuccess={() => {
|
||||||
if (this.state.isPromptPage && this.state.redirectUri) {
|
Setting.showMessage("success", i18next.t("general:Enabled successfully"));
|
||||||
Setting.goToLink(this.state.redirectUri);
|
if (this.state.isPromptPage && this.state.redirectUri) {
|
||||||
} else {
|
Setting.goToLink(this.state.redirectUri);
|
||||||
Setting.goToLink("/account");
|
} else {
|
||||||
}
|
Setting.goToLink("/account");
|
||||||
}}
|
}
|
||||||
onFail={(res) => {
|
}}
|
||||||
Setting.showMessage("error", `${i18next.t("general:Failed to enable")}: ${res.msg}`);
|
onFail={(res) => {
|
||||||
}} />;
|
Setting.showMessage("error", `${i18next.t("general:Failed to enable")}: ${res.msg}`);
|
||||||
|
}} />
|
||||||
|
);
|
||||||
default:
|
default:
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -328,24 +318,20 @@ class MfaSetupPage extends React.Component {
|
|||||||
<Col span={24} style={{justifyContent: "center"}}>
|
<Col span={24} style={{justifyContent: "center"}}>
|
||||||
<Row>
|
<Row>
|
||||||
<Col span={24}>
|
<Col span={24}>
|
||||||
<div style={{textAlign: "center", fontSize: "28px"}}>
|
<p style={{textAlign: "center", fontSize: "28px"}}>
|
||||||
{i18next.t("mfa:Protect your account with Multi-factor authentication")}</div>
|
{i18next.t("mfa:Protect your account with Multi-factor authentication")}</p>
|
||||||
<div style={{textAlign: "center", fontSize: "16px", marginTop: "10px"}}>{i18next.t("mfa:Each time you sign in to your Account, you'll need your password and a authentication code")}</div>
|
<p style={{textAlign: "center", fontSize: "16px", marginTop: "10px"}}>{i18next.t("mfa:Each time you sign in to your Account, you'll need your password and a authentication code")}</p>
|
||||||
</Col>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Col span={24}>
|
|
||||||
<Steps current={this.state.current}
|
|
||||||
items={[
|
|
||||||
{title: i18next.t("mfa:Verify Password"), icon: <UserOutlined />},
|
|
||||||
{title: i18next.t("mfa:Verify Code"), icon: <KeyOutlined />},
|
|
||||||
{title: i18next.t("general:Enable"), icon: <CheckOutlined />},
|
|
||||||
]}
|
|
||||||
style={{width: "90%", maxWidth: "500px", margin: "auto", marginTop: "80px",
|
|
||||||
}} >
|
|
||||||
</Steps>
|
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
|
<Steps current={this.state.current}
|
||||||
|
items={[
|
||||||
|
{title: i18next.t("mfa:Verify Password"), icon: <UserOutlined />},
|
||||||
|
{title: i18next.t("mfa:Verify Code"), icon: <KeyOutlined />},
|
||||||
|
{title: i18next.t("general:Enable"), icon: <CheckOutlined />},
|
||||||
|
]}
|
||||||
|
style={{width: "90%", maxWidth: "500px", margin: "auto", marginTop: "50px",
|
||||||
|
}} >
|
||||||
|
</Steps>
|
||||||
</Col>
|
</Col>
|
||||||
<Col span={24} style={{display: "flex", justifyContent: "center"}}>
|
<Col span={24} style={{display: "flex", justifyContent: "center"}}>
|
||||||
<div style={{marginTop: "10px", textAlign: "center"}}>
|
<div style={{marginTop: "10px", textAlign: "center"}}>
|
||||||
|
@ -12,23 +12,33 @@
|
|||||||
// 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 {Button, Col, Form, Input, Row} from "antd";
|
import {Button, Col, Form, Input, QRCode, Space} from "antd";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
import {CopyOutlined, UserOutlined} from "@ant-design/icons";
|
import {CopyOutlined, UserOutlined} from "@ant-design/icons";
|
||||||
import {SendCodeInput} from "../common/SendCodeInput";
|
import {SendCodeInput} from "../common/SendCodeInput";
|
||||||
import * as Setting from "../Setting";
|
import * as Setting from "../Setting";
|
||||||
import React from "react";
|
import React, {useEffect} from "react";
|
||||||
import copy from "copy-to-clipboard";
|
import copy from "copy-to-clipboard";
|
||||||
import {CountryCodeSelect} from "../common/select/CountryCodeSelect";
|
import {CountryCodeSelect} from "../common/select/CountryCodeSelect";
|
||||||
import {EmailMfaType} from "./MfaSetupPage";
|
import {EmailMfaType, SmsMfaType} from "./MfaSetupPage";
|
||||||
|
|
||||||
export const mfaAuth = "mfaAuth";
|
export const mfaAuth = "mfaAuth";
|
||||||
export const mfaSetup = "mfaSetup";
|
export const mfaSetup = "mfaSetup";
|
||||||
|
|
||||||
export const MfaSmsVerifyForm = ({mfaProps, application, onFinish, method}) => {
|
export const MfaSmsVerifyForm = ({mfaProps, application, onFinish, method, user}) => {
|
||||||
const [dest, setDest] = React.useState(mfaProps.secret ?? "");
|
const [dest, setDest] = React.useState(mfaProps.secret ?? "");
|
||||||
const [form] = Form.useForm();
|
const [form] = Form.useForm();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (mfaProps.mfaType === SmsMfaType) {
|
||||||
|
setDest(user.phone);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mfaProps.mfaType === EmailMfaType) {
|
||||||
|
setDest(user.email);
|
||||||
|
}
|
||||||
|
}, [mfaProps.mfaType]);
|
||||||
|
|
||||||
const isEmail = () => {
|
const isEmail = () => {
|
||||||
return mfaProps.mfaType === EmailMfaType;
|
return mfaProps.mfaType === EmailMfaType;
|
||||||
};
|
};
|
||||||
@ -42,9 +52,9 @@ export const MfaSmsVerifyForm = ({mfaProps, application, onFinish, method}) => {
|
|||||||
countryCode: mfaProps.countryCode,
|
countryCode: mfaProps.countryCode,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{mfaProps.secret !== "" ?
|
{dest !== "" ?
|
||||||
<div style={{marginBottom: 20, textAlign: "left", gap: 8}}>
|
<div style={{marginBottom: 20, textAlign: "left", gap: 8}}>
|
||||||
{isEmail() ? i18next.t("mfa:Your email is") : i18next.t("mfa:Your phone is")} {mfaProps.secret}
|
{isEmail() ? i18next.t("mfa:Your email is") : i18next.t("mfa:Your phone is")} {dest}
|
||||||
</div> :
|
</div> :
|
||||||
(<React.Fragment>
|
(<React.Fragment>
|
||||||
<p>{isEmail() ? i18next.t("mfa:Please bind your email first, the system will automatically uses the mail for multi-factor authentication") :
|
<p>{isEmail() ? i18next.t("mfa:Please bind your email first, the system will automatically uses the mail for multi-factor authentication") :
|
||||||
@ -114,44 +124,49 @@ export const MfaSmsVerifyForm = ({mfaProps, application, onFinish, method}) => {
|
|||||||
export const MfaTotpVerifyForm = ({mfaProps, onFinish}) => {
|
export const MfaTotpVerifyForm = ({mfaProps, onFinish}) => {
|
||||||
const [form] = Form.useForm();
|
const [form] = Form.useForm();
|
||||||
|
|
||||||
|
const renderSecret = () => {
|
||||||
|
if (!mfaProps.secret) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<React.Fragment>
|
||||||
|
<Col span={24} style={{display: "flex", justifyContent: "center"}}>
|
||||||
|
<QRCode
|
||||||
|
errorLevel="H"
|
||||||
|
value={mfaProps.url}
|
||||||
|
icon={"https://cdn.casdoor.com/static/favicon.png"}
|
||||||
|
/>
|
||||||
|
</Col>
|
||||||
|
<p style={{textAlign: "center"}}>{i18next.t("mfa:Scan the QR code with your Authenticator App")}</p>
|
||||||
|
<p style={{textAlign: "center"}}>{i18next.t("mfa:Or copy the secret to your Authenticator App")}</p>
|
||||||
|
<Col span={24}>
|
||||||
|
<Space>
|
||||||
|
<Input value={mfaProps.secret} />
|
||||||
|
<Button
|
||||||
|
type="primary"
|
||||||
|
shape="round"
|
||||||
|
icon={<CopyOutlined />}
|
||||||
|
onClick={() => {
|
||||||
|
copy(`${mfaProps.secret}`);
|
||||||
|
Setting.showMessage(
|
||||||
|
"success",
|
||||||
|
i18next.t("mfa:Multi-factor secret to clipboard successfully")
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Space>
|
||||||
|
</Col>
|
||||||
|
</React.Fragment>
|
||||||
|
);
|
||||||
|
};
|
||||||
return (
|
return (
|
||||||
<Form
|
<Form
|
||||||
form={form}
|
form={form}
|
||||||
style={{width: "300px"}}
|
style={{width: "300px"}}
|
||||||
onFinish={onFinish}
|
onFinish={onFinish}
|
||||||
>
|
>
|
||||||
<Row type="flex" justify="center" align="middle">
|
{renderSecret()}
|
||||||
<Col>
|
|
||||||
</Col>
|
|
||||||
</Row>
|
|
||||||
|
|
||||||
<Row type="flex" justify="center" align="middle">
|
|
||||||
<Col>
|
|
||||||
{Setting.getLabel(
|
|
||||||
i18next.t("mfa:Multi-factor secret"),
|
|
||||||
i18next.t("mfa:Multi-factor secret - Tooltip")
|
|
||||||
)}
|
|
||||||
:
|
|
||||||
</Col>
|
|
||||||
<Col>
|
|
||||||
<Input value={mfaProps.secret} />
|
|
||||||
</Col>
|
|
||||||
<Col>
|
|
||||||
<Button
|
|
||||||
type="primary"
|
|
||||||
shape="round"
|
|
||||||
icon={<CopyOutlined />}
|
|
||||||
onClick={() => {
|
|
||||||
copy(`${mfaProps.secret}`);
|
|
||||||
Setting.showMessage(
|
|
||||||
"success",
|
|
||||||
i18next.t("mfa:Multi-factor secret to clipboard successfully")
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</Col>
|
|
||||||
</Row>
|
|
||||||
|
|
||||||
<Form.Item
|
<Form.Item
|
||||||
name="passcode"
|
name="passcode"
|
||||||
rules={[{required: true, message: "Please input your passcode"}]}
|
rules={[{required: true, message: "Please input your passcode"}]}
|
||||||
@ -162,7 +177,6 @@ export const MfaTotpVerifyForm = ({mfaProps, onFinish}) => {
|
|||||||
placeholder={i18next.t("mfa:Passcode")}
|
placeholder={i18next.t("mfa:Passcode")}
|
||||||
/>
|
/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
|
||||||
<Form.Item>
|
<Form.Item>
|
||||||
<Button
|
<Button
|
||||||
style={{marginTop: 24}}
|
style={{marginTop: 24}}
|
||||||
|
@ -49,9 +49,14 @@ class PromptPage extends React.Component {
|
|||||||
const organizationName = this.props.account.owner;
|
const organizationName = this.props.account.owner;
|
||||||
const userName = this.props.account.name;
|
const userName = this.props.account.name;
|
||||||
UserBackend.getUser(organizationName, userName)
|
UserBackend.getUser(organizationName, userName)
|
||||||
.then((user) => {
|
.then((res) => {
|
||||||
|
if (res.status === "error") {
|
||||||
|
Setting.showMessage("error", res.msg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
user: user,
|
user: res,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -62,10 +67,15 @@ class PromptPage extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ApplicationBackend.getApplication("admin", this.state.applicationName)
|
ApplicationBackend.getApplication("admin", this.state.applicationName)
|
||||||
.then((application) => {
|
.then((res) => {
|
||||||
this.onUpdateApplication(application);
|
if (res.status === "error") {
|
||||||
|
Setting.showMessage("error", res.msg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.onUpdateApplication(res);
|
||||||
this.setState({
|
this.setState({
|
||||||
application: application,
|
application: res,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -43,10 +43,14 @@ class ResultPage extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ApplicationBackend.getApplication("admin", this.state.applicationName)
|
ApplicationBackend.getApplication("admin", this.state.applicationName)
|
||||||
.then((application) => {
|
.then((res) => {
|
||||||
this.onUpdateApplication(application);
|
if (res.status === "error") {
|
||||||
|
Setting.showMessage("error", res.msg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.onUpdateApplication(res);
|
||||||
this.setState({
|
this.setState({
|
||||||
application: application,
|
application: res,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -108,8 +108,13 @@ class SignupPage extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ApplicationBackend.getApplication("admin", applicationName)
|
ApplicationBackend.getApplication("admin", applicationName)
|
||||||
.then((application) => {
|
.then((res) => {
|
||||||
this.onUpdateApplication(application);
|
if (res.status === "error") {
|
||||||
|
Setting.showMessage("error", res.msg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.onUpdateApplication(res);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,6 +127,11 @@ export const CropperDivModal = (props) => {
|
|||||||
setLoading(true);
|
setLoading(true);
|
||||||
ResourceBackend.getResources(user.owner, user.name, "", "", "", "", "", "")
|
ResourceBackend.getResources(user.owner, user.name, "", "", "", "", "", "")
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
|
if (res.status === "error") {
|
||||||
|
Setting.showMessage("error", res.msg);
|
||||||
|
setLoading(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
setOptions(getOptions(res));
|
setOptions(getOptions(res));
|
||||||
});
|
});
|
||||||
|
@ -96,6 +96,7 @@
|
|||||||
"Signup items": "Registrierungs Items",
|
"Signup items": "Registrierungs Items",
|
||||||
"Signup items - Tooltip": "Items, die Benutzer ausfüllen müssen, wenn sie neue Konten registrieren",
|
"Signup items - Tooltip": "Items, die Benutzer ausfüllen müssen, wenn sie neue Konten registrieren",
|
||||||
"Signup page URL copied to clipboard successfully, please paste it into the incognito window or another browser": "Die URL der Registrierungsseite wurde in die Zwischenablage kopiert. Bitte fügen Sie sie in einen Inkognito-Tab oder einen anderen Browser ein",
|
"Signup page URL copied to clipboard successfully, please paste it into the incognito window or another browser": "Die URL der Registrierungsseite wurde in die Zwischenablage kopiert. Bitte fügen Sie sie in einen Inkognito-Tab oder einen anderen Browser ein",
|
||||||
|
"Tags - Tooltip": "Only users with the tag that is listed in the application tags can login",
|
||||||
"The application does not allow to sign up new account": "Die Anwendung erlaubt es nicht, ein neues Konto zu registrieren",
|
"The application does not allow to sign up new account": "Die Anwendung erlaubt es nicht, ein neues Konto zu registrieren",
|
||||||
"Token expire": "Token läuft ab",
|
"Token expire": "Token läuft ab",
|
||||||
"Token expire - Tooltip": "Ablaufzeit des Access-Tokens",
|
"Token expire - Tooltip": "Ablaufzeit des Access-Tokens",
|
||||||
@ -434,17 +435,18 @@
|
|||||||
"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",
|
||||||
"Multi-factor secret": "Multi-factor secret",
|
|
||||||
"Multi-factor secret - Tooltip": "Multi-factor secret - Tooltip",
|
|
||||||
"Multi-factor secret to clipboard successfully": "Multi-factor secret to clipboard successfully",
|
"Multi-factor secret to clipboard successfully": "Multi-factor secret to clipboard successfully",
|
||||||
|
"Or copy the secret to your Authenticator App": "Or copy the secret to your Authenticator App",
|
||||||
"Passcode": "Passcode",
|
"Passcode": "Passcode",
|
||||||
"Please bind your email first, the system will automatically uses the mail for multi-factor authentication": "Please bind your email first, the system will automatically uses the mail for multi-factor authentication",
|
"Please bind your email first, the system will automatically uses the mail for multi-factor authentication": "Please bind your email first, the system will automatically uses the mail for multi-factor authentication",
|
||||||
"Please bind your phone first, the system automatically uses the phone for multi-factor authentication": "Please bind your phone first, the system automatically uses the phone for multi-factor authentication",
|
"Please bind your phone first, the system automatically uses the phone for multi-factor authentication": "Please bind your phone first, the system automatically uses the phone for multi-factor authentication",
|
||||||
"Please save this recovery code. Once your device cannot provide an authentication code, you can reset mfa authentication by this recovery code": "Please save this recovery code. Once your device cannot provide an authentication code, you can reset mfa authentication by this recovery code",
|
"Please save this recovery code. Once your device cannot provide an authentication code, you can reset mfa authentication by this recovery code": "Please save this recovery code. Once your device cannot provide an authentication code, you can reset mfa authentication by this recovery code",
|
||||||
"Protect your account with Multi-factor authentication": "Protect your account with Multi-factor authentication",
|
"Protect your account with Multi-factor authentication": "Protect your account with Multi-factor authentication",
|
||||||
"Recovery code": "Recovery code",
|
"Recovery code": "Recovery code",
|
||||||
|
"Scan the QR code with your Authenticator App": "Scan the QR code with your Authenticator App",
|
||||||
"Set preferred": "Set preferred",
|
"Set preferred": "Set preferred",
|
||||||
"Setup": "Setup",
|
"Setup": "Setup",
|
||||||
|
"Use Authenticator App": "Use Authenticator App",
|
||||||
"Use Email": "Use Email",
|
"Use Email": "Use Email",
|
||||||
"Use SMS": "Use SMS",
|
"Use SMS": "Use SMS",
|
||||||
"Use SMS verification code": "Use SMS verification code",
|
"Use SMS verification code": "Use SMS verification code",
|
||||||
@ -568,6 +570,7 @@
|
|||||||
"Copy pricing page URL": "Preisseite URL kopieren",
|
"Copy pricing page URL": "Preisseite URL kopieren",
|
||||||
"Edit Pricing": "Edit Pricing",
|
"Edit Pricing": "Edit Pricing",
|
||||||
"Free": "Kostenlos",
|
"Free": "Kostenlos",
|
||||||
|
"Failed to get plans": "Es konnten keine Pläne abgerufen werden",
|
||||||
"Getting started": "Loslegen",
|
"Getting started": "Loslegen",
|
||||||
"New Pricing": "New Pricing",
|
"New Pricing": "New Pricing",
|
||||||
"Trial duration": "Testphase Dauer",
|
"Trial duration": "Testphase Dauer",
|
||||||
|
@ -96,6 +96,7 @@
|
|||||||
"Signup items": "Signup items",
|
"Signup items": "Signup items",
|
||||||
"Signup items - Tooltip": "Items for users to fill in when registering new accounts",
|
"Signup items - Tooltip": "Items for users to fill in when registering new accounts",
|
||||||
"Signup page URL copied to clipboard successfully, please paste it into the incognito window or another browser": "Signup page URL copied to clipboard successfully, please paste it into the incognito window or another browser",
|
"Signup page URL copied to clipboard successfully, please paste it into the incognito window or another browser": "Signup page URL copied to clipboard successfully, please paste it into the incognito window or another browser",
|
||||||
|
"Tags - Tooltip": "Only users with the tag that is listed in the application tags can login",
|
||||||
"The application does not allow to sign up new account": "The application does not allow to sign up new account",
|
"The application does not allow to sign up new account": "The application does not allow to sign up new account",
|
||||||
"Token expire": "Token expire",
|
"Token expire": "Token expire",
|
||||||
"Token expire - Tooltip": "Access token expiration time",
|
"Token expire - Tooltip": "Access token expiration time",
|
||||||
@ -434,17 +435,18 @@
|
|||||||
"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": "If you are unable to access your device, enter your recovery code to verify your identity",
|
"Multi-factor recover description": "If you are unable to access your device, enter your recovery code to verify your identity",
|
||||||
"Multi-factor secret": "Multi-factor secret",
|
|
||||||
"Multi-factor secret - Tooltip": "Multi-factor secret - Tooltip",
|
|
||||||
"Multi-factor secret to clipboard successfully": "Multi-factor secret to clipboard successfully",
|
"Multi-factor secret to clipboard successfully": "Multi-factor secret to clipboard successfully",
|
||||||
|
"Or copy the secret to your Authenticator App": "Or copy the secret to your Authenticator App",
|
||||||
"Passcode": "Passcode",
|
"Passcode": "Passcode",
|
||||||
"Please bind your email first, the system will automatically uses the mail for multi-factor authentication": "Please bind your email first, the system will automatically uses the mail for multi-factor authentication",
|
"Please bind your email first, the system will automatically uses the mail for multi-factor authentication": "Please bind your email first, the system will automatically uses the mail for multi-factor authentication",
|
||||||
"Please bind your phone first, the system automatically uses the phone for multi-factor authentication": "Please bind your phone first, the system automatically uses the phone for multi-factor authentication",
|
"Please bind your phone first, the system automatically uses the phone for multi-factor authentication": "Please bind your phone first, the system automatically uses the phone for multi-factor authentication",
|
||||||
"Please save this recovery code. Once your device cannot provide an authentication code, you can reset mfa authentication by this recovery code": "Please save this recovery code. Once your device cannot provide an authentication code, you can reset mfa authentication by this recovery code",
|
"Please save this recovery code. Once your device cannot provide an authentication code, you can reset mfa authentication by this recovery code": "Please save this recovery code. Once your device cannot provide an authentication code, you can reset mfa authentication by this recovery code",
|
||||||
"Protect your account with Multi-factor authentication": "Protect your account with Multi-factor authentication",
|
"Protect your account with Multi-factor authentication": "Protect your account with Multi-factor authentication",
|
||||||
"Recovery code": "Recovery code",
|
"Recovery code": "Recovery code",
|
||||||
|
"Scan the QR code with your Authenticator App": "Scan the QR code with your Authenticator App",
|
||||||
"Set preferred": "Set preferred",
|
"Set preferred": "Set preferred",
|
||||||
"Setup": "Setup",
|
"Setup": "Setup",
|
||||||
|
"Use Authenticator App": "Use Authenticator App",
|
||||||
"Use Email": "Use Email",
|
"Use Email": "Use Email",
|
||||||
"Use SMS": "Use SMS",
|
"Use SMS": "Use SMS",
|
||||||
"Use SMS verification code": "Use SMS verification code",
|
"Use SMS verification code": "Use SMS verification code",
|
||||||
@ -568,6 +570,7 @@
|
|||||||
"Copy pricing page URL": "Copy pricing page URL",
|
"Copy pricing page URL": "Copy pricing page URL",
|
||||||
"Edit Pricing": "Edit Pricing",
|
"Edit Pricing": "Edit Pricing",
|
||||||
"Free": "Free",
|
"Free": "Free",
|
||||||
|
"Failed to get plans": "Failed to get plans",
|
||||||
"Getting started": "Getting started",
|
"Getting started": "Getting started",
|
||||||
"New Pricing": "New Pricing",
|
"New Pricing": "New Pricing",
|
||||||
"Trial duration": "Trial duration",
|
"Trial duration": "Trial duration",
|
||||||
|
@ -96,6 +96,7 @@
|
|||||||
"Signup items": "Artículos de registro",
|
"Signup items": "Artículos de registro",
|
||||||
"Signup items - Tooltip": "Elementos para que los usuarios los completen al registrar nuevas cuentas",
|
"Signup items - Tooltip": "Elementos para que los usuarios los completen al registrar nuevas cuentas",
|
||||||
"Signup page URL copied to clipboard successfully, please paste it into the incognito window or another browser": "La URL de la página de registro se ha copiado correctamente en el portapapeles. Por favor, péguela en una ventana de incógnito o en otro navegador",
|
"Signup page URL copied to clipboard successfully, please paste it into the incognito window or another browser": "La URL de la página de registro se ha copiado correctamente en el portapapeles. Por favor, péguela en una ventana de incógnito o en otro navegador",
|
||||||
|
"Tags - Tooltip": "Only users with the tag that is listed in the application tags can login",
|
||||||
"The application does not allow to sign up new account": "La aplicación no permite registrarse una cuenta nueva",
|
"The application does not allow to sign up new account": "La aplicación no permite registrarse una cuenta nueva",
|
||||||
"Token expire": "Token expirado",
|
"Token expire": "Token expirado",
|
||||||
"Token expire - Tooltip": "Tiempo de expiración del token de acceso",
|
"Token expire - Tooltip": "Tiempo de expiración del token de acceso",
|
||||||
@ -434,17 +435,18 @@
|
|||||||
"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",
|
||||||
"Multi-factor secret": "Multi-factor secret",
|
|
||||||
"Multi-factor secret - Tooltip": "Multi-factor secret - Tooltip",
|
|
||||||
"Multi-factor secret to clipboard successfully": "Multi-factor secret to clipboard successfully",
|
"Multi-factor secret to clipboard successfully": "Multi-factor secret to clipboard successfully",
|
||||||
|
"Or copy the secret to your Authenticator App": "Or copy the secret to your Authenticator App",
|
||||||
"Passcode": "Passcode",
|
"Passcode": "Passcode",
|
||||||
"Please bind your email first, the system will automatically uses the mail for multi-factor authentication": "Please bind your email first, the system will automatically uses the mail for multi-factor authentication",
|
"Please bind your email first, the system will automatically uses the mail for multi-factor authentication": "Please bind your email first, the system will automatically uses the mail for multi-factor authentication",
|
||||||
"Please bind your phone first, the system automatically uses the phone for multi-factor authentication": "Please bind your phone first, the system automatically uses the phone for multi-factor authentication",
|
"Please bind your phone first, the system automatically uses the phone for multi-factor authentication": "Please bind your phone first, the system automatically uses the phone for multi-factor authentication",
|
||||||
"Please save this recovery code. Once your device cannot provide an authentication code, you can reset mfa authentication by this recovery code": "Please save this recovery code. Once your device cannot provide an authentication code, you can reset mfa authentication by this recovery code",
|
"Please save this recovery code. Once your device cannot provide an authentication code, you can reset mfa authentication by this recovery code": "Please save this recovery code. Once your device cannot provide an authentication code, you can reset mfa authentication by this recovery code",
|
||||||
"Protect your account with Multi-factor authentication": "Protect your account with Multi-factor authentication",
|
"Protect your account with Multi-factor authentication": "Protect your account with Multi-factor authentication",
|
||||||
"Recovery code": "Recovery code",
|
"Recovery code": "Recovery code",
|
||||||
|
"Scan the QR code with your Authenticator App": "Scan the QR code with your Authenticator App",
|
||||||
"Set preferred": "Set preferred",
|
"Set preferred": "Set preferred",
|
||||||
"Setup": "Setup",
|
"Setup": "Setup",
|
||||||
|
"Use Authenticator App": "Use Authenticator App",
|
||||||
"Use Email": "Use Email",
|
"Use Email": "Use Email",
|
||||||
"Use SMS": "Use SMS",
|
"Use SMS": "Use SMS",
|
||||||
"Use SMS verification code": "Use SMS verification code",
|
"Use SMS verification code": "Use SMS verification code",
|
||||||
@ -568,6 +570,7 @@
|
|||||||
"Copy pricing page URL": "Copiar URL de la página de precios",
|
"Copy pricing page URL": "Copiar URL de la página de precios",
|
||||||
"Edit Pricing": "Edit Pricing",
|
"Edit Pricing": "Edit Pricing",
|
||||||
"Free": "Gratis",
|
"Free": "Gratis",
|
||||||
|
"Failed to get plans": "No se pudieron obtener los planes",
|
||||||
"Getting started": "Empezar",
|
"Getting started": "Empezar",
|
||||||
"New Pricing": "New Pricing",
|
"New Pricing": "New Pricing",
|
||||||
"Trial duration": "Duración del período de prueba",
|
"Trial duration": "Duración del período de prueba",
|
||||||
|
@ -96,6 +96,7 @@
|
|||||||
"Signup items": "Les éléments d'inscription",
|
"Signup items": "Les éléments d'inscription",
|
||||||
"Signup items - Tooltip": "Eléments à remplir par les utilisateurs lors de l'inscription de nouveaux comptes",
|
"Signup items - Tooltip": "Eléments à remplir par les utilisateurs lors de l'inscription de nouveaux comptes",
|
||||||
"Signup page URL copied to clipboard successfully, please paste it into the incognito window or another browser": "URL de la page d'inscription copiée avec succès dans le presse-papiers, veuillez la coller dans la fenêtre de navigation privée ou dans un autre navigateur",
|
"Signup page URL copied to clipboard successfully, please paste it into the incognito window or another browser": "URL de la page d'inscription copiée avec succès dans le presse-papiers, veuillez la coller dans la fenêtre de navigation privée ou dans un autre navigateur",
|
||||||
|
"Tags - Tooltip": "Only users with the tag that is listed in the application tags can login",
|
||||||
"The application does not allow to sign up new account": "L'application ne permet pas de créer un nouveau compte",
|
"The application does not allow to sign up new account": "L'application ne permet pas de créer un nouveau compte",
|
||||||
"Token expire": "Le jeton expire",
|
"Token expire": "Le jeton expire",
|
||||||
"Token expire - Tooltip": "Temps d'expiration de jeton d'accès",
|
"Token expire - Tooltip": "Temps d'expiration de jeton d'accès",
|
||||||
@ -434,17 +435,18 @@
|
|||||||
"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",
|
||||||
"Multi-factor secret": "Multi-factor secret",
|
|
||||||
"Multi-factor secret - Tooltip": "Multi-factor secret - Tooltip",
|
|
||||||
"Multi-factor secret to clipboard successfully": "Multi-factor secret to clipboard successfully",
|
"Multi-factor secret to clipboard successfully": "Multi-factor secret to clipboard successfully",
|
||||||
|
"Or copy the secret to your Authenticator App": "Or copy the secret to your Authenticator App",
|
||||||
"Passcode": "Passcode",
|
"Passcode": "Passcode",
|
||||||
"Please bind your email first, the system will automatically uses the mail for multi-factor authentication": "Please bind your email first, the system will automatically uses the mail for multi-factor authentication",
|
"Please bind your email first, the system will automatically uses the mail for multi-factor authentication": "Please bind your email first, the system will automatically uses the mail for multi-factor authentication",
|
||||||
"Please bind your phone first, the system automatically uses the phone for multi-factor authentication": "Please bind your phone first, the system automatically uses the phone for multi-factor authentication",
|
"Please bind your phone first, the system automatically uses the phone for multi-factor authentication": "Please bind your phone first, the system automatically uses the phone for multi-factor authentication",
|
||||||
"Please save this recovery code. Once your device cannot provide an authentication code, you can reset mfa authentication by this recovery code": "Please save this recovery code. Once your device cannot provide an authentication code, you can reset mfa authentication by this recovery code",
|
"Please save this recovery code. Once your device cannot provide an authentication code, you can reset mfa authentication by this recovery code": "Please save this recovery code. Once your device cannot provide an authentication code, you can reset mfa authentication by this recovery code",
|
||||||
"Protect your account with Multi-factor authentication": "Protect your account with Multi-factor authentication",
|
"Protect your account with Multi-factor authentication": "Protect your account with Multi-factor authentication",
|
||||||
"Recovery code": "Recovery code",
|
"Recovery code": "Recovery code",
|
||||||
|
"Scan the QR code with your Authenticator App": "Scan the QR code with your Authenticator App",
|
||||||
"Set preferred": "Set preferred",
|
"Set preferred": "Set preferred",
|
||||||
"Setup": "Setup",
|
"Setup": "Setup",
|
||||||
|
"Use Authenticator App": "Use Authenticator App",
|
||||||
"Use Email": "Use Email",
|
"Use Email": "Use Email",
|
||||||
"Use SMS": "Use SMS",
|
"Use SMS": "Use SMS",
|
||||||
"Use SMS verification code": "Use SMS verification code",
|
"Use SMS verification code": "Use SMS verification code",
|
||||||
@ -568,6 +570,7 @@
|
|||||||
"Copy pricing page URL": "Copier l'URL de la page tarifs",
|
"Copy pricing page URL": "Copier l'URL de la page tarifs",
|
||||||
"Edit Pricing": "Edit Pricing",
|
"Edit Pricing": "Edit Pricing",
|
||||||
"Free": "Gratuit",
|
"Free": "Gratuit",
|
||||||
|
"Failed to get plans": "Échec de l'obtention des plans",
|
||||||
"Getting started": "Commencer",
|
"Getting started": "Commencer",
|
||||||
"New Pricing": "New Pricing",
|
"New Pricing": "New Pricing",
|
||||||
"Trial duration": "Durée de l'essai",
|
"Trial duration": "Durée de l'essai",
|
||||||
|
@ -96,6 +96,7 @@
|
|||||||
"Signup items": "Item pendaftaran",
|
"Signup items": "Item pendaftaran",
|
||||||
"Signup items - Tooltip": "Item-item yang harus diisi pengguna saat mendaftar untuk akun baru",
|
"Signup items - Tooltip": "Item-item yang harus diisi pengguna saat mendaftar untuk akun baru",
|
||||||
"Signup page URL copied to clipboard successfully, please paste it into the incognito window or another browser": "Tautan halaman pendaftaran URL berhasil disalin ke papan klip, silakan tempelkan ke dalam jendela incognito atau browser lain",
|
"Signup page URL copied to clipboard successfully, please paste it into the incognito window or another browser": "Tautan halaman pendaftaran URL berhasil disalin ke papan klip, silakan tempelkan ke dalam jendela incognito atau browser lain",
|
||||||
|
"Tags - Tooltip": "Only users with the tag that is listed in the application tags can login",
|
||||||
"The application does not allow to sign up new account": "Aplikasi tidak memperbolehkan untuk mendaftar akun baru",
|
"The application does not allow to sign up new account": "Aplikasi tidak memperbolehkan untuk mendaftar akun baru",
|
||||||
"Token expire": "Token kadaluarsa",
|
"Token expire": "Token kadaluarsa",
|
||||||
"Token expire - Tooltip": "Waktu kadaluwarsa token akses",
|
"Token expire - Tooltip": "Waktu kadaluwarsa token akses",
|
||||||
@ -434,17 +435,18 @@
|
|||||||
"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",
|
||||||
"Multi-factor secret": "Multi-factor secret",
|
|
||||||
"Multi-factor secret - Tooltip": "Multi-factor secret - Tooltip",
|
|
||||||
"Multi-factor secret to clipboard successfully": "Multi-factor secret to clipboard successfully",
|
"Multi-factor secret to clipboard successfully": "Multi-factor secret to clipboard successfully",
|
||||||
|
"Or copy the secret to your Authenticator App": "Or copy the secret to your Authenticator App",
|
||||||
"Passcode": "Passcode",
|
"Passcode": "Passcode",
|
||||||
"Please bind your email first, the system will automatically uses the mail for multi-factor authentication": "Please bind your email first, the system will automatically uses the mail for multi-factor authentication",
|
"Please bind your email first, the system will automatically uses the mail for multi-factor authentication": "Please bind your email first, the system will automatically uses the mail for multi-factor authentication",
|
||||||
"Please bind your phone first, the system automatically uses the phone for multi-factor authentication": "Please bind your phone first, the system automatically uses the phone for multi-factor authentication",
|
"Please bind your phone first, the system automatically uses the phone for multi-factor authentication": "Please bind your phone first, the system automatically uses the phone for multi-factor authentication",
|
||||||
"Please save this recovery code. Once your device cannot provide an authentication code, you can reset mfa authentication by this recovery code": "Please save this recovery code. Once your device cannot provide an authentication code, you can reset mfa authentication by this recovery code",
|
"Please save this recovery code. Once your device cannot provide an authentication code, you can reset mfa authentication by this recovery code": "Please save this recovery code. Once your device cannot provide an authentication code, you can reset mfa authentication by this recovery code",
|
||||||
"Protect your account with Multi-factor authentication": "Protect your account with Multi-factor authentication",
|
"Protect your account with Multi-factor authentication": "Protect your account with Multi-factor authentication",
|
||||||
"Recovery code": "Recovery code",
|
"Recovery code": "Recovery code",
|
||||||
|
"Scan the QR code with your Authenticator App": "Scan the QR code with your Authenticator App",
|
||||||
"Set preferred": "Set preferred",
|
"Set preferred": "Set preferred",
|
||||||
"Setup": "Setup",
|
"Setup": "Setup",
|
||||||
|
"Use Authenticator App": "Use Authenticator App",
|
||||||
"Use Email": "Use Email",
|
"Use Email": "Use Email",
|
||||||
"Use SMS": "Use SMS",
|
"Use SMS": "Use SMS",
|
||||||
"Use SMS verification code": "Use SMS verification code",
|
"Use SMS verification code": "Use SMS verification code",
|
||||||
@ -568,6 +570,7 @@
|
|||||||
"Copy pricing page URL": "Salin URL halaman harga",
|
"Copy pricing page URL": "Salin URL halaman harga",
|
||||||
"Edit Pricing": "Edit Pricing",
|
"Edit Pricing": "Edit Pricing",
|
||||||
"Free": "Gratis",
|
"Free": "Gratis",
|
||||||
|
"Failed to get plans": "Gagal mendapatkan rencana",
|
||||||
"Getting started": "Mulai",
|
"Getting started": "Mulai",
|
||||||
"New Pricing": "New Pricing",
|
"New Pricing": "New Pricing",
|
||||||
"Trial duration": "Durasi percobaan",
|
"Trial duration": "Durasi percobaan",
|
||||||
|
@ -96,6 +96,7 @@
|
|||||||
"Signup items": "サインアップアイテム",
|
"Signup items": "サインアップアイテム",
|
||||||
"Signup items - Tooltip": "新しいアカウントを登録する際にユーザーが入力するアイテム",
|
"Signup items - Tooltip": "新しいアカウントを登録する際にユーザーが入力するアイテム",
|
||||||
"Signup page URL copied to clipboard successfully, please paste it into the incognito window or another browser": "サインアップページのURLがクリップボードに正常にコピーされました。シークレットウィンドウまたは別のブラウザに貼り付けてください",
|
"Signup page URL copied to clipboard successfully, please paste it into the incognito window or another browser": "サインアップページのURLがクリップボードに正常にコピーされました。シークレットウィンドウまたは別のブラウザに貼り付けてください",
|
||||||
|
"Tags - Tooltip": "Only users with the tag that is listed in the application tags can login",
|
||||||
"The application does not allow to sign up new account": "アプリケーションでは新しいアカウントの登録ができません",
|
"The application does not allow to sign up new account": "アプリケーションでは新しいアカウントの登録ができません",
|
||||||
"Token expire": "トークンの有効期限が切れました",
|
"Token expire": "トークンの有効期限が切れました",
|
||||||
"Token expire - Tooltip": "アクセストークンの有効期限",
|
"Token expire - Tooltip": "アクセストークンの有効期限",
|
||||||
@ -434,17 +435,18 @@
|
|||||||
"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",
|
||||||
"Multi-factor secret": "Multi-factor secret",
|
|
||||||
"Multi-factor secret - Tooltip": "Multi-factor secret - Tooltip",
|
|
||||||
"Multi-factor secret to clipboard successfully": "Multi-factor secret to clipboard successfully",
|
"Multi-factor secret to clipboard successfully": "Multi-factor secret to clipboard successfully",
|
||||||
|
"Or copy the secret to your Authenticator App": "Or copy the secret to your Authenticator App",
|
||||||
"Passcode": "Passcode",
|
"Passcode": "Passcode",
|
||||||
"Please bind your email first, the system will automatically uses the mail for multi-factor authentication": "Please bind your email first, the system will automatically uses the mail for multi-factor authentication",
|
"Please bind your email first, the system will automatically uses the mail for multi-factor authentication": "Please bind your email first, the system will automatically uses the mail for multi-factor authentication",
|
||||||
"Please bind your phone first, the system automatically uses the phone for multi-factor authentication": "Please bind your phone first, the system automatically uses the phone for multi-factor authentication",
|
"Please bind your phone first, the system automatically uses the phone for multi-factor authentication": "Please bind your phone first, the system automatically uses the phone for multi-factor authentication",
|
||||||
"Please save this recovery code. Once your device cannot provide an authentication code, you can reset mfa authentication by this recovery code": "Please save this recovery code. Once your device cannot provide an authentication code, you can reset mfa authentication by this recovery code",
|
"Please save this recovery code. Once your device cannot provide an authentication code, you can reset mfa authentication by this recovery code": "Please save this recovery code. Once your device cannot provide an authentication code, you can reset mfa authentication by this recovery code",
|
||||||
"Protect your account with Multi-factor authentication": "Protect your account with Multi-factor authentication",
|
"Protect your account with Multi-factor authentication": "Protect your account with Multi-factor authentication",
|
||||||
"Recovery code": "Recovery code",
|
"Recovery code": "Recovery code",
|
||||||
|
"Scan the QR code with your Authenticator App": "Scan the QR code with your Authenticator App",
|
||||||
"Set preferred": "Set preferred",
|
"Set preferred": "Set preferred",
|
||||||
"Setup": "Setup",
|
"Setup": "Setup",
|
||||||
|
"Use Authenticator App": "Use Authenticator App",
|
||||||
"Use Email": "Use Email",
|
"Use Email": "Use Email",
|
||||||
"Use SMS": "Use SMS",
|
"Use SMS": "Use SMS",
|
||||||
"Use SMS verification code": "Use SMS verification code",
|
"Use SMS verification code": "Use SMS verification code",
|
||||||
@ -568,6 +570,7 @@
|
|||||||
"Copy pricing page URL": "価格ページのURLをコピー",
|
"Copy pricing page URL": "価格ページのURLをコピー",
|
||||||
"Edit Pricing": "Edit Pricing",
|
"Edit Pricing": "Edit Pricing",
|
||||||
"Free": "無料",
|
"Free": "無料",
|
||||||
|
"Failed to get plans": "計画の取得に失敗しました",
|
||||||
"Getting started": "はじめる",
|
"Getting started": "はじめる",
|
||||||
"New Pricing": "New Pricing",
|
"New Pricing": "New Pricing",
|
||||||
"Trial duration": "トライアル期間の長さ",
|
"Trial duration": "トライアル期間の長さ",
|
||||||
|
@ -96,6 +96,7 @@
|
|||||||
"Signup items": "가입 항목",
|
"Signup items": "가입 항목",
|
||||||
"Signup items - Tooltip": "새로운 계정 등록시 사용자가 작성해야하는 항목들",
|
"Signup items - Tooltip": "새로운 계정 등록시 사용자가 작성해야하는 항목들",
|
||||||
"Signup page URL copied to clipboard successfully, please paste it into the incognito window or another browser": "가입 페이지 URL이 클립보드에 성공적으로 복사되었습니다. 시크릿 창이나 다른 브라우저에 붙여넣어 주십시오",
|
"Signup page URL copied to clipboard successfully, please paste it into the incognito window or another browser": "가입 페이지 URL이 클립보드에 성공적으로 복사되었습니다. 시크릿 창이나 다른 브라우저에 붙여넣어 주십시오",
|
||||||
|
"Tags - Tooltip": "Only users with the tag that is listed in the application tags can login",
|
||||||
"The application does not allow to sign up new account": "이 어플리케이션은 새 계정 등록을 허용하지 않습니다",
|
"The application does not allow to sign up new account": "이 어플리케이션은 새 계정 등록을 허용하지 않습니다",
|
||||||
"Token expire": "토큰 만료",
|
"Token expire": "토큰 만료",
|
||||||
"Token expire - Tooltip": "액세스 토큰 만료 시간",
|
"Token expire - Tooltip": "액세스 토큰 만료 시간",
|
||||||
@ -434,17 +435,18 @@
|
|||||||
"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",
|
||||||
"Multi-factor secret": "Multi-factor secret",
|
|
||||||
"Multi-factor secret - Tooltip": "Multi-factor secret - Tooltip",
|
|
||||||
"Multi-factor secret to clipboard successfully": "Multi-factor secret to clipboard successfully",
|
"Multi-factor secret to clipboard successfully": "Multi-factor secret to clipboard successfully",
|
||||||
|
"Or copy the secret to your Authenticator App": "Or copy the secret to your Authenticator App",
|
||||||
"Passcode": "Passcode",
|
"Passcode": "Passcode",
|
||||||
"Please bind your email first, the system will automatically uses the mail for multi-factor authentication": "Please bind your email first, the system will automatically uses the mail for multi-factor authentication",
|
"Please bind your email first, the system will automatically uses the mail for multi-factor authentication": "Please bind your email first, the system will automatically uses the mail for multi-factor authentication",
|
||||||
"Please bind your phone first, the system automatically uses the phone for multi-factor authentication": "Please bind your phone first, the system automatically uses the phone for multi-factor authentication",
|
"Please bind your phone first, the system automatically uses the phone for multi-factor authentication": "Please bind your phone first, the system automatically uses the phone for multi-factor authentication",
|
||||||
"Please save this recovery code. Once your device cannot provide an authentication code, you can reset mfa authentication by this recovery code": "Please save this recovery code. Once your device cannot provide an authentication code, you can reset mfa authentication by this recovery code",
|
"Please save this recovery code. Once your device cannot provide an authentication code, you can reset mfa authentication by this recovery code": "Please save this recovery code. Once your device cannot provide an authentication code, you can reset mfa authentication by this recovery code",
|
||||||
"Protect your account with Multi-factor authentication": "Protect your account with Multi-factor authentication",
|
"Protect your account with Multi-factor authentication": "Protect your account with Multi-factor authentication",
|
||||||
"Recovery code": "Recovery code",
|
"Recovery code": "Recovery code",
|
||||||
|
"Scan the QR code with your Authenticator App": "Scan the QR code with your Authenticator App",
|
||||||
"Set preferred": "Set preferred",
|
"Set preferred": "Set preferred",
|
||||||
"Setup": "Setup",
|
"Setup": "Setup",
|
||||||
|
"Use Authenticator App": "Use Authenticator App",
|
||||||
"Use Email": "Use Email",
|
"Use Email": "Use Email",
|
||||||
"Use SMS": "Use SMS",
|
"Use SMS": "Use SMS",
|
||||||
"Use SMS verification code": "Use SMS verification code",
|
"Use SMS verification code": "Use SMS verification code",
|
||||||
@ -568,6 +570,7 @@
|
|||||||
"Copy pricing page URL": "가격 페이지 URL 복사",
|
"Copy pricing page URL": "가격 페이지 URL 복사",
|
||||||
"Edit Pricing": "Edit Pricing",
|
"Edit Pricing": "Edit Pricing",
|
||||||
"Free": "무료",
|
"Free": "무료",
|
||||||
|
"Failed to get plans": "계획을 가져오지 못했습니다.",
|
||||||
"Getting started": "시작하기",
|
"Getting started": "시작하기",
|
||||||
"New Pricing": "New Pricing",
|
"New Pricing": "New Pricing",
|
||||||
"Trial duration": "체험 기간",
|
"Trial duration": "체험 기간",
|
||||||
|
@ -96,6 +96,7 @@
|
|||||||
"Signup items": "Itens de registro",
|
"Signup items": "Itens de registro",
|
||||||
"Signup items - Tooltip": "Itens para os usuários preencherem ao registrar novas contas",
|
"Signup items - Tooltip": "Itens para os usuários preencherem ao registrar novas contas",
|
||||||
"Signup page URL copied to clipboard successfully, please paste it into the incognito window or another browser": "URL da página de registro copiada para a área de transferência com sucesso. Cole-a na janela anônima ou em outro navegador",
|
"Signup page URL copied to clipboard successfully, please paste it into the incognito window or another browser": "URL da página de registro copiada para a área de transferência com sucesso. Cole-a na janela anônima ou em outro navegador",
|
||||||
|
"Tags - Tooltip": "Only users with the tag that is listed in the application tags can login",
|
||||||
"The application does not allow to sign up new account": "A aplicação não permite o registro de novas contas",
|
"The application does not allow to sign up new account": "A aplicação não permite o registro de novas contas",
|
||||||
"Token expire": "Expiração do Token",
|
"Token expire": "Expiração do Token",
|
||||||
"Token expire - Tooltip": "Tempo de expiração do token de acesso",
|
"Token expire - Tooltip": "Tempo de expiração do token de acesso",
|
||||||
@ -434,17 +435,18 @@
|
|||||||
"Multi-factor methods": "Métodos de vários fatores",
|
"Multi-factor methods": "Métodos de vários fatores",
|
||||||
"Multi-factor recover": "Recuperação de vários fatores",
|
"Multi-factor recover": "Recuperação de vários fatores",
|
||||||
"Multi-factor recover description": "Se você não conseguir acessar seu dispositivo, insira seu código de recuperação para verificar sua identidade",
|
"Multi-factor recover description": "Se você não conseguir acessar seu dispositivo, insira seu código de recuperação para verificar sua identidade",
|
||||||
"Multi-factor secret": "Segredo de vários fatores",
|
|
||||||
"Multi-factor secret - Tooltip": "Segredo de vários fatores - Dica de ferramenta",
|
|
||||||
"Multi-factor secret to clipboard successfully": "Segredo de vários fatores copiado para a área de transferência com sucesso",
|
"Multi-factor secret to clipboard successfully": "Segredo de vários fatores copiado para a área de transferência com sucesso",
|
||||||
|
"Or copy the secret to your Authenticator App": "Or copy the secret to your Authenticator App",
|
||||||
"Passcode": "Código de acesso",
|
"Passcode": "Código de acesso",
|
||||||
"Please bind your email first, the system will automatically uses the mail for multi-factor authentication": "Please bind your email first, the system will automatically uses the mail for multi-factor authentication",
|
"Please bind your email first, the system will automatically uses the mail for multi-factor authentication": "Please bind your email first, the system will automatically uses the mail for multi-factor authentication",
|
||||||
"Please bind your phone first, the system automatically uses the phone for multi-factor authentication": "Please bind your phone first, the system automatically uses the phone for multi-factor authentication",
|
"Please bind your phone first, the system automatically uses the phone for multi-factor authentication": "Please bind your phone first, the system automatically uses the phone for multi-factor authentication",
|
||||||
"Please save this recovery code. Once your device cannot provide an authentication code, you can reset mfa authentication by this recovery code": "Guarde este código de recuperação. Quando o seu dispositivo não puder fornecer um código de autenticação, você poderá redefinir a autenticação mfa usando este código de recuperação",
|
"Please save this recovery code. Once your device cannot provide an authentication code, you can reset mfa authentication by this recovery code": "Guarde este código de recuperação. Quando o seu dispositivo não puder fornecer um código de autenticação, você poderá redefinir a autenticação mfa usando este código de recuperação",
|
||||||
"Protect your account with Multi-factor authentication": "Proteja sua conta com autenticação de vários fatores",
|
"Protect your account with Multi-factor authentication": "Proteja sua conta com autenticação de vários fatores",
|
||||||
"Recovery code": "Código de recuperação",
|
"Recovery code": "Código de recuperação",
|
||||||
|
"Scan the QR code with your Authenticator App": "Scan the QR code with your Authenticator App",
|
||||||
"Set preferred": "Definir preferido",
|
"Set preferred": "Definir preferido",
|
||||||
"Setup": "Configuração",
|
"Setup": "Configuração",
|
||||||
|
"Use Authenticator App": "Use Authenticator App",
|
||||||
"Use Email": "Use Email",
|
"Use Email": "Use Email",
|
||||||
"Use SMS": "Use SMS",
|
"Use SMS": "Use SMS",
|
||||||
"Use SMS verification code": "Usar código de verificação SMS",
|
"Use SMS verification code": "Usar código de verificação SMS",
|
||||||
@ -568,6 +570,7 @@
|
|||||||
"Copy pricing page URL": "Sao chép URL trang bảng giá",
|
"Copy pricing page URL": "Sao chép URL trang bảng giá",
|
||||||
"Edit Pricing": "Edit Pricing",
|
"Edit Pricing": "Edit Pricing",
|
||||||
"Free": "Miễn phí",
|
"Free": "Miễn phí",
|
||||||
|
"Failed to get plans": "Falha ao obter planos",
|
||||||
"Getting started": "Bắt đầu",
|
"Getting started": "Bắt đầu",
|
||||||
"New Pricing": "New Pricing",
|
"New Pricing": "New Pricing",
|
||||||
"Trial duration": "Thời gian thử nghiệm",
|
"Trial duration": "Thời gian thử nghiệm",
|
||||||
|
@ -96,6 +96,7 @@
|
|||||||
"Signup items": "Элементы регистрации",
|
"Signup items": "Элементы регистрации",
|
||||||
"Signup items - Tooltip": "Элементы, которые пользователи должны заполнить при регистрации новых аккаунтов",
|
"Signup items - Tooltip": "Элементы, которые пользователи должны заполнить при регистрации новых аккаунтов",
|
||||||
"Signup page URL copied to clipboard successfully, please paste it into the incognito window or another browser": "Успешно скопирован URL страницы регистрации в буфер обмена, пожалуйста, вставьте его в режиме инкогнито или в другом браузере",
|
"Signup page URL copied to clipboard successfully, please paste it into the incognito window or another browser": "Успешно скопирован URL страницы регистрации в буфер обмена, пожалуйста, вставьте его в режиме инкогнито или в другом браузере",
|
||||||
|
"Tags - Tooltip": "Only users with the tag that is listed in the application tags can login",
|
||||||
"The application does not allow to sign up new account": "Приложение не позволяет зарегистрироваться новому аккаунту",
|
"The application does not allow to sign up new account": "Приложение не позволяет зарегистрироваться новому аккаунту",
|
||||||
"Token expire": "Срок действия токена истекает",
|
"Token expire": "Срок действия токена истекает",
|
||||||
"Token expire - Tooltip": "Время истечения токена доступа",
|
"Token expire - Tooltip": "Время истечения токена доступа",
|
||||||
@ -434,17 +435,18 @@
|
|||||||
"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",
|
||||||
"Multi-factor secret": "Multi-factor secret",
|
|
||||||
"Multi-factor secret - Tooltip": "Multi-factor secret - Tooltip",
|
|
||||||
"Multi-factor secret to clipboard successfully": "Multi-factor secret to clipboard successfully",
|
"Multi-factor secret to clipboard successfully": "Multi-factor secret to clipboard successfully",
|
||||||
|
"Or copy the secret to your Authenticator App": "Or copy the secret to your Authenticator App",
|
||||||
"Passcode": "Passcode",
|
"Passcode": "Passcode",
|
||||||
"Please bind your email first, the system will automatically uses the mail for multi-factor authentication": "Please bind your email first, the system will automatically uses the mail for multi-factor authentication",
|
"Please bind your email first, the system will automatically uses the mail for multi-factor authentication": "Please bind your email first, the system will automatically uses the mail for multi-factor authentication",
|
||||||
"Please bind your phone first, the system automatically uses the phone for multi-factor authentication": "Please bind your phone first, the system automatically uses the phone for multi-factor authentication",
|
"Please bind your phone first, the system automatically uses the phone for multi-factor authentication": "Please bind your phone first, the system automatically uses the phone for multi-factor authentication",
|
||||||
"Please save this recovery code. Once your device cannot provide an authentication code, you can reset mfa authentication by this recovery code": "Please save this recovery code. Once your device cannot provide an authentication code, you can reset mfa authentication by this recovery code",
|
"Please save this recovery code. Once your device cannot provide an authentication code, you can reset mfa authentication by this recovery code": "Please save this recovery code. Once your device cannot provide an authentication code, you can reset mfa authentication by this recovery code",
|
||||||
"Protect your account with Multi-factor authentication": "Protect your account with Multi-factor authentication",
|
"Protect your account with Multi-factor authentication": "Protect your account with Multi-factor authentication",
|
||||||
"Recovery code": "Recovery code",
|
"Recovery code": "Recovery code",
|
||||||
|
"Scan the QR code with your Authenticator App": "Scan the QR code with your Authenticator App",
|
||||||
"Set preferred": "Set preferred",
|
"Set preferred": "Set preferred",
|
||||||
"Setup": "Setup",
|
"Setup": "Setup",
|
||||||
|
"Use Authenticator App": "Use Authenticator App",
|
||||||
"Use Email": "Use Email",
|
"Use Email": "Use Email",
|
||||||
"Use SMS": "Use SMS",
|
"Use SMS": "Use SMS",
|
||||||
"Use SMS verification code": "Use SMS verification code",
|
"Use SMS verification code": "Use SMS verification code",
|
||||||
@ -568,6 +570,7 @@
|
|||||||
"Copy pricing page URL": "Скопировать URL прайс-листа",
|
"Copy pricing page URL": "Скопировать URL прайс-листа",
|
||||||
"Edit Pricing": "Edit Pricing",
|
"Edit Pricing": "Edit Pricing",
|
||||||
"Free": "Бесплатно",
|
"Free": "Бесплатно",
|
||||||
|
"Failed to get plans": "Не удалось получить планы",
|
||||||
"Getting started": "Выьрать план",
|
"Getting started": "Выьрать план",
|
||||||
"New Pricing": "New Pricing",
|
"New Pricing": "New Pricing",
|
||||||
"Trial duration": "Продолжительность пробного периода",
|
"Trial duration": "Продолжительность пробного периода",
|
||||||
|
@ -96,6 +96,7 @@
|
|||||||
"Signup items": "Các mục đăng ký",
|
"Signup items": "Các mục đăng ký",
|
||||||
"Signup items - Tooltip": "Các thông tin cần được người dùng điền khi đăng ký tài khoản mới",
|
"Signup items - Tooltip": "Các thông tin cần được người dùng điền khi đăng ký tài khoản mới",
|
||||||
"Signup page URL copied to clipboard successfully, please paste it into the incognito window or another browser": "Đã sao chép thành công đường dẫn trang đăng ký vào clipboard, vui lòng dán nó vào cửa sổ ẩn danh hoặc trình duyệt khác",
|
"Signup page URL copied to clipboard successfully, please paste it into the incognito window or another browser": "Đã sao chép thành công đường dẫn trang đăng ký vào clipboard, vui lòng dán nó vào cửa sổ ẩn danh hoặc trình duyệt khác",
|
||||||
|
"Tags - Tooltip": "Only users with the tag that is listed in the application tags can login",
|
||||||
"The application does not allow to sign up new account": "Ứng dụng không cho phép đăng ký tài khoản mới",
|
"The application does not allow to sign up new account": "Ứng dụng không cho phép đăng ký tài khoản mới",
|
||||||
"Token expire": "Mã thông báo hết hạn",
|
"Token expire": "Mã thông báo hết hạn",
|
||||||
"Token expire - Tooltip": "Thời gian hết hạn của mã truy cập",
|
"Token expire - Tooltip": "Thời gian hết hạn của mã truy cập",
|
||||||
@ -434,17 +435,18 @@
|
|||||||
"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",
|
||||||
"Multi-factor secret": "Multi-factor secret",
|
|
||||||
"Multi-factor secret - Tooltip": "Multi-factor secret - Tooltip",
|
|
||||||
"Multi-factor secret to clipboard successfully": "Multi-factor secret to clipboard successfully",
|
"Multi-factor secret to clipboard successfully": "Multi-factor secret to clipboard successfully",
|
||||||
|
"Or copy the secret to your Authenticator App": "Or copy the secret to your Authenticator App",
|
||||||
"Passcode": "Passcode",
|
"Passcode": "Passcode",
|
||||||
"Please bind your email first, the system will automatically uses the mail for multi-factor authentication": "Please bind your email first, the system will automatically uses the mail for multi-factor authentication",
|
"Please bind your email first, the system will automatically uses the mail for multi-factor authentication": "Please bind your email first, the system will automatically uses the mail for multi-factor authentication",
|
||||||
"Please bind your phone first, the system automatically uses the phone for multi-factor authentication": "Please bind your phone first, the system automatically uses the phone for multi-factor authentication",
|
"Please bind your phone first, the system automatically uses the phone for multi-factor authentication": "Please bind your phone first, the system automatically uses the phone for multi-factor authentication",
|
||||||
"Please save this recovery code. Once your device cannot provide an authentication code, you can reset mfa authentication by this recovery code": "Please save this recovery code. Once your device cannot provide an authentication code, you can reset mfa authentication by this recovery code",
|
"Please save this recovery code. Once your device cannot provide an authentication code, you can reset mfa authentication by this recovery code": "Please save this recovery code. Once your device cannot provide an authentication code, you can reset mfa authentication by this recovery code",
|
||||||
"Protect your account with Multi-factor authentication": "Protect your account with Multi-factor authentication",
|
"Protect your account with Multi-factor authentication": "Protect your account with Multi-factor authentication",
|
||||||
"Recovery code": "Recovery code",
|
"Recovery code": "Recovery code",
|
||||||
|
"Scan the QR code with your Authenticator App": "Scan the QR code with your Authenticator App",
|
||||||
"Set preferred": "Set preferred",
|
"Set preferred": "Set preferred",
|
||||||
"Setup": "Setup",
|
"Setup": "Setup",
|
||||||
|
"Use Authenticator App": "Use Authenticator App",
|
||||||
"Use Email": "Use Email",
|
"Use Email": "Use Email",
|
||||||
"Use SMS": "Use SMS",
|
"Use SMS": "Use SMS",
|
||||||
"Use SMS verification code": "Use SMS verification code",
|
"Use SMS verification code": "Use SMS verification code",
|
||||||
@ -568,6 +570,7 @@
|
|||||||
"Copy pricing page URL": "Sao chép URL trang bảng giá",
|
"Copy pricing page URL": "Sao chép URL trang bảng giá",
|
||||||
"Edit Pricing": "Edit Pricing",
|
"Edit Pricing": "Edit Pricing",
|
||||||
"Free": "Miễn phí",
|
"Free": "Miễn phí",
|
||||||
|
"Failed to get plans": "Không thể lấy được các kế hoạch",
|
||||||
"Getting started": "Bắt đầu",
|
"Getting started": "Bắt đầu",
|
||||||
"New Pricing": "New Pricing",
|
"New Pricing": "New Pricing",
|
||||||
"Trial duration": "Thời gian thử nghiệm",
|
"Trial duration": "Thời gian thử nghiệm",
|
||||||
|
@ -96,6 +96,7 @@
|
|||||||
"Signup items": "注册项",
|
"Signup items": "注册项",
|
||||||
"Signup items - Tooltip": "注册用户注册时需要填写的项目",
|
"Signup items - Tooltip": "注册用户注册时需要填写的项目",
|
||||||
"Signup page URL copied to clipboard successfully, please paste it into the incognito window or another browser": "注册页面URL已成功复制到剪贴板,请粘贴到当前浏览器的隐身模式窗口或另一个浏览器访问",
|
"Signup page URL copied to clipboard successfully, please paste it into the incognito window or another browser": "注册页面URL已成功复制到剪贴板,请粘贴到当前浏览器的隐身模式窗口或另一个浏览器访问",
|
||||||
|
"Tags - Tooltip": "用户的标签在应用的标签集合中时,用户才可以登录该应用",
|
||||||
"The application does not allow to sign up new account": "该应用不允许注册新账户",
|
"The application does not allow to sign up new account": "该应用不允许注册新账户",
|
||||||
"Token expire": "Access Token过期",
|
"Token expire": "Access Token过期",
|
||||||
"Token expire - Tooltip": "Access Token过期时间",
|
"Token expire - Tooltip": "Access Token过期时间",
|
||||||
@ -434,17 +435,18 @@
|
|||||||
"Multi-factor methods": "多因素认证方式",
|
"Multi-factor methods": "多因素认证方式",
|
||||||
"Multi-factor recover": "重置多因素认证",
|
"Multi-factor recover": "重置多因素认证",
|
||||||
"Multi-factor recover description": "如果您无法访问您的设备,输入您的多因素认证恢复代码来确认您的身份",
|
"Multi-factor recover description": "如果您无法访问您的设备,输入您的多因素认证恢复代码来确认您的身份",
|
||||||
"Multi-factor secret": "多因素密钥",
|
|
||||||
"Multi-factor secret - Tooltip": "多因素密钥 - Tooltip",
|
|
||||||
"Multi-factor secret to clipboard successfully": "多因素密钥已复制到剪贴板",
|
"Multi-factor secret to clipboard successfully": "多因素密钥已复制到剪贴板",
|
||||||
|
"Or copy the secret to your Authenticator App": "或者将这个密钥复制到你的身份验证应用中",
|
||||||
"Passcode": "认证码",
|
"Passcode": "认证码",
|
||||||
"Please bind your email first, the system will automatically uses the mail for multi-factor authentication": "请先绑定邮箱,之后会自动使用该邮箱作为多因素认证的方式",
|
"Please bind your email first, the system will automatically uses the mail for multi-factor authentication": "请先绑定邮箱,之后会自动使用该邮箱作为多因素认证的方式",
|
||||||
"Please bind your phone first, the system automatically uses the phone for multi-factor authentication": "请先绑定手机号,之后会自动使用该手机号作为多因素认证的方式",
|
"Please bind your phone first, the system automatically uses the phone for multi-factor authentication": "请先绑定手机号,之后会自动使用该手机号作为多因素认证的方式",
|
||||||
"Please save this recovery code. Once your device cannot provide an authentication code, you can reset mfa authentication by this recovery code": "请保存此恢复代码。一旦您的设备无法提供身份验证码,您可以通过此恢复码重置多因素认证",
|
"Please save this recovery code. Once your device cannot provide an authentication code, you can reset mfa authentication by this recovery code": "请保存此恢复代码。一旦您的设备无法提供身份验证码,您可以通过此恢复码重置多因素认证",
|
||||||
"Protect your account with Multi-factor authentication": "通过多因素认证保护您的帐户",
|
"Protect your account with Multi-factor authentication": "通过多因素认证保护您的帐户",
|
||||||
"Recovery code": "恢复码",
|
"Recovery code": "恢复码",
|
||||||
|
"Scan the QR code with your Authenticator App": "用你的身份验证应用扫描二维码",
|
||||||
"Set preferred": "设为首选",
|
"Set preferred": "设为首选",
|
||||||
"Setup": "设置",
|
"Setup": "设置",
|
||||||
|
"Use Authenticator App": "使用身份验证应用",
|
||||||
"Use Email": "使用电子邮件",
|
"Use Email": "使用电子邮件",
|
||||||
"Use SMS": "使用短信",
|
"Use SMS": "使用短信",
|
||||||
"Use SMS verification code": "使用手机或电子邮件发送验证码认证",
|
"Use SMS verification code": "使用手机或电子邮件发送验证码认证",
|
||||||
@ -568,6 +570,7 @@
|
|||||||
"Copy pricing page URL": "复制定价页面链接",
|
"Copy pricing page URL": "复制定价页面链接",
|
||||||
"Edit Pricing": "编辑定价",
|
"Edit Pricing": "编辑定价",
|
||||||
"Free": "免费",
|
"Free": "免费",
|
||||||
|
"Failed to get plans": "未能获取计划",
|
||||||
"Getting started": "开始使用",
|
"Getting started": "开始使用",
|
||||||
"New Pricing": "添加定价",
|
"New Pricing": "添加定价",
|
||||||
"Trial duration": "试用期时长",
|
"Trial duration": "试用期时长",
|
||||||
|
@ -64,6 +64,11 @@ class PricingPage extends React.Component {
|
|||||||
|
|
||||||
Promise.all(plans)
|
Promise.all(plans)
|
||||||
.then(results => {
|
.then(results => {
|
||||||
|
const hasError = results.some(result => result.status === "error");
|
||||||
|
if (hasError) {
|
||||||
|
Setting.showMessage("error", `${i18next.t("Failed to get plans")}`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
this.setState({
|
this.setState({
|
||||||
plans: results,
|
plans: results,
|
||||||
loading: false,
|
loading: false,
|
||||||
@ -81,6 +86,11 @@ class PricingPage extends React.Component {
|
|||||||
|
|
||||||
PricingBackend.getPricing(this.state.owner, pricingName)
|
PricingBackend.getPricing(this.state.owner, pricingName)
|
||||||
.then((result) => {
|
.then((result) => {
|
||||||
|
if (result.status === "error") {
|
||||||
|
Setting.showMessage("error", result.msg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
loading: false,
|
loading: false,
|
||||||
pricing: result,
|
pricing: result,
|
||||||
|
3021
web/yarn.lock
3021
web/yarn.lock
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user