Move source and state from membership to profile

Signed-off-by: Émile Ré <emile@getprobo.com>
This commit is contained in:
Émile Ré
2026-02-13 21:21:11 +04:00
parent ec3d8fad40
commit 56ec0ab3c3
33 changed files with 1066 additions and 1220 deletions

View File

@@ -181,6 +181,8 @@ type Identity implements Node {
type Profile implements Node {
id: ID!
fullName: String!
source: String!
state: ProfileState!
additionalEmailAddresses: [EmailAddr!]!
kind: ProfileKind!
position: String
@@ -198,6 +200,32 @@ type Profile implements Node {
@session(required: PRESENT)
}
enum ProfileState
@goModel(model: "go.probo.inc/probo/pkg/coredata.ProfileState") {
ACTIVE @goEnum(value: "go.probo.inc/probo/pkg/coredata.ProfileStateActive")
INACTIVE
@goEnum(value: "go.probo.inc/probo/pkg/coredata.ProfileStateInactive")
}
enum ProfileSource
@goModel(model: "go.probo.inc/probo/pkg/coredata.ProfileSource") {
MANUAL
@goEnum(value: "go.probo.inc/probo/pkg/coredata.ProfileSourceManual")
SAML @goEnum(value: "go.probo.inc/probo/pkg/coredata.ProfileSourceSAML")
SCIM @goEnum(value: "go.probo.inc/probo/pkg/coredata.ProfileSourceSCIM")
}
enum ProfileKind @goModel(model: "go.probo.inc/probo/pkg/coredata.MembershipProfileKind") {
EMPLOYEE
@goEnum(value: "go.probo.inc/probo/pkg/coredata.MembershipProfileKindEmployee")
CONTRACTOR
@goEnum(value: "go.probo.inc/probo/pkg/coredata.MembershipProfileKindContractor")
SERVICE_ACCOUNT
@goEnum(
value: "go.probo.inc/probo/pkg/coredata.MembershipProfileKindServiceAccount"
)
}
type Organization implements Node {
id: ID!
name: String!
@@ -243,17 +271,6 @@ type Organization implements Node {
@session(required: PRESENT)
}
enum ProfileKind @goModel(model: "go.probo.inc/probo/pkg/coredata.MembershipProfileKind") {
EMPLOYEE
@goEnum(value: "go.probo.inc/probo/pkg/coredata.MembershipProfileKindEmployee")
CONTRACTOR
@goEnum(value: "go.probo.inc/probo/pkg/coredata.MembershipProfileKindContractor")
SERVICE_ACCOUNT
@goEnum(
value: "go.probo.inc/probo/pkg/coredata.MembershipProfileKindServiceAccount"
)
}
enum MembershipRole
@goModel(model: "go.probo.inc/probo/pkg/coredata.MembershipRole") {
OWNER @goEnum(value: "go.probo.inc/probo/pkg/coredata.MembershipRoleOwner")
@@ -265,27 +282,10 @@ enum MembershipRole
@goEnum(value: "go.probo.inc/probo/pkg/coredata.MembershipRoleAuditor")
}
enum MembershipSource
@goModel(model: "go.probo.inc/probo/pkg/coredata.MembershipSource") {
MANUAL
@goEnum(value: "go.probo.inc/probo/pkg/coredata.MembershipSourceManual")
SAML @goEnum(value: "go.probo.inc/probo/pkg/coredata.MembershipSourceSAML")
SCIM @goEnum(value: "go.probo.inc/probo/pkg/coredata.MembershipSourceSCIM")
}
enum MembershipState
@goModel(model: "go.probo.inc/probo/pkg/coredata.MembershipState") {
ACTIVE @goEnum(value: "go.probo.inc/probo/pkg/coredata.MembershipStateActive")
INACTIVE
@goEnum(value: "go.probo.inc/probo/pkg/coredata.MembershipStateInactive")
}
type Membership implements Node {
id: ID!
createdAt: Datetime!
role: MembershipRole!
source: MembershipSource!
state: MembershipState!
lastSession: Session @goField(forceResolver: true)
@@ -440,7 +440,7 @@ type SCIMEvent implements Node {
requestBody: String
responseBody: String
errorMessage: String
profile: Profile @goField(forceResolver: true)
userName: String!
ipAddress: String!
createdAt: Datetime!

View File

@@ -192,8 +192,6 @@ type ComplexityRoot struct {
LastSession func(childComplexity int) int
Permission func(childComplexity int, action string) int
Role func(childComplexity int) int
Source func(childComplexity int) int
State func(childComplexity int) int
}
Mutation struct {
@@ -299,6 +297,8 @@ type ComplexityRoot struct {
Organization func(childComplexity int) int
Permission func(childComplexity int, action string) int
Position func(childComplexity int) int
Source func(childComplexity int) int
State func(childComplexity int) int
UpdatedAt func(childComplexity int) int
}
@@ -414,10 +414,10 @@ type ComplexityRoot struct {
Method func(childComplexity int) int
Path func(childComplexity int) int
Permission func(childComplexity int, action string) int
Profile func(childComplexity int) int
RequestBody func(childComplexity int) int
ResponseBody func(childComplexity int) int
StatusCode func(childComplexity int) int
UserName func(childComplexity int) int
}
SCIMEventConnection struct {
@@ -605,8 +605,6 @@ type SCIMConfigurationResolver interface {
Permission(ctx context.Context, obj *types.SCIMConfiguration, action string) (bool, error)
}
type SCIMEventResolver interface {
Profile(ctx context.Context, obj *types.SCIMEvent) (*types.Profile, error)
Permission(ctx context.Context, obj *types.SCIMEvent, action string) (bool, error)
}
type SCIMEventConnectionResolver interface {
@@ -1042,18 +1040,6 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin
}
return e.complexity.Membership.Role(childComplexity), true
case "Membership.source":
if e.complexity.Membership.Source == nil {
break
}
return e.complexity.Membership.Source(childComplexity), true
case "Membership.state":
if e.complexity.Membership.State == nil {
break
}
return e.complexity.Membership.State(childComplexity), true
case "Mutation.acceptInvitation":
if e.complexity.Mutation.AcceptInvitation == nil {
@@ -1706,6 +1692,18 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin
}
return e.complexity.Profile.Position(childComplexity), true
case "Profile.source":
if e.complexity.Profile.Source == nil {
break
}
return e.complexity.Profile.Source(childComplexity), true
case "Profile.state":
if e.complexity.Profile.State == nil {
break
}
return e.complexity.Profile.State(childComplexity), true
case "Profile.updatedAt":
if e.complexity.Profile.UpdatedAt == nil {
break
@@ -2142,12 +2140,6 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin
}
return e.complexity.SCIMEvent.Permission(childComplexity, args["action"].(string)), true
case "SCIMEvent.profile":
if e.complexity.SCIMEvent.Profile == nil {
break
}
return e.complexity.SCIMEvent.Profile(childComplexity), true
case "SCIMEvent.requestBody":
if e.complexity.SCIMEvent.RequestBody == nil {
break
@@ -2166,6 +2158,12 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin
}
return e.complexity.SCIMEvent.StatusCode(childComplexity), true
case "SCIMEvent.userName":
if e.complexity.SCIMEvent.UserName == nil {
break
}
return e.complexity.SCIMEvent.UserName(childComplexity), true
case "SCIMEventConnection.edges":
if e.complexity.SCIMEventConnection.Edges == nil {
@@ -2683,6 +2681,8 @@ type Identity implements Node {
type Profile implements Node {
id: ID!
fullName: String!
source: String!
state: ProfileState!
additionalEmailAddresses: [EmailAddr!]!
kind: ProfileKind!
position: String
@@ -2700,6 +2700,32 @@ type Profile implements Node {
@session(required: PRESENT)
}
enum ProfileState
@goModel(model: "go.probo.inc/probo/pkg/coredata.ProfileState") {
ACTIVE @goEnum(value: "go.probo.inc/probo/pkg/coredata.ProfileStateActive")
INACTIVE
@goEnum(value: "go.probo.inc/probo/pkg/coredata.ProfileStateInactive")
}
enum ProfileSource
@goModel(model: "go.probo.inc/probo/pkg/coredata.ProfileSource") {
MANUAL
@goEnum(value: "go.probo.inc/probo/pkg/coredata.ProfileSourceManual")
SAML @goEnum(value: "go.probo.inc/probo/pkg/coredata.ProfileSourceSAML")
SCIM @goEnum(value: "go.probo.inc/probo/pkg/coredata.ProfileSourceSCIM")
}
enum ProfileKind @goModel(model: "go.probo.inc/probo/pkg/coredata.MembershipProfileKind") {
EMPLOYEE
@goEnum(value: "go.probo.inc/probo/pkg/coredata.MembershipProfileKindEmployee")
CONTRACTOR
@goEnum(value: "go.probo.inc/probo/pkg/coredata.MembershipProfileKindContractor")
SERVICE_ACCOUNT
@goEnum(
value: "go.probo.inc/probo/pkg/coredata.MembershipProfileKindServiceAccount"
)
}
type Organization implements Node {
id: ID!
name: String!
@@ -2745,17 +2771,6 @@ type Organization implements Node {
@session(required: PRESENT)
}
enum ProfileKind @goModel(model: "go.probo.inc/probo/pkg/coredata.MembershipProfileKind") {
EMPLOYEE
@goEnum(value: "go.probo.inc/probo/pkg/coredata.MembershipProfileKindEmployee")
CONTRACTOR
@goEnum(value: "go.probo.inc/probo/pkg/coredata.MembershipProfileKindContractor")
SERVICE_ACCOUNT
@goEnum(
value: "go.probo.inc/probo/pkg/coredata.MembershipProfileKindServiceAccount"
)
}
enum MembershipRole
@goModel(model: "go.probo.inc/probo/pkg/coredata.MembershipRole") {
OWNER @goEnum(value: "go.probo.inc/probo/pkg/coredata.MembershipRoleOwner")
@@ -2767,27 +2782,10 @@ enum MembershipRole
@goEnum(value: "go.probo.inc/probo/pkg/coredata.MembershipRoleAuditor")
}
enum MembershipSource
@goModel(model: "go.probo.inc/probo/pkg/coredata.MembershipSource") {
MANUAL
@goEnum(value: "go.probo.inc/probo/pkg/coredata.MembershipSourceManual")
SAML @goEnum(value: "go.probo.inc/probo/pkg/coredata.MembershipSourceSAML")
SCIM @goEnum(value: "go.probo.inc/probo/pkg/coredata.MembershipSourceSCIM")
}
enum MembershipState
@goModel(model: "go.probo.inc/probo/pkg/coredata.MembershipState") {
ACTIVE @goEnum(value: "go.probo.inc/probo/pkg/coredata.MembershipStateActive")
INACTIVE
@goEnum(value: "go.probo.inc/probo/pkg/coredata.MembershipStateInactive")
}
type Membership implements Node {
id: ID!
createdAt: Datetime!
role: MembershipRole!
source: MembershipSource!
state: MembershipState!
lastSession: Session @goField(forceResolver: true)
@@ -2942,7 +2940,7 @@ type SCIMEvent implements Node {
requestBody: String
responseBody: String
errorMessage: String
profile: Profile @goField(forceResolver: true)
userName: String!
ipAddress: String!
createdAt: Datetime!
@@ -4335,10 +4333,6 @@ func (ec *executionContext) fieldContext_AcceptInvitationPayload_membership(_ co
return ec.fieldContext_Membership_createdAt(ctx, field)
case "role":
return ec.fieldContext_Membership_role(ctx, field)
case "source":
return ec.fieldContext_Membership_source(ctx, field)
case "state":
return ec.fieldContext_Membership_state(ctx, field)
case "lastSession":
return ec.fieldContext_Membership_lastSession(ctx, field)
case "permission":
@@ -4756,10 +4750,6 @@ func (ec *executionContext) fieldContext_CreateOrganizationPayload_membership(_
return ec.fieldContext_Membership_createdAt(ctx, field)
case "role":
return ec.fieldContext_Membership_role(ctx, field)
case "source":
return ec.fieldContext_Membership_source(ctx, field)
case "state":
return ec.fieldContext_Membership_state(ctx, field)
case "lastSession":
return ec.fieldContext_Membership_lastSession(ctx, field)
case "permission":
@@ -6338,64 +6328,6 @@ func (ec *executionContext) fieldContext_Membership_role(_ context.Context, fiel
return fc, nil
}
func (ec *executionContext) _Membership_source(ctx context.Context, field graphql.CollectedField, obj *types.Membership) (ret graphql.Marshaler) {
return graphql.ResolveField(
ctx,
ec.OperationContext,
field,
ec.fieldContext_Membership_source,
func(ctx context.Context) (any, error) {
return obj.Source, nil
},
nil,
ec.marshalNMembershipSource2goᚗproboᚗincᚋproboᚋpkgᚋcoredataᚐMembershipSource,
true,
true,
)
}
func (ec *executionContext) fieldContext_Membership_source(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
fc = &graphql.FieldContext{
Object: "Membership",
Field: field,
IsMethod: false,
IsResolver: false,
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
return nil, errors.New("field of type MembershipSource does not have child fields")
},
}
return fc, nil
}
func (ec *executionContext) _Membership_state(ctx context.Context, field graphql.CollectedField, obj *types.Membership) (ret graphql.Marshaler) {
return graphql.ResolveField(
ctx,
ec.OperationContext,
field,
ec.fieldContext_Membership_state,
func(ctx context.Context) (any, error) {
return obj.State, nil
},
nil,
ec.marshalNMembershipState2goᚗproboᚗincᚋproboᚋpkgᚋcoredataᚐMembershipState,
true,
true,
)
}
func (ec *executionContext) fieldContext_Membership_state(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
fc = &graphql.FieldContext{
Object: "Membership",
Field: field,
IsMethod: false,
IsResolver: false,
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
return nil, errors.New("field of type MembershipState does not have child fields")
},
}
return fc, nil
}
func (ec *executionContext) _Membership_lastSession(ctx context.Context, field graphql.CollectedField, obj *types.Membership) (ret graphql.Marshaler) {
return graphql.ResolveField(
ctx,
@@ -8921,6 +8853,10 @@ func (ec *executionContext) fieldContext_Organization_viewer(_ context.Context,
return ec.fieldContext_Profile_id(ctx, field)
case "fullName":
return ec.fieldContext_Profile_fullName(ctx, field)
case "source":
return ec.fieldContext_Profile_source(ctx, field)
case "state":
return ec.fieldContext_Profile_state(ctx, field)
case "additionalEmailAddresses":
return ec.fieldContext_Profile_additionalEmailAddresses(ctx, field)
case "kind":
@@ -9086,10 +9022,6 @@ func (ec *executionContext) fieldContext_OrganizationSessionCreated_membership(_
return ec.fieldContext_Membership_createdAt(ctx, field)
case "role":
return ec.fieldContext_Membership_role(ctx, field)
case "source":
return ec.fieldContext_Membership_source(ctx, field)
case "state":
return ec.fieldContext_Membership_state(ctx, field)
case "lastSession":
return ec.fieldContext_Membership_lastSession(ctx, field)
case "permission":
@@ -9714,6 +9646,64 @@ func (ec *executionContext) fieldContext_Profile_fullName(_ context.Context, fie
return fc, nil
}
func (ec *executionContext) _Profile_source(ctx context.Context, field graphql.CollectedField, obj *types.Profile) (ret graphql.Marshaler) {
return graphql.ResolveField(
ctx,
ec.OperationContext,
field,
ec.fieldContext_Profile_source,
func(ctx context.Context) (any, error) {
return obj.Source, nil
},
nil,
ec.marshalNString2string,
true,
true,
)
}
func (ec *executionContext) fieldContext_Profile_source(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
fc = &graphql.FieldContext{
Object: "Profile",
Field: field,
IsMethod: false,
IsResolver: false,
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
return nil, errors.New("field of type String does not have child fields")
},
}
return fc, nil
}
func (ec *executionContext) _Profile_state(ctx context.Context, field graphql.CollectedField, obj *types.Profile) (ret graphql.Marshaler) {
return graphql.ResolveField(
ctx,
ec.OperationContext,
field,
ec.fieldContext_Profile_state,
func(ctx context.Context) (any, error) {
return obj.State, nil
},
nil,
ec.marshalNProfileState2goᚗproboᚗincᚋproboᚋpkgᚋcoredataᚐProfileState,
true,
true,
)
}
func (ec *executionContext) fieldContext_Profile_state(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
fc = &graphql.FieldContext{
Object: "Profile",
Field: field,
IsMethod: false,
IsResolver: false,
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
return nil, errors.New("field of type ProfileState does not have child fields")
},
}
return fc, nil
}
func (ec *executionContext) _Profile_additionalEmailAddresses(ctx context.Context, field graphql.CollectedField, obj *types.Profile) (ret graphql.Marshaler) {
return graphql.ResolveField(
ctx,
@@ -10063,10 +10053,6 @@ func (ec *executionContext) fieldContext_Profile_membership(_ context.Context, f
return ec.fieldContext_Membership_createdAt(ctx, field)
case "role":
return ec.fieldContext_Membership_role(ctx, field)
case "source":
return ec.fieldContext_Membership_source(ctx, field)
case "state":
return ec.fieldContext_Membership_state(ctx, field)
case "lastSession":
return ec.fieldContext_Membership_lastSession(ctx, field)
case "permission":
@@ -10297,6 +10283,10 @@ func (ec *executionContext) fieldContext_ProfileEdge_node(_ context.Context, fie
return ec.fieldContext_Profile_id(ctx, field)
case "fullName":
return ec.fieldContext_Profile_fullName(ctx, field)
case "source":
return ec.fieldContext_Profile_source(ctx, field)
case "state":
return ec.fieldContext_Profile_state(ctx, field)
case "additionalEmailAddresses":
return ec.fieldContext_Profile_additionalEmailAddresses(ctx, field)
case "kind":
@@ -12488,58 +12478,30 @@ func (ec *executionContext) fieldContext_SCIMEvent_errorMessage(_ context.Contex
return fc, nil
}
func (ec *executionContext) _SCIMEvent_profile(ctx context.Context, field graphql.CollectedField, obj *types.SCIMEvent) (ret graphql.Marshaler) {
func (ec *executionContext) _SCIMEvent_userName(ctx context.Context, field graphql.CollectedField, obj *types.SCIMEvent) (ret graphql.Marshaler) {
return graphql.ResolveField(
ctx,
ec.OperationContext,
field,
ec.fieldContext_SCIMEvent_profile,
ec.fieldContext_SCIMEvent_userName,
func(ctx context.Context) (any, error) {
return ec.resolvers.SCIMEvent().Profile(ctx, obj)
return obj.UserName, nil
},
nil,
ec.marshalOProfile2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋconnectᚋv1ᚋtypesᚐProfile,
ec.marshalNString2string,
true,
true,
false,
)
}
func (ec *executionContext) fieldContext_SCIMEvent_profile(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
func (ec *executionContext) fieldContext_SCIMEvent_userName(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
fc = &graphql.FieldContext{
Object: "SCIMEvent",
Field: field,
IsMethod: true,
IsResolver: true,
IsMethod: false,
IsResolver: false,
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
switch field.Name {
case "id":
return ec.fieldContext_Profile_id(ctx, field)
case "fullName":
return ec.fieldContext_Profile_fullName(ctx, field)
case "additionalEmailAddresses":
return ec.fieldContext_Profile_additionalEmailAddresses(ctx, field)
case "kind":
return ec.fieldContext_Profile_kind(ctx, field)
case "position":
return ec.fieldContext_Profile_position(ctx, field)
case "contractStartDate":
return ec.fieldContext_Profile_contractStartDate(ctx, field)
case "contractEndDate":
return ec.fieldContext_Profile_contractEndDate(ctx, field)
case "createdAt":
return ec.fieldContext_Profile_createdAt(ctx, field)
case "updatedAt":
return ec.fieldContext_Profile_updatedAt(ctx, field)
case "identity":
return ec.fieldContext_Profile_identity(ctx, field)
case "organization":
return ec.fieldContext_Profile_organization(ctx, field)
case "membership":
return ec.fieldContext_Profile_membership(ctx, field)
case "permission":
return ec.fieldContext_Profile_permission(ctx, field)
}
return nil, fmt.Errorf("no field named %q was found under type Profile", field.Name)
return nil, errors.New("field of type String does not have child fields")
},
}
return fc, nil
@@ -12803,8 +12765,8 @@ func (ec *executionContext) fieldContext_SCIMEventEdge_node(_ context.Context, f
return ec.fieldContext_SCIMEvent_responseBody(ctx, field)
case "errorMessage":
return ec.fieldContext_SCIMEvent_errorMessage(ctx, field)
case "profile":
return ec.fieldContext_SCIMEvent_profile(ctx, field)
case "userName":
return ec.fieldContext_SCIMEvent_userName(ctx, field)
case "ipAddress":
return ec.fieldContext_SCIMEvent_ipAddress(ctx, field)
case "createdAt":
@@ -13585,10 +13547,6 @@ func (ec *executionContext) fieldContext_UpdateMembershipPayload_membership(_ co
return ec.fieldContext_Membership_createdAt(ctx, field)
case "role":
return ec.fieldContext_Membership_role(ctx, field)
case "source":
return ec.fieldContext_Membership_source(ctx, field)
case "state":
return ec.fieldContext_Membership_state(ctx, field)
case "lastSession":
return ec.fieldContext_Membership_lastSession(ctx, field)
case "permission":
@@ -13691,6 +13649,10 @@ func (ec *executionContext) fieldContext_UpdateProfilePayload_profile(_ context.
return ec.fieldContext_Profile_id(ctx, field)
case "fullName":
return ec.fieldContext_Profile_fullName(ctx, field)
case "source":
return ec.fieldContext_Profile_source(ctx, field)
case "state":
return ec.fieldContext_Profile_state(ctx, field)
case "additionalEmailAddresses":
return ec.fieldContext_Profile_additionalEmailAddresses(ctx, field)
case "kind":
@@ -18019,16 +17981,6 @@ func (ec *executionContext) _Membership(ctx context.Context, sel ast.SelectionSe
if out.Values[i] == graphql.Null {
atomic.AddUint32(&out.Invalids, 1)
}
case "source":
out.Values[i] = ec._Membership_source(ctx, field, obj)
if out.Values[i] == graphql.Null {
atomic.AddUint32(&out.Invalids, 1)
}
case "state":
out.Values[i] = ec._Membership_state(ctx, field, obj)
if out.Values[i] == graphql.Null {
atomic.AddUint32(&out.Invalids, 1)
}
case "lastSession":
field := field
@@ -19023,6 +18975,16 @@ func (ec *executionContext) _Profile(ctx context.Context, sel ast.SelectionSet,
if out.Values[i] == graphql.Null {
atomic.AddUint32(&out.Invalids, 1)
}
case "source":
out.Values[i] = ec._Profile_source(ctx, field, obj)
if out.Values[i] == graphql.Null {
atomic.AddUint32(&out.Invalids, 1)
}
case "state":
out.Values[i] = ec._Profile_state(ctx, field, obj)
if out.Values[i] == graphql.Null {
atomic.AddUint32(&out.Invalids, 1)
}
case "additionalEmailAddresses":
out.Values[i] = ec._Profile_additionalEmailAddresses(ctx, field, obj)
if out.Values[i] == graphql.Null {
@@ -20471,39 +20433,11 @@ func (ec *executionContext) _SCIMEvent(ctx context.Context, sel ast.SelectionSet
out.Values[i] = ec._SCIMEvent_responseBody(ctx, field, obj)
case "errorMessage":
out.Values[i] = ec._SCIMEvent_errorMessage(ctx, field, obj)
case "profile":
field := field
innerFunc := func(ctx context.Context, _ *graphql.FieldSet) (res graphql.Marshaler) {
defer func() {
if r := recover(); r != nil {
ec.Error(ctx, ec.Recover(ctx, r))
}
}()
res = ec._SCIMEvent_profile(ctx, field, obj)
return res
case "userName":
out.Values[i] = ec._SCIMEvent_userName(ctx, field, obj)
if out.Values[i] == graphql.Null {
atomic.AddUint32(&out.Invalids, 1)
}
if field.Deferrable != nil {
dfs, ok := deferred[field.Deferrable.Label]
di := 0
if ok {
dfs.AddField(field)
di = len(dfs.Values) - 1
} else {
dfs = graphql.NewFieldSet([]graphql.CollectedField{field})
deferred[field.Deferrable.Label] = dfs
}
dfs.Concurrently(di, func(ctx context.Context) graphql.Marshaler {
return innerFunc(ctx, dfs)
})
// don't run the out.Concurrently() call below
out.Values[i] = graphql.Null
continue
}
out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) })
case "ipAddress":
out.Values[i] = ec._SCIMEvent_ipAddress(ctx, field, obj)
if out.Values[i] == graphql.Null {
@@ -22073,64 +22007,6 @@ var (
}
)
func (ec *executionContext) unmarshalNMembershipSource2goᚗproboᚗincᚋproboᚋpkgᚋcoredataᚐMembershipSource(ctx context.Context, v any) (coredata.MembershipSource, error) {
tmp, err := graphql.UnmarshalString(v)
res := unmarshalNMembershipSource2goᚗproboᚗincᚋproboᚋpkgᚋcoredataᚐMembershipSource[tmp]
return res, graphql.ErrorOnPath(ctx, err)
}
func (ec *executionContext) marshalNMembershipSource2goᚗproboᚗincᚋproboᚋpkgᚋcoredataᚐMembershipSource(ctx context.Context, sel ast.SelectionSet, v coredata.MembershipSource) graphql.Marshaler {
_ = sel
res := graphql.MarshalString(marshalNMembershipSource2goᚗproboᚗincᚋproboᚋpkgᚋcoredataᚐMembershipSource[v])
if res == graphql.Null {
if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {
graphql.AddErrorf(ctx, "the requested element is null which the schema does not allow")
}
}
return res
}
var (
unmarshalNMembershipSource2goᚗproboᚗincᚋproboᚋpkgᚋcoredataᚐMembershipSource = map[string]coredata.MembershipSource{
"MANUAL": coredata.MembershipSourceManual,
"SAML": coredata.MembershipSourceSAML,
"SCIM": coredata.MembershipSourceSCIM,
}
marshalNMembershipSource2goᚗproboᚗincᚋproboᚋpkgᚋcoredataᚐMembershipSource = map[coredata.MembershipSource]string{
coredata.MembershipSourceManual: "MANUAL",
coredata.MembershipSourceSAML: "SAML",
coredata.MembershipSourceSCIM: "SCIM",
}
)
func (ec *executionContext) unmarshalNMembershipState2goᚗproboᚗincᚋproboᚋpkgᚋcoredataᚐMembershipState(ctx context.Context, v any) (coredata.MembershipState, error) {
tmp, err := graphql.UnmarshalString(v)
res := unmarshalNMembershipState2goᚗproboᚗincᚋproboᚋpkgᚋcoredataᚐMembershipState[tmp]
return res, graphql.ErrorOnPath(ctx, err)
}
func (ec *executionContext) marshalNMembershipState2goᚗproboᚗincᚋproboᚋpkgᚋcoredataᚐMembershipState(ctx context.Context, sel ast.SelectionSet, v coredata.MembershipState) graphql.Marshaler {
_ = sel
res := graphql.MarshalString(marshalNMembershipState2goᚗproboᚗincᚋproboᚋpkgᚋcoredataᚐMembershipState[v])
if res == graphql.Null {
if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {
graphql.AddErrorf(ctx, "the requested element is null which the schema does not allow")
}
}
return res
}
var (
unmarshalNMembershipState2goᚗproboᚗincᚋproboᚋpkgᚋcoredataᚐMembershipState = map[string]coredata.MembershipState{
"ACTIVE": coredata.MembershipStateActive,
"INACTIVE": coredata.MembershipStateInactive,
}
marshalNMembershipState2goᚗproboᚗincᚋproboᚋpkgᚋcoredataᚐMembershipState = map[coredata.MembershipState]string{
coredata.MembershipStateActive: "ACTIVE",
coredata.MembershipStateInactive: "INACTIVE",
}
)
func (ec *executionContext) unmarshalNOrderDirection2goᚗproboᚗincᚋproboᚋpkgᚋpageᚐOrderDirection(ctx context.Context, v any) (page.OrderDirection, error) {
tmp, err := graphql.UnmarshalString(v)
res := unmarshalNOrderDirection2goᚗproboᚗincᚋproboᚋpkgᚋpageᚐOrderDirection[tmp]
@@ -22363,6 +22239,34 @@ var (
}
)
func (ec *executionContext) unmarshalNProfileState2goᚗproboᚗincᚋproboᚋpkgᚋcoredataᚐProfileState(ctx context.Context, v any) (coredata.ProfileState, error) {
tmp, err := graphql.UnmarshalString(v)
res := unmarshalNProfileState2goᚗproboᚗincᚋproboᚋpkgᚋcoredataᚐProfileState[tmp]
return res, graphql.ErrorOnPath(ctx, err)
}
func (ec *executionContext) marshalNProfileState2goᚗproboᚗincᚋproboᚋpkgᚋcoredataᚐProfileState(ctx context.Context, sel ast.SelectionSet, v coredata.ProfileState) graphql.Marshaler {
_ = sel
res := graphql.MarshalString(marshalNProfileState2goᚗproboᚗincᚋproboᚋpkgᚋcoredataᚐProfileState[v])
if res == graphql.Null {
if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {
graphql.AddErrorf(ctx, "the requested element is null which the schema does not allow")
}
}
return res
}
var (
unmarshalNProfileState2goᚗproboᚗincᚋproboᚋpkgᚋcoredataᚐProfileState = map[string]coredata.ProfileState{
"ACTIVE": coredata.ProfileStateActive,
"INACTIVE": coredata.ProfileStateInactive,
}
marshalNProfileState2goᚗproboᚗincᚋproboᚋpkgᚋcoredataᚐProfileState = map[coredata.ProfileState]string{
coredata.ProfileStateActive: "ACTIVE",
coredata.ProfileStateInactive: "INACTIVE",
}
)
func (ec *executionContext) unmarshalNReauthenticationReason2goᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋconnectᚋv1ᚋtypesᚐReauthenticationReason(ctx context.Context, v any) (types.ReauthenticationReason, error) {
var res types.ReauthenticationReason
err := res.UnmarshalGQL(v)

View File

@@ -46,13 +46,13 @@ type (
}
scimRequestContext struct {
ctx context.Context
config *coredata.SCIMConfiguration
ipAddress net.IP
method string
path string
membershipID *gid.GID
handler *scimResourceHandler
ctx context.Context
config *coredata.SCIMConfiguration
ipAddress net.IP
method string
path string
userName string
handler *scimResourceHandler
}
)
@@ -145,23 +145,23 @@ func (rc *scimRequestContext) logAndWrapError(err error, logMsg string) error {
if errors.As(err, &scimErr) {
errMsg := scimErr.Detail
// Don't reference membershipID for 404 errors - the resource doesn't exist
membershipID := rc.membershipID
// Don't reference profileID for 404 errors - the resource doesn't exist
userName := rc.userName
if scimErr.Status == http.StatusNotFound {
membershipID = nil
userName = ""
}
rc.handler.handler.iam.SCIMService.LogEvent(rc.ctx, rc.config, rc.method, rc.path, membershipID, rc.ipAddress, scimErr.Status, &errMsg)
rc.handler.handler.iam.SCIMService.LogEvent(rc.ctx, rc.config, rc.method, rc.path, userName, rc.ipAddress, scimErr.Status, &errMsg)
return err
}
rc.handler.handler.logger.ErrorCtx(rc.ctx, logMsg, log.Error(err))
errMsg := "internal server error"
rc.handler.handler.iam.SCIMService.LogEvent(rc.ctx, rc.config, rc.method, rc.path, rc.membershipID, rc.ipAddress, 500, &errMsg)
rc.handler.handler.iam.SCIMService.LogEvent(rc.ctx, rc.config, rc.method, rc.path, rc.userName, rc.ipAddress, 500, &errMsg)
return scimerrors.ScimErrorInternal
}
func (rc *scimRequestContext) logSuccess(statusCode int) {
rc.handler.handler.iam.SCIMService.LogEvent(rc.ctx, rc.config, rc.method, rc.path, rc.membershipID, rc.ipAddress, statusCode, nil)
rc.handler.handler.iam.SCIMService.LogEvent(rc.ctx, rc.config, rc.method, rc.path, rc.userName, rc.ipAddress, statusCode, nil)
}
func (h *scimResourceHandler) Create(r *http.Request, attributes scim.ResourceAttributes) (scim.Resource, error) {
@@ -179,9 +179,10 @@ func (h *scimResourceHandler) Create(r *http.Request, attributes scim.ResourceAt
return scim.Resource{}, rc.logAndWrapError(err, "cannot create user")
}
membershipID, _ := gid.ParseGID(resource.ID)
rc.membershipID = &membershipID
rc.userName = resource.Attributes["userName"].(string)
rc.logSuccess(201)
return resource, nil
}
@@ -195,18 +196,20 @@ func (h *scimResourceHandler) Get(r *http.Request, id string) (scim.Resource, er
handler: h,
}
membershipID, err := gid.ParseGID(id)
profileID, err := gid.ParseGID(id)
if err != nil {
return scim.Resource{}, rc.logAndWrapError(scimerrors.ScimErrorResourceNotFound(id), "invalid membership ID")
return scim.Resource{}, rc.logAndWrapError(scimerrors.ScimErrorResourceNotFound(id), "invalid profile ID")
}
rc.membershipID = &membershipID
resource, err := h.handler.iam.SCIMService.GetUser(rc.ctx, rc.config, membershipID)
resource, err := h.handler.iam.SCIMService.GetUser(rc.ctx, rc.config, profileID)
if err != nil {
return scim.Resource{}, rc.logAndWrapError(err, "cannot get user")
}
rc.userName = resource.Attributes["userName"].(string)
rc.logSuccess(200)
return resource, nil
}
@@ -256,18 +259,20 @@ func (h *scimResourceHandler) Replace(r *http.Request, id string, attributes sci
handler: h,
}
membershipID, err := gid.ParseGID(id)
profileID, err := gid.ParseGID(id)
if err != nil {
return scim.Resource{}, rc.logAndWrapError(scimerrors.ScimErrorResourceNotFound(id), "invalid membership ID")
return scim.Resource{}, rc.logAndWrapError(scimerrors.ScimErrorResourceNotFound(id), "invalid profile ID")
}
rc.membershipID = &membershipID
resource, err := h.handler.iam.SCIMService.ReplaceUser(rc.ctx, rc.config, membershipID, attributes)
resource, err := h.handler.iam.SCIMService.ReplaceUser(rc.ctx, rc.config, profileID, attributes)
if err != nil {
return scim.Resource{}, rc.logAndWrapError(err, "cannot update user")
}
rc.userName = resource.Attributes["userName"].(string)
rc.logSuccess(200)
return resource, nil
}
@@ -281,18 +286,20 @@ func (h *scimResourceHandler) Patch(r *http.Request, id string, operations []sci
handler: h,
}
membershipID, err := gid.ParseGID(id)
profileID, err := gid.ParseGID(id)
if err != nil {
return scim.Resource{}, rc.logAndWrapError(scimerrors.ScimErrorResourceNotFound(id), "invalid membership ID")
return scim.Resource{}, rc.logAndWrapError(scimerrors.ScimErrorResourceNotFound(id), "invalid profile ID")
}
rc.membershipID = &membershipID
resource, err := h.handler.iam.SCIMService.PatchUser(rc.ctx, rc.config, membershipID, operations)
resource, err := h.handler.iam.SCIMService.PatchUser(rc.ctx, rc.config, profileID, operations)
if err != nil {
return scim.Resource{}, rc.logAndWrapError(err, "cannot patch user")
}
rc.userName = resource.Attributes["userName"].(string)
rc.logSuccess(200)
return resource, nil
}
@@ -306,19 +313,20 @@ func (h *scimResourceHandler) Delete(r *http.Request, id string) error {
handler: h,
}
membershipID, err := gid.ParseGID(id)
profileID, err := gid.ParseGID(id)
if err != nil {
return rc.logAndWrapError(scimerrors.ScimErrorResourceNotFound(id), "invalid membership ID")
return rc.logAndWrapError(scimerrors.ScimErrorResourceNotFound(id), "invalid profile ID")
}
rc.membershipID = &membershipID
err = h.handler.iam.SCIMService.DeleteUser(rc.ctx, rc.config, membershipID)
err = h.handler.iam.SCIMService.DeleteUser(rc.ctx, rc.config, profileID)
if err != nil {
return rc.logAndWrapError(err, "cannot delete user")
}
rc.membershipID = nil
rc.userName = ""
rc.logSuccess(204)
return nil
}

View File

@@ -23,7 +23,5 @@ func NewMembership(membership *coredata.Membership) *Membership {
ID: membership.ID,
CreatedAt: membership.CreatedAt,
Role: membership.Role,
Source: membership.Source,
State: membership.State,
}
}

View File

@@ -66,6 +66,8 @@ func NewProfile(profile *coredata.MembershipProfile) *Profile {
return &Profile{
ID: profile.ID,
FullName: profile.FullName,
Source: profile.Source.String(),
State: profile.State,
AdditionalEmailAddresses: profile.AdditionalEmailAddresses,
Kind: profile.Kind,
Position: profile.Position,

View File

@@ -64,6 +64,7 @@ func NewSCIMEvent(scimEvent *coredata.SCIMEvent) *SCIMEvent {
ID: scimEvent.ID,
Method: scimEvent.Method,
Path: scimEvent.Path,
UserName: scimEvent.UserName,
StatusCode: scimEvent.StatusCode,
RequestBody: scimEvent.RequestBody,
ResponseBody: scimEvent.ResponseBody,
@@ -72,12 +73,5 @@ func NewSCIMEvent(scimEvent *coredata.SCIMEvent) *SCIMEvent {
CreatedAt: scimEvent.CreatedAt,
}
// FIXME: profile
// if scimEvent.MembershipID != nil {
// event.Membership = &Membership{
// ID: *scimEvent.MembershipID,
// }
// }
return event
}

View File

@@ -220,13 +220,11 @@ type InviteMemberPayload struct {
}
type Membership struct {
ID gid.GID `json:"id"`
CreatedAt time.Time `json:"createdAt"`
Role coredata.MembershipRole `json:"role"`
Source coredata.MembershipSource `json:"source"`
State coredata.MembershipState `json:"state"`
LastSession *Session `json:"lastSession,omitempty"`
Permission bool `json:"permission"`
ID gid.GID `json:"id"`
CreatedAt time.Time `json:"createdAt"`
Role coredata.MembershipRole `json:"role"`
LastSession *Session `json:"lastSession,omitempty"`
Permission bool `json:"permission"`
}
func (Membership) IsNode() {}
@@ -298,6 +296,8 @@ type PersonalAPIKeyEdge struct {
type Profile struct {
ID gid.GID `json:"id"`
FullName string `json:"fullName"`
Source string `json:"source"`
State coredata.ProfileState `json:"state"`
AdditionalEmailAddresses []mail.Addr `json:"additionalEmailAddresses"`
Kind coredata.MembershipProfileKind `json:"kind"`
Position *string `json:"position,omitempty"`
@@ -452,7 +452,7 @@ type SCIMEvent struct {
RequestBody *string `json:"requestBody,omitempty"`
ResponseBody *string `json:"responseBody,omitempty"`
ErrorMessage *string `json:"errorMessage,omitempty"`
Profile *Profile `json:"profile,omitempty"`
UserName string `json:"userName"`
IPAddress string `json:"ipAddress"`
CreatedAt time.Time `json:"createdAt"`
Permission bool `json:"permission"`

View File

@@ -360,9 +360,9 @@ func (r *mutationResolver) SignIn(ctx context.Context, input types.SignInInput)
if err != nil {
// Here session middleware already took care of expired/nil root session so we only handle membership related errors
var errMembershipNotFound *iam.ErrMembershipNotFound
var errMembershipInactive *iam.ErrMembershipInactive
var errUserInactive *iam.ErrUserInactive
if errors.As(err, &errMembershipNotFound) || errors.As(err, &errMembershipInactive) {
if errors.As(err, &errMembershipNotFound) || errors.As(err, &errUserInactive) {
return nil, gqlutils.Forbiddenf(ctx, "forbidden")
}
@@ -890,13 +890,13 @@ func (r *mutationResolver) InviteMember(ctx context.Context, input types.InviteM
)
if err != nil {
var errOrganizationNotFound *iam.ErrOrganizationNotFound
var errMembershipAlreadyExists *iam.ErrMembershipAlreadyExists
var errUserAlreadyExists *iam.ErrUserAlreadyExists
if errors.As(err, &errOrganizationNotFound) {
return nil, gqlutils.NotFound(ctx, err)
}
if errors.As(err, &errMembershipAlreadyExists) {
if errors.As(err, &errUserAlreadyExists) {
return nil, gqlutils.Conflict(ctx, err)
}
@@ -994,7 +994,7 @@ func (r *mutationResolver) RemoveMember(ctx context.Context, input types.RemoveM
err := r.iam.OrganizationService.RemoveMember(ctx, input.OrganizationID, input.MembershipID)
if err != nil {
var errManagedBySCIM *iam.ErrMembershipManagedBySCIM
var errManagedBySCIM *iam.ErrUserManagedBySCIM
var errLastActiveOwner *iam.ErrLastActiveOwner
if errors.As(err, &errManagedBySCIM) {
@@ -1889,11 +1889,6 @@ func (r *sCIMConfigurationResolver) Permission(ctx context.Context, obj *types.S
return r.Resolver.Permission(ctx, obj, action)
}
// Profile is the resolver for the profile field.
func (r *sCIMEventResolver) Profile(ctx context.Context, obj *types.SCIMEvent) (*types.Profile, error) {
panic(fmt.Errorf("not implemented: Profile - profile"))
}
// Permission is the resolver for the permission field.
func (r *sCIMEventResolver) Permission(ctx context.Context, obj *types.SCIMEvent, action string) (bool, error) {
return r.Resolver.Permission(ctx, obj, action)