feat: add commands for managing organizations and users
Introduce `AddUserToOrganization`, `RemoveAPIKey`, and `RemoveOrganization` commands to enhance organization management. Implement validation for user addition and API key removal. Update GraphQL schema to support new mutations and add caching for the new events, ensuring that organizations and their relationships are accurately represented in the cache.
This commit is contained in:
+411
-10
@@ -61,9 +61,12 @@ type ComplexityRoot struct {
|
||||
}
|
||||
|
||||
Mutation struct {
|
||||
AddAPIKey func(childComplexity int, input *model.InputAPIKey) int
|
||||
AddOrganization func(childComplexity int, name string) int
|
||||
UpdateSubGraph func(childComplexity int, input model.InputSubGraph) int
|
||||
AddAPIKey func(childComplexity int, input *model.InputAPIKey) int
|
||||
AddOrganization func(childComplexity int, name string) int
|
||||
AddUserToOrganization func(childComplexity int, organizationID string, userID string) int
|
||||
RemoveAPIKey func(childComplexity int, organizationID string, keyName string) int
|
||||
RemoveOrganization func(childComplexity int, organizationID string) int
|
||||
UpdateSubGraph func(childComplexity int, input model.InputSubGraph) int
|
||||
}
|
||||
|
||||
Organization struct {
|
||||
@@ -74,9 +77,10 @@ type ComplexityRoot struct {
|
||||
}
|
||||
|
||||
Query struct {
|
||||
LatestSchema func(childComplexity int, ref string) int
|
||||
Organizations func(childComplexity int) int
|
||||
Supergraph func(childComplexity int, ref string, isAfter *string) int
|
||||
AllOrganizations func(childComplexity int) int
|
||||
LatestSchema func(childComplexity int, ref string) int
|
||||
Organizations func(childComplexity int) int
|
||||
Supergraph func(childComplexity int, ref string, isAfter *string) int
|
||||
}
|
||||
|
||||
SchemaUpdate struct {
|
||||
@@ -119,11 +123,15 @@ type ComplexityRoot struct {
|
||||
|
||||
type MutationResolver interface {
|
||||
AddOrganization(ctx context.Context, name string) (*model.Organization, error)
|
||||
AddUserToOrganization(ctx context.Context, organizationID string, userID string) (*model.Organization, error)
|
||||
AddAPIKey(ctx context.Context, input *model.InputAPIKey) (*model.APIKey, error)
|
||||
RemoveAPIKey(ctx context.Context, organizationID string, keyName string) (*model.Organization, error)
|
||||
RemoveOrganization(ctx context.Context, organizationID string) (bool, error)
|
||||
UpdateSubGraph(ctx context.Context, input model.InputSubGraph) (*model.SubGraph, error)
|
||||
}
|
||||
type QueryResolver interface {
|
||||
Organizations(ctx context.Context) ([]*model.Organization, error)
|
||||
AllOrganizations(ctx context.Context) ([]*model.Organization, error)
|
||||
Supergraph(ctx context.Context, ref string, isAfter *string) (model.Supergraph, error)
|
||||
LatestSchema(ctx context.Context, ref string) (*model.SchemaUpdate, error)
|
||||
}
|
||||
@@ -215,6 +223,39 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin
|
||||
}
|
||||
|
||||
return e.complexity.Mutation.AddOrganization(childComplexity, args["name"].(string)), true
|
||||
case "Mutation.addUserToOrganization":
|
||||
if e.complexity.Mutation.AddUserToOrganization == nil {
|
||||
break
|
||||
}
|
||||
|
||||
args, err := ec.field_Mutation_addUserToOrganization_args(ctx, rawArgs)
|
||||
if err != nil {
|
||||
return 0, false
|
||||
}
|
||||
|
||||
return e.complexity.Mutation.AddUserToOrganization(childComplexity, args["organizationId"].(string), args["userId"].(string)), true
|
||||
case "Mutation.removeAPIKey":
|
||||
if e.complexity.Mutation.RemoveAPIKey == nil {
|
||||
break
|
||||
}
|
||||
|
||||
args, err := ec.field_Mutation_removeAPIKey_args(ctx, rawArgs)
|
||||
if err != nil {
|
||||
return 0, false
|
||||
}
|
||||
|
||||
return e.complexity.Mutation.RemoveAPIKey(childComplexity, args["organizationId"].(string), args["keyName"].(string)), true
|
||||
case "Mutation.removeOrganization":
|
||||
if e.complexity.Mutation.RemoveOrganization == nil {
|
||||
break
|
||||
}
|
||||
|
||||
args, err := ec.field_Mutation_removeOrganization_args(ctx, rawArgs)
|
||||
if err != nil {
|
||||
return 0, false
|
||||
}
|
||||
|
||||
return e.complexity.Mutation.RemoveOrganization(childComplexity, args["organizationId"].(string)), true
|
||||
case "Mutation.updateSubGraph":
|
||||
if e.complexity.Mutation.UpdateSubGraph == nil {
|
||||
break
|
||||
@@ -252,6 +293,12 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin
|
||||
|
||||
return e.complexity.Organization.Users(childComplexity), true
|
||||
|
||||
case "Query.allOrganizations":
|
||||
if e.complexity.Query.AllOrganizations == nil {
|
||||
break
|
||||
}
|
||||
|
||||
return e.complexity.Query.AllOrganizations(childComplexity), true
|
||||
case "Query.latestSchema":
|
||||
if e.complexity.Query.LatestSchema == nil {
|
||||
break
|
||||
@@ -532,13 +579,17 @@ func (ec *executionContext) introspectType(name string) (*introspection.Type, er
|
||||
var sources = []*ast.Source{
|
||||
{Name: "../schema.graphqls", Input: `type Query {
|
||||
organizations: [Organization!]! @auth(user: true)
|
||||
supergraph(ref: String!, isAfter: String): Supergraph! @auth(organization: true)
|
||||
latestSchema(ref: String!): SchemaUpdate! @auth(organization: true)
|
||||
allOrganizations: [Organization!]! @auth(user: true)
|
||||
supergraph(ref: String!, isAfter: String): Supergraph! @auth(user: true, organization: true)
|
||||
latestSchema(ref: String!): SchemaUpdate! @auth(user: true, organization: true)
|
||||
}
|
||||
|
||||
type Mutation {
|
||||
addOrganization(name: String!): Organization! @auth(user: true)
|
||||
addUserToOrganization(organizationId: ID!, userId: String!): Organization! @auth(user: true)
|
||||
addAPIKey(input: InputAPIKey): APIKey! @auth(user: true)
|
||||
removeAPIKey(organizationId: ID!, keyName: String!): Organization! @auth(user: true)
|
||||
removeOrganization(organizationId: ID!): Boolean! @auth(user: true)
|
||||
updateSubGraph(input: InputSubGraph!): SubGraph! @auth(organization: true)
|
||||
}
|
||||
|
||||
@@ -663,6 +714,49 @@ func (ec *executionContext) field_Mutation_addOrganization_args(ctx context.Cont
|
||||
return args, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) field_Mutation_addUserToOrganization_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) {
|
||||
var err error
|
||||
args := map[string]any{}
|
||||
arg0, err := graphql.ProcessArgField(ctx, rawArgs, "organizationId", ec.unmarshalNID2string)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
args["organizationId"] = arg0
|
||||
arg1, err := graphql.ProcessArgField(ctx, rawArgs, "userId", ec.unmarshalNString2string)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
args["userId"] = arg1
|
||||
return args, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) field_Mutation_removeAPIKey_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) {
|
||||
var err error
|
||||
args := map[string]any{}
|
||||
arg0, err := graphql.ProcessArgField(ctx, rawArgs, "organizationId", ec.unmarshalNID2string)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
args["organizationId"] = arg0
|
||||
arg1, err := graphql.ProcessArgField(ctx, rawArgs, "keyName", ec.unmarshalNString2string)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
args["keyName"] = arg1
|
||||
return args, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) field_Mutation_removeOrganization_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) {
|
||||
var err error
|
||||
args := map[string]any{}
|
||||
arg0, err := graphql.ProcessArgField(ctx, rawArgs, "organizationId", ec.unmarshalNID2string)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
args["organizationId"] = arg0
|
||||
return args, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) field_Mutation_updateSubGraph_args(ctx context.Context, rawArgs map[string]any) (map[string]any, error) {
|
||||
var err error
|
||||
args := map[string]any{}
|
||||
@@ -1057,6 +1151,75 @@ func (ec *executionContext) fieldContext_Mutation_addOrganization(ctx context.Co
|
||||
return fc, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) _Mutation_addUserToOrganization(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {
|
||||
return graphql.ResolveField(
|
||||
ctx,
|
||||
ec.OperationContext,
|
||||
field,
|
||||
ec.fieldContext_Mutation_addUserToOrganization,
|
||||
func(ctx context.Context) (any, error) {
|
||||
fc := graphql.GetFieldContext(ctx)
|
||||
return ec.resolvers.Mutation().AddUserToOrganization(ctx, fc.Args["organizationId"].(string), fc.Args["userId"].(string))
|
||||
},
|
||||
func(ctx context.Context, next graphql.Resolver) graphql.Resolver {
|
||||
directive0 := next
|
||||
|
||||
directive1 := func(ctx context.Context) (any, error) {
|
||||
user, err := ec.unmarshalOBoolean2ᚖbool(ctx, true)
|
||||
if err != nil {
|
||||
var zeroVal *model.Organization
|
||||
return zeroVal, err
|
||||
}
|
||||
if ec.directives.Auth == nil {
|
||||
var zeroVal *model.Organization
|
||||
return zeroVal, errors.New("directive auth is not implemented")
|
||||
}
|
||||
return ec.directives.Auth(ctx, nil, directive0, user, nil)
|
||||
}
|
||||
|
||||
next = directive1
|
||||
return next
|
||||
},
|
||||
ec.marshalNOrganization2ᚖgitlabᚗcomᚋunboundsoftwareᚋschemasᚋgraphᚋmodelᚐOrganization,
|
||||
true,
|
||||
true,
|
||||
)
|
||||
}
|
||||
|
||||
func (ec *executionContext) fieldContext_Mutation_addUserToOrganization(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 "id":
|
||||
return ec.fieldContext_Organization_id(ctx, field)
|
||||
case "name":
|
||||
return ec.fieldContext_Organization_name(ctx, field)
|
||||
case "users":
|
||||
return ec.fieldContext_Organization_users(ctx, field)
|
||||
case "apiKeys":
|
||||
return ec.fieldContext_Organization_apiKeys(ctx, field)
|
||||
}
|
||||
return nil, fmt.Errorf("no field named %q was found under type Organization", 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_addUserToOrganization_args(ctx, field.ArgumentMap(ec.Variables)); err != nil {
|
||||
ec.Error(ctx, err)
|
||||
return fc, err
|
||||
}
|
||||
return fc, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) _Mutation_addAPIKey(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {
|
||||
return graphql.ResolveField(
|
||||
ctx,
|
||||
@@ -1132,6 +1295,134 @@ func (ec *executionContext) fieldContext_Mutation_addAPIKey(ctx context.Context,
|
||||
return fc, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) _Mutation_removeAPIKey(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {
|
||||
return graphql.ResolveField(
|
||||
ctx,
|
||||
ec.OperationContext,
|
||||
field,
|
||||
ec.fieldContext_Mutation_removeAPIKey,
|
||||
func(ctx context.Context) (any, error) {
|
||||
fc := graphql.GetFieldContext(ctx)
|
||||
return ec.resolvers.Mutation().RemoveAPIKey(ctx, fc.Args["organizationId"].(string), fc.Args["keyName"].(string))
|
||||
},
|
||||
func(ctx context.Context, next graphql.Resolver) graphql.Resolver {
|
||||
directive0 := next
|
||||
|
||||
directive1 := func(ctx context.Context) (any, error) {
|
||||
user, err := ec.unmarshalOBoolean2ᚖbool(ctx, true)
|
||||
if err != nil {
|
||||
var zeroVal *model.Organization
|
||||
return zeroVal, err
|
||||
}
|
||||
if ec.directives.Auth == nil {
|
||||
var zeroVal *model.Organization
|
||||
return zeroVal, errors.New("directive auth is not implemented")
|
||||
}
|
||||
return ec.directives.Auth(ctx, nil, directive0, user, nil)
|
||||
}
|
||||
|
||||
next = directive1
|
||||
return next
|
||||
},
|
||||
ec.marshalNOrganization2ᚖgitlabᚗcomᚋunboundsoftwareᚋschemasᚋgraphᚋmodelᚐOrganization,
|
||||
true,
|
||||
true,
|
||||
)
|
||||
}
|
||||
|
||||
func (ec *executionContext) fieldContext_Mutation_removeAPIKey(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 "id":
|
||||
return ec.fieldContext_Organization_id(ctx, field)
|
||||
case "name":
|
||||
return ec.fieldContext_Organization_name(ctx, field)
|
||||
case "users":
|
||||
return ec.fieldContext_Organization_users(ctx, field)
|
||||
case "apiKeys":
|
||||
return ec.fieldContext_Organization_apiKeys(ctx, field)
|
||||
}
|
||||
return nil, fmt.Errorf("no field named %q was found under type Organization", 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_removeAPIKey_args(ctx, field.ArgumentMap(ec.Variables)); err != nil {
|
||||
ec.Error(ctx, err)
|
||||
return fc, err
|
||||
}
|
||||
return fc, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) _Mutation_removeOrganization(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {
|
||||
return graphql.ResolveField(
|
||||
ctx,
|
||||
ec.OperationContext,
|
||||
field,
|
||||
ec.fieldContext_Mutation_removeOrganization,
|
||||
func(ctx context.Context) (any, error) {
|
||||
fc := graphql.GetFieldContext(ctx)
|
||||
return ec.resolvers.Mutation().RemoveOrganization(ctx, fc.Args["organizationId"].(string))
|
||||
},
|
||||
func(ctx context.Context, next graphql.Resolver) graphql.Resolver {
|
||||
directive0 := next
|
||||
|
||||
directive1 := func(ctx context.Context) (any, error) {
|
||||
user, err := ec.unmarshalOBoolean2ᚖbool(ctx, true)
|
||||
if err != nil {
|
||||
var zeroVal bool
|
||||
return zeroVal, err
|
||||
}
|
||||
if ec.directives.Auth == nil {
|
||||
var zeroVal bool
|
||||
return zeroVal, errors.New("directive auth is not implemented")
|
||||
}
|
||||
return ec.directives.Auth(ctx, nil, directive0, user, nil)
|
||||
}
|
||||
|
||||
next = directive1
|
||||
return next
|
||||
},
|
||||
ec.marshalNBoolean2bool,
|
||||
true,
|
||||
true,
|
||||
)
|
||||
}
|
||||
|
||||
func (ec *executionContext) fieldContext_Mutation_removeOrganization(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) {
|
||||
return nil, errors.New("field of type Boolean does not have child fields")
|
||||
},
|
||||
}
|
||||
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_removeOrganization_args(ctx, field.ArgumentMap(ec.Variables)); err != nil {
|
||||
ec.Error(ctx, err)
|
||||
return fc, err
|
||||
}
|
||||
return fc, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) _Mutation_updateSubGraph(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {
|
||||
return graphql.ResolveField(
|
||||
ctx,
|
||||
@@ -1400,6 +1691,63 @@ func (ec *executionContext) fieldContext_Query_organizations(_ context.Context,
|
||||
return fc, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) _Query_allOrganizations(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {
|
||||
return graphql.ResolveField(
|
||||
ctx,
|
||||
ec.OperationContext,
|
||||
field,
|
||||
ec.fieldContext_Query_allOrganizations,
|
||||
func(ctx context.Context) (any, error) {
|
||||
return ec.resolvers.Query().AllOrganizations(ctx)
|
||||
},
|
||||
func(ctx context.Context, next graphql.Resolver) graphql.Resolver {
|
||||
directive0 := next
|
||||
|
||||
directive1 := func(ctx context.Context) (any, error) {
|
||||
user, err := ec.unmarshalOBoolean2ᚖbool(ctx, true)
|
||||
if err != nil {
|
||||
var zeroVal []*model.Organization
|
||||
return zeroVal, err
|
||||
}
|
||||
if ec.directives.Auth == nil {
|
||||
var zeroVal []*model.Organization
|
||||
return zeroVal, errors.New("directive auth is not implemented")
|
||||
}
|
||||
return ec.directives.Auth(ctx, nil, directive0, user, nil)
|
||||
}
|
||||
|
||||
next = directive1
|
||||
return next
|
||||
},
|
||||
ec.marshalNOrganization2ᚕᚖgitlabᚗcomᚋunboundsoftwareᚋschemasᚋgraphᚋmodelᚐOrganizationᚄ,
|
||||
true,
|
||||
true,
|
||||
)
|
||||
}
|
||||
|
||||
func (ec *executionContext) fieldContext_Query_allOrganizations(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
|
||||
fc = &graphql.FieldContext{
|
||||
Object: "Query",
|
||||
Field: field,
|
||||
IsMethod: true,
|
||||
IsResolver: true,
|
||||
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
|
||||
switch field.Name {
|
||||
case "id":
|
||||
return ec.fieldContext_Organization_id(ctx, field)
|
||||
case "name":
|
||||
return ec.fieldContext_Organization_name(ctx, field)
|
||||
case "users":
|
||||
return ec.fieldContext_Organization_users(ctx, field)
|
||||
case "apiKeys":
|
||||
return ec.fieldContext_Organization_apiKeys(ctx, field)
|
||||
}
|
||||
return nil, fmt.Errorf("no field named %q was found under type Organization", field.Name)
|
||||
},
|
||||
}
|
||||
return fc, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) _Query_supergraph(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {
|
||||
return graphql.ResolveField(
|
||||
ctx,
|
||||
@@ -1414,6 +1762,11 @@ func (ec *executionContext) _Query_supergraph(ctx context.Context, field graphql
|
||||
directive0 := next
|
||||
|
||||
directive1 := func(ctx context.Context) (any, error) {
|
||||
user, err := ec.unmarshalOBoolean2ᚖbool(ctx, true)
|
||||
if err != nil {
|
||||
var zeroVal model.Supergraph
|
||||
return zeroVal, err
|
||||
}
|
||||
organization, err := ec.unmarshalOBoolean2ᚖbool(ctx, true)
|
||||
if err != nil {
|
||||
var zeroVal model.Supergraph
|
||||
@@ -1423,7 +1776,7 @@ func (ec *executionContext) _Query_supergraph(ctx context.Context, field graphql
|
||||
var zeroVal model.Supergraph
|
||||
return zeroVal, errors.New("directive auth is not implemented")
|
||||
}
|
||||
return ec.directives.Auth(ctx, nil, directive0, nil, organization)
|
||||
return ec.directives.Auth(ctx, nil, directive0, user, organization)
|
||||
}
|
||||
|
||||
next = directive1
|
||||
@@ -1473,6 +1826,11 @@ func (ec *executionContext) _Query_latestSchema(ctx context.Context, field graph
|
||||
directive0 := next
|
||||
|
||||
directive1 := func(ctx context.Context) (any, error) {
|
||||
user, err := ec.unmarshalOBoolean2ᚖbool(ctx, true)
|
||||
if err != nil {
|
||||
var zeroVal *model.SchemaUpdate
|
||||
return zeroVal, err
|
||||
}
|
||||
organization, err := ec.unmarshalOBoolean2ᚖbool(ctx, true)
|
||||
if err != nil {
|
||||
var zeroVal *model.SchemaUpdate
|
||||
@@ -1482,7 +1840,7 @@ func (ec *executionContext) _Query_latestSchema(ctx context.Context, field graph
|
||||
var zeroVal *model.SchemaUpdate
|
||||
return zeroVal, errors.New("directive auth is not implemented")
|
||||
}
|
||||
return ec.directives.Auth(ctx, nil, directive0, nil, organization)
|
||||
return ec.directives.Auth(ctx, nil, directive0, user, organization)
|
||||
}
|
||||
|
||||
next = directive1
|
||||
@@ -3938,6 +4296,13 @@ func (ec *executionContext) _Mutation(ctx context.Context, sel ast.SelectionSet)
|
||||
if out.Values[i] == graphql.Null {
|
||||
out.Invalids++
|
||||
}
|
||||
case "addUserToOrganization":
|
||||
out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) {
|
||||
return ec._Mutation_addUserToOrganization(ctx, field)
|
||||
})
|
||||
if out.Values[i] == graphql.Null {
|
||||
out.Invalids++
|
||||
}
|
||||
case "addAPIKey":
|
||||
out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) {
|
||||
return ec._Mutation_addAPIKey(ctx, field)
|
||||
@@ -3945,6 +4310,20 @@ func (ec *executionContext) _Mutation(ctx context.Context, sel ast.SelectionSet)
|
||||
if out.Values[i] == graphql.Null {
|
||||
out.Invalids++
|
||||
}
|
||||
case "removeAPIKey":
|
||||
out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) {
|
||||
return ec._Mutation_removeAPIKey(ctx, field)
|
||||
})
|
||||
if out.Values[i] == graphql.Null {
|
||||
out.Invalids++
|
||||
}
|
||||
case "removeOrganization":
|
||||
out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) {
|
||||
return ec._Mutation_removeOrganization(ctx, field)
|
||||
})
|
||||
if out.Values[i] == graphql.Null {
|
||||
out.Invalids++
|
||||
}
|
||||
case "updateSubGraph":
|
||||
out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) {
|
||||
return ec._Mutation_updateSubGraph(ctx, field)
|
||||
@@ -4069,6 +4448,28 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr
|
||||
func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) })
|
||||
}
|
||||
|
||||
out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) })
|
||||
case "allOrganizations":
|
||||
field := field
|
||||
|
||||
innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
ec.Error(ctx, ec.Recover(ctx, r))
|
||||
}
|
||||
}()
|
||||
res = ec._Query_allOrganizations(ctx, field)
|
||||
if res == graphql.Null {
|
||||
atomic.AddUint32(&fs.Invalids, 1)
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
rrm := func(ctx context.Context) graphql.Marshaler {
|
||||
return ec.OperationContext.RootResolverMiddleware(ctx,
|
||||
func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) })
|
||||
}
|
||||
|
||||
out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) })
|
||||
case "supergraph":
|
||||
field := field
|
||||
|
||||
@@ -1,12 +1,16 @@
|
||||
type Query {
|
||||
organizations: [Organization!]! @auth(user: true)
|
||||
supergraph(ref: String!, isAfter: String): Supergraph! @auth(organization: true)
|
||||
latestSchema(ref: String!): SchemaUpdate! @auth(organization: true)
|
||||
allOrganizations: [Organization!]! @auth(user: true)
|
||||
supergraph(ref: String!, isAfter: String): Supergraph! @auth(user: true, organization: true)
|
||||
latestSchema(ref: String!): SchemaUpdate! @auth(user: true, organization: true)
|
||||
}
|
||||
|
||||
type Mutation {
|
||||
addOrganization(name: String!): Organization! @auth(user: true)
|
||||
addUserToOrganization(organizationId: ID!, userId: String!): Organization! @auth(user: true)
|
||||
addAPIKey(input: InputAPIKey): APIKey! @auth(user: true)
|
||||
removeAPIKey(organizationId: ID!, keyName: String!): Organization! @auth(user: true)
|
||||
removeOrganization(organizationId: ID!): Boolean! @auth(user: true)
|
||||
updateSubGraph(input: InputSubGraph!): SubGraph! @auth(organization: true)
|
||||
}
|
||||
|
||||
|
||||
+114
-7
@@ -37,6 +37,24 @@ func (r *mutationResolver) AddOrganization(ctx context.Context, name string) (*m
|
||||
return ToGqlOrganization(*org), nil
|
||||
}
|
||||
|
||||
// AddUserToOrganization is the resolver for the addUserToOrganization field.
|
||||
func (r *mutationResolver) AddUserToOrganization(ctx context.Context, organizationID string, userID string) (*model.Organization, error) {
|
||||
sub := middleware.UserFromContext(ctx)
|
||||
org := &domain.Organization{BaseAggregate: eventsourced.BaseAggregateFromString(organizationID)}
|
||||
h, err := r.handler(ctx, org)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, err = h.Handle(ctx, &domain.AddUserToOrganization{
|
||||
UserId: userID,
|
||||
Initiator: sub,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ToGqlOrganization(*org), nil
|
||||
}
|
||||
|
||||
// AddAPIKey is the resolver for the addAPIKey field.
|
||||
func (r *mutationResolver) AddAPIKey(ctx context.Context, input *model.InputAPIKey) (*model.APIKey, error) {
|
||||
sub := middleware.UserFromContext(ctx)
|
||||
@@ -71,6 +89,41 @@ func (r *mutationResolver) AddAPIKey(ctx context.Context, input *model.InputAPIK
|
||||
}, nil
|
||||
}
|
||||
|
||||
// RemoveAPIKey is the resolver for the removeAPIKey field.
|
||||
func (r *mutationResolver) RemoveAPIKey(ctx context.Context, organizationID string, keyName string) (*model.Organization, error) {
|
||||
sub := middleware.UserFromContext(ctx)
|
||||
org := &domain.Organization{BaseAggregate: eventsourced.BaseAggregateFromString(organizationID)}
|
||||
h, err := r.handler(ctx, org)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, err = h.Handle(ctx, &domain.RemoveAPIKey{
|
||||
KeyName: keyName,
|
||||
Initiator: sub,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ToGqlOrganization(*org), nil
|
||||
}
|
||||
|
||||
// RemoveOrganization is the resolver for the removeOrganization field.
|
||||
func (r *mutationResolver) RemoveOrganization(ctx context.Context, organizationID string) (bool, error) {
|
||||
sub := middleware.UserFromContext(ctx)
|
||||
org := &domain.Organization{BaseAggregate: eventsourced.BaseAggregateFromString(organizationID)}
|
||||
h, err := r.handler(ctx, org)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
_, err = h.Handle(ctx, &domain.RemoveOrganization{
|
||||
Initiator: sub,
|
||||
})
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// UpdateSubGraph is the resolver for the updateSubGraph field.
|
||||
func (r *mutationResolver) UpdateSubGraph(ctx context.Context, input model.InputSubGraph) (*model.SubGraph, error) {
|
||||
orgId := middleware.OrganizationFromContext(ctx)
|
||||
@@ -183,13 +236,49 @@ func (r *queryResolver) Organizations(ctx context.Context) ([]*model.Organizatio
|
||||
return ToGqlOrganizations(orgs), nil
|
||||
}
|
||||
|
||||
// AllOrganizations is the resolver for the allOrganizations field.
|
||||
func (r *queryResolver) AllOrganizations(ctx context.Context) ([]*model.Organization, error) {
|
||||
// Check if user has admin role
|
||||
if !middleware.UserHasRole(ctx, "admin") {
|
||||
return nil, fmt.Errorf("unauthorized: admin role required")
|
||||
}
|
||||
|
||||
orgs := r.Cache.AllOrganizations()
|
||||
return ToGqlOrganizations(orgs), nil
|
||||
}
|
||||
|
||||
// Supergraph is the resolver for the supergraph field.
|
||||
func (r *queryResolver) Supergraph(ctx context.Context, ref string, isAfter *string) (model.Supergraph, error) {
|
||||
orgId := middleware.OrganizationFromContext(ctx)
|
||||
_, err := r.apiKeyCanAccessRef(ctx, ref, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
userId := middleware.UserFromContext(ctx)
|
||||
|
||||
r.Logger.Info("Supergraph query",
|
||||
"ref", ref,
|
||||
"orgId", orgId,
|
||||
"userId", userId,
|
||||
)
|
||||
|
||||
// If authenticated with API key (organization), check access
|
||||
if orgId != "" {
|
||||
_, err := r.apiKeyCanAccessRef(ctx, ref, false)
|
||||
if err != nil {
|
||||
r.Logger.Error("API key cannot access ref", "error", err, "ref", ref)
|
||||
return nil, err
|
||||
}
|
||||
} else if userId != "" {
|
||||
// For user authentication, check if user has access to ref through their organizations
|
||||
userOrgs := r.Cache.OrganizationsByUser(userId)
|
||||
if len(userOrgs) == 0 {
|
||||
r.Logger.Error("User has no organizations", "userId", userId)
|
||||
return nil, fmt.Errorf("user has no access to any organizations")
|
||||
}
|
||||
// Use the first organization's ID for querying
|
||||
orgId = userOrgs[0].ID.String()
|
||||
r.Logger.Info("Using organization from user context", "orgId", orgId)
|
||||
} else {
|
||||
return nil, fmt.Errorf("no authentication provided")
|
||||
}
|
||||
|
||||
after := ""
|
||||
if isAfter != nil {
|
||||
after = *isAfter
|
||||
@@ -241,16 +330,34 @@ func (r *queryResolver) Supergraph(ctx context.Context, ref string, isAfter *str
|
||||
// LatestSchema is the resolver for the latestSchema field.
|
||||
func (r *queryResolver) LatestSchema(ctx context.Context, ref string) (*model.SchemaUpdate, error) {
|
||||
orgId := middleware.OrganizationFromContext(ctx)
|
||||
userId := middleware.UserFromContext(ctx)
|
||||
|
||||
r.Logger.Info("LatestSchema query",
|
||||
"ref", ref,
|
||||
"orgId", orgId,
|
||||
"userId", userId,
|
||||
)
|
||||
|
||||
_, err := r.apiKeyCanAccessRef(ctx, ref, false)
|
||||
if err != nil {
|
||||
r.Logger.Error("API key cannot access ref", "error", err, "ref", ref)
|
||||
return nil, err
|
||||
// If authenticated with API key (organization), check access
|
||||
if orgId != "" {
|
||||
_, err := r.apiKeyCanAccessRef(ctx, ref, false)
|
||||
if err != nil {
|
||||
r.Logger.Error("API key cannot access ref", "error", err, "ref", ref)
|
||||
return nil, err
|
||||
}
|
||||
} else if userId != "" {
|
||||
// For user authentication, check if user has access to ref through their organizations
|
||||
userOrgs := r.Cache.OrganizationsByUser(userId)
|
||||
if len(userOrgs) == 0 {
|
||||
r.Logger.Error("User has no organizations", "userId", userId)
|
||||
return nil, fmt.Errorf("user has no access to any organizations")
|
||||
}
|
||||
// Use the first organization's ID for querying
|
||||
// In a real-world scenario, you might want to check which org has access to this ref
|
||||
orgId = userOrgs[0].ID.String()
|
||||
r.Logger.Info("Using organization from user context", "orgId", orgId)
|
||||
} else {
|
||||
return nil, fmt.Errorf("no authentication provided")
|
||||
}
|
||||
|
||||
// Get current services and schema
|
||||
|
||||
Reference in New Issue
Block a user