mirror of
https://github.com/casdoor/casdoor.git
synced 2025-08-04 03:50:30 +08:00
Compare commits
37 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
0d48da24dc | ||
![]() |
de9eeaa1ef | ||
![]() |
ae6e35ee73 | ||
![]() |
a58df645bf | ||
![]() |
68417a2d7a | ||
![]() |
9511fae9d9 | ||
![]() |
347d3d2b53 | ||
![]() |
6edfc08b28 | ||
![]() |
bc1c4d32f0 | ||
![]() |
96250aa70a | ||
![]() |
3d4ca1adb1 | ||
![]() |
ba97458edd | ||
![]() |
855259c6e7 | ||
![]() |
28297e06f7 | ||
![]() |
f3aed0b6a8 | ||
![]() |
35e1f8538e | ||
![]() |
30a14ff54a | ||
![]() |
1ab7a54133 | ||
![]() |
0e2dad35f3 | ||
![]() |
d31077a510 | ||
![]() |
eee9b8b9fe | ||
![]() |
91cb5f393a | ||
![]() |
807aea5ec7 | ||
![]() |
1c42b6e395 | ||
![]() |
49a73f8138 | ||
![]() |
55784c68a3 | ||
![]() |
8080b10b3b | ||
![]() |
cd7589775c | ||
![]() |
0a8c2a35fe | ||
![]() |
d1e734e4ce | ||
![]() |
68f032b54d | ||
![]() |
1780620ef4 | ||
![]() |
5c968ed1ce | ||
![]() |
4016fc0f65 | ||
![]() |
463b3ad976 | ||
![]() |
b817a55f9f | ||
![]() |
2c2ddfbb92 |
@@ -37,8 +37,8 @@
|
|||||||
<a href="https://crowdin.com/project/casdoor-site">
|
<a href="https://crowdin.com/project/casdoor-site">
|
||||||
<img alt="Crowdin" src="https://badges.crowdin.net/casdoor-site/localized.svg">
|
<img alt="Crowdin" src="https://badges.crowdin.net/casdoor-site/localized.svg">
|
||||||
</a>
|
</a>
|
||||||
<a href="https://gitter.im/casbin/casdoor">
|
<a href="https://discord.gg/5rPsrAzK7S">
|
||||||
<img alt="Gitter" src="https://badges.gitter.im/casbin/casdoor.svg">
|
<img alt="Discord" src="https://img.shields.io/discord/1022748306096537660?style=flat-square&logo=discord&label=discord&color=5865F2">
|
||||||
</a>
|
</a>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
@@ -71,7 +71,7 @@ https://casdoor.org/docs/category/integrations
|
|||||||
|
|
||||||
## How to contact?
|
## How to contact?
|
||||||
|
|
||||||
- Gitter: https://gitter.im/casbin/casdoor
|
- Discord: https://discord.gg/5rPsrAzK7S
|
||||||
- Forum: https://forum.casbin.com
|
- Forum: https://forum.casbin.com
|
||||||
- Contact: https://tawk.to/chat/623352fea34c2456412b8c51/1fuc7od6e
|
- Contact: https://tawk.to/chat/623352fea34c2456412b8c51/1fuc7od6e
|
||||||
|
|
||||||
|
@@ -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,10 +69,13 @@ func (c *ApiController) HandleLoggedIn(application *object.Application, user *ob
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if form.Password != "" && user.IsMfaEnabled() {
|
// check user's tag
|
||||||
c.setMfaSessionData(&object.MfaSessionData{UserId: userId})
|
if !user.IsGlobalAdmin && !user.IsAdmin && len(application.Tags) > 0 {
|
||||||
resp = &Response{Status: object.NextMfa, Data: user.GetPreferredMfaProps(true)}
|
// only users with the tag that is listed in the application tags can login
|
||||||
return
|
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.Type == ResponseTypeLogin {
|
if form.Type == ResponseTypeLogin {
|
||||||
@@ -238,7 +241,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{}
|
||||||
@@ -344,17 +347,26 @@ func (c *ApiController) Login() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
resp = c.HandleLoggedIn(application, user, &authForm)
|
|
||||||
|
|
||||||
organization, err := object.GetOrganizationByUser(user)
|
organization, err := object.GetOrganizationByUser(user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.ResponseError(err.Error())
|
c.ResponseError(err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
if user != nil && organization.HasRequiredMfa() && !user.IsMfaEnabled() {
|
if object.IsNeedPromptMfa(organization, user) {
|
||||||
resp.Msg = object.RequiredMfa
|
// The prompt page needs the user to be signed in
|
||||||
|
c.SetSessionUsername(user.GetId())
|
||||||
|
c.ResponseOk(object.RequiredMfa)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if user.IsMfaEnabled() {
|
||||||
|
c.setMfaUserSession(user.GetId())
|
||||||
|
c.ResponseOk(object.NextMfa, user.GetPreferredMfaProps(true))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
resp = c.HandleLoggedIn(application, user, &authForm)
|
||||||
|
|
||||||
record := object.NewRecord(c.Ctx)
|
record := object.NewRecord(c.Ctx)
|
||||||
record.Organization = application.Organization
|
record.Organization = application.Organization
|
||||||
record.User = user.Name
|
record.User = user.Name
|
||||||
@@ -407,15 +419,8 @@ func (c *ApiController) Login() {
|
|||||||
}
|
}
|
||||||
} else if provider.Category == "OAuth" {
|
} else if provider.Category == "OAuth" {
|
||||||
// OAuth
|
// OAuth
|
||||||
|
idpInfo := object.FromProviderToIdpInfo(c.Ctx, provider)
|
||||||
clientId := provider.ClientId
|
idProvider := idp.GetIdProvider(idpInfo, authForm.RedirectUri)
|
||||||
clientSecret := provider.ClientSecret
|
|
||||||
if provider.Type == "WeChat" && strings.Contains(c.Ctx.Request.UserAgent(), "MicroMessenger") {
|
|
||||||
clientId = provider.ClientId2
|
|
||||||
clientSecret = provider.ClientSecret2
|
|
||||||
}
|
|
||||||
|
|
||||||
idProvider := idp.GetIdProvider(provider.Type, provider.SubType, clientId, clientSecret, provider.AppId, authForm.RedirectUri, provider.Domain, provider.CustomAuthUrl, provider.CustomTokenUrl, provider.CustomUserInfoUrl)
|
|
||||||
if idProvider == nil {
|
if idProvider == nil {
|
||||||
c.ResponseError(fmt.Sprintf(c.T("storage:The provider type: %s is not supported"), provider.Type))
|
c.ResponseError(fmt.Sprintf(c.T("storage:The provider type: %s is not supported"), provider.Type))
|
||||||
return
|
return
|
||||||
@@ -647,13 +652,16 @@ func (c *ApiController) Login() {
|
|||||||
resp = &Response{Status: "error", Msg: "Failed to link user account", Data: isLinked}
|
resp = &Response{Status: "error", Msg: "Failed to link user account", Data: isLinked}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if c.getMfaSessionData() != nil {
|
} else if c.getMfaUserSession() != "" {
|
||||||
mfaSession := c.getMfaSessionData()
|
user, err := object.GetUser(c.getMfaUserSession())
|
||||||
user, err := object.GetUser(mfaSession.UserId)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.ResponseError(err.Error())
|
c.ResponseError(err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if user == nil {
|
||||||
|
c.ResponseError("expired user session")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if authForm.Passcode != "" {
|
if authForm.Passcode != "" {
|
||||||
mfaUtil := object.GetMfaUtil(authForm.MfaType, user.GetPreferredMfaProps(false))
|
mfaUtil := object.GetMfaUtil(authForm.MfaType, user.GetPreferredMfaProps(false))
|
||||||
@@ -667,13 +675,15 @@ func (c *ApiController) Login() {
|
|||||||
c.ResponseError(err.Error())
|
c.ResponseError(err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
} else if authForm.RecoveryCode != "" {
|
||||||
if authForm.RecoveryCode != "" {
|
|
||||||
err = object.MfaRecover(user, authForm.RecoveryCode)
|
err = object.MfaRecover(user, authForm.RecoveryCode)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.ResponseError(err.Error())
|
c.ResponseError(err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
c.ResponseError("missing passcode or recovery code")
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
application, err := object.GetApplication(fmt.Sprintf("admin/%s", authForm.Application))
|
application, err := object.GetApplication(fmt.Sprintf("admin/%s", authForm.Application))
|
||||||
@@ -688,6 +698,7 @@ func (c *ApiController) Login() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
resp = c.HandleLoggedIn(application, user, &authForm)
|
resp = c.HandleLoggedIn(application, user, &authForm)
|
||||||
|
c.setMfaUserSession("")
|
||||||
|
|
||||||
record := object.NewRecord(c.Ctx)
|
record := object.NewRecord(c.Ctx)
|
||||||
record.Organization = application.Organization
|
record.Organization = application.Organization
|
||||||
@@ -756,7 +767,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 +778,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
|
||||||
@@ -176,24 +178,16 @@ func (c *ApiController) SetSessionData(s *SessionData) {
|
|||||||
c.SetSession("SessionData", util.StructToJson(s))
|
c.SetSession("SessionData", util.StructToJson(s))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ApiController) setMfaSessionData(data *object.MfaSessionData) {
|
func (c *ApiController) setMfaUserSession(userId string) {
|
||||||
if data == nil {
|
c.SetSession(object.MfaSessionUserId, userId)
|
||||||
c.SetSession(object.MfaSessionUserId, nil)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
c.SetSession(object.MfaSessionUserId, data.UserId)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ApiController) getMfaSessionData() *object.MfaSessionData {
|
func (c *ApiController) getMfaUserSession() string {
|
||||||
userId := c.GetSession(object.MfaSessionUserId)
|
userId := c.Ctx.Input.CruSession.Get(object.MfaSessionUserId)
|
||||||
if userId == nil {
|
if userId == nil {
|
||||||
return nil
|
return ""
|
||||||
}
|
}
|
||||||
|
return userId.(string)
|
||||||
data := &object.MfaSessionData{
|
|
||||||
UserId: userId.(string),
|
|
||||||
}
|
|
||||||
return data
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ApiController) setExpireForSession() {
|
func (c *ApiController) setExpireForSession() {
|
||||||
|
@@ -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
|
||||||
|
@@ -44,14 +44,26 @@ func (c *ApiController) Enforce() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if permissionId != "" {
|
if permissionId != "" {
|
||||||
enforceResult, err := object.Enforce(permissionId, &request)
|
permission, err := object.GetPermission(permissionId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.ResponseError(err.Error())
|
c.ResponseError(err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
res := []bool{}
|
res := []bool{}
|
||||||
res = append(res, enforceResult)
|
|
||||||
|
if permission == nil {
|
||||||
|
res = append(res, false)
|
||||||
|
} else {
|
||||||
|
enforceResult, err := object.Enforce(permission, &request)
|
||||||
|
if err != nil {
|
||||||
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
res = append(res, enforceResult)
|
||||||
|
}
|
||||||
|
|
||||||
c.ResponseOk(res)
|
c.ResponseOk(res)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -76,8 +88,16 @@ func (c *ApiController) Enforce() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
res := []bool{}
|
res := []bool{}
|
||||||
for _, permission := range permissions {
|
|
||||||
enforceResult, err := object.Enforce(permission.GetId(), &request)
|
listPermissionIdMap := object.GroupPermissionsByModelAdapter(permissions)
|
||||||
|
for _, permissionIds := range listPermissionIdMap {
|
||||||
|
firstPermission, err := object.GetPermission(permissionIds[0])
|
||||||
|
if err != nil {
|
||||||
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
enforceResult, err := object.Enforce(firstPermission, &request, permissionIds...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.ResponseError(err.Error())
|
c.ResponseError(err.Error())
|
||||||
return
|
return
|
||||||
@@ -85,6 +105,7 @@ func (c *ApiController) Enforce() {
|
|||||||
|
|
||||||
res = append(res, enforceResult)
|
res = append(res, enforceResult)
|
||||||
}
|
}
|
||||||
|
|
||||||
c.ResponseOk(res)
|
c.ResponseOk(res)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -109,14 +130,32 @@ func (c *ApiController) BatchEnforce() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if permissionId != "" {
|
if permissionId != "" {
|
||||||
enforceResult, err := object.BatchEnforce(permissionId, &requests)
|
permission, err := object.GetPermission(permissionId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.ResponseError(err.Error())
|
c.ResponseError(err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
res := [][]bool{}
|
res := [][]bool{}
|
||||||
res = append(res, enforceResult)
|
|
||||||
|
if permission == nil {
|
||||||
|
l := len(requests)
|
||||||
|
resRequest := make([]bool, l)
|
||||||
|
for i := 0; i < l; i++ {
|
||||||
|
resRequest[i] = false
|
||||||
|
}
|
||||||
|
|
||||||
|
res = append(res, resRequest)
|
||||||
|
} else {
|
||||||
|
enforceResult, err := object.BatchEnforce(permission, &requests)
|
||||||
|
if err != nil {
|
||||||
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
res = append(res, enforceResult)
|
||||||
|
}
|
||||||
|
|
||||||
c.ResponseOk(res)
|
c.ResponseOk(res)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -135,8 +174,16 @@ func (c *ApiController) BatchEnforce() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
res := [][]bool{}
|
res := [][]bool{}
|
||||||
for _, permission := range permissions {
|
|
||||||
enforceResult, err := object.BatchEnforce(permission.GetId(), &requests)
|
listPermissionIdMap := object.GroupPermissionsByModelAdapter(permissions)
|
||||||
|
for _, permissionIds := range listPermissionIdMap {
|
||||||
|
firstPermission, err := object.GetPermission(permissionIds[0])
|
||||||
|
if err != nil {
|
||||||
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
enforceResult, err := object.BatchEnforce(firstPermission, &requests, permissionIds...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.ResponseError(err.Error())
|
c.ResponseError(err.Error())
|
||||||
return
|
return
|
||||||
@@ -144,6 +191,7 @@ func (c *ApiController) BatchEnforce() {
|
|||||||
|
|
||||||
res = append(res, enforceResult)
|
res = append(res, enforceResult)
|
||||||
}
|
}
|
||||||
|
|
||||||
c.ResponseOk(res)
|
c.ResponseOk(res)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -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
|
||||||
|
@@ -37,17 +37,27 @@ func (c *ApiController) GetOrganizations() {
|
|||||||
value := c.Input().Get("value")
|
value := c.Input().Get("value")
|
||||||
sortField := c.Input().Get("sortField")
|
sortField := c.Input().Get("sortField")
|
||||||
sortOrder := c.Input().Get("sortOrder")
|
sortOrder := c.Input().Get("sortOrder")
|
||||||
|
organizationName := c.Input().Get("organizationName")
|
||||||
|
|
||||||
|
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 {
|
||||||
@@ -64,7 +74,7 @@ func (c *ApiController) GetOrganizations() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
paginator := pagination.SetPaginator(c.Ctx, limit, count)
|
paginator := pagination.SetPaginator(c.Ctx, limit, count)
|
||||||
organizations, err := object.GetMaskedOrganizations(object.GetPaginationOrganizations(owner, paginator.Offset(), limit, field, value, sortField, sortOrder))
|
organizations, err := object.GetMaskedOrganizations(object.GetPaginationOrganizations(owner, organizationName, paginator.Offset(), limit, field, value, sortField, sortOrder))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.ResponseError(err.Error())
|
c.ResponseError(err.Error())
|
||||||
return
|
return
|
||||||
|
@@ -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))
|
||||||
|
@@ -42,17 +42,22 @@ func (c *ApiController) GetRecords() {
|
|||||||
value := c.Input().Get("value")
|
value := c.Input().Get("value")
|
||||||
sortField := c.Input().Get("sortField")
|
sortField := c.Input().Get("sortField")
|
||||||
sortOrder := c.Input().Get("sortOrder")
|
sortOrder := c.Input().Get("sortOrder")
|
||||||
|
organizationName := c.Input().Get("organizationName")
|
||||||
|
|
||||||
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
|
||||||
c.ServeJSON()
|
c.ServeJSON()
|
||||||
} else {
|
} else {
|
||||||
limit := util.ParseInt(limit)
|
limit := util.ParseInt(limit)
|
||||||
|
if c.IsGlobalAdmin() && organizationName != "" {
|
||||||
|
organization = organizationName
|
||||||
|
}
|
||||||
filterRecord := &object.Record{Organization: organization}
|
filterRecord := &object.Record{Organization: organization}
|
||||||
count, err := object.GetRecordCount(field, value, filterRecord)
|
count, err := object.GetRecordCount(field, value, filterRecord)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -84,12 +89,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
|
||||||
|
@@ -29,9 +29,19 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// GetResources
|
// GetResources
|
||||||
// @router /get-resources [get]
|
|
||||||
// @Tag Resource API
|
// @Tag Resource API
|
||||||
// @Title GetResources
|
// @Title GetResources
|
||||||
|
// @Description get resources
|
||||||
|
// @Param owner query string true "Owner"
|
||||||
|
// @Param user query string true "User"
|
||||||
|
// @Param pageSize query integer false "Page Size"
|
||||||
|
// @Param p query integer false "Page Number"
|
||||||
|
// @Param field query string false "Field"
|
||||||
|
// @Param value query string false "Value"
|
||||||
|
// @Param sortField query string false "Sort Field"
|
||||||
|
// @Param sortOrder query string false "Sort Order"
|
||||||
|
// @Success 200 {array} object.Resource The Response object
|
||||||
|
// @router /get-resources [get]
|
||||||
func (c *ApiController) GetResources() {
|
func (c *ApiController) GetResources() {
|
||||||
owner := c.Input().Get("owner")
|
owner := c.Input().Get("owner")
|
||||||
user := c.Input().Get("user")
|
user := c.Input().Get("user")
|
||||||
@@ -53,7 +63,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
|
||||||
@@ -80,13 +91,17 @@ func (c *ApiController) GetResources() {
|
|||||||
// GetResource
|
// GetResource
|
||||||
// @Tag Resource API
|
// @Tag Resource API
|
||||||
// @Title GetResource
|
// @Title GetResource
|
||||||
|
// @Description get resource
|
||||||
|
// @Param id query string true "The id ( owner/name ) of resource"
|
||||||
|
// @Success 200 {object} object.Resource The Response object
|
||||||
// @router /get-resource [get]
|
// @router /get-resource [get]
|
||||||
func (c *ApiController) GetResource() {
|
func (c *ApiController) GetResource() {
|
||||||
id := c.Input().Get("id")
|
id := c.Input().Get("id")
|
||||||
|
|
||||||
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
|
||||||
@@ -96,6 +111,10 @@ func (c *ApiController) GetResource() {
|
|||||||
// UpdateResource
|
// UpdateResource
|
||||||
// @Tag Resource API
|
// @Tag Resource API
|
||||||
// @Title UpdateResource
|
// @Title UpdateResource
|
||||||
|
// @Description get resource
|
||||||
|
// @Param id query string true "The id ( owner/name ) of resource"
|
||||||
|
// @Param resource body object.Resource true "The resource object"
|
||||||
|
// @Success 200 {object} controllers.Response Success or error
|
||||||
// @router /update-resource [post]
|
// @router /update-resource [post]
|
||||||
func (c *ApiController) UpdateResource() {
|
func (c *ApiController) UpdateResource() {
|
||||||
id := c.Input().Get("id")
|
id := c.Input().Get("id")
|
||||||
@@ -114,6 +133,8 @@ func (c *ApiController) UpdateResource() {
|
|||||||
// AddResource
|
// AddResource
|
||||||
// @Tag Resource API
|
// @Tag Resource API
|
||||||
// @Title AddResource
|
// @Title AddResource
|
||||||
|
// @Param resource body object.Resource true "Resource object"
|
||||||
|
// @Success 200 {object} controllers.Response Success or error
|
||||||
// @router /add-resource [post]
|
// @router /add-resource [post]
|
||||||
func (c *ApiController) AddResource() {
|
func (c *ApiController) AddResource() {
|
||||||
var resource object.Resource
|
var resource object.Resource
|
||||||
@@ -130,6 +151,8 @@ func (c *ApiController) AddResource() {
|
|||||||
// DeleteResource
|
// DeleteResource
|
||||||
// @Tag Resource API
|
// @Tag Resource API
|
||||||
// @Title DeleteResource
|
// @Title DeleteResource
|
||||||
|
// @Param resource body object.Resource true "Resource object"
|
||||||
|
// @Success 200 {object} controllers.Response Success or error
|
||||||
// @router /delete-resource [post]
|
// @router /delete-resource [post]
|
||||||
func (c *ApiController) DeleteResource() {
|
func (c *ApiController) DeleteResource() {
|
||||||
var resource object.Resource
|
var resource object.Resource
|
||||||
@@ -158,6 +181,16 @@ func (c *ApiController) DeleteResource() {
|
|||||||
// UploadResource
|
// UploadResource
|
||||||
// @Tag Resource API
|
// @Tag Resource API
|
||||||
// @Title UploadResource
|
// @Title UploadResource
|
||||||
|
// @Param owner query string true "Owner"
|
||||||
|
// @Param user query string true "User"
|
||||||
|
// @Param application query string true "Application"
|
||||||
|
// @Param tag query string false "Tag"
|
||||||
|
// @Param parent query string false "Parent"
|
||||||
|
// @Param fullFilePath query string true "Full File Path"
|
||||||
|
// @Param createdTime query string false "Created Time"
|
||||||
|
// @Param description query string false "Description"
|
||||||
|
// @Param file formData file true "Resource file"
|
||||||
|
// @Success 200 {object} object.Resource FileUrl, objectKey
|
||||||
// @router /upload-resource [post]
|
// @router /upload-resource [post]
|
||||||
func (c *ApiController) UploadResource() {
|
func (c *ApiController) UploadResource() {
|
||||||
owner := c.Input().Get("owner")
|
owner := c.Input().Get("owner")
|
||||||
@@ -196,16 +229,16 @@ func (c *ApiController) UploadResource() {
|
|||||||
|
|
||||||
fileType := "unknown"
|
fileType := "unknown"
|
||||||
contentType := header.Header.Get("Content-Type")
|
contentType := header.Header.Get("Content-Type")
|
||||||
fileType, _ = util.GetOwnerAndNameFromId(contentType)
|
fileType, _ = util.GetOwnerAndNameFromIdNoCheck(contentType + "/")
|
||||||
|
|
||||||
if fileType != "image" && fileType != "video" {
|
if fileType != "image" && fileType != "video" {
|
||||||
ext := filepath.Ext(filename)
|
ext := filepath.Ext(filename)
|
||||||
mimeType := mime.TypeByExtension(ext)
|
mimeType := mime.TypeByExtension(ext)
|
||||||
fileType, _ = util.GetOwnerAndNameFromId(mimeType)
|
fileType, _ = util.GetOwnerAndNameFromIdNoCheck(mimeType + "/")
|
||||||
}
|
}
|
||||||
|
|
||||||
fullFilePath = object.GetTruncatedPath(provider, fullFilePath, 175)
|
fullFilePath = object.GetTruncatedPath(provider, fullFilePath, 175)
|
||||||
if tag != "avatar" && tag != "termsOfUse" {
|
if tag != "avatar" && tag != "termsOfUse" && !strings.HasPrefix(tag, "idCard") {
|
||||||
ext := filepath.Ext(filepath.Base(fullFilePath))
|
ext := filepath.Ext(filepath.Base(fullFilePath))
|
||||||
index := len(fullFilePath) - len(ext)
|
index := len(fullFilePath) - len(ext)
|
||||||
for i := 1; ; i++ {
|
for i := 1; ; i++ {
|
||||||
@@ -292,7 +325,7 @@ func (c *ApiController) UploadResource() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
_, applicationId := util.GetOwnerAndNameFromIdNoCheck(strings.TrimRight(fullFilePath, ".html"))
|
_, applicationId := util.GetOwnerAndNameFromIdNoCheck(strings.TrimSuffix(fullFilePath, ".html"))
|
||||||
applicationObj, err := object.GetApplication(applicationId)
|
applicationObj, err := object.GetApplication(applicationId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.ResponseError(err.Error())
|
c.ResponseError(err.Error())
|
||||||
@@ -305,6 +338,25 @@ func (c *ApiController) UploadResource() {
|
|||||||
c.ResponseError(err.Error())
|
c.ResponseError(err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
case "idCardFront", "idCardBack", "idCardWithPerson":
|
||||||
|
user, err := object.GetUserNoCheck(util.GetId(owner, username))
|
||||||
|
if err != nil {
|
||||||
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if user == nil {
|
||||||
|
c.ResponseError(c.T("resource:User is nil for tag: avatar"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
user.Properties[tag] = fileUrl
|
||||||
|
user.Properties["isIdCardVerified"] = "false"
|
||||||
|
_, err = object.UpdateUser(user.GetId(), user, []string{"properties"}, false)
|
||||||
|
if err != nil {
|
||||||
|
c.ResponseError(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
c.ResponseOk(fileUrl, objectKey)
|
c.ResponseOk(fileUrl, objectKey)
|
||||||
|
@@ -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 {
|
||||||
@@ -319,7 +325,7 @@ func (c *ApiController) IntrospectToken() {
|
|||||||
Sub: jwtToken.Subject,
|
Sub: jwtToken.Subject,
|
||||||
Aud: jwtToken.Audience,
|
Aud: jwtToken.Audience,
|
||||||
Iss: jwtToken.Issuer,
|
Iss: jwtToken.Issuer,
|
||||||
Jti: jwtToken.Id,
|
Jti: jwtToken.ID,
|
||||||
}
|
}
|
||||||
c.ServeJSON()
|
c.ServeJSON()
|
||||||
}
|
}
|
||||||
|
@@ -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
|
||||||
@@ -416,6 +423,7 @@ func (c *ApiController) SetPassword() {
|
|||||||
|
|
||||||
requestUserId := c.GetSessionUsername()
|
requestUserId := c.GetSessionUsername()
|
||||||
if requestUserId == "" && code == "" {
|
if requestUserId == "" && code == "" {
|
||||||
|
c.ResponseError(c.T("general:Please login first"), "Please login first")
|
||||||
return
|
return
|
||||||
} else if code == "" {
|
} else if code == "" {
|
||||||
hasPermission, err := object.CheckUserPermission(requestUserId, userId, true, c.GetAcceptLanguage())
|
hasPermission, err := object.CheckUserPermission(requestUserId, userId, true, c.GetAcceptLanguage())
|
||||||
@@ -425,7 +433,7 @@ func (c *ApiController) SetPassword() {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if code != c.GetSession("verifiedCode") {
|
if code != c.GetSession("verifiedCode") {
|
||||||
c.ResponseError("")
|
c.ResponseError(c.T("general:Missing parameter"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
c.SetSession("verifiedCode", "")
|
c.SetSession("verifiedCode", "")
|
||||||
@@ -497,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 {
|
||||||
|
@@ -93,10 +93,9 @@ func (c *ApiController) SendVerificationCode() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// mfaSessionData != nil, means method is MfaAuthVerification
|
// mfaUserSession != "", means method is MfaAuthVerification
|
||||||
if mfaSessionData := c.getMfaSessionData(); mfaSessionData != nil {
|
if mfaUserSession := c.getMfaUserSession(); mfaUserSession != "" {
|
||||||
user, err = object.GetUser(mfaSessionData.UserId)
|
user, err = object.GetUser(mfaUserSession)
|
||||||
c.setMfaSessionData(nil)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.ResponseError(err.Error())
|
c.ResponseError(err.Error())
|
||||||
return
|
return
|
||||||
@@ -134,6 +133,8 @@ func (c *ApiController) SendVerificationCode() {
|
|||||||
if user != nil && util.GetMaskedEmail(mfaProps.Secret) == vform.Dest {
|
if user != nil && util.GetMaskedEmail(mfaProps.Secret) == vform.Dest {
|
||||||
vform.Dest = mfaProps.Secret
|
vform.Dest = mfaProps.Secret
|
||||||
}
|
}
|
||||||
|
} else if vform.Method == MfaSetupVerification {
|
||||||
|
c.SetSession(object.MfaDestSession, vform.Dest)
|
||||||
}
|
}
|
||||||
|
|
||||||
provider, err := application.GetEmailProvider()
|
provider, err := application.GetEmailProvider()
|
||||||
@@ -164,6 +165,11 @@ func (c *ApiController) SendVerificationCode() {
|
|||||||
vform.CountryCode = user.GetCountryCode(vform.CountryCode)
|
vform.CountryCode = user.GetCountryCode(vform.CountryCode)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if vform.Method == MfaSetupVerification {
|
||||||
|
c.SetSession(object.MfaCountryCodeSession, vform.CountryCode)
|
||||||
|
c.SetSession(object.MfaDestSession, vform.Dest)
|
||||||
|
}
|
||||||
} else if vform.Method == MfaAuthVerification {
|
} else if vform.Method == MfaAuthVerification {
|
||||||
mfaProps := user.GetPreferredMfaProps(false)
|
mfaProps := user.GetPreferredMfaProps(false)
|
||||||
if user != nil && util.GetMaskedPhone(mfaProps.Secret) == vform.Dest {
|
if user != nil && util.GetMaskedPhone(mfaProps.Secret) == vform.Dest {
|
||||||
@@ -187,11 +193,6 @@ func (c *ApiController) SendVerificationCode() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if vform.Method == MfaSetupVerification {
|
|
||||||
c.SetSession(object.MfaSmsCountryCodeSession, vform.CountryCode)
|
|
||||||
c.SetSession(object.MfaSmsDestSession, vform.Dest)
|
|
||||||
}
|
|
||||||
|
|
||||||
if sendResp != nil {
|
if sendResp != nil {
|
||||||
c.ResponseError(sendResp.Error())
|
c.ResponseError(sendResp.Error())
|
||||||
} else {
|
} else {
|
||||||
|
@@ -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
|
||||||
|
7
go.mod
7
go.mod
@@ -39,17 +39,18 @@ require (
|
|||||||
github.com/lib/pq v1.10.2
|
github.com/lib/pq v1.10.2
|
||||||
github.com/lor00x/goldap v0.0.0-20180618054307-a546dffdd1a3
|
github.com/lor00x/goldap v0.0.0-20180618054307-a546dffdd1a3
|
||||||
github.com/markbates/goth v1.75.2
|
github.com/markbates/goth v1.75.2
|
||||||
|
github.com/mitchellh/mapstructure v1.5.0
|
||||||
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 +60,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不匹配"
|
||||||
|
@@ -20,32 +20,37 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
_ "net/url"
|
|
||||||
_ "time"
|
|
||||||
|
|
||||||
|
"github.com/casdoor/casdoor/util"
|
||||||
|
"github.com/mitchellh/mapstructure"
|
||||||
"golang.org/x/oauth2"
|
"golang.org/x/oauth2"
|
||||||
)
|
)
|
||||||
|
|
||||||
type CustomIdProvider struct {
|
type CustomIdProvider struct {
|
||||||
Client *http.Client
|
Client *http.Client
|
||||||
Config *oauth2.Config
|
Config *oauth2.Config
|
||||||
UserInfoUrl string
|
|
||||||
|
UserInfoURL string
|
||||||
|
TokenURL string
|
||||||
|
AuthURL string
|
||||||
|
UserMapping map[string]string
|
||||||
|
Scopes []string
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewCustomIdProvider(clientId string, clientSecret string, redirectUrl string, authUrl string, tokenUrl string, userInfoUrl string) *CustomIdProvider {
|
func NewCustomIdProvider(idpInfo *ProviderInfo, redirectUrl string) *CustomIdProvider {
|
||||||
idp := &CustomIdProvider{}
|
idp := &CustomIdProvider{}
|
||||||
idp.UserInfoUrl = userInfoUrl
|
|
||||||
|
|
||||||
config := &oauth2.Config{
|
idp.Config = &oauth2.Config{
|
||||||
ClientID: clientId,
|
ClientID: idpInfo.ClientId,
|
||||||
ClientSecret: clientSecret,
|
ClientSecret: idpInfo.ClientSecret,
|
||||||
RedirectURL: redirectUrl,
|
RedirectURL: redirectUrl,
|
||||||
Endpoint: oauth2.Endpoint{
|
Endpoint: oauth2.Endpoint{
|
||||||
AuthURL: authUrl,
|
AuthURL: idpInfo.AuthURL,
|
||||||
TokenURL: tokenUrl,
|
TokenURL: idpInfo.TokenURL,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
idp.Config = config
|
idp.UserInfoURL = idpInfo.UserInfoURL
|
||||||
|
idp.UserMapping = idpInfo.UserMapping
|
||||||
|
|
||||||
return idp
|
return idp
|
||||||
}
|
}
|
||||||
@@ -60,22 +65,20 @@ func (idp *CustomIdProvider) GetToken(code string) (*oauth2.Token, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type CustomUserInfo struct {
|
type CustomUserInfo struct {
|
||||||
Id string `json:"sub"`
|
Id string `mapstructure:"id"`
|
||||||
Name string `json:"preferred_username,omitempty"`
|
Username string `mapstructure:"username"`
|
||||||
DisplayName string `json:"name"`
|
DisplayName string `mapstructure:"displayName"`
|
||||||
Email string `json:"email"`
|
Email string `mapstructure:"email"`
|
||||||
AvatarUrl string `json:"picture"`
|
AvatarUrl string `mapstructure:"avatarUrl"`
|
||||||
Status string `json:"status"`
|
|
||||||
Msg string `json:"msg"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (idp *CustomIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo, error) {
|
func (idp *CustomIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo, error) {
|
||||||
ctUserinfo := &CustomUserInfo{}
|
|
||||||
accessToken := token.AccessToken
|
accessToken := token.AccessToken
|
||||||
request, err := http.NewRequest("GET", idp.UserInfoUrl, nil)
|
request, err := http.NewRequest("GET", idp.UserInfoURL, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// add accessToken to request header
|
// add accessToken to request header
|
||||||
request.Header.Add("Authorization", fmt.Sprintf("Bearer %s", accessToken))
|
request.Header.Add("Authorization", fmt.Sprintf("Bearer %s", accessToken))
|
||||||
resp, err := idp.Client.Do(request)
|
resp, err := idp.Client.Do(request)
|
||||||
@@ -89,21 +92,40 @@ func (idp *CustomIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo, error)
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = json.Unmarshal(data, ctUserinfo)
|
var dataMap map[string]interface{}
|
||||||
|
err = json.Unmarshal(data, &dataMap)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if ctUserinfo.Status != "" {
|
// map user info
|
||||||
return nil, fmt.Errorf("err: %s", ctUserinfo.Msg)
|
for k, v := range idp.UserMapping {
|
||||||
|
_, ok := dataMap[v]
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("cannot find %s in user from castom provider", v)
|
||||||
|
}
|
||||||
|
dataMap[k] = dataMap[v]
|
||||||
|
}
|
||||||
|
|
||||||
|
// try to parse id to string
|
||||||
|
id, err := util.ParseIdToString(dataMap["id"])
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
dataMap["id"] = id
|
||||||
|
|
||||||
|
customUserinfo := &CustomUserInfo{}
|
||||||
|
err = mapstructure.Decode(dataMap, customUserinfo)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
userInfo := &UserInfo{
|
userInfo := &UserInfo{
|
||||||
Id: ctUserinfo.Id,
|
Id: customUserinfo.Id,
|
||||||
Username: ctUserinfo.Name,
|
Username: customUserinfo.Username,
|
||||||
DisplayName: ctUserinfo.DisplayName,
|
DisplayName: customUserinfo.DisplayName,
|
||||||
Email: ctUserinfo.Email,
|
Email: customUserinfo.Email,
|
||||||
AvatarUrl: ctUserinfo.AvatarUrl,
|
AvatarUrl: customUserinfo.AvatarUrl,
|
||||||
}
|
}
|
||||||
return userInfo, nil
|
return userInfo, nil
|
||||||
}
|
}
|
||||||
|
123
idp/provider.go
123
idp/provider.go
@@ -32,72 +32,89 @@ type UserInfo struct {
|
|||||||
AvatarUrl string
|
AvatarUrl string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ProviderInfo struct {
|
||||||
|
Type string
|
||||||
|
SubType string
|
||||||
|
ClientId string
|
||||||
|
ClientSecret string
|
||||||
|
AppId string
|
||||||
|
HostUrl string
|
||||||
|
RedirectUrl string
|
||||||
|
|
||||||
|
TokenURL string
|
||||||
|
AuthURL string
|
||||||
|
UserInfoURL string
|
||||||
|
UserMapping map[string]string
|
||||||
|
}
|
||||||
|
|
||||||
type IdProvider interface {
|
type IdProvider interface {
|
||||||
SetHttpClient(client *http.Client)
|
SetHttpClient(client *http.Client)
|
||||||
GetToken(code string) (*oauth2.Token, error)
|
GetToken(code string) (*oauth2.Token, error)
|
||||||
GetUserInfo(token *oauth2.Token) (*UserInfo, error)
|
GetUserInfo(token *oauth2.Token) (*UserInfo, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetIdProvider(typ string, subType string, clientId string, clientSecret string, appId string, redirectUrl string, hostUrl string, authUrl string, tokenUrl string, userInfoUrl string) IdProvider {
|
func GetIdProvider(idpInfo *ProviderInfo, redirectUrl string) IdProvider {
|
||||||
if typ == "GitHub" {
|
switch idpInfo.Type {
|
||||||
return NewGithubIdProvider(clientId, clientSecret, redirectUrl)
|
case "GitHub":
|
||||||
} else if typ == "Google" {
|
return NewGithubIdProvider(idpInfo.ClientId, idpInfo.ClientSecret, redirectUrl)
|
||||||
return NewGoogleIdProvider(clientId, clientSecret, redirectUrl)
|
case "Google":
|
||||||
} else if typ == "QQ" {
|
return NewGoogleIdProvider(idpInfo.ClientId, idpInfo.ClientSecret, redirectUrl)
|
||||||
return NewQqIdProvider(clientId, clientSecret, redirectUrl)
|
case "QQ":
|
||||||
} else if typ == "WeChat" {
|
return NewQqIdProvider(idpInfo.ClientId, idpInfo.ClientSecret, redirectUrl)
|
||||||
return NewWeChatIdProvider(clientId, clientSecret, redirectUrl)
|
case "WeChat":
|
||||||
} else if typ == "Facebook" {
|
return NewWeChatIdProvider(idpInfo.ClientId, idpInfo.ClientSecret, redirectUrl)
|
||||||
return NewFacebookIdProvider(clientId, clientSecret, redirectUrl)
|
case "Facebook":
|
||||||
} else if typ == "DingTalk" {
|
return NewFacebookIdProvider(idpInfo.ClientId, idpInfo.ClientSecret, redirectUrl)
|
||||||
return NewDingTalkIdProvider(clientId, clientSecret, redirectUrl)
|
case "DingTalk":
|
||||||
} else if typ == "Weibo" {
|
return NewDingTalkIdProvider(idpInfo.ClientId, idpInfo.ClientSecret, redirectUrl)
|
||||||
return NewWeiBoIdProvider(clientId, clientSecret, redirectUrl)
|
case "Weibo":
|
||||||
} else if typ == "Gitee" {
|
return NewWeiBoIdProvider(idpInfo.ClientId, idpInfo.ClientSecret, redirectUrl)
|
||||||
return NewGiteeIdProvider(clientId, clientSecret, redirectUrl)
|
case "Gitee":
|
||||||
} else if typ == "LinkedIn" {
|
return NewGiteeIdProvider(idpInfo.ClientId, idpInfo.ClientSecret, redirectUrl)
|
||||||
return NewLinkedInIdProvider(clientId, clientSecret, redirectUrl)
|
case "LinkedIn":
|
||||||
} else if typ == "WeCom" {
|
return NewLinkedInIdProvider(idpInfo.ClientId, idpInfo.ClientSecret, redirectUrl)
|
||||||
if subType == "Internal" {
|
case "WeCom":
|
||||||
return NewWeComInternalIdProvider(clientId, clientSecret, redirectUrl)
|
if idpInfo.SubType == "Internal" {
|
||||||
} else if subType == "Third-party" {
|
return NewWeComInternalIdProvider(idpInfo.ClientId, idpInfo.ClientSecret, redirectUrl)
|
||||||
return NewWeComIdProvider(clientId, clientSecret, redirectUrl)
|
} else if idpInfo.SubType == "Third-party" {
|
||||||
|
return NewWeComIdProvider(idpInfo.ClientId, idpInfo.ClientSecret, redirectUrl)
|
||||||
} else {
|
} else {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
} else if typ == "Lark" {
|
case "Lark":
|
||||||
return NewLarkIdProvider(clientId, clientSecret, redirectUrl)
|
return NewLarkIdProvider(idpInfo.ClientId, idpInfo.ClientSecret, redirectUrl)
|
||||||
} else if typ == "GitLab" {
|
case "GitLab":
|
||||||
return NewGitlabIdProvider(clientId, clientSecret, redirectUrl)
|
return NewGitlabIdProvider(idpInfo.ClientId, idpInfo.ClientSecret, redirectUrl)
|
||||||
} else if typ == "Adfs" {
|
case "Adfs":
|
||||||
return NewAdfsIdProvider(clientId, clientSecret, redirectUrl, hostUrl)
|
return NewAdfsIdProvider(idpInfo.ClientId, idpInfo.ClientSecret, redirectUrl, idpInfo.HostUrl)
|
||||||
} else if typ == "Baidu" {
|
case "Baidu":
|
||||||
return NewBaiduIdProvider(clientId, clientSecret, redirectUrl)
|
return NewBaiduIdProvider(idpInfo.ClientId, idpInfo.ClientSecret, redirectUrl)
|
||||||
} else if typ == "Alipay" {
|
case "Alipay":
|
||||||
return NewAlipayIdProvider(clientId, clientSecret, redirectUrl)
|
return NewAlipayIdProvider(idpInfo.ClientId, idpInfo.ClientSecret, redirectUrl)
|
||||||
} else if typ == "Custom" {
|
case "Custom":
|
||||||
return NewCustomIdProvider(clientId, clientSecret, redirectUrl, authUrl, tokenUrl, userInfoUrl)
|
return NewCustomIdProvider(idpInfo, redirectUrl)
|
||||||
} else if typ == "Infoflow" {
|
case "Infoflow":
|
||||||
if subType == "Internal" {
|
if idpInfo.SubType == "Internal" {
|
||||||
return NewInfoflowInternalIdProvider(clientId, clientSecret, appId, redirectUrl)
|
return NewInfoflowInternalIdProvider(idpInfo.ClientId, idpInfo.ClientSecret, idpInfo.AppId, redirectUrl)
|
||||||
} else if subType == "Third-party" {
|
} else if idpInfo.SubType == "Third-party" {
|
||||||
return NewInfoflowIdProvider(clientId, clientSecret, appId, redirectUrl)
|
return NewInfoflowIdProvider(idpInfo.ClientId, idpInfo.ClientSecret, idpInfo.AppId, redirectUrl)
|
||||||
} else {
|
} else {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
} else if typ == "Casdoor" {
|
case "Casdoor":
|
||||||
return NewCasdoorIdProvider(clientId, clientSecret, redirectUrl, hostUrl)
|
return NewCasdoorIdProvider(idpInfo.ClientId, idpInfo.ClientSecret, redirectUrl, idpInfo.HostUrl)
|
||||||
} else if typ == "Okta" {
|
case "Okta":
|
||||||
return NewOktaIdProvider(clientId, clientSecret, redirectUrl, hostUrl)
|
return NewOktaIdProvider(idpInfo.ClientId, idpInfo.ClientSecret, redirectUrl, idpInfo.HostUrl)
|
||||||
} else if typ == "Douyin" {
|
case "Douyin":
|
||||||
return NewDouyinIdProvider(clientId, clientSecret, redirectUrl)
|
return NewDouyinIdProvider(idpInfo.ClientId, idpInfo.ClientSecret, redirectUrl)
|
||||||
} else if isGothSupport(typ) {
|
case "Bilibili":
|
||||||
return NewGothIdProvider(typ, clientId, clientSecret, redirectUrl, hostUrl)
|
return NewBilibiliIdProvider(idpInfo.ClientId, idpInfo.ClientSecret, redirectUrl)
|
||||||
} else if typ == "Bilibili" {
|
default:
|
||||||
return NewBilibiliIdProvider(clientId, clientSecret, redirectUrl)
|
if isGothSupport(idpInfo.Type) {
|
||||||
|
return NewGothIdProvider(idpInfo.Type, idpInfo.ClientId, idpInfo.ClientSecret, redirectUrl, idpInfo.HostUrl)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var gothList = []string{
|
var gothList = []string{
|
||||||
|
@@ -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.")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -61,7 +61,7 @@ func getBuiltInAccountItems() []*AccountItem {
|
|||||||
{Name: "Signup application", Visible: true, ViewRule: "Public", ModifyRule: "Admin"},
|
{Name: "Signup application", Visible: true, ViewRule: "Public", ModifyRule: "Admin"},
|
||||||
{Name: "Roles", Visible: true, ViewRule: "Public", ModifyRule: "Immutable"},
|
{Name: "Roles", Visible: true, ViewRule: "Public", ModifyRule: "Immutable"},
|
||||||
{Name: "Permissions", Visible: true, ViewRule: "Public", ModifyRule: "Immutable"},
|
{Name: "Permissions", Visible: true, ViewRule: "Public", ModifyRule: "Immutable"},
|
||||||
{Name: "Groups", Visible: true, ViewRule: "Public", ModifyRule: "Immutable"},
|
{Name: "Groups", Visible: true, ViewRule: "Public", ModifyRule: "Admin"},
|
||||||
{Name: "3rd-party logins", Visible: true, ViewRule: "Self", ModifyRule: "Self"},
|
{Name: "3rd-party logins", Visible: true, ViewRule: "Self", ModifyRule: "Self"},
|
||||||
{Name: "Properties", Visible: false, ViewRule: "Admin", ModifyRule: "Admin"},
|
{Name: "Properties", Visible: false, ViewRule: "Admin", ModifyRule: "Admin"},
|
||||||
{Name: "Is admin", Visible: true, ViewRule: "Admin", ModifyRule: "Admin"},
|
{Name: "Is admin", Visible: true, ViewRule: "Admin", ModifyRule: "Admin"},
|
||||||
@@ -93,7 +93,7 @@ func initBuiltInOrganization() bool {
|
|||||||
Favicon: fmt.Sprintf("%s/img/casbin/favicon.ico", conf.GetConfigString("staticBaseUrl")),
|
Favicon: fmt.Sprintf("%s/img/casbin/favicon.ico", conf.GetConfigString("staticBaseUrl")),
|
||||||
PasswordType: "plain",
|
PasswordType: "plain",
|
||||||
PasswordOptions: []string{"AtLeast6"},
|
PasswordOptions: []string{"AtLeast6"},
|
||||||
CountryCodes: []string{"US", "ES", "CN", "FR", "DE", "GB", "JP", "KR", "VN", "ID", "SG", "IN"},
|
CountryCodes: []string{"US", "ES", "FR", "DE", "GB", "CN", "JP", "KR", "VN", "ID", "SG", "IN"},
|
||||||
DefaultAvatar: fmt.Sprintf("%s/img/casbin.svg", conf.GetConfigString("staticBaseUrl")),
|
DefaultAvatar: fmt.Sprintf("%s/img/casbin.svg", conf.GetConfigString("staticBaseUrl")),
|
||||||
Tags: []string{},
|
Tags: []string{},
|
||||||
Languages: []string{"en", "zh", "es", "fr", "de", "id", "ja", "ko", "ru", "vi", "pt"},
|
Languages: []string{"en", "zh", "es", "fr", "de", "id", "ja", "ko", "ru", "vi", "pt"},
|
||||||
@@ -130,7 +130,7 @@ func initBuiltInUser() {
|
|||||||
Avatar: fmt.Sprintf("%s/img/casbin.svg", conf.GetConfigString("staticBaseUrl")),
|
Avatar: fmt.Sprintf("%s/img/casbin.svg", conf.GetConfigString("staticBaseUrl")),
|
||||||
Email: "admin@example.com",
|
Email: "admin@example.com",
|
||||||
Phone: "12345678910",
|
Phone: "12345678910",
|
||||||
CountryCode: "CN",
|
CountryCode: "US",
|
||||||
Address: []string{},
|
Address: []string{},
|
||||||
Affiliation: "Example Inc.",
|
Affiliation: "Example Inc.",
|
||||||
Tag: "staff",
|
Tag: "staff",
|
||||||
@@ -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,9 +22,7 @@ import (
|
|||||||
"github.com/beego/beego/context"
|
"github.com/beego/beego/context"
|
||||||
)
|
)
|
||||||
|
|
||||||
type MfaSessionData struct {
|
const MfaRecoveryCodesSession = "mfa_recovery_codes"
|
||||||
UserId string
|
|
||||||
}
|
|
||||||
|
|
||||||
type MfaProps struct {
|
type MfaProps struct {
|
||||||
Enabled bool `json:"enabled"`
|
Enabled bool `json:"enabled"`
|
||||||
@@ -37,10 +35,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 +56,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 +95,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 +105,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 +123,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 +140,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 +169,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"
|
MfaCountryCodeSession = "mfa_country_code"
|
||||||
MfaSmsDestSession = "mfa_dest"
|
MfaDestSession = "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
|
||||||
}
|
}
|
||||||
@@ -50,9 +48,19 @@ func (mfa *SmsMfa) Initiate(ctx *context.Context, name string, secret string) (*
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (mfa *SmsMfa) SetupVerify(ctx *context.Context, passCode string) error {
|
func (mfa *SmsMfa) SetupVerify(ctx *context.Context, passCode string) error {
|
||||||
dest := ctx.Input.CruSession.Get(MfaSmsDestSession).(string)
|
destSession := ctx.Input.CruSession.Get(MfaDestSession)
|
||||||
countryCode := ctx.Input.CruSession.Get(MfaSmsCountryCodeSession).(string)
|
if destSession == nil {
|
||||||
|
return errors.New("dest session is missing")
|
||||||
|
}
|
||||||
|
dest := destSession.(string)
|
||||||
|
|
||||||
if !util.IsEmailValid(dest) {
|
if !util.IsEmailValid(dest) {
|
||||||
|
countryCodeSession := ctx.Input.CruSession.Get(MfaCountryCodeSession)
|
||||||
|
if countryCodeSession == nil {
|
||||||
|
return errors.New("country code is missing")
|
||||||
|
}
|
||||||
|
countryCode := countryCodeSession.(string)
|
||||||
|
|
||||||
dest, _ = util.GetE164Number(dest, countryCode)
|
dest, _ = util.GetE164Number(dest, countryCode)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -63,9 +71,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"}
|
||||||
@@ -80,8 +88,8 @@ func (mfa *SmsMfa) Enable(ctx *context.Context, user *User) error {
|
|||||||
columns = append(columns, "mfa_phone_enabled")
|
columns = append(columns, "mfa_phone_enabled")
|
||||||
|
|
||||||
if user.Phone == "" {
|
if user.Phone == "" {
|
||||||
user.Phone = ctx.Input.CruSession.Get(MfaSmsDestSession).(string)
|
user.Phone = ctx.Input.CruSession.Get(MfaDestSession).(string)
|
||||||
user.CountryCode = ctx.Input.CruSession.Get(MfaSmsCountryCodeSession).(string)
|
user.CountryCode = ctx.Input.CruSession.Get(MfaCountryCodeSession).(string)
|
||||||
columns = append(columns, "phone", "country_code")
|
columns = append(columns, "phone", "country_code")
|
||||||
}
|
}
|
||||||
} else if mfa.Config.MfaType == EmailType {
|
} else if mfa.Config.MfaType == EmailType {
|
||||||
@@ -89,7 +97,7 @@ func (mfa *SmsMfa) Enable(ctx *context.Context, user *User) error {
|
|||||||
columns = append(columns, "mfa_email_enabled")
|
columns = append(columns, "mfa_email_enabled")
|
||||||
|
|
||||||
if user.Email == "" {
|
if user.Email == "" {
|
||||||
user.Email = ctx.Input.CruSession.Get(MfaSmsDestSession).(string)
|
user.Email = ctx.Input.CruSession.Get(MfaDestSession).(string)
|
||||||
columns = append(columns, "email")
|
columns = append(columns, "email")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -98,6 +106,11 @@ func (mfa *SmsMfa) Enable(ctx *context.Context, user *User) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ctx.Input.CruSession.Delete(MfaRecoveryCodesSession)
|
||||||
|
ctx.Input.CruSession.Delete(MfaDestSession)
|
||||||
|
ctx.Input.CruSession.Delete(MfaCountryCodeSession)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -111,7 +124,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 +135,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,
|
||||||
|
140
object/mfa_totp.go
Normal file
140
object/mfa_totp.go
Normal file
@@ -0,0 +1,140 @@
|
|||||||
|
// 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)
|
||||||
|
if secret == nil {
|
||||||
|
return errors.New("totp secret is missing")
|
||||||
|
}
|
||||||
|
result := totp.Validate(passcode, secret.(string))
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.Input.CruSession.Delete(MfaRecoveryCodesSession)
|
||||||
|
ctx.Input.CruSession.Delete(MfaTotpSecretSession)
|
||||||
|
|
||||||
|
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,
|
||||||
|
}
|
||||||
|
}
|
@@ -65,10 +65,13 @@ func getOriginFromHost(host string) (string, string) {
|
|||||||
return origin, origin
|
return origin, origin
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// "door.casdoor.com"
|
||||||
protocol := "https://"
|
protocol := "https://"
|
||||||
if strings.HasPrefix(host, "localhost") {
|
if !strings.Contains(host, ".") {
|
||||||
|
// "localhost:8000" or "computer-name:80"
|
||||||
protocol = "http://"
|
protocol = "http://"
|
||||||
} else if isIpAddress(host) {
|
} else if isIpAddress(host) {
|
||||||
|
// "192.168.0.10"
|
||||||
protocol = "http://"
|
protocol = "http://"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -69,7 +69,7 @@ type Organization struct {
|
|||||||
IsProfilePublic bool `json:"isProfilePublic"`
|
IsProfilePublic bool `json:"isProfilePublic"`
|
||||||
|
|
||||||
MfaItems []*MfaItem `xorm:"varchar(300)" json:"mfaItems"`
|
MfaItems []*MfaItem `xorm:"varchar(300)" json:"mfaItems"`
|
||||||
AccountItems []*AccountItem `xorm:"varchar(3000)" json:"accountItems"`
|
AccountItems []*AccountItem `xorm:"varchar(5000)" json:"accountItems"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetOrganizationCount(owner, field, value string) (int64, error) {
|
func GetOrganizationCount(owner, field, value string) (int64, error) {
|
||||||
@@ -104,10 +104,15 @@ func GetOrganizationsByFields(owner string, fields ...string) ([]*Organization,
|
|||||||
return organizations, nil
|
return organizations, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetPaginationOrganizations(owner string, offset, limit int, field, value, sortField, sortOrder string) ([]*Organization, error) {
|
func GetPaginationOrganizations(owner string, name string, offset, limit int, field, value, sortField, sortOrder string) ([]*Organization, error) {
|
||||||
organizations := []*Organization{}
|
organizations := []*Organization{}
|
||||||
session := GetSession(owner, offset, limit, field, value, sortField, sortOrder)
|
session := GetSession(owner, offset, limit, field, value, sortField, sortOrder)
|
||||||
err := session.Find(&organizations)
|
var err error
|
||||||
|
if name != "" {
|
||||||
|
err = session.Find(&organizations, &Organization{Name: name})
|
||||||
|
} else {
|
||||||
|
err = session.Find(&organizations)
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -231,6 +236,10 @@ func DeleteOrganization(organization *Organization) (bool, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func GetOrganizationByUser(user *User) (*Organization, error) {
|
func GetOrganizationByUser(user *User) (*Organization, error) {
|
||||||
|
if user == nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
return getOrganization("admin", user.Owner)
|
return getOrganization("admin", user.Owner)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -467,10 +476,21 @@ func organizationChangeTrigger(oldName string, newName string) error {
|
|||||||
return session.Commit()
|
return session.Commit()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (org *Organization) HasRequiredMfa() bool {
|
func IsNeedPromptMfa(org *Organization, user *User) bool {
|
||||||
|
if org == nil || user == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
for _, item := range org.MfaItems {
|
for _, item := range org.MfaItems {
|
||||||
if item.Rule == "Required" {
|
if item.Rule == "Required" {
|
||||||
return true
|
if item.Name == EmailType && !user.MfaEmailEnabled {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if item.Name == SmsType && !user.MfaPhoneEnabled {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if item.Name == TotpType && user.TotpSecret == "" {
|
||||||
|
return true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
|
@@ -370,3 +370,24 @@ func GetMaskedPermissions(permissions []*Permission) []*Permission {
|
|||||||
|
|
||||||
return permissions
|
return permissions
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GroupPermissionsByModelAdapter group permissions by model and adapter.
|
||||||
|
// Every model and adapter will be a key, and the value is a list of permission ids.
|
||||||
|
// With each list of permission ids have the same key, we just need to init the
|
||||||
|
// enforcer and do the enforce/batch-enforce once (with list of permission ids
|
||||||
|
// as the policyFilter when the enforcer load policy).
|
||||||
|
func GroupPermissionsByModelAdapter(permissions []*Permission) map[string][]string {
|
||||||
|
m := make(map[string][]string)
|
||||||
|
|
||||||
|
for _, permission := range permissions {
|
||||||
|
key := permission.Model + permission.Adapter
|
||||||
|
permissionIds, ok := m[key]
|
||||||
|
if !ok {
|
||||||
|
m[key] = []string{permission.GetId()}
|
||||||
|
} else {
|
||||||
|
m[key] = append(permissionIds, permission.GetId())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
@@ -26,7 +26,7 @@ import (
|
|||||||
xormadapter "github.com/casdoor/xorm-adapter/v3"
|
xormadapter "github.com/casdoor/xorm-adapter/v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
func getEnforcer(permission *Permission) *casbin.Enforcer {
|
func getEnforcer(permission *Permission, permissionIDs ...string) *casbin.Enforcer {
|
||||||
tableName := "permission_rule"
|
tableName := "permission_rule"
|
||||||
if len(permission.Adapter) != 0 {
|
if len(permission.Adapter) != 0 {
|
||||||
adapterObj, err := getCasbinAdapter(permission.Owner, permission.Adapter)
|
adapterObj, err := getCasbinAdapter(permission.Owner, permission.Adapter)
|
||||||
@@ -77,8 +77,13 @@ func getEnforcer(permission *Permission) *casbin.Enforcer {
|
|||||||
|
|
||||||
enforcer.SetAdapter(adapter)
|
enforcer.SetAdapter(adapter)
|
||||||
|
|
||||||
|
policyFilterV5 := []string{permission.GetId()}
|
||||||
|
if len(permissionIDs) != 0 {
|
||||||
|
policyFilterV5 = permissionIDs
|
||||||
|
}
|
||||||
|
|
||||||
policyFilter := xormadapter.Filter{
|
policyFilter := xormadapter.Filter{
|
||||||
V5: []string{permission.GetId()},
|
V5: policyFilterV5,
|
||||||
}
|
}
|
||||||
|
|
||||||
if !HasRoleDefinition(m) {
|
if !HasRoleDefinition(m) {
|
||||||
@@ -241,28 +246,13 @@ func removePolicies(permission *Permission) {
|
|||||||
|
|
||||||
type CasbinRequest = []interface{}
|
type CasbinRequest = []interface{}
|
||||||
|
|
||||||
func Enforce(permissionId string, request *CasbinRequest) (bool, error) {
|
func Enforce(permission *Permission, request *CasbinRequest, permissionIds ...string) (bool, error) {
|
||||||
permission, err := GetPermission(permissionId)
|
enforcer := getEnforcer(permission, permissionIds...)
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
|
|
||||||
enforcer := getEnforcer(permission)
|
|
||||||
return enforcer.Enforce(*request...)
|
return enforcer.Enforce(*request...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func BatchEnforce(permissionId string, requests *[]CasbinRequest) ([]bool, error) {
|
func BatchEnforce(permission *Permission, requests *[]CasbinRequest, permissionIds ...string) ([]bool, error) {
|
||||||
permission, err := GetPermission(permissionId)
|
enforcer := getEnforcer(permission, permissionIds...)
|
||||||
if err != nil {
|
|
||||||
res := []bool{}
|
|
||||||
for i := 0; i < len(*requests); i++ {
|
|
||||||
res = append(res, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
return res, err
|
|
||||||
}
|
|
||||||
|
|
||||||
enforcer := getEnforcer(permission)
|
|
||||||
return enforcer.BatchEnforce(*requests)
|
return enforcer.BatchEnforce(*requests)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -16,8 +16,11 @@ package object
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/beego/beego/context"
|
||||||
"github.com/casdoor/casdoor/i18n"
|
"github.com/casdoor/casdoor/i18n"
|
||||||
|
"github.com/casdoor/casdoor/idp"
|
||||||
"github.com/casdoor/casdoor/pp"
|
"github.com/casdoor/casdoor/pp"
|
||||||
"github.com/casdoor/casdoor/util"
|
"github.com/casdoor/casdoor/util"
|
||||||
"github.com/xorm-io/core"
|
"github.com/xorm-io/core"
|
||||||
@@ -28,21 +31,22 @@ type Provider struct {
|
|||||||
Name string `xorm:"varchar(100) notnull pk unique" json:"name"`
|
Name string `xorm:"varchar(100) notnull pk unique" json:"name"`
|
||||||
CreatedTime string `xorm:"varchar(100)" json:"createdTime"`
|
CreatedTime string `xorm:"varchar(100)" json:"createdTime"`
|
||||||
|
|
||||||
DisplayName string `xorm:"varchar(100)" json:"displayName"`
|
DisplayName string `xorm:"varchar(100)" json:"displayName"`
|
||||||
Category string `xorm:"varchar(100)" json:"category"`
|
Category string `xorm:"varchar(100)" json:"category"`
|
||||||
Type string `xorm:"varchar(100)" json:"type"`
|
Type string `xorm:"varchar(100)" json:"type"`
|
||||||
SubType string `xorm:"varchar(100)" json:"subType"`
|
SubType string `xorm:"varchar(100)" json:"subType"`
|
||||||
Method string `xorm:"varchar(100)" json:"method"`
|
Method string `xorm:"varchar(100)" json:"method"`
|
||||||
ClientId string `xorm:"varchar(100)" json:"clientId"`
|
ClientId string `xorm:"varchar(100)" json:"clientId"`
|
||||||
ClientSecret string `xorm:"varchar(2000)" json:"clientSecret"`
|
ClientSecret string `xorm:"varchar(2000)" json:"clientSecret"`
|
||||||
ClientId2 string `xorm:"varchar(100)" json:"clientId2"`
|
ClientId2 string `xorm:"varchar(100)" json:"clientId2"`
|
||||||
ClientSecret2 string `xorm:"varchar(100)" json:"clientSecret2"`
|
ClientSecret2 string `xorm:"varchar(100)" json:"clientSecret2"`
|
||||||
Cert string `xorm:"varchar(100)" json:"cert"`
|
Cert string `xorm:"varchar(100)" json:"cert"`
|
||||||
CustomAuthUrl string `xorm:"varchar(200)" json:"customAuthUrl"`
|
CustomAuthUrl string `xorm:"varchar(200)" json:"customAuthUrl"`
|
||||||
CustomScope string `xorm:"varchar(200)" json:"customScope"`
|
CustomTokenUrl string `xorm:"varchar(200)" json:"customTokenUrl"`
|
||||||
CustomTokenUrl string `xorm:"varchar(200)" json:"customTokenUrl"`
|
CustomUserInfoUrl string `xorm:"varchar(200)" json:"customUserInfoUrl"`
|
||||||
CustomUserInfoUrl string `xorm:"varchar(200)" json:"customUserInfoUrl"`
|
CustomLogo string `xorm:"varchar(200)" json:"customLogo"`
|
||||||
CustomLogo string `xorm:"varchar(200)" json:"customLogo"`
|
Scopes string `xorm:"varchar(100)" json:"scopes"`
|
||||||
|
UserMapping map[string]string `xorm:"varchar(500)" json:"userMapping"`
|
||||||
|
|
||||||
Host string `xorm:"varchar(100)" json:"host"`
|
Host string `xorm:"varchar(100)" json:"host"`
|
||||||
Port int `json:"port"`
|
Port int `json:"port"`
|
||||||
@@ -365,3 +369,27 @@ func providerChangeTrigger(oldName string, newName string) error {
|
|||||||
|
|
||||||
return session.Commit()
|
return session.Commit()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func FromProviderToIdpInfo(ctx *context.Context, provider *Provider) *idp.ProviderInfo {
|
||||||
|
providerInfo := &idp.ProviderInfo{
|
||||||
|
Type: provider.Type,
|
||||||
|
SubType: provider.SubType,
|
||||||
|
ClientId: provider.ClientId,
|
||||||
|
ClientSecret: provider.ClientSecret,
|
||||||
|
AppId: provider.AppId,
|
||||||
|
HostUrl: provider.Host,
|
||||||
|
TokenURL: provider.CustomTokenUrl,
|
||||||
|
AuthURL: provider.CustomAuthUrl,
|
||||||
|
UserInfoURL: provider.CustomUserInfoUrl,
|
||||||
|
UserMapping: provider.UserMapping,
|
||||||
|
}
|
||||||
|
|
||||||
|
if provider.Type == "WeChat" {
|
||||||
|
if ctx != nil && strings.Contains(ctx.Request.UserAgent(), "MicroMessenger") {
|
||||||
|
providerInfo.ClientId = provider.ClientId2
|
||||||
|
providerInfo.ClientSecret = provider.ClientSecret2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return providerInfo
|
||||||
|
}
|
||||||
|
@@ -50,6 +50,7 @@ type Syncer struct {
|
|||||||
AvatarBaseUrl string `xorm:"varchar(100)" json:"avatarBaseUrl"`
|
AvatarBaseUrl string `xorm:"varchar(100)" json:"avatarBaseUrl"`
|
||||||
ErrorText string `xorm:"mediumtext" json:"errorText"`
|
ErrorText string `xorm:"mediumtext" json:"errorText"`
|
||||||
SyncInterval int `json:"syncInterval"`
|
SyncInterval int `json:"syncInterval"`
|
||||||
|
IsReadOnly bool `json:"isReadOnly"`
|
||||||
IsEnabled bool `json:"isEnabled"`
|
IsEnabled bool `json:"isEnabled"`
|
||||||
|
|
||||||
Adapter *Adapter `xorm:"-" json:"-"`
|
Adapter *Adapter `xorm:"-" json:"-"`
|
||||||
|
@@ -63,9 +63,11 @@ func (syncer *Syncer) syncUsers() {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if user.PreHash == oHash {
|
if user.PreHash == oHash {
|
||||||
updatedOUser := syncer.createOriginalUserFromUser(user)
|
if !syncer.IsReadOnly {
|
||||||
syncer.updateUser(updatedOUser)
|
updatedOUser := syncer.createOriginalUserFromUser(user)
|
||||||
fmt.Printf("Update from user to oUser: %v\n", updatedOUser)
|
syncer.updateUser(updatedOUser)
|
||||||
|
fmt.Printf("Update from user to oUser: %v\n", updatedOUser)
|
||||||
|
}
|
||||||
|
|
||||||
// update preHash
|
// update preHash
|
||||||
user.PreHash = user.Hash
|
user.PreHash = user.Hash
|
||||||
@@ -91,15 +93,17 @@ func (syncer *Syncer) syncUsers() {
|
|||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, user := range users {
|
if !syncer.IsReadOnly {
|
||||||
id := user.Id
|
for _, user := range users {
|
||||||
if _, ok := oUserMap[id]; !ok {
|
id := user.Id
|
||||||
newOUser := syncer.createOriginalUserFromUser(user)
|
if _, ok := oUserMap[id]; !ok {
|
||||||
_, err = syncer.addUser(newOUser)
|
newOUser := syncer.createOriginalUserFromUser(user)
|
||||||
if err != nil {
|
_, err = syncer.addUser(newOUser)
|
||||||
panic(err)
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
fmt.Printf("New oUser: %v\n", newOUser)
|
||||||
}
|
}
|
||||||
fmt.Printf("New oUser: %v\n", newOUser)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -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 {
|
||||||
|
@@ -160,7 +160,8 @@ 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"`
|
||||||
|
TotpSecret string `xorm:"varchar(100)" json:"totpSecret"`
|
||||||
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
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -828,11 +832,14 @@ func userChangeTrigger(oldName string, newName string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (user *User) IsMfaEnabled() bool {
|
func (user *User) IsMfaEnabled() bool {
|
||||||
|
if user == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
return user.PreferredMfaType != ""
|
return user.PreferredMfaType != ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func (user *User) GetPreferredMfaProps(masked bool) *MfaProps {
|
func (user *User) GetPreferredMfaProps(masked bool) *MfaProps {
|
||||||
if user.PreferredMfaType == "" {
|
if user == nil || user.PreferredMfaType == "" {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return user.GetMfaProps(user.PreferredMfaType, masked)
|
return user.GetMfaProps(user.PreferredMfaType, masked)
|
||||||
|
@@ -55,7 +55,7 @@ func StaticFilter(ctx *context.Context) {
|
|||||||
path += urlPath
|
path += urlPath
|
||||||
}
|
}
|
||||||
|
|
||||||
path2 := strings.TrimLeft(path, "web/build/images/")
|
path2 := strings.TrimPrefix(path, "web/build/images/")
|
||||||
if util.FileExist(path2) {
|
if util.FileExist(path2) {
|
||||||
makeGzipResponse(ctx.ResponseWriter, ctx.Request, path2)
|
makeGzipResponse(ctx.ResponseWriter, ctx.Request, path2)
|
||||||
return
|
return
|
||||||
|
File diff suppressed because it is too large
Load Diff
@@ -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:
|
||||||
@@ -272,6 +308,18 @@ paths:
|
|||||||
tags:
|
tags:
|
||||||
- Resource API
|
- Resource API
|
||||||
operationId: ApiController.AddResource
|
operationId: ApiController.AddResource
|
||||||
|
parameters:
|
||||||
|
- in: body
|
||||||
|
name: resource
|
||||||
|
description: Resource object
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/object.Resource'
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: Success or error
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/controllers.Response'
|
||||||
/api/add-role:
|
/api/add-role:
|
||||||
post:
|
post:
|
||||||
tags:
|
tags:
|
||||||
@@ -386,6 +434,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 +559,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 +608,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 +680,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:
|
||||||
@@ -792,6 +881,18 @@ paths:
|
|||||||
tags:
|
tags:
|
||||||
- Resource API
|
- Resource API
|
||||||
operationId: ApiController.DeleteResource
|
operationId: ApiController.DeleteResource
|
||||||
|
parameters:
|
||||||
|
- in: body
|
||||||
|
name: resource
|
||||||
|
description: Resource object
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/object.Resource'
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: Success or error
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/controllers.Response'
|
||||||
/api/delete-role:
|
/api/delete-role:
|
||||||
post:
|
post:
|
||||||
tags:
|
tags:
|
||||||
@@ -923,12 +1024,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 +1061,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 +1320,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 +1500,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 +1694,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:
|
||||||
@@ -1669,12 +1842,67 @@ paths:
|
|||||||
get:
|
get:
|
||||||
tags:
|
tags:
|
||||||
- Resource API
|
- Resource API
|
||||||
|
description: get resource
|
||||||
operationId: ApiController.GetResource
|
operationId: ApiController.GetResource
|
||||||
|
parameters:
|
||||||
|
- in: query
|
||||||
|
name: id
|
||||||
|
description: The id ( owner/name ) of resource
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: The Response object
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/object.Resource'
|
||||||
/api/get-resources:
|
/api/get-resources:
|
||||||
get:
|
get:
|
||||||
tags:
|
tags:
|
||||||
- Resource API
|
- Resource API
|
||||||
|
description: get resources
|
||||||
operationId: ApiController.GetResources
|
operationId: ApiController.GetResources
|
||||||
|
parameters:
|
||||||
|
- in: query
|
||||||
|
name: owner
|
||||||
|
description: Owner
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
- in: query
|
||||||
|
name: user
|
||||||
|
description: User
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
- in: query
|
||||||
|
name: pageSize
|
||||||
|
description: Page Size
|
||||||
|
type: integer
|
||||||
|
- in: query
|
||||||
|
name: p
|
||||||
|
description: Page Number
|
||||||
|
type: integer
|
||||||
|
- in: query
|
||||||
|
name: field
|
||||||
|
description: Field
|
||||||
|
type: string
|
||||||
|
- in: query
|
||||||
|
name: value
|
||||||
|
description: Value
|
||||||
|
type: string
|
||||||
|
- in: query
|
||||||
|
name: sortField
|
||||||
|
description: Sort Field
|
||||||
|
type: string
|
||||||
|
- in: query
|
||||||
|
name: sortOrder
|
||||||
|
description: Sort Order
|
||||||
|
type: string
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: The Response object
|
||||||
|
schema:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
$ref: '#/definitions/object.Resource'
|
||||||
/api/get-role:
|
/api/get-role:
|
||||||
get:
|
get:
|
||||||
tags:
|
tags:
|
||||||
@@ -1793,7 +2021,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 +2400,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 +2579,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 +2708,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 +2800,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:
|
||||||
@@ -2765,7 +3039,25 @@ paths:
|
|||||||
post:
|
post:
|
||||||
tags:
|
tags:
|
||||||
- Resource API
|
- Resource API
|
||||||
|
description: get resource
|
||||||
operationId: ApiController.UpdateResource
|
operationId: ApiController.UpdateResource
|
||||||
|
parameters:
|
||||||
|
- in: query
|
||||||
|
name: id
|
||||||
|
description: The id ( owner/name ) of resource
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
- in: body
|
||||||
|
name: resource
|
||||||
|
description: The resource object
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/object.Resource'
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: Success or error
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/controllers.Response'
|
||||||
/api/update-role:
|
/api/update-role:
|
||||||
post:
|
post:
|
||||||
tags:
|
tags:
|
||||||
@@ -2928,6 +3220,53 @@ paths:
|
|||||||
tags:
|
tags:
|
||||||
- Resource API
|
- Resource API
|
||||||
operationId: ApiController.UploadResource
|
operationId: ApiController.UploadResource
|
||||||
|
parameters:
|
||||||
|
- in: query
|
||||||
|
name: owner
|
||||||
|
description: Owner
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
- in: query
|
||||||
|
name: user
|
||||||
|
description: User
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
- in: query
|
||||||
|
name: application
|
||||||
|
description: Application
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
- in: query
|
||||||
|
name: tag
|
||||||
|
description: Tag
|
||||||
|
type: string
|
||||||
|
- in: query
|
||||||
|
name: parent
|
||||||
|
description: Parent
|
||||||
|
type: string
|
||||||
|
- in: query
|
||||||
|
name: fullFilePath
|
||||||
|
description: Full File Path
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
- in: query
|
||||||
|
name: createdTime
|
||||||
|
description: Created Time
|
||||||
|
type: string
|
||||||
|
- in: query
|
||||||
|
name: description
|
||||||
|
description: Description
|
||||||
|
type: string
|
||||||
|
- in: formData
|
||||||
|
name: file
|
||||||
|
description: Resource file
|
||||||
|
required: true
|
||||||
|
type: file
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: FileUrl, objectKey
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/object.Resource'
|
||||||
/api/user:
|
/api/user:
|
||||||
get:
|
get:
|
||||||
tags:
|
tags:
|
||||||
@@ -2994,7 +3333,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 +3362,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 +3394,13 @@ definitions:
|
|||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
data:
|
data:
|
||||||
$ref: '#/definitions/1225.0xc0002e2ae0.false'
|
additionalProperties:
|
||||||
|
description: support string, struct or []struct
|
||||||
|
type: string
|
||||||
data2:
|
data2:
|
||||||
$ref: '#/definitions/1260.0xc0002e2b10.false'
|
additionalProperties:
|
||||||
|
description: support string, struct or []struct
|
||||||
|
type: string
|
||||||
msg:
|
msg:
|
||||||
type: string
|
type: string
|
||||||
name:
|
name:
|
||||||
@@ -3090,8 +3424,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
|
||||||
@@ -3210,6 +3544,10 @@ definitions:
|
|||||||
$ref: '#/definitions/object.SignupItem'
|
$ref: '#/definitions/object.SignupItem'
|
||||||
signupUrl:
|
signupUrl:
|
||||||
type: string
|
type: string
|
||||||
|
tags:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
termsOfUse:
|
termsOfUse:
|
||||||
type: string
|
type: string
|
||||||
themeData:
|
themeData:
|
||||||
@@ -3220,7 +3558,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 +3633,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 +3771,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 +3791,8 @@ definitions:
|
|||||||
properties:
|
properties:
|
||||||
createdTime:
|
createdTime:
|
||||||
type: string
|
type: string
|
||||||
|
description:
|
||||||
|
type: string
|
||||||
displayName:
|
displayName:
|
||||||
type: string
|
type: string
|
||||||
isEnabled:
|
isEnabled:
|
||||||
@@ -3520,6 +3898,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 +3989,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 +4071,6 @@ definitions:
|
|||||||
type: string
|
type: string
|
||||||
displayName:
|
displayName:
|
||||||
type: string
|
type: string
|
||||||
hasTrial:
|
|
||||||
type: boolean
|
|
||||||
isEnabled:
|
isEnabled:
|
||||||
type: boolean
|
type: boolean
|
||||||
name:
|
name:
|
||||||
@@ -3792,8 +4174,6 @@ definitions:
|
|||||||
type: string
|
type: string
|
||||||
customLogo:
|
customLogo:
|
||||||
type: string
|
type: string
|
||||||
customScope:
|
|
||||||
type: string
|
|
||||||
customTokenUrl:
|
customTokenUrl:
|
||||||
type: string
|
type: string
|
||||||
customUserInfoUrl:
|
customUserInfoUrl:
|
||||||
@@ -3835,6 +4215,8 @@ definitions:
|
|||||||
type: string
|
type: string
|
||||||
regionId:
|
regionId:
|
||||||
type: string
|
type: string
|
||||||
|
scopes:
|
||||||
|
type: string
|
||||||
signName:
|
signName:
|
||||||
type: string
|
type: string
|
||||||
subType:
|
subType:
|
||||||
@@ -3845,6 +4227,9 @@ definitions:
|
|||||||
type: string
|
type: string
|
||||||
type:
|
type:
|
||||||
type: string
|
type: string
|
||||||
|
userMapping:
|
||||||
|
additionalProperties:
|
||||||
|
type: string
|
||||||
object.ProviderItem:
|
object.ProviderItem:
|
||||||
title: ProviderItem
|
title: ProviderItem
|
||||||
type: object
|
type: object
|
||||||
@@ -3898,12 +4283,47 @@ definitions:
|
|||||||
type: string
|
type: string
|
||||||
user:
|
user:
|
||||||
type: string
|
type: string
|
||||||
|
object.Resource:
|
||||||
|
title: Resource
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
application:
|
||||||
|
type: string
|
||||||
|
createdTime:
|
||||||
|
type: string
|
||||||
|
description:
|
||||||
|
type: string
|
||||||
|
fileFormat:
|
||||||
|
type: string
|
||||||
|
fileName:
|
||||||
|
type: string
|
||||||
|
fileSize:
|
||||||
|
type: integer
|
||||||
|
format: int64
|
||||||
|
fileType:
|
||||||
|
type: string
|
||||||
|
name:
|
||||||
|
type: string
|
||||||
|
owner:
|
||||||
|
type: string
|
||||||
|
parent:
|
||||||
|
type: string
|
||||||
|
provider:
|
||||||
|
type: string
|
||||||
|
tag:
|
||||||
|
type: string
|
||||||
|
url:
|
||||||
|
type: string
|
||||||
|
user:
|
||||||
|
type: string
|
||||||
object.Role:
|
object.Role:
|
||||||
title: Role
|
title: Role
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
createdTime:
|
createdTime:
|
||||||
type: string
|
type: string
|
||||||
|
description:
|
||||||
|
type: string
|
||||||
displayName:
|
displayName:
|
||||||
type: string
|
type: string
|
||||||
domains:
|
domains:
|
||||||
@@ -3995,6 +4415,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 +4539,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 +4561,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 +4633,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 +4704,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 +4748,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 +4758,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 +4798,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 +4848,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 +4894,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
|
||||||
|
@@ -72,6 +72,9 @@ func UrlJoin(base string, path string) string {
|
|||||||
|
|
||||||
func GetUrlPath(urlString string) string {
|
func GetUrlPath(urlString string) string {
|
||||||
u, _ := url.Parse(urlString)
|
u, _ := url.Parse(urlString)
|
||||||
|
if u == nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
return u.Path
|
return u.Path
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -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 != "" {
|
||||||
|
@@ -289,3 +289,18 @@ func HasString(strs []string, str string) bool {
|
|||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ParseIdToString(input interface{}) (string, error) {
|
||||||
|
switch v := input.(type) {
|
||||||
|
case string:
|
||||||
|
return v, nil
|
||||||
|
case int:
|
||||||
|
return strconv.Itoa(v), nil
|
||||||
|
case int64:
|
||||||
|
return strconv.FormatInt(v, 10), nil
|
||||||
|
case float64:
|
||||||
|
return strconv.FormatFloat(v, 'f', -1, 64), nil
|
||||||
|
default:
|
||||||
|
return "", fmt.Errorf("unsupported id type: %T", input)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -246,3 +246,23 @@ func TestSnakeString(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestParseId(t *testing.T) {
|
||||||
|
scenarios := []struct {
|
||||||
|
description string
|
||||||
|
input interface{}
|
||||||
|
expected interface{}
|
||||||
|
}{
|
||||||
|
{"Should be return 123456", "123456", "123456"},
|
||||||
|
{"Should be return 123456", 123456, "123456"},
|
||||||
|
{"Should be return 123456", int64(123456), "123456"},
|
||||||
|
{"Should be return 123456", float64(123456), "123456"},
|
||||||
|
}
|
||||||
|
for _, scenery := range scenarios {
|
||||||
|
t.Run(scenery.description, func(t *testing.T) {
|
||||||
|
actual, err := ParseIdToString(scenery.input)
|
||||||
|
assert.Nil(t, err, "The returned value not is expected")
|
||||||
|
assert.Equal(t, scenery.expected, actual, "The returned value not is expected")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -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,
|
||||||
});
|
});
|
||||||
|
@@ -25,8 +25,9 @@ import PopconfirmModal from "./common/modal/PopconfirmModal";
|
|||||||
class AdapterListPage extends BaseListPage {
|
class AdapterListPage extends BaseListPage {
|
||||||
newAdapter() {
|
newAdapter() {
|
||||||
const randomName = Setting.getRandomName();
|
const randomName = Setting.getRandomName();
|
||||||
|
const owner = Setting.getRequestOrganization(this.props.account);
|
||||||
return {
|
return {
|
||||||
owner: this.props.account.owner,
|
owner: owner,
|
||||||
name: `adapter_${randomName}`,
|
name: `adapter_${randomName}`,
|
||||||
createdTime: moment().format(),
|
createdTime: moment().format(),
|
||||||
type: "Database",
|
type: "Database",
|
||||||
@@ -87,7 +88,7 @@ class AdapterListPage extends BaseListPage {
|
|||||||
...this.getColumnSearchProps("name"),
|
...this.getColumnSearchProps("name"),
|
||||||
render: (text, record, index) => {
|
render: (text, record, index) => {
|
||||||
return (
|
return (
|
||||||
<Link to={`/adapters/${record.organization}/${text}`}>
|
<Link to={`/adapters/${record.owner}/${text}`}>
|
||||||
{text}
|
{text}
|
||||||
</Link>
|
</Link>
|
||||||
);
|
);
|
||||||
@@ -246,7 +247,7 @@ class AdapterListPage extends BaseListPage {
|
|||||||
value = params.type;
|
value = params.type;
|
||||||
}
|
}
|
||||||
this.setState({loading: true});
|
this.setState({loading: true});
|
||||||
AdapterBackend.getAdapters(Setting.isAdminUser(this.props.account) ? "" : this.props.account.owner, params.pagination.current, params.pagination.pageSize, field, value, sortField, sortOrder)
|
AdapterBackend.getAdapters(Setting.isDefaultOrganizationSelected(this.props.account) ? "" : Setting.getRequestOrganization(this.props.account), params.pagination.current, params.pagination.pageSize, field, value, sortField, sortOrder)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
this.setState({
|
this.setState({
|
||||||
loading: false,
|
loading: false,
|
||||||
|
136
web/src/App.js
136
web/src/App.js
@@ -15,9 +15,11 @@
|
|||||||
import React, {Component} from "react";
|
import React, {Component} from "react";
|
||||||
import "./App.less";
|
import "./App.less";
|
||||||
import {Helmet} from "react-helmet";
|
import {Helmet} from "react-helmet";
|
||||||
|
import EnableMfaNotification from "./common/notifaction/EnableMfaNotification";
|
||||||
import GroupTreePage from "./GroupTreePage";
|
import GroupTreePage from "./GroupTreePage";
|
||||||
import GroupEditPage from "./GroupEdit";
|
import GroupEditPage from "./GroupEdit";
|
||||||
import GroupListPage from "./GroupList";
|
import GroupListPage from "./GroupList";
|
||||||
|
import {MfaRuleRequired} from "./Setting";
|
||||||
import * as Setting from "./Setting";
|
import * as Setting from "./Setting";
|
||||||
import {StyleProvider, legacyLogicalPropertiesTransformer} from "@ant-design/cssinjs";
|
import {StyleProvider, legacyLogicalPropertiesTransformer} from "@ant-design/cssinjs";
|
||||||
import {BarsOutlined, CommentOutlined, DownOutlined, InfoCircleFilled, LogoutOutlined, SettingOutlined} from "@ant-design/icons";
|
import {BarsOutlined, CommentOutlined, DownOutlined, InfoCircleFilled, LogoutOutlined, SettingOutlined} from "@ant-design/icons";
|
||||||
@@ -64,6 +66,13 @@ import ProductBuyPage from "./ProductBuyPage";
|
|||||||
import PaymentListPage from "./PaymentListPage";
|
import PaymentListPage from "./PaymentListPage";
|
||||||
import PaymentEditPage from "./PaymentEditPage";
|
import PaymentEditPage from "./PaymentEditPage";
|
||||||
import PaymentResultPage from "./PaymentResultPage";
|
import PaymentResultPage from "./PaymentResultPage";
|
||||||
|
import ModelListPage from "./ModelListPage";
|
||||||
|
import ModelEditPage from "./ModelEditPage";
|
||||||
|
import AdapterListPage from "./AdapterListPage";
|
||||||
|
import AdapterEditPage from "./AdapterEditPage";
|
||||||
|
import SessionListPage from "./SessionListPage";
|
||||||
|
import MfaSetupPage from "./auth/MfaSetupPage";
|
||||||
|
import SystemInfo from "./SystemInfo";
|
||||||
import AccountPage from "./account/AccountPage";
|
import AccountPage from "./account/AccountPage";
|
||||||
import HomePage from "./basic/HomePage";
|
import HomePage from "./basic/HomePage";
|
||||||
import CustomGithubCorner from "./common/CustomGithubCorner";
|
import CustomGithubCorner from "./common/CustomGithubCorner";
|
||||||
@@ -73,19 +82,13 @@ import * as Auth from "./auth/Auth";
|
|||||||
import EntryPage from "./EntryPage";
|
import EntryPage from "./EntryPage";
|
||||||
import * as AuthBackend from "./auth/AuthBackend";
|
import * as AuthBackend from "./auth/AuthBackend";
|
||||||
import AuthCallback from "./auth/AuthCallback";
|
import AuthCallback from "./auth/AuthCallback";
|
||||||
import LanguageSelect from "./common/select/LanguageSelect";
|
|
||||||
import i18next from "i18next";
|
|
||||||
import OdicDiscoveryPage from "./auth/OidcDiscoveryPage";
|
import OdicDiscoveryPage from "./auth/OidcDiscoveryPage";
|
||||||
import SamlCallback from "./auth/SamlCallback";
|
import SamlCallback from "./auth/SamlCallback";
|
||||||
import ModelListPage from "./ModelListPage";
|
import i18next from "i18next";
|
||||||
import ModelEditPage from "./ModelEditPage";
|
|
||||||
import SystemInfo from "./SystemInfo";
|
|
||||||
import AdapterListPage from "./AdapterListPage";
|
|
||||||
import AdapterEditPage from "./AdapterEditPage";
|
|
||||||
import {withTranslation} from "react-i18next";
|
import {withTranslation} from "react-i18next";
|
||||||
|
import LanguageSelect from "./common/select/LanguageSelect";
|
||||||
import ThemeSelect from "./common/select/ThemeSelect";
|
import ThemeSelect from "./common/select/ThemeSelect";
|
||||||
import SessionListPage from "./SessionListPage";
|
import OrganizationSelect from "./common/select/OrganizationSelect";
|
||||||
import MfaSetupPage from "./auth/MfaSetupPage";
|
|
||||||
|
|
||||||
const {Header, Footer, Content} = Layout;
|
const {Header, Footer, Content} = Layout;
|
||||||
|
|
||||||
@@ -101,12 +104,13 @@ class App extends Component {
|
|||||||
themeAlgorithm: ["default"],
|
themeAlgorithm: ["default"],
|
||||||
themeData: Conf.ThemeDefault,
|
themeData: Conf.ThemeDefault,
|
||||||
logo: this.getLogo(Setting.getAlgorithmNames(Conf.ThemeDefault)),
|
logo: this.getLogo(Setting.getAlgorithmNames(Conf.ThemeDefault)),
|
||||||
|
requiredEnableMfa: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
Setting.initServerUrl();
|
Setting.initServerUrl();
|
||||||
Auth.initAuthWithConfig({
|
Auth.initAuthWithConfig({
|
||||||
serverUrl: Setting.ServerUrl,
|
serverUrl: Setting.ServerUrl,
|
||||||
appName: "app-built-in", // the application name of Casdoor itself, do not change it
|
appName: Conf.DefaultApplication, // the application used in Casdoor root path: "/"
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -115,16 +119,29 @@ class App extends Component {
|
|||||||
this.getAccount();
|
this.getAccount();
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidUpdate() {
|
componentDidUpdate(prevProps, prevState, snapshot) {
|
||||||
// eslint-disable-next-line no-restricted-globals
|
|
||||||
const uri = location.pathname;
|
const uri = location.pathname;
|
||||||
if (this.state.uri !== uri) {
|
if (this.state.uri !== uri) {
|
||||||
this.updateMenuKey();
|
this.updateMenuKey();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.state.account !== prevState.account) {
|
||||||
|
const requiredEnableMfa = Setting.isRequiredEnableMfa(this.state.account, this.state.account?.organization);
|
||||||
|
this.setState({
|
||||||
|
requiredEnableMfa: requiredEnableMfa,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (requiredEnableMfa === true) {
|
||||||
|
const mfaType = Setting.getMfaItemsByRules(this.state.account, this.state.account?.organization, [MfaRuleRequired])
|
||||||
|
.find((item) => item.rule === MfaRuleRequired)?.name;
|
||||||
|
if (mfaType !== undefined) {
|
||||||
|
this.props.history.push(`/mfa/setup?mfaType=${mfaType}`, {from: "/login"});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
updateMenuKey() {
|
updateMenuKey() {
|
||||||
// eslint-disable-next-line no-restricted-globals
|
|
||||||
const uri = location.pathname;
|
const uri = location.pathname;
|
||||||
this.setState({
|
this.setState({
|
||||||
uri: uri,
|
uri: uri,
|
||||||
@@ -340,12 +357,16 @@ class App extends Component {
|
|||||||
|
|
||||||
renderRightDropdown() {
|
renderRightDropdown() {
|
||||||
const items = [];
|
const items = [];
|
||||||
items.push(Setting.getItem(<><SettingOutlined /> {i18next.t("account:My Account")}</>,
|
if (this.state.requiredEnableMfa === false) {
|
||||||
"/account"
|
items.push(Setting.getItem(<><SettingOutlined /> {i18next.t("account:My Account")}</>,
|
||||||
));
|
"/account"
|
||||||
items.push(Setting.getItem(<><CommentOutlined /> {i18next.t("account:Chats & Messages")}</>,
|
));
|
||||||
"/chat"
|
if (Conf.EnableChatPages) {
|
||||||
));
|
items.push(Setting.getItem(<><CommentOutlined /> {i18next.t("account:Chats & Messages")}</>,
|
||||||
|
"/chat"
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
items.push(Setting.getItem(<><LogoutOutlined /> {i18next.t("account:Logout")}</>,
|
items.push(Setting.getItem(<><LogoutOutlined /> {i18next.t("account:Logout")}</>,
|
||||||
"/logout"));
|
"/logout"));
|
||||||
|
|
||||||
@@ -396,6 +417,17 @@ class App extends Component {
|
|||||||
});
|
});
|
||||||
}} />
|
}} />
|
||||||
<LanguageSelect languages={this.state.account.organization.languages} />
|
<LanguageSelect languages={this.state.account.organization.languages} />
|
||||||
|
{Setting.isAdminUser(this.state.account) && !Setting.isMobile() &&
|
||||||
|
<OrganizationSelect
|
||||||
|
initValue={Setting.getOrganization()}
|
||||||
|
withAll={true}
|
||||||
|
style={{marginRight: "20px", width: "180px", display: "flex"}}
|
||||||
|
onChange={(value) => {
|
||||||
|
Setting.setOrganization(value);
|
||||||
|
}}
|
||||||
|
className="select-box"
|
||||||
|
/>
|
||||||
|
}
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -411,6 +443,14 @@ class App extends Component {
|
|||||||
res.push(Setting.getItem(<Link to="/">{i18next.t("general:Home")}</Link>, "/"));
|
res.push(Setting.getItem(<Link to="/">{i18next.t("general:Home")}</Link>, "/"));
|
||||||
|
|
||||||
if (Setting.isLocalAdminUser(this.state.account)) {
|
if (Setting.isLocalAdminUser(this.state.account)) {
|
||||||
|
if (Conf.ShowGithubCorner) {
|
||||||
|
res.push(Setting.getItem(<a href={"https://casdoor.com"}>
|
||||||
|
<span style={{fontWeight: "bold", backgroundColor: "rgba(87,52,211,0.4)", marginTop: "12px", paddingLeft: "5px", paddingRight: "5px", display: "flex", alignItems: "center", height: "40px", borderRadius: "5px"}}>
|
||||||
|
🚀 SaaS Hosting 🔥
|
||||||
|
</span>
|
||||||
|
</a>, "#"));
|
||||||
|
}
|
||||||
|
|
||||||
res.push(Setting.getItem(<Link to="/organizations">{i18next.t("general:Organizations")}</Link>,
|
res.push(Setting.getItem(<Link to="/organizations">{i18next.t("general:Organizations")}</Link>,
|
||||||
"/organizations"));
|
"/organizations"));
|
||||||
|
|
||||||
@@ -449,13 +489,15 @@ class App extends Component {
|
|||||||
"/providers"
|
"/providers"
|
||||||
));
|
));
|
||||||
|
|
||||||
res.push(Setting.getItem(<Link to="/chats">{i18next.t("general:Chats")}</Link>,
|
if (Conf.EnableChatPages) {
|
||||||
"/chats"
|
res.push(Setting.getItem(<Link to="/chats">{i18next.t("general:Chats")}</Link>,
|
||||||
));
|
"/chats"
|
||||||
|
));
|
||||||
|
|
||||||
res.push(Setting.getItem(<Link to="/messages">{i18next.t("general:Messages")}</Link>,
|
res.push(Setting.getItem(<Link to="/messages">{i18next.t("general:Messages")}</Link>,
|
||||||
"/messages"
|
"/messages"
|
||||||
));
|
));
|
||||||
|
}
|
||||||
|
|
||||||
res.push(Setting.getItem(<Link to="/resources">{i18next.t("general:Resources")}</Link>,
|
res.push(Setting.getItem(<Link to="/resources">{i18next.t("general:Resources")}</Link>,
|
||||||
"/resources"
|
"/resources"
|
||||||
@@ -476,7 +518,6 @@ class App extends Component {
|
|||||||
res.push(Setting.getItem(<Link to="/subscriptions">{i18next.t("general:Subscriptions")}</Link>,
|
res.push(Setting.getItem(<Link to="/subscriptions">{i18next.t("general:Subscriptions")}</Link>,
|
||||||
"/subscriptions"
|
"/subscriptions"
|
||||||
));
|
));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Setting.isLocalAdminUser(this.state.account)) {
|
if (Setting.isLocalAdminUser(this.state.account)) {
|
||||||
@@ -501,7 +542,6 @@ class App extends Component {
|
|||||||
));
|
));
|
||||||
|
|
||||||
if (Conf.EnableExtraPages) {
|
if (Conf.EnableExtraPages) {
|
||||||
|
|
||||||
res.push(Setting.getItem(<Link to="/products">{i18next.t("general:Products")}</Link>,
|
res.push(Setting.getItem(<Link to="/products">{i18next.t("general:Products")}</Link>,
|
||||||
"/products"
|
"/products"
|
||||||
));
|
));
|
||||||
@@ -510,8 +550,8 @@ class App extends Component {
|
|||||||
"/payments"
|
"/payments"
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Setting.isAdminUser(this.state.account)) {
|
if (Setting.isAdminUser(this.state.account)) {
|
||||||
res.push(Setting.getItem(<Link to="/sysinfo">{i18next.t("general:System Info")}</Link>,
|
res.push(Setting.getItem(<Link to="/sysinfo">{i18next.t("general:System Info")}</Link>,
|
||||||
"/sysinfo"
|
"/sysinfo"
|
||||||
@@ -525,14 +565,6 @@ class App extends Component {
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
renderHomeIfLoggedIn(component) {
|
|
||||||
if (this.state.account !== null && this.state.account !== undefined) {
|
|
||||||
return <Redirect to="/" />;
|
|
||||||
} else {
|
|
||||||
return component;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
renderLoginIfNotLoggedIn(component) {
|
renderLoginIfNotLoggedIn(component) {
|
||||||
if (this.state.account === null) {
|
if (this.state.account === null) {
|
||||||
sessionStorage.setItem("from", window.location.pathname);
|
sessionStorage.setItem("from", window.location.pathname);
|
||||||
@@ -544,12 +576,6 @@ class App extends Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
isStartPages() {
|
|
||||||
return window.location.pathname.startsWith("/login") ||
|
|
||||||
window.location.pathname.startsWith("/signup") ||
|
|
||||||
window.location.pathname === "/";
|
|
||||||
}
|
|
||||||
|
|
||||||
renderRouter() {
|
renderRouter() {
|
||||||
return (
|
return (
|
||||||
<Switch>
|
<Switch>
|
||||||
@@ -601,13 +627,13 @@ class App extends Component {
|
|||||||
<Route exact path="/subscriptions" render={(props) => this.renderLoginIfNotLoggedIn(<SubscriptionListPage account={this.state.account} {...props} />)} />
|
<Route exact path="/subscriptions" render={(props) => this.renderLoginIfNotLoggedIn(<SubscriptionListPage account={this.state.account} {...props} />)} />
|
||||||
<Route exact path="/subscriptions/:organizationName/:subscriptionName" render={(props) => this.renderLoginIfNotLoggedIn(<SubscriptionEditPage account={this.state.account} {...props} />)} />
|
<Route exact path="/subscriptions/:organizationName/:subscriptionName" render={(props) => this.renderLoginIfNotLoggedIn(<SubscriptionEditPage account={this.state.account} {...props} />)} />
|
||||||
<Route exact path="/products" render={(props) => this.renderLoginIfNotLoggedIn(<ProductListPage account={this.state.account} {...props} />)} />
|
<Route exact path="/products" render={(props) => this.renderLoginIfNotLoggedIn(<ProductListPage account={this.state.account} {...props} />)} />
|
||||||
<Route exact path="/products/:productName" render={(props) => this.renderLoginIfNotLoggedIn(<ProductEditPage account={this.state.account} {...props} />)} />
|
<Route exact path="/products/:organizationName/:productName" render={(props) => this.renderLoginIfNotLoggedIn(<ProductEditPage account={this.state.account} {...props} />)} />
|
||||||
<Route exact path="/products/:productName/buy" render={(props) => this.renderLoginIfNotLoggedIn(<ProductBuyPage account={this.state.account} {...props} />)} />
|
<Route exact path="/products/:productName/buy" render={(props) => this.renderLoginIfNotLoggedIn(<ProductBuyPage account={this.state.account} {...props} />)} />
|
||||||
<Route exact path="/payments" render={(props) => this.renderLoginIfNotLoggedIn(<PaymentListPage account={this.state.account} {...props} />)} />
|
<Route exact path="/payments" render={(props) => this.renderLoginIfNotLoggedIn(<PaymentListPage account={this.state.account} {...props} />)} />
|
||||||
<Route exact path="/payments/:paymentName" render={(props) => this.renderLoginIfNotLoggedIn(<PaymentEditPage account={this.state.account} {...props} />)} />
|
<Route exact path="/payments/:paymentName" render={(props) => this.renderLoginIfNotLoggedIn(<PaymentEditPage account={this.state.account} {...props} />)} />
|
||||||
<Route exact path="/payments/:paymentName/result" render={(props) => this.renderLoginIfNotLoggedIn(<PaymentResultPage account={this.state.account} {...props} />)} />
|
<Route exact path="/payments/:paymentName/result" render={(props) => this.renderLoginIfNotLoggedIn(<PaymentResultPage account={this.state.account} {...props} />)} />
|
||||||
<Route exact path="/records" render={(props) => this.renderLoginIfNotLoggedIn(<RecordListPage account={this.state.account} {...props} />)} />
|
<Route exact path="/records" render={(props) => this.renderLoginIfNotLoggedIn(<RecordListPage account={this.state.account} {...props} />)} />
|
||||||
<Route exact path="/mfa-authentication/setup" render={(props) => this.renderLoginIfNotLoggedIn(<MfaSetupPage account={this.state.account} {...props} />)} />
|
<Route exact path="/mfa/setup" render={(props) => this.renderLoginIfNotLoggedIn(<MfaSetupPage account={this.state.account} onfinish={() => this.setState({requiredEnableMfa: false})} {...props} />)} />
|
||||||
<Route exact path="/.well-known/openid-configuration" render={(props) => <OdicDiscoveryPage />} />
|
<Route exact path="/.well-known/openid-configuration" render={(props) => <OdicDiscoveryPage />} />
|
||||||
<Route exact path="/sysinfo" render={(props) => this.renderLoginIfNotLoggedIn(<SystemInfo account={this.state.account} {...props} />)} />
|
<Route exact path="/sysinfo" render={(props) => this.renderLoginIfNotLoggedIn(<SystemInfo account={this.state.account} {...props} />)} />
|
||||||
<Route path="" render={() => <Result status="404" title="404 NOT FOUND" subTitle={i18next.t("general:Sorry, the page you visited does not exist.")}
|
<Route path="" render={() => <Result status="404" title="404 NOT FOUND" subTitle={i18next.t("general:Sorry, the page you visited does not exist.")}
|
||||||
@@ -638,18 +664,24 @@ class App extends Component {
|
|||||||
if (key === "/swagger") {
|
if (key === "/swagger") {
|
||||||
window.open(Setting.isLocalhost() ? `${Setting.ServerUrl}/swagger` : "/swagger", "_blank");
|
window.open(Setting.isLocalhost() ? `${Setting.ServerUrl}/swagger` : "/swagger", "_blank");
|
||||||
} else {
|
} else {
|
||||||
this.props.history.push(key);
|
if (this.state.requiredEnableMfa) {
|
||||||
|
Setting.showMessage("info", "Please enable MFA first!");
|
||||||
|
} else {
|
||||||
|
this.props.history.push(key);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
const menuStyleRight = Setting.isAdminUser(this.state.account) && !Setting.isMobile() ? "calc(180px + 260px)" : "260px";
|
||||||
return (
|
return (
|
||||||
<Layout id="parent-area">
|
<Layout id="parent-area">
|
||||||
<Header style={{padding: "0", marginBottom: "3px", backgroundColor: this.state.themeAlgorithm.includes("dark") ? "black" : "white"}}>
|
<EnableMfaNotification account={this.state.account} />
|
||||||
|
<Header style={{padding: "0", marginBottom: "3px", backgroundColor: this.state.themeAlgorithm.includes("dark") ? "black" : "white"}} >
|
||||||
{Setting.isMobile() ? null : (
|
{Setting.isMobile() ? null : (
|
||||||
<Link to={"/"}>
|
<Link to={"/"}>
|
||||||
<div className="logo" style={{background: `url(${this.state.logo})`}} />
|
<div className="logo" style={{background: `url(${this.state.logo})`}} />
|
||||||
</Link>
|
</Link>
|
||||||
)}
|
)}
|
||||||
{Setting.isMobile() ?
|
{this.state.requiredEnableMfa || (Setting.isMobile() ?
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
<Drawer title={i18next.t("general:Close")} placement="left" visible={this.state.menuVisible} onClose={this.onClose}>
|
<Drawer title={i18next.t("general:Close")} placement="left" visible={this.state.menuVisible} onClose={this.onClose}>
|
||||||
<Menu
|
<Menu
|
||||||
@@ -670,9 +702,9 @@ class App extends Component {
|
|||||||
items={this.getMenuItems()}
|
items={this.getMenuItems()}
|
||||||
mode={"horizontal"}
|
mode={"horizontal"}
|
||||||
selectedKeys={[this.state.selectedMenuKey]}
|
selectedKeys={[this.state.selectedMenuKey]}
|
||||||
style={{position: "absolute", left: "145px", right: "260px"}}
|
style={{position: "absolute", left: "145px", right: menuStyleRight}}
|
||||||
/>
|
/>
|
||||||
}
|
)}
|
||||||
{
|
{
|
||||||
this.renderAccountMenu()
|
this.renderAccountMenu()
|
||||||
}
|
}
|
||||||
@@ -736,9 +768,11 @@ class App extends Component {
|
|||||||
<EntryPage
|
<EntryPage
|
||||||
account={this.state.account}
|
account={this.state.account}
|
||||||
theme={this.state.themeData}
|
theme={this.state.themeData}
|
||||||
onUpdateAccount={(account) => {
|
onLoginSuccess={(redirectUrl) => {
|
||||||
this.onUpdateAccount(account);
|
localStorage.setItem("mfaRedirectUrl", redirectUrl);
|
||||||
|
this.getAccount();
|
||||||
}}
|
}}
|
||||||
|
onUpdateAccount={(account) => this.onUpdateAccount(account)}
|
||||||
updataThemeData={this.setTheme}
|
updataThemeData={this.setTheme}
|
||||||
/> :
|
/> :
|
||||||
<Switch>
|
<Switch>
|
||||||
|
@@ -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"))} :
|
||||||
|
@@ -28,18 +28,13 @@ class ApplicationListPage extends BaseListPage {
|
|||||||
super(props);
|
super(props);
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
|
||||||
this.setState({
|
|
||||||
organizationName: this.props.account.owner,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
newApplication() {
|
newApplication() {
|
||||||
const randomName = Setting.getRandomName();
|
const randomName = Setting.getRandomName();
|
||||||
|
const organizationName = Setting.getRequestOrganization(this.props.account);
|
||||||
return {
|
return {
|
||||||
owner: "admin", // this.props.account.applicationName,
|
owner: "admin", // this.props.account.applicationName,
|
||||||
name: `application_${randomName}`,
|
name: `application_${randomName}`,
|
||||||
organization: this.state.organizationName,
|
organization: organizationName,
|
||||||
createdTime: moment().format(),
|
createdTime: moment().format(),
|
||||||
displayName: `New Application - ${randomName}`,
|
displayName: `New Application - ${randomName}`,
|
||||||
logo: `${Setting.StaticBaseUrl}/img/casdoor-logo_1185x256.png`,
|
logo: `${Setting.StaticBaseUrl}/img/casdoor-logo_1185x256.png`,
|
||||||
@@ -273,8 +268,8 @@ class ApplicationListPage extends BaseListPage {
|
|||||||
const field = params.searchedColumn, value = params.searchText;
|
const field = params.searchedColumn, value = params.searchText;
|
||||||
const sortField = params.sortField, sortOrder = params.sortOrder;
|
const sortField = params.sortField, sortOrder = params.sortOrder;
|
||||||
this.setState({loading: true});
|
this.setState({loading: true});
|
||||||
(Setting.isAdminUser(this.props.account) ? ApplicationBackend.getApplications("admin", params.pagination.current, params.pagination.pageSize, field, value, sortField, sortOrder) :
|
(Setting.isDefaultOrganizationSelected(this.props.account) ? ApplicationBackend.getApplications("admin", params.pagination.current, params.pagination.pageSize, field, value, sortField, sortOrder) :
|
||||||
ApplicationBackend.getApplicationsByOrganization("admin", this.props.account.organization.name, params.pagination.current, params.pagination.pageSize, field, value, sortField, sortOrder))
|
ApplicationBackend.getApplicationsByOrganization("admin", Setting.getRequestOrganization(this.props.account), params.pagination.current, params.pagination.pageSize, field, value, sortField, sortOrder))
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
this.setState({
|
this.setState({
|
||||||
loading: false,
|
loading: false,
|
||||||
|
@@ -17,6 +17,7 @@ import {Button, Input, Result, Space} from "antd";
|
|||||||
import {SearchOutlined} from "@ant-design/icons";
|
import {SearchOutlined} from "@ant-design/icons";
|
||||||
import Highlighter from "react-highlight-words";
|
import Highlighter from "react-highlight-words";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
|
import * as Setting from "./Setting";
|
||||||
|
|
||||||
class BaseListPage extends React.Component {
|
class BaseListPage extends React.Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
@@ -35,6 +36,22 @@ class BaseListPage extends React.Component {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleOrganizationChange = () => {
|
||||||
|
const {pagination} = this.state;
|
||||||
|
this.fetch({pagination});
|
||||||
|
};
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
window.addEventListener("storageOrganizationChanged", this.handleOrganizationChange);
|
||||||
|
if (!Setting.isAdminUser(this.props.account)) {
|
||||||
|
Setting.setOrganization("All");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillUnmount() {
|
||||||
|
window.removeEventListener("storageOrganizationChanged", this.handleOrganizationChange);
|
||||||
|
}
|
||||||
|
|
||||||
UNSAFE_componentWillMount() {
|
UNSAFE_componentWillMount() {
|
||||||
const {pagination} = this.state;
|
const {pagination} = this.state;
|
||||||
this.fetch({pagination});
|
this.fetch({pagination});
|
||||||
|
@@ -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,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@@ -28,6 +28,7 @@ class CertListPage extends BaseListPage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
|
super.componentDidMount();
|
||||||
this.setState({
|
this.setState({
|
||||||
owner: Setting.isAdminUser(this.props.account) ? "admin" : this.props.account.owner,
|
owner: Setting.isAdminUser(this.props.account) ? "admin" : this.props.account.owner,
|
||||||
});
|
});
|
||||||
@@ -35,8 +36,9 @@ class CertListPage extends BaseListPage {
|
|||||||
|
|
||||||
newCert() {
|
newCert() {
|
||||||
const randomName = Setting.getRandomName();
|
const randomName = Setting.getRandomName();
|
||||||
|
const owner = Setting.isDefaultOrganizationSelected(this.props.account) ? this.state.owner : Setting.getRequestOrganization(this.props.account);
|
||||||
return {
|
return {
|
||||||
owner: this.state.owner,
|
owner: owner,
|
||||||
name: `cert_${randomName}`,
|
name: `cert_${randomName}`,
|
||||||
createdTime: moment().format(),
|
createdTime: moment().format(),
|
||||||
displayName: `New Cert - ${randomName}`,
|
displayName: `New Cert - ${randomName}`,
|
||||||
@@ -211,7 +213,7 @@ class CertListPage extends BaseListPage {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Table scroll={{x: "max-content"}} columns={columns} dataSource={certs} rowKey="name" size="middle" bordered pagination={paginationProps}
|
<Table scroll={{x: "max-content"}} columns={columns} dataSource={certs} rowKey={(record) => `${record.owner}/${record.name}`} size="middle" bordered pagination={paginationProps}
|
||||||
title={() => (
|
title={() => (
|
||||||
<div>
|
<div>
|
||||||
{i18next.t("general:Certs")}
|
{i18next.t("general:Certs")}
|
||||||
@@ -236,8 +238,8 @@ class CertListPage extends BaseListPage {
|
|||||||
value = params.type;
|
value = params.type;
|
||||||
}
|
}
|
||||||
this.setState({loading: true});
|
this.setState({loading: true});
|
||||||
(Setting.isAdminUser(this.props.account) ? CertBackend.getGlobleCerts(params.pagination.current, params.pagination.pageSize, field, value, sortField, sortOrder)
|
(Setting.isDefaultOrganizationSelected(this.props.account) ? CertBackend.getGlobleCerts(params.pagination.current, params.pagination.pageSize, field, value, sortField, sortOrder)
|
||||||
: CertBackend.getCerts(this.props.account.owner, params.pagination.current, params.pagination.pageSize, field, value, sortField, sortOrder))
|
: CertBackend.getCerts(Setting.getRequestOrganization(this.props.account), params.pagination.current, params.pagination.pageSize, field, value, sortField, sortOrder))
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
this.setState({
|
this.setState({
|
||||||
loading: false,
|
loading: false,
|
||||||
|
@@ -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,
|
||||||
});
|
});
|
||||||
|
@@ -25,12 +25,13 @@ import PopconfirmModal from "./common/modal/PopconfirmModal";
|
|||||||
class ChatListPage extends BaseListPage {
|
class ChatListPage extends BaseListPage {
|
||||||
newChat() {
|
newChat() {
|
||||||
const randomName = Setting.getRandomName();
|
const randomName = Setting.getRandomName();
|
||||||
|
const organizationName = Setting.getRequestOrganization(this.props.account);
|
||||||
return {
|
return {
|
||||||
owner: "admin", // this.props.account.applicationName,
|
owner: "admin", // this.props.account.applicationName,
|
||||||
name: `chat_${randomName}`,
|
name: `chat_${randomName}`,
|
||||||
createdTime: moment().format(),
|
createdTime: moment().format(),
|
||||||
updatedTime: moment().format(),
|
updatedTime: moment().format(),
|
||||||
organization: this.props.account.owner,
|
organization: organizationName,
|
||||||
displayName: `New Chat - ${randomName}`,
|
displayName: `New Chat - ${randomName}`,
|
||||||
type: "Single",
|
type: "Single",
|
||||||
category: "Chat Category - 1",
|
category: "Chat Category - 1",
|
||||||
|
@@ -1,32 +1,34 @@
|
|||||||
// Copyright 2021 The Casdoor Authors. All Rights Reserved.
|
// Copyright 2021 The Casdoor Authors. All Rights Reserved.
|
||||||
//
|
//
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with the License.
|
// you may not use this file except in compliance with the License.
|
||||||
// You may obtain a copy of the License at
|
// You may obtain a copy of the License at
|
||||||
//
|
//
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
//
|
//
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
// 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.
|
||||||
|
|
||||||
export const ShowGithubCorner = false;
|
export const DefaultApplication = "app-built-in";
|
||||||
export const GithubRepo = "https://github.com/casdoor/casdoor";
|
|
||||||
export const IsDemoMode = false;
|
export const ShowGithubCorner = false;
|
||||||
|
export const IsDemoMode = false;
|
||||||
export const ForceLanguage = "";
|
|
||||||
export const DefaultLanguage = "en";
|
export const ForceLanguage = "";
|
||||||
|
export const DefaultLanguage = "en";
|
||||||
export const EnableExtraPages = true;
|
|
||||||
|
export const EnableExtraPages = true;
|
||||||
export const InitThemeAlgorithm = true;
|
export const EnableChatPages = true;
|
||||||
export const ThemeDefault = {
|
|
||||||
themeType: "default",
|
export const InitThemeAlgorithm = true;
|
||||||
colorPrimary: "#5734d3",
|
export const ThemeDefault = {
|
||||||
borderRadius: 6,
|
themeType: "default",
|
||||||
isCompact: false,
|
colorPrimary: "#5734d3",
|
||||||
};
|
borderRadius: 6,
|
||||||
|
isCompact: false,
|
||||||
export const CustomFooter = null;
|
};
|
||||||
|
|
||||||
|
export const CustomFooter = null;
|
||||||
|
@@ -41,7 +41,7 @@ class EntryPage extends React.Component {
|
|||||||
|
|
||||||
renderHomeIfLoggedIn(component) {
|
renderHomeIfLoggedIn(component) {
|
||||||
if (this.props.account !== null && this.props.account !== undefined) {
|
if (this.props.account !== null && this.props.account !== undefined) {
|
||||||
return <Redirect to="/" />;
|
return <Redirect to={{pathname: "/", state: {from: "/login"}}} />;
|
||||||
} else {
|
} else {
|
||||||
return component;
|
return component;
|
||||||
}
|
}
|
||||||
@@ -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);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@@ -49,8 +49,9 @@ class GroupListPage extends BaseListPage {
|
|||||||
|
|
||||||
newGroup() {
|
newGroup() {
|
||||||
const randomName = Setting.getRandomName();
|
const randomName = Setting.getRandomName();
|
||||||
|
const owner = Setting.getRequestOrganization(this.props.account);
|
||||||
return {
|
return {
|
||||||
owner: this.props.account.owner,
|
owner: owner,
|
||||||
name: `group_${randomName}`,
|
name: `group_${randomName}`,
|
||||||
createdTime: moment().format(),
|
createdTime: moment().format(),
|
||||||
updatedTime: moment().format(),
|
updatedTime: moment().format(),
|
||||||
@@ -251,7 +252,7 @@ class GroupListPage extends BaseListPage {
|
|||||||
value = params.type;
|
value = params.type;
|
||||||
}
|
}
|
||||||
this.setState({loading: true});
|
this.setState({loading: true});
|
||||||
GroupBackend.getGroups(this.state.owner, false, params.pagination.current, params.pagination.pageSize, field, value, sortField, sortOrder)
|
GroupBackend.getGroups(Setting.isDefaultOrganizationSelected(this.props.account) ? "" : Setting.getRequestOrganization(this.props.account), false, params.pagination.current, params.pagination.pageSize, field, value, sortField, sortOrder)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
this.setState({
|
this.setState({
|
||||||
loading: false,
|
loading: false,
|
||||||
|
@@ -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,
|
||||||
});
|
});
|
||||||
|
@@ -25,11 +25,12 @@ import PopconfirmModal from "./common/modal/PopconfirmModal";
|
|||||||
class MessageListPage extends BaseListPage {
|
class MessageListPage extends BaseListPage {
|
||||||
newMessage() {
|
newMessage() {
|
||||||
const randomName = Setting.getRandomName();
|
const randomName = Setting.getRandomName();
|
||||||
|
const organizationName = Setting.getRequestOrganization(this.props.account);
|
||||||
return {
|
return {
|
||||||
owner: "admin", // this.props.account.messagename,
|
owner: "admin", // this.props.account.messagename,
|
||||||
name: `message_${randomName}`,
|
name: `message_${randomName}`,
|
||||||
createdTime: moment().format(),
|
createdTime: moment().format(),
|
||||||
organization: this.props.account.owner,
|
organization: organizationName,
|
||||||
chat: "",
|
chat: "",
|
||||||
replyTo: "",
|
replyTo: "",
|
||||||
author: `${this.props.account.owner}/${this.props.account.name}`,
|
author: `${this.props.account.owner}/${this.props.account.name}`,
|
||||||
@@ -208,7 +209,7 @@ class MessageListPage extends BaseListPage {
|
|||||||
value = params.type;
|
value = params.type;
|
||||||
}
|
}
|
||||||
this.setState({loading: true});
|
this.setState({loading: true});
|
||||||
MessageBackend.getMessages("admin", Setting.isAdminUser(this.props.account) ? "" : this.props.account.owner, params.pagination.current, params.pagination.pageSize, field, value, sortField, sortOrder)
|
MessageBackend.getMessages("admin", Setting.isDefaultOrganizationSelected(this.props.account) ? "" : Setting.getRequestOrganization(this.props.account), params.pagination.current, params.pagination.pageSize, field, value, sortField, sortOrder)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
this.setState({
|
this.setState({
|
||||||
loading: false,
|
loading: false,
|
||||||
|
@@ -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,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@@ -40,8 +40,9 @@ m = g(r.sub, p.sub) && r.obj == p.obj && r.act == p.act`;
|
|||||||
class ModelListPage extends BaseListPage {
|
class ModelListPage extends BaseListPage {
|
||||||
newModel() {
|
newModel() {
|
||||||
const randomName = Setting.getRandomName();
|
const randomName = Setting.getRandomName();
|
||||||
|
const owner = Setting.getRequestOrganization(this.props.account);
|
||||||
return {
|
return {
|
||||||
owner: this.props.account.owner,
|
owner: owner,
|
||||||
name: `model_${randomName}`,
|
name: `model_${randomName}`,
|
||||||
createdTime: moment().format(),
|
createdTime: moment().format(),
|
||||||
displayName: `New Model - ${randomName}`,
|
displayName: `New Model - ${randomName}`,
|
||||||
@@ -202,7 +203,7 @@ class ModelListPage extends BaseListPage {
|
|||||||
value = params.type;
|
value = params.type;
|
||||||
}
|
}
|
||||||
this.setState({loading: true});
|
this.setState({loading: true});
|
||||||
ModelBackend.getModels(Setting.isAdminUser(this.props.account) ? "" : this.props.account.owner, params.pagination.current, params.pagination.pageSize, field, value, sortField, sortOrder)
|
ModelBackend.getModels(Setting.isDefaultOrganizationSelected(this.props.account) ? "" : Setting.getRequestOrganization(this.props.account), params.pagination.current, params.pagination.pageSize, field, value, sortField, sortOrder)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
this.setState({
|
this.setState({
|
||||||
loading: false,
|
loading: false,
|
||||||
|
@@ -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,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -422,6 +427,7 @@ class OrganizationEditPage extends React.Component {
|
|||||||
this.setState({
|
this.setState({
|
||||||
organizationName: this.state.organization.name,
|
organizationName: this.state.organization.name,
|
||||||
});
|
});
|
||||||
|
window.dispatchEvent(new Event("storageOrganizationsChanged"));
|
||||||
|
|
||||||
if (willExist) {
|
if (willExist) {
|
||||||
this.props.history.push("/organizations");
|
this.props.history.push("/organizations");
|
||||||
@@ -443,6 +449,7 @@ class OrganizationEditPage extends React.Component {
|
|||||||
.then((res) => {
|
.then((res) => {
|
||||||
if (res.status === "ok") {
|
if (res.status === "ok") {
|
||||||
this.props.history.push("/organizations");
|
this.props.history.push("/organizations");
|
||||||
|
window.dispatchEvent(new Event("storageOrganizationsChanged"));
|
||||||
} else {
|
} else {
|
||||||
Setting.showMessage("error", `${i18next.t("general:Failed to delete")}: ${res.msg}`);
|
Setting.showMessage("error", `${i18next.t("general:Failed to delete")}: ${res.msg}`);
|
||||||
}
|
}
|
||||||
|
@@ -35,7 +35,7 @@ class OrganizationListPage extends BaseListPage {
|
|||||||
passwordType: "plain",
|
passwordType: "plain",
|
||||||
PasswordSalt: "",
|
PasswordSalt: "",
|
||||||
passwordOptions: [],
|
passwordOptions: [],
|
||||||
countryCodes: ["CN"],
|
countryCodes: ["US"],
|
||||||
defaultAvatar: `${Setting.StaticBaseUrl}/img/casbin.svg`,
|
defaultAvatar: `${Setting.StaticBaseUrl}/img/casbin.svg`,
|
||||||
defaultApplication: "",
|
defaultApplication: "",
|
||||||
tags: [],
|
tags: [],
|
||||||
@@ -53,25 +53,40 @@ class OrganizationListPage extends BaseListPage {
|
|||||||
{name: "Password", visible: true, viewRule: "Self", modifyRule: "Self"},
|
{name: "Password", visible: true, viewRule: "Self", modifyRule: "Self"},
|
||||||
{name: "Email", visible: true, viewRule: "Public", modifyRule: "Self"},
|
{name: "Email", visible: true, viewRule: "Public", modifyRule: "Self"},
|
||||||
{name: "Phone", visible: true, viewRule: "Public", modifyRule: "Self"},
|
{name: "Phone", visible: true, viewRule: "Public", modifyRule: "Self"},
|
||||||
|
{name: "Country code", visible: true, viewRule: "Public", modifyRule: "Self"},
|
||||||
{name: "Country/Region", visible: true, viewRule: "Public", modifyRule: "Self"},
|
{name: "Country/Region", visible: true, viewRule: "Public", modifyRule: "Self"},
|
||||||
{name: "Location", visible: true, viewRule: "Public", modifyRule: "Self"},
|
{name: "Location", visible: true, viewRule: "Public", modifyRule: "Self"},
|
||||||
|
{name: "Address", visible: true, viewRule: "Public", modifyRule: "Self"},
|
||||||
{name: "Affiliation", visible: true, viewRule: "Public", modifyRule: "Self"},
|
{name: "Affiliation", visible: true, viewRule: "Public", modifyRule: "Self"},
|
||||||
{name: "Title", visible: true, viewRule: "Public", modifyRule: "Self"},
|
{name: "Title", visible: true, viewRule: "Public", modifyRule: "Self"},
|
||||||
|
{name: "ID card type", visible: true, viewRule: "Public", modifyRule: "Self"},
|
||||||
|
{name: "ID card", visible: true, viewRule: "Public", modifyRule: "Self"},
|
||||||
|
{name: "ID card info", visible: true, viewRule: "Public", modifyRule: "Self"},
|
||||||
{name: "Homepage", visible: true, viewRule: "Public", modifyRule: "Self"},
|
{name: "Homepage", visible: true, viewRule: "Public", modifyRule: "Self"},
|
||||||
{name: "Bio", visible: true, viewRule: "Public", modifyRule: "Self"},
|
{name: "Bio", visible: true, viewRule: "Public", modifyRule: "Self"},
|
||||||
{name: "Tag", visible: true, viewRule: "Public", modifyRule: "Admin"},
|
{name: "Tag", visible: true, viewRule: "Public", modifyRule: "Admin"},
|
||||||
|
{name: "Language", visible: true, viewRule: "Public", modifyRule: "Admin"},
|
||||||
|
{name: "Gender", visible: true, viewRule: "Public", modifyRule: "Admin"},
|
||||||
|
{name: "Birthday", visible: true, viewRule: "Public", modifyRule: "Admin"},
|
||||||
|
{name: "Education", visible: true, viewRule: "Public", modifyRule: "Admin"},
|
||||||
|
{name: "Score", visible: true, viewRule: "Public", modifyRule: "Admin"},
|
||||||
|
{name: "Karma", visible: true, viewRule: "Public", modifyRule: "Admin"},
|
||||||
|
{name: "Ranking", visible: true, viewRule: "Public", modifyRule: "Admin"},
|
||||||
{name: "Signup application", visible: true, viewRule: "Public", modifyRule: "Admin"},
|
{name: "Signup application", visible: true, viewRule: "Public", modifyRule: "Admin"},
|
||||||
{name: "API key", label: i18next.t("general:API key")},
|
{name: "API key", label: i18next.t("general:API key"), modifyRule: "Self"},
|
||||||
|
{name: "Groups", visible: true, viewRule: "Public", modifyRule: "Admin"},
|
||||||
{name: "Roles", visible: true, viewRule: "Public", modifyRule: "Immutable"},
|
{name: "Roles", visible: true, viewRule: "Public", modifyRule: "Immutable"},
|
||||||
{name: "Permissions", visible: true, viewRule: "Public", modifyRule: "Immutable"},
|
{name: "Permissions", visible: true, viewRule: "Public", modifyRule: "Immutable"},
|
||||||
{name: "Groups", visible: true, viewRule: "Public", modifyRule: "Immutable"},
|
|
||||||
{name: "3rd-party logins", visible: true, viewRule: "Self", modifyRule: "Self"},
|
{name: "3rd-party logins", visible: true, viewRule: "Self", modifyRule: "Self"},
|
||||||
{Name: "Multi-factor authentication", Visible: true, ViewRule: "Self", ModifyRule: "Self"},
|
|
||||||
{name: "Properties", visible: false, viewRule: "Admin", modifyRule: "Admin"},
|
{name: "Properties", visible: false, viewRule: "Admin", modifyRule: "Admin"},
|
||||||
|
{name: "Is online", visible: true, viewRule: "Admin", modifyRule: "Admin"},
|
||||||
{name: "Is admin", visible: true, viewRule: "Admin", modifyRule: "Admin"},
|
{name: "Is admin", visible: true, viewRule: "Admin", modifyRule: "Admin"},
|
||||||
{name: "Is global admin", visible: true, viewRule: "Admin", modifyRule: "Admin"},
|
{name: "Is global admin", visible: true, viewRule: "Admin", modifyRule: "Admin"},
|
||||||
{name: "Is forbidden", visible: true, viewRule: "Admin", modifyRule: "Admin"},
|
{name: "Is forbidden", visible: true, viewRule: "Admin", modifyRule: "Admin"},
|
||||||
{name: "Is deleted", visible: true, viewRule: "Admin", modifyRule: "Admin"},
|
{name: "Is deleted", visible: true, viewRule: "Admin", modifyRule: "Admin"},
|
||||||
|
{Name: "Multi-factor authentication", Visible: true, ViewRule: "Self", ModifyRule: "Self"},
|
||||||
|
{Name: "WebAuthn credentials", Visible: true, ViewRule: "Self", ModifyRule: "Self"},
|
||||||
|
{Name: "Managed accounts", Visible: true, ViewRule: "Self", ModifyRule: "Self"},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -83,6 +98,7 @@ class OrganizationListPage extends BaseListPage {
|
|||||||
if (res.status === "ok") {
|
if (res.status === "ok") {
|
||||||
this.props.history.push({pathname: `/organizations/${newOrganization.name}`, mode: "add"});
|
this.props.history.push({pathname: `/organizations/${newOrganization.name}`, mode: "add"});
|
||||||
Setting.showMessage("success", i18next.t("general:Successfully added"));
|
Setting.showMessage("success", i18next.t("general:Successfully added"));
|
||||||
|
window.dispatchEvent(new Event("storageOrganizationsChanged"));
|
||||||
} else {
|
} else {
|
||||||
Setting.showMessage("error", `${i18next.t("general:Failed to add")}: ${res.msg}`);
|
Setting.showMessage("error", `${i18next.t("general:Failed to add")}: ${res.msg}`);
|
||||||
}
|
}
|
||||||
@@ -99,8 +115,11 @@ class OrganizationListPage extends BaseListPage {
|
|||||||
Setting.showMessage("success", i18next.t("general:Successfully deleted"));
|
Setting.showMessage("success", i18next.t("general:Successfully deleted"));
|
||||||
this.setState({
|
this.setState({
|
||||||
data: Setting.deleteRow(this.state.data, i),
|
data: Setting.deleteRow(this.state.data, i),
|
||||||
pagination: {total: this.state.pagination.total - 1},
|
pagination: {
|
||||||
|
...this.state.pagination,
|
||||||
|
total: this.state.pagination.total - 1},
|
||||||
});
|
});
|
||||||
|
window.dispatchEvent(new Event("storageOrganizationsChanged"));
|
||||||
} else {
|
} else {
|
||||||
Setting.showMessage("error", `${i18next.t("general:Failed to delete")}: ${res.msg}`);
|
Setting.showMessage("error", `${i18next.t("general:Failed to delete")}: ${res.msg}`);
|
||||||
}
|
}
|
||||||
@@ -275,7 +294,7 @@ class OrganizationListPage extends BaseListPage {
|
|||||||
value = params.passwordType;
|
value = params.passwordType;
|
||||||
}
|
}
|
||||||
this.setState({loading: true});
|
this.setState({loading: true});
|
||||||
OrganizationBackend.getOrganizations("admin", params.pagination.current, params.pagination.pageSize, field, value, sortField, sortOrder)
|
OrganizationBackend.getOrganizations("admin", Setting.isDefaultOrganizationSelected(this.props.account) ? "" : Setting.getRequestOrganization(this.props.account), params.pagination.current, params.pagination.pageSize, field, value, sortField, sortOrder)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
this.setState({
|
this.setState({
|
||||||
loading: false,
|
loading: false,
|
||||||
|
@@ -26,6 +26,7 @@ import PopconfirmModal from "./common/modal/PopconfirmModal";
|
|||||||
class PaymentListPage extends BaseListPage {
|
class PaymentListPage extends BaseListPage {
|
||||||
newPayment() {
|
newPayment() {
|
||||||
const randomName = Setting.getRandomName();
|
const randomName = Setting.getRandomName();
|
||||||
|
const organizationName = Setting.getRequestOrganization(this.props.account);
|
||||||
return {
|
return {
|
||||||
owner: "admin",
|
owner: "admin",
|
||||||
name: `payment_${randomName}`,
|
name: `payment_${randomName}`,
|
||||||
@@ -33,7 +34,7 @@ class PaymentListPage extends BaseListPage {
|
|||||||
displayName: `New Payment - ${randomName}`,
|
displayName: `New Payment - ${randomName}`,
|
||||||
provider: "provider_pay_paypal",
|
provider: "provider_pay_paypal",
|
||||||
type: "PayPal",
|
type: "PayPal",
|
||||||
organization: this.props.account.owner,
|
organization: organizationName,
|
||||||
user: "admin",
|
user: "admin",
|
||||||
productName: "computer-1",
|
productName: "computer-1",
|
||||||
productDisplayName: "A notebook computer",
|
productDisplayName: "A notebook computer",
|
||||||
@@ -265,7 +266,7 @@ class PaymentListPage extends BaseListPage {
|
|||||||
value = params.type;
|
value = params.type;
|
||||||
}
|
}
|
||||||
this.setState({loading: true});
|
this.setState({loading: true});
|
||||||
PaymentBackend.getPayments("admin", Setting.isAdminUser(this.props.account) ? "" : this.props.account.owner, params.pagination.current, params.pagination.pageSize, field, value, sortField, sortOrder)
|
PaymentBackend.getPayments("admin", Setting.isDefaultOrganizationSelected(this.props.account) ? "" : Setting.getRequestOrganization(this.props.account), params.pagination.current, params.pagination.pageSize, field, value, sortField, sortOrder)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
this.setState({
|
this.setState({
|
||||||
loading: false,
|
loading: false,
|
||||||
|
@@ -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,
|
||||||
});
|
});
|
||||||
|
@@ -26,8 +26,9 @@ import {UploadOutlined} from "@ant-design/icons";
|
|||||||
class PermissionListPage extends BaseListPage {
|
class PermissionListPage extends BaseListPage {
|
||||||
newPermission() {
|
newPermission() {
|
||||||
const randomName = Setting.getRandomName();
|
const randomName = Setting.getRandomName();
|
||||||
|
const owner = Setting.getRequestOrganization(this.props.account);
|
||||||
return {
|
return {
|
||||||
owner: this.props.account.owner,
|
owner: owner,
|
||||||
name: `permission_${randomName}`,
|
name: `permission_${randomName}`,
|
||||||
createdTime: moment().format(),
|
createdTime: moment().format(),
|
||||||
displayName: `New Permission - ${randomName}`,
|
displayName: `New Permission - ${randomName}`,
|
||||||
@@ -383,7 +384,7 @@ class PermissionListPage extends BaseListPage {
|
|||||||
this.setState({loading: true});
|
this.setState({loading: true});
|
||||||
|
|
||||||
const getPermissions = Setting.isLocalAdminUser(this.props.account) ? PermissionBackend.getPermissions : PermissionBackend.getPermissionsBySubmitter;
|
const getPermissions = Setting.isLocalAdminUser(this.props.account) ? PermissionBackend.getPermissions : PermissionBackend.getPermissionsBySubmitter;
|
||||||
getPermissions(Setting.isAdminUser(this.props.account) ? "" : this.props.account.owner, params.pagination.current, params.pagination.pageSize, field, value, sortField, sortOrder)
|
getPermissions(Setting.isDefaultOrganizationSelected(this.props.account) ? "" : Setting.getRequestOrganization(this.props.account), params.pagination.current, params.pagination.pageSize, field, value, sortField, sortOrder)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
this.setState({
|
this.setState({
|
||||||
loading: false,
|
loading: false,
|
||||||
|
@@ -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,
|
||||||
});
|
});
|
||||||
|
@@ -25,8 +25,7 @@ import PopconfirmModal from "./common/modal/PopconfirmModal";
|
|||||||
class PlanListPage extends BaseListPage {
|
class PlanListPage extends BaseListPage {
|
||||||
newPlan() {
|
newPlan() {
|
||||||
const randomName = Setting.getRandomName();
|
const randomName = Setting.getRandomName();
|
||||||
const owner = (this.state.organizationName !== undefined) ? this.state.organizationName : this.props.account.owner;
|
const owner = Setting.getRequestOrganization(this.props.account);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
owner: owner,
|
owner: owner,
|
||||||
name: `plan_${randomName}`,
|
name: `plan_${randomName}`,
|
||||||
@@ -197,7 +196,7 @@ class PlanListPage extends BaseListPage {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Table scroll={{x: "max-content"}} columns={columns} dataSource={plans} rowKey="name" size="middle" bordered pagination={paginationProps}
|
<Table scroll={{x: "max-content"}} columns={columns} dataSource={plans} rowKey={(record) => `${record.owner}/${record.name}`} size="middle" bordered pagination={paginationProps}
|
||||||
title={() => (
|
title={() => (
|
||||||
<div>
|
<div>
|
||||||
{i18next.t("general:Plans")}
|
{i18next.t("general:Plans")}
|
||||||
@@ -219,7 +218,7 @@ class PlanListPage extends BaseListPage {
|
|||||||
value = params.type;
|
value = params.type;
|
||||||
}
|
}
|
||||||
this.setState({loading: true});
|
this.setState({loading: true});
|
||||||
PlanBackend.getPlans(Setting.isAdminUser(this.props.account) ? "" : this.props.account.owner, params.pagination.current, params.pagination.pageSize, field, value, sortField, sortOrder)
|
PlanBackend.getPlans(Setting.isDefaultOrganizationSelected(this.props.account) ? "" : Setting.getRequestOrganization(this.props.account), params.pagination.current, params.pagination.pageSize, field, value, sortField, sortOrder)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
this.setState({
|
this.setState({
|
||||||
loading: false,
|
loading: false,
|
||||||
|
@@ -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,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@@ -25,8 +25,7 @@ import PopconfirmModal from "./common/modal/PopconfirmModal";
|
|||||||
class PricingListPage extends BaseListPage {
|
class PricingListPage extends BaseListPage {
|
||||||
newPricing() {
|
newPricing() {
|
||||||
const randomName = Setting.getRandomName();
|
const randomName = Setting.getRandomName();
|
||||||
const owner = (this.state.organizationName !== undefined) ? this.state.organizationName : this.props.account.owner;
|
const owner = Setting.getRequestOrganization(this.props.account);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
owner: owner,
|
owner: owner,
|
||||||
name: `pricing_${randomName}`,
|
name: `pricing_${randomName}`,
|
||||||
@@ -166,7 +165,7 @@ class PricingListPage extends BaseListPage {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Table scroll={{x: "max-content"}} columns={columns} dataSource={pricings} rowKey="name" size="middle" bordered pagination={paginationProps}
|
<Table scroll={{x: "max-content"}} columns={columns} dataSource={pricings} rowKey={(record) => `${record.owner}/${record.name}`} size="middle" bordered pagination={paginationProps}
|
||||||
title={() => (
|
title={() => (
|
||||||
<div>
|
<div>
|
||||||
{i18next.t("general:Pricings")}
|
{i18next.t("general:Pricings")}
|
||||||
@@ -188,7 +187,7 @@ class PricingListPage extends BaseListPage {
|
|||||||
value = params.type;
|
value = params.type;
|
||||||
}
|
}
|
||||||
this.setState({loading: true});
|
this.setState({loading: true});
|
||||||
PricingBackend.getPricings(Setting.isAdminUser(this.props.account) ? "" : this.props.account.owner, params.pagination.current, params.pagination.pageSize, field, value, sortField, sortOrder)
|
PricingBackend.getPricings(Setting.isDefaultOrganizationSelected(this.props.account) ? "" : Setting.getRequestOrganization(this.props.account), params.pagination.current, params.pagination.pageSize, field, value, sortField, sortOrder)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
this.setState({
|
this.setState({
|
||||||
loading: false,
|
loading: false,
|
||||||
|
@@ -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,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@@ -20,6 +20,7 @@ import i18next from "i18next";
|
|||||||
import {LinkOutlined} from "@ant-design/icons";
|
import {LinkOutlined} from "@ant-design/icons";
|
||||||
import * as ProviderBackend from "./backend/ProviderBackend";
|
import * as ProviderBackend from "./backend/ProviderBackend";
|
||||||
import ProductBuyPage from "./ProductBuyPage";
|
import ProductBuyPage from "./ProductBuyPage";
|
||||||
|
import * as OrganizationBackend from "./backend/OrganizationBackend";
|
||||||
|
|
||||||
const {Option} = Select;
|
const {Option} = Select;
|
||||||
|
|
||||||
@@ -39,11 +40,12 @@ class ProductEditPage extends React.Component {
|
|||||||
|
|
||||||
UNSAFE_componentWillMount() {
|
UNSAFE_componentWillMount() {
|
||||||
this.getProduct();
|
this.getProduct();
|
||||||
|
this.getOrganizations();
|
||||||
this.getPaymentProviders();
|
this.getPaymentProviders();
|
||||||
}
|
}
|
||||||
|
|
||||||
getProduct() {
|
getProduct() {
|
||||||
ProductBackend.getProduct(this.props.account.owner, this.state.productName)
|
ProductBackend.getProduct(this.state.organizationName, this.state.productName)
|
||||||
.then((product) => {
|
.then((product) => {
|
||||||
if (product === null) {
|
if (product === null) {
|
||||||
this.props.history.push("/404");
|
this.props.history.push("/404");
|
||||||
@@ -56,6 +58,15 @@ class ProductEditPage extends React.Component {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getOrganizations() {
|
||||||
|
OrganizationBackend.getOrganizations("admin")
|
||||||
|
.then((res) => {
|
||||||
|
this.setState({
|
||||||
|
organizations: (res.msg === undefined) ? res : [],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
getPaymentProviders() {
|
getPaymentProviders() {
|
||||||
ProviderBackend.getProviders(this.props.account.owner)
|
ProviderBackend.getProviders(this.props.account.owner)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
@@ -312,7 +323,7 @@ class ProductEditPage extends React.Component {
|
|||||||
if (willExist) {
|
if (willExist) {
|
||||||
this.props.history.push("/products");
|
this.props.history.push("/products");
|
||||||
} else {
|
} else {
|
||||||
this.props.history.push(`/products/${this.state.product.name}`);
|
this.props.history.push(`/products/${this.state.product.owner}/${this.state.product.name}`);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Setting.showMessage("error", `${i18next.t("general:Failed to save")}: ${res.msg}`);
|
Setting.showMessage("error", `${i18next.t("general:Failed to save")}: ${res.msg}`);
|
||||||
|
@@ -26,8 +26,9 @@ import PopconfirmModal from "./common/modal/PopconfirmModal";
|
|||||||
class ProductListPage extends BaseListPage {
|
class ProductListPage extends BaseListPage {
|
||||||
newProduct() {
|
newProduct() {
|
||||||
const randomName = Setting.getRandomName();
|
const randomName = Setting.getRandomName();
|
||||||
|
const owner = Setting.getRequestOrganization(this.props.account);
|
||||||
return {
|
return {
|
||||||
owner: this.props.account.owner,
|
owner: owner,
|
||||||
name: `product_${randomName}`,
|
name: `product_${randomName}`,
|
||||||
createdTime: moment().format(),
|
createdTime: moment().format(),
|
||||||
displayName: `New Product - ${randomName}`,
|
displayName: `New Product - ${randomName}`,
|
||||||
@@ -47,7 +48,7 @@ class ProductListPage extends BaseListPage {
|
|||||||
ProductBackend.addProduct(newProduct)
|
ProductBackend.addProduct(newProduct)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
if (res.status === "ok") {
|
if (res.status === "ok") {
|
||||||
this.props.history.push({pathname: `/products/${newProduct.name}`, mode: "add"});
|
this.props.history.push({pathname: `/products/${newProduct.owner}/${newProduct.name}`, mode: "add"});
|
||||||
Setting.showMessage("success", i18next.t("general:Successfully added"));
|
Setting.showMessage("success", i18next.t("general:Successfully added"));
|
||||||
} else {
|
} else {
|
||||||
Setting.showMessage("error", `${i18next.t("general:Failed to add")}: ${res.msg}`);
|
Setting.showMessage("error", `${i18next.t("general:Failed to add")}: ${res.msg}`);
|
||||||
@@ -88,7 +89,7 @@ class ProductListPage extends BaseListPage {
|
|||||||
...this.getColumnSearchProps("name"),
|
...this.getColumnSearchProps("name"),
|
||||||
render: (text, record, index) => {
|
render: (text, record, index) => {
|
||||||
return (
|
return (
|
||||||
<Link to={`/products/${text}`}>
|
<Link to={`/products/${record.owner}/${text}`}>
|
||||||
{text}
|
{text}
|
||||||
</Link>
|
</Link>
|
||||||
);
|
);
|
||||||
@@ -201,7 +202,7 @@ class ProductListPage extends BaseListPage {
|
|||||||
size="small"
|
size="small"
|
||||||
locale={{emptyText: " "}}
|
locale={{emptyText: " "}}
|
||||||
dataSource={providers}
|
dataSource={providers}
|
||||||
renderItem={(providerName, i) => {
|
renderItem={(providerName, record, i) => {
|
||||||
return (
|
return (
|
||||||
<List.Item>
|
<List.Item>
|
||||||
<div style={{display: "inline"}}>
|
<div style={{display: "inline"}}>
|
||||||
@@ -247,7 +248,7 @@ class ProductListPage extends BaseListPage {
|
|||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Button style={{marginTop: "10px", marginBottom: "10px", marginRight: "10px"}} onClick={() => this.props.history.push(`/products/${record.name}/buy`)}>{i18next.t("product:Buy")}</Button>
|
<Button style={{marginTop: "10px", marginBottom: "10px", marginRight: "10px"}} onClick={() => this.props.history.push(`/products/${record.name}/buy`)}>{i18next.t("product:Buy")}</Button>
|
||||||
<Button style={{marginTop: "10px", marginBottom: "10px", marginRight: "10px"}} type="primary" onClick={() => this.props.history.push(`/products/${record.name}`)}>{i18next.t("general:Edit")}</Button>
|
<Button style={{marginTop: "10px", marginBottom: "10px", marginRight: "10px"}} type="primary" onClick={() => this.props.history.push(`/products/${record.owner}/${record.name}`)}>{i18next.t("general:Edit")}</Button>
|
||||||
<PopconfirmModal
|
<PopconfirmModal
|
||||||
title={i18next.t("general:Sure to delete") + `: ${record.name} ?`}
|
title={i18next.t("general:Sure to delete") + `: ${record.name} ?`}
|
||||||
onConfirm={() => this.deleteProduct(index)}
|
onConfirm={() => this.deleteProduct(index)}
|
||||||
@@ -268,7 +269,7 @@ class ProductListPage extends BaseListPage {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Table scroll={{x: "max-content"}} columns={columns} dataSource={products} rowKey="name" size="middle" bordered pagination={paginationProps}
|
<Table scroll={{x: "max-content"}} columns={columns} dataSource={products} rowKey={(record) => `${record.owner}/${record.name}`} size="middle" bordered pagination={paginationProps}
|
||||||
title={() => (
|
title={() => (
|
||||||
<div>
|
<div>
|
||||||
{i18next.t("general:Products")}
|
{i18next.t("general:Products")}
|
||||||
@@ -290,7 +291,7 @@ class ProductListPage extends BaseListPage {
|
|||||||
value = params.type;
|
value = params.type;
|
||||||
}
|
}
|
||||||
this.setState({loading: true});
|
this.setState({loading: true});
|
||||||
ProductBackend.getProducts(Setting.isAdminUser(this.props.account) ? "" : this.props.account.owner, params.pagination.current, params.pagination.pageSize, field, value, sortField, sortOrder)
|
ProductBackend.getProducts(Setting.isDefaultOrganizationSelected(this.props.account) ? "" : Setting.getRequestOrganization(this.props.account), params.pagination.current, params.pagination.pageSize, field, value, sortField, sortOrder)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
this.setState({
|
this.setState({
|
||||||
loading: false,
|
loading: false,
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user