Consolidate hub type definitions into their own files

Move Organization, Identity, TrustCenter, and Viewer definitions to
include all their connection fields directly, removing all extend type
blocks for these hub types from entity files.

This eliminates the Relay schemaExtensions constraint where extend type
could only target types defined in the main schema file. Entity files
now only define their own standalone types and extend type Mutation.

Signed-off-by: Émile Ré <emile@getprobo.com>
This commit is contained in:
Émile Ré
2026-04-14 18:02:38 +04:00
parent 31cca05ca4
commit 5f93071b20
70 changed files with 2208 additions and 2279 deletions

View File

@@ -10,12 +10,9 @@ import (
"go.gearno.de/kit/log"
"go.probo.inc/probo/pkg/coredata"
"go.probo.inc/probo/pkg/iam"
"go.probo.inc/probo/pkg/page"
"go.probo.inc/probo/pkg/server/api/connect/v1/schema"
"go.probo.inc/probo/pkg/server/api/connect/v1/types"
"go.probo.inc/probo/pkg/server/gqlutils"
"go.probo.inc/probo/pkg/server/gqlutils/types/cursor"
)
// Organization is the resolver for the organization field.
@@ -44,50 +41,6 @@ func (r *auditLogEntryConnectionResolver) TotalCount(ctx context.Context, obj *t
return count, nil
}
// AuditLogEntries is the resolver for the auditLogEntries field.
func (r *organizationResolver) AuditLogEntries(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.AuditLogEntryOrderBy, filter *types.AuditLogEntryFilter) (*types.AuditLogEntryConnection, error) {
if err := r.authorize(ctx, obj.ID, iam.ActionAuditLogEntryList); err != nil {
return nil, err
}
pageOrderBy := page.OrderBy[coredata.AuditLogEntryOrderField]{
Field: coredata.AuditLogEntryOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.AuditLogEntryOrderField]{
Field: orderBy.Field,
Direction: orderBy.Direction,
}
}
c := cursor.NewCursor(first, after, last, before, pageOrderBy)
coredataFilter := coredata.NewAuditLogEntryFilter()
if filter != nil {
if filter.Action != nil {
coredataFilter.WithAction(*filter.Action)
}
if filter.ActorID != nil {
coredataFilter.WithActorID(*filter.ActorID)
}
if filter.ResourceType != nil {
coredataFilter.WithResourceType(*filter.ResourceType)
}
if filter.ResourceID != nil {
coredataFilter.WithResourceID(*filter.ResourceID)
}
}
p, err := r.iam.OrganizationService.ListAuditLogEntries(ctx, obj.ID, c, coredataFilter)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot list audit log entries", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return types.NewAuditLogEntryConnection(p, r, obj.ID, coredataFilter), nil
}
// AuditLogEntry returns schema.AuditLogEntryResolver implementation.
func (r *Resolver) AuditLogEntry() schema.AuditLogEntryResolver { return &auditLogEntryResolver{r} }

View File

@@ -10,7 +10,6 @@ import (
"errors"
"fmt"
"strings"
"time"
"github.com/99designs/gqlgen/graphql"
"github.com/vektah/gqlparser/v2/gqlerror"
@@ -19,13 +18,123 @@ import (
"go.probo.inc/probo/pkg/gid"
"go.probo.inc/probo/pkg/iam"
"go.probo.inc/probo/pkg/mail"
"go.probo.inc/probo/pkg/page"
"go.probo.inc/probo/pkg/server/api/authn"
"go.probo.inc/probo/pkg/server/api/authz"
"go.probo.inc/probo/pkg/server/api/connect/v1/schema"
"go.probo.inc/probo/pkg/server/api/connect/v1/types"
"go.probo.inc/probo/pkg/server/gqlutils"
"go.probo.inc/probo/pkg/server/gqlutils/types/cursor"
)
// Profiles is the resolver for the profiles field.
func (r *identityResolver) Profiles(ctx context.Context, obj *types.Identity, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.ProfileOrderBy, filter *types.ProfileFilter) (*types.ProfileConnection, error) {
if err := r.authorize(ctx, obj.ID, iam.ActionMembershipProfileList, authz.WithSkipAssumptionCheck()); err != nil {
return nil, err
}
filters := coredata.NewMembershipProfileFilter(nil).WithMembership()
if filter != nil {
filters = coredata.NewMembershipProfileFilter(filter.ExcludeContractEnded).WithMembership()
if filter.State != nil {
filters.WithState(*filter.State)
}
}
if gqlutils.OnlyTotalCountSelected(ctx) {
return &types.ProfileConnection{
Resolver: r,
ParentID: obj.ID,
Filters: filters,
}, nil
}
pageOrderBy := page.OrderBy[coredata.MembershipProfileOrderField]{
Field: coredata.MembershipProfileOrderFieldFullName,
Direction: page.OrderDirectionAsc,
}
if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.MembershipProfileOrderField]{
Field: orderBy.Field,
Direction: orderBy.Direction,
}
}
cursor := cursor.NewCursor(first, after, last, before, pageOrderBy)
page, err := r.iam.AccountService.ListProfilesForIdentity(ctx, obj.ID, cursor, filters)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot list profiles", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return types.NewProfileConnection(page, r, obj.ID, filters), nil
}
// Sessions is the resolver for the sessions field.
func (r *identityResolver) Sessions(ctx context.Context, obj *types.Identity, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.SessionOrder) (*types.SessionConnection, error) {
if err := r.authorize(ctx, obj.ID, iam.ActionSessionList); err != nil {
return nil, err
}
if gqlutils.OnlyTotalCountSelected(ctx) {
return &types.SessionConnection{
Resolver: r,
ParentID: obj.ID,
}, nil
}
pageOrderBy := page.OrderBy[coredata.SessionOrderField]{
Field: coredata.SessionOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.SessionOrderField]{
Field: orderBy.Field,
Direction: orderBy.Direction,
}
}
cursor := cursor.NewCursor(first, after, last, before, pageOrderBy)
page, err := r.iam.AccountService.ListSessions(ctx, obj.ID, cursor)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot list sessions", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return types.NewSessionConnection(page, r, obj.ID), nil
}
// PersonalAPIKeys is the resolver for the personalAPIKeys field.
func (r *identityResolver) PersonalAPIKeys(ctx context.Context, obj *types.Identity, first *int, after *page.CursorKey, last *int, before *page.CursorKey) (*types.PersonalAPIKeyConnection, error) {
if err := r.authorize(ctx, obj.ID, iam.ActionPersonalAPIKeyList); err != nil {
return nil, err
}
if gqlutils.OnlyTotalCountSelected(ctx) {
return &types.PersonalAPIKeyConnection{
Resolver: r,
ParentID: obj.ID,
}, nil
}
pageOrderBy := page.OrderBy[coredata.PersonalAPIKeyOrderField]{
Field: coredata.PersonalAPIKeyOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
cursor := cursor.NewCursor(first, after, last, before, pageOrderBy)
page, err := r.iam.AccountService.ListPersonalAPIKeys(ctx, obj.ID, cursor)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot list personal api keys", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return types.NewPersonalAPIKeyConnection(page, r, obj.ID), nil
}
// SsoLoginURL is the resolver for the ssoLoginURL field.
func (r *identityResolver) SsoLoginURL(ctx context.Context, obj *types.Identity) (*string, error) {
if err := r.authorize(ctx, obj.ID, iam.ActionIdentityGet); err != nil {
@@ -525,63 +634,6 @@ func (r *mutationResolver) RevokeAllSessions(ctx context.Context) (*types.Revoke
return &types.RevokeAllSessionsPayload{RevokedCount: int(revokedCount)}, nil
}
// LogoURL is the resolver for the logoUrl field.
func (r *organizationResolver) LogoURL(ctx context.Context, obj *types.Organization) (*string, error) {
if err := r.authorize(ctx, obj.ID, iam.ActionOrganizationGet, authz.WithSkipAssumptionCheck()); err != nil {
return nil, err
}
presignedURL, err := r.iam.OrganizationService.GenerateLogoURL(ctx, obj.ID, 1*time.Hour)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot generate logo URL", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return presignedURL, nil
}
// HorizontalLogoURL is the resolver for the horizontalLogoUrl field.
func (r *organizationResolver) HorizontalLogoURL(ctx context.Context, obj *types.Organization) (*string, error) {
if err := r.authorize(ctx, obj.ID, iam.ActionOrganizationGet); err != nil {
return nil, err
}
presignedURL, err := r.iam.OrganizationService.GenerateHorizontalLogoURL(ctx, obj.ID, 1*time.Hour)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot generate horizontal logo URL", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return presignedURL, nil
}
// Viewer is the resolver for the viewer field.
func (r *organizationResolver) Viewer(ctx context.Context, obj *types.Organization) (*types.Profile, error) {
if err := r.authorize(ctx, obj.ID, iam.ActionMembershipProfileGet); err != nil {
return nil, err
}
identity := authn.IdentityFromContext(ctx)
profile, err := r.iam.OrganizationService.GetProfileForIdentityAndOrganization(ctx, identity.ID, obj.ID)
if err != nil {
var errNotFound *iam.ErrProfileNotFound
if errors.As(err, &errNotFound) {
return nil, gqlutils.NotFound(ctx, err)
}
r.logger.ErrorCtx(ctx, "cannot get profile", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return types.NewProfile(profile), nil
}
// Permission is the resolver for the permission field.
func (r *organizationResolver) Permission(ctx context.Context, obj *types.Organization, action string) (bool, error) {
return r.Resolver.Permission(ctx, obj, action)
}
// Node is the resolver for the node field.
func (r *queryResolver) Node(ctx context.Context, id gid.GID) (types.Node, error) {
var (
@@ -797,13 +849,9 @@ func (r *Resolver) Identity() schema.IdentityResolver { return &identityResolver
// Mutation returns schema.MutationResolver implementation.
func (r *Resolver) Mutation() schema.MutationResolver { return &mutationResolver{r} }
// Organization returns schema.OrganizationResolver implementation.
func (r *Resolver) Organization() schema.OrganizationResolver { return &organizationResolver{r} }
// Query returns schema.QueryResolver implementation.
func (r *Resolver) Query() schema.QueryResolver { return &queryResolver{r} }
type identityResolver struct{ *Resolver }
type mutationResolver struct{ *Resolver }
type organizationResolver struct{ *Resolver }
type queryResolver struct{ *Resolver }

View File

@@ -1,14 +1,3 @@
extend type Organization {
auditLogEntries(
first: Int
after: CursorKey
last: Int
before: CursorKey
orderBy: AuditLogEntryOrder
filter: AuditLogEntryFilter
): AuditLogEntryConnection! @goField(forceResolver: true)
}
enum AuditLogActorType
@goModel(
model: "go.probo.inc/probo/pkg/coredata.AuditLogActorType"

View File

@@ -66,6 +66,30 @@ type Identity implements Node {
createdAt: Datetime!
updatedAt: Datetime!
profiles(
first: Int
after: CursorKey
last: Int
before: CursorKey
orderBy: ProfileOrder
filter: ProfileFilter
): ProfileConnection @goField(forceResolver: true)
sessions(
first: Int
after: CursorKey
last: Int
before: CursorKey
orderBy: SessionOrder
): SessionConnection @goField(forceResolver: true)
personalAPIKeys(
first: Int
after: CursorKey
last: Int
before: CursorKey
): PersonalAPIKeyConnection @goField(forceResolver: true)
ssoLoginURL: String
@goField(forceResolver: true)
@session(required: PRESENT)
@@ -75,25 +99,6 @@ type Identity implements Node {
@session(required: PRESENT)
}
type Organization implements Node {
id: ID!
name: String!
logoUrl: String @goField(forceResolver: true)
horizontalLogoUrl: String @goField(forceResolver: true)
email: String
description: String
websiteUrl: String
headquarterAddress: String
createdAt: Datetime!
updatedAt: Datetime!
viewer: Profile @goField(forceResolver: true)
permission(action: String!): Boolean!
@goField(forceResolver: true)
@session(required: PRESENT)
}
type Mutation {
signIn(input: SignInInput!): SignInPayload @session(required: OPTIONAL)
signUp(input: SignUpInput!): SignUpPayload @session(required: NONE)

View File

@@ -1,3 +1,49 @@
type Organization implements Node {
id: ID!
name: String!
logoUrl: String @goField(forceResolver: true)
horizontalLogoUrl: String @goField(forceResolver: true)
email: String
description: String
websiteUrl: String
headquarterAddress: String
createdAt: Datetime!
updatedAt: Datetime!
profiles(
first: Int
after: CursorKey
last: Int
before: CursorKey
orderBy: ProfileOrder
): ProfileConnection @goField(forceResolver: true)
samlConfigurations(
first: Int
after: CursorKey
last: Int
before: CursorKey
): SAMLConfigurationConnection @goField(forceResolver: true)
scimConfiguration: SCIMConfiguration @goField(forceResolver: true)
scimBridgeTypes: [SCIMBridgeTypeInfo!]! @goField(forceResolver: true)
auditLogEntries(
first: Int
after: CursorKey
last: Int
before: CursorKey
orderBy: AuditLogEntryOrder
filter: AuditLogEntryFilter
): AuditLogEntryConnection! @goField(forceResolver: true)
viewer: Profile @goField(forceResolver: true)
permission(action: String!): Boolean!
@goField(forceResolver: true)
@session(required: PRESENT)
}
extend type Mutation {
createOrganization(
input: CreateOrganizationInput!

View File

@@ -1,12 +1,3 @@
extend type Identity {
personalAPIKeys(
first: Int
after: CursorKey
last: Int
before: CursorKey
): PersonalAPIKeyConnection @goField(forceResolver: true)
}
type PersonalAPIKey implements Node {
id: ID!
name: String!

View File

@@ -1,24 +1,3 @@
extend type Identity {
profiles(
first: Int
after: CursorKey
last: Int
before: CursorKey
orderBy: ProfileOrder
filter: ProfileFilter
): ProfileConnection @goField(forceResolver: true)
}
extend type Organization {
profiles(
first: Int
after: CursorKey
last: Int
before: CursorKey
orderBy: ProfileOrder
): ProfileConnection @goField(forceResolver: true)
}
type Profile implements Node {
id: ID!
fullName: String!

View File

@@ -1,12 +1,3 @@
extend type Organization {
samlConfigurations(
first: Int
after: CursorKey
last: Int
before: CursorKey
): SAMLConfigurationConnection @goField(forceResolver: true)
}
type SAMLConfiguration implements Node {
id: ID!
emailDomain: String!

View File

@@ -1,8 +1,3 @@
extend type Organization {
scimConfiguration: SCIMConfiguration @goField(forceResolver: true)
scimBridgeTypes: [SCIMBridgeTypeInfo!]! @goField(forceResolver: true)
}
type SCIMConfiguration implements Node {
id: ID!
endpointUrl: String! @goField(forceResolver: true)

View File

@@ -13,16 +13,6 @@ input SessionOrder {
field: SessionOrderField!
}
extend type Identity {
sessions(
first: Int
after: CursorKey
last: Int
before: CursorKey
orderBy: SessionOrder
): SessionConnection @goField(forceResolver: true)
}
type Session implements Node {
id: ID!
identity: Identity @goField(forceResolver: true)

View File

@@ -9,13 +9,19 @@ import (
"context"
"errors"
"fmt"
"time"
"go.gearno.de/kit/log"
"go.probo.inc/probo/pkg/coredata"
"go.probo.inc/probo/pkg/iam"
"go.probo.inc/probo/pkg/iam/scim/bridge/provider/googleworkspace"
"go.probo.inc/probo/pkg/page"
"go.probo.inc/probo/pkg/server/api/authn"
"go.probo.inc/probo/pkg/server/api/authz"
"go.probo.inc/probo/pkg/server/api/connect/v1/schema"
"go.probo.inc/probo/pkg/server/api/connect/v1/types"
"go.probo.inc/probo/pkg/server/gqlutils"
"go.probo.inc/probo/pkg/server/gqlutils/types/cursor"
)
// CreateOrganization is the resolver for the createOrganization field.
@@ -148,3 +154,206 @@ func (r *mutationResolver) DeleteOrganization(ctx context.Context, input types.D
func (r *mutationResolver) DeleteOrganizationHorizontalLogo(ctx context.Context, input types.DeleteOrganizationHorizontalLogoInput) (*types.DeleteOrganizationHorizontalLogoPayload, error) {
panic(fmt.Errorf("not implemented: DeleteOrganizationHorizontalLogo - deleteOrganizationHorizontalLogo"))
}
// LogoURL is the resolver for the logoUrl field.
func (r *organizationResolver) LogoURL(ctx context.Context, obj *types.Organization) (*string, error) {
if err := r.authorize(ctx, obj.ID, iam.ActionOrganizationGet, authz.WithSkipAssumptionCheck()); err != nil {
return nil, err
}
presignedURL, err := r.iam.OrganizationService.GenerateLogoURL(ctx, obj.ID, 1*time.Hour)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot generate logo URL", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return presignedURL, nil
}
// HorizontalLogoURL is the resolver for the horizontalLogoUrl field.
func (r *organizationResolver) HorizontalLogoURL(ctx context.Context, obj *types.Organization) (*string, error) {
if err := r.authorize(ctx, obj.ID, iam.ActionOrganizationGet); err != nil {
return nil, err
}
presignedURL, err := r.iam.OrganizationService.GenerateHorizontalLogoURL(ctx, obj.ID, 1*time.Hour)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot generate horizontal logo URL", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return presignedURL, nil
}
// Profiles is the resolver for the profiles field.
func (r *organizationResolver) Profiles(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.ProfileOrderBy) (*types.ProfileConnection, error) {
if err := r.authorize(ctx, obj.ID, iam.ActionMembershipProfileList); err != nil {
return nil, err
}
filter := coredata.NewMembershipProfileFilter(nil).WithMembership()
if gqlutils.OnlyTotalCountSelected(ctx) {
return &types.ProfileConnection{
Resolver: r,
ParentID: obj.ID,
Filters: filter,
}, nil
}
pageOrderBy := page.OrderBy[coredata.MembershipProfileOrderField]{
Field: coredata.MembershipProfileOrderFieldFullName,
Direction: page.OrderDirectionAsc,
}
if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.MembershipProfileOrderField]{
Field: orderBy.Field,
Direction: orderBy.Direction,
}
}
cursor := cursor.NewCursor(first, after, last, before, pageOrderBy)
page, err := r.iam.OrganizationService.ListProfiles(ctx, obj.ID, cursor, filter)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot list profiles", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return types.NewProfileConnection(page, r, obj.ID, filter), nil
}
// SamlConfigurations is the resolver for the samlConfigurations field.
func (r *organizationResolver) SamlConfigurations(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey) (*types.SAMLConfigurationConnection, error) {
if err := r.authorize(ctx, obj.ID, iam.ActionSAMLConfigurationList); err != nil {
return nil, err
}
if gqlutils.OnlyTotalCountSelected(ctx) {
return &types.SAMLConfigurationConnection{
Resolver: r,
ParentID: obj.ID,
}, nil
}
pageOrderBy := page.OrderBy[coredata.SAMLConfigurationOrderField]{
Field: coredata.SAMLConfigurationOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
cursor := cursor.NewCursor(first, after, last, before, pageOrderBy)
page, err := r.iam.OrganizationService.ListSAMLConfigurations(ctx, obj.ID, cursor)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot list saml configurations", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return types.NewSAMLConfigurationConnection(page, r, obj.ID), nil
}
// ScimConfiguration is the resolver for the scimConfiguration field.
func (r *organizationResolver) ScimConfiguration(ctx context.Context, obj *types.Organization) (*types.SCIMConfiguration, error) {
if err := r.authorize(ctx, obj.ID, iam.ActionSCIMConfigurationGet); err != nil {
return nil, err
}
config, err := r.iam.OrganizationService.GetSCIMConfiguration(ctx, obj.ID)
if err != nil {
var notFound *iam.ErrNoSCIMConfigurationFound
if errors.As(err, &notFound) {
return nil, nil
}
r.logger.ErrorCtx(ctx, "cannot get scim configuration", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return types.NewSCIMConfiguration(config), nil
}
// ScimBridgeTypes is the resolver for the scimBridgeTypes field.
func (r *organizationResolver) ScimBridgeTypes(ctx context.Context, obj *types.Organization) ([]*types.SCIMBridgeTypeInfo, error) {
return []*types.SCIMBridgeTypeInfo{
{
Type: coredata.SCIMBridgeTypeGoogleWorkspace,
Oauth2Scopes: googleworkspace.OAuth2Scopes,
},
}, nil
}
// AuditLogEntries is the resolver for the auditLogEntries field.
func (r *organizationResolver) AuditLogEntries(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.AuditLogEntryOrderBy, filter *types.AuditLogEntryFilter) (*types.AuditLogEntryConnection, error) {
if err := r.authorize(ctx, obj.ID, iam.ActionAuditLogEntryList); err != nil {
return nil, err
}
pageOrderBy := page.OrderBy[coredata.AuditLogEntryOrderField]{
Field: coredata.AuditLogEntryOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.AuditLogEntryOrderField]{
Field: orderBy.Field,
Direction: orderBy.Direction,
}
}
c := cursor.NewCursor(first, after, last, before, pageOrderBy)
coredataFilter := coredata.NewAuditLogEntryFilter()
if filter != nil {
if filter.Action != nil {
coredataFilter.WithAction(*filter.Action)
}
if filter.ActorID != nil {
coredataFilter.WithActorID(*filter.ActorID)
}
if filter.ResourceType != nil {
coredataFilter.WithResourceType(*filter.ResourceType)
}
if filter.ResourceID != nil {
coredataFilter.WithResourceID(*filter.ResourceID)
}
}
p, err := r.iam.OrganizationService.ListAuditLogEntries(ctx, obj.ID, c, coredataFilter)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot list audit log entries", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return types.NewAuditLogEntryConnection(p, r, obj.ID, coredataFilter), nil
}
// Viewer is the resolver for the viewer field.
func (r *organizationResolver) Viewer(ctx context.Context, obj *types.Organization) (*types.Profile, error) {
if err := r.authorize(ctx, obj.ID, iam.ActionMembershipProfileGet); err != nil {
return nil, err
}
identity := authn.IdentityFromContext(ctx)
profile, err := r.iam.OrganizationService.GetProfileForIdentityAndOrganization(ctx, identity.ID, obj.ID)
if err != nil {
var errNotFound *iam.ErrProfileNotFound
if errors.As(err, &errNotFound) {
return nil, gqlutils.NotFound(ctx, err)
}
r.logger.ErrorCtx(ctx, "cannot get profile", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return types.NewProfile(profile), nil
}
// Permission is the resolver for the permission field.
func (r *organizationResolver) Permission(ctx context.Context, obj *types.Organization, action string) (bool, error) {
return r.Resolver.Permission(ctx, obj, action)
}
// Organization returns schema.OrganizationResolver implementation.
func (r *Resolver) Organization() schema.OrganizationResolver { return &organizationResolver{r} }
type organizationResolver struct{ *Resolver }

View File

@@ -11,43 +11,12 @@ import (
"go.gearno.de/kit/log"
"go.probo.inc/probo/pkg/coredata"
"go.probo.inc/probo/pkg/iam"
"go.probo.inc/probo/pkg/page"
"go.probo.inc/probo/pkg/server/api/authn"
"go.probo.inc/probo/pkg/server/api/connect/v1/schema"
"go.probo.inc/probo/pkg/server/api/connect/v1/types"
"go.probo.inc/probo/pkg/server/gqlutils"
"go.probo.inc/probo/pkg/server/gqlutils/types/cursor"
)
// PersonalAPIKeys is the resolver for the personalAPIKeys field.
func (r *identityResolver) PersonalAPIKeys(ctx context.Context, obj *types.Identity, first *int, after *page.CursorKey, last *int, before *page.CursorKey) (*types.PersonalAPIKeyConnection, error) {
if err := r.authorize(ctx, obj.ID, iam.ActionPersonalAPIKeyList); err != nil {
return nil, err
}
if gqlutils.OnlyTotalCountSelected(ctx) {
return &types.PersonalAPIKeyConnection{
Resolver: r,
ParentID: obj.ID,
}, nil
}
pageOrderBy := page.OrderBy[coredata.PersonalAPIKeyOrderField]{
Field: coredata.PersonalAPIKeyOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
cursor := cursor.NewCursor(first, after, last, before, pageOrderBy)
page, err := r.iam.AccountService.ListPersonalAPIKeys(ctx, obj.ID, cursor)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot list personal api keys", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return types.NewPersonalAPIKeyConnection(page, r, obj.ID), nil
}
// CreatePersonalAPIKey is the resolver for the createPersonalAPIKey field.
func (r *mutationResolver) CreatePersonalAPIKey(ctx context.Context, input types.CreatePersonalAPIKeyInput) (*types.CreatePersonalAPIKeyPayload, error) {
identity := authn.IdentityFromContext(ctx)

View File

@@ -21,50 +21,6 @@ import (
"go.probo.inc/probo/pkg/server/gqlutils/types/cursor"
)
// Profiles is the resolver for the profiles field.
func (r *identityResolver) Profiles(ctx context.Context, obj *types.Identity, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.ProfileOrderBy, filter *types.ProfileFilter) (*types.ProfileConnection, error) {
if err := r.authorize(ctx, obj.ID, iam.ActionMembershipProfileList, authz.WithSkipAssumptionCheck()); err != nil {
return nil, err
}
filters := coredata.NewMembershipProfileFilter(nil).WithMembership()
if filter != nil {
filters = coredata.NewMembershipProfileFilter(filter.ExcludeContractEnded).WithMembership()
if filter.State != nil {
filters.WithState(*filter.State)
}
}
if gqlutils.OnlyTotalCountSelected(ctx) {
return &types.ProfileConnection{
Resolver: r,
ParentID: obj.ID,
Filters: filters,
}, nil
}
pageOrderBy := page.OrderBy[coredata.MembershipProfileOrderField]{
Field: coredata.MembershipProfileOrderFieldFullName,
Direction: page.OrderDirectionAsc,
}
if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.MembershipProfileOrderField]{
Field: orderBy.Field,
Direction: orderBy.Direction,
}
}
cursor := cursor.NewCursor(first, after, last, before, pageOrderBy)
page, err := r.iam.AccountService.ListProfilesForIdentity(ctx, obj.ID, cursor, filters)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot list profiles", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return types.NewProfileConnection(page, r, obj.ID, filters), nil
}
// Permission is the resolver for the permission field.
func (r *invitationResolver) Permission(ctx context.Context, obj *types.Invitation, action string) (bool, error) {
return r.Resolver.Permission(ctx, obj, action)
@@ -268,44 +224,6 @@ func (r *mutationResolver) RemoveUser(ctx context.Context, input types.RemoveUse
return &types.RemoveUserPayload{DeletedProfileID: input.ProfileID}, nil
}
// Profiles is the resolver for the profiles field.
func (r *organizationResolver) Profiles(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.ProfileOrderBy) (*types.ProfileConnection, error) {
if err := r.authorize(ctx, obj.ID, iam.ActionMembershipProfileList); err != nil {
return nil, err
}
filter := coredata.NewMembershipProfileFilter(nil).WithMembership()
if gqlutils.OnlyTotalCountSelected(ctx) {
return &types.ProfileConnection{
Resolver: r,
ParentID: obj.ID,
Filters: filter,
}, nil
}
pageOrderBy := page.OrderBy[coredata.MembershipProfileOrderField]{
Field: coredata.MembershipProfileOrderFieldFullName,
Direction: page.OrderDirectionAsc,
}
if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.MembershipProfileOrderField]{
Field: orderBy.Field,
Direction: orderBy.Direction,
}
}
cursor := cursor.NewCursor(first, after, last, before, pageOrderBy)
page, err := r.iam.OrganizationService.ListProfiles(ctx, obj.ID, cursor, filter)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot list profiles", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return types.NewProfileConnection(page, r, obj.ID, filter), nil
}
// Identity is the resolver for the identity field.
func (r *profileResolver) Identity(ctx context.Context, obj *types.Profile) (*types.Identity, error) {
if err := r.authorize(

View File

@@ -12,11 +12,9 @@ import (
"go.gearno.de/kit/log"
"go.probo.inc/probo/pkg/coredata"
"go.probo.inc/probo/pkg/iam"
"go.probo.inc/probo/pkg/page"
"go.probo.inc/probo/pkg/server/api/connect/v1/schema"
"go.probo.inc/probo/pkg/server/api/connect/v1/types"
"go.probo.inc/probo/pkg/server/gqlutils"
"go.probo.inc/probo/pkg/server/gqlutils/types/cursor"
)
// CreateSAMLConfiguration is the resolver for the createSAMLConfiguration field.
@@ -116,35 +114,6 @@ func (r *mutationResolver) DeleteSAMLConfiguration(ctx context.Context, input ty
return &types.DeleteSAMLConfigurationPayload{DeletedSamlConfigurationID: input.SamlConfigurationID}, nil
}
// SamlConfigurations is the resolver for the samlConfigurations field.
func (r *organizationResolver) SamlConfigurations(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey) (*types.SAMLConfigurationConnection, error) {
if err := r.authorize(ctx, obj.ID, iam.ActionSAMLConfigurationList); err != nil {
return nil, err
}
if gqlutils.OnlyTotalCountSelected(ctx) {
return &types.SAMLConfigurationConnection{
Resolver: r,
ParentID: obj.ID,
}, nil
}
pageOrderBy := page.OrderBy[coredata.SAMLConfigurationOrderField]{
Field: coredata.SAMLConfigurationOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
cursor := cursor.NewCursor(first, after, last, before, pageOrderBy)
page, err := r.iam.OrganizationService.ListSAMLConfigurations(ctx, obj.ID, cursor)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot list saml configurations", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return types.NewSAMLConfigurationConnection(page, r, obj.ID), nil
}
// TestLoginURL is the resolver for the testLoginUrl field.
func (r *sAMLConfigurationResolver) TestLoginURL(ctx context.Context, obj *types.SAMLConfiguration) (string, error) {
return r.baseURL.WithPath("/api/connect/v1/saml/2.0/" + obj.ID.String()).MustString(), nil

View File

@@ -12,7 +12,6 @@ import (
"go.gearno.de/kit/log"
"go.probo.inc/probo/pkg/coredata"
"go.probo.inc/probo/pkg/iam"
"go.probo.inc/probo/pkg/iam/scim/bridge/provider/googleworkspace"
"go.probo.inc/probo/pkg/page"
"go.probo.inc/probo/pkg/server/api/connect/v1/schema"
"go.probo.inc/probo/pkg/server/api/connect/v1/types"
@@ -107,36 +106,6 @@ func (r *mutationResolver) UpdateSCIMBridge(ctx context.Context, input types.Upd
}, nil
}
// ScimConfiguration is the resolver for the scimConfiguration field.
func (r *organizationResolver) ScimConfiguration(ctx context.Context, obj *types.Organization) (*types.SCIMConfiguration, error) {
if err := r.authorize(ctx, obj.ID, iam.ActionSCIMConfigurationGet); err != nil {
return nil, err
}
config, err := r.iam.OrganizationService.GetSCIMConfiguration(ctx, obj.ID)
if err != nil {
var notFound *iam.ErrNoSCIMConfigurationFound
if errors.As(err, &notFound) {
return nil, nil
}
r.logger.ErrorCtx(ctx, "cannot get scim configuration", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return types.NewSCIMConfiguration(config), nil
}
// ScimBridgeTypes is the resolver for the scimBridgeTypes field.
func (r *organizationResolver) ScimBridgeTypes(ctx context.Context, obj *types.Organization) ([]*types.SCIMBridgeTypeInfo, error) {
return []*types.SCIMBridgeTypeInfo{
{
Type: coredata.SCIMBridgeTypeGoogleWorkspace,
Oauth2Scopes: googleworkspace.OAuth2Scopes,
},
}, nil
}
// ScimConfiguration is the resolver for the scimConfiguration field.
func (r *sCIMBridgeResolver) ScimConfiguration(ctx context.Context, obj *types.SCIMBridge) (*types.SCIMConfiguration, error) {
if err := r.authorize(ctx, obj.ScimConfiguration.ID, iam.ActionSCIMConfigurationGet); err != nil {

View File

@@ -9,50 +9,11 @@ import (
"context"
"go.gearno.de/kit/log"
"go.probo.inc/probo/pkg/coredata"
"go.probo.inc/probo/pkg/iam"
"go.probo.inc/probo/pkg/page"
"go.probo.inc/probo/pkg/server/api/connect/v1/schema"
"go.probo.inc/probo/pkg/server/api/connect/v1/types"
"go.probo.inc/probo/pkg/server/gqlutils"
"go.probo.inc/probo/pkg/server/gqlutils/types/cursor"
)
// Sessions is the resolver for the sessions field.
func (r *identityResolver) Sessions(ctx context.Context, obj *types.Identity, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.SessionOrder) (*types.SessionConnection, error) {
if err := r.authorize(ctx, obj.ID, iam.ActionSessionList); err != nil {
return nil, err
}
if gqlutils.OnlyTotalCountSelected(ctx) {
return &types.SessionConnection{
Resolver: r,
ParentID: obj.ID,
}, nil
}
pageOrderBy := page.OrderBy[coredata.SessionOrderField]{
Field: coredata.SessionOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.SessionOrderField]{
Field: orderBy.Field,
Direction: orderBy.Direction,
}
}
cursor := cursor.NewCursor(first, after, last, before, pageOrderBy)
page, err := r.iam.AccountService.ListSessions(ctx, obj.ID, cursor)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot list sessions", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return types.NewSessionConnection(page, r, obj.ID), nil
}
// Identity is the resolver for the identity field.
func (r *sessionResolver) Identity(ctx context.Context, obj *types.Session) (*types.Identity, error) {
if gqlutils.OnlyIDSelected(ctx) {

View File

@@ -955,64 +955,6 @@ func (r *mutationResolver) FlagAccessEntry(ctx context.Context, input types.Flag
}, nil
}
// AccessSources is the resolver for the accessSources field.
func (r *organizationResolver) AccessSources(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.AccessSourceOrder) (*types.AccessSourceConnection, error) {
if err := r.authorize(ctx, obj.ID, probo.ActionAccessSourceList); err != nil {
return nil, err
}
scope := coredata.NewScopeFromObjectID(obj.ID)
pageOrderBy := page.OrderBy[coredata.AccessSourceOrderField]{
Field: coredata.AccessSourceOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.AccessSourceOrderField]{
Field: orderBy.Field,
Direction: orderBy.Direction,
}
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
p, err := r.accessReview.Sources(scope).ListForOrganizationID(ctx, obj.ID, cursor)
if err != nil {
panic(fmt.Errorf("cannot list access sources: %w", err))
}
return types.NewAccessSourceConnection(p, r, obj.ID), nil
}
// AccessReviewCampaigns is the resolver for the accessReviewCampaigns field.
func (r *organizationResolver) AccessReviewCampaigns(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.AccessReviewCampaignOrder) (*types.AccessReviewCampaignConnection, error) {
if err := r.authorize(ctx, obj.ID, probo.ActionAccessReviewCampaignList); err != nil {
return nil, err
}
scope := coredata.NewScopeFromObjectID(obj.ID)
pageOrderBy := page.OrderBy[coredata.AccessReviewCampaignOrderField]{
Field: coredata.AccessReviewCampaignOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.AccessReviewCampaignOrderField]{
Field: orderBy.Field,
Direction: orderBy.Direction,
}
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
p, err := r.accessReview.Campaigns(scope).ListForOrganizationID(ctx, obj.ID, cursor)
if err != nil {
panic(fmt.Errorf("cannot list access review campaigns: %w", err))
}
return types.NewAccessReviewCampaignConnection(p, r, obj.ID), nil
}
// AccessEntry returns schema.AccessEntryResolver implementation.
func (r *Resolver) AccessEntry() schema.AccessEntryResolver { return &accessEntryResolver{r} }

View File

@@ -405,76 +405,6 @@ func (r *mutationResolver) DeleteDatum(ctx context.Context, input types.DeleteDa
}, nil
}
// Assets is the resolver for the assets field.
func (r *organizationResolver) Assets(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.AssetOrderBy, filter *types.AssetFilter) (*types.AssetConnection, error) {
if err := r.authorize(ctx, obj.ID, probo.ActionAssetList); err != nil {
return nil, err
}
prb := r.ProboService(ctx, obj.ID.TenantID())
pageOrderBy := page.OrderBy[coredata.AssetOrderField]{
Field: coredata.AssetOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.AssetOrderField]{
Field: orderBy.Field,
Direction: orderBy.Direction,
}
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
assetFilter := coredata.NewAssetFilter(nil)
if filter != nil {
assetFilter = coredata.NewAssetFilter(&filter.SnapshotID)
}
page, err := prb.Assets.ListForOrganizationID(ctx, obj.ID, cursor, assetFilter)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot list organization assets", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return types.NewAssetConnection(page, r, obj.ID, filter), nil
}
// Assets is the resolver for the assets field.
func (r *organizationResolver) Data(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.DatumOrderBy, filter *types.DatumFilter) (*types.DatumConnection, error) {
if err := r.authorize(ctx, obj.ID, probo.ActionDatumList); err != nil {
return nil, err
}
prb := r.ProboService(ctx, obj.ID.TenantID())
pageOrderBy := page.OrderBy[coredata.DatumOrderField]{
Field: coredata.DatumOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.DatumOrderField]{
Field: orderBy.Field,
Direction: orderBy.Direction,
}
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
datumFilter := coredata.NewDatumFilter(nil)
if filter != nil {
datumFilter = coredata.NewDatumFilter(&filter.SnapshotID)
}
page, err := prb.Data.ListForOrganizationID(ctx, obj.ID, cursor, datumFilter)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot list organization data", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return types.NewDataConnection(page, r, obj.ID, filter), nil
}
// Asset returns schema.AssetResolver implementation.
func (r *Resolver) Asset() schema.AssetResolver { return &assetResolver{r} }

View File

@@ -677,85 +677,6 @@ func (r *mutationResolver) DeleteFindingAuditMapping(ctx context.Context, input
}, nil
}
// Audits is the resolver for the audits field.
func (r *organizationResolver) Audits(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.AuditOrderBy) (*types.AuditConnection, error) {
if err := r.authorize(ctx, obj.ID, probo.ActionAuditList); err != nil {
return nil, err
}
prb := r.ProboService(ctx, obj.ID.TenantID())
pageOrderBy := page.OrderBy[coredata.AuditOrderField]{
Field: coredata.AuditOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.AuditOrderField]{
Field: orderBy.Field,
Direction: orderBy.Direction,
}
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
page, err := prb.Audits.ListForOrganizationID(ctx, obj.ID, cursor)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot list organization audits", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return types.NewAuditConnection(page, r, obj.ID), nil
}
// Findings is the resolver for the findings field.
func (r *organizationResolver) Findings(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.FindingOrder, filter *types.FindingFilter) (*types.FindingConnection, error) {
if err := r.authorize(ctx, obj.ID, probo.ActionFindingList); err != nil {
return nil, err
}
prb := r.ProboService(ctx, obj.ID.TenantID())
pageOrderBy := page.OrderBy[coredata.FindingOrderField]{
Field: coredata.FindingOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.FindingOrderField]{
Field: orderBy.Field,
Direction: orderBy.Direction,
}
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
var (
kind *coredata.FindingKind
status *coredata.FindingStatus
priority *coredata.FindingPriority
ownerID *gid.GID
)
if filter != nil {
kind = filter.Kind
status = filter.Status
priority = filter.Priority
ownerID = filter.OwnerID
}
findingFilter := coredata.NewFindingFilter(nil, kind, status, priority, ownerID)
if filter != nil {
findingFilter = coredata.NewFindingFilter(&filter.SnapshotID, kind, status, priority, ownerID)
}
page, err := prb.Findings.ListForOrganizationID(ctx, obj.ID, cursor, findingFilter)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot list organization findings", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return types.NewFindingConnection(page, r, obj.ID, filter), nil
}
// DownloadURL is the resolver for the downloadUrl field.
func (r *reportResolver) DownloadURL(ctx context.Context, obj *types.Report) (*string, error) {
if err := r.authorize(ctx, obj.ID, probo.ActionReportDownloadUrlGet); err != nil {

View File

@@ -10,8 +10,6 @@ import (
"go.gearno.de/kit/log"
"go.probo.inc/probo/pkg/coredata"
"go.probo.inc/probo/pkg/iam"
"go.probo.inc/probo/pkg/page"
"go.probo.inc/probo/pkg/server/api/console/v1/schema"
"go.probo.inc/probo/pkg/server/api/console/v1/types"
"go.probo.inc/probo/pkg/server/gqlutils"
@@ -43,50 +41,6 @@ func (r *auditLogEntryConnectionResolver) TotalCount(ctx context.Context, obj *t
return count, nil
}
// AuditLogEntries is the resolver for the auditLogEntries field.
func (r *organizationResolver) AuditLogEntries(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.AuditLogEntryOrderBy, filter *types.AuditLogEntryFilter) (*types.AuditLogEntryConnection, error) {
if err := r.authorize(ctx, obj.ID, iam.ActionAuditLogEntryList); err != nil {
return nil, err
}
pageOrderBy := page.OrderBy[coredata.AuditLogEntryOrderField]{
Field: coredata.AuditLogEntryOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.AuditLogEntryOrderField]{
Field: orderBy.Field,
Direction: orderBy.Direction,
}
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
coredataFilter := coredata.NewAuditLogEntryFilter()
if filter != nil {
if filter.Action != nil {
coredataFilter.WithAction(*filter.Action)
}
if filter.ActorID != nil {
coredataFilter.WithActorID(*filter.ActorID)
}
if filter.ResourceType != nil {
coredataFilter.WithResourceType(*filter.ResourceType)
}
if filter.ResourceID != nil {
coredataFilter.WithResourceID(*filter.ResourceID)
}
}
p, err := r.iam.OrganizationService.ListAuditLogEntries(ctx, obj.ID, cursor, coredataFilter)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot list audit log entries", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return types.NewAuditLogEntryConnection(p, r, obj.ID, coredataFilter), nil
}
// AuditLogEntry returns schema.AuditLogEntryResolver implementation.
func (r *Resolver) AuditLogEntry() schema.AuditLogEntryResolver { return &auditLogEntryResolver{r} }

View File

@@ -21,7 +21,6 @@ import (
"go.probo.inc/probo/pkg/server/api/console/v1/schema"
"go.probo.inc/probo/pkg/server/api/console/v1/types"
"go.probo.inc/probo/pkg/server/gqlutils"
"go.probo.inc/probo/pkg/server/gqlutils/types/cursor"
"go.probo.inc/probo/pkg/validator"
)
@@ -73,117 +72,6 @@ func (r *mutationResolver) UpdateOrganizationContext(ctx context.Context, input
}, nil
}
// LogoURL is the resolver for the logoUrl field.
func (r *organizationResolver) LogoURL(ctx context.Context, obj *types.Organization) (*string, error) {
if err := r.authorize(ctx, obj.ID, probo.ActionOrganizationGetLogoUrl); err != nil {
return nil, err
}
prb := r.ProboService(ctx, obj.ID.TenantID())
logoURL, err := prb.Organizations.GenerateLogoURL(ctx, obj.ID, 1*time.Hour)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot generate logo url", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return logoURL, nil
}
// HorizontalLogoURL is the resolver for the horizontalLogoUrl field.
func (r *organizationResolver) HorizontalLogoURL(ctx context.Context, obj *types.Organization) (*string, error) {
if err := r.authorize(ctx, obj.ID, probo.ActionOrganizationGetHorizontalLogoUrl); err != nil {
return nil, err
}
prb := r.ProboService(ctx, obj.ID.TenantID())
horizontalLogoURL, err := prb.Organizations.GenerateHorizontalLogoURL(ctx, obj.ID, 1*time.Hour)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot generate horizontal logo url", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return horizontalLogoURL, nil
}
// Context is the resolver for the context field.
func (r *organizationResolver) Context(ctx context.Context, obj *types.Organization) (*types.OrganizationContext, error) {
if err := r.authorize(ctx, obj.ID, probo.ActionOrganizationContextGet); err != nil {
return nil, err
}
prb := r.ProboService(ctx, obj.ID.TenantID())
orgContext, err := prb.Organizations.GetContext(ctx, obj.ID)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot load organization context", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return types.NewOrganizationContext(orgContext), nil
}
// Profiles is the resolver for the profiles field.
func (r *organizationResolver) Profiles(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.ProfileOrderBy, filter *types.ProfileFilter) (*types.ProfileConnection, error) {
if err := r.authorize(ctx, obj.ID, iam.ActionMembershipProfileList); err != nil {
return nil, err
}
if gqlutils.OnlyTotalCountSelected(ctx) {
return &types.ProfileConnection{
Resolver: r,
ParentID: obj.ID,
}, nil
}
filters := coredata.NewMembershipProfileFilter(nil).WithMembership()
if filter != nil {
filters = coredata.NewMembershipProfileFilter(filter.ExcludeContractEnded).WithMembership()
}
pageOrderBy := page.OrderBy[coredata.MembershipProfileOrderField]{
Field: coredata.MembershipProfileOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if orderBy != nil {
pageOrderBy.Field = coredata.MembershipProfileOrderField(orderBy.Field)
pageOrderBy.Direction = page.OrderDirection(orderBy.Direction)
}
cursor := cursor.NewCursor(first, after, last, before, pageOrderBy)
page, err := r.iam.OrganizationService.ListProfiles(ctx, obj.ID, cursor, filters)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot list profiles", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return types.NewProfileConnection(page, r, obj.ID, filters), nil
}
// MeasureCategories is the resolver for the measureCategories field.
func (r *organizationResolver) MeasureCategories(ctx context.Context, obj *types.Organization) ([]string, error) {
if err := r.authorize(ctx, obj.ID, probo.ActionMeasureList); err != nil {
return nil, err
}
prb := r.ProboService(ctx, obj.ID.TenantID())
categories, err := prb.Measures.ListDistinctCategoriesForOrganizationID(ctx, obj.ID)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot list measure categories", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return categories, nil
}
// Permission is the resolver for the permission field.
func (r *organizationResolver) Permission(ctx context.Context, obj *types.Organization, action string) (bool, error) {
return r.Resolver.Permission(ctx, obj, action)
}
// Node is the resolver for the node field.
func (r *queryResolver) Node(ctx context.Context, id gid.GID) (types.Node, error) {
var (
@@ -543,15 +431,170 @@ func (r *queryResolver) Viewer(ctx context.Context) (*types.Viewer, error) {
return &types.Viewer{ID: viewerID}, nil
}
// SignableDocuments is the resolver for the signableDocuments field.
func (r *viewerResolver) SignableDocuments(ctx context.Context, obj *types.Viewer, organizationID gid.GID, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.DocumentOrderBy) (*types.EmployeeDocumentConnection, error) {
if err := r.authorize(ctx, organizationID, probo.ActionEmployeeDocumentList); err != nil {
return nil, err
}
prb := r.ProboService(ctx, organizationID.TenantID())
pageOrderBy := page.OrderBy[coredata.DocumentOrderField]{
Field: coredata.DocumentOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.DocumentOrderField]{
Field: orderBy.Field,
Direction: orderBy.Direction,
}
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
identity := authn.IdentityFromContext(ctx)
documentFilter := coredata.NewDocumentFilter(nil).WithEmployeeIdentityID(&identity.ID, coredata.EmployeeFilterModeSignature)
documentsPage, err := prb.Documents.ListByOrganizationID(ctx, organizationID, cursor, documentFilter)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot list organization signable documents", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
employeeDocuments := make([]*types.EmployeeDocument, len(documentsPage.Data))
for i, doc := range documentsPage.Data {
employeeDocuments[i] = &types.EmployeeDocument{
ID: doc.ID,
Title: doc.Title,
DocumentType: doc.DocumentType,
CreatedAt: doc.CreatedAt,
UpdatedAt: doc.UpdatedAt,
FilterMode: types.EmployeeDocumentFilterModeSignature,
}
}
page := page.NewPage(employeeDocuments, documentsPage.Cursor)
return types.NewEmployeeDocumentConnection(page), nil
}
// SignableDocument is the resolver for the signableDocument field.
func (r *viewerResolver) SignableDocument(ctx context.Context, obj *types.Viewer, id gid.GID) (*types.EmployeeDocument, error) {
if err := r.authorize(ctx, id, probo.ActionEmployeeDocumentGet); err != nil {
return nil, err
}
prb := r.ProboService(ctx, id.TenantID())
identity := authn.IdentityFromContext(ctx)
documentFilter := coredata.NewDocumentFilter(nil).WithEmployeeIdentityID(&identity.ID, coredata.EmployeeFilterModeSignature)
document, err := prb.Documents.GetWithFilter(ctx, id, documentFilter)
if err != nil {
if errors.Is(err, coredata.ErrResourceNotFound) {
return nil, gqlutils.NotFound(ctx, err)
}
r.logger.ErrorCtx(ctx, "cannot get signable document", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return &types.EmployeeDocument{
ID: document.ID,
Title: document.Title,
DocumentType: document.DocumentType,
CreatedAt: document.CreatedAt,
UpdatedAt: document.UpdatedAt,
FilterMode: types.EmployeeDocumentFilterModeSignature,
}, nil
}
// ApprovableDocuments is the resolver for the approvableDocuments field.
func (r *viewerResolver) ApprovableDocuments(ctx context.Context, obj *types.Viewer, organizationID gid.GID, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.DocumentOrderBy) (*types.EmployeeDocumentConnection, error) {
if err := r.authorize(ctx, organizationID, probo.ActionEmployeeDocumentList); err != nil {
return nil, err
}
prb := r.ProboService(ctx, organizationID.TenantID())
pageOrderBy := page.OrderBy[coredata.DocumentOrderField]{
Field: coredata.DocumentOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.DocumentOrderField]{
Field: orderBy.Field,
Direction: orderBy.Direction,
}
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
identity := authn.IdentityFromContext(ctx)
documentFilter := coredata.NewDocumentFilter(nil).WithEmployeeIdentityID(&identity.ID, coredata.EmployeeFilterModeApproval)
documentsPage, err := prb.Documents.ListByOrganizationID(ctx, organizationID, cursor, documentFilter)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot list organization approvable documents", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
employeeDocuments := make([]*types.EmployeeDocument, len(documentsPage.Data))
for i, doc := range documentsPage.Data {
employeeDocuments[i] = &types.EmployeeDocument{
ID: doc.ID,
Title: doc.Title,
DocumentType: doc.DocumentType,
CreatedAt: doc.CreatedAt,
UpdatedAt: doc.UpdatedAt,
FilterMode: types.EmployeeDocumentFilterModeApproval,
}
}
page := page.NewPage(employeeDocuments, documentsPage.Cursor)
return types.NewEmployeeDocumentConnection(page), nil
}
// ApprovableDocument is the resolver for the approvableDocument field.
func (r *viewerResolver) ApprovableDocument(ctx context.Context, obj *types.Viewer, id gid.GID) (*types.EmployeeDocument, error) {
if err := r.authorize(ctx, id, probo.ActionEmployeeDocumentGet); err != nil {
return nil, err
}
prb := r.ProboService(ctx, id.TenantID())
identity := authn.IdentityFromContext(ctx)
documentFilter := coredata.NewDocumentFilter(nil).WithEmployeeIdentityID(&identity.ID, coredata.EmployeeFilterModeApproval)
document, err := prb.Documents.GetWithFilter(ctx, id, documentFilter)
if err != nil {
if errors.Is(err, coredata.ErrResourceNotFound) {
return nil, gqlutils.NotFound(ctx, err)
}
r.logger.ErrorCtx(ctx, "cannot get approvable document", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return &types.EmployeeDocument{
ID: document.ID,
Title: document.Title,
DocumentType: document.DocumentType,
CreatedAt: document.CreatedAt,
UpdatedAt: document.UpdatedAt,
FilterMode: types.EmployeeDocumentFilterModeApproval,
}, nil
}
// File returns schema.FileResolver implementation.
func (r *Resolver) File() schema.FileResolver { return &fileResolver{r} }
// Mutation returns schema.MutationResolver implementation.
func (r *Resolver) Mutation() schema.MutationResolver { return &mutationResolver{r} }
// Organization returns schema.OrganizationResolver implementation.
func (r *Resolver) Organization() schema.OrganizationResolver { return &organizationResolver{r} }
// Query returns schema.QueryResolver implementation.
func (r *Resolver) Query() schema.QueryResolver { return &queryResolver{r} }
@@ -560,6 +603,5 @@ func (r *Resolver) Viewer() schema.ViewerResolver { return &viewerResolver{r} }
type fileResolver struct{ *Resolver }
type mutationResolver struct{ *Resolver }
type organizationResolver struct{ *Resolver }
type queryResolver struct{ *Resolver }
type viewerResolver struct{ *Resolver }

View File

@@ -14,12 +14,10 @@ import (
"go.probo.inc/probo/pkg/accessreview/drivers"
"go.probo.inc/probo/pkg/connector"
"go.probo.inc/probo/pkg/coredata"
"go.probo.inc/probo/pkg/page"
"go.probo.inc/probo/pkg/probo"
"go.probo.inc/probo/pkg/server/api/console/v1/schema"
"go.probo.inc/probo/pkg/server/api/console/v1/types"
"go.probo.inc/probo/pkg/server/gqlutils"
"go.probo.inc/probo/pkg/slack"
)
// Oauth2Scopes is the resolver for the oauth2Scopes field.
@@ -167,96 +165,6 @@ func (r *mutationResolver) DeleteSlackConnection(ctx context.Context, input type
}, nil
}
// SlackConnections is the resolver for the slackConnections field.
func (r *organizationResolver) SlackConnections(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey) (*types.SlackConnectionConnection, error) {
if err := r.authorize(ctx, obj.ID, probo.ActionSlackConnectionList); err != nil {
return nil, err
}
prb := r.ProboService(ctx, obj.ID.TenantID())
slackProvider := coredata.ConnectorProviderSlack
filter := coredata.NewConnectorProviderFilter(&slackProvider)
pageOrderBy := page.OrderBy[coredata.ConnectorOrderField]{
Field: coredata.ConnectorOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
page, err := prb.Connectors.ListForOrganizationID(ctx, obj.ID, cursor, filter)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot list organization slack connections", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return types.NewSlackConnectionConnection(page), nil
}
// SlackOAuth2Scopes is the resolver for the slackOAuth2Scopes field.
func (r *organizationResolver) SlackOAuth2Scopes(ctx context.Context, obj *types.Organization) ([]string, error) {
return slack.OAuth2Scopes, nil
}
// Connectors is the resolver for the connectors field.
func (r *organizationResolver) Connectors(ctx context.Context, obj *types.Organization, filter *types.ConnectorFilter) ([]*types.Connector, error) {
if err := r.authorize(ctx, obj.ID, probo.ActionConnectorList); err != nil {
return nil, err
}
prb := r.ProboService(ctx, obj.ID.TenantID())
connectors, err := prb.Connectors.ListAllForOrganizationID(ctx, obj.ID)
if err != nil {
panic(fmt.Errorf("cannot list organization connectors: %w", err))
}
if filter != nil && len(filter.Providers) > 0 {
allowed := make(map[coredata.ConnectorProvider]struct{}, len(filter.Providers))
for _, provider := range filter.Providers {
allowed[provider] = struct{}{}
}
filtered := make(coredata.Connectors, 0, len(connectors))
for _, cnnctr := range connectors {
if _, ok := allowed[cnnctr.Provider]; ok {
filtered = append(filtered, cnnctr)
}
}
connectors = filtered
}
return types.NewConnectors(connectors), nil
}
// ConnectorProviderInfos is the resolver for the connectorProviderInfos field.
func (r *organizationResolver) ConnectorProviderInfos(ctx context.Context, obj *types.Organization) ([]*types.ConnectorProviderInfo, error) {
if err := r.authorize(ctx, obj.ID, probo.ActionConnectorList); err != nil {
return nil, err
}
var infos []*types.ConnectorProviderInfo
for _, provider := range coredata.ConnectorProviders() {
_, oauthErr := r.connectorRegistry.Get(string(provider))
scopes := drivers.ProviderOAuth2Scopes(provider)
if scopes == nil {
scopes = []string{}
}
info := &types.ConnectorProviderInfo{
Provider: provider,
DisplayName: providerDisplayName(provider),
OauthConfigured: oauthErr == nil,
APIKeySupported: providerSupportsAPIKey(provider),
ClientCredentialsSupported: providerSupportsClientCredentials(provider),
Oauth2Scopes: scopes,
ExtraSettings: providerExtraSettings(provider),
}
infos = append(infos, info)
}
return infos, nil
}
// Permission is the resolver for the permission field.
func (r *slackConnectionResolver) Permission(ctx context.Context, obj *types.SlackConnection, action string) (bool, error) {
return r.Resolver.Permission(ctx, obj, action)

View File

@@ -865,76 +865,6 @@ func (r *mutationResolver) ExportStatementOfApplicabilityPDF(ctx context.Context
}, nil
}
// Controls is the resolver for the controls field.
func (r *organizationResolver) Controls(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.ControlOrderBy, filter *types.ControlFilter) (*types.ControlConnection, error) {
if err := r.authorize(ctx, obj.ID, probo.ActionControlList); err != nil {
return nil, err
}
prb := r.ProboService(ctx, obj.ID.TenantID())
pageOrderBy := page.OrderBy[coredata.ControlOrderField]{
Field: coredata.ControlOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.ControlOrderField]{
Field: orderBy.Field,
Direction: orderBy.Direction,
}
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
var controlFilter = coredata.NewControlFilter(nil)
if filter != nil {
controlFilter = coredata.NewControlFilter(filter.Query)
}
page, err := prb.Controls.ListForOrganizationID(ctx, obj.ID, cursor, controlFilter)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot list controls", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return types.NewControlConnection(page, r, obj.ID, controlFilter), nil
}
// StatementsOfApplicability is the resolver for the statementsOfApplicability field.
func (r *organizationResolver) StatementsOfApplicability(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.StatementOfApplicabilityOrderBy, filter *types.StatementOfApplicabilityFilter) (*types.StatementOfApplicabilityConnection, error) {
if err := r.authorize(ctx, obj.ID, probo.ActionStatementOfApplicabilityList); err != nil {
return nil, err
}
prb := r.ProboService(ctx, obj.ID.TenantID())
pageOrderBy := page.OrderBy[coredata.StatementOfApplicabilityOrderField]{
Field: coredata.StatementOfApplicabilityOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.StatementOfApplicabilityOrderField]{
Field: orderBy.Field,
Direction: orderBy.Direction,
}
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
var statementOfApplicabilityFilter = coredata.NewStatementOfApplicabilityFilter(nil)
if filter != nil {
statementOfApplicabilityFilter = coredata.NewStatementOfApplicabilityFilter(&filter.SnapshotID)
}
page, err := prb.StatementsOfApplicability.ListForOrganizationID(ctx, obj.ID, cursor, statementOfApplicabilityFilter)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot list organization statements_of_applicability", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return types.NewStatementOfApplicabilityConnection(page, r, obj.ID, statementOfApplicabilityFilter), nil
}
// Organization is the resolver for the organization field.
func (r *statementOfApplicabilityResolver) Organization(ctx context.Context, obj *types.StatementOfApplicability) (*types.Organization, error) {
if err := r.authorize(ctx, obj.ID, probo.ActionOrganizationGet); err != nil {

View File

@@ -15,7 +15,6 @@ import (
"go.gearno.de/kit/log"
"go.probo.inc/probo/pkg/coredata"
"go.probo.inc/probo/pkg/gid"
"go.probo.inc/probo/pkg/page"
"go.probo.inc/probo/pkg/probo"
"go.probo.inc/probo/pkg/server/api/console/v1/dataloader"
"go.probo.inc/probo/pkg/server/api/console/v1/schema"
@@ -326,78 +325,6 @@ func (r *mutationResolver) ExportTransferImpactAssessmentsPDF(ctx context.Contex
}, nil
}
// DataProtectionImpactAssessments is the resolver for the dataProtectionImpactAssessments field.
func (r *organizationResolver) DataProtectionImpactAssessments(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.DataProtectionImpactAssessmentOrderBy, filter *types.DataProtectionImpactAssessmentFilter) (*types.DataProtectionImpactAssessmentConnection, error) {
if err := r.authorize(ctx, obj.ID, probo.ActionDataProtectionImpactAssessmentList); err != nil {
return nil, err
}
prb := r.ProboService(ctx, obj.ID.TenantID())
pageOrderBy := page.OrderBy[coredata.DataProtectionImpactAssessmentOrderField]{
Field: coredata.DataProtectionImpactAssessmentOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.DataProtectionImpactAssessmentOrderField]{
Field: orderBy.Field,
Direction: orderBy.Direction,
}
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
dpiaFilter := coredata.NewDataProtectionImpactAssessmentFilter(nil)
if filter != nil {
dpiaFilter = coredata.NewDataProtectionImpactAssessmentFilter(&filter.SnapshotID)
}
page, err := prb.DataProtectionImpactAssessments.ListForOrganizationID(ctx, obj.ID, cursor, dpiaFilter)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot list organization data protection impact assessments", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return types.NewDataProtectionImpactAssessmentConnection(page, r, obj.ID, dpiaFilter), nil
}
// TransferImpactAssessments is the resolver for the transferImpactAssessments field.
func (r *organizationResolver) TransferImpactAssessments(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.TransferImpactAssessmentOrderBy, filter *types.TransferImpactAssessmentFilter) (*types.TransferImpactAssessmentConnection, error) {
if err := r.authorize(ctx, obj.ID, probo.ActionTransferImpactAssessmentList); err != nil {
return nil, err
}
prb := r.ProboService(ctx, obj.ID.TenantID())
pageOrderBy := page.OrderBy[coredata.TransferImpactAssessmentOrderField]{
Field: coredata.TransferImpactAssessmentOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.TransferImpactAssessmentOrderField]{
Field: orderBy.Field,
Direction: orderBy.Direction,
}
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
tiaFilter := coredata.NewTransferImpactAssessmentFilter(nil)
if filter != nil {
tiaFilter = coredata.NewTransferImpactAssessmentFilter(&filter.SnapshotID)
}
page, err := prb.TransferImpactAssessments.ListForOrganizationID(ctx, obj.ID, cursor, tiaFilter)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot list organization transfer impact assessments", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return types.NewTransferImpactAssessmentConnection(page, r, obj.ID, tiaFilter), nil
}
// ProcessingActivity is the resolver for the processingActivity field.
func (r *transferImpactAssessmentResolver) ProcessingActivity(ctx context.Context, obj *types.TransferImpactAssessment) (*types.ProcessingActivity, error) {
if err := r.authorize(ctx, obj.ID, probo.ActionProcessingActivityGet); err != nil {

View File

@@ -1633,202 +1633,6 @@ func (r *mutationResolver) ExportEmployeeDocumentVersionPDF(ctx context.Context,
}, nil
}
// Documents is the resolver for the documents field.
func (r *organizationResolver) Documents(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.DocumentOrderBy, filter *types.DocumentFilter) (*types.DocumentConnection, error) {
if err := r.authorize(ctx, obj.ID, probo.ActionDocumentList); err != nil {
return nil, err
}
prb := r.ProboService(ctx, obj.ID.TenantID())
pageOrderBy := page.OrderBy[coredata.DocumentOrderField]{
Field: coredata.DocumentOrderFieldTitle,
Direction: page.OrderDirectionDesc,
}
if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.DocumentOrderField]{
Field: orderBy.Field,
Direction: orderBy.Direction,
}
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
var documentFilter = coredata.NewDocumentFilter(nil)
if filter != nil {
documentFilter = coredata.NewDocumentFilter(filter.Query).
WithDocumentTypes(filter.DocumentTypes).
WithClassifications(filter.Classifications).
WithStatus(filter.Status)
}
page, err := prb.Documents.ListByOrganizationID(ctx, obj.ID, cursor, documentFilter)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot list organization documents", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return types.NewDocumentConnection(page, r, obj.ID, documentFilter), nil
}
// SignableDocuments is the resolver for the signableDocuments field.
func (r *viewerResolver) SignableDocuments(ctx context.Context, obj *types.Viewer, organizationID gid.GID, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.DocumentOrderBy) (*types.EmployeeDocumentConnection, error) {
if err := r.authorize(ctx, organizationID, probo.ActionEmployeeDocumentList); err != nil {
return nil, err
}
prb := r.ProboService(ctx, organizationID.TenantID())
pageOrderBy := page.OrderBy[coredata.DocumentOrderField]{
Field: coredata.DocumentOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.DocumentOrderField]{
Field: orderBy.Field,
Direction: orderBy.Direction,
}
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
identity := authn.IdentityFromContext(ctx)
documentFilter := coredata.NewDocumentFilter(nil).WithEmployeeIdentityID(&identity.ID, coredata.EmployeeFilterModeSignature)
documentsPage, err := prb.Documents.ListByOrganizationID(ctx, organizationID, cursor, documentFilter)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot list organization signable documents", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
employeeDocuments := make([]*types.EmployeeDocument, len(documentsPage.Data))
for i, doc := range documentsPage.Data {
employeeDocuments[i] = &types.EmployeeDocument{
ID: doc.ID,
Title: doc.Title,
DocumentType: doc.DocumentType,
CreatedAt: doc.CreatedAt,
UpdatedAt: doc.UpdatedAt,
FilterMode: types.EmployeeDocumentFilterModeSignature,
}
}
page := page.NewPage(employeeDocuments, documentsPage.Cursor)
return types.NewEmployeeDocumentConnection(page), nil
}
// SignableDocument is the resolver for the signableDocument field.
func (r *viewerResolver) SignableDocument(ctx context.Context, obj *types.Viewer, id gid.GID) (*types.EmployeeDocument, error) {
if err := r.authorize(ctx, id, probo.ActionEmployeeDocumentGet); err != nil {
return nil, err
}
prb := r.ProboService(ctx, id.TenantID())
identity := authn.IdentityFromContext(ctx)
documentFilter := coredata.NewDocumentFilter(nil).WithEmployeeIdentityID(&identity.ID, coredata.EmployeeFilterModeSignature)
document, err := prb.Documents.GetWithFilter(ctx, id, documentFilter)
if err != nil {
if errors.Is(err, coredata.ErrResourceNotFound) {
return nil, gqlutils.NotFound(ctx, err)
}
r.logger.ErrorCtx(ctx, "cannot get signable document", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return &types.EmployeeDocument{
ID: document.ID,
Title: document.Title,
DocumentType: document.DocumentType,
CreatedAt: document.CreatedAt,
UpdatedAt: document.UpdatedAt,
FilterMode: types.EmployeeDocumentFilterModeSignature,
}, nil
}
// ApprovableDocuments is the resolver for the approvableDocuments field.
func (r *viewerResolver) ApprovableDocuments(ctx context.Context, obj *types.Viewer, organizationID gid.GID, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.DocumentOrderBy) (*types.EmployeeDocumentConnection, error) {
if err := r.authorize(ctx, organizationID, probo.ActionEmployeeDocumentList); err != nil {
return nil, err
}
prb := r.ProboService(ctx, organizationID.TenantID())
pageOrderBy := page.OrderBy[coredata.DocumentOrderField]{
Field: coredata.DocumentOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.DocumentOrderField]{
Field: orderBy.Field,
Direction: orderBy.Direction,
}
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
identity := authn.IdentityFromContext(ctx)
documentFilter := coredata.NewDocumentFilter(nil).WithEmployeeIdentityID(&identity.ID, coredata.EmployeeFilterModeApproval)
documentsPage, err := prb.Documents.ListByOrganizationID(ctx, organizationID, cursor, documentFilter)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot list organization approvable documents", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
employeeDocuments := make([]*types.EmployeeDocument, len(documentsPage.Data))
for i, doc := range documentsPage.Data {
employeeDocuments[i] = &types.EmployeeDocument{
ID: doc.ID,
Title: doc.Title,
DocumentType: doc.DocumentType,
CreatedAt: doc.CreatedAt,
UpdatedAt: doc.UpdatedAt,
FilterMode: types.EmployeeDocumentFilterModeApproval,
}
}
page := page.NewPage(employeeDocuments, documentsPage.Cursor)
return types.NewEmployeeDocumentConnection(page), nil
}
// ApprovableDocument is the resolver for the approvableDocument field.
func (r *viewerResolver) ApprovableDocument(ctx context.Context, obj *types.Viewer, id gid.GID) (*types.EmployeeDocument, error) {
if err := r.authorize(ctx, id, probo.ActionEmployeeDocumentGet); err != nil {
return nil, err
}
prb := r.ProboService(ctx, id.TenantID())
identity := authn.IdentityFromContext(ctx)
documentFilter := coredata.NewDocumentFilter(nil).WithEmployeeIdentityID(&identity.ID, coredata.EmployeeFilterModeApproval)
document, err := prb.Documents.GetWithFilter(ctx, id, documentFilter)
if err != nil {
if errors.Is(err, coredata.ErrResourceNotFound) {
return nil, gqlutils.NotFound(ctx, err)
}
r.logger.ErrorCtx(ctx, "cannot get approvable document", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return &types.EmployeeDocument{
ID: document.ID,
Title: document.Title,
DocumentType: document.DocumentType,
CreatedAt: document.CreatedAt,
UpdatedAt: document.UpdatedAt,
FilterMode: types.EmployeeDocumentFilterModeApproval,
}, nil
}
// Document returns schema.DocumentResolver implementation.
func (r *Resolver) Document() schema.DocumentResolver { return &documentResolver{r} }

View File

@@ -8,12 +8,10 @@ package console_v1
import (
"context"
"errors"
"fmt"
"github.com/vikstrous/dataloadgen"
"go.gearno.de/kit/log"
"go.probo.inc/probo/pkg/coredata"
"go.probo.inc/probo/pkg/page"
"go.probo.inc/probo/pkg/probo"
"go.probo.inc/probo/pkg/server/api/console/v1/dataloader"
"go.probo.inc/probo/pkg/server/api/console/v1/schema"
@@ -180,11 +178,6 @@ func (r *mutationResolver) UploadMeasureEvidence(ctx context.Context, input type
}, nil
}
// Evidences is the resolver for the evidences field.
func (r *organizationResolver) Evidences(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.EvidenceOrderBy) (*types.EvidenceConnection, error) {
panic(fmt.Errorf("not implemented: Evidences - evidences"))
}
// Evidence returns schema.EvidenceResolver implementation.
func (r *Resolver) Evidence() schema.EvidenceResolver { return &evidenceResolver{r} }

View File

@@ -259,36 +259,6 @@ func (r *mutationResolver) ExportFramework(ctx context.Context, input types.Expo
}, nil
}
// Frameworks is the resolver for the frameworks field.
func (r *organizationResolver) Frameworks(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.FrameworkOrderBy) (*types.FrameworkConnection, error) {
if err := r.authorize(ctx, obj.ID, probo.ActionFrameworkList); err != nil {
return nil, err
}
prb := r.ProboService(ctx, obj.ID.TenantID())
pageOrderBy := page.OrderBy[coredata.FrameworkOrderField]{
Field: coredata.FrameworkOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.FrameworkOrderField]{
Field: orderBy.Field,
Direction: orderBy.Direction,
}
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
page, err := prb.Frameworks.ListForOrganizationID(ctx, obj.ID, cursor)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot list organization frameworks", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return types.NewFrameworkConnection(page, r, obj.ID), nil
}
// Framework returns schema.FrameworkResolver implementation.
func (r *Resolver) Framework() schema.FrameworkResolver { return &frameworkResolver{r} }

View File

@@ -1,21 +1,3 @@
extend type Organization {
accessSources(
first: Int
after: CursorKey
last: Int
before: CursorKey
orderBy: AccessSourceOrder
): AccessSourceConnection! @goField(forceResolver: true)
accessReviewCampaigns(
first: Int
after: CursorKey
last: Int
before: CursorKey
orderBy: AccessReviewCampaignOrder
): AccessReviewCampaignConnection! @goField(forceResolver: true)
}
enum AccessReviewCampaignStatus
@goModel(
model: "go.probo.inc/probo/pkg/coredata.AccessReviewCampaignStatus"

View File

@@ -1,23 +1,3 @@
extend type Organization {
assets(
first: Int
after: CursorKey
last: Int
before: CursorKey
orderBy: AssetOrder
filter: AssetFilter = { snapshotId: null }
): AssetConnection! @goField(forceResolver: true)
data(
first: Int
after: CursorKey
last: Int
before: CursorKey
orderBy: DatumOrder
filter: DatumFilter = { snapshotId: null }
): DatumConnection! @goField(forceResolver: true)
}
enum AssetType @goModel(model: "go.probo.inc/probo/pkg/coredata.AssetType") {
PHYSICAL @goEnum(value: "go.probo.inc/probo/pkg/coredata.AssetTypePhysical")
VIRTUAL @goEnum(value: "go.probo.inc/probo/pkg/coredata.AssetTypeVirtual")

View File

@@ -1,22 +1,3 @@
extend type Organization {
audits(
first: Int
after: CursorKey
last: Int
before: CursorKey
orderBy: AuditOrder
): AuditConnection! @goField(forceResolver: true)
findings(
first: Int
after: CursorKey
last: Int
before: CursorKey
orderBy: FindingOrder
filter: FindingFilter = { snapshotId: null }
): FindingConnection @goField(forceResolver: true)
}
enum AuditState @goModel(model: "go.probo.inc/probo/pkg/coredata.AuditState") {
NOT_STARTED
@goEnum(value: "go.probo.inc/probo/pkg/coredata.AuditStateNotStarted")

View File

@@ -1,14 +1,3 @@
extend type Organization {
auditLogEntries(
first: Int
after: CursorKey
last: Int
before: CursorKey
orderBy: AuditLogEntryOrder
filter: AuditLogEntryFilter
): AuditLogEntryConnection! @goField(forceResolver: true)
}
enum AuditLogActorType
@goModel(
model: "go.probo.inc/probo/pkg/coredata.AuditLogActorType"

View File

@@ -311,35 +311,28 @@ type Query {
type Viewer {
id: ID!
}
type Organization implements Node {
id: ID!
name: String!
logoUrl: String @goField(forceResolver: true)
horizontalLogoUrl: String @goField(forceResolver: true)
description: String
websiteUrl: String
email: String
headquarterAddress: String
context: OrganizationContext @goField(forceResolver: true)
profiles(
signableDocuments(
organizationId: ID!
first: Int
after: CursorKey
last: Int
before: CursorKey
orderBy: ProfileOrder
filter: ProfileFilter
): ProfileConnection! @goField(forceResolver: true)
orderBy: DocumentOrder
): EmployeeDocumentConnection! @goField(forceResolver: true)
measureCategories: [String!]! @goField(forceResolver: true)
signableDocument(id: ID!): EmployeeDocument @goField(forceResolver: true)
createdAt: Datetime!
updatedAt: Datetime!
approvableDocuments(
organizationId: ID!
first: Int
after: CursorKey
last: Int
before: CursorKey
orderBy: DocumentOrder
): EmployeeDocumentConnection! @goField(forceResolver: true)
permission(action: String!): Boolean! @goField(forceResolver: true)
approvableDocument(id: ID!): EmployeeDocument @goField(forceResolver: true)
}
type Mutation {

View File

@@ -1,15 +1,3 @@
extend type Organization {
slackConnections(
first: Int
after: CursorKey
last: Int
before: CursorKey
): SlackConnectionConnection! @goField(forceResolver: true)
slackOAuth2Scopes: [String!]! @goField(forceResolver: true)
connectors(filter: ConnectorFilter): [Connector!]! @goField(forceResolver: true)
connectorProviderInfos: [ConnectorProviderInfo!]! @goField(forceResolver: true)
}
enum ConnectorProvider
@goModel(model: "go.probo.inc/probo/pkg/coredata.ConnectorProvider") {
SLACK @goEnum(value: "go.probo.inc/probo/pkg/coredata.ConnectorProviderSlack")

View File

@@ -1,23 +1,3 @@
extend type Organization {
controls(
first: Int
after: CursorKey
last: Int
before: CursorKey
orderBy: ControlOrder
filter: ControlFilter
): ControlConnection! @goField(forceResolver: true)
statementsOfApplicability(
first: Int
after: CursorKey
last: Int
before: CursorKey
orderBy: StatementOfApplicabilityOrder
filter: StatementOfApplicabilityFilter = { snapshotId: null }
): StatementOfApplicabilityConnection! @goField(forceResolver: true)
}
enum ControlImplementationState
@goModel(
model: "go.probo.inc/probo/pkg/coredata.ControlImplementationState"

View File

@@ -1,23 +1,3 @@
extend type Organization {
dataProtectionImpactAssessments(
first: Int
after: CursorKey
last: Int
before: CursorKey
orderBy: DataProtectionImpactAssessmentOrder
filter: DataProtectionImpactAssessmentFilter = { snapshotId: null }
): DataProtectionImpactAssessmentConnection! @goField(forceResolver: true)
transferImpactAssessments(
first: Int
after: CursorKey
last: Int
before: CursorKey
orderBy: TransferImpactAssessmentOrder
filter: TransferImpactAssessmentFilter = { snapshotId: null }
): TransferImpactAssessmentConnection! @goField(forceResolver: true)
}
enum DataProtectionImpactAssessmentResidualRisk
@goModel(
model: "go.probo.inc/probo/pkg/coredata.DataProtectionImpactAssessmentResidualRisk"

View File

@@ -1,38 +1,3 @@
extend type Organization {
documents(
first: Int
after: CursorKey
last: Int
before: CursorKey
orderBy: DocumentOrder
filter: DocumentFilter
): DocumentConnection! @goField(forceResolver: true)
}
extend type Viewer {
signableDocuments(
organizationId: ID!
first: Int
after: CursorKey
last: Int
before: CursorKey
orderBy: DocumentOrder
): EmployeeDocumentConnection! @goField(forceResolver: true)
signableDocument(id: ID!): EmployeeDocument @goField(forceResolver: true)
approvableDocuments(
organizationId: ID!
first: Int
after: CursorKey
last: Int
before: CursorKey
orderBy: DocumentOrder
): EmployeeDocumentConnection! @goField(forceResolver: true)
approvableDocument(id: ID!): EmployeeDocument @goField(forceResolver: true)
}
enum DocumentVersionStatus
@goModel(model: "go.probo.inc/probo/pkg/coredata.DocumentVersionStatus") {
DRAFT

View File

@@ -1,13 +1,3 @@
extend type Organization {
evidences(
first: Int
after: CursorKey
last: Int
before: CursorKey
orderBy: EvidenceOrder
): EvidenceConnection! @goField(forceResolver: true)
}
enum EvidenceState
@goModel(model: "go.probo.inc/probo/pkg/coredata.EvidenceState") {
FULFILLED

View File

@@ -1,13 +1,3 @@
extend type Organization {
frameworks(
first: Int
after: CursorKey
last: Int
before: CursorKey
orderBy: FrameworkOrder
): FrameworkConnection! @goField(forceResolver: true)
}
enum FrameworkOrderField
@goModel(model: "go.probo.inc/probo/pkg/coredata.FrameworkOrderField") {
CREATED_AT

View File

@@ -1,14 +1,3 @@
extend type Organization {
measures(
first: Int
after: CursorKey
last: Int
before: CursorKey
orderBy: MeasureOrder
filter: MeasureFilter
): MeasureConnection! @goField(forceResolver: true)
}
enum MeasureState
@goModel(model: "go.probo.inc/probo/pkg/coredata.MeasureState") {
NOT_STARTED

View File

@@ -1,13 +1,3 @@
extend type Organization {
meetings(
first: Int
after: CursorKey
last: Int
before: CursorKey
orderBy: MeetingOrder
): MeetingConnection! @goField(forceResolver: true)
}
enum MeetingOrderField
@goModel(model: "go.probo.inc/probo/pkg/coredata.MeetingOrderField") {
DATE @goEnum(value: "go.probo.inc/probo/pkg/coredata.MeetingOrderFieldDate")

View File

@@ -1,14 +1,3 @@
extend type Organization {
obligations(
first: Int
after: CursorKey
last: Int
before: CursorKey
orderBy: ObligationOrder
filter: ObligationFilter = { snapshotId: null }
): ObligationConnection! @goField(forceResolver: true)
}
enum ObligationStatus
@goModel(model: "go.probo.inc/probo/pkg/coredata.ObligationStatus") {
NON_COMPLIANT

View File

@@ -81,3 +81,258 @@ input UpdateOrganizationContextInput {
type UpdateOrganizationContextPayload {
context: OrganizationContext!
}
type Organization implements Node {
id: ID!
name: String!
logoUrl: String @goField(forceResolver: true)
horizontalLogoUrl: String @goField(forceResolver: true)
description: String
websiteUrl: String
email: String
headquarterAddress: String
context: OrganizationContext @goField(forceResolver: true)
profiles(
first: Int
after: CursorKey
last: Int
before: CursorKey
orderBy: ProfileOrder
filter: ProfileFilter
): ProfileConnection! @goField(forceResolver: true)
measureCategories: [String!]! @goField(forceResolver: true)
accessSources(
first: Int
after: CursorKey
last: Int
before: CursorKey
orderBy: AccessSourceOrder
): AccessSourceConnection! @goField(forceResolver: true)
accessReviewCampaigns(
first: Int
after: CursorKey
last: Int
before: CursorKey
orderBy: AccessReviewCampaignOrder
): AccessReviewCampaignConnection! @goField(forceResolver: true)
assets(
first: Int
after: CursorKey
last: Int
before: CursorKey
orderBy: AssetOrder
filter: AssetFilter = { snapshotId: null }
): AssetConnection! @goField(forceResolver: true)
data(
first: Int
after: CursorKey
last: Int
before: CursorKey
orderBy: DatumOrder
filter: DatumFilter = { snapshotId: null }
): DatumConnection! @goField(forceResolver: true)
audits(
first: Int
after: CursorKey
last: Int
before: CursorKey
orderBy: AuditOrder
): AuditConnection! @goField(forceResolver: true)
findings(
first: Int
after: CursorKey
last: Int
before: CursorKey
orderBy: FindingOrder
filter: FindingFilter = { snapshotId: null }
): FindingConnection @goField(forceResolver: true)
auditLogEntries(
first: Int
after: CursorKey
last: Int
before: CursorKey
orderBy: AuditLogEntryOrder
filter: AuditLogEntryFilter
): AuditLogEntryConnection! @goField(forceResolver: true)
slackConnections(
first: Int
after: CursorKey
last: Int
before: CursorKey
): SlackConnectionConnection! @goField(forceResolver: true)
slackOAuth2Scopes: [String!]! @goField(forceResolver: true)
connectors(filter: ConnectorFilter): [Connector!]! @goField(forceResolver: true)
connectorProviderInfos: [ConnectorProviderInfo!]! @goField(forceResolver: true)
controls(
first: Int
after: CursorKey
last: Int
before: CursorKey
orderBy: ControlOrder
filter: ControlFilter
): ControlConnection! @goField(forceResolver: true)
statementsOfApplicability(
first: Int
after: CursorKey
last: Int
before: CursorKey
orderBy: StatementOfApplicabilityOrder
filter: StatementOfApplicabilityFilter = { snapshotId: null }
): StatementOfApplicabilityConnection! @goField(forceResolver: true)
dataProtectionImpactAssessments(
first: Int
after: CursorKey
last: Int
before: CursorKey
orderBy: DataProtectionImpactAssessmentOrder
filter: DataProtectionImpactAssessmentFilter = { snapshotId: null }
): DataProtectionImpactAssessmentConnection! @goField(forceResolver: true)
transferImpactAssessments(
first: Int
after: CursorKey
last: Int
before: CursorKey
orderBy: TransferImpactAssessmentOrder
filter: TransferImpactAssessmentFilter = { snapshotId: null }
): TransferImpactAssessmentConnection! @goField(forceResolver: true)
documents(
first: Int
after: CursorKey
last: Int
before: CursorKey
orderBy: DocumentOrder
filter: DocumentFilter
): DocumentConnection! @goField(forceResolver: true)
evidences(
first: Int
after: CursorKey
last: Int
before: CursorKey
orderBy: EvidenceOrder
): EvidenceConnection! @goField(forceResolver: true)
frameworks(
first: Int
after: CursorKey
last: Int
before: CursorKey
orderBy: FrameworkOrder
): FrameworkConnection! @goField(forceResolver: true)
measures(
first: Int
after: CursorKey
last: Int
before: CursorKey
orderBy: MeasureOrder
filter: MeasureFilter
): MeasureConnection! @goField(forceResolver: true)
meetings(
first: Int
after: CursorKey
last: Int
before: CursorKey
orderBy: MeetingOrder
): MeetingConnection! @goField(forceResolver: true)
obligations(
first: Int
after: CursorKey
last: Int
before: CursorKey
orderBy: ObligationOrder
filter: ObligationFilter = { snapshotId: null }
): ObligationConnection! @goField(forceResolver: true)
processingActivities(
first: Int
after: CursorKey
last: Int
before: CursorKey
orderBy: ProcessingActivityOrder
filter: ProcessingActivityFilter = { snapshotId: null }
): ProcessingActivityConnection! @goField(forceResolver: true)
rightsRequests(
first: Int
after: CursorKey
last: Int
before: CursorKey
orderBy: RightsRequestOrder
): RightsRequestConnection! @goField(forceResolver: true)
risks(
first: Int
after: CursorKey
last: Int
before: CursorKey
orderBy: RiskOrder
filter: RiskFilter = { snapshotId: null }
): RiskConnection! @goField(forceResolver: true)
snapshots(
first: Int
after: CursorKey
last: Int
before: CursorKey
orderBy: SnapshotOrder
): SnapshotConnection! @goField(forceResolver: true)
tasks(
first: Int
after: CursorKey
last: Int
before: CursorKey
orderBy: TaskOrder
): TaskConnection! @goField(forceResolver: true)
trustCenter: TrustCenter @goField(forceResolver: true)
customDomain: CustomDomain @goField(forceResolver: true)
trustCenterFiles(
first: Int
after: CursorKey
last: Int
before: CursorKey
orderBy: TrustCenterFileOrder
): TrustCenterFileConnection! @goField(forceResolver: true)
vendors(
first: Int
after: CursorKey
last: Int
before: CursorKey
orderBy: VendorOrder
filter: VendorFilter = { snapshotId: null }
): VendorConnection! @goField(forceResolver: true)
webhookSubscriptions(
first: Int
after: CursorKey
last: Int
before: CursorKey
orderBy: WebhookSubscriptionOrder
): WebhookSubscriptionConnection! @goField(forceResolver: true)
createdAt: Datetime!
updatedAt: Datetime!
permission(action: String!): Boolean! @goField(forceResolver: true)
}

View File

@@ -1,14 +1,3 @@
extend type Organization {
processingActivities(
first: Int
after: CursorKey
last: Int
before: CursorKey
orderBy: ProcessingActivityOrder
filter: ProcessingActivityFilter = { snapshotId: null }
): ProcessingActivityConnection! @goField(forceResolver: true)
}
enum ProcessingActivitySpecialOrCriminalDatum
@goModel(
model: "go.probo.inc/probo/pkg/coredata.ProcessingActivitySpecialOrCriminalDatum"

View File

@@ -1,13 +1,3 @@
extend type Organization {
rightsRequests(
first: Int
after: CursorKey
last: Int
before: CursorKey
orderBy: RightsRequestOrder
): RightsRequestConnection! @goField(forceResolver: true)
}
enum RightsRequestType
@goModel(model: "go.probo.inc/probo/pkg/coredata.RightsRequestType") {
ACCESS

View File

@@ -1,14 +1,3 @@
extend type Organization {
risks(
first: Int
after: CursorKey
last: Int
before: CursorKey
orderBy: RiskOrder
filter: RiskFilter = { snapshotId: null }
): RiskConnection! @goField(forceResolver: true)
}
enum RiskTreatment
@goModel(model: "go.probo.inc/probo/pkg/coredata.RiskTreatment") {
MITIGATED

View File

@@ -1,13 +1,3 @@
extend type Organization {
snapshots(
first: Int
after: CursorKey
last: Int
before: CursorKey
orderBy: SnapshotOrder
): SnapshotConnection! @goField(forceResolver: true)
}
enum SnapshotsType
@goModel(model: "go.probo.inc/probo/pkg/coredata.SnapshotsType") {
RISKS @goEnum(value: "go.probo.inc/probo/pkg/coredata.SnapshotsTypeRisks")

View File

@@ -1,13 +1,3 @@
extend type Organization {
tasks(
first: Int
after: CursorKey
last: Int
before: CursorKey
orderBy: TaskOrder
): TaskConnection! @goField(forceResolver: true)
}
enum TaskState @goModel(model: "go.probo.inc/probo/pkg/coredata.TaskState") {
TODO @goEnum(value: "go.probo.inc/probo/pkg/coredata.TaskStateTodo")
IN_PROGRESS @goEnum(value: "go.probo.inc/probo/pkg/coredata.TaskStateInProgress")

View File

@@ -1,15 +1,3 @@
extend type Organization {
trustCenter: TrustCenter @goField(forceResolver: true)
customDomain: CustomDomain @goField(forceResolver: true)
trustCenterFiles(
first: Int
after: CursorKey
last: Int
before: CursorKey
orderBy: TrustCenterFileOrder
): TrustCenterFileConnection! @goField(forceResolver: true)
}
enum TrustCenterVisibility
@goModel(model: "go.probo.inc/probo/pkg/coredata.TrustCenterVisibility") {
NONE

View File

@@ -1,14 +1,3 @@
extend type Organization {
vendors(
first: Int
after: CursorKey
last: Int
before: CursorKey
orderBy: VendorOrder
filter: VendorFilter = { snapshotId: null }
): VendorConnection! @goField(forceResolver: true)
}
enum VendorCategory
@goModel(model: "go.probo.inc/probo/pkg/coredata.VendorCategory") {
ANALYTICS

View File

@@ -1,13 +1,3 @@
extend type Organization {
webhookSubscriptions(
first: Int
after: CursorKey
last: Int
before: CursorKey
orderBy: WebhookSubscriptionOrder
): WebhookSubscriptionConnection! @goField(forceResolver: true)
}
enum WebhookEventType
@goModel(model: "go.probo.inc/probo/pkg/coredata.WebhookEventType") {
MEETING_CREATED

View File

@@ -386,41 +386,6 @@ func (r *mutationResolver) DeleteMeasureDocumentMapping(ctx context.Context, inp
}, nil
}
// Measures is the resolver for the measures field.
func (r *organizationResolver) Measures(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.MeasureOrderBy, filter *types.MeasureFilter) (*types.MeasureConnection, error) {
if err := r.authorize(ctx, obj.ID, probo.ActionMeasureList); err != nil {
return nil, err
}
prb := r.ProboService(ctx, obj.ID.TenantID())
pageOrderBy := page.OrderBy[coredata.MeasureOrderField]{
Field: coredata.MeasureOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.MeasureOrderField]{
Field: orderBy.Field,
Direction: orderBy.Direction,
}
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
var measureFilter = coredata.NewMeasureFilter(nil, nil, nil)
if filter != nil {
measureFilter = coredata.NewMeasureFilter(filter.Query, filter.State, filter.Category)
}
page, err := prb.Measures.ListForOrganizationID(ctx, obj.ID, cursor, measureFilter)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot list organization measures", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return types.NewMeasureConnection(page, r, obj.ID, measureFilter), nil
}
// Measure returns schema.MeasureResolver implementation.
func (r *Resolver) Measure() schema.MeasureResolver { return &measureResolver{r} }

View File

@@ -14,7 +14,6 @@ import (
"go.probo.inc/probo/pkg/coredata"
"go.probo.inc/probo/pkg/gid"
"go.probo.inc/probo/pkg/iam"
"go.probo.inc/probo/pkg/page"
"go.probo.inc/probo/pkg/probo"
"go.probo.inc/probo/pkg/server/api/console/v1/dataloader"
"go.probo.inc/probo/pkg/server/api/console/v1/schema"
@@ -185,36 +184,6 @@ func (r *mutationResolver) DeleteMeeting(ctx context.Context, input types.Delete
}, nil
}
// Meetings is the resolver for the meetings field.
func (r *organizationResolver) Meetings(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.MeetingOrderBy) (*types.MeetingConnection, error) {
if err := r.authorize(ctx, obj.ID, probo.ActionMeetingList); err != nil {
return nil, err
}
prb := r.ProboService(ctx, obj.ID.TenantID())
pageOrderBy := page.OrderBy[coredata.MeetingOrderField]{
Field: coredata.MeetingOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.MeetingOrderField]{
Field: orderBy.Field,
Direction: orderBy.Direction,
}
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
page, err := prb.Meetings.ListForOrganizationID(ctx, obj.ID, cursor)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot list organization meetings", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return types.NewMeetingConnection(page, r, obj.ID), nil
}
// Meeting returns schema.MeetingResolver implementation.
func (r *Resolver) Meeting() schema.MeetingResolver { return &meetingResolver{r} }

View File

@@ -13,7 +13,6 @@ import (
"go.gearno.de/kit/log"
"go.probo.inc/probo/pkg/coredata"
"go.probo.inc/probo/pkg/iam"
"go.probo.inc/probo/pkg/page"
"go.probo.inc/probo/pkg/probo"
"go.probo.inc/probo/pkg/server/api/console/v1/dataloader"
"go.probo.inc/probo/pkg/server/api/console/v1/schema"
@@ -199,42 +198,6 @@ func (r *obligationConnectionResolver) TotalCount(ctx context.Context, obj *type
return 0, gqlutils.Internal(ctx)
}
// Obligations is the resolver for the obligations field.
func (r *organizationResolver) Obligations(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.ObligationOrderBy, filter *types.ObligationFilter) (*types.ObligationConnection, error) {
if err := r.authorize(ctx, obj.ID, probo.ActionObligationList); err != nil {
return nil, err
}
prb := r.ProboService(ctx, obj.ID.TenantID())
pageOrderBy := page.OrderBy[coredata.ObligationOrderField]{
Field: coredata.ObligationOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.ObligationOrderField]{
Field: orderBy.Field,
Direction: orderBy.Direction,
}
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
obligationFilter := coredata.NewObligationFilter(nil)
if filter != nil {
obligationFilter = coredata.NewObligationFilter(&filter.SnapshotID)
}
page, err := prb.Obligations.ListForOrganizationID(ctx, obj.ID, cursor, obligationFilter)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot list organization obligations", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return types.NewObligationConnection(page, r, obj.ID, filter), nil
}
// Obligation returns schema.ObligationResolver implementation.
func (r *Resolver) Obligation() schema.ObligationResolver { return &obligationResolver{r} }

File diff suppressed because it is too large Load Diff

View File

@@ -155,42 +155,6 @@ func (r *mutationResolver) ExportProcessingActivitiesPDF(ctx context.Context, in
}, nil
}
// ProcessingActivities is the resolver for the processingActivities field.
func (r *organizationResolver) ProcessingActivities(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.ProcessingActivityOrderBy, filter *types.ProcessingActivityFilter) (*types.ProcessingActivityConnection, error) {
if err := r.authorize(ctx, obj.ID, probo.ActionProcessingActivityList); err != nil {
return nil, err
}
prb := r.ProboService(ctx, obj.ID.TenantID())
pageOrderBy := page.OrderBy[coredata.ProcessingActivityOrderField]{
Field: coredata.ProcessingActivityOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.ProcessingActivityOrderField]{
Field: orderBy.Field,
Direction: orderBy.Direction,
}
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
processingActivityFilter := coredata.NewProcessingActivityFilter(nil)
if filter != nil {
processingActivityFilter = coredata.NewProcessingActivityFilter(&filter.SnapshotID)
}
page, err := prb.ProcessingActivities.ListForOrganizationID(ctx, obj.ID, cursor, processingActivityFilter)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot list organization processing activities", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return types.NewProcessingActivityConnection(page, r, obj.ID, filter), nil
}
// Organization is the resolver for the organization field.
func (r *processingActivityResolver) Organization(ctx context.Context, obj *types.ProcessingActivity) (*types.Organization, error) {
if err := r.authorize(ctx, obj.ID, probo.ActionOrganizationGet); err != nil {

View File

@@ -12,7 +12,6 @@ import (
"go.gearno.de/kit/log"
"go.probo.inc/probo/pkg/coredata"
"go.probo.inc/probo/pkg/iam"
"go.probo.inc/probo/pkg/page"
"go.probo.inc/probo/pkg/probo"
"go.probo.inc/probo/pkg/server/api/console/v1/schema"
"go.probo.inc/probo/pkg/server/api/console/v1/types"
@@ -105,37 +104,6 @@ func (r *mutationResolver) DeleteRightsRequest(ctx context.Context, input types.
}, nil
}
// RightsRequests is the resolver for the rightsRequests field.
func (r *organizationResolver) RightsRequests(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.RightsRequestOrderBy) (*types.RightsRequestConnection, error) {
if err := r.authorize(ctx, obj.ID, probo.ActionRightsRequestList); err != nil {
return nil, err
}
prb := r.ProboService(ctx, obj.ID.TenantID())
pageOrderBy := page.OrderBy[coredata.RightsRequestOrderField]{
Field: coredata.RightsRequestOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.RightsRequestOrderField]{
Field: orderBy.Field,
Direction: orderBy.Direction,
}
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
page, err := prb.RightsRequests.ListForOrganizationID(ctx, obj.ID, cursor)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot list organization rights requests", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return types.NewRightsRequestConnection(page, r, obj.ID), nil
}
// Organization is the resolver for the organization field.
func (r *rightsRequestResolver) Organization(ctx context.Context, obj *types.RightsRequest) (*types.Organization, error) {
if err := r.authorize(ctx, obj.ID, iam.ActionOrganizationGet); err != nil {

View File

@@ -239,41 +239,6 @@ func (r *mutationResolver) DeleteRiskObligationMapping(ctx context.Context, inpu
}, nil
}
// Risks is the resolver for the risks field.
func (r *organizationResolver) Risks(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.RiskOrderBy, filter *types.RiskFilter) (*types.RiskConnection, error) {
if err := r.authorize(ctx, obj.ID, probo.ActionRiskList); err != nil {
return nil, err
}
prb := r.ProboService(ctx, obj.ID.TenantID())
pageOrderBy := page.OrderBy[coredata.RiskOrderField]{
Field: coredata.RiskOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.RiskOrderField]{
Field: orderBy.Field,
Direction: orderBy.Direction,
}
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
var riskFilter = coredata.NewRiskFilter(nil, nil)
if filter != nil {
riskFilter = coredata.NewRiskFilter(filter.Query, &filter.SnapshotID)
}
page, err := prb.Risks.ListForOrganizationID(ctx, obj.ID, cursor, riskFilter)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot list organization risks", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return types.NewRiskConnection(page, r, obj.ID, riskFilter), nil
}
// Owner is the resolver for the owner field.
func (r *riskResolver) Owner(ctx context.Context, obj *types.Risk) (*types.Profile, error) {
if err := r.authorize(ctx, obj.ID, iam.ActionMembershipProfileGet); err != nil {

View File

@@ -64,36 +64,6 @@ func (r *mutationResolver) DeleteSnapshot(ctx context.Context, input types.Delet
}, nil
}
// Snapshots is the resolver for the snapshots field.
func (r *organizationResolver) Snapshots(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.SnapshotOrderBy) (*types.SnapshotConnection, error) {
if err := r.authorize(ctx, obj.ID, probo.ActionSnapshotList); err != nil {
return nil, err
}
prb := r.ProboService(ctx, obj.ID.TenantID())
pageOrderBy := page.OrderBy[coredata.SnapshotOrderField]{
Field: coredata.SnapshotOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.SnapshotOrderField]{
Field: orderBy.Field,
Direction: orderBy.Direction,
}
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
page, err := prb.Snapshots.ListForOrganizationID(ctx, obj.ID, cursor)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot list organization snapshots", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return types.NewSnapshotConnection(page, r, obj.ID), nil
}
// Organization is the resolver for the organization field.
func (r *snapshotResolver) Organization(ctx context.Context, obj *types.Snapshot) (*types.Organization, error) {
if err := r.authorize(ctx, obj.ID, probo.ActionOrganizationGet); err != nil {

View File

@@ -115,36 +115,6 @@ func (r *mutationResolver) DeleteTask(ctx context.Context, input types.DeleteTas
}, nil
}
// Tasks is the resolver for the tasks field.
func (r *organizationResolver) Tasks(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.TaskOrderBy) (*types.TaskConnection, error) {
if err := r.authorize(ctx, obj.ID, probo.ActionTaskList); err != nil {
return nil, err
}
prb := r.ProboService(ctx, obj.ID.TenantID())
pageOrderBy := page.OrderBy[coredata.TaskOrderField]{
Field: coredata.TaskOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.TaskOrderField]{
Field: orderBy.Field,
Direction: orderBy.Direction,
}
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
page, err := prb.Tasks.ListForOrganizationID(ctx, obj.ID, cursor)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot list organization tasks", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return types.NewTaskConnection(page, r, obj.ID), nil
}
// AssignedTo is the resolver for the assignedTo field.
func (r *taskResolver) AssignedTo(ctx context.Context, obj *types.Task) (*types.Profile, error) {
if err := r.authorize(ctx, obj.ID, iam.ActionMembershipProfileGet); err != nil {

View File

@@ -675,83 +675,6 @@ func (r *mutationResolver) DeleteCustomDomain(ctx context.Context, input types.D
}, nil
}
// TrustCenter is the resolver for the trustCenter field.
func (r *organizationResolver) TrustCenter(ctx context.Context, obj *types.Organization) (*types.TrustCenter, error) {
if err := r.authorize(ctx, obj.ID, probo.ActionTrustCenterGet); err != nil {
return nil, err
}
prb := r.ProboService(ctx, obj.ID.TenantID())
trustCenter, err := prb.TrustCenters.GetByOrganizationID(ctx, obj.ID)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot get trust center", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
var file *coredata.File
if trustCenter.NonDisclosureAgreementFileID != nil {
file, err = prb.Files.Get(ctx, *trustCenter.NonDisclosureAgreementFileID)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot get NDA file", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
}
return types.NewTrustCenter(trustCenter, file), nil
}
// CustomDomain is the resolver for the customDomain field.
func (r *organizationResolver) CustomDomain(ctx context.Context, obj *types.Organization) (*types.CustomDomain, error) {
if err := r.authorize(ctx, obj.ID, probo.ActionCustomDomainGet); err != nil {
return nil, err
}
prb := r.ProboService(ctx, obj.ID.TenantID())
domain, err := prb.CustomDomains.GetOrganizationCustomDomain(ctx, obj.ID)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot get custom domain", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
if domain == nil {
return nil, nil
}
return types.NewCustomDomain(domain, r.customDomainCname), nil
}
// TrustCenterFiles is the resolver for the trustCenterFiles field.
func (r *organizationResolver) TrustCenterFiles(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.OrderBy[coredata.TrustCenterFileOrderField]) (*types.TrustCenterFileConnection, error) {
if err := r.authorize(ctx, obj.ID, probo.ActionTrustCenterFileList); err != nil {
return nil, err
}
prb := r.ProboService(ctx, obj.ID.TenantID())
pageOrderBy := page.OrderBy[coredata.TrustCenterFileOrderField]{
Field: coredata.TrustCenterFileOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.TrustCenterFileOrderField]{
Field: orderBy.Field,
Direction: orderBy.Direction,
}
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
pageResult, err := prb.TrustCenterFiles.ListForOrganizationID(ctx, obj.ID, cursor, &coredata.TrustCenterFileFilter{})
if err != nil {
r.logger.ErrorCtx(ctx, "cannot list organization trust center files", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return types.NewTrustCenterFileConnection(pageResult, obj.ID), nil
}
// LogoFileURL is the resolver for the logoFileUrl field.
func (r *trustCenterResolver) LogoFileURL(ctx context.Context, obj *types.TrustCenter) (*string, error) {
if err := r.authorize(ctx, obj.ID, probo.ActionTrustCenterGet); err != nil {

View File

@@ -558,41 +558,6 @@ func (r *mutationResolver) AssessVendor(ctx context.Context, input types.AssessV
}, nil
}
// Vendors is the resolver for the vendors field.
func (r *organizationResolver) Vendors(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.VendorOrderBy, filter *types.VendorFilter) (*types.VendorConnection, error) {
if err := r.authorize(ctx, obj.ID, probo.ActionVendorList); err != nil {
return nil, err
}
prb := r.ProboService(ctx, obj.ID.TenantID())
pageOrderBy := page.OrderBy[coredata.VendorOrderField]{
Field: coredata.VendorOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.VendorOrderField]{
Field: orderBy.Field,
Direction: orderBy.Direction,
}
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
var vendorFilter = coredata.NewVendorFilter(nil, nil)
if filter != nil {
vendorFilter = coredata.NewVendorFilter(&filter.SnapshotID, nil)
}
page, err := prb.Vendors.ListForOrganizationID(ctx, obj.ID, cursor, vendorFilter)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot list organization vendors", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return types.NewVendorConnection(page, r, obj.ID), nil
}
// Organization is the resolver for the organization field.
func (r *vendorResolver) Organization(ctx context.Context, obj *types.Vendor) (*types.Organization, error) {
if err := r.authorize(ctx, obj.ID, probo.ActionOrganizationGet); err != nil {

View File

@@ -99,36 +99,6 @@ func (r *mutationResolver) DeleteWebhookSubscription(ctx context.Context, input
}, nil
}
// WebhookSubscriptions is the resolver for the webhookSubscriptions field.
func (r *organizationResolver) WebhookSubscriptions(ctx context.Context, obj *types.Organization, first *int, after *page.CursorKey, last *int, before *page.CursorKey, orderBy *types.WebhookSubscriptionOrderBy) (*types.WebhookSubscriptionConnection, error) {
if err := r.authorize(ctx, obj.ID, probo.ActionWebhookSubscriptionList); err != nil {
return nil, err
}
prb := r.ProboService(ctx, obj.ID.TenantID())
pageOrderBy := page.OrderBy[coredata.WebhookSubscriptionOrderField]{
Field: coredata.WebhookSubscriptionOrderFieldCreatedAt,
Direction: page.OrderDirectionDesc,
}
if orderBy != nil {
pageOrderBy = page.OrderBy[coredata.WebhookSubscriptionOrderField]{
Field: orderBy.Field,
Direction: orderBy.Direction,
}
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
page, err := prb.WebhookSubscriptions.ListForOrganizationID(ctx, obj.ID, cursor)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot list organization webhook subscriptions", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return types.NewWebhookSubscriptionConnection(page, r, obj.ID), nil
}
// TotalCount is the resolver for the totalCount field.
func (r *webhookEventConnectionResolver) TotalCount(ctx context.Context, obj *types.WebhookEventConnection) (int, error) {
if err := r.authorize(ctx, obj.ParentID, probo.ActionWebhookSubscriptionGet); err != nil {

View File

@@ -16,7 +16,6 @@ import (
"go.probo.inc/probo/pkg/coredata"
"go.probo.inc/probo/pkg/gid"
"go.probo.inc/probo/pkg/iam"
"go.probo.inc/probo/pkg/page"
"go.probo.inc/probo/pkg/saferedirect"
"go.probo.inc/probo/pkg/server/api/authn"
"go.probo.inc/probo/pkg/server/api/compliancepage"
@@ -350,164 +349,6 @@ func (r *queryResolver) OidcProviders(ctx context.Context) ([]*types.OIDCProvide
return result, nil
}
// LogoFileURL is the resolver for the logoFileUrl field.
func (r *trustCenterResolver) LogoFileURL(ctx context.Context, obj *types.TrustCenter) (*string, error) {
trustService := r.TrustService(ctx, obj.ID.TenantID())
return trustService.TrustCenters.GenerateLogoURL(ctx, obj.ID, 1*time.Hour)
}
// DarkLogoFileURL is the resolver for the darkLogoFileUrl field.
func (r *trustCenterResolver) DarkLogoFileURL(ctx context.Context, obj *types.TrustCenter) (*string, error) {
trustService := r.TrustService(ctx, obj.ID.TenantID())
return trustService.TrustCenters.GenerateDarkLogoURL(ctx, obj.ID, 1*time.Hour)
}
// Organization is the resolver for the organization field.
func (r *trustCenterResolver) Organization(ctx context.Context, obj *types.TrustCenter) (*types.Organization, error) {
return obj.Organization, nil
}
// Documents is the resolver for the documents field.
func (r *trustCenterResolver) Documents(ctx context.Context, obj *types.TrustCenter, first *int, after *page.CursorKey, last *int, before *page.CursorKey) (*types.DocumentConnection, error) {
trustService := r.TrustService(ctx, obj.ID.TenantID())
pageOrderBy := page.OrderBy[coredata.DocumentOrderField]{
Field: coredata.DocumentOrderFieldTitle,
Direction: page.OrderDirectionAsc,
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
documentPage, err := trustService.Documents.ListForOrganizationId(ctx, obj.Organization.ID, cursor)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot list public documents", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return types.NewDocumentConnection(documentPage), nil
}
// Audits is the resolver for the audits field.
func (r *trustCenterResolver) Audits(ctx context.Context, obj *types.TrustCenter, first *int, after *page.CursorKey, last *int, before *page.CursorKey) (*types.AuditConnection, error) {
trustService := r.TrustService(ctx, obj.ID.TenantID())
pageOrderBy := page.OrderBy[coredata.AuditOrderField]{
Field: coredata.AuditOrderFieldValidFrom,
Direction: page.OrderDirectionDesc,
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
auditPage, err := trustService.Audits.ListForOrganizationId(ctx, obj.Organization.ID, cursor)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot list public audits", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return types.NewAuditConnection(auditPage), nil
}
// Subprocessors is the resolver for the subprocessors field.
func (r *trustCenterResolver) Subprocessors(ctx context.Context, obj *types.TrustCenter, first *int, after *page.CursorKey, last *int, before *page.CursorKey) (*types.SubprocessorConnection, error) {
trustService := r.TrustService(ctx, obj.ID.TenantID())
pageOrderBy := page.OrderBy[coredata.VendorOrderField]{
Field: coredata.VendorOrderFieldName,
Direction: page.OrderDirectionAsc,
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
vendorPage, err := trustService.Vendors.ListForOrganizationId(ctx, obj.Organization.ID, cursor)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot list subprocessors", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return types.NewSubprocessorConnection(vendorPage, r, obj.ID), nil
}
// References is the resolver for the references field.
func (r *trustCenterResolver) References(ctx context.Context, obj *types.TrustCenter, first *int, after *page.CursorKey, last *int, before *page.CursorKey) (*types.TrustCenterReferenceConnection, error) {
trustService := r.TrustService(ctx, obj.ID.TenantID())
pageOrderBy := page.OrderBy[coredata.TrustCenterReferenceOrderField]{
Field: coredata.TrustCenterReferenceOrderFieldRank,
Direction: page.OrderDirectionAsc,
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
referencePage, err := trustService.TrustCenterReferences.ListForTrustCenterID(ctx, obj.ID, cursor)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot list public trust center references", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return types.NewTrustCenterReferenceConnection(referencePage), nil
}
// TrustCenterFiles is the resolver for the trustCenterFiles field.
func (r *trustCenterResolver) TrustCenterFiles(ctx context.Context, obj *types.TrustCenter, first *int, after *page.CursorKey, last *int, before *page.CursorKey) (*types.TrustCenterFileConnection, error) {
trustService := r.TrustService(ctx, obj.ID.TenantID())
pageOrderBy := page.OrderBy[coredata.TrustCenterFileOrderField]{
Field: coredata.TrustCenterFileOrderFieldName,
Direction: page.OrderDirectionAsc,
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
filter := coredata.NewTrustCenterFileFilter(
coredata.WithTrustCenterFileVisibilities(
coredata.TrustCenterVisibilityPublic,
coredata.TrustCenterVisibilityPrivate,
),
)
trustCenterFilePage, err := trustService.TrustCenterFiles.ListForOrganizationId(ctx, obj.Organization.ID, cursor, filter)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot list public trust center files", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return types.NewTrustCenterFileConnection(trustCenterFilePage), nil
}
// ComplianceFrameworks is the resolver for the complianceFrameworks field.
func (r *trustCenterResolver) ComplianceFrameworks(ctx context.Context, obj *types.TrustCenter, first *int, after *page.CursorKey, last *int, before *page.CursorKey) (*types.ComplianceFrameworkConnection, error) {
trustService := r.TrustService(ctx, obj.ID.TenantID())
pageOrderBy := page.OrderBy[coredata.ComplianceFrameworkOrderField]{
Field: coredata.ComplianceFrameworkOrderFieldRank,
Direction: page.OrderDirectionAsc,
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
cfPage, err := trustService.ComplianceFrameworks.ListByTrustCenterID(ctx, obj.ID, cursor)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot list compliance frameworks", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return types.NewComplianceFrameworkConnection(cfPage), nil
}
// ExternalUrls is the resolver for the externalUrls field.
func (r *trustCenterResolver) ExternalUrls(ctx context.Context, obj *types.TrustCenter, first *int, after *page.CursorKey, last *int, before *page.CursorKey) (*types.ComplianceExternalURLConnection, error) {
trustService := r.TrustService(ctx, obj.ID.TenantID())
pageOrderBy := page.OrderBy[coredata.ComplianceExternalURLOrderField]{
Field: coredata.ComplianceExternalURLOrderFieldRank,
Direction: page.OrderDirectionAsc,
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
result, err := trustService.ComplianceExternalURLs.ListForTrustCenterID(ctx, obj.ID, cursor)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot list compliance external URLs", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return types.NewComplianceExternalURLConnection(result), nil
}
// Mutation returns schema.MutationResolver implementation.
func (r *Resolver) Mutation() schema.MutationResolver { return &mutationResolver{r} }
@@ -517,10 +358,6 @@ func (r *Resolver) Organization() schema.OrganizationResolver { return &organiza
// Query returns schema.QueryResolver implementation.
func (r *Resolver) Query() schema.QueryResolver { return &queryResolver{r} }
// TrustCenter returns schema.TrustCenterResolver implementation.
func (r *Resolver) TrustCenter() schema.TrustCenterResolver { return &trustCenterResolver{r} }
type mutationResolver struct{ *Resolver }
type organizationResolver struct{ *Resolver }
type queryResolver struct{ *Resolver }
type trustCenterResolver struct{ *Resolver }

View File

@@ -315,65 +315,6 @@ type Query {
@session(required: OPTIONAL)
}
type TrustCenter implements Node {
id: ID!
active: Boolean!
slug: String!
logoFileUrl: String @goField(forceResolver: true)
darkLogoFileUrl: String @goField(forceResolver: true)
organization: Organization! @goField(forceResolver: true)
documents(
first: Int
after: CursorKey
last: Int
before: CursorKey
): DocumentConnection! @goField(forceResolver: true)
audits(
first: Int
after: CursorKey
last: Int
before: CursorKey
): AuditConnection! @goField(forceResolver: true)
subprocessors(
first: Int
after: CursorKey
last: Int
before: CursorKey
): SubprocessorConnection! @goField(forceResolver: true)
references(
first: Int
after: CursorKey
last: Int
before: CursorKey
): TrustCenterReferenceConnection! @goField(forceResolver: true)
trustCenterFiles(
first: Int
after: CursorKey
last: Int
before: CursorKey
): TrustCenterFileConnection! @goField(forceResolver: true)
complianceFrameworks(
first: Int
after: CursorKey
last: Int
before: CursorKey
): ComplianceFrameworkConnection! @goField(forceResolver: true)
externalUrls(
first: Int
after: CursorKey
last: Int
before: CursorKey
): ComplianceExternalURLConnection! @goField(forceResolver: true)
}
type Mutation {
sendMagicLink(input: SendMagicLinkInput!): SendMagicLinkPayload
@session(required: OPTIONAL)

View File

@@ -1,14 +1,3 @@
extend type TrustCenter {
viewerSubscription: MailingListSubscriber @goField(forceResolver: true)
updates(
first: Int
after: CursorKey
last: Int
before: CursorKey
): MailingListUpdateConnection! @goField(forceResolver: true)
}
type MailingListUpdate implements Node {
id: ID!
title: String!

View File

@@ -1,7 +1,3 @@
extend type TrustCenter {
nonDisclosureAgreement: NonDisclosureAgreement @goField(forceResolver: true)
}
type NonDisclosureAgreement {
fileName: String!
fileUrl: String! @goField(forceResolver: true)

View File

@@ -1,3 +1,73 @@
type TrustCenter implements Node {
id: ID!
active: Boolean!
slug: String!
logoFileUrl: String @goField(forceResolver: true)
darkLogoFileUrl: String @goField(forceResolver: true)
nonDisclosureAgreement: NonDisclosureAgreement @goField(forceResolver: true)
viewerSubscription: MailingListSubscriber @goField(forceResolver: true)
organization: Organization! @goField(forceResolver: true)
documents(
first: Int
after: CursorKey
last: Int
before: CursorKey
): DocumentConnection! @goField(forceResolver: true)
audits(
first: Int
after: CursorKey
last: Int
before: CursorKey
): AuditConnection! @goField(forceResolver: true)
subprocessors(
first: Int
after: CursorKey
last: Int
before: CursorKey
): SubprocessorConnection! @goField(forceResolver: true)
references(
first: Int
after: CursorKey
last: Int
before: CursorKey
): TrustCenterReferenceConnection! @goField(forceResolver: true)
trustCenterFiles(
first: Int
after: CursorKey
last: Int
before: CursorKey
): TrustCenterFileConnection! @goField(forceResolver: true)
complianceFrameworks(
first: Int
after: CursorKey
last: Int
before: CursorKey
): ComplianceFrameworkConnection! @goField(forceResolver: true)
externalUrls(
first: Int
after: CursorKey
last: Int
before: CursorKey
): ComplianceExternalURLConnection! @goField(forceResolver: true)
updates(
first: Int
after: CursorKey
last: Int
before: CursorKey
): MailingListUpdateConnection! @goField(forceResolver: true)
}
enum DocumentType
@goModel(model: "go.probo.inc/probo/pkg/coredata.DocumentType") {
OTHER @goEnum(value: "go.probo.inc/probo/pkg/coredata.DocumentTypeOther")

View File

@@ -10,9 +10,7 @@ import (
"errors"
"go.gearno.de/kit/log"
"go.probo.inc/probo/pkg/coredata"
"go.probo.inc/probo/pkg/mailman"
"go.probo.inc/probo/pkg/page"
"go.probo.inc/probo/pkg/server/api/authn"
"go.probo.inc/probo/pkg/server/api/compliancepage"
"go.probo.inc/probo/pkg/server/api/trust/v1/types"
@@ -81,57 +79,3 @@ func (r *mutationResolver) UnsubscribeFromMailingList(ctx context.Context) (*typ
return &types.UnsubscribeFromMailingListPayload{DeletedMailingListSubscriberID: &subscriber.ID}, nil
}
// ViewerSubscription is the resolver for the viewerSubscription field.
func (r *trustCenterResolver) ViewerSubscription(ctx context.Context, obj *types.TrustCenter) (*types.MailingListSubscriber, error) {
trustCenter := compliancepage.CompliancePageFromContext(ctx)
if trustCenter.MailingListID == nil {
return nil, nil
}
identity := authn.IdentityFromContext(ctx)
if identity == nil {
return nil, nil
}
subscriber, err := r.mailman.GetSubscriber(ctx, *trustCenter.MailingListID, identity.EmailAddress)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot get mailing list subscription", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
if subscriber == nil {
return nil, nil
}
return types.NewMailingListSubscriber(subscriber), nil
}
// Updates is the resolver for the updates field.
func (r *trustCenterResolver) Updates(ctx context.Context, obj *types.TrustCenter, first *int, after *page.CursorKey, last *int, before *page.CursorKey) (*types.MailingListUpdateConnection, error) {
trustService := r.TrustService(ctx, obj.ID.TenantID())
tc, err := trustService.TrustCenters.Get(ctx, obj.ID)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot load trust center", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
if tc.MailingListID == nil {
return &types.MailingListUpdateConnection{Edges: []*types.MailingListUpdateEdge{}, PageInfo: &types.PageInfo{}}, nil
}
pageOrderBy := page.OrderBy[coredata.MailingListUpdateOrderField]{
Field: coredata.MailingListUpdateOrderFieldUpdatedAt,
Direction: page.OrderDirectionDesc,
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
result, err := r.mailman.ListSentMailingListUpdates(ctx, *tc.MailingListID, cursor)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot list mailing list updates", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return types.NewMailingListUpdateConnection(result), nil
}

View File

@@ -137,27 +137,6 @@ func (r *nonDisclosureAgreementResolver) ViewerSignature(ctx context.Context, ob
return types.NewElectronicSignature(sig), nil
}
// NonDisclosureAgreement is the resolver for the nonDisclosureAgreement field.
func (r *trustCenterResolver) NonDisclosureAgreement(ctx context.Context, obj *types.TrustCenter) (*types.NonDisclosureAgreement, error) {
trustCenter := compliancepage.CompliancePageFromContext(ctx)
if trustCenter.NonDisclosureAgreementFileID == nil {
return nil, nil
}
trustService := r.TrustService(ctx, obj.ID.TenantID())
file, err := trustService.TrustCenters.GetNDAFile(ctx, obj.ID)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot load NDA file", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
if file == nil {
return nil, nil
}
return types.NewNonDisclosureAgreement(file), nil
}
// NonDisclosureAgreement returns schema.NonDisclosureAgreementResolver implementation.
func (r *Resolver) NonDisclosureAgreement() schema.NonDisclosureAgreementResolver {
return &nonDisclosureAgreementResolver{r}

View File

@@ -15,6 +15,7 @@ import (
"go.gearno.de/kit/log"
"go.probo.inc/probo/pkg/coredata"
"go.probo.inc/probo/pkg/gid"
"go.probo.inc/probo/pkg/page"
"go.probo.inc/probo/pkg/server/api/authn"
"go.probo.inc/probo/pkg/server/api/compliancepage"
"go.probo.inc/probo/pkg/server/api/trust/v1/schema"
@@ -609,6 +610,239 @@ func (r *subprocessorConnectionResolver) TotalCount(ctx context.Context, obj *ty
return 0, gqlutils.Internal(ctx)
}
// LogoFileURL is the resolver for the logoFileUrl field.
func (r *trustCenterResolver) LogoFileURL(ctx context.Context, obj *types.TrustCenter) (*string, error) {
trustService := r.TrustService(ctx, obj.ID.TenantID())
return trustService.TrustCenters.GenerateLogoURL(ctx, obj.ID, 1*time.Hour)
}
// DarkLogoFileURL is the resolver for the darkLogoFileUrl field.
func (r *trustCenterResolver) DarkLogoFileURL(ctx context.Context, obj *types.TrustCenter) (*string, error) {
trustService := r.TrustService(ctx, obj.ID.TenantID())
return trustService.TrustCenters.GenerateDarkLogoURL(ctx, obj.ID, 1*time.Hour)
}
// NonDisclosureAgreement is the resolver for the nonDisclosureAgreement field.
func (r *trustCenterResolver) NonDisclosureAgreement(ctx context.Context, obj *types.TrustCenter) (*types.NonDisclosureAgreement, error) {
trustCenter := compliancepage.CompliancePageFromContext(ctx)
if trustCenter.NonDisclosureAgreementFileID == nil {
return nil, nil
}
trustService := r.TrustService(ctx, obj.ID.TenantID())
file, err := trustService.TrustCenters.GetNDAFile(ctx, obj.ID)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot load NDA file", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
if file == nil {
return nil, nil
}
return types.NewNonDisclosureAgreement(file), nil
}
// ViewerSubscription is the resolver for the viewerSubscription field.
func (r *trustCenterResolver) ViewerSubscription(ctx context.Context, obj *types.TrustCenter) (*types.MailingListSubscriber, error) {
trustCenter := compliancepage.CompliancePageFromContext(ctx)
if trustCenter.MailingListID == nil {
return nil, nil
}
identity := authn.IdentityFromContext(ctx)
if identity == nil {
return nil, nil
}
subscriber, err := r.mailman.GetSubscriber(ctx, *trustCenter.MailingListID, identity.EmailAddress)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot get mailing list subscription", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
if subscriber == nil {
return nil, nil
}
return types.NewMailingListSubscriber(subscriber), nil
}
// Organization is the resolver for the organization field.
func (r *trustCenterResolver) Organization(ctx context.Context, obj *types.TrustCenter) (*types.Organization, error) {
return obj.Organization, nil
}
// Documents is the resolver for the documents field.
func (r *trustCenterResolver) Documents(ctx context.Context, obj *types.TrustCenter, first *int, after *page.CursorKey, last *int, before *page.CursorKey) (*types.DocumentConnection, error) {
trustService := r.TrustService(ctx, obj.ID.TenantID())
pageOrderBy := page.OrderBy[coredata.DocumentOrderField]{
Field: coredata.DocumentOrderFieldTitle,
Direction: page.OrderDirectionAsc,
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
documentPage, err := trustService.Documents.ListForOrganizationId(ctx, obj.Organization.ID, cursor)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot list public documents", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return types.NewDocumentConnection(documentPage), nil
}
// Audits is the resolver for the audits field.
func (r *trustCenterResolver) Audits(ctx context.Context, obj *types.TrustCenter, first *int, after *page.CursorKey, last *int, before *page.CursorKey) (*types.AuditConnection, error) {
trustService := r.TrustService(ctx, obj.ID.TenantID())
pageOrderBy := page.OrderBy[coredata.AuditOrderField]{
Field: coredata.AuditOrderFieldValidFrom,
Direction: page.OrderDirectionDesc,
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
auditPage, err := trustService.Audits.ListForOrganizationId(ctx, obj.Organization.ID, cursor)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot list public audits", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return types.NewAuditConnection(auditPage), nil
}
// Subprocessors is the resolver for the subprocessors field.
func (r *trustCenterResolver) Subprocessors(ctx context.Context, obj *types.TrustCenter, first *int, after *page.CursorKey, last *int, before *page.CursorKey) (*types.SubprocessorConnection, error) {
trustService := r.TrustService(ctx, obj.ID.TenantID())
pageOrderBy := page.OrderBy[coredata.VendorOrderField]{
Field: coredata.VendorOrderFieldName,
Direction: page.OrderDirectionAsc,
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
vendorPage, err := trustService.Vendors.ListForOrganizationId(ctx, obj.Organization.ID, cursor)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot list subprocessors", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return types.NewSubprocessorConnection(vendorPage, r, obj.ID), nil
}
// References is the resolver for the references field.
func (r *trustCenterResolver) References(ctx context.Context, obj *types.TrustCenter, first *int, after *page.CursorKey, last *int, before *page.CursorKey) (*types.TrustCenterReferenceConnection, error) {
trustService := r.TrustService(ctx, obj.ID.TenantID())
pageOrderBy := page.OrderBy[coredata.TrustCenterReferenceOrderField]{
Field: coredata.TrustCenterReferenceOrderFieldRank,
Direction: page.OrderDirectionAsc,
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
referencePage, err := trustService.TrustCenterReferences.ListForTrustCenterID(ctx, obj.ID, cursor)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot list public trust center references", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return types.NewTrustCenterReferenceConnection(referencePage), nil
}
// TrustCenterFiles is the resolver for the trustCenterFiles field.
func (r *trustCenterResolver) TrustCenterFiles(ctx context.Context, obj *types.TrustCenter, first *int, after *page.CursorKey, last *int, before *page.CursorKey) (*types.TrustCenterFileConnection, error) {
trustService := r.TrustService(ctx, obj.ID.TenantID())
pageOrderBy := page.OrderBy[coredata.TrustCenterFileOrderField]{
Field: coredata.TrustCenterFileOrderFieldName,
Direction: page.OrderDirectionAsc,
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
filter := coredata.NewTrustCenterFileFilter(
coredata.WithTrustCenterFileVisibilities(
coredata.TrustCenterVisibilityPublic,
coredata.TrustCenterVisibilityPrivate,
),
)
trustCenterFilePage, err := trustService.TrustCenterFiles.ListForOrganizationId(ctx, obj.Organization.ID, cursor, filter)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot list public trust center files", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return types.NewTrustCenterFileConnection(trustCenterFilePage), nil
}
// ComplianceFrameworks is the resolver for the complianceFrameworks field.
func (r *trustCenterResolver) ComplianceFrameworks(ctx context.Context, obj *types.TrustCenter, first *int, after *page.CursorKey, last *int, before *page.CursorKey) (*types.ComplianceFrameworkConnection, error) {
trustService := r.TrustService(ctx, obj.ID.TenantID())
pageOrderBy := page.OrderBy[coredata.ComplianceFrameworkOrderField]{
Field: coredata.ComplianceFrameworkOrderFieldRank,
Direction: page.OrderDirectionAsc,
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
cfPage, err := trustService.ComplianceFrameworks.ListByTrustCenterID(ctx, obj.ID, cursor)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot list compliance frameworks", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return types.NewComplianceFrameworkConnection(cfPage), nil
}
// ExternalUrls is the resolver for the externalUrls field.
func (r *trustCenterResolver) ExternalUrls(ctx context.Context, obj *types.TrustCenter, first *int, after *page.CursorKey, last *int, before *page.CursorKey) (*types.ComplianceExternalURLConnection, error) {
trustService := r.TrustService(ctx, obj.ID.TenantID())
pageOrderBy := page.OrderBy[coredata.ComplianceExternalURLOrderField]{
Field: coredata.ComplianceExternalURLOrderFieldRank,
Direction: page.OrderDirectionAsc,
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
result, err := trustService.ComplianceExternalURLs.ListForTrustCenterID(ctx, obj.ID, cursor)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot list compliance external URLs", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return types.NewComplianceExternalURLConnection(result), nil
}
// Updates is the resolver for the updates field.
func (r *trustCenterResolver) Updates(ctx context.Context, obj *types.TrustCenter, first *int, after *page.CursorKey, last *int, before *page.CursorKey) (*types.MailingListUpdateConnection, error) {
trustService := r.TrustService(ctx, obj.ID.TenantID())
tc, err := trustService.TrustCenters.Get(ctx, obj.ID)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot load trust center", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
if tc.MailingListID == nil {
return &types.MailingListUpdateConnection{Edges: []*types.MailingListUpdateEdge{}, PageInfo: &types.PageInfo{}}, nil
}
pageOrderBy := page.OrderBy[coredata.MailingListUpdateOrderField]{
Field: coredata.MailingListUpdateOrderFieldUpdatedAt,
Direction: page.OrderDirectionDesc,
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
result, err := r.mailman.ListSentMailingListUpdates(ctx, *tc.MailingListID, cursor)
if err != nil {
r.logger.ErrorCtx(ctx, "cannot list mailing list updates", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return types.NewMailingListUpdateConnection(result), nil
}
// IsUserAuthorized is the resolver for the isUserAuthorized field.
func (r *trustCenterFileResolver) IsUserAuthorized(ctx context.Context, obj *types.TrustCenterFile) (bool, error) {
trustService := r.TrustService(ctx, obj.ID.TenantID())
@@ -725,6 +959,9 @@ func (r *Resolver) SubprocessorConnection() schema.SubprocessorConnectionResolve
return &subprocessorConnectionResolver{r}
}
// TrustCenter returns schema.TrustCenterResolver implementation.
func (r *Resolver) TrustCenter() schema.TrustCenterResolver { return &trustCenterResolver{r} }
// TrustCenterFile returns schema.TrustCenterFileResolver implementation.
func (r *Resolver) TrustCenterFile() schema.TrustCenterFileResolver {
return &trustCenterFileResolver{r}
@@ -741,5 +978,6 @@ type documentResolver struct{ *Resolver }
type frameworkResolver struct{ *Resolver }
type reportResolver struct{ *Resolver }
type subprocessorConnectionResolver struct{ *Resolver }
type trustCenterResolver struct{ *Resolver }
type trustCenterFileResolver struct{ *Resolver }
type trustCenterReferenceResolver struct{ *Resolver }