Add authorization checks and filtering in collection and document listing
- Integrated authorization information retrieval in `ListCollections` and `ListDocuments` functions to enhance security. - Implemented permission-based filtering to ensure users can only access collections and documents they are authorized to view. - Refactored query parameter construction for improved readability and maintainability.
This commit is contained in:
parent
0eff0091a0
commit
6b38b76558
4 changed files with 89 additions and 3 deletions
|
|
@ -309,6 +309,10 @@ func GetCollection(c *gin.Context) {
|
|||
|
||||
// ListCollections lists collections with pagination
|
||||
func ListCollections(c *gin.Context) {
|
||||
|
||||
// Get authorized information
|
||||
authInfo := authorized.GetInfo(c)
|
||||
|
||||
// Check if kb.Instance is available
|
||||
if kb.Instance == nil {
|
||||
errorResp := &response.ErrorResponse{
|
||||
|
|
@ -364,13 +368,14 @@ func ListCollections(c *gin.Context) {
|
|||
}
|
||||
|
||||
// Build query parameters
|
||||
param := model.QueryParam{
|
||||
Select: selectFields,
|
||||
}
|
||||
param := model.QueryParam{Select: selectFields}
|
||||
|
||||
// Add filters
|
||||
var wheres []model.QueryWhere
|
||||
|
||||
// Apply permission-based filtering
|
||||
wheres = append(wheres, AuthFilter(c, authInfo)...)
|
||||
|
||||
// Filter by keywords (search in name and description)
|
||||
if keywords := strings.TrimSpace(c.Query("keywords")); keywords != "" {
|
||||
wheres = append(wheres, model.QueryWhere{
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import (
|
|||
"github.com/yaoapp/gou/model"
|
||||
"github.com/yaoapp/yao/attachment"
|
||||
"github.com/yaoapp/yao/kb"
|
||||
"github.com/yaoapp/yao/openapi/oauth/authorized"
|
||||
"github.com/yaoapp/yao/openapi/response"
|
||||
)
|
||||
|
||||
|
|
@ -102,9 +103,15 @@ func ListDocuments(c *gin.Context) {
|
|||
Select: selectFields,
|
||||
}
|
||||
|
||||
// Get authorized information
|
||||
authInfo := authorized.GetInfo(c)
|
||||
|
||||
// Add filters
|
||||
var wheres []model.QueryWhere
|
||||
|
||||
// Apply permission-based filtering
|
||||
wheres = append(wheres, AuthFilter(c, authInfo)...)
|
||||
|
||||
// Filter by keywords (search in name and description)
|
||||
if keywords := strings.TrimSpace(c.Query("keywords")); keywords != "" {
|
||||
wheres = append(wheres, model.QueryWhere{
|
||||
|
|
|
|||
68
openapi/kb/filter.go
Normal file
68
openapi/kb/filter.go
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
package kb
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/yaoapp/gou/model"
|
||||
"github.com/yaoapp/yao/openapi/oauth/authorized"
|
||||
"github.com/yaoapp/yao/openapi/oauth/types"
|
||||
)
|
||||
|
||||
// AuthFilter applies permission-based filtering to query wheres
|
||||
// This function builds where clauses based on the user's authorization constraints
|
||||
// It supports TeamOnly and OwnerOnly constraints for data access control
|
||||
//
|
||||
// Parameters:
|
||||
// - c: gin.Context containing authorization information
|
||||
// - authInfo: authorized information extracted from the context
|
||||
//
|
||||
// Returns:
|
||||
// - []model.QueryWhere: array of where clauses to apply to the query
|
||||
func AuthFilter(c *gin.Context, authInfo *types.AuthorizedInfo) []model.QueryWhere {
|
||||
if authInfo == nil {
|
||||
return []model.QueryWhere{}
|
||||
}
|
||||
|
||||
var wheres []model.QueryWhere
|
||||
scope := authInfo.AccessScope()
|
||||
|
||||
// Team only - User can access:
|
||||
// 1. Public records (public = true)
|
||||
// 2. Records in their team where:
|
||||
// - They created the record (__yao_created_by matches)
|
||||
// - OR the record is shared with team (share = "team")
|
||||
if authInfo.Constraints.TeamOnly && authorized.IsTeamMember(c) {
|
||||
wheres = append(wheres, model.QueryWhere{
|
||||
Wheres: []model.QueryWhere{
|
||||
{Column: "public", Value: true, Method: "orwhere"},
|
||||
{Wheres: []model.QueryWhere{
|
||||
{Column: "__yao_team_id", Value: scope.TeamID},
|
||||
{Wheres: []model.QueryWhere{
|
||||
{Column: "__yao_created_by", Value: scope.CreatedBy},
|
||||
{Column: "share", Value: "team", Method: "orwhere"},
|
||||
}},
|
||||
}, Method: "orwhere"},
|
||||
},
|
||||
})
|
||||
return wheres
|
||||
}
|
||||
|
||||
// Owner only - User can access:
|
||||
// 1. Public records (public = true)
|
||||
// 2. Records they created where:
|
||||
// - __yao_team_id is null (not team records)
|
||||
// - __yao_created_by matches their user ID
|
||||
if authInfo.Constraints.OwnerOnly && authInfo.UserID != "" {
|
||||
wheres = append(wheres, model.QueryWhere{
|
||||
Wheres: []model.QueryWhere{
|
||||
{Column: "public", Value: true, Method: "orwhere"},
|
||||
{Wheres: []model.QueryWhere{
|
||||
{Column: "__yao_team_id", OP: "null"},
|
||||
{Column: "__yao_created_by", Value: scope.CreatedBy},
|
||||
}, Method: "orwhere"},
|
||||
},
|
||||
})
|
||||
return wheres
|
||||
}
|
||||
|
||||
return wheres
|
||||
}
|
||||
|
|
@ -50,6 +50,12 @@ func GetInfo(c *gin.Context) *types.AuthorizedInfo {
|
|||
return info
|
||||
}
|
||||
|
||||
// IsTeamMember checks if the user is a team member
|
||||
func IsTeamMember(c *gin.Context) bool {
|
||||
authInfo := GetInfo(c)
|
||||
return authInfo != nil && authInfo.TeamID != "" && authInfo.UserID != ""
|
||||
}
|
||||
|
||||
// GetConstraints extracts data access constraints from the gin context
|
||||
// Returns a DataConstraints struct with all constraint flags
|
||||
func GetConstraints(c *gin.Context) types.DataConstraints {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue