mirror of
https://github.com/harness/drone.git
synced 2025-05-10 22:21:22 +08:00
Merge branch 'mg/memberships/spaces_list_filter' of _OKE5H2PQKOUfzFFDuD4FA/default/CODE/gitness (#368)
This commit is contained in:
commit
e8c1ac6ba3
@ -58,12 +58,12 @@ import (
|
|||||||
// Injectors from wire.go:
|
// Injectors from wire.go:
|
||||||
|
|
||||||
func initSystem(ctx context.Context, config *types.Config) (*server.System, error) {
|
func initSystem(ctx context.Context, config *types.Config) (*server.System, error) {
|
||||||
principalUID := check.ProvidePrincipalUIDCheck()
|
|
||||||
databaseConfig := server.ProvideDatabaseConfig(config)
|
databaseConfig := server.ProvideDatabaseConfig(config)
|
||||||
db, err := database.ProvideDatabase(ctx, databaseConfig)
|
db, err := database.ProvideDatabase(ctx, databaseConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
principalUID := check.ProvidePrincipalUIDCheck()
|
||||||
pathTransformation := store.ProvidePathTransformation()
|
pathTransformation := store.ProvidePathTransformation()
|
||||||
pathStore := database.ProvidePathStore(db, pathTransformation)
|
pathStore := database.ProvidePathStore(db, pathTransformation)
|
||||||
pathCache := cache.ProvidePathCache(pathStore, pathTransformation)
|
pathCache := cache.ProvidePathCache(pathStore, pathTransformation)
|
||||||
@ -76,7 +76,7 @@ func initSystem(ctx context.Context, config *types.Config) (*server.System, erro
|
|||||||
principalUIDTransformation := store.ProvidePrincipalUIDTransformation()
|
principalUIDTransformation := store.ProvidePrincipalUIDTransformation()
|
||||||
principalStore := database.ProvidePrincipalStore(db, principalUIDTransformation)
|
principalStore := database.ProvidePrincipalStore(db, principalUIDTransformation)
|
||||||
tokenStore := database.ProvideTokenStore(db)
|
tokenStore := database.ProvideTokenStore(db)
|
||||||
controller := user.NewController(principalUID, authorizer, principalStore, tokenStore, membershipStore)
|
controller := user.ProvideController(db, principalUID, authorizer, principalStore, tokenStore, membershipStore)
|
||||||
serviceController := service.NewController(principalUID, authorizer, principalStore)
|
serviceController := service.NewController(principalUID, authorizer, principalStore)
|
||||||
bootstrapBootstrap := bootstrap.ProvideBootstrap(config, controller, serviceController)
|
bootstrapBootstrap := bootstrap.ProvideBootstrap(config, controller, serviceController)
|
||||||
authenticator := authn.ProvideAuthenticator(principalStore, tokenStore)
|
authenticator := authn.ProvideAuthenticator(principalStore, tokenStore)
|
||||||
|
@ -19,7 +19,7 @@ import (
|
|||||||
func (c *Controller) MembershipList(ctx context.Context,
|
func (c *Controller) MembershipList(ctx context.Context,
|
||||||
session *auth.Session,
|
session *auth.Session,
|
||||||
spaceRef string,
|
spaceRef string,
|
||||||
opts types.MembershipFilter,
|
filter types.MembershipUserFilter,
|
||||||
) ([]types.MembershipUser, int64, error) {
|
) ([]types.MembershipUser, int64, error) {
|
||||||
space, err := c.spaceStore.FindByRef(ctx, spaceRef)
|
space, err := c.spaceStore.FindByRef(ctx, spaceRef)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -34,17 +34,17 @@ func (c *Controller) MembershipList(ctx context.Context,
|
|||||||
var membershipsCount int64
|
var membershipsCount int64
|
||||||
|
|
||||||
err = dbtx.New(c.db).WithTx(ctx, func(ctx context.Context) error {
|
err = dbtx.New(c.db).WithTx(ctx, func(ctx context.Context) error {
|
||||||
memberships, err = c.membershipStore.ListUsers(ctx, space.ID, opts)
|
memberships, err = c.membershipStore.ListUsers(ctx, space.ID, filter)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to list memberships for space: %w", err)
|
return fmt.Errorf("failed to list memberships for space: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if opts.Page == 1 && len(memberships) < opts.Size {
|
if filter.Page == 1 && len(memberships) < filter.Size {
|
||||||
membershipsCount = int64(len(memberships))
|
membershipsCount = int64(len(memberships))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
membershipsCount, err = c.membershipStore.CountUsers(ctx, space.ID, opts)
|
membershipsCount, err = c.membershipStore.CountUsers(ctx, space.ID, filter)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to count memberships for space: %w", err)
|
return fmt.Errorf("failed to count memberships for space: %w", err)
|
||||||
}
|
}
|
||||||
|
@ -13,10 +13,12 @@ import (
|
|||||||
"github.com/harness/gitness/types/check"
|
"github.com/harness/gitness/types/check"
|
||||||
"github.com/harness/gitness/types/enum"
|
"github.com/harness/gitness/types/enum"
|
||||||
|
|
||||||
|
"github.com/jmoiron/sqlx"
|
||||||
"golang.org/x/crypto/bcrypt"
|
"golang.org/x/crypto/bcrypt"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Controller struct {
|
type Controller struct {
|
||||||
|
db *sqlx.DB
|
||||||
principalUIDCheck check.PrincipalUID
|
principalUIDCheck check.PrincipalUID
|
||||||
authorizer authz.Authorizer
|
authorizer authz.Authorizer
|
||||||
principalStore store.PrincipalStore
|
principalStore store.PrincipalStore
|
||||||
@ -25,6 +27,7 @@ type Controller struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func NewController(
|
func NewController(
|
||||||
|
db *sqlx.DB,
|
||||||
principalUIDCheck check.PrincipalUID,
|
principalUIDCheck check.PrincipalUID,
|
||||||
authorizer authz.Authorizer,
|
authorizer authz.Authorizer,
|
||||||
principalStore store.PrincipalStore,
|
principalStore store.PrincipalStore,
|
||||||
@ -32,6 +35,7 @@ func NewController(
|
|||||||
membershipStore store.MembershipStore,
|
membershipStore store.MembershipStore,
|
||||||
) *Controller {
|
) *Controller {
|
||||||
return &Controller{
|
return &Controller{
|
||||||
|
db: db,
|
||||||
principalUIDCheck: principalUIDCheck,
|
principalUIDCheck: principalUIDCheck,
|
||||||
authorizer: authorizer,
|
authorizer: authorizer,
|
||||||
principalStore: principalStore,
|
principalStore: principalStore,
|
||||||
|
@ -10,6 +10,7 @@ import (
|
|||||||
|
|
||||||
apiauth "github.com/harness/gitness/internal/api/auth"
|
apiauth "github.com/harness/gitness/internal/api/auth"
|
||||||
"github.com/harness/gitness/internal/auth"
|
"github.com/harness/gitness/internal/auth"
|
||||||
|
"github.com/harness/gitness/store/database/dbtx"
|
||||||
"github.com/harness/gitness/types"
|
"github.com/harness/gitness/types"
|
||||||
"github.com/harness/gitness/types/enum"
|
"github.com/harness/gitness/types/enum"
|
||||||
)
|
)
|
||||||
@ -18,21 +19,42 @@ import (
|
|||||||
func (c *Controller) MembershipSpaces(ctx context.Context,
|
func (c *Controller) MembershipSpaces(ctx context.Context,
|
||||||
session *auth.Session,
|
session *auth.Session,
|
||||||
userUID string,
|
userUID string,
|
||||||
) ([]types.MembershipSpace, error) {
|
filter types.MembershipSpaceFilter,
|
||||||
|
) ([]types.MembershipSpace, int64, error) {
|
||||||
user, err := findUserFromUID(ctx, c.principalStore, userUID)
|
user, err := findUserFromUID(ctx, c.principalStore, userUID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to find user by UID: %w", err)
|
return nil, 0, fmt.Errorf("failed to find user by UID: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure principal has required permissions.
|
// Ensure principal has required permissions.
|
||||||
if err = apiauth.CheckUser(ctx, c.authorizer, session, user, enum.PermissionUserView); err != nil {
|
if err = apiauth.CheckUser(ctx, c.authorizer, session, user, enum.PermissionUserView); err != nil {
|
||||||
return nil, err
|
return nil, 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
membershipSpaces, err := c.membershipStore.ListSpaces(ctx, user.ID)
|
var membershipSpaces []types.MembershipSpace
|
||||||
|
var membershipsCount int64
|
||||||
|
|
||||||
|
err = dbtx.New(c.db).WithTx(ctx, func(ctx context.Context) error {
|
||||||
|
membershipSpaces, err = c.membershipStore.ListSpaces(ctx, user.ID, filter)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to list membership spaces for user: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if filter.Page == 1 && len(membershipSpaces) < filter.Size {
|
||||||
|
membershipsCount = int64(len(membershipSpaces))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
membershipsCount, err = c.membershipStore.CountSpaces(ctx, user.ID, filter)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to count memberships for user: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}, dbtx.TxDefaultReadOnly)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to list membership spaces for user: %w", err)
|
return nil, 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return membershipSpaces, nil
|
return membershipSpaces, membershipsCount, nil
|
||||||
}
|
}
|
||||||
|
@ -10,14 +10,16 @@ import (
|
|||||||
"github.com/harness/gitness/types/check"
|
"github.com/harness/gitness/types/check"
|
||||||
|
|
||||||
"github.com/google/wire"
|
"github.com/google/wire"
|
||||||
|
"github.com/jmoiron/sqlx"
|
||||||
)
|
)
|
||||||
|
|
||||||
// WireSet provides a wire set for this package.
|
// WireSet provides a wire set for this package.
|
||||||
var WireSet = wire.NewSet(
|
var WireSet = wire.NewSet(
|
||||||
NewController,
|
ProvideController,
|
||||||
)
|
)
|
||||||
|
|
||||||
func ProvideController(
|
func ProvideController(
|
||||||
|
db *sqlx.DB,
|
||||||
principalUIDCheck check.PrincipalUID,
|
principalUIDCheck check.PrincipalUID,
|
||||||
authorizer authz.Authorizer,
|
authorizer authz.Authorizer,
|
||||||
principalStore store.PrincipalStore,
|
principalStore store.PrincipalStore,
|
||||||
@ -25,6 +27,7 @@ func ProvideController(
|
|||||||
membershipStore store.MembershipStore,
|
membershipStore store.MembershipStore,
|
||||||
) *Controller {
|
) *Controller {
|
||||||
return NewController(
|
return NewController(
|
||||||
|
db,
|
||||||
principalUIDCheck,
|
principalUIDCheck,
|
||||||
authorizer,
|
authorizer,
|
||||||
principalStore,
|
principalStore,
|
||||||
|
@ -24,7 +24,7 @@ func HandleMembershipList(spaceCtrl *space.Controller) http.HandlerFunc {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
filter := request.ParseMembershipFilter(r)
|
filter := request.ParseMembershipUserFilter(r)
|
||||||
|
|
||||||
memberships, membershipsCount, err := spaceCtrl.MembershipList(ctx, session, spaceRef, filter)
|
memberships, membershipsCount, err := spaceCtrl.MembershipList(ctx, session, spaceRef, filter)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -18,12 +18,15 @@ func HandleMembershipSpaces(userCtrl *user.Controller) http.HandlerFunc {
|
|||||||
session, _ := request.AuthSessionFrom(ctx)
|
session, _ := request.AuthSessionFrom(ctx)
|
||||||
userUID := session.Principal.UID
|
userUID := session.Principal.UID
|
||||||
|
|
||||||
membershipSpaces, err := userCtrl.MembershipSpaces(ctx, session, userUID)
|
filter := request.ParseMembershipSpaceFilter(r)
|
||||||
|
|
||||||
|
membershipSpaces, membershipSpaceCount, err := userCtrl.MembershipSpaces(ctx, session, userUID, filter)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
render.TranslatedUserError(w, err)
|
render.TranslatedUserError(w, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
render.Pagination(r, w, filter.Page, filter.Size, int(membershipSpaceCount))
|
||||||
render.JSON(w, http.StatusOK, membershipSpaces)
|
render.JSON(w, http.StatusOK, membershipSpaces)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -115,7 +115,7 @@ var queryParameterQuerySpace = openapi3.ParameterOrRef{
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
var queryParameterSpaceMembers = openapi3.ParameterOrRef{
|
var queryParameterMembershipUsers = openapi3.ParameterOrRef{
|
||||||
Parameter: &openapi3.Parameter{
|
Parameter: &openapi3.Parameter{
|
||||||
Name: request.QueryParamQuery,
|
Name: request.QueryParamQuery,
|
||||||
In: openapi3.ParameterInQuery,
|
In: openapi3.ParameterInQuery,
|
||||||
@ -129,7 +129,7 @@ var queryParameterSpaceMembers = openapi3.ParameterOrRef{
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
var queryParameterSortSpaceMembers = openapi3.ParameterOrRef{
|
var queryParameterSortMembershipUsers = openapi3.ParameterOrRef{
|
||||||
Parameter: &openapi3.Parameter{
|
Parameter: &openapi3.Parameter{
|
||||||
Name: request.QueryParamSort,
|
Name: request.QueryParamSort,
|
||||||
In: openapi3.ParameterInQuery,
|
In: openapi3.ParameterInQuery,
|
||||||
@ -138,8 +138,8 @@ var queryParameterSortSpaceMembers = openapi3.ParameterOrRef{
|
|||||||
Schema: &openapi3.SchemaOrRef{
|
Schema: &openapi3.SchemaOrRef{
|
||||||
Schema: &openapi3.Schema{
|
Schema: &openapi3.Schema{
|
||||||
Type: ptrSchemaType(openapi3.SchemaTypeString),
|
Type: ptrSchemaType(openapi3.SchemaTypeString),
|
||||||
Default: ptrptr(enum.MembershipSortName),
|
Default: ptrptr(enum.MembershipUserSortName),
|
||||||
Enum: enum.MembershipSort("").Enum(),
|
Enum: enum.MembershipUserSort("").Enum(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -370,8 +370,8 @@ func spaceOperations(reflector *openapi3.Reflector) {
|
|||||||
opMembershipList.WithTags("space")
|
opMembershipList.WithTags("space")
|
||||||
opMembershipList.WithMapOfAnything(map[string]interface{}{"operationId": "membershipList"})
|
opMembershipList.WithMapOfAnything(map[string]interface{}{"operationId": "membershipList"})
|
||||||
opMembershipList.WithParameters(
|
opMembershipList.WithParameters(
|
||||||
queryParameterSpaceMembers,
|
queryParameterMembershipUsers,
|
||||||
queryParameterOrder, queryParameterSortSpaceMembers,
|
queryParameterOrder, queryParameterSortMembershipUsers,
|
||||||
queryParameterPage, queryParameterLimit)
|
queryParameterPage, queryParameterLimit)
|
||||||
_ = reflector.SetRequest(&opMembershipList, &struct {
|
_ = reflector.SetRequest(&opMembershipList, &struct {
|
||||||
spaceRequest
|
spaceRequest
|
||||||
|
@ -8,9 +8,12 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/harness/gitness/internal/api/controller/user"
|
"github.com/harness/gitness/internal/api/controller/user"
|
||||||
|
"github.com/harness/gitness/internal/api/request"
|
||||||
"github.com/harness/gitness/internal/api/usererror"
|
"github.com/harness/gitness/internal/api/usererror"
|
||||||
"github.com/harness/gitness/types"
|
"github.com/harness/gitness/types"
|
||||||
|
"github.com/harness/gitness/types/enum"
|
||||||
|
|
||||||
|
"github.com/gotidy/ptr"
|
||||||
"github.com/swaggest/openapi-go/openapi3"
|
"github.com/swaggest/openapi-go/openapi3"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -18,6 +21,36 @@ type createTokenRequest struct {
|
|||||||
user.CreateTokenInput
|
user.CreateTokenInput
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var queryParameterMembershipSpaces = openapi3.ParameterOrRef{
|
||||||
|
Parameter: &openapi3.Parameter{
|
||||||
|
Name: request.QueryParamQuery,
|
||||||
|
In: openapi3.ParameterInQuery,
|
||||||
|
Description: ptr.String("The substring by which the spaces the users is a member of are filtered."),
|
||||||
|
Required: ptr.Bool(false),
|
||||||
|
Schema: &openapi3.SchemaOrRef{
|
||||||
|
Schema: &openapi3.Schema{
|
||||||
|
Type: ptrSchemaType(openapi3.SchemaTypeString),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
var queryParameterSortMembershipSpaces = openapi3.ParameterOrRef{
|
||||||
|
Parameter: &openapi3.Parameter{
|
||||||
|
Name: request.QueryParamSort,
|
||||||
|
In: openapi3.ParameterInQuery,
|
||||||
|
Description: ptr.String("The field by which the spaces the user is a member of are sorted."),
|
||||||
|
Required: ptr.Bool(false),
|
||||||
|
Schema: &openapi3.SchemaOrRef{
|
||||||
|
Schema: &openapi3.Schema{
|
||||||
|
Type: ptrSchemaType(openapi3.SchemaTypeString),
|
||||||
|
Default: ptrptr(enum.MembershipSpaceSortUID),
|
||||||
|
Enum: enum.MembershipSpaceSort("").Enum(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
// helper function that constructs the openapi specification
|
// helper function that constructs the openapi specification
|
||||||
// for user account resources.
|
// for user account resources.
|
||||||
func buildUser(reflector *openapi3.Reflector) {
|
func buildUser(reflector *openapi3.Reflector) {
|
||||||
@ -48,6 +81,10 @@ func buildUser(reflector *openapi3.Reflector) {
|
|||||||
opMemberSpaces := openapi3.Operation{}
|
opMemberSpaces := openapi3.Operation{}
|
||||||
opMemberSpaces.WithTags("user")
|
opMemberSpaces.WithTags("user")
|
||||||
opMemberSpaces.WithMapOfAnything(map[string]interface{}{"operationId": "membershipSpaces"})
|
opMemberSpaces.WithMapOfAnything(map[string]interface{}{"operationId": "membershipSpaces"})
|
||||||
|
opMemberSpaces.WithParameters(
|
||||||
|
queryParameterMembershipSpaces,
|
||||||
|
queryParameterOrder, queryParameterSortMembershipSpaces,
|
||||||
|
queryParameterPage, queryParameterLimit)
|
||||||
_ = reflector.SetRequest(&opMemberSpaces, struct{}{}, http.MethodGet)
|
_ = reflector.SetRequest(&opMemberSpaces, struct{}{}, http.MethodGet)
|
||||||
_ = reflector.SetJSONResponse(&opMemberSpaces, new([]types.MembershipSpace), http.StatusOK)
|
_ = reflector.SetJSONResponse(&opMemberSpaces, new([]types.MembershipSpace), http.StatusOK)
|
||||||
_ = reflector.SetJSONResponse(&opMemberSpaces, new(usererror.Error), http.StatusInternalServerError)
|
_ = reflector.SetJSONResponse(&opMemberSpaces, new(usererror.Error), http.StatusInternalServerError)
|
||||||
|
@ -11,20 +11,34 @@ import (
|
|||||||
"github.com/harness/gitness/types/enum"
|
"github.com/harness/gitness/types/enum"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ParseMembershipSort extracts the membership sort parameter from the url.
|
// ParseMembershipUserSort extracts the membership sort parameter from the url.
|
||||||
func ParseMembershipSort(r *http.Request) enum.MembershipSort {
|
func ParseMembershipUserSort(r *http.Request) enum.MembershipUserSort {
|
||||||
return enum.ParseMembershipSort(
|
return enum.ParseMembershipUserSort(
|
||||||
r.URL.Query().Get(QueryParamSort),
|
r.URL.Query().Get(QueryParamSort),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ParseMembershipFilter extracts the membership filter from the url.
|
// ParseMembershipUserFilter extracts the membership filter from the url.
|
||||||
func ParseMembershipFilter(r *http.Request) types.MembershipFilter {
|
func ParseMembershipUserFilter(r *http.Request) types.MembershipUserFilter {
|
||||||
return types.MembershipFilter{
|
return types.MembershipUserFilter{
|
||||||
Page: ParsePage(r),
|
ListQueryFilter: ParseListQueryFilterFromRequest(r),
|
||||||
Size: ParseLimit(r),
|
Sort: ParseMembershipUserSort(r),
|
||||||
Query: ParseQuery(r),
|
Order: ParseOrder(r),
|
||||||
Sort: ParseMembershipSort(r),
|
}
|
||||||
Order: ParseOrder(r),
|
}
|
||||||
|
|
||||||
|
// ParseMembershipSpaceSort extracts the membership space sort parameter from the url.
|
||||||
|
func ParseMembershipSpaceSort(r *http.Request) enum.MembershipSpaceSort {
|
||||||
|
return enum.ParseMembershipSpaceSort(
|
||||||
|
r.URL.Query().Get(QueryParamSort),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParseMembershipSpaceFilter extracts the membership space filter from the url.
|
||||||
|
func ParseMembershipSpaceFilter(r *http.Request) types.MembershipSpaceFilter {
|
||||||
|
return types.MembershipSpaceFilter{
|
||||||
|
ListQueryFilter: ParseListQueryFilterFromRequest(r),
|
||||||
|
Sort: ParseMembershipSpaceSort(r),
|
||||||
|
Order: ParseOrder(r),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -230,9 +230,10 @@ type (
|
|||||||
Create(ctx context.Context, membership *types.Membership) error
|
Create(ctx context.Context, membership *types.Membership) error
|
||||||
Update(ctx context.Context, membership *types.Membership) error
|
Update(ctx context.Context, membership *types.Membership) error
|
||||||
Delete(ctx context.Context, key types.MembershipKey) error
|
Delete(ctx context.Context, key types.MembershipKey) error
|
||||||
CountUsers(ctx context.Context, spaceID int64, filter types.MembershipFilter) (int64, error)
|
CountUsers(ctx context.Context, spaceID int64, filter types.MembershipUserFilter) (int64, error)
|
||||||
ListUsers(ctx context.Context, spaceID int64, filter types.MembershipFilter) ([]types.MembershipUser, error)
|
ListUsers(ctx context.Context, spaceID int64, filter types.MembershipUserFilter) ([]types.MembershipUser, error)
|
||||||
ListSpaces(ctx context.Context, userID int64) ([]types.MembershipSpace, error)
|
CountSpaces(ctx context.Context, userID int64, filter types.MembershipSpaceFilter) (int64, error)
|
||||||
|
ListSpaces(ctx context.Context, userID int64, filter types.MembershipSpaceFilter) ([]types.MembershipSpace, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TokenStore defines the token data storage.
|
// TokenStore defines the token data storage.
|
||||||
|
@ -183,7 +183,7 @@ func (s *MembershipStore) Delete(ctx context.Context, key types.MembershipKey) e
|
|||||||
// CountUsers returns a number of users memberships that matches the provided filter.
|
// CountUsers returns a number of users memberships that matches the provided filter.
|
||||||
func (s *MembershipStore) CountUsers(ctx context.Context,
|
func (s *MembershipStore) CountUsers(ctx context.Context,
|
||||||
spaceID int64,
|
spaceID int64,
|
||||||
filter types.MembershipFilter,
|
filter types.MembershipUserFilter,
|
||||||
) (int64, error) {
|
) (int64, error) {
|
||||||
stmt := database.Builder.
|
stmt := database.Builder.
|
||||||
Select("count(*)").
|
Select("count(*)").
|
||||||
@ -191,11 +191,11 @@ func (s *MembershipStore) CountUsers(ctx context.Context,
|
|||||||
InnerJoin("principals ON membership_principal_id = principal_id").
|
InnerJoin("principals ON membership_principal_id = principal_id").
|
||||||
Where("membership_space_id = ?", spaceID)
|
Where("membership_space_id = ?", spaceID)
|
||||||
|
|
||||||
stmt = prepareMembershipListUsersStmt(stmt, filter)
|
stmt = applyMembershipUserFilter(stmt, filter)
|
||||||
|
|
||||||
sql, args, err := stmt.ToSql()
|
sql, args, err := stmt.ToSql()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, fmt.Errorf("failed to convert membership count query to sql: %w", err)
|
return 0, fmt.Errorf("failed to convert membership users count query to sql: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
db := dbtx.GetAccessor(ctx, s.db)
|
db := dbtx.GetAccessor(ctx, s.db)
|
||||||
@ -203,7 +203,7 @@ func (s *MembershipStore) CountUsers(ctx context.Context,
|
|||||||
var count int64
|
var count int64
|
||||||
err = db.QueryRowContext(ctx, sql, args...).Scan(&count)
|
err = db.QueryRowContext(ctx, sql, args...).Scan(&count)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, database.ProcessSQLErrorf(err, "Failed executing membership count query")
|
return 0, database.ProcessSQLErrorf(err, "Failed executing membership users count query")
|
||||||
}
|
}
|
||||||
|
|
||||||
return count, nil
|
return count, nil
|
||||||
@ -212,7 +212,7 @@ func (s *MembershipStore) CountUsers(ctx context.Context,
|
|||||||
// ListUsers returns a list of memberships for a space or a user.
|
// ListUsers returns a list of memberships for a space or a user.
|
||||||
func (s *MembershipStore) ListUsers(ctx context.Context,
|
func (s *MembershipStore) ListUsers(ctx context.Context,
|
||||||
spaceID int64,
|
spaceID int64,
|
||||||
filter types.MembershipFilter,
|
filter types.MembershipUserFilter,
|
||||||
) ([]types.MembershipUser, error) {
|
) ([]types.MembershipUser, error) {
|
||||||
const columns = membershipColumns + "," + principalInfoCommonColumns
|
const columns = membershipColumns + "," + principalInfoCommonColumns
|
||||||
stmt := database.Builder.
|
stmt := database.Builder.
|
||||||
@ -221,7 +221,7 @@ func (s *MembershipStore) ListUsers(ctx context.Context,
|
|||||||
InnerJoin("principals ON membership_principal_id = principal_id").
|
InnerJoin("principals ON membership_principal_id = principal_id").
|
||||||
Where("membership_space_id = ?", spaceID)
|
Where("membership_space_id = ?", spaceID)
|
||||||
|
|
||||||
stmt = prepareMembershipListUsersStmt(stmt, filter)
|
stmt = applyMembershipUserFilter(stmt, filter)
|
||||||
stmt = stmt.Limit(database.Limit(filter.Size))
|
stmt = stmt.Limit(database.Limit(filter.Size))
|
||||||
stmt = stmt.Offset(database.Offset(filter.Page, filter.Size))
|
stmt = stmt.Offset(database.Offset(filter.Page, filter.Size))
|
||||||
|
|
||||||
@ -231,9 +231,9 @@ func (s *MembershipStore) ListUsers(ctx context.Context,
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch filter.Sort {
|
switch filter.Sort {
|
||||||
case enum.MembershipSortName:
|
case enum.MembershipUserSortName:
|
||||||
stmt = stmt.OrderBy("principal_display_name " + order.String())
|
stmt = stmt.OrderBy("principal_display_name " + order.String())
|
||||||
case enum.MembershipSortCreated:
|
case enum.MembershipUserSortCreated:
|
||||||
stmt = stmt.OrderBy("membership_created " + order.String())
|
stmt = stmt.OrderBy("membership_created " + order.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -258,9 +258,9 @@ func (s *MembershipStore) ListUsers(ctx context.Context,
|
|||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func prepareMembershipListUsersStmt(
|
func applyMembershipUserFilter(
|
||||||
stmt squirrel.SelectBuilder,
|
stmt squirrel.SelectBuilder,
|
||||||
opts types.MembershipFilter,
|
opts types.MembershipUserFilter,
|
||||||
) squirrel.SelectBuilder {
|
) squirrel.SelectBuilder {
|
||||||
if opts.Query != "" {
|
if opts.Query != "" {
|
||||||
searchTerm := "%%" + strings.ToLower(opts.Query) + "%%"
|
searchTerm := "%%" + strings.ToLower(opts.Query) + "%%"
|
||||||
@ -270,9 +270,38 @@ func prepareMembershipListUsersStmt(
|
|||||||
return stmt
|
return stmt
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *MembershipStore) CountSpaces(ctx context.Context,
|
||||||
|
userID int64,
|
||||||
|
filter types.MembershipSpaceFilter,
|
||||||
|
) (int64, error) {
|
||||||
|
stmt := database.Builder.
|
||||||
|
Select("count(*)").
|
||||||
|
From("memberships").
|
||||||
|
InnerJoin("spaces ON spaces.space_id = membership_space_id").
|
||||||
|
Where("membership_principal_id = ?", userID)
|
||||||
|
|
||||||
|
stmt = applyMembershipSpaceFilter(stmt, filter)
|
||||||
|
|
||||||
|
sql, args, err := stmt.ToSql()
|
||||||
|
if err != nil {
|
||||||
|
return 0, fmt.Errorf("failed to convert membership spaces count query to sql: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
db := dbtx.GetAccessor(ctx, s.db)
|
||||||
|
|
||||||
|
var count int64
|
||||||
|
err = db.QueryRowContext(ctx, sql, args...).Scan(&count)
|
||||||
|
if err != nil {
|
||||||
|
return 0, database.ProcessSQLErrorf(err, "Failed executing membership spaces count query")
|
||||||
|
}
|
||||||
|
|
||||||
|
return count, nil
|
||||||
|
}
|
||||||
|
|
||||||
// ListSpaces returns a list of spaces in which the provided user is a member.
|
// ListSpaces returns a list of spaces in which the provided user is a member.
|
||||||
func (s *MembershipStore) ListSpaces(ctx context.Context,
|
func (s *MembershipStore) ListSpaces(ctx context.Context,
|
||||||
userID int64,
|
userID int64,
|
||||||
|
filter types.MembershipSpaceFilter,
|
||||||
) ([]types.MembershipSpace, error) {
|
) ([]types.MembershipSpace, error) {
|
||||||
const columns = membershipColumns + "," + spaceColumnsForJoin
|
const columns = membershipColumns + "," + spaceColumnsForJoin
|
||||||
stmt := database.Builder.
|
stmt := database.Builder.
|
||||||
@ -280,8 +309,25 @@ func (s *MembershipStore) ListSpaces(ctx context.Context,
|
|||||||
From("memberships").
|
From("memberships").
|
||||||
InnerJoin("spaces ON spaces.space_id = membership_space_id").
|
InnerJoin("spaces ON spaces.space_id = membership_space_id").
|
||||||
InnerJoin(`paths ON spaces.space_id=paths.path_space_id AND paths.path_is_primary=true`).
|
InnerJoin(`paths ON spaces.space_id=paths.path_space_id AND paths.path_is_primary=true`).
|
||||||
Where("membership_principal_id = ?", userID).
|
Where("membership_principal_id = ?", userID)
|
||||||
OrderBy("space_path asc")
|
|
||||||
|
stmt = applyMembershipSpaceFilter(stmt, filter)
|
||||||
|
stmt = stmt.Limit(database.Limit(filter.Size))
|
||||||
|
stmt = stmt.Offset(database.Offset(filter.Page, filter.Size))
|
||||||
|
|
||||||
|
order := filter.Order
|
||||||
|
if order == enum.OrderDefault {
|
||||||
|
order = enum.OrderAsc
|
||||||
|
}
|
||||||
|
|
||||||
|
switch filter.Sort {
|
||||||
|
case enum.MembershipSpaceSortUID:
|
||||||
|
stmt = stmt.OrderBy("space_uid " + order.String())
|
||||||
|
case enum.MembershipSpaceSortPath:
|
||||||
|
stmt = stmt.OrderBy("space_path " + order.String())
|
||||||
|
case enum.MembershipSpaceSortCreated:
|
||||||
|
stmt = stmt.OrderBy("membership_created " + order.String())
|
||||||
|
}
|
||||||
|
|
||||||
sql, args, err := stmt.ToSql()
|
sql, args, err := stmt.ToSql()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -303,6 +349,18 @@ func (s *MembershipStore) ListSpaces(ctx context.Context,
|
|||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func applyMembershipSpaceFilter(
|
||||||
|
stmt squirrel.SelectBuilder,
|
||||||
|
opts types.MembershipSpaceFilter,
|
||||||
|
) squirrel.SelectBuilder {
|
||||||
|
if opts.Query != "" {
|
||||||
|
searchTerm := "%%" + strings.ToLower(opts.Query) + "%%"
|
||||||
|
stmt = stmt.Where("LOWER(space_uid) LIKE ?", searchTerm)
|
||||||
|
}
|
||||||
|
|
||||||
|
return stmt
|
||||||
|
}
|
||||||
|
|
||||||
func mapToMembership(m *membership) types.Membership {
|
func mapToMembership(m *membership) types.Membership {
|
||||||
return types.Membership{
|
return types.Membership{
|
||||||
MembershipKey: types.MembershipKey{
|
MembershipKey: types.MembershipKey{
|
||||||
|
@ -8,45 +8,100 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
// MembershipSort represents membership sort order.
|
// MembershipUserSort represents membership user sort order.
|
||||||
type MembershipSort string
|
type MembershipUserSort string
|
||||||
|
|
||||||
// Order enumeration.
|
// MembershipUserSort enumeration.
|
||||||
const (
|
const (
|
||||||
MembershipSortName = name
|
MembershipUserSortName MembershipUserSort = name
|
||||||
MembershipSortCreated = created
|
MembershipUserSortCreated MembershipUserSort = created
|
||||||
)
|
)
|
||||||
|
|
||||||
var membershipSorts = sortEnum([]MembershipSort{
|
var membershipUserSorts = sortEnum([]MembershipUserSort{
|
||||||
MembershipSortName,
|
MembershipUserSortName,
|
||||||
MembershipSortCreated,
|
MembershipUserSortCreated,
|
||||||
})
|
})
|
||||||
|
|
||||||
func (MembershipSort) Enum() []interface{} { return toInterfaceSlice(membershipSorts) }
|
func (MembershipUserSort) Enum() []interface{} { return toInterfaceSlice(membershipUserSorts) }
|
||||||
func (s MembershipSort) Sanitize() (MembershipSort, bool) { return Sanitize(s, GetAllMembershipSorts) }
|
func (s MembershipUserSort) Sanitize() (MembershipUserSort, bool) {
|
||||||
func GetAllMembershipSorts() ([]MembershipSort, MembershipSort) {
|
return Sanitize(s, GetAllMembershipUserSorts)
|
||||||
return membershipSorts, MembershipSortName
|
}
|
||||||
|
func GetAllMembershipUserSorts() ([]MembershipUserSort, MembershipUserSort) {
|
||||||
|
return membershipUserSorts, MembershipUserSortName
|
||||||
}
|
}
|
||||||
|
|
||||||
// ParseMembershipSort parses the membership sort attribute string
|
// ParseMembershipUserSort parses the membership user sort attribute string
|
||||||
// and returns the equivalent enumeration.
|
// and returns the equivalent enumeration.
|
||||||
func ParseMembershipSort(s string) MembershipSort {
|
func ParseMembershipUserSort(s string) MembershipUserSort {
|
||||||
switch strings.ToLower(s) {
|
switch strings.ToLower(s) {
|
||||||
case name:
|
case name:
|
||||||
return MembershipSortName
|
return MembershipUserSortName
|
||||||
case created, createdAt:
|
case created, createdAt:
|
||||||
return MembershipSortCreated
|
return MembershipUserSortCreated
|
||||||
default:
|
default:
|
||||||
return MembershipSortName
|
return MembershipUserSortName
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// String returns the string representation of the attribute.
|
// String returns the string representation of the attribute.
|
||||||
func (s MembershipSort) String() string {
|
func (s MembershipUserSort) String() string {
|
||||||
switch s {
|
switch s {
|
||||||
case MembershipSortName:
|
case MembershipUserSortName:
|
||||||
return name
|
return name
|
||||||
case MembershipSortCreated:
|
case MembershipUserSortCreated:
|
||||||
|
return created
|
||||||
|
default:
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MembershipSpaceSort represents membership space sort order.
|
||||||
|
type MembershipSpaceSort string
|
||||||
|
|
||||||
|
// MembershipSpaceSort enumeration.
|
||||||
|
const (
|
||||||
|
MembershipSpaceSortUID MembershipSpaceSort = uid
|
||||||
|
MembershipSpaceSortPath MembershipSpaceSort = path
|
||||||
|
MembershipSpaceSortCreated MembershipSpaceSort = created
|
||||||
|
)
|
||||||
|
|
||||||
|
var membershipSpaceSorts = sortEnum([]MembershipSpaceSort{
|
||||||
|
MembershipSpaceSortUID,
|
||||||
|
MembershipSpaceSortPath,
|
||||||
|
MembershipSpaceSortCreated,
|
||||||
|
})
|
||||||
|
|
||||||
|
func (MembershipSpaceSort) Enum() []interface{} { return toInterfaceSlice(membershipSpaceSorts) }
|
||||||
|
func (s MembershipSpaceSort) Sanitize() (MembershipSpaceSort, bool) {
|
||||||
|
return Sanitize(s, GetAllMembershipSpaceSorts)
|
||||||
|
}
|
||||||
|
func GetAllMembershipSpaceSorts() ([]MembershipSpaceSort, MembershipSpaceSort) {
|
||||||
|
return membershipSpaceSorts, MembershipSpaceSortPath
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParseMembershipSpaceSort parses the membership space sort attribute string
|
||||||
|
// and returns the equivalent enumeration.
|
||||||
|
func ParseMembershipSpaceSort(s string) MembershipSpaceSort {
|
||||||
|
switch strings.ToLower(s) {
|
||||||
|
case name:
|
||||||
|
return MembershipSpaceSortUID
|
||||||
|
case path:
|
||||||
|
return MembershipSpaceSortPath
|
||||||
|
case created, createdAt:
|
||||||
|
return MembershipSpaceSortCreated
|
||||||
|
default:
|
||||||
|
return MembershipSpaceSortUID
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// String returns the string representation of the attribute.
|
||||||
|
func (s MembershipSpaceSort) String() string {
|
||||||
|
switch s {
|
||||||
|
case MembershipSpaceSortUID:
|
||||||
|
return uid
|
||||||
|
case MembershipSpaceSortPath:
|
||||||
|
return path
|
||||||
|
case MembershipSpaceSortCreated:
|
||||||
return created
|
return created
|
||||||
default:
|
default:
|
||||||
return undefined
|
return undefined
|
||||||
|
@ -32,6 +32,13 @@ type MembershipUser struct {
|
|||||||
AddedBy PrincipalInfo `json:"added_by"`
|
AddedBy PrincipalInfo `json:"added_by"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MembershipUserFilter holds membership user query parameters.
|
||||||
|
type MembershipUserFilter struct {
|
||||||
|
ListQueryFilter
|
||||||
|
Sort enum.MembershipUserSort `json:"sort"`
|
||||||
|
Order enum.Order `json:"order"`
|
||||||
|
}
|
||||||
|
|
||||||
// MembershipSpace adds space info to the Membership data.
|
// MembershipSpace adds space info to the Membership data.
|
||||||
type MembershipSpace struct {
|
type MembershipSpace struct {
|
||||||
Membership
|
Membership
|
||||||
@ -39,11 +46,9 @@ type MembershipSpace struct {
|
|||||||
AddedBy PrincipalInfo `json:"added_by"`
|
AddedBy PrincipalInfo `json:"added_by"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// MembershipFilter holds membership query parameters.
|
// MembershipSpaceFilter holds membership space query parameters.
|
||||||
type MembershipFilter struct {
|
type MembershipSpaceFilter struct {
|
||||||
Page int `json:"page"`
|
ListQueryFilter
|
||||||
Size int `json:"size"`
|
Sort enum.MembershipSpaceSort `json:"sort"`
|
||||||
Query string `json:"query"`
|
Order enum.Order `json:"order"`
|
||||||
Sort enum.MembershipSort `json:"sort"`
|
|
||||||
Order enum.Order `json:"order"`
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user