From 9bd185a9c65f934c1ab3e3c45fee909bfd2e3bb3 Mon Sep 17 00:00:00 2001 From: Lakhan Samani Date: Tue, 25 Jan 2022 10:57:40 +0530 Subject: [PATCH] feat: add pagination for users & verification_requests --- server/constants/pagination.go | 4 + server/db/models/verification_requests.go | 14 + server/db/providers/arangodb/user.go | 28 +- .../arangodb/verification_requests.go | 26 +- server/db/providers/mongodb/user.go | 34 +- .../mongodb/verification_requests.go | 29 +- server/db/providers/providers.go | 9 +- server/db/providers/sql/user.go | 26 +- .../db/providers/sql/verification_requests.go | 27 +- server/graph/generated/generated.go | 690 +++++++++++++++++- server/graph/model/models_gen.go | 26 + server/graph/schema.graphqls | 30 +- server/graph/schema.resolvers.go | 8 +- server/resolvers/users.go | 17 +- server/resolvers/verification_requests.go | 25 +- server/test/resolvers_test.go | 6 +- server/test/users_test.go | 18 +- server/test/verification_requests_test.go | 16 +- server/utils/pagination.go | 29 + 19 files changed, 962 insertions(+), 100 deletions(-) create mode 100644 server/constants/pagination.go create mode 100644 server/utils/pagination.go diff --git a/server/constants/pagination.go b/server/constants/pagination.go new file mode 100644 index 0000000..c375d52 --- /dev/null +++ b/server/constants/pagination.go @@ -0,0 +1,4 @@ +package constants + +// DefaultLimit is the default limit for pagination +var DefaultLimit = 10 diff --git a/server/db/models/verification_requests.go b/server/db/models/verification_requests.go index 931887f..29da0f0 100644 --- a/server/db/models/verification_requests.go +++ b/server/db/models/verification_requests.go @@ -1,5 +1,7 @@ package models +import "github.com/authorizerdev/authorizer/server/graph/model" + // VerificationRequest model for db type VerificationRequest struct { Key string `json:"_key,omitempty" bson:"_key"` // for arangodb @@ -11,3 +13,15 @@ type VerificationRequest struct { UpdatedAt int64 `gorm:"autoUpdateTime" json:"updated_at" bson:"updated_at"` Email string `gorm:"uniqueIndex:idx_email_identifier" json:"email" bson:"email"` } + +func (v *VerificationRequest) AsAPIVerificationRequest() *model.VerificationRequest { + return &model.VerificationRequest{ + ID: v.ID, + Token: &v.Token, + Identifier: &v.Identifier, + Expires: &v.ExpiresAt, + CreatedAt: &v.CreatedAt, + UpdatedAt: &v.UpdatedAt, + Email: &v.Email, + } +} diff --git a/server/db/providers/arangodb/user.go b/server/db/providers/arangodb/user.go index 055bd52..6cc4cb6 100644 --- a/server/db/providers/arangodb/user.go +++ b/server/db/providers/arangodb/user.go @@ -1,6 +1,7 @@ package arangodb import ( + "context" "fmt" "log" "strings" @@ -11,6 +12,7 @@ import ( "github.com/authorizerdev/authorizer/server/constants" "github.com/authorizerdev/authorizer/server/db/models" "github.com/authorizerdev/authorizer/server/envstore" + "github.com/authorizerdev/authorizer/server/graph/model" "github.com/google/uuid" ) @@ -66,32 +68,40 @@ func (p *provider) DeleteUser(user models.User) error { } // ListUsers to get list of users from database -func (p *provider) ListUsers() ([]models.User, error) { - var users []models.User - query := fmt.Sprintf("FOR d in %s RETURN d", models.Collections.User) +func (p *provider) ListUsers(pagination model.Pagination) (*model.Users, error) { + var users []*model.User + ctx := driver.WithQueryFullCount(context.Background()) - cursor, err := p.db.Query(nil, query, nil) + query := fmt.Sprintf("FOR d in %s SORT d.created_at DESC LIMIT %d, %d RETURN d", models.Collections.User, pagination.Offset, pagination.Limit) + + cursor, err := p.db.Query(ctx, query, nil) if err != nil { - return users, err + return nil, err } defer cursor.Close() + paginationClone := pagination + paginationClone.Total = cursor.Statistics().FullCount() + for { var user models.User meta, err := cursor.ReadDocument(nil, &user) - if driver.IsNoMoreDocuments(err) { + if arangoDriver.IsNoMoreDocuments(err) { break } else if err != nil { - return users, err + return nil, err } if meta.Key != "" { - users = append(users, user) + users = append(users, user.AsAPIUser()) } } - return users, nil + return &model.Users{ + Pagination: &paginationClone, + Users: users, + }, nil } // GetUserByEmail to get user information from database using email address diff --git a/server/db/providers/arangodb/verification_requests.go b/server/db/providers/arangodb/verification_requests.go index ab7eee6..a5a9fe1 100644 --- a/server/db/providers/arangodb/verification_requests.go +++ b/server/db/providers/arangodb/verification_requests.go @@ -1,12 +1,14 @@ package arangodb import ( + "context" "fmt" "log" "time" "github.com/arangodb/go-driver" "github.com/authorizerdev/authorizer/server/db/models" + "github.com/authorizerdev/authorizer/server/graph/model" "github.com/google/uuid" ) @@ -93,17 +95,20 @@ func (p *provider) GetVerificationRequestByEmail(email string, identifier string } // ListVerificationRequests to get list of verification requests from database -func (p *provider) ListVerificationRequests() ([]models.VerificationRequest, error) { - var verificationRequests []models.VerificationRequest +func (p *provider) ListVerificationRequests(pagination model.Pagination) (*model.VerificationRequests, error) { + var verificationRequests []*model.VerificationRequest + ctx := driver.WithQueryFullCount(context.Background()) + query := fmt.Sprintf("FOR d in %s SORT d.created_at DESC LIMIT %d, %d RETURN d", models.Collections.VerificationRequest, pagination.Offset, pagination.Limit) - query := fmt.Sprintf("FOR d in %s RETURN d", models.Collections.VerificationRequest) - - cursor, err := p.db.Query(nil, query, nil) + cursor, err := p.db.Query(ctx, query, nil) if err != nil { - return verificationRequests, err + return nil, err } defer cursor.Close() + paginationClone := pagination + paginationClone.Total = cursor.Statistics().FullCount() + for { var verificationRequest models.VerificationRequest meta, err := cursor.ReadDocument(nil, &verificationRequest) @@ -111,16 +116,19 @@ func (p *provider) ListVerificationRequests() ([]models.VerificationRequest, err if driver.IsNoMoreDocuments(err) { break } else if err != nil { - return verificationRequests, err + return nil, err } if meta.Key != "" { - verificationRequests = append(verificationRequests, verificationRequest) + verificationRequests = append(verificationRequests, verificationRequest.AsAPIVerificationRequest()) } } - return verificationRequests, nil + return &model.VerificationRequests{ + VerificationRequests: verificationRequests, + Pagination: &paginationClone, + }, nil } // DeleteVerificationRequest to delete verification request from database diff --git a/server/db/providers/mongodb/user.go b/server/db/providers/mongodb/user.go index e62107e..93c38d0 100644 --- a/server/db/providers/mongodb/user.go +++ b/server/db/providers/mongodb/user.go @@ -8,6 +8,7 @@ import ( "github.com/authorizerdev/authorizer/server/constants" "github.com/authorizerdev/authorizer/server/db/models" "github.com/authorizerdev/authorizer/server/envstore" + "github.com/authorizerdev/authorizer/server/graph/model" "github.com/google/uuid" "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/mongo/options" @@ -60,13 +61,29 @@ func (p *provider) DeleteUser(user models.User) error { } // ListUsers to get list of users from database -func (p *provider) ListUsers() ([]models.User, error) { - var users []models.User +func (p *provider) ListUsers(pagination model.Pagination) (*model.Users, error) { + var users []*model.User + opts := options.Find() + opts.SetLimit(pagination.Limit) + opts.SetSkip(pagination.Offset) + opts.SetSort(bson.M{"created_at": -1}) + + paginationClone := pagination + // TODO add pagination total + userCollection := p.db.Collection(models.Collections.User, options.Collection()) - cursor, err := userCollection.Find(nil, bson.M{}, options.Find()) + count, err := userCollection.CountDocuments(nil, bson.M{}, options.Count()) + if err != nil { + log.Println("error getting total users:", err) + return nil, err + } + + paginationClone.Total = count + + cursor, err := userCollection.Find(nil, bson.M{}, opts) if err != nil { log.Println("error getting users:", err) - return users, err + return nil, err } defer cursor.Close(nil) @@ -74,12 +91,15 @@ func (p *provider) ListUsers() ([]models.User, error) { var user models.User err := cursor.Decode(&user) if err != nil { - return users, err + return nil, err } - users = append(users, user) + users = append(users, user.AsAPIUser()) } - return users, nil + return &model.Users{ + Pagination: &paginationClone, + Users: users, + }, nil } // GetUserByEmail to get user information from database using email address diff --git a/server/db/providers/mongodb/verification_requests.go b/server/db/providers/mongodb/verification_requests.go index 7e86745..2776a83 100644 --- a/server/db/providers/mongodb/verification_requests.go +++ b/server/db/providers/mongodb/verification_requests.go @@ -5,6 +5,7 @@ import ( "time" "github.com/authorizerdev/authorizer/server/db/models" + "github.com/authorizerdev/authorizer/server/graph/model" "github.com/google/uuid" "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/mongo/options" @@ -56,13 +57,24 @@ func (p *provider) GetVerificationRequestByEmail(email string, identifier string } // ListVerificationRequests to get list of verification requests from database -func (p *provider) ListVerificationRequests() ([]models.VerificationRequest, error) { - var verificationRequests []models.VerificationRequest +func (p *provider) ListVerificationRequests(pagination model.Pagination) (*model.VerificationRequests, error) { + var verificationRequests []*model.VerificationRequest + + opts := options.Find() + opts.SetLimit(pagination.Limit) + opts.SetSkip(pagination.Offset) + opts.SetSort(bson.M{"created_at": -1}) + verificationRequestCollection := p.db.Collection(models.Collections.VerificationRequest, options.Collection()) - cursor, err := verificationRequestCollection.Find(nil, bson.M{}, options.Find()) + + verificationRequestCollectionCount, err := verificationRequestCollection.CountDocuments(nil, bson.M{}) + paginationClone := pagination + paginationClone.Total = verificationRequestCollectionCount + + cursor, err := verificationRequestCollection.Find(nil, bson.M{}, opts) if err != nil { log.Println("error getting verification requests:", err) - return verificationRequests, err + return nil, err } defer cursor.Close(nil) @@ -70,12 +82,15 @@ func (p *provider) ListVerificationRequests() ([]models.VerificationRequest, err var verificationRequest models.VerificationRequest err := cursor.Decode(&verificationRequest) if err != nil { - return verificationRequests, err + return nil, err } - verificationRequests = append(verificationRequests, verificationRequest) + verificationRequests = append(verificationRequests, verificationRequest.AsAPIVerificationRequest()) } - return verificationRequests, nil + return &model.VerificationRequests{ + VerificationRequests: verificationRequests, + Pagination: &paginationClone, + }, nil } // DeleteVerificationRequest to delete verification request from database diff --git a/server/db/providers/providers.go b/server/db/providers/providers.go index da4e5f7..aa69c66 100644 --- a/server/db/providers/providers.go +++ b/server/db/providers/providers.go @@ -1,6 +1,9 @@ package providers -import "github.com/authorizerdev/authorizer/server/db/models" +import ( + "github.com/authorizerdev/authorizer/server/db/models" + "github.com/authorizerdev/authorizer/server/graph/model" +) type Provider interface { // AddUser to save user information in database @@ -10,7 +13,7 @@ type Provider interface { // DeleteUser to delete user information from database DeleteUser(user models.User) error // ListUsers to get list of users from database - ListUsers() ([]models.User, error) + ListUsers(pagination model.Pagination) (*model.Users, error) // GetUserByEmail to get user information from database using email address GetUserByEmail(email string) (models.User, error) // GetUserByID to get user information from database using user ID @@ -23,7 +26,7 @@ type Provider interface { // GetVerificationRequestByEmail to get verification request by email from database GetVerificationRequestByEmail(email string, identifier string) (models.VerificationRequest, error) // ListVerificationRequests to get list of verification requests from database - ListVerificationRequests() ([]models.VerificationRequest, error) + ListVerificationRequests(pagination model.Pagination) (*model.VerificationRequests, error) // DeleteVerificationRequest to delete verification request from database DeleteVerificationRequest(verificationRequest models.VerificationRequest) error diff --git a/server/db/providers/sql/user.go b/server/db/providers/sql/user.go index ad91b59..85c1d54 100644 --- a/server/db/providers/sql/user.go +++ b/server/db/providers/sql/user.go @@ -8,6 +8,7 @@ import ( "github.com/authorizerdev/authorizer/server/constants" "github.com/authorizerdev/authorizer/server/db/models" "github.com/authorizerdev/authorizer/server/envstore" + "github.com/authorizerdev/authorizer/server/graph/model" "github.com/google/uuid" "gorm.io/gorm/clause" ) @@ -64,15 +65,32 @@ func (p *provider) DeleteUser(user models.User) error { } // ListUsers to get list of users from database -func (p *provider) ListUsers() ([]models.User, error) { +func (p *provider) ListUsers(pagination model.Pagination) (*model.Users, error) { var users []models.User - result := p.db.Find(&users) + result := p.db.Limit(int(pagination.Limit)).Offset(int(pagination.Offset)).Order("created_at DESC").Find(&users) if result.Error != nil { log.Println("error getting users:", result.Error) - return users, result.Error + return nil, result.Error } - return users, nil + responseUsers := []*model.User{} + for _, user := range users { + responseUsers = append(responseUsers, user.AsAPIUser()) + } + + var total int64 + totalRes := p.db.Model(&models.User{}).Count(&total) + if totalRes.Error != nil { + return nil, totalRes.Error + } + + paginationClone := pagination + paginationClone.Total = total + + return &model.Users{ + Pagination: &paginationClone, + Users: responseUsers, + }, nil } // GetUserByEmail to get user information from database using email address diff --git a/server/db/providers/sql/verification_requests.go b/server/db/providers/sql/verification_requests.go index df21c7c..ba1d73b 100644 --- a/server/db/providers/sql/verification_requests.go +++ b/server/db/providers/sql/verification_requests.go @@ -4,6 +4,7 @@ import ( "log" "github.com/authorizerdev/authorizer/server/db/models" + "github.com/authorizerdev/authorizer/server/graph/model" "github.com/google/uuid" "gorm.io/gorm/clause" ) @@ -56,15 +57,33 @@ func (p *provider) GetVerificationRequestByEmail(email string, identifier string } // ListVerificationRequests to get list of verification requests from database -func (p *provider) ListVerificationRequests() ([]models.VerificationRequest, error) { +func (p *provider) ListVerificationRequests(pagination model.Pagination) (*model.VerificationRequests, error) { var verificationRequests []models.VerificationRequest - result := p.db.Find(&verificationRequests) + result := p.db.Limit(int(pagination.Limit)).Offset(int(pagination.Offset)).Order("created_at DESC").Find(&verificationRequests) if result.Error != nil { log.Println("error getting verification requests:", result.Error) - return verificationRequests, result.Error + return nil, result.Error } - return verificationRequests, nil + + responseVerificationRequests := []*model.VerificationRequest{} + for _, v := range verificationRequests { + responseVerificationRequests = append(responseVerificationRequests, v.AsAPIVerificationRequest()) + } + + var total int64 + totalRes := p.db.Model(&models.VerificationRequest{}).Count(&total) + if totalRes.Error != nil { + return nil, totalRes.Error + } + + paginationClone := pagination + paginationClone.Total = total + + return &model.VerificationRequests{ + VerificationRequests: responseVerificationRequests, + Pagination: &paginationClone, + }, nil } // DeleteVerificationRequest to delete verification request from database diff --git a/server/graph/generated/generated.go b/server/graph/generated/generated.go index 1db245a..e159ec6 100644 --- a/server/graph/generated/generated.go +++ b/server/graph/generated/generated.go @@ -120,6 +120,13 @@ type ComplexityRoot struct { VerifyEmail func(childComplexity int, params model.VerifyEmailInput) int } + Pagination struct { + Limit func(childComplexity int) int + Offset func(childComplexity int) int + Page func(childComplexity int) int + Total func(childComplexity int) int + } + Query struct { AdminSession func(childComplexity int) int Env func(childComplexity int) int @@ -127,8 +134,8 @@ type ComplexityRoot struct { Meta func(childComplexity int) int Profile func(childComplexity int) int Session func(childComplexity int, params *model.SessionQueryInput) int - Users func(childComplexity int) int - VerificationRequests func(childComplexity int) int + Users func(childComplexity int, params *model.PaginatedInput) int + VerificationRequests func(childComplexity int, params *model.PaginatedInput) int } Response struct { @@ -155,6 +162,11 @@ type ComplexityRoot struct { UpdatedAt func(childComplexity int) int } + Users struct { + Pagination func(childComplexity int) int + Users func(childComplexity int) int + } + ValidJWTResponse struct { Message func(childComplexity int) int Valid func(childComplexity int) int @@ -169,6 +181,11 @@ type ComplexityRoot struct { Token func(childComplexity int) int UpdatedAt func(childComplexity int) int } + + VerificationRequests struct { + Pagination func(childComplexity int) int + VerificationRequests func(childComplexity int) int + } } type MutationResolver interface { @@ -193,8 +210,8 @@ type QueryResolver interface { Session(ctx context.Context, params *model.SessionQueryInput) (*model.AuthResponse, error) IsValidJwt(ctx context.Context, params *model.IsValidJWTQueryInput) (*model.ValidJWTResponse, error) Profile(ctx context.Context) (*model.User, error) - Users(ctx context.Context) ([]*model.User, error) - VerificationRequests(ctx context.Context) ([]*model.VerificationRequest, error) + Users(ctx context.Context, params *model.PaginatedInput) (*model.Users, error) + VerificationRequests(ctx context.Context, params *model.PaginatedInput) (*model.VerificationRequests, error) AdminSession(ctx context.Context) (*model.Response, error) Env(ctx context.Context) (*model.Env, error) } @@ -713,6 +730,34 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Mutation.VerifyEmail(childComplexity, args["params"].(model.VerifyEmailInput)), true + case "Pagination.limit": + if e.complexity.Pagination.Limit == nil { + break + } + + return e.complexity.Pagination.Limit(childComplexity), true + + case "Pagination.offset": + if e.complexity.Pagination.Offset == nil { + break + } + + return e.complexity.Pagination.Offset(childComplexity), true + + case "Pagination.page": + if e.complexity.Pagination.Page == nil { + break + } + + return e.complexity.Pagination.Page(childComplexity), true + + case "Pagination.total": + if e.complexity.Pagination.Total == nil { + break + } + + return e.complexity.Pagination.Total(childComplexity), true + case "Query._admin_session": if e.complexity.Query.AdminSession == nil { break @@ -770,14 +815,24 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in break } - return e.complexity.Query.Users(childComplexity), true + args, err := ec.field_Query__users_args(context.TODO(), rawArgs) + if err != nil { + return 0, false + } + + return e.complexity.Query.Users(childComplexity, args["params"].(*model.PaginatedInput)), true case "Query._verification_requests": if e.complexity.Query.VerificationRequests == nil { break } - return e.complexity.Query.VerificationRequests(childComplexity), true + args, err := ec.field_Query__verification_requests_args(context.TODO(), rawArgs) + if err != nil { + return 0, false + } + + return e.complexity.Query.VerificationRequests(childComplexity, args["params"].(*model.PaginatedInput)), true case "Response.message": if e.complexity.Response.Message == nil { @@ -905,6 +960,20 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.User.UpdatedAt(childComplexity), true + case "Users.pagination": + if e.complexity.Users.Pagination == nil { + break + } + + return e.complexity.Users.Pagination(childComplexity), true + + case "Users.users": + if e.complexity.Users.Users == nil { + break + } + + return e.complexity.Users.Users(childComplexity), true + case "ValidJWTResponse.message": if e.complexity.ValidJWTResponse.Message == nil { break @@ -968,6 +1037,20 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.VerificationRequest.UpdatedAt(childComplexity), true + case "VerificationRequests.pagination": + if e.complexity.VerificationRequests.Pagination == nil { + break + } + + return e.complexity.VerificationRequests.Pagination(childComplexity), true + + case "VerificationRequests.verification_requests": + if e.complexity.VerificationRequests.VerificationRequests == nil { + break + } + + return e.complexity.VerificationRequests.VerificationRequests(childComplexity), true + } return 0, false } @@ -1039,6 +1122,13 @@ scalar Int64 scalar Map scalar Any +type Pagination { + limit: Int64! + page: Int64! + offset: Int64! + total: Int64! +} + type Meta { version: String! is_google_login_enabled: Boolean! @@ -1070,6 +1160,11 @@ type User { updated_at: Int64 } +type Users { + pagination: Pagination! + users: [User!]! +} + type VerificationRequest { id: ID! identifier: String @@ -1080,6 +1175,11 @@ type VerificationRequest { updated_at: Int64 } +type VerificationRequests { + pagination: Pagination! + verification_requests: [VerificationRequest!]! +} + type Error { message: String! reason: String! @@ -1269,6 +1369,15 @@ input IsValidJWTQueryInput { roles: [String!] } +input PaginationInput { + limit: Int64 + page: Int64 +} + +input PaginatedInput { + pagination: PaginationInput +} + type Mutation { signup(params: SignUpInput!): AuthResponse! login(params: LoginInput!): AuthResponse! @@ -1294,8 +1403,8 @@ type Query { is_valid_jwt(params: IsValidJWTQueryInput): ValidJWTResponse! profile: User! # admin only apis - _users: [User!]! - _verification_requests: [VerificationRequest!]! + _users(params: PaginatedInput): Users! + _verification_requests(params: PaginatedInput): VerificationRequests! _admin_session: Response! _env: Env! } @@ -1517,6 +1626,36 @@ func (ec *executionContext) field_Query___type_args(ctx context.Context, rawArgs return args, nil } +func (ec *executionContext) field_Query__users_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { + var err error + args := map[string]interface{}{} + var arg0 *model.PaginatedInput + if tmp, ok := rawArgs["params"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("params")) + arg0, err = ec.unmarshalOPaginatedInput2ᚖgithubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐPaginatedInput(ctx, tmp) + if err != nil { + return nil, err + } + } + args["params"] = arg0 + return args, nil +} + +func (ec *executionContext) field_Query__verification_requests_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { + var err error + args := map[string]interface{}{} + var arg0 *model.PaginatedInput + if tmp, ok := rawArgs["params"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("params")) + arg0, err = ec.unmarshalOPaginatedInput2ᚖgithubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐPaginatedInput(ctx, tmp) + if err != nil { + return nil, err + } + } + args["params"] = arg0 + return args, nil +} + func (ec *executionContext) field_Query_is_valid_jwt_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { var err error args := map[string]interface{}{} @@ -3735,6 +3874,146 @@ func (ec *executionContext) _Mutation__update_env(ctx context.Context, field gra return ec.marshalNResponse2ᚖgithubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐResponse(ctx, field.Selections, res) } +func (ec *executionContext) _Pagination_limit(ctx context.Context, field graphql.CollectedField, obj *model.Pagination) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "Pagination", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Limit, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(int64) + fc.Result = res + return ec.marshalNInt642int64(ctx, field.Selections, res) +} + +func (ec *executionContext) _Pagination_page(ctx context.Context, field graphql.CollectedField, obj *model.Pagination) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "Pagination", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Page, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(int64) + fc.Result = res + return ec.marshalNInt642int64(ctx, field.Selections, res) +} + +func (ec *executionContext) _Pagination_offset(ctx context.Context, field graphql.CollectedField, obj *model.Pagination) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "Pagination", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Offset, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(int64) + fc.Result = res + return ec.marshalNInt642int64(ctx, field.Selections, res) +} + +func (ec *executionContext) _Pagination_total(ctx context.Context, field graphql.CollectedField, obj *model.Pagination) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "Pagination", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Total, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(int64) + fc.Result = res + return ec.marshalNInt642int64(ctx, field.Selections, res) +} + func (ec *executionContext) _Query_meta(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { @@ -3905,9 +4184,16 @@ func (ec *executionContext) _Query__users(ctx context.Context, field graphql.Col } ctx = graphql.WithFieldContext(ctx, fc) + rawArgs := field.ArgumentMap(ec.Variables) + args, err := ec.field_Query__users_args(ctx, rawArgs) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + fc.Args = args resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().Users(rctx) + return ec.resolvers.Query().Users(rctx, args["params"].(*model.PaginatedInput)) }) if err != nil { ec.Error(ctx, err) @@ -3919,9 +4205,9 @@ func (ec *executionContext) _Query__users(ctx context.Context, field graphql.Col } return graphql.Null } - res := resTmp.([]*model.User) + res := resTmp.(*model.Users) fc.Result = res - return ec.marshalNUser2ᚕᚖgithubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐUserᚄ(ctx, field.Selections, res) + return ec.marshalNUsers2ᚖgithubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐUsers(ctx, field.Selections, res) } func (ec *executionContext) _Query__verification_requests(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { @@ -3940,9 +4226,16 @@ func (ec *executionContext) _Query__verification_requests(ctx context.Context, f } ctx = graphql.WithFieldContext(ctx, fc) + rawArgs := field.ArgumentMap(ec.Variables) + args, err := ec.field_Query__verification_requests_args(ctx, rawArgs) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + fc.Args = args resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().VerificationRequests(rctx) + return ec.resolvers.Query().VerificationRequests(rctx, args["params"].(*model.PaginatedInput)) }) if err != nil { ec.Error(ctx, err) @@ -3954,9 +4247,9 @@ func (ec *executionContext) _Query__verification_requests(ctx context.Context, f } return graphql.Null } - res := resTmp.([]*model.VerificationRequest) + res := resTmp.(*model.VerificationRequests) fc.Result = res - return ec.marshalNVerificationRequest2ᚕᚖgithubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐVerificationRequestᚄ(ctx, field.Selections, res) + return ec.marshalNVerificationRequests2ᚖgithubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐVerificationRequests(ctx, field.Selections, res) } func (ec *executionContext) _Query__admin_session(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { @@ -4694,6 +4987,76 @@ func (ec *executionContext) _User_updated_at(ctx context.Context, field graphql. return ec.marshalOInt642ᚖint64(ctx, field.Selections, res) } +func (ec *executionContext) _Users_pagination(ctx context.Context, field graphql.CollectedField, obj *model.Users) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "Users", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Pagination, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(*model.Pagination) + fc.Result = res + return ec.marshalNPagination2ᚖgithubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐPagination(ctx, field.Selections, res) +} + +func (ec *executionContext) _Users_users(ctx context.Context, field graphql.CollectedField, obj *model.Users) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "Users", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Users, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.([]*model.User) + fc.Result = res + return ec.marshalNUser2ᚕᚖgithubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐUserᚄ(ctx, field.Selections, res) +} + func (ec *executionContext) _ValidJWTResponse_valid(ctx context.Context, field graphql.CollectedField, obj *model.ValidJWTResponse) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { @@ -4991,6 +5354,76 @@ func (ec *executionContext) _VerificationRequest_updated_at(ctx context.Context, return ec.marshalOInt642ᚖint64(ctx, field.Selections, res) } +func (ec *executionContext) _VerificationRequests_pagination(ctx context.Context, field graphql.CollectedField, obj *model.VerificationRequests) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "VerificationRequests", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Pagination, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(*model.Pagination) + fc.Result = res + return ec.marshalNPagination2ᚖgithubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐPagination(ctx, field.Selections, res) +} + +func (ec *executionContext) _VerificationRequests_verification_requests(ctx context.Context, field graphql.CollectedField, obj *model.VerificationRequests) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "VerificationRequests", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.VerificationRequests, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.([]*model.VerificationRequest) + fc.Result = res + return ec.marshalNVerificationRequest2ᚕᚖgithubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐVerificationRequestᚄ(ctx, field.Selections, res) +} + func (ec *executionContext) ___Directive_name(ctx context.Context, field graphql.CollectedField, obj *introspection.Directive) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { @@ -6306,6 +6739,60 @@ func (ec *executionContext) unmarshalInputMagicLinkLoginInput(ctx context.Contex return it, nil } +func (ec *executionContext) unmarshalInputPaginatedInput(ctx context.Context, obj interface{}) (model.PaginatedInput, error) { + var it model.PaginatedInput + asMap := map[string]interface{}{} + for k, v := range obj.(map[string]interface{}) { + asMap[k] = v + } + + for k, v := range asMap { + switch k { + case "pagination": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("pagination")) + it.Pagination, err = ec.unmarshalOPaginationInput2ᚖgithubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐPaginationInput(ctx, v) + if err != nil { + return it, err + } + } + } + + return it, nil +} + +func (ec *executionContext) unmarshalInputPaginationInput(ctx context.Context, obj interface{}) (model.PaginationInput, error) { + var it model.PaginationInput + asMap := map[string]interface{}{} + for k, v := range obj.(map[string]interface{}) { + asMap[k] = v + } + + for k, v := range asMap { + switch k { + case "limit": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("limit")) + it.Limit, err = ec.unmarshalOInt642ᚖint64(ctx, v) + if err != nil { + return it, err + } + case "page": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("page")) + it.Page, err = ec.unmarshalOInt642ᚖint64(ctx, v) + if err != nil { + return it, err + } + } + } + + return it, nil +} + func (ec *executionContext) unmarshalInputResendVerifyEmailInput(ctx context.Context, obj interface{}) (model.ResendVerifyEmailInput, error) { var it model.ResendVerifyEmailInput asMap := map[string]interface{}{} @@ -7347,6 +7834,48 @@ func (ec *executionContext) _Mutation(ctx context.Context, sel ast.SelectionSet) return out } +var paginationImplementors = []string{"Pagination"} + +func (ec *executionContext) _Pagination(ctx context.Context, sel ast.SelectionSet, obj *model.Pagination) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, paginationImplementors) + + out := graphql.NewFieldSet(fields) + var invalids uint32 + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("Pagination") + case "limit": + out.Values[i] = ec._Pagination_limit(ctx, field, obj) + if out.Values[i] == graphql.Null { + invalids++ + } + case "page": + out.Values[i] = ec._Pagination_page(ctx, field, obj) + if out.Values[i] == graphql.Null { + invalids++ + } + case "offset": + out.Values[i] = ec._Pagination_offset(ctx, field, obj) + if out.Values[i] == graphql.Null { + invalids++ + } + case "total": + out.Values[i] = ec._Pagination_total(ctx, field, obj) + if out.Values[i] == graphql.Null { + invalids++ + } + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch() + if invalids > 0 { + return graphql.Null + } + return out +} + var queryImplementors = []string{"Query"} func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) graphql.Marshaler { @@ -7587,6 +8116,38 @@ func (ec *executionContext) _User(ctx context.Context, sel ast.SelectionSet, obj return out } +var usersImplementors = []string{"Users"} + +func (ec *executionContext) _Users(ctx context.Context, sel ast.SelectionSet, obj *model.Users) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, usersImplementors) + + out := graphql.NewFieldSet(fields) + var invalids uint32 + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("Users") + case "pagination": + out.Values[i] = ec._Users_pagination(ctx, field, obj) + if out.Values[i] == graphql.Null { + invalids++ + } + case "users": + out.Values[i] = ec._Users_users(ctx, field, obj) + if out.Values[i] == graphql.Null { + invalids++ + } + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch() + if invalids > 0 { + return graphql.Null + } + return out +} + var validJWTResponseImplementors = []string{"ValidJWTResponse"} func (ec *executionContext) _ValidJWTResponse(ctx context.Context, sel ast.SelectionSet, obj *model.ValidJWTResponse) graphql.Marshaler { @@ -7658,6 +8219,38 @@ func (ec *executionContext) _VerificationRequest(ctx context.Context, sel ast.Se return out } +var verificationRequestsImplementors = []string{"VerificationRequests"} + +func (ec *executionContext) _VerificationRequests(ctx context.Context, sel ast.SelectionSet, obj *model.VerificationRequests) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, verificationRequestsImplementors) + + out := graphql.NewFieldSet(fields) + var invalids uint32 + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("VerificationRequests") + case "pagination": + out.Values[i] = ec._VerificationRequests_pagination(ctx, field, obj) + if out.Values[i] == graphql.Null { + invalids++ + } + case "verification_requests": + out.Values[i] = ec._VerificationRequests_verification_requests(ctx, field, obj) + if out.Values[i] == graphql.Null { + invalids++ + } + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch() + if invalids > 0 { + return graphql.Null + } + return out +} + var __DirectiveImplementors = []string{"__Directive"} func (ec *executionContext) ___Directive(ctx context.Context, sel ast.SelectionSet, obj *introspection.Directive) graphql.Marshaler { @@ -7986,6 +8579,21 @@ func (ec *executionContext) marshalNID2string(ctx context.Context, sel ast.Selec return res } +func (ec *executionContext) unmarshalNInt642int64(ctx context.Context, v interface{}) (int64, error) { + res, err := graphql.UnmarshalInt64(v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalNInt642int64(ctx context.Context, sel ast.SelectionSet, v int64) graphql.Marshaler { + res := graphql.MarshalInt64(v) + if res == graphql.Null { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "must not be null") + } + } + return res +} + func (ec *executionContext) unmarshalNLoginInput2githubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐLoginInput(ctx context.Context, v interface{}) (model.LoginInput, error) { res, err := ec.unmarshalInputLoginInput(ctx, v) return res, graphql.ErrorOnPath(ctx, err) @@ -8010,6 +8618,16 @@ func (ec *executionContext) marshalNMeta2ᚖgithubᚗcomᚋauthorizerdevᚋautho return ec._Meta(ctx, sel, v) } +func (ec *executionContext) marshalNPagination2ᚖgithubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐPagination(ctx context.Context, sel ast.SelectionSet, v *model.Pagination) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + return ec._Pagination(ctx, sel, v) +} + func (ec *executionContext) unmarshalNResendVerifyEmailInput2githubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐResendVerifyEmailInput(ctx context.Context, v interface{}) (model.ResendVerifyEmailInput, error) { res, err := ec.unmarshalInputResendVerifyEmailInput(ctx, v) return res, graphql.ErrorOnPath(ctx, err) @@ -8163,6 +8781,20 @@ func (ec *executionContext) marshalNUser2ᚖgithubᚗcomᚋauthorizerdevᚋautho return ec._User(ctx, sel, v) } +func (ec *executionContext) marshalNUsers2githubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐUsers(ctx context.Context, sel ast.SelectionSet, v model.Users) graphql.Marshaler { + return ec._Users(ctx, sel, &v) +} + +func (ec *executionContext) marshalNUsers2ᚖgithubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐUsers(ctx context.Context, sel ast.SelectionSet, v *model.Users) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + return ec._Users(ctx, sel, v) +} + func (ec *executionContext) marshalNValidJWTResponse2githubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐValidJWTResponse(ctx context.Context, sel ast.SelectionSet, v model.ValidJWTResponse) graphql.Marshaler { return ec._ValidJWTResponse(ctx, sel, &v) } @@ -8231,6 +8863,20 @@ func (ec *executionContext) marshalNVerificationRequest2ᚖgithubᚗcomᚋauthor return ec._VerificationRequest(ctx, sel, v) } +func (ec *executionContext) marshalNVerificationRequests2githubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐVerificationRequests(ctx context.Context, sel ast.SelectionSet, v model.VerificationRequests) graphql.Marshaler { + return ec._VerificationRequests(ctx, sel, &v) +} + +func (ec *executionContext) marshalNVerificationRequests2ᚖgithubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐVerificationRequests(ctx context.Context, sel ast.SelectionSet, v *model.VerificationRequests) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + return ec._VerificationRequests(ctx, sel, v) +} + func (ec *executionContext) unmarshalNVerifyEmailInput2githubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐVerifyEmailInput(ctx context.Context, v interface{}) (model.VerifyEmailInput, error) { res, err := ec.unmarshalInputVerifyEmailInput(ctx, v) return res, graphql.ErrorOnPath(ctx, err) @@ -8540,6 +9186,22 @@ func (ec *executionContext) unmarshalOIsValidJWTQueryInput2ᚖgithubᚗcomᚋaut return &res, graphql.ErrorOnPath(ctx, err) } +func (ec *executionContext) unmarshalOPaginatedInput2ᚖgithubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐPaginatedInput(ctx context.Context, v interface{}) (*model.PaginatedInput, error) { + if v == nil { + return nil, nil + } + res, err := ec.unmarshalInputPaginatedInput(ctx, v) + return &res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) unmarshalOPaginationInput2ᚖgithubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐPaginationInput(ctx context.Context, v interface{}) (*model.PaginationInput, error) { + if v == nil { + return nil, nil + } + res, err := ec.unmarshalInputPaginationInput(ctx, v) + return &res, graphql.ErrorOnPath(ctx, err) +} + func (ec *executionContext) unmarshalOSessionQueryInput2ᚖgithubᚗcomᚋauthorizerdevᚋauthorizerᚋserverᚋgraphᚋmodelᚐSessionQueryInput(ctx context.Context, v interface{}) (*model.SessionQueryInput, error) { if v == nil { return nil, nil diff --git a/server/graph/model/models_gen.go b/server/graph/model/models_gen.go index abea8d3..0350d2a 100644 --- a/server/graph/model/models_gen.go +++ b/server/graph/model/models_gen.go @@ -93,6 +93,22 @@ type Meta struct { IsMagicLinkLoginEnabled bool `json:"is_magic_link_login_enabled"` } +type PaginatedInput struct { + Pagination *PaginationInput `json:"pagination"` +} + +type Pagination struct { + Limit int64 `json:"limit"` + Page int64 `json:"page"` + Offset int64 `json:"offset"` + Total int64 `json:"total"` +} + +type PaginationInput struct { + Limit *int64 `json:"limit"` + Page *int64 `json:"page"` +} + type ResendVerifyEmailInput struct { Email string `json:"email"` Identifier string `json:"identifier"` @@ -212,6 +228,11 @@ type User struct { UpdatedAt *int64 `json:"updated_at"` } +type Users struct { + Pagination *Pagination `json:"pagination"` + Users []*User `json:"users"` +} + type ValidJWTResponse struct { Valid bool `json:"valid"` Message string `json:"message"` @@ -227,6 +248,11 @@ type VerificationRequest struct { UpdatedAt *int64 `json:"updated_at"` } +type VerificationRequests struct { + Pagination *Pagination `json:"pagination"` + VerificationRequests []*VerificationRequest `json:"verification_requests"` +} + type VerifyEmailInput struct { Token string `json:"token"` } diff --git a/server/graph/schema.graphqls b/server/graph/schema.graphqls index 229c4b5..abb7979 100644 --- a/server/graph/schema.graphqls +++ b/server/graph/schema.graphqls @@ -5,6 +5,13 @@ scalar Int64 scalar Map scalar Any +type Pagination { + limit: Int64! + page: Int64! + offset: Int64! + total: Int64! +} + type Meta { version: String! is_google_login_enabled: Boolean! @@ -36,6 +43,11 @@ type User { updated_at: Int64 } +type Users { + pagination: Pagination! + users: [User!]! +} + type VerificationRequest { id: ID! identifier: String @@ -46,6 +58,11 @@ type VerificationRequest { updated_at: Int64 } +type VerificationRequests { + pagination: Pagination! + verification_requests: [VerificationRequest!]! +} + type Error { message: String! reason: String! @@ -235,6 +252,15 @@ input IsValidJWTQueryInput { roles: [String!] } +input PaginationInput { + limit: Int64 + page: Int64 +} + +input PaginatedInput { + pagination: PaginationInput +} + type Mutation { signup(params: SignUpInput!): AuthResponse! login(params: LoginInput!): AuthResponse! @@ -260,8 +286,8 @@ type Query { is_valid_jwt(params: IsValidJWTQueryInput): ValidJWTResponse! profile: User! # admin only apis - _users: [User!]! - _verification_requests: [VerificationRequest!]! + _users(params: PaginatedInput): Users! + _verification_requests(params: PaginatedInput): VerificationRequests! _admin_session: Response! _env: Env! } diff --git a/server/graph/schema.resolvers.go b/server/graph/schema.resolvers.go index b06e51d..e3cd241 100644 --- a/server/graph/schema.resolvers.go +++ b/server/graph/schema.resolvers.go @@ -87,12 +87,12 @@ func (r *queryResolver) Profile(ctx context.Context) (*model.User, error) { return resolvers.ProfileResolver(ctx) } -func (r *queryResolver) Users(ctx context.Context) ([]*model.User, error) { - return resolvers.UsersResolver(ctx) +func (r *queryResolver) Users(ctx context.Context, params *model.PaginatedInput) (*model.Users, error) { + return resolvers.UsersResolver(ctx, params) } -func (r *queryResolver) VerificationRequests(ctx context.Context) ([]*model.VerificationRequest, error) { - return resolvers.VerificationRequestsResolver(ctx) +func (r *queryResolver) VerificationRequests(ctx context.Context, params *model.PaginatedInput) (*model.VerificationRequests, error) { + return resolvers.VerificationRequestsResolver(ctx, params) } func (r *queryResolver) AdminSession(ctx context.Context) (*model.Response, error) { diff --git a/server/resolvers/users.go b/server/resolvers/users.go index 0b84f85..987f4bb 100644 --- a/server/resolvers/users.go +++ b/server/resolvers/users.go @@ -12,24 +12,21 @@ import ( // UsersResolver is a resolver for users query // This is admin only query -func UsersResolver(ctx context.Context) ([]*model.User, error) { +func UsersResolver(ctx context.Context, params *model.PaginatedInput) (*model.Users, error) { gc, err := utils.GinContextFromContext(ctx) - var res []*model.User if err != nil { - return res, err + return nil, err } if !token.IsSuperAdmin(gc) { - return res, fmt.Errorf("unauthorized") + return nil, fmt.Errorf("unauthorized") } - users, err := db.Provider.ListUsers() + pagination := utils.GetPagination(params) + + res, err := db.Provider.ListUsers(pagination) if err != nil { - return res, err - } - - for i := 0; i < len(users); i++ { - res = append(res, users[i].AsAPIUser()) + return nil, err } return res, nil diff --git a/server/resolvers/verification_requests.go b/server/resolvers/verification_requests.go index e7a2af3..ff5420d 100644 --- a/server/resolvers/verification_requests.go +++ b/server/resolvers/verification_requests.go @@ -12,32 +12,21 @@ import ( // VerificationRequestsResolver is a resolver for verification requests query // This is admin only query -func VerificationRequestsResolver(ctx context.Context) ([]*model.VerificationRequest, error) { +func VerificationRequestsResolver(ctx context.Context, params *model.PaginatedInput) (*model.VerificationRequests, error) { gc, err := utils.GinContextFromContext(ctx) - var res []*model.VerificationRequest if err != nil { - return res, err + return nil, err } if !token.IsSuperAdmin(gc) { - return res, fmt.Errorf("unauthorized") + return nil, fmt.Errorf("unauthorized") } - verificationRequests, err := db.Provider.ListVerificationRequests() + pagination := utils.GetPagination(params) + + res, err := db.Provider.ListVerificationRequests(pagination) if err != nil { - return res, err - } - - for i := 0; i < len(verificationRequests); i++ { - res = append(res, &model.VerificationRequest{ - ID: fmt.Sprintf("%v", verificationRequests[i].ID), - Email: &verificationRequests[i].Email, - Token: &verificationRequests[i].Token, - Identifier: &verificationRequests[i].Identifier, - Expires: &verificationRequests[i].ExpiresAt, - CreatedAt: &verificationRequests[i].CreatedAt, - UpdatedAt: &verificationRequests[i].UpdatedAt, - }) + return nil, err } return res, nil diff --git a/server/test/resolvers_test.go b/server/test/resolvers_test.go index 8ef351a..99ed69a 100644 --- a/server/test/resolvers_test.go +++ b/server/test/resolvers_test.go @@ -11,9 +11,9 @@ import ( func TestResolvers(t *testing.T) { databases := map[string]string{ - constants.DbTypeSqlite: "../../data.db", - // constants.DbTypeArangodb: "http://localhost:8529", - // constants.DbTypeMongodb: "mongodb://localhost:27017", + constants.DbTypeSqlite: "../../data.db", + constants.DbTypeArangodb: "http://localhost:8529", + constants.DbTypeMongodb: "mongodb://localhost:27017", } envstore.EnvInMemoryStoreObj.UpdateEnvVariable(constants.StringStoreIdentifier, constants.EnvKeyVersion, "test") for dbType, dbURL := range databases { diff --git a/server/test/users_test.go b/server/test/users_test.go index 437effb..0dc6e8e 100644 --- a/server/test/users_test.go +++ b/server/test/users_test.go @@ -2,6 +2,7 @@ package test import ( "fmt" + "log" "testing" "github.com/authorizerdev/authorizer/server/constants" @@ -23,15 +24,26 @@ func usersTest(t *testing.T, s TestSetup) { ConfirmPassword: s.TestInfo.Password, }) - users, err := resolvers.UsersResolver(ctx) + limit := int64(10) + page := int64(1) + pagination := &model.PaginatedInput{ + Pagination: &model.PaginationInput{ + Limit: &limit, + Page: &page, + }, + } + + usersRes, err := resolvers.UsersResolver(ctx, pagination) assert.NotNil(t, err, "unauthorized") h, err := utils.EncryptPassword(envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyAdminSecret)) assert.Nil(t, err) req.Header.Set("Cookie", fmt.Sprintf("%s=%s", envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyAdminCookieName), h)) - users, err = resolvers.UsersResolver(ctx) + + usersRes, err = resolvers.UsersResolver(ctx, pagination) assert.Nil(t, err) - rLen := len(users) + log.Println("=> userRes:", usersRes) + rLen := len(usersRes.Users) assert.GreaterOrEqual(t, rLen, 1) cleanData(email) diff --git a/server/test/verification_requests_test.go b/server/test/verification_requests_test.go index f434539..0374e3c 100644 --- a/server/test/verification_requests_test.go +++ b/server/test/verification_requests_test.go @@ -25,16 +25,26 @@ func verificationRequestsTest(t *testing.T, s TestSetup) { ConfirmPassword: s.TestInfo.Password, }) - requests, err := resolvers.VerificationRequestsResolver(ctx) + limit := int64(10) + page := int64(1) + pagination := &model.PaginatedInput{ + Pagination: &model.PaginationInput{ + Limit: &limit, + Page: &page, + }, + } + + requests, err := resolvers.VerificationRequestsResolver(ctx, pagination) assert.NotNil(t, err, "unauthorized") h, err := utils.EncryptPassword(envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyAdminSecret)) assert.Nil(t, err) req.Header.Set("Cookie", fmt.Sprintf("%s=%s", envstore.EnvInMemoryStoreObj.GetStringStoreEnvVariable(constants.EnvKeyAdminCookieName), h)) - requests, err = resolvers.VerificationRequestsResolver(ctx) + requests, err = resolvers.VerificationRequestsResolver(ctx, pagination) assert.Nil(t, err) - rLen := len(requests) + + rLen := len(requests.VerificationRequests) assert.GreaterOrEqual(t, rLen, 1) cleanData(email) diff --git a/server/utils/pagination.go b/server/utils/pagination.go new file mode 100644 index 0000000..e27eb53 --- /dev/null +++ b/server/utils/pagination.go @@ -0,0 +1,29 @@ +package utils + +import ( + "github.com/authorizerdev/authorizer/server/constants" + "github.com/authorizerdev/authorizer/server/graph/model" +) + +// GetPagination helps getting pagination data from paginated input +// also returns default limit and offset if pagination data is not present +func GetPagination(paginatedInput *model.PaginatedInput) model.Pagination { + limit := int64(constants.DefaultLimit) + page := int64(1) + + if paginatedInput != nil && paginatedInput.Pagination != nil { + if paginatedInput.Pagination.Limit != nil { + limit = *paginatedInput.Pagination.Limit + } + + if paginatedInput.Pagination.Page != nil { + page = *paginatedInput.Pagination.Page + } + } + + return model.Pagination{ + Limit: limit, + Offset: (page - 1) * limit, + Page: page, + } +}