From c8754872040dd21d20708619a88c4ab2067390ad Mon Sep 17 00:00:00 2001 From: Sarah Funkhouser <147884153+golanglemonade@users.noreply.github.com> Date: Tue, 10 Dec 2024 09:06:49 -0700 Subject: [PATCH] feat: create program members with program (#300) * feat: create program memmbers with program Signed-off-by: Sarah Funkhouser <147884153+golanglemonade@users.noreply.github.com> * remove extra return def Signed-off-by: Sarah Funkhouser <147884153+golanglemonade@users.noreply.github.com> * fix idents Signed-off-by: Sarah Funkhouser <147884153+golanglemonade@users.noreply.github.com> * generate Signed-off-by: Sarah Funkhouser <147884153+golanglemonade@users.noreply.github.com> --------- Signed-off-by: Sarah Funkhouser <147884153+golanglemonade@users.noreply.github.com> --- internal/ent/interceptors/user.go | 1 + internal/graphapi/gen_models.go | 11 + internal/graphapi/gen_server.go | 234 ++++++++++++++++++ .../graphapi/programextended.resolvers.go | 36 +++ internal/graphapi/programextended_test.go | 68 +++++ pkg/openlaneclient/graphclient.go | 127 ++++++++++ pkg/openlaneclient/models.go | 10 + query/program.graphql | 17 ++ schema.graphql | 17 ++ schema/programextended.graphql | 22 ++ 10 files changed, 543 insertions(+) create mode 100644 internal/graphapi/programextended_test.go diff --git a/internal/ent/interceptors/user.go b/internal/ent/interceptors/user.go index 806e5187..160de915 100644 --- a/internal/ent/interceptors/user.go +++ b/internal/ent/interceptors/user.go @@ -68,6 +68,7 @@ func filterType(ctx context.Context) string { "updateGroupMembership", "createProgramMembership", "updateProgramMembership", + "createProgramWithMembers", "createProgram", "updateProgram", "organization", diff --git a/internal/graphapi/gen_models.go b/internal/graphapi/gen_models.go index 8cad1c26..2072803b 100644 --- a/internal/graphapi/gen_models.go +++ b/internal/graphapi/gen_models.go @@ -7,6 +7,7 @@ import ( "entgo.io/contrib/entgql" "github.com/theopenlane/core/internal/ent/generated" + "github.com/theopenlane/core/pkg/enums" ) type SearchResult interface { @@ -201,6 +202,16 @@ type ControlUpdatePayload struct { Control *generated.Control `json:"control"` } +type CreateMemberWithProgramInput struct { + Role *enums.Role `json:"role,omitempty"` + UserID string `json:"userID"` +} + +type CreateProgramWithMembersInput struct { + Program *generated.CreateProgramInput `json:"program"` + Members []*CreateMemberWithProgramInput `json:"members,omitempty"` +} + // Return response for createBulkDocumentData mutation type DocumentDataBulkCreatePayload struct { // Created documentData diff --git a/internal/graphapi/gen_server.go b/internal/graphapi/gen_server.go index 07318190..fd79c98c 100644 --- a/internal/graphapi/gen_server.go +++ b/internal/graphapi/gen_server.go @@ -1942,6 +1942,7 @@ type ComplexityRoot struct { CreateProcedure func(childComplexity int, input generated.CreateProcedureInput) int CreateProgram func(childComplexity int, input generated.CreateProgramInput) int CreateProgramMembership func(childComplexity int, input generated.CreateProgramMembershipInput) int + CreateProgramWithMembers func(childComplexity int, input CreateProgramWithMembersInput) int CreateRisk func(childComplexity int, input generated.CreateRiskInput) int CreateStandard func(childComplexity int, input generated.CreateStandardInput) int CreateSubcontrol func(childComplexity int, input generated.CreateSubcontrolInput) int @@ -4201,6 +4202,7 @@ type MutationResolver interface { CreateBulkCSVProgram(ctx context.Context, input graphql.Upload) (*ProgramBulkCreatePayload, error) UpdateProgram(ctx context.Context, id string, input generated.UpdateProgramInput) (*ProgramUpdatePayload, error) DeleteProgram(ctx context.Context, id string) (*ProgramDeletePayload, error) + CreateProgramWithMembers(ctx context.Context, input CreateProgramWithMembersInput) (*ProgramCreatePayload, error) CreateProgramMembership(ctx context.Context, input generated.CreateProgramMembershipInput) (*ProgramMembershipCreatePayload, error) CreateBulkProgramMembership(ctx context.Context, input []*generated.CreateProgramMembershipInput) (*ProgramMembershipBulkCreatePayload, error) CreateBulkCSVProgramMembership(ctx context.Context, input graphql.Upload) (*ProgramMembershipBulkCreatePayload, error) @@ -13558,6 +13560,18 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Mutation.CreateProgramMembership(childComplexity, args["input"].(generated.CreateProgramMembershipInput)), true + case "Mutation.createProgramWithMembers": + if e.complexity.Mutation.CreateProgramWithMembers == nil { + break + } + + args, err := ec.field_Mutation_createProgramWithMembers_args(context.TODO(), rawArgs) + if err != nil { + return 0, false + } + + return e.complexity.Mutation.CreateProgramWithMembers(childComplexity, args["input"].(CreateProgramWithMembersInput)), true + case "Mutation.createRisk": if e.complexity.Mutation.CreateRisk == nil { break @@ -25107,6 +25121,7 @@ func (e *executableSchema) Exec(ctx context.Context) graphql.ResponseHandler { ec.unmarshalInputCreateIntegrationInput, ec.unmarshalInputCreateInternalPolicyInput, ec.unmarshalInputCreateInviteInput, + ec.unmarshalInputCreateMemberWithProgramInput, ec.unmarshalInputCreateNarrativeInput, ec.unmarshalInputCreateNoteInput, ec.unmarshalInputCreateOauthProviderInput, @@ -25119,6 +25134,7 @@ func (e *executableSchema) Exec(ctx context.Context) graphql.ResponseHandler { ec.unmarshalInputCreateProcedureInput, ec.unmarshalInputCreateProgramInput, ec.unmarshalInputCreateProgramMembershipInput, + ec.unmarshalInputCreateProgramWithMembersInput, ec.unmarshalInputCreateRiskInput, ec.unmarshalInputCreateStandardInput, ec.unmarshalInputCreateSubcontrolInput, @@ -62274,6 +62290,28 @@ type ProgramBulkCreatePayload { extend input ProgramMembershipWhereInput { programID: String userID: String +} + +input CreateProgramWithMembersInput{ + program: CreateProgramInput! + members: [CreateMemberWithProgramInput!] +} + +input CreateMemberWithProgramInput { + role: ProgramMembershipRole + userID: ID! +} + +extend type Mutation{ + """ + Create a new program with members + """ + createProgramWithMembers( + """ + values of the program + """ + input: CreateProgramWithMembersInput! + ): ProgramCreatePayload! }`, BuiltIn: false}, {Name: "../../schema/programmembership.graphql", Input: `extend type Query { """ @@ -67348,6 +67386,38 @@ func (ec *executionContext) field_Mutation_createProgramMembership_argsInput( return zeroVal, nil } +func (ec *executionContext) field_Mutation_createProgramWithMembers_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { + var err error + args := map[string]interface{}{} + arg0, err := ec.field_Mutation_createProgramWithMembers_argsInput(ctx, rawArgs) + if err != nil { + return nil, err + } + args["input"] = arg0 + return args, nil +} +func (ec *executionContext) field_Mutation_createProgramWithMembers_argsInput( + ctx context.Context, + rawArgs map[string]interface{}, +) (CreateProgramWithMembersInput, error) { + // We won't call the directive if the argument is null. + // Set call_argument_directives_with_null to true to call directives + // even if the argument is null. + _, ok := rawArgs["input"] + if !ok { + var zeroVal CreateProgramWithMembersInput + return zeroVal, nil + } + + ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("input")) + if tmp, ok := rawArgs["input"]; ok { + return ec.unmarshalNCreateProgramWithMembersInput2githubᚗcomᚋtheopenlaneᚋcoreᚋinternalᚋgraphapiᚐCreateProgramWithMembersInput(ctx, tmp) + } + + var zeroVal CreateProgramWithMembersInput + return zeroVal, nil +} + func (ec *executionContext) field_Mutation_createProgram_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { var err error args := map[string]interface{}{} @@ -159013,6 +159083,65 @@ func (ec *executionContext) fieldContext_Mutation_deleteProgram(ctx context.Cont return fc, nil } +func (ec *executionContext) _Mutation_createProgramWithMembers(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Mutation_createProgramWithMembers(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Mutation().CreateProgramWithMembers(rctx, fc.Args["input"].(CreateProgramWithMembersInput)) + }) + 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.(*ProgramCreatePayload) + fc.Result = res + return ec.marshalNProgramCreatePayload2ᚖgithubᚗcomᚋtheopenlaneᚋcoreᚋinternalᚋgraphapiᚐProgramCreatePayload(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Mutation_createProgramWithMembers(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Mutation", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "program": + return ec.fieldContext_ProgramCreatePayload_program(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type ProgramCreatePayload", field.Name) + }, + } + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + ec.Error(ctx, err) + } + }() + ctx = graphql.WithFieldContext(ctx, fc) + if fc.Args, err = ec.field_Mutation_createProgramWithMembers_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return fc, err + } + return fc, nil +} + func (ec *executionContext) _Mutation_createProgramMembership(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { fc, err := ec.fieldContext_Mutation_createProgramMembership(ctx, field) if err != nil { @@ -259853,6 +259982,40 @@ func (ec *executionContext) unmarshalInputCreateInviteInput(ctx context.Context, return it, nil } +func (ec *executionContext) unmarshalInputCreateMemberWithProgramInput(ctx context.Context, obj interface{}) (CreateMemberWithProgramInput, error) { + var it CreateMemberWithProgramInput + asMap := map[string]interface{}{} + for k, v := range obj.(map[string]interface{}) { + asMap[k] = v + } + + fieldsInOrder := [...]string{"role", "userID"} + for _, k := range fieldsInOrder { + v, ok := asMap[k] + if !ok { + continue + } + switch k { + case "role": + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("role")) + data, err := ec.unmarshalOProgramMembershipRole2ᚖgithubᚗcomᚋtheopenlaneᚋcoreᚋpkgᚋenumsᚐRole(ctx, v) + if err != nil { + return it, err + } + it.Role = data + case "userID": + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("userID")) + data, err := ec.unmarshalNID2string(ctx, v) + if err != nil { + return it, err + } + it.UserID = data + } + } + + return it, nil +} + func (ec *executionContext) unmarshalInputCreateNarrativeInput(ctx context.Context, obj interface{}) (generated.CreateNarrativeInput, error) { var it generated.CreateNarrativeInput asMap := map[string]interface{}{} @@ -261348,6 +261511,40 @@ func (ec *executionContext) unmarshalInputCreateProgramMembershipInput(ctx conte return it, nil } +func (ec *executionContext) unmarshalInputCreateProgramWithMembersInput(ctx context.Context, obj interface{}) (CreateProgramWithMembersInput, error) { + var it CreateProgramWithMembersInput + asMap := map[string]interface{}{} + for k, v := range obj.(map[string]interface{}) { + asMap[k] = v + } + + fieldsInOrder := [...]string{"program", "members"} + for _, k := range fieldsInOrder { + v, ok := asMap[k] + if !ok { + continue + } + switch k { + case "program": + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("program")) + data, err := ec.unmarshalNCreateProgramInput2ᚖgithubᚗcomᚋtheopenlaneᚋcoreᚋinternalᚋentᚋgeneratedᚐCreateProgramInput(ctx, v) + if err != nil { + return it, err + } + it.Program = data + case "members": + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("members")) + data, err := ec.unmarshalOCreateMemberWithProgramInput2ᚕᚖgithubᚗcomᚋtheopenlaneᚋcoreᚋinternalᚋgraphapiᚐCreateMemberWithProgramInputᚄ(ctx, v) + if err != nil { + return it, err + } + it.Members = data + } + } + + return it, nil +} + func (ec *executionContext) unmarshalInputCreateRiskInput(ctx context.Context, obj interface{}) (generated.CreateRiskInput, error) { var it generated.CreateRiskInput asMap := map[string]interface{}{} @@ -382877,6 +383074,13 @@ func (ec *executionContext) _Mutation(ctx context.Context, sel ast.SelectionSet) if out.Values[i] == graphql.Null { out.Invalids++ } + case "createProgramWithMembers": + out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) { + return ec._Mutation_createProgramWithMembers(ctx, field) + }) + if out.Values[i] == graphql.Null { + out.Invalids++ + } case "createProgramMembership": out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) { return ec._Mutation_createProgramMembership(ctx, field) @@ -404514,6 +404718,11 @@ func (ec *executionContext) unmarshalNCreateInviteInput2ᚖgithubᚗcomᚋtheope return &res, graphql.ErrorOnPath(ctx, err) } +func (ec *executionContext) unmarshalNCreateMemberWithProgramInput2ᚖgithubᚗcomᚋtheopenlaneᚋcoreᚋinternalᚋgraphapiᚐCreateMemberWithProgramInput(ctx context.Context, v interface{}) (*CreateMemberWithProgramInput, error) { + res, err := ec.unmarshalInputCreateMemberWithProgramInput(ctx, v) + return &res, graphql.ErrorOnPath(ctx, err) +} + func (ec *executionContext) unmarshalNCreateNarrativeInput2githubᚗcomᚋtheopenlaneᚋcoreᚋinternalᚋentᚋgeneratedᚐCreateNarrativeInput(ctx context.Context, v interface{}) (generated.CreateNarrativeInput, error) { res, err := ec.unmarshalInputCreateNarrativeInput(ctx, v) return res, graphql.ErrorOnPath(ctx, err) @@ -404624,6 +404833,11 @@ func (ec *executionContext) unmarshalNCreateProgramMembershipInput2ᚖgithubᚗc return &res, graphql.ErrorOnPath(ctx, err) } +func (ec *executionContext) unmarshalNCreateProgramWithMembersInput2githubᚗcomᚋtheopenlaneᚋcoreᚋinternalᚋgraphapiᚐCreateProgramWithMembersInput(ctx context.Context, v interface{}) (CreateProgramWithMembersInput, error) { + res, err := ec.unmarshalInputCreateProgramWithMembersInput(ctx, v) + return res, graphql.ErrorOnPath(ctx, err) +} + func (ec *executionContext) unmarshalNCreateRiskInput2githubᚗcomᚋtheopenlaneᚋcoreᚋinternalᚋentᚋgeneratedᚐCreateRiskInput(ctx context.Context, v interface{}) (generated.CreateRiskInput, error) { res, err := ec.unmarshalInputCreateRiskInput(ctx, v) return res, graphql.ErrorOnPath(ctx, err) @@ -412227,6 +412441,26 @@ func (ec *executionContext) unmarshalOCreateInviteInput2ᚕᚖgithubᚗcomᚋthe return res, nil } +func (ec *executionContext) unmarshalOCreateMemberWithProgramInput2ᚕᚖgithubᚗcomᚋtheopenlaneᚋcoreᚋinternalᚋgraphapiᚐCreateMemberWithProgramInputᚄ(ctx context.Context, v interface{}) ([]*CreateMemberWithProgramInput, error) { + if v == nil { + return nil, nil + } + var vSlice []interface{} + if v != nil { + vSlice = graphql.CoerceList(v) + } + var err error + res := make([]*CreateMemberWithProgramInput, len(vSlice)) + for i := range vSlice { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithIndex(i)) + res[i], err = ec.unmarshalNCreateMemberWithProgramInput2ᚖgithubᚗcomᚋtheopenlaneᚋcoreᚋinternalᚋgraphapiᚐCreateMemberWithProgramInput(ctx, vSlice[i]) + if err != nil { + return nil, err + } + } + return res, nil +} + func (ec *executionContext) unmarshalOCreateNarrativeInput2ᚕᚖgithubᚗcomᚋtheopenlaneᚋcoreᚋinternalᚋentᚋgeneratedᚐCreateNarrativeInputᚄ(ctx context.Context, v interface{}) ([]*generated.CreateNarrativeInput, error) { if v == nil { return nil, nil diff --git a/internal/graphapi/programextended.resolvers.go b/internal/graphapi/programextended.resolvers.go index f0e7993f..83462b87 100644 --- a/internal/graphapi/programextended.resolvers.go +++ b/internal/graphapi/programextended.resolvers.go @@ -10,8 +10,44 @@ import ( "github.com/99designs/gqlgen/graphql" "github.com/rs/zerolog/log" "github.com/theopenlane/core/internal/ent/generated" + "github.com/theopenlane/utils/rout" ) +// CreateProgramWithMembers is the resolver for the createProgramWithMembers field. +func (r *mutationResolver) CreateProgramWithMembers(ctx context.Context, input CreateProgramWithMembersInput) (*ProgramCreatePayload, error) { + // set the organization in the auth context if its not done for us + if err := setOrganizationInAuthContext(ctx, input.Program.OwnerID); err != nil { + log.Error().Err(err).Msg("failed to set organization in auth context") + return nil, rout.NewMissingRequiredFieldError("owner_id") + } + + res, err := withTransactionalMutation(ctx).Program.Create().SetInput(*input.Program).Save(ctx) + if err != nil { + return nil, parseRequestError(err, action{action: ActionCreate, object: "program"}) + } + + c := withTransactionalMutation(ctx) + builders := make([]*generated.ProgramMembershipCreate, len(input.Members)) + for i := range input.Members { + input := generated.CreateProgramMembershipInput{ + ProgramID: res.ID, + UserID: input.Members[i].UserID, + Role: input.Members[i].Role, + } + + builders[i] = c.ProgramMembership.Create().SetInput(input) + } + + _, err = c.ProgramMembership.CreateBulk(builders...).Save(ctx) + if err != nil { + return nil, err + } + + return &ProgramCreatePayload{ + Program: res, + }, nil +} + // AddProgramMembers is the resolver for the addProgramMembers field. func (r *updateProgramInputResolver) AddProgramMembers(ctx context.Context, obj *generated.UpdateProgramInput, data []*generated.CreateProgramMembershipInput) error { opCtx := graphql.GetOperationContext(ctx) diff --git a/internal/graphapi/programextended_test.go b/internal/graphapi/programextended_test.go new file mode 100644 index 00000000..7a9be504 --- /dev/null +++ b/internal/graphapi/programextended_test.go @@ -0,0 +1,68 @@ +package graphapi_test + +import ( + "context" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/theopenlane/core/pkg/enums" + "github.com/theopenlane/core/pkg/openlaneclient" +) + +func (suite *GraphTestSuite) TestMutationCreateProgramWithMembers() { + t := suite.T() + + members := []*openlaneclient.CreateMemberWithProgramInput{ + { + UserID: viewOnlyUser.ID, + Role: &enums.RoleMember, + }, + { + UserID: adminUser.ID, + Role: &enums.RoleAdmin, + }, + } + + testCases := []struct { + name string + request openlaneclient.CreateProgramWithMembersInput + client *openlaneclient.OpenlaneClient + ctx context.Context + expectedErr string + }{ + { + name: "happy path, minimal input", + request: openlaneclient.CreateProgramWithMembersInput{ + Program: &openlaneclient.CreateProgramInput{ + Name: "mitb program", + }, + Members: members, + }, + client: suite.client.api, + ctx: testUser1.UserCtx, + }, + } + + for _, tc := range testCases { + t.Run("Create "+tc.name, func(t *testing.T) { + resp, err := tc.client.CreateProgramWithMembers(tc.ctx, tc.request) + if tc.expectedErr != "" { + require.Error(t, err) + assert.ErrorContains(t, err, tc.expectedErr) + assert.Nil(t, resp) + + return + } + + require.NoError(t, err) + require.NotNil(t, resp) + + // check required fields + assert.Equal(t, tc.request.Program.Name, resp.CreateProgramWithMembers.Program.Name) + + // the creator is automatically added as an admin, and the members are added in addition + assert.Len(t, resp.CreateProgramWithMembers.Program.Members, len(tc.request.Members)+1) + }) + } +} diff --git a/pkg/openlaneclient/graphclient.go b/pkg/openlaneclient/graphclient.go index 1002aa98..3585cf34 100644 --- a/pkg/openlaneclient/graphclient.go +++ b/pkg/openlaneclient/graphclient.go @@ -276,6 +276,7 @@ type OpenlaneGraphClient interface { CreateBulkCSVProgram(ctx context.Context, input graphql.Upload, interceptors ...clientv2.RequestInterceptor) (*CreateBulkCSVProgram, error) CreateBulkProgram(ctx context.Context, input []*CreateProgramInput, interceptors ...clientv2.RequestInterceptor) (*CreateBulkProgram, error) CreateProgram(ctx context.Context, input CreateProgramInput, interceptors ...clientv2.RequestInterceptor) (*CreateProgram, error) + CreateProgramWithMembers(ctx context.Context, input CreateProgramWithMembersInput, interceptors ...clientv2.RequestInterceptor) (*CreateProgramWithMembers, error) DeleteProgram(ctx context.Context, deleteProgramID string, interceptors ...clientv2.RequestInterceptor) (*DeleteProgram, error) GetAllPrograms(ctx context.Context, interceptors ...clientv2.RequestInterceptor) (*GetAllPrograms, error) GetProgramByID(ctx context.Context, programID string, interceptors ...clientv2.RequestInterceptor) (*GetProgramByID, error) @@ -37803,6 +37804,85 @@ func (t *CreateProgram_CreateProgram) GetProgram() *CreateProgram_CreateProgram_ return &t.Program } +type CreateProgramWithMembers_CreateProgramWithMembers_Program_Members_User struct { + ID string "json:\"id\" graphql:\"id\"" + FirstName *string "json:\"firstName,omitempty\" graphql:\"firstName\"" + LastName *string "json:\"lastName,omitempty\" graphql:\"lastName\"" +} + +func (t *CreateProgramWithMembers_CreateProgramWithMembers_Program_Members_User) GetID() string { + if t == nil { + t = &CreateProgramWithMembers_CreateProgramWithMembers_Program_Members_User{} + } + return t.ID +} +func (t *CreateProgramWithMembers_CreateProgramWithMembers_Program_Members_User) GetFirstName() *string { + if t == nil { + t = &CreateProgramWithMembers_CreateProgramWithMembers_Program_Members_User{} + } + return t.FirstName +} +func (t *CreateProgramWithMembers_CreateProgramWithMembers_Program_Members_User) GetLastName() *string { + if t == nil { + t = &CreateProgramWithMembers_CreateProgramWithMembers_Program_Members_User{} + } + return t.LastName +} + +type CreateProgramWithMembers_CreateProgramWithMembers_Program_Members struct { + ID string "json:\"id\" graphql:\"id\"" + User CreateProgramWithMembers_CreateProgramWithMembers_Program_Members_User "json:\"user\" graphql:\"user\"" +} + +func (t *CreateProgramWithMembers_CreateProgramWithMembers_Program_Members) GetID() string { + if t == nil { + t = &CreateProgramWithMembers_CreateProgramWithMembers_Program_Members{} + } + return t.ID +} +func (t *CreateProgramWithMembers_CreateProgramWithMembers_Program_Members) GetUser() *CreateProgramWithMembers_CreateProgramWithMembers_Program_Members_User { + if t == nil { + t = &CreateProgramWithMembers_CreateProgramWithMembers_Program_Members{} + } + return &t.User +} + +type CreateProgramWithMembers_CreateProgramWithMembers_Program struct { + Name string "json:\"name\" graphql:\"name\"" + ID string "json:\"id\" graphql:\"id\"" + Members []*CreateProgramWithMembers_CreateProgramWithMembers_Program_Members "json:\"members,omitempty\" graphql:\"members\"" +} + +func (t *CreateProgramWithMembers_CreateProgramWithMembers_Program) GetName() string { + if t == nil { + t = &CreateProgramWithMembers_CreateProgramWithMembers_Program{} + } + return t.Name +} +func (t *CreateProgramWithMembers_CreateProgramWithMembers_Program) GetID() string { + if t == nil { + t = &CreateProgramWithMembers_CreateProgramWithMembers_Program{} + } + return t.ID +} +func (t *CreateProgramWithMembers_CreateProgramWithMembers_Program) GetMembers() []*CreateProgramWithMembers_CreateProgramWithMembers_Program_Members { + if t == nil { + t = &CreateProgramWithMembers_CreateProgramWithMembers_Program{} + } + return t.Members +} + +type CreateProgramWithMembers_CreateProgramWithMembers struct { + Program CreateProgramWithMembers_CreateProgramWithMembers_Program "json:\"program\" graphql:\"program\"" +} + +func (t *CreateProgramWithMembers_CreateProgramWithMembers) GetProgram() *CreateProgramWithMembers_CreateProgramWithMembers_Program { + if t == nil { + t = &CreateProgramWithMembers_CreateProgramWithMembers{} + } + return &t.Program +} + type DeleteProgram_DeleteProgram struct { DeletedID string "json:\"deletedID\" graphql:\"deletedID\"" } @@ -56396,6 +56476,17 @@ func (t *CreateProgram) GetCreateProgram() *CreateProgram_CreateProgram { return &t.CreateProgram } +type CreateProgramWithMembers struct { + CreateProgramWithMembers CreateProgramWithMembers_CreateProgramWithMembers "json:\"createProgramWithMembers\" graphql:\"createProgramWithMembers\"" +} + +func (t *CreateProgramWithMembers) GetCreateProgramWithMembers() *CreateProgramWithMembers_CreateProgramWithMembers { + if t == nil { + t = &CreateProgramWithMembers{} + } + return &t.CreateProgramWithMembers +} + type DeleteProgram struct { DeleteProgram DeleteProgram_DeleteProgram "json:\"deleteProgram\" graphql:\"deleteProgram\"" } @@ -69044,6 +69135,41 @@ func (c *Client) CreateProgram(ctx context.Context, input CreateProgramInput, in return &res, nil } +const CreateProgramWithMembersDocument = `mutation CreateProgramWithMembers ($input: CreateProgramWithMembersInput!) { + createProgramWithMembers(input: $input) { + program { + name + id + members { + id + user { + id + firstName + lastName + } + } + } + } +} +` + +func (c *Client) CreateProgramWithMembers(ctx context.Context, input CreateProgramWithMembersInput, interceptors ...clientv2.RequestInterceptor) (*CreateProgramWithMembers, error) { + vars := map[string]any{ + "input": input, + } + + var res CreateProgramWithMembers + if err := c.Client.Post(ctx, "CreateProgramWithMembers", CreateProgramWithMembersDocument, &res, vars, interceptors...); err != nil { + if c.Client.ParseDataWhenErrors { + return &res, err + } + + return nil, err + } + + return &res, nil +} + const DeleteProgramDocument = `mutation DeleteProgram ($deleteProgramId: ID!) { deleteProgram(id: $deleteProgramId) { deletedID @@ -74051,6 +74177,7 @@ var DocumentOperationNames = map[string]string{ CreateBulkCSVProgramDocument: "CreateBulkCSVProgram", CreateBulkProgramDocument: "CreateBulkProgram", CreateProgramDocument: "CreateProgram", + CreateProgramWithMembersDocument: "CreateProgramWithMembers", DeleteProgramDocument: "DeleteProgram", GetAllProgramsDocument: "GetAllPrograms", GetProgramByIDDocument: "GetProgramByID", diff --git a/pkg/openlaneclient/models.go b/pkg/openlaneclient/models.go index 60ab8151..c62d0504 100644 --- a/pkg/openlaneclient/models.go +++ b/pkg/openlaneclient/models.go @@ -3542,6 +3542,11 @@ type CreateInviteInput struct { EventIDs []string `json:"eventIDs,omitempty"` } +type CreateMemberWithProgramInput struct { + Role *enums.Role `json:"role,omitempty"` + UserID string `json:"userID"` +} + // CreateNarrativeInput is used for create Narrative object. // Input was generated by ent. type CreateNarrativeInput struct { @@ -3847,6 +3852,11 @@ type CreateProgramMembershipInput struct { UserID string `json:"userID"` } +type CreateProgramWithMembersInput struct { + Program *CreateProgramInput `json:"program"` + Members []*CreateMemberWithProgramInput `json:"members,omitempty"` +} + // CreateRiskInput is used for create Risk object. // Input was generated by ent. type CreateRiskInput struct { diff --git a/query/program.graphql b/query/program.graphql index 1d7b617f..0877221d 100644 --- a/query/program.graphql +++ b/query/program.graphql @@ -109,6 +109,23 @@ mutation CreateProgram($input: CreateProgramInput!) { } } +mutation CreateProgramWithMembers($input: CreateProgramWithMembersInput!) { + createProgramWithMembers(input: $input) { + program { + name + id + members { + id + user { + id + firstName + lastName + } + } + } + } +} + mutation DeleteProgram($deleteProgramId: ID!) { deleteProgram(id: $deleteProgramId) { deletedID diff --git a/schema.graphql b/schema.graphql index 5864f810..e518e466 100644 --- a/schema.graphql +++ b/schema.graphql @@ -4573,6 +4573,10 @@ input CreateInviteInput { ownerID: ID eventIDs: [ID!] } +input CreateMemberWithProgramInput { + role: ProgramMembershipRole + userID: ID! +} """ CreateNarrativeInput is used for create Narrative object. Input was generated by ent. @@ -5022,6 +5026,10 @@ input CreateProgramMembershipInput { programID: ID! userID: ID! } +input CreateProgramWithMembersInput { + program: CreateProgramInput! + members: [CreateMemberWithProgramInput!] +} """ CreateRiskInput is used for create Risk object. Input was generated by ent. @@ -17240,6 +17248,15 @@ type Mutation { id: ID! ): ProgramDeletePayload! """ + Create a new program with members + """ + createProgramWithMembers( + """ + values of the program + """ + input: CreateProgramWithMembersInput! + ): ProgramCreatePayload! + """ Create a new programMembership """ createProgramMembership( diff --git a/schema/programextended.graphql b/schema/programextended.graphql index de1f358a..56f26702 100644 --- a/schema/programextended.graphql +++ b/schema/programextended.graphql @@ -5,4 +5,26 @@ extend input UpdateProgramInput { extend input ProgramMembershipWhereInput { programID: String userID: String +} + +input CreateProgramWithMembersInput{ + program: CreateProgramInput! + members: [CreateMemberWithProgramInput!] +} + +input CreateMemberWithProgramInput { + role: ProgramMembershipRole + userID: ID! +} + +extend type Mutation{ + """ + Create a new program with members + """ + createProgramWithMembers( + """ + values of the program + """ + input: CreateProgramWithMembersInput! + ): ProgramCreatePayload! } \ No newline at end of file