mirror of
https://github.com/casdoor/casdoor.git
synced 2025-07-30 16:20:32 +08:00
Compare commits
29 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
fb16d8cee6 | ||
![]() |
5e4ba4f338 | ||
![]() |
ca47af2ee1 | ||
![]() |
59da104463 | ||
![]() |
c5bb916651 | ||
![]() |
e98264f957 | ||
![]() |
6a952952a8 | ||
![]() |
ba8a0f36be | ||
![]() |
b5e9084e5d | ||
![]() |
55d5ae10f2 | ||
![]() |
6986dad295 | ||
![]() |
949feb18af | ||
![]() |
d1f88ca9b8 | ||
![]() |
bfe8e5f3e7 | ||
![]() |
702ee6acd0 | ||
![]() |
0a9587901a | ||
![]() |
577bd6ce58 | ||
![]() |
3c4112dd44 | ||
![]() |
b7a37126ad | ||
![]() |
8669d5bb0d | ||
![]() |
aee3ea4981 | ||
![]() |
516f4b7569 | ||
![]() |
7d7ca10481 | ||
![]() |
a9d4978a0f | ||
![]() |
09f40bb5ce | ||
![]() |
a6f803aff1 | ||
![]() |
fc9528be43 | ||
![]() |
58e8f9f90b | ||
![]() |
e850e33f37 |
@@ -290,10 +290,11 @@ func (c *ApiController) Logout() {
|
||||
c.ResponseOk(user, application.HomepageUrl)
|
||||
return
|
||||
} else {
|
||||
if redirectUri == "" {
|
||||
c.ResponseError(c.T("general:Missing parameter") + ": post_logout_redirect_uri")
|
||||
return
|
||||
}
|
||||
// "post_logout_redirect_uri" has been made optional, see: https://github.com/casdoor/casdoor/issues/2151
|
||||
// if redirectUri == "" {
|
||||
// c.ResponseError(c.T("general:Missing parameter") + ": post_logout_redirect_uri")
|
||||
// return
|
||||
// }
|
||||
if accessToken == "" {
|
||||
c.ResponseError(c.T("general:Missing parameter") + ": id_token_hint")
|
||||
return
|
||||
|
@@ -48,14 +48,11 @@ func (c *ApiController) GetApplications() {
|
||||
} else {
|
||||
applications, err = object.GetOrganizationApplications(owner, organization)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = object.GetMaskedApplications(applications, userId)
|
||||
c.ServeJSON()
|
||||
c.ResponseOk(object.GetMaskedApplications(applications, userId))
|
||||
} else {
|
||||
limit := util.ParseInt(limit)
|
||||
count, err := object.GetApplicationCount(owner, field, value)
|
||||
@@ -86,14 +83,14 @@ func (c *ApiController) GetApplications() {
|
||||
func (c *ApiController) GetApplication() {
|
||||
userId := c.GetSessionUsername()
|
||||
id := c.Input().Get("id")
|
||||
|
||||
app, err := object.GetApplication(id)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = object.GetMaskedApplication(app, userId)
|
||||
c.ServeJSON()
|
||||
c.ResponseOk(object.GetMaskedApplication(app, userId))
|
||||
}
|
||||
|
||||
// GetUserApplication
|
||||
@@ -106,25 +103,24 @@ func (c *ApiController) GetApplication() {
|
||||
func (c *ApiController) GetUserApplication() {
|
||||
userId := c.GetSessionUsername()
|
||||
id := c.Input().Get("id")
|
||||
|
||||
user, err := object.GetUser(id)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
if user == nil {
|
||||
c.ResponseError(fmt.Sprintf(c.T("general:The user: %s doesn't exist"), id))
|
||||
return
|
||||
}
|
||||
|
||||
app, err := object.GetApplicationByUser(user)
|
||||
application, err := object.GetApplicationByUser(user)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = object.GetMaskedApplication(app, userId)
|
||||
c.ServeJSON()
|
||||
c.ResponseOk(object.GetMaskedApplication(application, userId))
|
||||
}
|
||||
|
||||
// GetOrganizationApplications
|
||||
@@ -157,8 +153,7 @@ func (c *ApiController) GetOrganizationApplications() {
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = object.GetMaskedApplications(applications, userId)
|
||||
c.ServeJSON()
|
||||
c.ResponseOk(object.GetMaskedApplications(applications, userId))
|
||||
} else {
|
||||
limit := util.ParseInt(limit)
|
||||
|
||||
|
226
controllers/casbin_api.go
Normal file
226
controllers/casbin_api.go
Normal file
@@ -0,0 +1,226 @@
|
||||
// Copyright 2022 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 controllers
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/casdoor/casdoor/object"
|
||||
"github.com/casdoor/casdoor/util"
|
||||
)
|
||||
|
||||
// Enforce
|
||||
// @Title Enforce
|
||||
// @Tag Enforce API
|
||||
// @Description Call Casbin Enforce API
|
||||
// @Param body body object.CasbinRequest true "Casbin request"
|
||||
// @Param permissionId query string false "permission id"
|
||||
// @Param modelId query string false "model id"
|
||||
// @Param resourceId query string false "resource id"
|
||||
// @Success 200 {object} controllers.Response The Response object
|
||||
// @router /enforce [post]
|
||||
func (c *ApiController) Enforce() {
|
||||
permissionId := c.Input().Get("permissionId")
|
||||
modelId := c.Input().Get("modelId")
|
||||
resourceId := c.Input().Get("resourceId")
|
||||
|
||||
var request object.CasbinRequest
|
||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &request)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
if permissionId != "" {
|
||||
permission, err := object.GetPermission(permissionId)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
res := []bool{}
|
||||
|
||||
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)
|
||||
return
|
||||
}
|
||||
|
||||
permissions := []*object.Permission{}
|
||||
if modelId != "" {
|
||||
owner, modelName := util.GetOwnerAndNameFromId(modelId)
|
||||
permissions, err = object.GetPermissionsByModel(owner, modelName)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
} else if resourceId != "" {
|
||||
permissions, err = object.GetPermissionsByResource(resourceId)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
} else {
|
||||
c.ResponseError(c.T("general:Missing parameter"))
|
||||
return
|
||||
}
|
||||
|
||||
res := []bool{}
|
||||
|
||||
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 {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
res = append(res, enforceResult)
|
||||
}
|
||||
|
||||
c.ResponseOk(res)
|
||||
}
|
||||
|
||||
// BatchEnforce
|
||||
// @Title BatchEnforce
|
||||
// @Tag Enforce API
|
||||
// @Description Call Casbin BatchEnforce API
|
||||
// @Param body body object.CasbinRequest true "array of casbin requests"
|
||||
// @Param permissionId query string false "permission id"
|
||||
// @Param modelId query string false "model id"
|
||||
// @Success 200 {object} controllers.Response The Response object
|
||||
// @router /batch-enforce [post]
|
||||
func (c *ApiController) BatchEnforce() {
|
||||
permissionId := c.Input().Get("permissionId")
|
||||
modelId := c.Input().Get("modelId")
|
||||
|
||||
var requests []object.CasbinRequest
|
||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &requests)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
if permissionId != "" {
|
||||
permission, err := object.GetPermission(permissionId)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
res := [][]bool{}
|
||||
|
||||
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)
|
||||
return
|
||||
}
|
||||
|
||||
permissions := []*object.Permission{}
|
||||
if modelId != "" {
|
||||
owner, modelName := util.GetOwnerAndNameFromId(modelId)
|
||||
permissions, err = object.GetPermissionsByModel(owner, modelName)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
} else {
|
||||
c.ResponseError(c.T("general:Missing parameter"))
|
||||
return
|
||||
}
|
||||
|
||||
res := [][]bool{}
|
||||
|
||||
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 {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
res = append(res, enforceResult)
|
||||
}
|
||||
|
||||
c.ResponseOk(res)
|
||||
}
|
||||
|
||||
func (c *ApiController) GetAllObjects() {
|
||||
userId := c.GetSessionUsername()
|
||||
if userId == "" {
|
||||
c.ResponseError(c.T("general:Please login first"))
|
||||
return
|
||||
}
|
||||
|
||||
c.ResponseOk(object.GetAllObjects(userId))
|
||||
}
|
||||
|
||||
func (c *ApiController) GetAllActions() {
|
||||
userId := c.GetSessionUsername()
|
||||
if userId == "" {
|
||||
c.ResponseError(c.T("general:Please login first"))
|
||||
return
|
||||
}
|
||||
|
||||
c.ResponseOk(object.GetAllActions(userId))
|
||||
}
|
||||
|
||||
func (c *ApiController) GetAllRoles() {
|
||||
userId := c.GetSessionUsername()
|
||||
if userId == "" {
|
||||
c.ResponseError(c.T("general:Please login first"))
|
||||
return
|
||||
}
|
||||
|
||||
c.ResponseOk(object.GetAllRoles(userId))
|
||||
}
|
@@ -45,8 +45,7 @@ func (c *ApiController) GetCerts() {
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = maskedCerts
|
||||
c.ServeJSON()
|
||||
c.ResponseOk(maskedCerts)
|
||||
} else {
|
||||
limit := util.ParseInt(limit)
|
||||
count, err := object.GetCertCount(owner, field, value)
|
||||
@@ -87,8 +86,7 @@ func (c *ApiController) GetGlobleCerts() {
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = maskedCerts
|
||||
c.ServeJSON()
|
||||
c.ResponseOk(maskedCerts)
|
||||
} else {
|
||||
limit := util.ParseInt(limit)
|
||||
count, err := object.GetGlobalCertsCount(field, value)
|
||||
@@ -123,8 +121,7 @@ func (c *ApiController) GetCert() {
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = object.GetMaskedCert(cert)
|
||||
c.ServeJSON()
|
||||
c.ResponseOk(object.GetMaskedCert(cert))
|
||||
}
|
||||
|
||||
// UpdateCert
|
||||
|
@@ -45,8 +45,7 @@ func (c *ApiController) GetChats() {
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = maskedChats
|
||||
c.ServeJSON()
|
||||
c.ResponseOk(maskedChats)
|
||||
} else {
|
||||
limit := util.ParseInt(limit)
|
||||
count, err := object.GetChatCount(owner, field, value)
|
||||
@@ -82,8 +81,7 @@ func (c *ApiController) GetChat() {
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = maskedChat
|
||||
c.ServeJSON()
|
||||
c.ResponseOk(maskedChat)
|
||||
}
|
||||
|
||||
// UpdateChat
|
||||
|
@@ -1,4 +1,4 @@
|
||||
// Copyright 2022 The Casdoor Authors. All Rights Reserved.
|
||||
// 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.
|
||||
@@ -17,210 +17,129 @@ package controllers
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/beego/beego/utils/pagination"
|
||||
"github.com/casdoor/casdoor/object"
|
||||
"github.com/casdoor/casdoor/util"
|
||||
)
|
||||
|
||||
// Enforce
|
||||
// @Title Enforce
|
||||
// @Tag Enforce API
|
||||
// @Description Call Casbin Enforce API
|
||||
// @Param body body object.CasbinRequest true "Casbin request"
|
||||
// @Param permissionId query string false "permission id"
|
||||
// @Param modelId query string false "model id"
|
||||
// @Param resourceId query string false "resource id"
|
||||
// @Success 200 {object} controllers.Response The Response object
|
||||
// @router /enforce [post]
|
||||
func (c *ApiController) Enforce() {
|
||||
permissionId := c.Input().Get("permissionId")
|
||||
modelId := c.Input().Get("modelId")
|
||||
resourceId := c.Input().Get("resourceId")
|
||||
// GetEnforcers
|
||||
// @Title GetEnforcers
|
||||
// @Tag Enforcer API
|
||||
// @Description get enforcers
|
||||
// @Param owner query string true "The owner of enforcers"
|
||||
// @Success 200 {array} object.Enforcer
|
||||
// @router /get-enforcers [get]
|
||||
func (c *ApiController) GetEnforcers() {
|
||||
owner := c.Input().Get("owner")
|
||||
limit := c.Input().Get("pageSize")
|
||||
page := c.Input().Get("p")
|
||||
field := c.Input().Get("field")
|
||||
value := c.Input().Get("value")
|
||||
sortField := c.Input().Get("sortField")
|
||||
sortOrder := c.Input().Get("sortOrder")
|
||||
|
||||
var request object.CasbinRequest
|
||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &request)
|
||||
if limit == "" || page == "" {
|
||||
enforcers, err := object.GetEnforcers(owner)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.ResponseOk(enforcers)
|
||||
} else {
|
||||
limit := util.ParseInt(limit)
|
||||
count, err := object.GetEnforcerCount(owner, field, value)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
paginator := pagination.SetPaginator(c.Ctx, limit, count)
|
||||
enforcers, err := object.GetPaginationEnforcers(owner, paginator.Offset(), limit, field, value, sortField, sortOrder)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.ResponseOk(enforcers, paginator.Nums())
|
||||
}
|
||||
}
|
||||
|
||||
// GetEnforcer
|
||||
// @Title GetEnforcer
|
||||
// @Tag Enforcer API
|
||||
// @Description get enforcer
|
||||
// @Param id query string true "The id ( owner/name ) of enforcer"
|
||||
// @Success 200 {object} object
|
||||
// @router /get-enforcer [get]
|
||||
func (c *ApiController) GetEnforcer() {
|
||||
id := c.Input().Get("id")
|
||||
|
||||
enforcer, err := object.GetEnforcer(id)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
if permissionId != "" {
|
||||
permission, err := object.GetPermission(permissionId)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
res := []bool{}
|
||||
|
||||
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)
|
||||
return
|
||||
}
|
||||
|
||||
permissions := []*object.Permission{}
|
||||
if modelId != "" {
|
||||
owner, modelName := util.GetOwnerAndNameFromId(modelId)
|
||||
permissions, err = object.GetPermissionsByModel(owner, modelName)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
} else if resourceId != "" {
|
||||
permissions, err = object.GetPermissionsByResource(resourceId)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
} else {
|
||||
c.ResponseError(c.T("general:Missing parameter"))
|
||||
return
|
||||
}
|
||||
|
||||
res := []bool{}
|
||||
|
||||
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 {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
res = append(res, enforceResult)
|
||||
}
|
||||
|
||||
c.ResponseOk(res)
|
||||
c.ResponseOk(enforcer)
|
||||
}
|
||||
|
||||
// BatchEnforce
|
||||
// @Title BatchEnforce
|
||||
// @Tag Enforce API
|
||||
// @Description Call Casbin BatchEnforce API
|
||||
// @Param body body object.CasbinRequest true "array of casbin requests"
|
||||
// @Param permissionId query string false "permission id"
|
||||
// @Param modelId query string false "model id"
|
||||
// @Success 200 {object} controllers.Response The Response object
|
||||
// @router /batch-enforce [post]
|
||||
func (c *ApiController) BatchEnforce() {
|
||||
permissionId := c.Input().Get("permissionId")
|
||||
modelId := c.Input().Get("modelId")
|
||||
// UpdateEnforcer
|
||||
// @Title UpdateEnforcer
|
||||
// @Tag Enforcer API
|
||||
// @Description update enforcer
|
||||
// @Param id query string true "The id ( owner/name ) of enforcer"
|
||||
// @Param enforcer body object true "The enforcer object"
|
||||
// @Success 200 {object} object
|
||||
// @router /update-enforcer [post]
|
||||
func (c *ApiController) UpdateEnforcer() {
|
||||
id := c.Input().Get("id")
|
||||
|
||||
var requests []object.CasbinRequest
|
||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &requests)
|
||||
enforcer := object.Enforcer{}
|
||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &enforcer)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
if permissionId != "" {
|
||||
permission, err := object.GetPermission(permissionId)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
res := [][]bool{}
|
||||
|
||||
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)
|
||||
return
|
||||
}
|
||||
|
||||
permissions := []*object.Permission{}
|
||||
if modelId != "" {
|
||||
owner, modelName := util.GetOwnerAndNameFromId(modelId)
|
||||
permissions, err = object.GetPermissionsByModel(owner, modelName)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
} else {
|
||||
c.ResponseError(c.T("general:Missing parameter"))
|
||||
return
|
||||
}
|
||||
|
||||
res := [][]bool{}
|
||||
|
||||
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 {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
res = append(res, enforceResult)
|
||||
}
|
||||
|
||||
c.ResponseOk(res)
|
||||
c.Data["json"] = wrapActionResponse(object.UpdateEnforcer(id, &enforcer))
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
func (c *ApiController) GetAllObjects() {
|
||||
userId := c.GetSessionUsername()
|
||||
if userId == "" {
|
||||
c.ResponseError(c.T("general:Please login first"))
|
||||
// AddEnforcer
|
||||
// @Title AddEnforcer
|
||||
// @Tag Enforcer API
|
||||
// @Description add enforcer
|
||||
// @Param enforcer body object true "The enforcer object"
|
||||
// @Success 200 {object} object
|
||||
// @router /add-enforcer [post]
|
||||
func (c *ApiController) AddEnforcer() {
|
||||
enforcer := object.Enforcer{}
|
||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &enforcer)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.ResponseOk(object.GetAllObjects(userId))
|
||||
c.Data["json"] = wrapActionResponse(object.AddEnforcer(&enforcer))
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
func (c *ApiController) GetAllActions() {
|
||||
userId := c.GetSessionUsername()
|
||||
if userId == "" {
|
||||
c.ResponseError(c.T("general:Please login first"))
|
||||
// DeleteEnforcer
|
||||
// @Title DeleteEnforcer
|
||||
// @Tag Enforcer API
|
||||
// @Description delete enforcer
|
||||
// @Param body body object.Enforce true "The enforcer object"
|
||||
// @Success 200 {object} object
|
||||
// @router /delete-enforcer [post]
|
||||
func (c *ApiController) DeleteEnforcer() {
|
||||
var enforcer object.Enforcer
|
||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &enforcer)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.ResponseOk(object.GetAllActions(userId))
|
||||
}
|
||||
|
||||
func (c *ApiController) GetAllRoles() {
|
||||
userId := c.GetSessionUsername()
|
||||
if userId == "" {
|
||||
c.ResponseError(c.T("general:Please login first"))
|
||||
return
|
||||
}
|
||||
|
||||
c.ResponseOk(object.GetAllRoles(userId))
|
||||
c.Data["json"] = wrapActionResponse(object.DeleteEnforcer(&enforcer))
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
@@ -82,9 +82,9 @@ func (c *ApiController) GetGroup() {
|
||||
group, err := object.GetGroup(id)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
} else {
|
||||
c.ResponseOk(group)
|
||||
return
|
||||
}
|
||||
c.ResponseOk(group)
|
||||
}
|
||||
|
||||
// UpdateGroup
|
||||
|
@@ -125,7 +125,12 @@ func (c *ApiController) GetLdap() {
|
||||
}
|
||||
|
||||
_, name := util.GetOwnerAndNameFromId(id)
|
||||
c.ResponseOk(object.GetMaskedLdap(object.GetLdap(name)))
|
||||
ldap, err := object.GetLdap(name)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
c.ResponseOk(object.GetMaskedLdap(ldap))
|
||||
}
|
||||
|
||||
// AddLdap
|
||||
|
@@ -57,8 +57,7 @@ func (c *ApiController) GetMessages() {
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = object.GetMaskedMessages(messages)
|
||||
c.ServeJSON()
|
||||
c.ResponseOk(object.GetMaskedMessages(messages))
|
||||
} else {
|
||||
limit := util.ParseInt(limit)
|
||||
count, err := object.GetMessageCount(owner, organization, field, value)
|
||||
@@ -94,8 +93,7 @@ func (c *ApiController) GetMessage() {
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = object.GetMaskedMessage(message)
|
||||
c.ServeJSON()
|
||||
c.ResponseOk(message)
|
||||
}
|
||||
|
||||
func (c *ApiController) ResponseErrorStream(errorText string) {
|
||||
|
@@ -45,8 +45,7 @@ func (c *ApiController) GetModels() {
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = models
|
||||
c.ServeJSON()
|
||||
c.ResponseOk(models)
|
||||
} else {
|
||||
limit := util.ParseInt(limit)
|
||||
count, err := object.GetModelCount(owner, field, value)
|
||||
@@ -82,8 +81,7 @@ func (c *ApiController) GetModel() {
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = model
|
||||
c.ServeJSON()
|
||||
c.ResponseOk(model)
|
||||
}
|
||||
|
||||
// UpdateModel
|
||||
|
@@ -55,8 +55,7 @@ func (c *ApiController) GetOrganizations() {
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = maskedOrganizations
|
||||
c.ServeJSON()
|
||||
c.ResponseOk(maskedOrganizations)
|
||||
} else {
|
||||
if !isGlobalAdmin {
|
||||
maskedOrganizations, err := object.GetMaskedOrganizations(object.GetOrganizations(owner, c.getCurrentUser().Owner))
|
||||
@@ -184,6 +183,8 @@ func (c *ApiController) DeleteOrganization() {
|
||||
func (c *ApiController) GetDefaultApplication() {
|
||||
userId := c.GetSessionUsername()
|
||||
id := c.Input().Get("id")
|
||||
redirectUri := c.Input().Get("redirectUri")
|
||||
typ := c.Input().Get("type")
|
||||
|
||||
application, err := object.GetDefaultApplication(id)
|
||||
if err != nil {
|
||||
@@ -191,6 +192,14 @@ func (c *ApiController) GetDefaultApplication() {
|
||||
return
|
||||
}
|
||||
|
||||
if typ == "cas" {
|
||||
err = object.CheckCasRestrict(application, c.GetAcceptLanguage(), redirectUri)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
maskedApplication := object.GetMaskedApplication(application, userId)
|
||||
c.ResponseOk(maskedApplication)
|
||||
}
|
||||
|
@@ -46,8 +46,7 @@ func (c *ApiController) GetPayments() {
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = payments
|
||||
c.ServeJSON()
|
||||
c.ResponseOk(payments)
|
||||
} else {
|
||||
limit := util.ParseInt(limit)
|
||||
count, err := object.GetPaymentCount(owner, organization, field, value)
|
||||
@@ -106,8 +105,7 @@ func (c *ApiController) GetPayment() {
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = payment
|
||||
c.ServeJSON()
|
||||
c.ResponseOk(payment)
|
||||
}
|
||||
|
||||
// UpdatePayment
|
||||
|
@@ -45,8 +45,7 @@ func (c *ApiController) GetPermissions() {
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = permissions
|
||||
c.ServeJSON()
|
||||
c.ResponseOk(permissions)
|
||||
} else {
|
||||
limit := util.ParseInt(limit)
|
||||
count, err := object.GetPermissionCount(owner, field, value)
|
||||
@@ -85,7 +84,6 @@ func (c *ApiController) GetPermissionsBySubmitter() {
|
||||
}
|
||||
|
||||
c.ResponseOk(permissions, len(permissions))
|
||||
return
|
||||
}
|
||||
|
||||
// GetPermissionsByRole
|
||||
@@ -104,7 +102,6 @@ func (c *ApiController) GetPermissionsByRole() {
|
||||
}
|
||||
|
||||
c.ResponseOk(permissions, len(permissions))
|
||||
return
|
||||
}
|
||||
|
||||
// GetPermission
|
||||
@@ -123,8 +120,7 @@ func (c *ApiController) GetPermission() {
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = permission
|
||||
c.ServeJSON()
|
||||
c.ResponseOk(permission)
|
||||
}
|
||||
|
||||
// UpdatePermission
|
||||
|
@@ -45,8 +45,7 @@ func (c *ApiController) GetPlans() {
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = plans
|
||||
c.ServeJSON()
|
||||
c.ResponseOk(plans)
|
||||
} else {
|
||||
limit := util.ParseInt(limit)
|
||||
count, err := object.GetPlanCount(owner, field, value)
|
||||
@@ -95,11 +94,10 @@ func (c *ApiController) GetPlan() {
|
||||
plan.Options = append(plan.Options, option.DisplayName)
|
||||
}
|
||||
|
||||
c.Data["json"] = plan
|
||||
c.ResponseOk(plan)
|
||||
} else {
|
||||
c.Data["json"] = plan
|
||||
c.ResponseOk(plan)
|
||||
}
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// UpdatePlan
|
||||
|
@@ -45,8 +45,7 @@ func (c *ApiController) GetPricings() {
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = pricings
|
||||
c.ServeJSON()
|
||||
c.ResponseOk(pricings)
|
||||
} else {
|
||||
limit := util.ParseInt(limit)
|
||||
count, err := object.GetPricingCount(owner, field, value)
|
||||
@@ -82,8 +81,7 @@ func (c *ApiController) GetPricing() {
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = pricing
|
||||
c.ServeJSON()
|
||||
c.ResponseOk(pricing)
|
||||
}
|
||||
|
||||
// UpdatePricing
|
||||
|
@@ -46,8 +46,7 @@ func (c *ApiController) GetProducts() {
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = products
|
||||
c.ServeJSON()
|
||||
c.ResponseOk(products)
|
||||
} else {
|
||||
limit := util.ParseInt(limit)
|
||||
count, err := object.GetProductCount(owner, field, value)
|
||||
@@ -89,8 +88,7 @@ func (c *ApiController) GetProduct() {
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = product
|
||||
c.ServeJSON()
|
||||
c.ResponseOk(product)
|
||||
}
|
||||
|
||||
// UpdateProduct
|
||||
|
@@ -51,8 +51,7 @@ func (c *ApiController) GetRecords() {
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = records
|
||||
c.ServeJSON()
|
||||
c.ResponseOk(records)
|
||||
} else {
|
||||
limit := util.ParseInt(limit)
|
||||
if c.IsGlobalAdmin() && organizationName != "" {
|
||||
@@ -99,8 +98,7 @@ func (c *ApiController) GetRecordsByFilter() {
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = records
|
||||
c.ServeJSON()
|
||||
c.ResponseOk(records)
|
||||
}
|
||||
|
||||
// AddRecord
|
||||
|
@@ -52,14 +52,6 @@ func (c *ApiController) GetResources() {
|
||||
sortField := c.Input().Get("sortField")
|
||||
sortOrder := c.Input().Get("sortOrder")
|
||||
|
||||
userObj, ok := c.RequireSignedInUser()
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
if userObj.IsAdmin {
|
||||
user = ""
|
||||
}
|
||||
|
||||
if limit == "" || page == "" {
|
||||
resources, err := object.GetResources(owner, user)
|
||||
if err != nil {
|
||||
@@ -67,8 +59,7 @@ func (c *ApiController) GetResources() {
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = resources
|
||||
c.ServeJSON()
|
||||
c.ResponseOk(resources)
|
||||
} else {
|
||||
limit := util.ParseInt(limit)
|
||||
count, err := object.GetResourceCount(owner, user, field, value)
|
||||
@@ -104,8 +95,7 @@ func (c *ApiController) GetResource() {
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = resource
|
||||
c.ServeJSON()
|
||||
c.ResponseOk(resource)
|
||||
}
|
||||
|
||||
// UpdateResource
|
||||
|
@@ -45,8 +45,7 @@ func (c *ApiController) GetRoles() {
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = roles
|
||||
c.ServeJSON()
|
||||
c.ResponseOk(roles)
|
||||
} else {
|
||||
limit := util.ParseInt(limit)
|
||||
count, err := object.GetRoleCount(owner, field, value)
|
||||
@@ -82,8 +81,7 @@ func (c *ApiController) GetRole() {
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = role
|
||||
c.ServeJSON()
|
||||
c.ResponseOk(role)
|
||||
}
|
||||
|
||||
// UpdateRole
|
||||
|
@@ -45,8 +45,7 @@ func (c *ApiController) GetSessions() {
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = sessions
|
||||
c.ServeJSON()
|
||||
c.ResponseOk(sessions)
|
||||
} else {
|
||||
limit := util.ParseInt(limit)
|
||||
count, err := object.GetSessionCount(owner, field, value)
|
||||
@@ -81,8 +80,7 @@ func (c *ApiController) GetSingleSession() {
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = session
|
||||
c.ServeJSON()
|
||||
c.ResponseOk(session)
|
||||
}
|
||||
|
||||
// UpdateSession
|
||||
@@ -161,7 +159,5 @@ func (c *ApiController) IsSessionDuplicated() {
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = &Response{Status: "ok", Msg: "", Data: isUserSessionDuplicated}
|
||||
|
||||
c.ServeJSON()
|
||||
c.ResponseOk(isUserSessionDuplicated)
|
||||
}
|
||||
|
@@ -45,8 +45,7 @@ func (c *ApiController) GetSubscriptions() {
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = subscriptions
|
||||
c.ServeJSON()
|
||||
c.ResponseOk(subscriptions)
|
||||
} else {
|
||||
limit := util.ParseInt(limit)
|
||||
count, err := object.GetSubscriptionCount(owner, field, value)
|
||||
@@ -82,8 +81,7 @@ func (c *ApiController) GetSubscription() {
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = subscription
|
||||
c.ServeJSON()
|
||||
c.ResponseOk(subscription)
|
||||
}
|
||||
|
||||
// UpdateSubscription
|
||||
|
@@ -46,8 +46,7 @@ func (c *ApiController) GetSyncers() {
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = organizationSyncers
|
||||
c.ServeJSON()
|
||||
c.ResponseOk(organizationSyncers)
|
||||
} else {
|
||||
limit := util.ParseInt(limit)
|
||||
count, err := object.GetSyncerCount(owner, organization, field, value)
|
||||
@@ -83,8 +82,7 @@ func (c *ApiController) GetSyncer() {
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = syncer
|
||||
c.ServeJSON()
|
||||
c.ResponseOk(syncer)
|
||||
}
|
||||
|
||||
// UpdateSyncer
|
||||
|
@@ -47,8 +47,7 @@ func (c *ApiController) GetTokens() {
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = token
|
||||
c.ServeJSON()
|
||||
c.ResponseOk(token)
|
||||
} else {
|
||||
limit := util.ParseInt(limit)
|
||||
count, err := object.GetTokenCount(owner, organization, field, value)
|
||||
@@ -83,8 +82,7 @@ func (c *ApiController) GetToken() {
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = token
|
||||
c.ServeJSON()
|
||||
c.ResponseOk(token)
|
||||
}
|
||||
|
||||
// UpdateToken
|
||||
|
@@ -45,8 +45,7 @@ func (c *ApiController) GetGlobalUsers() {
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = maskedUsers
|
||||
c.ServeJSON()
|
||||
c.ResponseOk(maskedUsers)
|
||||
} else {
|
||||
limit := util.ParseInt(limit)
|
||||
count, err := object.GetGlobalUserCount(field, value)
|
||||
@@ -106,8 +105,7 @@ func (c *ApiController) GetUsers() {
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = maskedUsers
|
||||
c.ServeJSON()
|
||||
c.ResponseOk(maskedUsers)
|
||||
} else {
|
||||
limit := util.ParseInt(limit)
|
||||
count, err := object.GetUserCount(owner, field, value, groupName)
|
||||
@@ -215,8 +213,7 @@ func (c *ApiController) GetUser() {
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = maskedUser
|
||||
c.ServeJSON()
|
||||
c.ResponseOk(maskedUser)
|
||||
}
|
||||
|
||||
// UpdateUser
|
||||
@@ -513,8 +510,7 @@ func (c *ApiController) GetSortedUsers() {
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = maskedUsers
|
||||
c.ServeJSON()
|
||||
c.ResponseOk(maskedUsers)
|
||||
}
|
||||
|
||||
// GetUserCount
|
||||
@@ -541,8 +537,7 @@ func (c *ApiController) GetUserCount() {
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = count
|
||||
c.ServeJSON()
|
||||
c.ResponseOk(count)
|
||||
}
|
||||
|
||||
// AddUserkeys
|
||||
|
@@ -26,9 +26,10 @@ import (
|
||||
// @Title GetWebhooks
|
||||
// @Tag Webhook API
|
||||
// @Description get webhooks
|
||||
// @Param owner query string true "The owner of webhooks"
|
||||
// @Param owner query string built-in/admin true "The owner of webhooks"
|
||||
// @Success 200 {array} object.Webhook The Response object
|
||||
// @router /get-webhooks [get]
|
||||
// @Security test_apiKey
|
||||
func (c *ApiController) GetWebhooks() {
|
||||
owner := c.Input().Get("owner")
|
||||
limit := c.Input().Get("pageSize")
|
||||
@@ -46,8 +47,7 @@ func (c *ApiController) GetWebhooks() {
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = webhooks
|
||||
c.ServeJSON()
|
||||
c.ResponseOk(webhooks)
|
||||
} else {
|
||||
limit := util.ParseInt(limit)
|
||||
count, err := object.GetWebhookCount(owner, organization, field, value)
|
||||
@@ -72,7 +72,7 @@ func (c *ApiController) GetWebhooks() {
|
||||
// @Title GetWebhook
|
||||
// @Tag Webhook API
|
||||
// @Description get webhook
|
||||
// @Param id query string true "The id ( owner/name ) of the webhook"
|
||||
// @Param id query string built-in/admin true "The id ( owner/name ) of the webhook"
|
||||
// @Success 200 {object} object.Webhook The Response object
|
||||
// @router /get-webhook [get]
|
||||
func (c *ApiController) GetWebhook() {
|
||||
@@ -84,15 +84,14 @@ func (c *ApiController) GetWebhook() {
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = webhook
|
||||
c.ServeJSON()
|
||||
c.ResponseOk(webhook)
|
||||
}
|
||||
|
||||
// UpdateWebhook
|
||||
// @Title UpdateWebhook
|
||||
// @Tag Webhook API
|
||||
// @Description update webhook
|
||||
// @Param id query string true "The id ( owner/name ) of the webhook"
|
||||
// @Param id query string built-in/admin true "The id ( owner/name ) of the webhook"
|
||||
// @Param body body object.Webhook true "The details of the webhook"
|
||||
// @Success 200 {object} controllers.Response The Response object
|
||||
// @router /update-webhook [post]
|
||||
|
@@ -21,15 +21,39 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/casdoor/casdoor/util"
|
||||
"golang.org/x/oauth2"
|
||||
)
|
||||
|
||||
const GoogleIdTokenKey = "GoogleIdToken"
|
||||
|
||||
type GoogleIdProvider struct {
|
||||
Client *http.Client
|
||||
Config *oauth2.Config
|
||||
}
|
||||
|
||||
// https://developers.google.com/identity/sign-in/web/backend-auth#calling-the-tokeninfo-endpoint
|
||||
type GoogleIdToken struct {
|
||||
// These six fields are included in all Google ID Tokens.
|
||||
Iss string `json:"iss"` // The issuer, or signer, of the token. For Google-signed ID tokens, this value is https://accounts.google.com.
|
||||
Sub string `json:"sub"` // The subject: the ID that represents the principal making the request.
|
||||
Azp string `json:"azp"` // Optional. Who the token was issued to. Here is the ClientID
|
||||
Aud string `json:"aud"` // The audience of the token. Here is the ClientID
|
||||
Iat string `json:"iat"` // Unix epoch time when the token was issued.
|
||||
Exp string `json:"exp"` // Unix epoch time when the token expires.
|
||||
// These seven fields are only included when the user has granted the "profile" and "email" OAuth scopes to the application.
|
||||
Email string `json:"email"`
|
||||
EmailVerified string `json:"email_verified"`
|
||||
Name string `json:"name"`
|
||||
Picture string `json:"picture"`
|
||||
GivenName string `json:"given_name"`
|
||||
FamilyName string `json:"family_name"`
|
||||
Locale string `json:"locale"`
|
||||
}
|
||||
|
||||
func NewGoogleIdProvider(clientId string, clientSecret string, redirectUrl string) *GoogleIdProvider {
|
||||
idp := &GoogleIdProvider{}
|
||||
|
||||
@@ -61,6 +85,25 @@ func (idp *GoogleIdProvider) getConfig() *oauth2.Config {
|
||||
}
|
||||
|
||||
func (idp *GoogleIdProvider) GetToken(code string) (*oauth2.Token, error) {
|
||||
// Obtained the GoogleIdToken through Google OneTap authorization.
|
||||
if strings.HasPrefix(code, GoogleIdTokenKey) {
|
||||
code = strings.TrimPrefix(code, GoogleIdTokenKey+"-")
|
||||
var googleIdToken GoogleIdToken
|
||||
if err := json.Unmarshal([]byte(code), &googleIdToken); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
expiry := int64(util.ParseInt(googleIdToken.Exp))
|
||||
token := &oauth2.Token{
|
||||
AccessToken: fmt.Sprintf("%v-%v", GoogleIdTokenKey, googleIdToken.Sub),
|
||||
TokenType: "Bearer",
|
||||
Expiry: time.Unix(expiry, 0),
|
||||
}
|
||||
token = token.WithExtra(map[string]interface{}{
|
||||
GoogleIdTokenKey: googleIdToken,
|
||||
})
|
||||
return token, nil
|
||||
}
|
||||
|
||||
ctx := context.WithValue(context.Background(), oauth2.HTTPClient, idp.Client)
|
||||
return idp.Config.Exchange(ctx, code)
|
||||
}
|
||||
@@ -88,6 +131,20 @@ type GoogleUserInfo struct {
|
||||
}
|
||||
|
||||
func (idp *GoogleIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo, error) {
|
||||
if strings.HasPrefix(token.AccessToken, GoogleIdTokenKey) {
|
||||
googleIdToken, ok := token.Extra(GoogleIdTokenKey).(GoogleIdToken)
|
||||
if !ok {
|
||||
return nil, errors.New("invalid googleIdToken")
|
||||
}
|
||||
userInfo := UserInfo{
|
||||
Id: googleIdToken.Sub,
|
||||
Username: googleIdToken.Email,
|
||||
DisplayName: googleIdToken.Name,
|
||||
Email: googleIdToken.Email,
|
||||
AvatarUrl: googleIdToken.Picture,
|
||||
}
|
||||
return &userInfo, nil
|
||||
}
|
||||
url := fmt.Sprintf("https://www.googleapis.com/oauth2/v2/userinfo?alt=json&access_token=%s", token.AccessToken)
|
||||
resp, err := idp.Client.Get(url)
|
||||
if err != nil {
|
||||
|
@@ -34,7 +34,7 @@ func StartLdapServer() {
|
||||
server.Handle(routes)
|
||||
err := server.ListenAndServe("0.0.0.0:" + conf.GetConfigString("ldapServerPort"))
|
||||
if err != nil {
|
||||
return
|
||||
log.Printf("StartLdapServer() failed, ErrMsg = %s", err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
|
2
main.go
2
main.go
@@ -39,7 +39,7 @@ func getCreateDatabaseFlag() bool {
|
||||
func main() {
|
||||
createDatabase := getCreateDatabaseFlag()
|
||||
|
||||
object.InitAdapter()
|
||||
object.InitAdapter(createDatabase)
|
||||
object.CreateTables(createDatabase)
|
||||
object.DoMigration()
|
||||
|
||||
|
@@ -15,8 +15,10 @@
|
||||
package object
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
"github.com/beego/beego"
|
||||
"github.com/casdoor/casdoor/conf"
|
||||
@@ -40,12 +42,19 @@ func InitConfig() {
|
||||
|
||||
beego.BConfig.WebConfig.Session.SessionOn = true
|
||||
|
||||
InitAdapter()
|
||||
InitAdapter(true)
|
||||
CreateTables(true)
|
||||
DoMigration()
|
||||
}
|
||||
|
||||
func InitAdapter() {
|
||||
func InitAdapter(createDatabase bool) {
|
||||
if createDatabase {
|
||||
err := createDatabaseForPostgres(conf.GetConfigString("driverName"), conf.GetConfigDataSourceName(), conf.GetConfigString("dbName"))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
adapter = NewAdapter(conf.GetConfigString("driverName"), conf.GetConfigDataSourceName(), conf.GetConfigString("dbName"))
|
||||
|
||||
tableNamePrefix := conf.GetConfigString("tableNamePrefix")
|
||||
@@ -96,7 +105,32 @@ func NewAdapter(driverName string, dataSourceName string, dbName string) *Adapte
|
||||
return a
|
||||
}
|
||||
|
||||
func createDatabaseForPostgres(driverName string, dataSourceName string, dbName string) error {
|
||||
if driverName == "postgres" {
|
||||
db, err := sql.Open(driverName, dataSourceName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer db.Close()
|
||||
|
||||
_, err = db.Exec(fmt.Sprintf("CREATE DATABASE %s;", dbName))
|
||||
if err != nil {
|
||||
if !strings.Contains(err.Error(), "already exists") {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func (a *Adapter) CreateDatabase() error {
|
||||
if a.driverName == "postgres" {
|
||||
return nil
|
||||
}
|
||||
|
||||
engine, err := xorm.NewEngine(a.driverName, a.dataSourceName)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -165,6 +199,11 @@ func (a *Adapter) createTable() {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
err = a.Engine.Sync2(new(Enforcer))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
err = a.Engine.Sync2(new(Provider))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
|
@@ -281,14 +281,21 @@ func GetApplication(id string) (*Application, error) {
|
||||
}
|
||||
|
||||
func GetMaskedApplication(application *Application, userId string) *Application {
|
||||
if isUserIdGlobalAdmin(userId) {
|
||||
return application
|
||||
}
|
||||
|
||||
if application == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
if userId != "" {
|
||||
if isUserIdGlobalAdmin(userId) {
|
||||
return application
|
||||
}
|
||||
|
||||
user, _ := GetUser(userId)
|
||||
if user != nil && user.IsApplicationAdmin(application) {
|
||||
return application
|
||||
}
|
||||
}
|
||||
|
||||
if application.ClientSecret != "" {
|
||||
application.ClientSecret = "***"
|
||||
}
|
||||
|
@@ -100,6 +100,13 @@ func UpdateCasbinAdapter(id string, casbinAdapter *CasbinAdapter) (bool, error)
|
||||
return false, err
|
||||
}
|
||||
|
||||
if name != casbinAdapter.Name {
|
||||
err := casbinAdapterChangeTrigger(name, casbinAdapter.Name)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
|
||||
session := adapter.Engine.ID(core.PK{owner, name}).AllCols()
|
||||
if casbinAdapter.Password == "***" {
|
||||
session.Omit("password")
|
||||
@@ -180,6 +187,26 @@ func initEnforcer(modelObj *Model, casbinAdapter *CasbinAdapter) (*casbin.Enforc
|
||||
return enforcer, nil
|
||||
}
|
||||
|
||||
func casbinAdapterChangeTrigger(oldName string, newName string) error {
|
||||
session := adapter.Engine.NewSession()
|
||||
defer session.Close()
|
||||
|
||||
err := session.Begin()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
enforcer := new(Enforcer)
|
||||
enforcer.Adapter = newName
|
||||
_, err = session.Where("adapter=?", oldName).Update(enforcer)
|
||||
if err != nil {
|
||||
session.Rollback()
|
||||
return err
|
||||
}
|
||||
|
||||
return session.Commit()
|
||||
}
|
||||
|
||||
func safeReturn(policy []string, i int) string {
|
||||
if len(policy) > i {
|
||||
return policy[i]
|
||||
|
@@ -365,7 +365,7 @@ func CheckAccessPermission(userId string, application *Application) (bool, error
|
||||
if containsAsterisk {
|
||||
return true, err
|
||||
}
|
||||
enforcer := getEnforcer(permission)
|
||||
enforcer := getPermissionEnforcer(permission)
|
||||
if allowed, err = enforcer.Enforce(userId, application.Name, "read"); allowed {
|
||||
return allowed, err
|
||||
}
|
||||
|
119
object/enforcer.go
Normal file
119
object/enforcer.go
Normal file
@@ -0,0 +1,119 @@
|
||||
// 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 (
|
||||
"github.com/casbin/casbin/v2"
|
||||
"github.com/casdoor/casdoor/util"
|
||||
"github.com/xorm-io/core"
|
||||
)
|
||||
|
||||
type Enforcer struct {
|
||||
Owner string `xorm:"varchar(100) notnull pk" json:"owner"`
|
||||
Name string `xorm:"varchar(100) notnull pk" json:"name"`
|
||||
CreatedTime string `xorm:"varchar(100)" json:"createdTime"`
|
||||
UpdatedTime string `xorm:"varchar(100) updated" json:"updatedTime"`
|
||||
DisplayName string `xorm:"varchar(100)" json:"displayName"`
|
||||
Description string `xorm:"varchar(100)" json:"description"`
|
||||
|
||||
Model string `xorm:"varchar(100)" json:"model"`
|
||||
Adapter string `xorm:"varchar(100)" json:"adapter"`
|
||||
IsEnabled bool `json:"isEnabled"`
|
||||
|
||||
*casbin.Enforcer
|
||||
}
|
||||
|
||||
func GetEnforcerCount(owner, field, value string) (int64, error) {
|
||||
session := GetSession(owner, -1, -1, field, value, "", "")
|
||||
return session.Count(&Enforcer{})
|
||||
}
|
||||
|
||||
func GetEnforcers(owner string) ([]*Enforcer, error) {
|
||||
enforcers := []*Enforcer{}
|
||||
err := adapter.Engine.Desc("created_time").Find(&enforcers, &Enforcer{Owner: owner})
|
||||
if err != nil {
|
||||
return enforcers, err
|
||||
}
|
||||
|
||||
return enforcers, nil
|
||||
}
|
||||
|
||||
func GetPaginationEnforcers(owner string, offset, limit int, field, value, sortField, sortOrder string) ([]*Enforcer, error) {
|
||||
enforcers := []*Enforcer{}
|
||||
session := GetSession(owner, offset, limit, field, value, sortField, sortOrder)
|
||||
err := session.Find(&enforcers)
|
||||
if err != nil {
|
||||
return enforcers, err
|
||||
}
|
||||
|
||||
return enforcers, nil
|
||||
}
|
||||
|
||||
func getEnforcer(owner string, name string) (*Enforcer, error) {
|
||||
if owner == "" || name == "" {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
enforcer := Enforcer{Owner: owner, Name: name}
|
||||
existed, err := adapter.Engine.Get(&enforcer)
|
||||
if err != nil {
|
||||
return &enforcer, err
|
||||
}
|
||||
|
||||
if existed {
|
||||
return &enforcer, nil
|
||||
} else {
|
||||
return nil, nil
|
||||
}
|
||||
}
|
||||
|
||||
func GetEnforcer(id string) (*Enforcer, error) {
|
||||
owner, name := util.GetOwnerAndNameFromId(id)
|
||||
return getEnforcer(owner, name)
|
||||
}
|
||||
|
||||
func UpdateEnforcer(id string, enforcer *Enforcer) (bool, error) {
|
||||
owner, name := util.GetOwnerAndNameFromId(id)
|
||||
if oldEnforcer, err := getEnforcer(owner, name); err != nil {
|
||||
return false, err
|
||||
} else if oldEnforcer == nil {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
affected, err := adapter.Engine.ID(core.PK{owner, name}).AllCols().Update(enforcer)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return affected != 0, nil
|
||||
}
|
||||
|
||||
func AddEnforcer(enforcer *Enforcer) (bool, error) {
|
||||
affected, err := adapter.Engine.Insert(enforcer)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return affected != 0, nil
|
||||
}
|
||||
|
||||
func DeleteEnforcer(enforcer *Enforcer) (bool, error) {
|
||||
affected, err := adapter.Engine.ID(core.PK{enforcer.Owner, enforcer.Name}).Delete(&Enforcer{})
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return affected != 0, nil
|
||||
}
|
@@ -135,12 +135,18 @@ func GetMaskedLdaps(ldaps []*Ldap, errs ...error) ([]*Ldap, error) {
|
||||
}
|
||||
|
||||
func UpdateLdap(ldap *Ldap) (bool, error) {
|
||||
if l, err := GetLdap(ldap.Id); err != nil {
|
||||
var l *Ldap
|
||||
var err error
|
||||
if l, err = GetLdap(ldap.Id); err != nil {
|
||||
return false, nil
|
||||
} else if l == nil {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
if ldap.Password == "***" {
|
||||
ldap.Password = l.Password
|
||||
}
|
||||
|
||||
affected, err := adapter.Engine.ID(ldap.Id).Cols("owner", "server_name", "host",
|
||||
"port", "enable_ssl", "username", "password", "base_dn", "filter", "filter_fields", "auto_sync").Update(ldap)
|
||||
if err != nil {
|
||||
|
@@ -154,6 +154,15 @@ func modelChangeTrigger(oldName string, newName string) error {
|
||||
permission.Model = newName
|
||||
_, err = session.Where("model=?", oldName).Update(permission)
|
||||
if err != nil {
|
||||
session.Rollback()
|
||||
return err
|
||||
}
|
||||
|
||||
enforcer := new(Enforcer)
|
||||
enforcer.Model = newName
|
||||
_, err = session.Where("model=?", oldName).Update(enforcer)
|
||||
if err != nil {
|
||||
session.Rollback()
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -161,5 +170,8 @@ func modelChangeTrigger(oldName string, newName string) error {
|
||||
}
|
||||
|
||||
func HasRoleDefinition(m model.Model) bool {
|
||||
if m == nil {
|
||||
return false
|
||||
}
|
||||
return m["g"] != nil
|
||||
}
|
||||
|
@@ -112,13 +112,13 @@ func getPermission(owner string, name string) (*Permission, error) {
|
||||
}
|
||||
|
||||
func GetPermission(id string) (*Permission, error) {
|
||||
owner, name := util.GetOwnerAndNameFromId(id)
|
||||
owner, name := util.GetOwnerAndNameFromIdNoCheck(id)
|
||||
return getPermission(owner, name)
|
||||
}
|
||||
|
||||
// checkPermissionValid verifies if the permission is valid
|
||||
func checkPermissionValid(permission *Permission) error {
|
||||
enforcer := getEnforcer(permission)
|
||||
enforcer := getPermissionEnforcer(permission)
|
||||
enforcer.EnableAutoSave(false)
|
||||
|
||||
policies := getPolicies(permission)
|
||||
@@ -149,7 +149,7 @@ func UpdatePermission(id string, permission *Permission) (bool, error) {
|
||||
return false, err
|
||||
}
|
||||
|
||||
owner, name := util.GetOwnerAndNameFromId(id)
|
||||
owner, name := util.GetOwnerAndNameFromIdNoCheck(id)
|
||||
oldPermission, err := getPermission(owner, name)
|
||||
if oldPermission == nil {
|
||||
return false, nil
|
||||
|
@@ -26,42 +26,7 @@ import (
|
||||
xormadapter "github.com/casdoor/xorm-adapter/v3"
|
||||
)
|
||||
|
||||
func getEnforcer(permission *Permission, permissionIDs ...string) *casbin.Enforcer {
|
||||
tableName := "permission_rule"
|
||||
if len(permission.Adapter) != 0 {
|
||||
adapterObj, err := getCasbinAdapter(permission.Owner, permission.Adapter)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
if adapterObj != nil && adapterObj.Table != "" {
|
||||
tableName = adapterObj.Table
|
||||
}
|
||||
}
|
||||
tableNamePrefix := conf.GetConfigString("tableNamePrefix")
|
||||
driverName := conf.GetConfigString("driverName")
|
||||
dataSourceName := conf.GetConfigRealDataSourceName(driverName)
|
||||
adapter, err := xormadapter.NewAdapterWithTableName(driverName, dataSourceName, tableName, tableNamePrefix, true)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
permissionModel, err := getModel(permission.Owner, permission.Model)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
m := model.Model{}
|
||||
if permissionModel != nil {
|
||||
m, err = GetBuiltInModel(permissionModel.ModelText)
|
||||
} else {
|
||||
m, err = GetBuiltInModel("")
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
func getPermissionEnforcer(p *Permission, permissionIDs ...string) *casbin.Enforcer {
|
||||
// Init an enforcer instance without specifying a model or adapter.
|
||||
// If you specify an adapter, it will load all policies, which is a
|
||||
// heavy process that can slow down the application.
|
||||
@@ -70,14 +35,17 @@ func getEnforcer(permission *Permission, permissionIDs ...string) *casbin.Enforc
|
||||
panic(err)
|
||||
}
|
||||
|
||||
err = enforcer.InitWithModelAndAdapter(m, nil)
|
||||
err = p.setEnforcerModel(enforcer)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
enforcer.SetAdapter(adapter)
|
||||
err = p.setEnforcerAdapter(enforcer)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
policyFilterV5 := []string{permission.GetId()}
|
||||
policyFilterV5 := []string{p.GetId()}
|
||||
if len(permissionIDs) != 0 {
|
||||
policyFilterV5 = permissionIDs
|
||||
}
|
||||
@@ -86,7 +54,7 @@ func getEnforcer(permission *Permission, permissionIDs ...string) *casbin.Enforc
|
||||
V5: policyFilterV5,
|
||||
}
|
||||
|
||||
if !HasRoleDefinition(m) {
|
||||
if !HasRoleDefinition(enforcer.GetModel()) {
|
||||
policyFilter.Ptype = []string{"p"}
|
||||
}
|
||||
|
||||
@@ -98,35 +66,70 @@ func getEnforcer(permission *Permission, permissionIDs ...string) *casbin.Enforc
|
||||
return enforcer
|
||||
}
|
||||
|
||||
func (p *Permission) setEnforcerAdapter(enforcer *casbin.Enforcer) error {
|
||||
tableName := "permission_rule"
|
||||
if len(p.Adapter) != 0 {
|
||||
adapterObj, err := getCasbinAdapter(p.Owner, p.Adapter)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if adapterObj != nil && adapterObj.Table != "" {
|
||||
tableName = adapterObj.Table
|
||||
}
|
||||
}
|
||||
tableNamePrefix := conf.GetConfigString("tableNamePrefix")
|
||||
driverName := conf.GetConfigString("driverName")
|
||||
dataSourceName := conf.GetConfigRealDataSourceName(driverName)
|
||||
casbinAdapter, err := xormadapter.NewAdapterWithTableName(driverName, dataSourceName, tableName, tableNamePrefix, true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
enforcer.SetAdapter(casbinAdapter)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Permission) setEnforcerModel(enforcer *casbin.Enforcer) error {
|
||||
permissionModel, err := getModel(p.Owner, p.Model)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// TODO: return error if permissionModel is nil.
|
||||
m := model.Model{}
|
||||
if permissionModel != nil {
|
||||
m, err = GetBuiltInModel(permissionModel.ModelText)
|
||||
} else {
|
||||
m, err = GetBuiltInModel("")
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = enforcer.InitWithModelAndAdapter(m, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func getPolicies(permission *Permission) [][]string {
|
||||
var policies [][]string
|
||||
|
||||
permissionId := permission.GetId()
|
||||
domainExist := len(permission.Domains) > 0
|
||||
|
||||
for _, user := range permission.Users {
|
||||
usersAndRoles := append(permission.Users, permission.Roles...)
|
||||
for _, userOrRole := range usersAndRoles {
|
||||
for _, resource := range permission.Resources {
|
||||
for _, action := range permission.Actions {
|
||||
if domainExist {
|
||||
for _, domain := range permission.Domains {
|
||||
policies = append(policies, []string{user, domain, resource, strings.ToLower(action), permission.Effect, permissionId})
|
||||
policies = append(policies, []string{userOrRole, domain, resource, strings.ToLower(action), strings.ToLower(permission.Effect), permissionId})
|
||||
}
|
||||
} else {
|
||||
policies = append(policies, []string{user, resource, strings.ToLower(action), permission.Effect, "", permissionId})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for _, role := range permission.Roles {
|
||||
for _, resource := range permission.Resources {
|
||||
for _, action := range permission.Actions {
|
||||
if domainExist {
|
||||
for _, domain := range permission.Domains {
|
||||
policies = append(policies, []string{role, domain, resource, strings.ToLower(action), "", permissionId})
|
||||
}
|
||||
} else {
|
||||
policies = append(policies, []string{role, resource, strings.ToLower(action), "", "", permissionId})
|
||||
policies = append(policies, []string{userOrRole, resource, strings.ToLower(action), strings.ToLower(permission.Effect), "", permissionId})
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -201,7 +204,7 @@ func getGroupingPolicies(permission *Permission) [][]string {
|
||||
}
|
||||
|
||||
func addPolicies(permission *Permission) {
|
||||
enforcer := getEnforcer(permission)
|
||||
enforcer := getPermissionEnforcer(permission)
|
||||
policies := getPolicies(permission)
|
||||
|
||||
_, err := enforcer.AddPolicies(policies)
|
||||
@@ -211,7 +214,7 @@ func addPolicies(permission *Permission) {
|
||||
}
|
||||
|
||||
func addGroupingPolicies(permission *Permission) {
|
||||
enforcer := getEnforcer(permission)
|
||||
enforcer := getPermissionEnforcer(permission)
|
||||
groupingPolicies := getGroupingPolicies(permission)
|
||||
|
||||
if len(groupingPolicies) > 0 {
|
||||
@@ -223,7 +226,7 @@ func addGroupingPolicies(permission *Permission) {
|
||||
}
|
||||
|
||||
func removeGroupingPolicies(permission *Permission) {
|
||||
enforcer := getEnforcer(permission)
|
||||
enforcer := getPermissionEnforcer(permission)
|
||||
groupingPolicies := getGroupingPolicies(permission)
|
||||
|
||||
if len(groupingPolicies) > 0 {
|
||||
@@ -235,7 +238,7 @@ func removeGroupingPolicies(permission *Permission) {
|
||||
}
|
||||
|
||||
func removePolicies(permission *Permission) {
|
||||
enforcer := getEnforcer(permission)
|
||||
enforcer := getPermissionEnforcer(permission)
|
||||
policies := getPolicies(permission)
|
||||
|
||||
_, err := enforcer.RemovePolicies(policies)
|
||||
@@ -247,12 +250,12 @@ func removePolicies(permission *Permission) {
|
||||
type CasbinRequest = []interface{}
|
||||
|
||||
func Enforce(permission *Permission, request *CasbinRequest, permissionIds ...string) (bool, error) {
|
||||
enforcer := getEnforcer(permission, permissionIds...)
|
||||
enforcer := getPermissionEnforcer(permission, permissionIds...)
|
||||
return enforcer.Enforce(*request...)
|
||||
}
|
||||
|
||||
func BatchEnforce(permission *Permission, requests *[]CasbinRequest, permissionIds ...string) ([]bool, error) {
|
||||
enforcer := getEnforcer(permission, permissionIds...)
|
||||
enforcer := getPermissionEnforcer(permission, permissionIds...)
|
||||
return enforcer.BatchEnforce(*requests)
|
||||
}
|
||||
|
||||
@@ -273,7 +276,7 @@ func getAllValues(userId string, fn func(enforcer *casbin.Enforcer) []string) []
|
||||
|
||||
var values []string
|
||||
for _, permission := range permissions {
|
||||
enforcer := getEnforcer(permission)
|
||||
enforcer := getPermissionEnforcer(permission)
|
||||
values = append(values, fn(enforcer)...)
|
||||
}
|
||||
return values
|
||||
|
@@ -16,6 +16,7 @@ package object
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/casdoor/casdoor/util"
|
||||
"github.com/xorm-io/core"
|
||||
@@ -76,6 +77,10 @@ func GetPaginationResources(owner, user string, offset, limit int, field, value,
|
||||
}
|
||||
|
||||
func getResource(owner string, name string) (*Resource, error) {
|
||||
if !strings.HasPrefix(name, "/") {
|
||||
name = "/" + name
|
||||
}
|
||||
|
||||
resource := Resource{Owner: owner, Name: name}
|
||||
existed, err := adapter.Engine.Get(&resource)
|
||||
if err != nil {
|
||||
|
@@ -82,12 +82,12 @@ func getRole(owner string, name string) (*Role, error) {
|
||||
}
|
||||
|
||||
func GetRole(id string) (*Role, error) {
|
||||
owner, name := util.GetOwnerAndNameFromId(id)
|
||||
owner, name := util.GetOwnerAndNameFromIdNoCheck(id)
|
||||
return getRole(owner, name)
|
||||
}
|
||||
|
||||
func UpdateRole(id string, role *Role) (bool, error) {
|
||||
owner, name := util.GetOwnerAndNameFromId(id)
|
||||
owner, name := util.GetOwnerAndNameFromIdNoCheck(id)
|
||||
oldRole, err := getRole(owner, name)
|
||||
if err != nil {
|
||||
return false, err
|
||||
@@ -391,10 +391,13 @@ func GetAncestorRoles(roleIds ...string) ([]*Role, error) {
|
||||
|
||||
// containsRole is a helper function to check if a roles is related to any role in the given list roles
|
||||
func containsRole(role *Role, roleMap map[string]*Role, visited map[string]bool, roleIds ...string) bool {
|
||||
if isContain, ok := visited[role.GetId()]; ok {
|
||||
roleId := role.GetId()
|
||||
if isContain, ok := visited[roleId]; ok {
|
||||
return isContain
|
||||
}
|
||||
|
||||
visited[role.GetId()] = false
|
||||
|
||||
for _, subRole := range role.Roles {
|
||||
if util.HasString(roleIds, subRole) {
|
||||
return true
|
||||
|
@@ -26,6 +26,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/beevik/etree"
|
||||
"github.com/casdoor/casdoor/i18n"
|
||||
"github.com/casdoor/casdoor/util"
|
||||
dsig "github.com/russellhaering/goxmldsig"
|
||||
)
|
||||
@@ -122,6 +123,13 @@ var stToServiceResponse sync.Map
|
||||
// pgt is short for proxy granting ticket
|
||||
var pgtToServiceResponse sync.Map
|
||||
|
||||
func CheckCasRestrict(application *Application, lang string, service string) error {
|
||||
if len(application.RedirectUris) > 0 && !application.IsRedirectUriValid(service) {
|
||||
return fmt.Errorf(i18n.Translate(lang, "token:Redirect URI: %s doesn't exist in the allowed Redirect URI list"), service)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func StoreCasTokenForPgt(token *CasAuthenticationSuccess, service, userId string) string {
|
||||
pgt := fmt.Sprintf("PGT-%s", util.GenerateId())
|
||||
pgtToServiceResponse.Store(pgt, &CasAuthenticationSuccessWrapper{
|
||||
|
@@ -281,6 +281,14 @@ func generateJwtToken(application *Application, user *User, nonce string, scope
|
||||
return "", "", "", err
|
||||
}
|
||||
|
||||
if cert == nil {
|
||||
if application.Cert == "" {
|
||||
return "", "", "", fmt.Errorf("The cert field of the application \"%s\" should not be empty", application.GetId())
|
||||
} else {
|
||||
return "", "", "", fmt.Errorf("The cert \"%s\" does not exist", application.Cert)
|
||||
}
|
||||
}
|
||||
|
||||
// RSA private key
|
||||
key, err := jwt.ParseRSAPrivateKeyFromPEM([]byte(cert.PrivateKey))
|
||||
if err != nil {
|
||||
|
@@ -860,3 +860,11 @@ func AddUserkeys(user *User, isAdmin bool) (bool, error) {
|
||||
|
||||
return UpdateUser(user.GetId(), user, []string{}, isAdmin)
|
||||
}
|
||||
|
||||
func (user *User) IsApplicationAdmin(application *Application) bool {
|
||||
if user == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
return (user.Owner == application.Organization && user.IsAdmin) || user.IsGlobalAdmin
|
||||
}
|
||||
|
@@ -69,7 +69,7 @@ func getObject(ctx *context.Context) (string, string) {
|
||||
// query == "?id=built-in/admin"
|
||||
id := ctx.Input.Query("id")
|
||||
if id != "" {
|
||||
return util.GetOwnerAndNameFromId(id)
|
||||
return util.GetOwnerAndNameFromIdNoCheck(id)
|
||||
}
|
||||
|
||||
owner := ctx.Input.Query("owner")
|
||||
@@ -156,7 +156,7 @@ func AuthzFilter(ctx *context.Context) {
|
||||
urlPath := getUrlPath(ctx.Request.URL.Path)
|
||||
|
||||
objOwner, objName := "", ""
|
||||
if urlPath != "/api/get-app-login" {
|
||||
if urlPath != "/api/get-app-login" && urlPath != "/api/get-resource" {
|
||||
objOwner, objName = getObject(ctx)
|
||||
}
|
||||
|
||||
|
@@ -17,6 +17,10 @@
|
||||
// @Title Casdoor API
|
||||
// @Description Documentation of Casdoor API
|
||||
// @Contact admin@casbin.org
|
||||
// @SecurityDefinition test_apiKey apiKey Authorization header
|
||||
// @Schemes http,https
|
||||
// @ExternalDocs Find out more about casdoor
|
||||
// @ExternalDocsUrl https://casdoor.org/
|
||||
package routers
|
||||
|
||||
import (
|
||||
@@ -123,6 +127,12 @@ func initAPI() {
|
||||
beego.Router("/api/add-policy", &controllers.ApiController{}, "POST:AddPolicy")
|
||||
beego.Router("/api/remove-policy", &controllers.ApiController{}, "POST:RemovePolicy")
|
||||
|
||||
beego.Router("/api/get-enforcers", &controllers.ApiController{}, "GET:GetEnforcers")
|
||||
beego.Router("/api/get-enforcer", &controllers.ApiController{}, "GET:GetEnforcer")
|
||||
beego.Router("/api/update-enforcer", &controllers.ApiController{}, "POST:UpdateEnforcer")
|
||||
beego.Router("/api/add-enforcer", &controllers.ApiController{}, "POST:AddEnforcer")
|
||||
beego.Router("/api/delete-enforcer", &controllers.ApiController{}, "POST:DeleteEnforcer")
|
||||
|
||||
beego.Router("/api/set-password", &controllers.ApiController{}, "POST:SetPassword")
|
||||
beego.Router("/api/check-user-password", &controllers.ApiController{}, "POST:CheckUserPassword")
|
||||
beego.Router("/api/get-email-and-phone", &controllers.ApiController{}, "GET:GetEmailAndPhone")
|
||||
|
@@ -23,7 +23,7 @@ func GetStorageProvider(providerType string, clientId string, clientSecret strin
|
||||
case "AWS S3":
|
||||
return NewAwsS3StorageProvider(clientId, clientSecret, region, bucket, endpoint)
|
||||
case "MinIO":
|
||||
return NewMinIOS3StorageProvider(clientId, clientSecret, region, bucket, endpoint)
|
||||
return NewMinIOS3StorageProvider(clientId, clientSecret, "_", bucket, endpoint)
|
||||
case "Aliyun OSS":
|
||||
return NewAliyunOssStorageProvider(clientId, clientSecret, region, bucket, endpoint)
|
||||
case "Tencent Cloud COS":
|
||||
|
@@ -9,6 +9,10 @@
|
||||
}
|
||||
},
|
||||
"basePath": "/",
|
||||
"schemes": [
|
||||
"http",
|
||||
"https"
|
||||
],
|
||||
"paths": {
|
||||
"/.well-known/jwks": {
|
||||
"get": {
|
||||
@@ -155,6 +159,34 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/add-enforcer": {
|
||||
"post": {
|
||||
"tags": [
|
||||
"Enforcer API"
|
||||
],
|
||||
"description": "add enforcer",
|
||||
"operationId": "ApiController.AddEnforcer",
|
||||
"parameters": [
|
||||
{
|
||||
"in": "body",
|
||||
"name": "enforcer",
|
||||
"description": "The enforcer object",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/object"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/object"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/add-group": {
|
||||
"post": {
|
||||
"tags": [
|
||||
@@ -1073,6 +1105,34 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/delete-enforcer": {
|
||||
"post": {
|
||||
"tags": [
|
||||
"Enforcer API"
|
||||
],
|
||||
"description": "delete enforcer",
|
||||
"operationId": "ApiController.DeleteEnforcer",
|
||||
"parameters": [
|
||||
{
|
||||
"in": "body",
|
||||
"name": "body",
|
||||
"description": "The enforcer object",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/object.Enforce"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/object"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/delete-group": {
|
||||
"post": {
|
||||
"tags": [
|
||||
@@ -2018,6 +2078,61 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/get-enforcer": {
|
||||
"get": {
|
||||
"tags": [
|
||||
"Enforcer API"
|
||||
],
|
||||
"description": "get enforcer",
|
||||
"operationId": "ApiController.GetEnforcer",
|
||||
"parameters": [
|
||||
{
|
||||
"in": "query",
|
||||
"name": "id",
|
||||
"description": "The id ( owner/name ) of enforcer",
|
||||
"required": true,
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/object"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/get-enforcers": {
|
||||
"get": {
|
||||
"tags": [
|
||||
"Enforcer API"
|
||||
],
|
||||
"description": "get enforcers",
|
||||
"operationId": "ApiController.GetEnforcers",
|
||||
"parameters": [
|
||||
{
|
||||
"in": "query",
|
||||
"name": "owner",
|
||||
"description": "The owner of enforcers",
|
||||
"required": true,
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "",
|
||||
"schema": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/object.Enforcer"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/get-global-providers": {
|
||||
"get": {
|
||||
"tags": [
|
||||
@@ -3571,7 +3686,8 @@
|
||||
"name": "id",
|
||||
"description": "The id ( owner/name ) of the webhook",
|
||||
"required": true,
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"default": "built-in/admin"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
@@ -3597,7 +3713,8 @@
|
||||
"name": "owner",
|
||||
"description": "The owner of webhooks",
|
||||
"required": true,
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"default": "built-in/admin"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
@@ -3610,7 +3727,12 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"test_apiKey": []
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"/api/health": {
|
||||
@@ -4394,6 +4516,41 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/update-enforcer": {
|
||||
"post": {
|
||||
"tags": [
|
||||
"Enforcer API"
|
||||
],
|
||||
"description": "update enforcer",
|
||||
"operationId": "ApiController.UpdateEnforcer",
|
||||
"parameters": [
|
||||
{
|
||||
"in": "query",
|
||||
"name": "id",
|
||||
"description": "The id ( owner/name ) of enforcer",
|
||||
"required": true,
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"in": "body",
|
||||
"name": "enforcer",
|
||||
"description": "The enforcer object",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/object"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/object"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/update-group": {
|
||||
"post": {
|
||||
"tags": [
|
||||
@@ -5024,7 +5181,8 @@
|
||||
"name": "id",
|
||||
"description": "The id ( owner/name ) of the webhook",
|
||||
"required": true,
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"default": "built-in/admin"
|
||||
},
|
||||
{
|
||||
"in": "body",
|
||||
@@ -5289,6 +5447,10 @@
|
||||
"title": "Response",
|
||||
"type": "object"
|
||||
},
|
||||
"casbin.Enforcer": {
|
||||
"title": "Enforcer",
|
||||
"type": "object"
|
||||
},
|
||||
"controllers.AuthForm": {
|
||||
"title": "AuthForm",
|
||||
"type": "object"
|
||||
@@ -5323,13 +5485,13 @@
|
||||
"properties": {
|
||||
"data": {
|
||||
"additionalProperties": {
|
||||
"description": "support string, struct or []struct",
|
||||
"description": "support string | class | List\u003cclass\u003e and os on",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"data2": {
|
||||
"additionalProperties": {
|
||||
"description": "support string, struct or []struct",
|
||||
"description": "support string | class | List\u003cclass\u003e and os on",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
@@ -5662,6 +5824,43 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"object.Enforce": {
|
||||
"title": "Enforce",
|
||||
"type": "object"
|
||||
},
|
||||
"object.Enforcer": {
|
||||
"title": "Enforcer",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"adapter": {
|
||||
"type": "string"
|
||||
},
|
||||
"createdTime": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": {
|
||||
"type": "string"
|
||||
},
|
||||
"displayName": {
|
||||
"type": "string"
|
||||
},
|
||||
"isEnabled": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"model": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"owner": {
|
||||
"type": "string"
|
||||
},
|
||||
"updatedTime": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"object.GaugeVecInfo": {
|
||||
"title": "GaugeVecInfo",
|
||||
"type": "object",
|
||||
@@ -7323,6 +7522,9 @@
|
||||
"meetup": {
|
||||
"type": "string"
|
||||
},
|
||||
"metamask": {
|
||||
"type": "string"
|
||||
},
|
||||
"mfaEmailEnabled": {
|
||||
"type": "boolean"
|
||||
},
|
||||
@@ -7569,15 +7771,21 @@
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"contentType": {
|
||||
"type": "string"
|
||||
"default": "application/json",
|
||||
"type": "string",
|
||||
"example": "application/json"
|
||||
},
|
||||
"createdTime": {
|
||||
"type": "string"
|
||||
"default": "2023-07-27T17:09:12+08:00",
|
||||
"type": "string",
|
||||
"example": "2023-07-27T17:09:12+08:00"
|
||||
},
|
||||
"events": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"default": "test",
|
||||
"example": "test"
|
||||
}
|
||||
},
|
||||
"headers": {
|
||||
@@ -7587,25 +7795,39 @@
|
||||
}
|
||||
},
|
||||
"isEnabled": {
|
||||
"type": "boolean"
|
||||
"default": true,
|
||||
"type": "boolean",
|
||||
"example": true
|
||||
},
|
||||
"isUserExtended": {
|
||||
"type": "boolean"
|
||||
"default": true,
|
||||
"type": "boolean",
|
||||
"example": true
|
||||
},
|
||||
"method": {
|
||||
"type": "string"
|
||||
"default": "POST",
|
||||
"type": "string",
|
||||
"example": "POST"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
"default": "test",
|
||||
"type": "string",
|
||||
"example": "test"
|
||||
},
|
||||
"organization": {
|
||||
"type": "string"
|
||||
"default": "built-in",
|
||||
"type": "string",
|
||||
"example": "built-in"
|
||||
},
|
||||
"owner": {
|
||||
"type": "string"
|
||||
"default": "built-in",
|
||||
"type": "string",
|
||||
"example": "built-in"
|
||||
},
|
||||
"url": {
|
||||
"type": "string"
|
||||
"default": "https://example.com/callback",
|
||||
"type": "string",
|
||||
"example": "https://example.com/callback"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -7670,5 +7892,16 @@
|
||||
"title": "Engine",
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"securityDefinitions": {
|
||||
"test_apiKey": {
|
||||
"type": "apiKey",
|
||||
"name": "Authorization",
|
||||
"in": "header"
|
||||
}
|
||||
},
|
||||
"externalDocs": {
|
||||
"description": "Find out more about casdoor",
|
||||
"url": "https://casdoor.org/"
|
||||
}
|
||||
}
|
@@ -6,6 +6,9 @@ info:
|
||||
contact:
|
||||
email: admin@casbin.org
|
||||
basePath: /
|
||||
schemes:
|
||||
- http
|
||||
- https
|
||||
paths:
|
||||
/.well-known/jwks:
|
||||
get:
|
||||
@@ -100,6 +103,24 @@ paths:
|
||||
description: The Response object
|
||||
schema:
|
||||
$ref: '#/definitions/controllers.Response'
|
||||
/api/add-enforcer:
|
||||
post:
|
||||
tags:
|
||||
- Enforcer API
|
||||
description: add enforcer
|
||||
operationId: ApiController.AddEnforcer
|
||||
parameters:
|
||||
- in: body
|
||||
name: enforcer
|
||||
description: The enforcer object
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/object'
|
||||
responses:
|
||||
"200":
|
||||
description: ""
|
||||
schema:
|
||||
$ref: '#/definitions/object'
|
||||
/api/add-group:
|
||||
post:
|
||||
tags:
|
||||
@@ -693,6 +714,24 @@ paths:
|
||||
description: The Response object
|
||||
schema:
|
||||
$ref: '#/definitions/controllers.Response'
|
||||
/api/delete-enforcer:
|
||||
post:
|
||||
tags:
|
||||
- Enforcer API
|
||||
description: delete enforcer
|
||||
operationId: ApiController.DeleteEnforcer
|
||||
parameters:
|
||||
- in: body
|
||||
name: body
|
||||
description: The enforcer object
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/object.Enforce'
|
||||
responses:
|
||||
"200":
|
||||
description: ""
|
||||
schema:
|
||||
$ref: '#/definitions/object'
|
||||
/api/delete-group:
|
||||
post:
|
||||
tags:
|
||||
@@ -1307,6 +1346,42 @@ paths:
|
||||
description: The Response object
|
||||
schema:
|
||||
$ref: '#/definitions/controllers.Response'
|
||||
/api/get-enforcer:
|
||||
get:
|
||||
tags:
|
||||
- Enforcer API
|
||||
description: get enforcer
|
||||
operationId: ApiController.GetEnforcer
|
||||
parameters:
|
||||
- in: query
|
||||
name: id
|
||||
description: The id ( owner/name ) of enforcer
|
||||
required: true
|
||||
type: string
|
||||
responses:
|
||||
"200":
|
||||
description: ""
|
||||
schema:
|
||||
$ref: '#/definitions/object'
|
||||
/api/get-enforcers:
|
||||
get:
|
||||
tags:
|
||||
- Enforcer API
|
||||
description: get enforcers
|
||||
operationId: ApiController.GetEnforcers
|
||||
parameters:
|
||||
- in: query
|
||||
name: owner
|
||||
description: The owner of enforcers
|
||||
required: true
|
||||
type: string
|
||||
responses:
|
||||
"200":
|
||||
description: ""
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/definitions/object.Enforcer'
|
||||
/api/get-global-providers:
|
||||
get:
|
||||
tags:
|
||||
@@ -2329,6 +2404,7 @@ paths:
|
||||
description: The id ( owner/name ) of the webhook
|
||||
required: true
|
||||
type: string
|
||||
default: built-in/admin
|
||||
responses:
|
||||
"200":
|
||||
description: The Response object
|
||||
@@ -2346,6 +2422,7 @@ paths:
|
||||
description: The owner of webhooks
|
||||
required: true
|
||||
type: string
|
||||
default: built-in/admin
|
||||
responses:
|
||||
"200":
|
||||
description: The Response object
|
||||
@@ -2353,6 +2430,8 @@ paths:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/definitions/object.Webhook'
|
||||
security:
|
||||
- test_apiKey: []
|
||||
/api/health:
|
||||
get:
|
||||
tags:
|
||||
@@ -2869,6 +2948,29 @@ paths:
|
||||
description: The Response object
|
||||
schema:
|
||||
$ref: '#/definitions/controllers.Response'
|
||||
/api/update-enforcer:
|
||||
post:
|
||||
tags:
|
||||
- Enforcer API
|
||||
description: update enforcer
|
||||
operationId: ApiController.UpdateEnforcer
|
||||
parameters:
|
||||
- in: query
|
||||
name: id
|
||||
description: The id ( owner/name ) of enforcer
|
||||
required: true
|
||||
type: string
|
||||
- in: body
|
||||
name: enforcer
|
||||
description: The enforcer object
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/object'
|
||||
responses:
|
||||
"200":
|
||||
description: ""
|
||||
schema:
|
||||
$ref: '#/definitions/object'
|
||||
/api/update-group:
|
||||
post:
|
||||
tags:
|
||||
@@ -3286,6 +3388,7 @@ paths:
|
||||
description: The id ( owner/name ) of the webhook
|
||||
required: true
|
||||
type: string
|
||||
default: built-in/admin
|
||||
- in: body
|
||||
name: body
|
||||
description: The details of the webhook
|
||||
@@ -3458,6 +3561,9 @@ definitions:
|
||||
Response:
|
||||
title: Response
|
||||
type: object
|
||||
casbin.Enforcer:
|
||||
title: Enforcer
|
||||
type: object
|
||||
controllers.AuthForm:
|
||||
title: AuthForm
|
||||
type: object
|
||||
@@ -3483,11 +3589,11 @@ definitions:
|
||||
properties:
|
||||
data:
|
||||
additionalProperties:
|
||||
description: support string, struct or []struct
|
||||
description: support string | class | List<class> and os on
|
||||
type: string
|
||||
data2:
|
||||
additionalProperties:
|
||||
description: support string, struct or []struct
|
||||
description: support string | class | List<class> and os on
|
||||
type: string
|
||||
msg:
|
||||
type: string
|
||||
@@ -3710,6 +3816,31 @@ definitions:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
object.Enforce:
|
||||
title: Enforce
|
||||
type: object
|
||||
object.Enforcer:
|
||||
title: Enforcer
|
||||
type: object
|
||||
properties:
|
||||
adapter:
|
||||
type: string
|
||||
createdTime:
|
||||
type: string
|
||||
description:
|
||||
type: string
|
||||
displayName:
|
||||
type: string
|
||||
isEnabled:
|
||||
type: boolean
|
||||
model:
|
||||
type: string
|
||||
name:
|
||||
type: string
|
||||
owner:
|
||||
type: string
|
||||
updatedTime:
|
||||
type: string
|
||||
object.GaugeVecInfo:
|
||||
title: GaugeVecInfo
|
||||
type: object
|
||||
@@ -4828,6 +4959,8 @@ definitions:
|
||||
$ref: '#/definitions/object.ManagedAccount'
|
||||
meetup:
|
||||
type: string
|
||||
metamask:
|
||||
type: string
|
||||
mfaEmailEnabled:
|
||||
type: boolean
|
||||
mfaPhoneEnabled:
|
||||
@@ -4993,31 +5126,51 @@ definitions:
|
||||
type: object
|
||||
properties:
|
||||
contentType:
|
||||
default: application/json
|
||||
type: string
|
||||
example: application/json
|
||||
createdTime:
|
||||
default: "2023-07-27T17:09:12+08:00"
|
||||
type: string
|
||||
example: "2023-07-27T17:09:12+08:00"
|
||||
events:
|
||||
default: '[ddd]'
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
headers:
|
||||
default: '[]'
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/definitions/object.Header'
|
||||
isEnabled:
|
||||
default: true
|
||||
type: boolean
|
||||
example: true
|
||||
isUserExtended:
|
||||
default: true
|
||||
type: boolean
|
||||
example: true
|
||||
method:
|
||||
default: POST
|
||||
type: string
|
||||
example: POST
|
||||
name:
|
||||
default: test
|
||||
type: string
|
||||
example: test
|
||||
organization:
|
||||
default: built-in
|
||||
type: string
|
||||
example: built-in
|
||||
owner:
|
||||
default: built-in
|
||||
type: string
|
||||
example: built-in
|
||||
url:
|
||||
default: https://example.com/callback
|
||||
type: string
|
||||
example: https://example.com/callback
|
||||
protocol.CredentialAssertion:
|
||||
title: CredentialAssertion
|
||||
type: object
|
||||
@@ -5062,3 +5215,11 @@ definitions:
|
||||
xorm.Engine:
|
||||
title: Engine
|
||||
type: object
|
||||
securityDefinitions:
|
||||
test_apiKey:
|
||||
type: apiKey
|
||||
name: Authorization
|
||||
in: header
|
||||
externalDocs:
|
||||
description: Find out more about casdoor
|
||||
url: https://casdoor.org/
|
||||
|
@@ -33,6 +33,7 @@
|
||||
"react-device-detect": "^2.2.2",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-github-corner": "^2.5.0",
|
||||
"react-google-one-tap-login": "^0.1.1",
|
||||
"react-helmet": "^6.1.0",
|
||||
"react-highlight-words": "^0.18.0",
|
||||
"react-i18next": "^11.8.7",
|
||||
|
@@ -68,7 +68,7 @@ class AdapterEditPage extends React.Component {
|
||||
OrganizationBackend.getOrganizations("admin")
|
||||
.then((res) => {
|
||||
this.setState({
|
||||
organizations: (res.msg === undefined) ? res : [],
|
||||
organizations: res.data || [],
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -80,8 +80,9 @@ class AdapterEditPage extends React.Component {
|
||||
Setting.showMessage("error", res.msg);
|
||||
return;
|
||||
}
|
||||
|
||||
this.setState({
|
||||
models: res,
|
||||
models: res.data,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@@ -15,10 +15,6 @@
|
||||
import React, {Component} from "react";
|
||||
import "./App.less";
|
||||
import {Helmet} from "react-helmet";
|
||||
import EnableMfaNotification from "./common/notifaction/EnableMfaNotification";
|
||||
import GroupTreePage from "./GroupTreePage";
|
||||
import GroupEditPage from "./GroupEdit";
|
||||
import GroupListPage from "./GroupList";
|
||||
import {MfaRuleRequired} from "./Setting";
|
||||
import * as Setting from "./Setting";
|
||||
import {StyleProvider, legacyLogicalPropertiesTransformer} from "@ant-design/cssinjs";
|
||||
@@ -33,6 +29,11 @@ import RoleListPage from "./RoleListPage";
|
||||
import RoleEditPage from "./RoleEditPage";
|
||||
import PermissionListPage from "./PermissionListPage";
|
||||
import PermissionEditPage from "./PermissionEditPage";
|
||||
import EnforcerEditPage from "./EnforcerEditPage";
|
||||
import EnforcerListPage from "./EnforcerListPage";
|
||||
import GroupTreePage from "./GroupTreePage";
|
||||
import GroupEditPage from "./GroupEdit";
|
||||
import GroupListPage from "./GroupList";
|
||||
import ProviderListPage from "./ProviderListPage";
|
||||
import ProviderEditPage from "./ProviderEditPage";
|
||||
import ApplicationListPage from "./ApplicationListPage";
|
||||
@@ -86,6 +87,7 @@ import OdicDiscoveryPage from "./auth/OidcDiscoveryPage";
|
||||
import SamlCallback from "./auth/SamlCallback";
|
||||
import i18next from "i18next";
|
||||
import {withTranslation} from "react-i18next";
|
||||
import EnableMfaNotification from "./common/notifaction/EnableMfaNotification";
|
||||
import LanguageSelect from "./common/select/LanguageSelect";
|
||||
import ThemeSelect from "./common/select/ThemeSelect";
|
||||
import OrganizationSelect from "./common/select/OrganizationSelect";
|
||||
@@ -164,6 +166,8 @@ class App extends Component {
|
||||
this.setState({selectedMenuKey: "/models"});
|
||||
} else if (uri.includes("/adapters")) {
|
||||
this.setState({selectedMenuKey: "/adapters"});
|
||||
} else if (uri.includes("/enforcers")) {
|
||||
this.setState({selectedMenuKey: "/enforcers"});
|
||||
} else if (uri.includes("/providers")) {
|
||||
this.setState({selectedMenuKey: "/providers"});
|
||||
} else if (uri.includes("/applications")) {
|
||||
@@ -481,6 +485,10 @@ class App extends Component {
|
||||
res.push(Setting.getItem(<Link to="/adapters">{i18next.t("general:Adapters")}</Link>,
|
||||
"/adapters"
|
||||
));
|
||||
|
||||
res.push(Setting.getItem(<Link to="/enforcers">{i18next.t("general:Enforcers")}</Link>,
|
||||
"/enforcers"
|
||||
));
|
||||
}
|
||||
|
||||
if (Setting.isLocalAdminUser(this.state.account)) {
|
||||
@@ -599,6 +607,8 @@ class App extends Component {
|
||||
<Route exact path="/permissions/:organizationName/:permissionName" render={(props) => this.renderLoginIfNotLoggedIn(<PermissionEditPage account={this.state.account} {...props} />)} />
|
||||
<Route exact path="/models" render={(props) => this.renderLoginIfNotLoggedIn(<ModelListPage account={this.state.account} {...props} />)} />
|
||||
<Route exact path="/models/:organizationName/:modelName" render={(props) => this.renderLoginIfNotLoggedIn(<ModelEditPage account={this.state.account} {...props} />)} />
|
||||
<Route exact path="/enforcers" render={(props) => this.renderLoginIfNotLoggedIn(<EnforcerListPage account={this.state.account} {...props} />)} />
|
||||
<Route exact path="/enforcers/:organizationName/:enforcerName" render={(props) => this.renderLoginIfNotLoggedIn(<EnforcerEditPage account={this.state.account} {...props} />)} />
|
||||
<Route exact path="/adapters" render={(props) => this.renderLoginIfNotLoggedIn(<AdapterListPage account={this.state.account} {...props} />)} />
|
||||
<Route exact path="/adapters/:organizationName/:adapterName" render={(props) => this.renderLoginIfNotLoggedIn(<AdapterEditPage account={this.state.account} {...props} />)} />
|
||||
<Route exact path="/providers" render={(props) => this.renderLoginIfNotLoggedIn(<ProviderListPage account={this.state.account} {...props} />)} />
|
||||
|
@@ -119,7 +119,7 @@ class ApplicationEditPage extends React.Component {
|
||||
getApplication() {
|
||||
ApplicationBackend.getApplication("admin", this.state.applicationName)
|
||||
.then((res) => {
|
||||
if (res === null) {
|
||||
if (res.data === null) {
|
||||
this.props.history.push("/404");
|
||||
return;
|
||||
}
|
||||
@@ -129,32 +129,33 @@ class ApplicationEditPage extends React.Component {
|
||||
return;
|
||||
}
|
||||
|
||||
if (res.grantTypes === null || res.grantTypes === undefined || res.grantTypes.length === 0) {
|
||||
res.grantTypes = ["authorization_code"];
|
||||
const application = res.data;
|
||||
if (application.grantTypes === null || application.grantTypes === undefined || application.grantTypes.length === 0) {
|
||||
application.grantTypes = ["authorization_code"];
|
||||
}
|
||||
|
||||
if (res.tags === null || res.tags === undefined) {
|
||||
res.tags = [];
|
||||
if (application.tags === null || application.tags === undefined) {
|
||||
application.tags = [];
|
||||
}
|
||||
|
||||
this.setState({
|
||||
application: res,
|
||||
application: application,
|
||||
});
|
||||
|
||||
this.getCerts(res.organization);
|
||||
this.getCerts(application.organization);
|
||||
});
|
||||
}
|
||||
|
||||
getOrganizations() {
|
||||
OrganizationBackend.getOrganizations("admin")
|
||||
.then((res) => {
|
||||
if (res?.status === "error") {
|
||||
if (res.status === "error") {
|
||||
this.setState({
|
||||
isAuthorized: false,
|
||||
});
|
||||
} else {
|
||||
this.setState({
|
||||
organizations: (res.msg === undefined) ? res : [],
|
||||
organizations: res.data || [],
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -164,7 +165,7 @@ class ApplicationEditPage extends React.Component {
|
||||
CertBackend.getCerts(owner)
|
||||
.then((res) => {
|
||||
this.setState({
|
||||
certs: (res.msg === undefined) ? res : [],
|
||||
certs: res.data || [],
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -184,9 +185,9 @@ class ApplicationEditPage extends React.Component {
|
||||
|
||||
getSamlMetadata() {
|
||||
ApplicationBackend.getSamlMetadata("admin", this.state.applicationName)
|
||||
.then((res) => {
|
||||
.then((data) => {
|
||||
this.setState({
|
||||
samlMetadata: res,
|
||||
samlMetadata: data,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@@ -45,7 +45,7 @@ class CertEditPage extends React.Component {
|
||||
getCert() {
|
||||
CertBackend.getCert(this.state.owner, this.state.certName)
|
||||
.then((res) => {
|
||||
if (res === null) {
|
||||
if (res.data === null) {
|
||||
this.props.history.push("/404");
|
||||
return;
|
||||
}
|
||||
@@ -56,7 +56,7 @@ class CertEditPage extends React.Component {
|
||||
}
|
||||
|
||||
this.setState({
|
||||
cert: res,
|
||||
cert: res.data,
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -65,7 +65,7 @@ class CertEditPage extends React.Component {
|
||||
OrganizationBackend.getOrganizations("admin")
|
||||
.then((res) => {
|
||||
this.setState({
|
||||
organizations: (res.msg === undefined) ? res : [],
|
||||
organizations: res.data || [],
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@@ -41,7 +41,7 @@ class ChatEditPage extends React.Component {
|
||||
getChat() {
|
||||
ChatBackend.getChat("admin", this.state.chatName)
|
||||
.then((res) => {
|
||||
if (res === null) {
|
||||
if (res.data === null) {
|
||||
this.props.history.push("/404");
|
||||
return;
|
||||
}
|
||||
@@ -51,10 +51,10 @@ class ChatEditPage extends React.Component {
|
||||
return;
|
||||
}
|
||||
this.setState({
|
||||
chat: res,
|
||||
chat: res.data,
|
||||
});
|
||||
|
||||
this.getUsers(res.organization);
|
||||
this.getUsers(res.data.organization);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ class ChatEditPage extends React.Component {
|
||||
OrganizationBackend.getOrganizations("admin")
|
||||
.then((res) => {
|
||||
this.setState({
|
||||
organizations: (res.msg === undefined) ? res : [],
|
||||
organizations: res.data || [],
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -76,7 +76,7 @@ class ChatEditPage extends React.Component {
|
||||
}
|
||||
|
||||
this.setState({
|
||||
users: res,
|
||||
users: res.data,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@@ -79,7 +79,8 @@ class ChatPage extends BaseListPage {
|
||||
|
||||
getMessages(chatName) {
|
||||
MessageBackend.getChatMessages(chatName)
|
||||
.then((messages) => {
|
||||
.then((res) => {
|
||||
const messages = res.data;
|
||||
this.setState({
|
||||
messages: messages,
|
||||
});
|
||||
@@ -229,7 +230,7 @@ class ChatPage extends BaseListPage {
|
||||
</div>
|
||||
)
|
||||
}
|
||||
<ChatBox messages={this.state.messages} sendMessage={(text) => {this.sendMessage(text);}} account={this.props.account} />
|
||||
<ChatBox messages={this.state.messages || []} sendMessage={(text) => {this.sendMessage(text);}} account={this.props.account} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
257
web/src/EnforcerEditPage.js
Normal file
257
web/src/EnforcerEditPage.js
Normal file
@@ -0,0 +1,257 @@
|
||||
// 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.
|
||||
|
||||
import React from "react";
|
||||
import {Button, Card, Col, Input, Row, Select, Switch} from "antd";
|
||||
import * as AdapterBackend from "./backend/AdapterBackend";
|
||||
import * as EnforcerBackend from "./backend/EnforcerBackend";
|
||||
import * as ModelBackend from "./backend/ModelBackend";
|
||||
import * as OrganizationBackend from "./backend/OrganizationBackend";
|
||||
import * as Setting from "./Setting";
|
||||
import i18next from "i18next";
|
||||
|
||||
class EnforcerEditPage extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
classes: props,
|
||||
organizationName: props.organizationName !== undefined ? props.organizationName : props.match.params.organizationName,
|
||||
enforcerName: props.match.params.enforcerName,
|
||||
enforcer: null,
|
||||
organizations: [],
|
||||
models: [],
|
||||
adapters: [],
|
||||
mode: props.location.mode !== undefined ? props.location.mode : "edit",
|
||||
};
|
||||
}
|
||||
|
||||
UNSAFE_componentWillMount() {
|
||||
this.getEnforcer();
|
||||
this.getOrganizations();
|
||||
}
|
||||
|
||||
getEnforcer() {
|
||||
EnforcerBackend.getEnforcer(this.state.organizationName, this.state.enforcerName)
|
||||
.then((res) => {
|
||||
if (res.data === null) {
|
||||
this.props.history.push("/404");
|
||||
return;
|
||||
}
|
||||
|
||||
if (res.status === "error") {
|
||||
Setting.showMessage("error", res.msg);
|
||||
return;
|
||||
}
|
||||
|
||||
this.setState({
|
||||
enforcer: res.data,
|
||||
});
|
||||
|
||||
this.getModels(this.state.organizationName);
|
||||
this.getAdapters(this.state.organizationName);
|
||||
});
|
||||
}
|
||||
|
||||
getOrganizations() {
|
||||
OrganizationBackend.getOrganizations("admin")
|
||||
.then((res) => {
|
||||
this.setState({
|
||||
organizations: res.data || [],
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
getModels(organizationName) {
|
||||
ModelBackend.getModels(organizationName)
|
||||
.then((res) => {
|
||||
this.setState({
|
||||
models: res.data || [],
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
getAdapters(organizationName) {
|
||||
AdapterBackend.getAdapters(organizationName)
|
||||
.then((res) => {
|
||||
this.setState({
|
||||
adapters: res.data || [],
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
parseEnforcerField(key, value) {
|
||||
if ([""].includes(key)) {
|
||||
value = Setting.myParseInt(value);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
updateEnforcerField(key, value) {
|
||||
value = this.parseEnforcerField(key, value);
|
||||
|
||||
const enforcer = this.state.enforcer;
|
||||
enforcer[key] = value;
|
||||
this.setState({
|
||||
enforcer: enforcer,
|
||||
});
|
||||
}
|
||||
|
||||
renderEnforcer() {
|
||||
return (
|
||||
<Card size="small" title={
|
||||
<div>
|
||||
{this.state.mode === "add" ? i18next.t("enforcer:New Enforcer") : i18next.t("enforcer:Edit Enforcer")}
|
||||
<Button onClick={() => this.submitEnforcerEdit(false)}>{i18next.t("general:Save")}</Button>
|
||||
<Button style={{marginLeft: "20px"}} type="primary" onClick={() => this.submitEnforcerEdit(true)}>{i18next.t("general:Save & Exit")}</Button>
|
||||
{this.state.mode === "add" ? <Button style={{marginLeft: "20px"}} onClick={() => this.deleteEnforcer()}>{i18next.t("general:Cancel")}</Button> : null}
|
||||
</div>
|
||||
} style={(Setting.isMobile()) ? {margin: "5px"} : {}} type="inner">
|
||||
<Row style={{marginTop: "10px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("general:Organization"), i18next.t("general:Organization - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Select virtual={false} style={{width: "100%"}} disabled={!Setting.isAdminUser(this.props.account)} value={this.state.enforcer.owner} onChange={(owner => {
|
||||
this.updateEnforcerField("owner", owner);
|
||||
this.getModels(owner);
|
||||
this.getAdapters(owner);
|
||||
})}
|
||||
options={this.state.organizations.map((organization) => Setting.getOption(organization.name, organization.name))
|
||||
} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("general:Name"), i18next.t("general:Name - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Input value={this.state.enforcer.name} onChange={e => {
|
||||
this.updateEnforcerField("name", e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("general:Display name"), i18next.t("general:Display name - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Input value={this.state.enforcer.displayName} onChange={e => {
|
||||
this.updateEnforcerField("displayName", e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("general:Description"), i18next.t("general:Description - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Input value={this.state.enforcer.description} onChange={e => {
|
||||
this.updateEnforcerField("description", e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("general:Model"), i18next.t("general:Model - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Select virtual={false} style={{width: "100%"}} value={this.state.enforcer.model} onChange={(model => {
|
||||
this.updateEnforcerField("model", model);
|
||||
})}
|
||||
options={this.state.models.map((model) => Setting.getOption(model.displayName, model.name))
|
||||
} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("general:Adapter"), i18next.t("general:Adapter - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Select virtual={false} style={{width: "100%"}} value={this.state.enforcer.adapter} onChange={(adapter => {
|
||||
this.updateEnforcerField("adapter", adapter);
|
||||
})}
|
||||
options={this.state.adapters.map((adapter) => Setting.getOption(adapter.name, adapter.name))
|
||||
} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 19 : 2}>
|
||||
{Setting.getLabel(i18next.t("general:Is enabled"), i18next.t("general:Is enabled - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={1} >
|
||||
<Switch checked={this.state.enforcer.isEnabled} onChange={checked => {
|
||||
this.updateEnforcerField("isEnabled", checked);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
|
||||
submitEnforcerEdit(willExist) {
|
||||
const enforcer = Setting.deepCopy(this.state.enforcer);
|
||||
EnforcerBackend.updateEnforcer(this.state.organizationName, this.state.enforcerName, enforcer)
|
||||
.then((res) => {
|
||||
if (res.status === "ok") {
|
||||
Setting.showMessage("success", i18next.t("general:Successfully saved"));
|
||||
this.setState({
|
||||
enforcerName: this.state.enforcer.name,
|
||||
});
|
||||
|
||||
if (willExist) {
|
||||
this.props.history.push("/enforcers");
|
||||
} else {
|
||||
this.props.history.push(`/enforcers/${this.state.enforcer.owner}/${this.state.enforcer.name}`);
|
||||
}
|
||||
} else {
|
||||
Setting.showMessage("error", `${i18next.t("general:Failed to save")}: ${res.msg}`);
|
||||
this.updateEnforcerField("name", this.state.enforcerName);
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
Setting.showMessage("error", `${i18next.t("general:Failed to connect to server")}: ${error}`);
|
||||
});
|
||||
}
|
||||
|
||||
deleteEnforcer() {
|
||||
EnforcerBackend.deleteEnforcer(this.state.enforcer)
|
||||
.then((res) => {
|
||||
if (res.status === "ok") {
|
||||
this.props.history.push("/enforcers");
|
||||
} else {
|
||||
Setting.showMessage("error", `${i18next.t("general:Failed to delete")}: ${res.msg}`);
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
Setting.showMessage("error", `${i18next.t("general:Failed to connect to server")}: ${error}`);
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
{
|
||||
this.state.enforcer !== null ? this.renderEnforcer() : null
|
||||
}
|
||||
<div style={{marginTop: "20px", marginLeft: "40px"}}>
|
||||
<Button size="large" onClick={() => this.submitEnforcerEdit(false)}>{i18next.t("general:Save")}</Button>
|
||||
<Button style={{marginLeft: "20px"}} type="primary" size="large" onClick={() => this.submitEnforcerEdit(true)}>{i18next.t("general:Save & Exit")}</Button>
|
||||
{this.state.mode === "add" ? <Button style={{marginLeft: "20px"}} size="large" onClick={() => this.deleteEnforcer()}>{i18next.t("general:Cancel")}</Button> : null}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default EnforcerEditPage;
|
218
web/src/EnforcerListPage.js
Normal file
218
web/src/EnforcerListPage.js
Normal file
@@ -0,0 +1,218 @@
|
||||
// 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.
|
||||
|
||||
import React from "react";
|
||||
import {Link} from "react-router-dom";
|
||||
import {Button, Switch, Table} from "antd";
|
||||
import moment from "moment";
|
||||
import * as Setting from "./Setting";
|
||||
import * as EnforcerBackend from "./backend/EnforcerBackend";
|
||||
import i18next from "i18next";
|
||||
import BaseListPage from "./BaseListPage";
|
||||
import PopconfirmModal from "./common/modal/PopconfirmModal";
|
||||
|
||||
class EnforcerListPage extends BaseListPage {
|
||||
newEnforcer() {
|
||||
const randomName = Setting.getRandomName();
|
||||
const owner = Setting.getRequestOrganization(this.props.account);
|
||||
return {
|
||||
owner: owner,
|
||||
name: `enforcer_${randomName}`,
|
||||
createdTime: moment().format(),
|
||||
displayName: `New Enforcer - ${randomName}`,
|
||||
isEnabled: true,
|
||||
};
|
||||
}
|
||||
|
||||
addEnforcer() {
|
||||
const newEnforcer = this.newEnforcer();
|
||||
EnforcerBackend.addEnforcer(newEnforcer)
|
||||
.then((res) => {
|
||||
if (res.status === "ok") {
|
||||
this.props.history.push({pathname: `/enforcers/${newEnforcer.owner}/${newEnforcer.name}`, mode: "add"});
|
||||
Setting.showMessage("success", i18next.t("general:Successfully added"));
|
||||
} else {
|
||||
Setting.showMessage("error", `${i18next.t("general:Failed to add")}: ${res.msg}`);
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
Setting.showMessage("error", `${i18next.t("general:Failed to connect to server")}: ${error}`);
|
||||
});
|
||||
}
|
||||
|
||||
deleteEnforcer(i) {
|
||||
EnforcerBackend.deleteEnforcer(this.state.data[i])
|
||||
.then((res) => {
|
||||
if (res.status === "ok") {
|
||||
Setting.showMessage("success", i18next.t("general:Successfully deleted"));
|
||||
this.setState({
|
||||
data: Setting.deleteRow(this.state.data, i),
|
||||
pagination: {total: this.state.pagination.total - 1},
|
||||
});
|
||||
} else {
|
||||
Setting.showMessage("error", `${i18next.t("general:Failed to delete")}: ${res.msg}`);
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
Setting.showMessage("error", `${i18next.t("general:Failed to connect to server")}: ${error}`);
|
||||
});
|
||||
}
|
||||
|
||||
renderTable(enforcers) {
|
||||
const columns = [
|
||||
{
|
||||
title: i18next.t("general:Name"),
|
||||
dataIndex: "name",
|
||||
key: "name",
|
||||
width: "150px",
|
||||
fixed: "left",
|
||||
sorter: true,
|
||||
...this.getColumnSearchProps("name"),
|
||||
render: (text, record, index) => {
|
||||
return (
|
||||
<Link to={`/enforcers/${record.owner}/${text}`}>
|
||||
{text}
|
||||
</Link>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: i18next.t("general:Organization"),
|
||||
dataIndex: "owner",
|
||||
key: "owner",
|
||||
width: "120px",
|
||||
sorter: true,
|
||||
...this.getColumnSearchProps("owner"),
|
||||
render: (text, record, index) => {
|
||||
return (
|
||||
<Link to={`/organizations/${text}`}>
|
||||
{text}
|
||||
</Link>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: i18next.t("general:Created time"),
|
||||
dataIndex: "createdTime",
|
||||
key: "createdTime",
|
||||
width: "160px",
|
||||
sorter: true,
|
||||
render: (text, record, index) => {
|
||||
return Setting.getFormattedDate(text);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: i18next.t("general:Display name"),
|
||||
dataIndex: "displayName",
|
||||
key: "displayName",
|
||||
width: "200px",
|
||||
sorter: true,
|
||||
...this.getColumnSearchProps("displayName"),
|
||||
},
|
||||
{
|
||||
title: i18next.t("general:Is enabled"),
|
||||
dataIndex: "isEnabled",
|
||||
key: "isEnabled",
|
||||
width: "120px",
|
||||
sorter: true,
|
||||
render: (text, record, index) => {
|
||||
return (
|
||||
<Switch disabled checkedChildren="ON" unCheckedChildren="OFF" checked={text} />
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: i18next.t("general:Action"),
|
||||
dataIndex: "",
|
||||
key: "op",
|
||||
width: "170px",
|
||||
fixed: (Setting.isMobile()) ? "false" : "right",
|
||||
render: (text, record, index) => {
|
||||
return (
|
||||
<div>
|
||||
<Button style={{marginTop: "10px", marginBottom: "10px", marginRight: "10px"}} type="primary"
|
||||
onClick={() => this.props.history.push(`/enforcers/${record.owner}/${record.name}`)}>{i18next.t("general:Edit")}</Button>
|
||||
<PopconfirmModal
|
||||
title={i18next.t("general:Sure to delete") + `: ${record.name} ?`}
|
||||
onConfirm={() => this.deleteEnforcer(index)}
|
||||
>
|
||||
</PopconfirmModal>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
const paginationProps = {
|
||||
total: this.state.pagination.total,
|
||||
showQuickJumper: true,
|
||||
showSizeChanger: true,
|
||||
showTotal: () => i18next.t("general:{total} in total").replace("{total}", this.state.pagination.total),
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Table scroll={{x: "max-content"}} columns={columns} dataSource={enforcers} rowKey={(record) => `${record.owner}/${record.name}`} size="middle" bordered
|
||||
pagination={paginationProps}
|
||||
title={() => (
|
||||
<div>
|
||||
{i18next.t("general:Enforcers")}
|
||||
<Button type="primary" size="small"
|
||||
onClick={this.addEnforcer.bind(this)}>{i18next.t("general:Add")}</Button>
|
||||
</div>
|
||||
)}
|
||||
loading={this.state.loading}
|
||||
onChange={this.handleTableChange}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
fetch = (params = {}) => {
|
||||
let field = params.searchedColumn, value = params.searchText;
|
||||
const sortField = params.sortField, sortOrder = params.sortOrder;
|
||||
if (params.type !== undefined && params.type !== null) {
|
||||
field = "type";
|
||||
value = params.type;
|
||||
}
|
||||
this.setState({loading: true});
|
||||
EnforcerBackend.getEnforcers(Setting.isDefaultOrganizationSelected(this.props.account) ? "" : Setting.getRequestOrganization(this.props.account), params.pagination.current, params.pagination.pageSize, field, value, sortField, sortOrder)
|
||||
.then((res) => {
|
||||
this.setState({
|
||||
loading: false,
|
||||
});
|
||||
if (res.status === "ok") {
|
||||
this.setState({
|
||||
data: res.data,
|
||||
pagination: {
|
||||
...params.pagination,
|
||||
total: res.data2,
|
||||
},
|
||||
searchText: params.searchText,
|
||||
searchedColumn: params.searchedColumn,
|
||||
});
|
||||
} else {
|
||||
if (Setting.isResponseDenied(res)) {
|
||||
this.setState({
|
||||
isAuthorized: false,
|
||||
});
|
||||
} else {
|
||||
Setting.showMessage("error", res.msg);
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
export default EnforcerListPage;
|
@@ -79,7 +79,9 @@ class EntryPage extends React.Component {
|
||||
Setting.showMessage("error", res.msg);
|
||||
return;
|
||||
}
|
||||
const themeData = res !== null ? Setting.getThemeData(res.organizationObj, res) : Conf.ThemeDefault;
|
||||
|
||||
const application = res.data;
|
||||
const themeData = application !== null ? Setting.getThemeData(application.organizationObj, application) : Conf.ThemeDefault;
|
||||
this.props.updataThemeData(themeData);
|
||||
});
|
||||
};
|
||||
|
@@ -67,7 +67,7 @@ class GroupEditPage extends React.Component {
|
||||
.then((res) => {
|
||||
if (res.status === "ok") {
|
||||
this.setState({
|
||||
organizations: res.data,
|
||||
organizations: res.data || [],
|
||||
});
|
||||
}
|
||||
});
|
||||
|
@@ -55,7 +55,7 @@ class LdapEditPage extends React.Component {
|
||||
OrganizationBackend.getOrganizations("admin")
|
||||
.then((res) => {
|
||||
this.setState({
|
||||
organizations: (res.msg === undefined) ? res : [],
|
||||
organizations: res.data || [],
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@@ -46,7 +46,7 @@ class MessageEditPage extends React.Component {
|
||||
getMessage() {
|
||||
MessageBackend.getMessage("admin", this.state.messageName)
|
||||
.then((res) => {
|
||||
if (res === null) {
|
||||
if (res.data === null) {
|
||||
this.props.history.push("/404");
|
||||
return;
|
||||
}
|
||||
@@ -54,11 +54,11 @@ class MessageEditPage extends React.Component {
|
||||
Setting.showMessage("error", res.msg);
|
||||
return;
|
||||
}
|
||||
this.setState({
|
||||
message: res,
|
||||
});
|
||||
|
||||
this.getUsers(res.organization);
|
||||
this.setState({
|
||||
message: res.data,
|
||||
});
|
||||
this.getUsers(res.data.organization);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -66,7 +66,7 @@ class MessageEditPage extends React.Component {
|
||||
OrganizationBackend.getOrganizations("admin")
|
||||
.then((res) => {
|
||||
this.setState({
|
||||
organizations: (res.msg === undefined) ? res : [],
|
||||
organizations: res.data || [],
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -75,7 +75,7 @@ class MessageEditPage extends React.Component {
|
||||
ChatBackend.getChats("admin")
|
||||
.then((res) => {
|
||||
this.setState({
|
||||
chats: (res.msg === undefined) ? res : [],
|
||||
chats: res.data || [],
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -87,8 +87,9 @@ class MessageEditPage extends React.Component {
|
||||
Setting.showMessage("error", res.msg);
|
||||
return;
|
||||
}
|
||||
|
||||
this.setState({
|
||||
users: res,
|
||||
users: res.data,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@@ -48,7 +48,7 @@ class ModelEditPage extends React.Component {
|
||||
getModel() {
|
||||
ModelBackend.getModel(this.state.organizationName, this.state.modelName)
|
||||
.then((res) => {
|
||||
if (res === null) {
|
||||
if (res.data === null) {
|
||||
this.props.history.push("/404");
|
||||
return;
|
||||
}
|
||||
@@ -59,7 +59,7 @@ class ModelEditPage extends React.Component {
|
||||
}
|
||||
|
||||
this.setState({
|
||||
model: res,
|
||||
model: res.data,
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -68,7 +68,7 @@ class ModelEditPage extends React.Component {
|
||||
OrganizationBackend.getOrganizations("admin")
|
||||
.then((res) => {
|
||||
this.setState({
|
||||
organizations: (res.msg === undefined) ? res : [],
|
||||
organizations: res.data || [],
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@@ -75,7 +75,7 @@ class OrganizationEditPage extends React.Component {
|
||||
}
|
||||
|
||||
this.setState({
|
||||
applications: res,
|
||||
applications: res.data || [],
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@@ -41,14 +41,14 @@ class PaymentEditPage extends React.Component {
|
||||
|
||||
getPayment() {
|
||||
PaymentBackend.getPayment("admin", this.state.paymentName)
|
||||
.then((payment) => {
|
||||
if (payment === null) {
|
||||
.then((res) => {
|
||||
if (res.data === null) {
|
||||
this.props.history.push("/404");
|
||||
return;
|
||||
}
|
||||
|
||||
this.setState({
|
||||
payment: payment,
|
||||
payment: res.data,
|
||||
});
|
||||
|
||||
Setting.scrollToDiv("invoice-area");
|
||||
|
@@ -41,12 +41,12 @@ class PaymentResultPage extends React.Component {
|
||||
|
||||
getPayment() {
|
||||
PaymentBackend.getPayment("admin", this.state.paymentName)
|
||||
.then((payment) => {
|
||||
.then((res) => {
|
||||
this.setState({
|
||||
payment: payment,
|
||||
payment: res.data,
|
||||
});
|
||||
|
||||
if (payment.state === "Created") {
|
||||
if (res.data.state === "Created") {
|
||||
this.setState({timeout: setTimeout(() => this.getPayment(), 1000)});
|
||||
}
|
||||
});
|
||||
|
@@ -30,7 +30,7 @@ class PermissionEditPage extends React.Component {
|
||||
this.state = {
|
||||
classes: props,
|
||||
organizationName: props.organizationName !== undefined ? props.organizationName : props.match.params.organizationName,
|
||||
permissionName: props.match.params.permissionName,
|
||||
permissionName: decodeURIComponent(props.match.params.permissionName),
|
||||
permission: null,
|
||||
organizations: [],
|
||||
model: null,
|
||||
@@ -50,7 +50,9 @@ class PermissionEditPage extends React.Component {
|
||||
getPermission() {
|
||||
PermissionBackend.getPermission(this.state.organizationName, this.state.permissionName)
|
||||
.then((res) => {
|
||||
if (res === null) {
|
||||
const permission = res.data;
|
||||
|
||||
if (permission === null) {
|
||||
this.props.history.push("/404");
|
||||
return;
|
||||
}
|
||||
@@ -61,14 +63,14 @@ class PermissionEditPage extends React.Component {
|
||||
}
|
||||
|
||||
this.setState({
|
||||
permission: res,
|
||||
permission: permission,
|
||||
});
|
||||
|
||||
this.getUsers(res.owner);
|
||||
this.getRoles(res.owner);
|
||||
this.getModels(res.owner);
|
||||
this.getResources(res.owner);
|
||||
this.getModel(res.owner, res.model);
|
||||
this.getUsers(permission.owner);
|
||||
this.getRoles(permission.owner);
|
||||
this.getModels(permission.owner);
|
||||
this.getResources(permission.owner);
|
||||
this.getModel(permission.owner, permission.model);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -76,7 +78,7 @@ class PermissionEditPage extends React.Component {
|
||||
OrganizationBackend.getOrganizations("admin")
|
||||
.then((res) => {
|
||||
this.setState({
|
||||
organizations: (res.msg === undefined) ? res : [],
|
||||
organizations: res.data || [],
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -88,8 +90,9 @@ class PermissionEditPage extends React.Component {
|
||||
Setting.showMessage("error", res.msg);
|
||||
return;
|
||||
}
|
||||
|
||||
this.setState({
|
||||
users: res,
|
||||
users: res.data,
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -101,8 +104,9 @@ class PermissionEditPage extends React.Component {
|
||||
Setting.showMessage("error", res.msg);
|
||||
return;
|
||||
}
|
||||
|
||||
this.setState({
|
||||
roles: res,
|
||||
roles: res.data,
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -114,21 +118,21 @@ class PermissionEditPage extends React.Component {
|
||||
Setting.showMessage("error", res.msg);
|
||||
return;
|
||||
}
|
||||
|
||||
this.setState({
|
||||
models: res,
|
||||
models: res.data,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
getModel(organizationName, modelName) {
|
||||
if (modelName === "") {
|
||||
return;
|
||||
}
|
||||
ModelBackend.getModel(organizationName, modelName)
|
||||
.then((res) => {
|
||||
if (res.status === "error") {
|
||||
Setting.showMessage("error", res.msg);
|
||||
return;
|
||||
}
|
||||
this.setState({
|
||||
model: res,
|
||||
model: res.data,
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -137,7 +141,7 @@ class PermissionEditPage extends React.Component {
|
||||
ApplicationBackend.getApplicationsByOrganization("admin", organizationName)
|
||||
.then((res) => {
|
||||
this.setState({
|
||||
resources: (res.msg === undefined) ? res : [],
|
||||
resources: res.data || [],
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -316,7 +320,7 @@ class PermissionEditPage extends React.Component {
|
||||
{Setting.getLabel(i18next.t("permission:Actions"), i18next.t("permission:Actions - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Select virtual={false} mode="multiple" style={{width: "100%"}} value={this.state.permission.actions} onChange={(value => {
|
||||
<Select virtual={false} mode={(this.state.permission.resourceType === "Custom") ? "tags" : "multiple"} style={{width: "100%"}} value={this.state.permission.actions} onChange={(value => {
|
||||
this.updatePermissionField("actions", value);
|
||||
})}
|
||||
options={[
|
||||
@@ -445,7 +449,7 @@ class PermissionEditPage extends React.Component {
|
||||
if (willExist) {
|
||||
this.props.history.push("/permissions");
|
||||
} else {
|
||||
this.props.history.push(`/permissions/${this.state.permission.owner}/${this.state.permission.name}`);
|
||||
this.props.history.push(`/permissions/${this.state.permission.owner}/${encodeURIComponent(this.state.permission.name)}`);
|
||||
}
|
||||
} else {
|
||||
Setting.showMessage("error", `${i18next.t("general:Failed to save")}: ${res.msg}`);
|
||||
|
@@ -128,7 +128,7 @@ class PermissionListPage extends BaseListPage {
|
||||
...this.getColumnSearchProps("name"),
|
||||
render: (text, record, index) => {
|
||||
return (
|
||||
<Link to={`/permissions/${record.owner}/${text}`}>
|
||||
<Link to={`/permissions/${record.owner}/${encodeURIComponent(text)}`}>
|
||||
{text}
|
||||
</Link>
|
||||
);
|
||||
@@ -336,7 +336,7 @@ class PermissionListPage extends BaseListPage {
|
||||
render: (text, record, index) => {
|
||||
return (
|
||||
<div>
|
||||
<Button style={{marginTop: "10px", marginBottom: "10px", marginRight: "10px"}} type="primary" onClick={() => this.props.history.push(`/permissions/${record.owner}/${record.name}`)}>{i18next.t("general:Edit")}</Button>
|
||||
<Button style={{marginTop: "10px", marginBottom: "10px", marginRight: "10px"}} type="primary" onClick={() => this.props.history.push(`/permissions/${record.owner}/${encodeURIComponent(record.name)}`)}>{i18next.t("general:Edit")}</Button>
|
||||
<PopconfirmModal
|
||||
title={i18next.t("general:Sure to delete") + `: ${record.name} ?`}
|
||||
onConfirm={() => this.deletePermission(index)}
|
||||
|
@@ -46,18 +46,18 @@ class PlanEditPage extends React.Component {
|
||||
|
||||
getPlan() {
|
||||
PlanBackend.getPlan(this.state.organizationName, this.state.planName)
|
||||
.then((plan) => {
|
||||
if (plan === null) {
|
||||
.then((res) => {
|
||||
if (res.data === null) {
|
||||
this.props.history.push("/404");
|
||||
return;
|
||||
}
|
||||
|
||||
this.setState({
|
||||
plan: plan,
|
||||
plan: res.data,
|
||||
});
|
||||
|
||||
this.getUsers(plan.owner);
|
||||
this.getRoles(plan.owner);
|
||||
this.getUsers(this.state.organizationName);
|
||||
this.getRoles(this.state.organizationName);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -68,8 +68,9 @@ class PlanEditPage extends React.Component {
|
||||
Setting.showMessage("error", res.msg);
|
||||
return;
|
||||
}
|
||||
|
||||
this.setState({
|
||||
roles: res,
|
||||
roles: res.data,
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -81,8 +82,9 @@ class PlanEditPage extends React.Component {
|
||||
Setting.showMessage("error", res.msg);
|
||||
return;
|
||||
}
|
||||
|
||||
this.setState({
|
||||
users: res,
|
||||
users: res.data,
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -91,7 +93,7 @@ class PlanEditPage extends React.Component {
|
||||
OrganizationBackend.getOrganizations("admin")
|
||||
.then((res) => {
|
||||
this.setState({
|
||||
organizations: (res.msg === undefined) ? res : [],
|
||||
organizations: res.data || [],
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@@ -148,7 +148,7 @@ class PlanListPage extends BaseListPage {
|
||||
...this.getColumnSearchProps("role"),
|
||||
render: (text, record, index) => {
|
||||
return (
|
||||
<Link to={`/roles/${text}`}>
|
||||
<Link to={`/roles/${encodeURIComponent(text)}`}>
|
||||
{text}
|
||||
</Link>
|
||||
);
|
||||
|
@@ -44,13 +44,12 @@ class PricingEditPage extends React.Component {
|
||||
this.getPricing();
|
||||
this.getOrganizations();
|
||||
this.getApplicationsByOrganization(this.state.organizationName);
|
||||
this.getUserApplication();
|
||||
}
|
||||
|
||||
getPricing() {
|
||||
PricingBackend.getPricing(this.state.organizationName, this.state.pricingName)
|
||||
.then((res) => {
|
||||
if (res === null) {
|
||||
if (res.data === null) {
|
||||
this.props.history.push("/404");
|
||||
return;
|
||||
}
|
||||
@@ -61,9 +60,9 @@ class PricingEditPage extends React.Component {
|
||||
}
|
||||
|
||||
this.setState({
|
||||
pricing: res,
|
||||
pricing: res.data,
|
||||
});
|
||||
this.getPlans(res.owner);
|
||||
this.getPlans(this.state.organizationName);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -74,8 +73,9 @@ class PricingEditPage extends React.Component {
|
||||
Setting.showMessage("error", res.msg);
|
||||
return;
|
||||
}
|
||||
|
||||
this.setState({
|
||||
plans: res,
|
||||
plans: res.data,
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -84,7 +84,16 @@ class PricingEditPage extends React.Component {
|
||||
OrganizationBackend.getOrganizations("admin")
|
||||
.then((res) => {
|
||||
this.setState({
|
||||
organizations: (res.msg === undefined) ? res : [],
|
||||
organizations: res.data || [],
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
getApplicationsByOrganization(organizationName) {
|
||||
ApplicationBackend.getApplicationsByOrganization("admin", organizationName)
|
||||
.then((res) => {
|
||||
this.setState({
|
||||
applications: res.data || [],
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -107,28 +116,6 @@ class PricingEditPage extends React.Component {
|
||||
});
|
||||
}
|
||||
|
||||
getApplicationsByOrganization(organizationName) {
|
||||
ApplicationBackend.getApplicationsByOrganization("admin", organizationName)
|
||||
.then((res) => {
|
||||
this.setState({
|
||||
applications: (res.msg === undefined) ? res : [],
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
getUserApplication() {
|
||||
ApplicationBackend.getUserApplication(this.state.organizationName, this.state.userName)
|
||||
.then((res) => {
|
||||
if (res.status === "error") {
|
||||
Setting.showMessage("error", res.msg);
|
||||
return;
|
||||
}
|
||||
this.setState({
|
||||
application: res,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
renderPricing() {
|
||||
return (
|
||||
<Card size="small" title={
|
||||
|
@@ -48,7 +48,7 @@ class ProductBuyPage extends React.Component {
|
||||
}
|
||||
|
||||
this.setState({
|
||||
product: res,
|
||||
product: res.data,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@@ -46,14 +46,14 @@ class ProductEditPage extends React.Component {
|
||||
|
||||
getProduct() {
|
||||
ProductBackend.getProduct(this.state.organizationName, this.state.productName)
|
||||
.then((product) => {
|
||||
if (product === null) {
|
||||
.then((res) => {
|
||||
if (res.data === null) {
|
||||
this.props.history.push("/404");
|
||||
return;
|
||||
}
|
||||
|
||||
this.setState({
|
||||
product: product,
|
||||
product: res.data,
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -62,7 +62,7 @@ class ProductEditPage extends React.Component {
|
||||
OrganizationBackend.getOrganizations("admin")
|
||||
.then((res) => {
|
||||
this.setState({
|
||||
organizations: (res.msg === undefined) ? res : [],
|
||||
organizations: res.data || [],
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@@ -50,7 +50,7 @@ class ProviderEditPage extends React.Component {
|
||||
getProvider() {
|
||||
ProviderBackend.getProvider(this.state.owner, this.state.providerName)
|
||||
.then((res) => {
|
||||
if (res === null) {
|
||||
if (res.data === null) {
|
||||
this.props.history.push("/404");
|
||||
return;
|
||||
}
|
||||
@@ -72,7 +72,7 @@ class ProviderEditPage extends React.Component {
|
||||
OrganizationBackend.getOrganizations("admin")
|
||||
.then((res) => {
|
||||
this.setState({
|
||||
organizations: res.msg === undefined ? res : [],
|
||||
organizations: res.data || [],
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -527,7 +527,7 @@ class ProviderEditPage extends React.Component {
|
||||
)
|
||||
}
|
||||
{
|
||||
(this.state.provider.category === "Captcha" && this.state.provider.type === "Default") || this.state.provider.category === "Web3" ? null : (
|
||||
(this.state.provider.category === "Captcha" && this.state.provider.type === "Default") || (this.state.provider.category === "Web3") || (this.state.provider.category === "Storage" && this.state.provider.type === "Local File System") ? null : (
|
||||
<React.Fragment>
|
||||
{
|
||||
this.state.provider.category === "AI" ? null : (
|
||||
@@ -616,36 +616,42 @@ class ProviderEditPage extends React.Component {
|
||||
}
|
||||
{this.state.provider.category === "Storage" ? (
|
||||
<div>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={2}>
|
||||
{Setting.getLabel(i18next.t("provider:Endpoint"), i18next.t("provider:Region endpoint for Internet"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Input value={this.state.provider.endpoint} onChange={e => {
|
||||
this.updateProviderField("endpoint", e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={2}>
|
||||
{Setting.getLabel(i18next.t("provider:Endpoint (Intranet)"), i18next.t("provider:Region endpoint for Intranet"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Input value={this.state.provider.intranetEndpoint} onChange={e => {
|
||||
this.updateProviderField("intranetEndpoint", e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={2}>
|
||||
{Setting.getLabel(i18next.t("provider:Bucket"), i18next.t("provider:Bucket - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Input value={this.state.provider.bucket} onChange={e => {
|
||||
this.updateProviderField("bucket", e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
{["Local File System"].includes(this.state.provider.type) ? null : (
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={2}>
|
||||
{Setting.getLabel(i18next.t("provider:Endpoint"), i18next.t("provider:Region endpoint for Internet"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Input value={this.state.provider.endpoint} onChange={e => {
|
||||
this.updateProviderField("endpoint", e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
)}
|
||||
{["Local File System", "MinIO", "Tencent Cloud COS"].includes(this.state.provider.type) ? null : (
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={2}>
|
||||
{Setting.getLabel(i18next.t("provider:Endpoint (Intranet)"), i18next.t("provider:Region endpoint for Intranet"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Input value={this.state.provider.intranetEndpoint} onChange={e => {
|
||||
this.updateProviderField("intranetEndpoint", e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
)}
|
||||
{["Local File System"].includes(this.state.provider.type) ? null : (
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={2}>
|
||||
{Setting.getLabel(i18next.t("provider:Bucket"), i18next.t("provider:Bucket - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Input value={this.state.provider.bucket} onChange={e => {
|
||||
this.updateProviderField("bucket", e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
)}
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={2}>
|
||||
{Setting.getLabel(i18next.t("provider:Path prefix"), i18next.t("provider:Path prefix - Tooltip"))} :
|
||||
@@ -656,17 +662,19 @@ class ProviderEditPage extends React.Component {
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={2}>
|
||||
{Setting.getLabel(i18next.t("provider:Domain"), i18next.t("provider:Domain - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Input value={this.state.provider.domain} onChange={e => {
|
||||
this.updateProviderField("domain", e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
{["AWS S3", "MinIO", "Tencent Cloud COS"].includes(this.state.provider.type) ? (
|
||||
{["MinIO"].includes(this.state.provider.type) ? null : (
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={2}>
|
||||
{Setting.getLabel(i18next.t("provider:Domain"), i18next.t("provider:Domain - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Input value={this.state.provider.domain} disabled={this.state.provider.type === "Local File System"} onChange={e => {
|
||||
this.updateProviderField("domain", e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
)}
|
||||
{["AWS S3", "Tencent Cloud COS"].includes(this.state.provider.type) ? (
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={2}>
|
||||
{Setting.getLabel(i18next.t("provider:Region ID"), i18next.t("provider:Region ID - Tooltip"))} :
|
||||
|
@@ -26,7 +26,7 @@ class RoleEditPage extends React.Component {
|
||||
this.state = {
|
||||
classes: props,
|
||||
organizationName: props.organizationName !== undefined ? props.organizationName : props.match.params.organizationName,
|
||||
roleName: props.match.params.roleName,
|
||||
roleName: decodeURIComponent(props.match.params.roleName),
|
||||
role: null,
|
||||
organizations: [],
|
||||
users: [],
|
||||
@@ -43,7 +43,7 @@ class RoleEditPage extends React.Component {
|
||||
getRole() {
|
||||
RoleBackend.getRole(this.state.organizationName, this.state.roleName)
|
||||
.then((res) => {
|
||||
if (res === null) {
|
||||
if (res.data === null) {
|
||||
this.props.history.push("/404");
|
||||
return;
|
||||
}
|
||||
@@ -53,11 +53,11 @@ class RoleEditPage extends React.Component {
|
||||
}
|
||||
|
||||
this.setState({
|
||||
role: res,
|
||||
role: res.data,
|
||||
});
|
||||
|
||||
this.getUsers(res.owner);
|
||||
this.getRoles(res.owner);
|
||||
this.getUsers(this.state.organizationName);
|
||||
this.getRoles(this.state.organizationName);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -65,7 +65,7 @@ class RoleEditPage extends React.Component {
|
||||
OrganizationBackend.getOrganizations("admin")
|
||||
.then((res) => {
|
||||
this.setState({
|
||||
organizations: (res.msg === undefined) ? res : [],
|
||||
organizations: res.data || [],
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -77,8 +77,9 @@ class RoleEditPage extends React.Component {
|
||||
Setting.showMessage("error", res.msg);
|
||||
return;
|
||||
}
|
||||
|
||||
this.setState({
|
||||
users: res,
|
||||
users: res.data,
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -90,8 +91,9 @@ class RoleEditPage extends React.Component {
|
||||
Setting.showMessage("error", res.msg);
|
||||
return;
|
||||
}
|
||||
|
||||
this.setState({
|
||||
roles: res,
|
||||
roles: res.data,
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -223,7 +225,7 @@ class RoleEditPage extends React.Component {
|
||||
if (willExist) {
|
||||
this.props.history.push("/roles");
|
||||
} else {
|
||||
this.props.history.push(`/roles/${this.state.role.owner}/${this.state.role.name}`);
|
||||
this.props.history.push(`/roles/${this.state.role.owner}/${encodeURIComponent(this.state.role.name)}`);
|
||||
}
|
||||
} else {
|
||||
Setting.showMessage("error", `${i18next.t("general:Failed to save")}: ${res.msg}`);
|
||||
|
@@ -121,7 +121,7 @@ class RoleListPage extends BaseListPage {
|
||||
...this.getColumnSearchProps("name"),
|
||||
render: (text, record, index) => {
|
||||
return (
|
||||
<Link to={`/roles/${record.owner}/${record.name}`}>
|
||||
<Link to={`/roles/${record.owner}/${encodeURIComponent(record.name)}`}>
|
||||
{text}
|
||||
</Link>
|
||||
);
|
||||
@@ -213,7 +213,7 @@ class RoleListPage extends BaseListPage {
|
||||
render: (text, record, index) => {
|
||||
return (
|
||||
<div>
|
||||
<Button style={{marginTop: "10px", marginBottom: "10px", marginRight: "10px"}} type="primary" onClick={() => this.props.history.push(`/roles/${record.owner}/${record.name}`)}>{i18next.t("general:Edit")}</Button>
|
||||
<Button style={{marginTop: "10px", marginBottom: "10px", marginRight: "10px"}} type="primary" onClick={() => this.props.history.push(`/roles/${record.owner}/${encodeURIComponent(record.name)}`)}>{i18next.t("general:Edit")}</Button>
|
||||
<PopconfirmModal
|
||||
title={i18next.t("general:Sure to delete") + `: ${record.name} ?`}
|
||||
onConfirm={() => this.deleteRole(index)}
|
||||
|
@@ -47,7 +47,7 @@ class SubscriptionEditPage extends React.Component {
|
||||
getSubscription() {
|
||||
SubscriptionBackend.getSubscription(this.state.organizationName, this.state.subscriptionName)
|
||||
.then((res) => {
|
||||
if (res === null) {
|
||||
if (res.data === null) {
|
||||
this.props.history.push("/404");
|
||||
return;
|
||||
}
|
||||
@@ -58,11 +58,11 @@ class SubscriptionEditPage extends React.Component {
|
||||
}
|
||||
|
||||
this.setState({
|
||||
subscription: res,
|
||||
subscription: res.data,
|
||||
});
|
||||
|
||||
this.getUsers(res.owner);
|
||||
this.getPlanes(res.owner);
|
||||
this.getUsers(this.state.organizationName);
|
||||
this.getPlanes(this.state.organizationName);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -70,7 +70,7 @@ class SubscriptionEditPage extends React.Component {
|
||||
PlanBackend.getPlans(organizationName)
|
||||
.then((res) => {
|
||||
this.setState({
|
||||
planes: res,
|
||||
planes: res.data,
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -82,8 +82,9 @@ class SubscriptionEditPage extends React.Component {
|
||||
Setting.showMessage("error", res.msg);
|
||||
return;
|
||||
}
|
||||
|
||||
this.setState({
|
||||
users: res,
|
||||
users: res.data,
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -92,7 +93,7 @@ class SubscriptionEditPage extends React.Component {
|
||||
OrganizationBackend.getOrganizations("admin")
|
||||
.then((res) => {
|
||||
this.setState({
|
||||
organizations: (res.msg === undefined) ? res : [],
|
||||
organizations: res.data || [],
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@@ -48,7 +48,7 @@ class SyncerEditPage extends React.Component {
|
||||
getSyncer() {
|
||||
SyncerBackend.getSyncer("admin", this.state.syncerName)
|
||||
.then((res) => {
|
||||
if (res === null) {
|
||||
if (res.data === null) {
|
||||
this.props.history.push("/404");
|
||||
return;
|
||||
}
|
||||
@@ -59,7 +59,7 @@ class SyncerEditPage extends React.Component {
|
||||
}
|
||||
|
||||
this.setState({
|
||||
syncer: res,
|
||||
syncer: res.data,
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -68,7 +68,7 @@ class SyncerEditPage extends React.Component {
|
||||
OrganizationBackend.getOrganizations("admin")
|
||||
.then((res) => {
|
||||
this.setState({
|
||||
organizations: (res.msg === undefined) ? res : [],
|
||||
organizations: res.data || [],
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@@ -36,7 +36,7 @@ class TokenEditPage extends React.Component {
|
||||
getToken() {
|
||||
TokenBackend.getToken("admin", this.state.tokenName)
|
||||
.then((res) => {
|
||||
if (res === null) {
|
||||
if (res.data === null) {
|
||||
this.props.history.push("/404");
|
||||
return;
|
||||
}
|
||||
@@ -47,7 +47,7 @@ class TokenEditPage extends React.Component {
|
||||
}
|
||||
|
||||
this.setState({
|
||||
token: res,
|
||||
token: res.data,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@@ -75,19 +75,20 @@ class UserEditPage extends React.Component {
|
||||
|
||||
getUser() {
|
||||
UserBackend.getUser(this.state.organizationName, this.state.userName)
|
||||
.then((data) => {
|
||||
if (data === null) {
|
||||
.then((res) => {
|
||||
if (res.data === null) {
|
||||
this.props.history.push("/404");
|
||||
return;
|
||||
}
|
||||
|
||||
if (data.status === null || data.status !== "error") {
|
||||
this.setState({
|
||||
user: data,
|
||||
multiFactorAuths: data?.multiFactorAuths ?? [],
|
||||
});
|
||||
if (res.status === "error") {
|
||||
Setting.showMessage("error", res.msg);
|
||||
return;
|
||||
}
|
||||
|
||||
this.setState({
|
||||
user: res.data,
|
||||
multiFactorAuths: res.data?.multiFactorAuths ?? [],
|
||||
loading: false,
|
||||
});
|
||||
});
|
||||
@@ -108,7 +109,7 @@ class UserEditPage extends React.Component {
|
||||
OrganizationBackend.getOrganizations("admin")
|
||||
.then((res) => {
|
||||
this.setState({
|
||||
organizations: (res.msg === undefined) ? res : [],
|
||||
organizations: res.data || [],
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -117,7 +118,7 @@ class UserEditPage extends React.Component {
|
||||
ApplicationBackend.getApplicationsByOrganization("admin", organizationName)
|
||||
.then((res) => {
|
||||
this.setState({
|
||||
applications: (res.msg === undefined) ? res : [],
|
||||
applications: res.data || [],
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -129,12 +130,10 @@ class UserEditPage extends React.Component {
|
||||
Setting.showMessage("error", res.msg);
|
||||
return;
|
||||
}
|
||||
this.setState({
|
||||
application: res,
|
||||
});
|
||||
|
||||
this.setState({
|
||||
isGroupsVisible: res.organizationObj.accountItems?.some((item) => item.name === "Groups" && item.visible),
|
||||
application: res.data,
|
||||
isGroupsVisible: res.data?.organizationObj.accountItems?.some((item) => item.name === "Groups" && item.visible),
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@@ -122,14 +122,14 @@ class WebhookEditPage extends React.Component {
|
||||
|
||||
getWebhook() {
|
||||
WebhookBackend.getWebhook("admin", this.state.webhookName)
|
||||
.then((webhook) => {
|
||||
if (webhook === null) {
|
||||
.then((res) => {
|
||||
if (res.data === null) {
|
||||
this.props.history.push("/404");
|
||||
return;
|
||||
}
|
||||
|
||||
this.setState({
|
||||
webhook: webhook,
|
||||
webhook: res.data,
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -138,7 +138,7 @@ class WebhookEditPage extends React.Component {
|
||||
OrganizationBackend.getOrganizations("admin")
|
||||
.then((res) => {
|
||||
this.setState({
|
||||
organizations: (res.msg === undefined) ? res : [],
|
||||
organizations: res.data || [],
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@@ -68,7 +68,7 @@ class ForgetPage extends React.Component {
|
||||
Setting.showMessage("error", res.msg);
|
||||
return;
|
||||
}
|
||||
this.onUpdateApplication(res);
|
||||
this.onUpdateApplication(res.data);
|
||||
});
|
||||
}
|
||||
getApplicationObj() {
|
||||
|
@@ -14,6 +14,9 @@
|
||||
|
||||
import {createButton} from "react-social-login-buttons";
|
||||
import {StaticBaseUrl} from "../Setting";
|
||||
import {useGoogleOneTapLogin} from "react-google-one-tap-login";
|
||||
import * as Setting from "../Setting";
|
||||
import * as Provider from "./Provider";
|
||||
|
||||
function Icon({width = 24, height = 24, color}) {
|
||||
return <img src={`${StaticBaseUrl}/buttons/google.svg`} alt="Sign in with Google" />;
|
||||
@@ -29,4 +32,29 @@ const config = {
|
||||
|
||||
const GoogleLoginButton = createButton(config);
|
||||
|
||||
export function GoogleOneTapLoginVirtualButton(prop) {
|
||||
const application = prop.application;
|
||||
const providerConf = prop.providerConf;
|
||||
// https://stackoverflow.com/questions/62281579/google-one-tap-sign-in-ui-not-displayed-after-clicking-the-close-button
|
||||
// document.cookie = "g_state=;path=/;expires=Thu, 01 Jan 1970 00:00:01 GMT";
|
||||
useGoogleOneTapLogin({
|
||||
googleAccountConfigs: {
|
||||
client_id: providerConf.provider.clientId,
|
||||
},
|
||||
onError: (error) => {
|
||||
Setting.showMessage("error", error);
|
||||
},
|
||||
onSuccess: (response) => {
|
||||
const code = "GoogleIdToken-" + JSON.stringify(response);
|
||||
const authUrlParams = new URLSearchParams(Provider.getAuthUrl(application, providerConf.provider, "signup"));
|
||||
const state = authUrlParams.get("state");
|
||||
let redirectUri = authUrlParams.get("redirect_uri");
|
||||
redirectUri = `${redirectUri}?state=${state}&code=${encodeURIComponent(code)}`;
|
||||
Setting.goToLink(redirectUri);
|
||||
},
|
||||
disableCancelOnUnmount: true,
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
export default GoogleLoginButton;
|
||||
|
@@ -36,7 +36,7 @@ import {CaptchaModal} from "../common/modal/CaptchaModal";
|
||||
import {CaptchaRule} from "../common/modal/CaptchaModal";
|
||||
import RedirectForm from "../common/RedirectForm";
|
||||
import {MfaAuthVerifyForm, NextMfa, RequiredMfa} from "./mfa/MfaAuthVerifyForm";
|
||||
|
||||
import {GoogleOneTapLoginVirtualButton} from "./GoogleLoginButton";
|
||||
class LoginPage extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
@@ -170,10 +170,15 @@ class LoginPage extends React.Component {
|
||||
Setting.showMessage("error", res.msg);
|
||||
return;
|
||||
}
|
||||
this.onUpdateApplication(res);
|
||||
this.onUpdateApplication(res.data);
|
||||
});
|
||||
} else {
|
||||
OrganizationBackend.getDefaultApplication("admin", this.state.owner)
|
||||
let redirectUri = "";
|
||||
if (this.state.type === "cas") {
|
||||
const casParams = Util.getCasParameters();
|
||||
redirectUri = casParams.service;
|
||||
}
|
||||
OrganizationBackend.getDefaultApplication("admin", this.state.owner, this.state.type, redirectUri)
|
||||
.then((res) => {
|
||||
if (res.status === "ok") {
|
||||
const application = res.data;
|
||||
@@ -183,9 +188,9 @@ class LoginPage extends React.Component {
|
||||
});
|
||||
} else {
|
||||
this.onUpdateApplication(null);
|
||||
Setting.showMessage("error", res.msg);
|
||||
|
||||
this.props.history.push("/404");
|
||||
this.setState({
|
||||
msg: res.msg,
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -418,6 +423,16 @@ class LoginPage extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
renderOtherFormProvider(application) {
|
||||
for (const providerConf of application.providers) {
|
||||
if (providerConf.provider?.type === "Google" && providerConf.rule === "OneTap" && this.props.preview !== "auto") {
|
||||
return (
|
||||
<GoogleOneTapLoginVirtualButton application={application} providerConf={providerConf} />
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
renderForm(application) {
|
||||
if (this.state.msg !== null) {
|
||||
return Util.renderMessage(this.state.msg);
|
||||
@@ -575,6 +590,9 @@ class LoginPage extends React.Component {
|
||||
return ProviderButton.renderProviderLogo(providerItem.provider, application, 30, 5, "small", this.props.location);
|
||||
})
|
||||
}
|
||||
{
|
||||
this.renderOtherFormProvider(application)
|
||||
}
|
||||
</Form.Item>
|
||||
</Form>
|
||||
);
|
||||
@@ -596,6 +614,9 @@ class LoginPage extends React.Component {
|
||||
return ProviderButton.renderProviderLogo(providerItem.provider, application, 40, 10, "big", this.props.location);
|
||||
})
|
||||
}
|
||||
{
|
||||
this.renderOtherFormProvider(application)
|
||||
}
|
||||
<div>
|
||||
<br />
|
||||
{
|
||||
|
@@ -69,7 +69,7 @@ class MfaSetupPage extends React.Component {
|
||||
return;
|
||||
}
|
||||
this.setState({
|
||||
application: res,
|
||||
application: res.data,
|
||||
});
|
||||
} else {
|
||||
Setting.showMessage("error", i18next.t("mfa:Failed to get application"));
|
||||
|
@@ -63,7 +63,7 @@ class PromptPage extends React.Component {
|
||||
}
|
||||
|
||||
this.setState({
|
||||
user: res,
|
||||
user: res.data,
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -80,9 +80,9 @@ class PromptPage extends React.Component {
|
||||
return;
|
||||
}
|
||||
|
||||
this.onUpdateApplication(res);
|
||||
this.onUpdateApplication(res.data);
|
||||
this.setState({
|
||||
application: res,
|
||||
application: res.data,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@@ -48,9 +48,10 @@ class ResultPage extends React.Component {
|
||||
Setting.showMessage("error", res.msg);
|
||||
return;
|
||||
}
|
||||
this.onUpdateApplication(res);
|
||||
|
||||
this.onUpdateApplication(res.data);
|
||||
this.setState({
|
||||
application: res,
|
||||
application: res.data,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@@ -114,7 +114,7 @@ class SignupPage extends React.Component {
|
||||
return;
|
||||
}
|
||||
|
||||
this.onUpdateApplication(res);
|
||||
this.onUpdateApplication(res.data);
|
||||
});
|
||||
}
|
||||
|
||||
|
71
web/src/backend/EnforcerBackend.js
Normal file
71
web/src/backend/EnforcerBackend.js
Normal file
@@ -0,0 +1,71 @@
|
||||
// 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.
|
||||
|
||||
import * as Setting from "../Setting";
|
||||
|
||||
export function getEnforcers(owner, page = "", pageSize = "", field = "", value = "", sortField = "", sortOrder = "") {
|
||||
return fetch(`${Setting.ServerUrl}/api/get-enforcers?owner=${owner}&p=${page}&pageSize=${pageSize}&field=${field}&value=${value}&sortField=${sortField}&sortOrder=${sortOrder}`, {
|
||||
method: "GET",
|
||||
credentials: "include",
|
||||
headers: {
|
||||
"Accept-Language": Setting.getAcceptLanguage(),
|
||||
},
|
||||
}).then(res => res.json());
|
||||
}
|
||||
|
||||
export function getEnforcer(owner, name) {
|
||||
return fetch(`${Setting.ServerUrl}/api/get-enforcer?id=${owner}/${encodeURIComponent(name)}`, {
|
||||
method: "GET",
|
||||
credentials: "include",
|
||||
headers: {
|
||||
"Accept-Language": Setting.getAcceptLanguage(),
|
||||
},
|
||||
}).then(res => res.json());
|
||||
}
|
||||
|
||||
export function updateEnforcer(owner, name, enforcer) {
|
||||
const newEnforcer = Setting.deepCopy(enforcer);
|
||||
return fetch(`${Setting.ServerUrl}/api/update-enforcer?id=${owner}/${encodeURIComponent(name)}`, {
|
||||
method: "POST",
|
||||
credentials: "include",
|
||||
body: JSON.stringify(newEnforcer),
|
||||
headers: {
|
||||
"Accept-Language": Setting.getAcceptLanguage(),
|
||||
},
|
||||
}).then(res => res.json());
|
||||
}
|
||||
|
||||
export function addEnforcer(enforcer) {
|
||||
const newEnforcer = Setting.deepCopy(enforcer);
|
||||
return fetch(`${Setting.ServerUrl}/api/add-enforcer`, {
|
||||
method: "POST",
|
||||
credentials: "include",
|
||||
body: JSON.stringify(newEnforcer),
|
||||
headers: {
|
||||
"Accept-Language": Setting.getAcceptLanguage(),
|
||||
},
|
||||
}).then(res => res.json());
|
||||
}
|
||||
|
||||
export function deleteEnforcer(enforcer) {
|
||||
const newEnforcer = Setting.deepCopy(enforcer);
|
||||
return fetch(`${Setting.ServerUrl}/api/delete-enforcer`, {
|
||||
method: "POST",
|
||||
credentials: "include",
|
||||
body: JSON.stringify(newEnforcer),
|
||||
headers: {
|
||||
"Accept-Language": Setting.getAcceptLanguage(),
|
||||
},
|
||||
}).then(res => res.json());
|
||||
}
|
@@ -70,8 +70,8 @@ export function deleteOrganization(organization) {
|
||||
}).then(res => res.json());
|
||||
}
|
||||
|
||||
export function getDefaultApplication(owner, name) {
|
||||
return fetch(`${Setting.ServerUrl}/api/get-default-application?id=${owner}/${encodeURIComponent(name)}`, {
|
||||
export function getDefaultApplication(owner, name, type = "", redirectUri = "") {
|
||||
return fetch(`${Setting.ServerUrl}/api/get-default-application?id=${owner}/${encodeURIComponent(name)}&type=${type}&redirectUri=${redirectUri}`, {
|
||||
method: "GET",
|
||||
credentials: "include",
|
||||
headers: {
|
||||
|
@@ -36,7 +36,7 @@ class HomePage extends React.Component {
|
||||
ApplicationBackend.getApplicationsByOrganization("admin", organizationName)
|
||||
.then((res) => {
|
||||
this.setState({
|
||||
applications: (res.msg === undefined) ? res : [],
|
||||
applications: res.data || [],
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@@ -15,6 +15,7 @@
|
||||
import {Checkbox, Form, Modal} from "antd";
|
||||
import i18next from "i18next";
|
||||
import React, {useEffect, useState} from "react";
|
||||
import * as Setting from "../../Setting";
|
||||
|
||||
export const AgreementModal = (props) => {
|
||||
const {open, onOk, onCancel, application} = props;
|
||||
@@ -31,14 +32,16 @@ export const AgreementModal = (props) => {
|
||||
<Modal
|
||||
title={i18next.t("signup:Terms of Use")}
|
||||
open={open}
|
||||
width={"55vw"}
|
||||
width={Setting.isMobile() ? "100vw" : "55vw"}
|
||||
closable={false}
|
||||
okText={i18next.t("signup:Accept")}
|
||||
cancelText={i18next.t("signup:Decline")}
|
||||
onOk={onOk}
|
||||
onCancel={onCancel}
|
||||
style={{top: Setting.isMobile() ? "5px" : ""}}
|
||||
maskStyle={{backgroundColor: Setting.isMobile() ? "white" : ""}}
|
||||
>
|
||||
<iframe title={"terms"} style={{border: 0, width: "100%", height: "60vh"}} srcDoc={doc} />
|
||||
<iframe title={"terms"} style={{border: 0, width: "100%", height: Setting.isMobile() ? "80vh" : "60vh"}} srcDoc={doc} />
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
@@ -197,6 +197,7 @@
|
||||
"Confirm": "Confirm",
|
||||
"Created time": "Erstellte Zeit",
|
||||
"Custom": "Custom",
|
||||
"Default": "Default",
|
||||
"Default application": "Standard Anwendung",
|
||||
"Default application - Tooltip": "Standard-Anwendung für Benutzer, die direkt von der Organisationsseite registriert wurden",
|
||||
"Default avatar": "Standard-Avatar",
|
||||
@@ -722,6 +723,8 @@
|
||||
"Secret key - Tooltip": "Vom Server verwendet, um die API des Verifizierungscodes-Providers für die Verifizierung aufzurufen",
|
||||
"Send Testing Email": "Senden Sie eine Test-E-Mail",
|
||||
"Send Testing SMS": "Sende Test-SMS",
|
||||
"Sender number": "Sender number",
|
||||
"Sender number - Tooltip": "Sender number - Tooltip",
|
||||
"Sign Name": "Signatur Namen",
|
||||
"Sign Name - Tooltip": "Name der Signatur, die verwendet werden soll",
|
||||
"Sign request": "Signaturanfrage",
|
||||
|
@@ -197,6 +197,7 @@
|
||||
"Confirm": "Confirm",
|
||||
"Created time": "Created time",
|
||||
"Custom": "Custom",
|
||||
"Default": "Default",
|
||||
"Default application": "Default application",
|
||||
"Default application - Tooltip": "Default application for users registered directly from the organization page",
|
||||
"Default avatar": "Default avatar",
|
||||
@@ -722,6 +723,8 @@
|
||||
"Secret key - Tooltip": "Used by the server to call the verification code provider API for verification",
|
||||
"Send Testing Email": "Send Testing Email",
|
||||
"Send Testing SMS": "Send Testing SMS",
|
||||
"Sender number": "Sender number",
|
||||
"Sender number - Tooltip": "Sender number - Tooltip",
|
||||
"Sign Name": "Sign Name",
|
||||
"Sign Name - Tooltip": "Name of the signature to be used",
|
||||
"Sign request": "Sign request",
|
||||
|
@@ -197,6 +197,7 @@
|
||||
"Confirm": "Confirm",
|
||||
"Created time": "Tiempo creado",
|
||||
"Custom": "Custom",
|
||||
"Default": "Default",
|
||||
"Default application": "Aplicación predeterminada",
|
||||
"Default application - Tooltip": "Aplicación predeterminada para usuarios registrados directamente desde la página de la organización",
|
||||
"Default avatar": "Avatar predeterminado",
|
||||
@@ -722,6 +723,8 @@
|
||||
"Secret key - Tooltip": "Utilizado por el servidor para llamar a la API del proveedor de códigos de verificación para verificar",
|
||||
"Send Testing Email": "Enviar correo electrónico de prueba",
|
||||
"Send Testing SMS": "Enviar SMS de prueba",
|
||||
"Sender number": "Sender number",
|
||||
"Sender number - Tooltip": "Sender number - Tooltip",
|
||||
"Sign Name": "Firma de Nombre",
|
||||
"Sign Name - Tooltip": "Nombre de la firma a ser utilizada",
|
||||
"Sign request": "Solicitud de firma",
|
||||
|
@@ -197,6 +197,7 @@
|
||||
"Confirm": "Confirm",
|
||||
"Created time": "Temps créé",
|
||||
"Custom": "Custom",
|
||||
"Default": "Default",
|
||||
"Default application": "Application par défaut",
|
||||
"Default application - Tooltip": "Application par défaut pour les utilisateurs enregistrés directement depuis la page de l'organisation",
|
||||
"Default avatar": "Avatar par défaut",
|
||||
@@ -722,6 +723,8 @@
|
||||
"Secret key - Tooltip": "Utilisé par le serveur pour appeler l'API du fournisseur de code de vérification pour vérifier",
|
||||
"Send Testing Email": "Envoyer un e-mail de test",
|
||||
"Send Testing SMS": "Envoyer des messages SMS de tests",
|
||||
"Sender number": "Sender number",
|
||||
"Sender number - Tooltip": "Sender number - Tooltip",
|
||||
"Sign Name": "Nom de signature",
|
||||
"Sign Name - Tooltip": "Nom de la signature à utiliser",
|
||||
"Sign request": "Demande de signature",
|
||||
|
@@ -197,6 +197,7 @@
|
||||
"Confirm": "Confirm",
|
||||
"Created time": "Waktu dibuat",
|
||||
"Custom": "Custom",
|
||||
"Default": "Default",
|
||||
"Default application": "Aplikasi default",
|
||||
"Default application - Tooltip": "Aplikasi default untuk pengguna yang terdaftar langsung dari halaman organisasi",
|
||||
"Default avatar": "Avatar default",
|
||||
@@ -722,6 +723,8 @@
|
||||
"Secret key - Tooltip": "Digunakan oleh server untuk memanggil API penyedia kode verifikasi untuk melakukan verifikasi",
|
||||
"Send Testing Email": "Kirim Email Uji Coba",
|
||||
"Send Testing SMS": "Kirim SMS Uji Coba",
|
||||
"Sender number": "Sender number",
|
||||
"Sender number - Tooltip": "Sender number - Tooltip",
|
||||
"Sign Name": "Tanda Tangan",
|
||||
"Sign Name - Tooltip": "Nama tanda tangan yang akan digunakan",
|
||||
"Sign request": "Permintaan tanda tangan",
|
||||
|
@@ -197,6 +197,7 @@
|
||||
"Confirm": "Confirm",
|
||||
"Created time": "作成された時間",
|
||||
"Custom": "Custom",
|
||||
"Default": "Default",
|
||||
"Default application": "デフォルトアプリケーション",
|
||||
"Default application - Tooltip": "組織ページから直接登録されたユーザーのデフォルトアプリケーション",
|
||||
"Default avatar": "デフォルトのアバター",
|
||||
@@ -722,6 +723,8 @@
|
||||
"Secret key - Tooltip": "認証のためにサーバーによって使用され、認証コードプロバイダAPIを呼び出すためのもの",
|
||||
"Send Testing Email": "テスト用メールを送信する",
|
||||
"Send Testing SMS": "テストSMSを送信してください",
|
||||
"Sender number": "Sender number",
|
||||
"Sender number - Tooltip": "Sender number - Tooltip",
|
||||
"Sign Name": "署名",
|
||||
"Sign Name - Tooltip": "使用する署名の名前",
|
||||
"Sign request": "サインリクエスト",
|
||||
|
@@ -197,6 +197,7 @@
|
||||
"Confirm": "Confirm",
|
||||
"Created time": "작성한 시간",
|
||||
"Custom": "Custom",
|
||||
"Default": "Default",
|
||||
"Default application": "기본 애플리케이션",
|
||||
"Default application - Tooltip": "조직 페이지에서 직접 등록한 사용자의 기본 응용 프로그램",
|
||||
"Default avatar": "기본 아바타",
|
||||
@@ -722,6 +723,8 @@
|
||||
"Secret key - Tooltip": "검증을 위해 서버에서 인증 코드 공급자 API를 호출하는 데 사용됩니다",
|
||||
"Send Testing Email": "테스트 이메일을 보내기",
|
||||
"Send Testing SMS": "테스트 SMS를 보내세요",
|
||||
"Sender number": "Sender number",
|
||||
"Sender number - Tooltip": "Sender number - Tooltip",
|
||||
"Sign Name": "신명서",
|
||||
"Sign Name - Tooltip": "사용할 서명의 이름",
|
||||
"Sign request": "표지 요청",
|
||||
|
@@ -197,6 +197,7 @@
|
||||
"Confirm": "Confirm",
|
||||
"Created time": "Hora de Criação",
|
||||
"Custom": "Custom",
|
||||
"Default": "Default",
|
||||
"Default application": "Aplicação padrão",
|
||||
"Default application - Tooltip": "Aplicação padrão para usuários registrados diretamente na página da organização",
|
||||
"Default avatar": "Avatar padrão",
|
||||
@@ -722,6 +723,8 @@
|
||||
"Secret key - Tooltip": "Usada pelo servidor para chamar a API do fornecedor de código de verificação para verificação",
|
||||
"Send Testing Email": "Enviar E-mail de Teste",
|
||||
"Send Testing SMS": "Enviar SMS de Teste",
|
||||
"Sender number": "Sender number",
|
||||
"Sender number - Tooltip": "Sender number - Tooltip",
|
||||
"Sign Name": "Nome do Sinal",
|
||||
"Sign Name - Tooltip": "Nome da assinatura a ser usada",
|
||||
"Sign request": "Solicitação de assinatura",
|
||||
|
@@ -197,6 +197,7 @@
|
||||
"Confirm": "Confirm",
|
||||
"Created time": "Созданное время",
|
||||
"Custom": "Custom",
|
||||
"Default": "Default",
|
||||
"Default application": "Приложение по умолчанию",
|
||||
"Default application - Tooltip": "По умолчанию приложение для пользователей, зарегистрированных непосредственно со страницы организации",
|
||||
"Default avatar": "Стандартный аватар",
|
||||
@@ -722,6 +723,8 @@
|
||||
"Secret key - Tooltip": "Используется сервером для вызова API-интерфейса поставщика кода подтверждения для проверки",
|
||||
"Send Testing Email": "Отправить тестовое письмо",
|
||||
"Send Testing SMS": "Отправить тестовое SMS-сообщение",
|
||||
"Sender number": "Sender number",
|
||||
"Sender number - Tooltip": "Sender number - Tooltip",
|
||||
"Sign Name": "Подпись имени",
|
||||
"Sign Name - Tooltip": "Имя подписи, которую нужно использовать",
|
||||
"Sign request": "Подписать запрос",
|
||||
|
@@ -197,6 +197,7 @@
|
||||
"Confirm": "Confirm",
|
||||
"Created time": "Thời gian tạo",
|
||||
"Custom": "Custom",
|
||||
"Default": "Default",
|
||||
"Default application": "Ứng dụng mặc định",
|
||||
"Default application - Tooltip": "Ứng dụng mặc định cho người dùng đăng ký trực tiếp từ trang tổ chức",
|
||||
"Default avatar": "Hình đại diện mặc định",
|
||||
@@ -722,6 +723,8 @@
|
||||
"Secret key - Tooltip": "Được sử dụng bởi máy chủ để gọi API nhà cung cấp mã xác minh để xác minh",
|
||||
"Send Testing Email": "Gửi Email kiểm tra",
|
||||
"Send Testing SMS": "Gửi SMS kiểm tra",
|
||||
"Sender number": "Sender number",
|
||||
"Sender number - Tooltip": "Sender number - Tooltip",
|
||||
"Sign Name": "Ký tên",
|
||||
"Sign Name - Tooltip": "Tên chữ ký sẽ được sử dụng",
|
||||
"Sign request": "Yêu cầu ký tên",
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user