Trust center access management - get rid of access token

Signed-off-by: Émile Ré <emile@getprobo.com>
This commit is contained in:
Émile Ré
2026-01-15 16:16:06 +04:00
committed by Bryan Frimin
parent 8b3bda56e6
commit 44d85a2b12
39 changed files with 582 additions and 1800 deletions

View File

@@ -23,10 +23,16 @@ import (
type ctxKey struct{ name string }
var (
compliancePageKey = &ctxKey{name: "compliance_page"}
compliancePageKey = &ctxKey{name: "compliance_page"}
complianceMembershipKey = &ctxKey{name: "compliance_membership"}
)
func CompliancePageFromContext(ctx context.Context) *coredata.TrustCenter {
trustCenter, _ := ctx.Value(compliancePageKey).(*coredata.TrustCenter)
return trustCenter
}
func ComplianceMembershipFromContext(ctx context.Context) *coredata.TrustCenterAccess {
membership, _ := ctx.Value(complianceMembershipKey).(*coredata.TrustCenterAccess)
return membership
}

View File

@@ -16,10 +16,15 @@ package compliancepage
import (
"context"
"errors"
"net/http"
"github.com/99designs/gqlgen/graphql"
"github.com/go-chi/chi/v5"
"github.com/vektah/gqlparser/v2/gqlerror"
"go.gearno.de/kit/httpserver"
"go.probo.inc/probo/pkg/gid"
"go.probo.inc/probo/pkg/server/gqlutils"
"go.probo.inc/probo/pkg/trust"
)
@@ -33,7 +38,25 @@ func NewIDMiddleware(trustSvc *trust.Service) func(next http.Handler) http.Handl
if id, err := gid.ParseGID(value); err == nil {
compliancePage, err := trustSvc.Get(ctx, id)
if err != nil || !compliancePage.Active {
if err != nil {
if errors.Is(err, trust.ErrPageNotFound) {
next.ServeHTTP(w, r)
return
}
httpserver.RenderJSON(
w,
http.StatusInternalServerError,
&graphql.Response{
Errors: gqlerror.List{
gqlutils.Internal(ctx),
},
},
)
return
}
if !compliancePage.Active {
next.ServeHTTP(w, r)
return
}
@@ -43,7 +66,26 @@ func NewIDMiddleware(trustSvc *trust.Service) func(next http.Handler) http.Handl
return
}
if compliancePage, err := trustSvc.GetBySlug(ctx, value); err == nil && compliancePage.Active {
compliancePage, err := trustSvc.GetBySlug(ctx, value)
if err != nil {
if errors.Is(err, trust.ErrPageNotFound) {
next.ServeHTTP(w, r)
return
}
httpserver.RenderJSON(
w,
http.StatusInternalServerError,
&graphql.Response{
Errors: gqlerror.List{
gqlutils.Internal(ctx),
},
},
)
return
}
if compliancePage.Active {
ctx = context.WithValue(ctx, compliancePageKey, compliancePage)
next.ServeHTTP(w, r.WithContext(ctx))
return

View File

@@ -0,0 +1,74 @@
// Copyright (c) 2025 Probo Inc <hello@getprobo.com>.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
package compliancepage
import (
"context"
"errors"
"net/http"
"github.com/99designs/gqlgen/graphql"
"github.com/vektah/gqlparser/v2/gqlerror"
"go.gearno.de/kit/httpserver"
"go.gearno.de/kit/log"
"go.probo.inc/probo/pkg/server/api/authn"
"go.probo.inc/probo/pkg/server/gqlutils"
"go.probo.inc/probo/pkg/trust"
)
func NewMembershipMiddleware(trustSvc *trust.Service, logger *log.Logger) func(next http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(
func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
identity := authn.IdentityFromContext(r.Context())
if identity == nil {
next.ServeHTTP(w, r)
return
}
compliancePage := CompliancePageFromContext(ctx)
membership, err := trustSvc.GetMembershipByCompliancePageIDAndEmail(ctx, compliancePage.ID, identity.EmailAddress)
if err != nil {
if errors.Is(err, trust.ErrMembershipNotFound) {
next.ServeHTTP(w, r)
return
}
logger.ErrorCtx(ctx, "cannot get membership by page id and email", log.Error(err))
httpserver.RenderJSON(
w,
http.StatusInternalServerError,
&graphql.Response{
Errors: gqlerror.List{
gqlutils.Internal(ctx),
},
},
)
return
}
if membership.Active {
ctx = context.WithValue(ctx, complianceMembershipKey, membership)
next.ServeHTTP(w, r.WithContext(ctx))
return
}
next.ServeHTTP(w, r)
},
)
}
}

View File

@@ -16,8 +16,13 @@ package compliancepage
import (
"context"
"errors"
"net/http"
"github.com/99designs/gqlgen/graphql"
"github.com/vektah/gqlparser/v2/gqlerror"
"go.gearno.de/kit/httpserver"
"go.probo.inc/probo/pkg/server/gqlutils"
"go.probo.inc/probo/pkg/trust"
)
@@ -32,13 +37,31 @@ func NewSNIMiddleware(trustSvc *trust.Service) func(next http.Handler) http.Hand
}
compliancePage, err := trustSvc.GetByDomainName(ctx, r.TLS.ServerName)
if err != nil || !compliancePage.Active {
next.ServeHTTP(w, r)
if err != nil {
if errors.Is(err, trust.ErrPageNotFound) {
next.ServeHTTP(w, r)
return
}
httpserver.RenderJSON(
w,
http.StatusInternalServerError,
&graphql.Response{
Errors: gqlerror.List{
gqlutils.Internal(ctx),
},
},
)
return
}
ctx = context.WithValue(ctx, compliancePageKey, compliancePage)
next.ServeHTTP(w, r.WithContext(ctx))
if compliancePage.Active {
ctx = context.WithValue(ctx, compliancePageKey, compliancePage)
next.ServeHTTP(w, r.WithContext(ctx))
return
}
next.ServeHTTP(w, r)
})
}
}

View File

@@ -6169,7 +6169,7 @@ func (r *organizationResolver) TrustCenterFiles(ctx context.Context, obj *types.
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
pageResult, err := prb.TrustCenterFiles.ListForOrganizationID(ctx, obj.ID, cursor)
pageResult, err := prb.TrustCenterFiles.ListForOrganizationID(ctx, obj.ID, cursor, &coredata.TrustCenterFileFilter{})
if err != nil {
// TODO no panic use gqlutils.InternalError
panic(fmt.Errorf("cannot list organization trust center files: %w", err))

View File

@@ -0,0 +1,63 @@
// Copyright (c) 2025 Probo Inc <hello@getprobo.com>.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
package trust_v1
import (
"context"
"net/http"
"github.com/99designs/gqlgen/graphql"
"go.gearno.de/kit/log"
"go.probo.inc/probo/pkg/baseurl"
"go.probo.inc/probo/pkg/iam"
"go.probo.inc/probo/pkg/securecookie"
"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"
"go.probo.inc/probo/pkg/server/gqlutils"
"go.probo.inc/probo/pkg/server/gqlutils/directives/session"
"go.probo.inc/probo/pkg/trust"
)
func MembersOnlyDirective(ctx context.Context, obj any, next graphql.Resolver) (any, error) {
membership := compliancepage.ComplianceMembershipFromContext(ctx)
if membership == nil {
return nil, gqlutils.Forbiddenf(ctx, "insufficient permission to access this resource")
}
return next(ctx)
}
func NewGraphQLHandler(iamSvc *iam.Service, trustSvc *trust.Service, logger *log.Logger, baseURL *baseurl.BaseURL, cookieConfig securecookie.Config) http.Handler {
config := schema.Config{
Resolvers: &Resolver{
iam: iamSvc,
trust: trustSvc,
logger: logger,
baseURL: baseURL,
sessionCookie: authn.NewCookie(&cookieConfig),
},
Directives: schema.DirectiveRoot{
Session: session.Directive,
MembersOnly: MembersOnlyDirective,
},
}
es := schema.NewExecutableSchema(config)
gqlh := gqlutils.NewHandler(es, logger)
return gqlh
}

View File

@@ -28,9 +28,6 @@ import (
"go.probo.inc/probo/pkg/securecookie"
"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"
"go.probo.inc/probo/pkg/server/gqlutils"
"go.probo.inc/probo/pkg/server/gqlutils/directives/session"
"go.probo.inc/probo/pkg/trust"
)
@@ -85,21 +82,9 @@ func NewMux(
r.Use(compliancepage.NewCompliancePagePresenceMiddleware())
r.Use(authn.NewSessionMiddleware(iamSvc, cookieConfig))
r.Use(compliancepage.NewMembershipMiddleware(trustSvc, logger))
config := schema.Config{
Resolvers: &Resolver{
iam: iamSvc,
trust: trustSvc,
logger: logger,
sessionCookie: authn.NewCookie(&cookieConfig),
baseURL: baseURL,
},
Directives: schema.DirectiveRoot{
Session: session.Directive,
},
}
es := schema.NewExecutableSchema(config)
graphqlHandler := gqlutils.NewHandler(es, logger)
graphqlHandler := NewGraphQLHandler(iamSvc, trustSvc, logger, baseURL, cookieConfig)
r.Handle("/graphql", graphqlHandler)

View File

@@ -12,6 +12,8 @@ directive @goModel(
directive @goEnum(value: String) on ENUM_VALUE
directive @membersOnly on FIELD_DEFINITION
enum Role {
NONE
USER
@@ -495,7 +497,7 @@ type TrustCenter implements Node {
ndaFileName: String
ndaFileUrl: String @goField(forceResolver: true)
organization: Organization! @goField(forceResolver: true)
isUserAuthenticated: Boolean! @goField(forceResolver: true)
isViewerMember: Boolean! @goField(forceResolver: true)
hasAcceptedNonDisclosureAgreement: Boolean! @goField(forceResolver: true)
documents(
@@ -610,30 +612,37 @@ type Query {
type Mutation {
sendMagicLink(input: SendMagicLinkInput!): SendMagicLinkPayload
@session(required: OPTIONAL)
verifyMagicLink(input: VerifyMagicLinkInput!): VerifyMagicLinkPayload
@session(required: OPTIONAL)
requestAllAccesses: RequestAccessesPayload!
requestAllAccesses: RequestAccessesPayload! @session(required: PRESENT)
exportDocumentPDF(input: ExportDocumentPDFInput!): ExportDocumentPDFPayload!
@session(required: NONE)
@session(required: PRESENT)
@membersOnly
exportReportPDF(input: ExportReportPDFInput!): ExportReportPDFPayload!
@session(required: NONE)
@session(required: PRESENT)
@membersOnly
acceptNonDisclosureAgreement: AcceptNonDisclosureAgreementPayload!
@session(required: PRESENT)
@membersOnly
requestDocumentAccess(
input: RequestDocumentAccessInput!
): RequestAccessesPayload!
): RequestAccessesPayload! @session(required: PRESENT)
requestReportAccess(input: RequestReportAccessInput!): RequestAccessesPayload!
requestReportAccess(
input: RequestReportAccessInput!
): RequestAccessesPayload! @session(required: PRESENT)
requestTrustCenterFileAccess(
input: RequestTrustCenterFileAccessInput!
): RequestAccessesPayload!
): RequestAccessesPayload! @session(required: PRESENT)
exportTrustCenterFile(
input: ExportTrustCenterFileInput!
): ExportTrustCenterFilePayload!
): ExportTrustCenterFilePayload! @session(required: PRESENT) @membersOnly
}

View File

@@ -60,7 +60,8 @@ type ResolverRoot interface {
}
type DirectiveRoot struct {
Session func(ctx context.Context, obj any, next graphql.Resolver, required session.SessionRequirement) (res any, err error)
MembersOnly func(ctx context.Context, obj any, next graphql.Resolver) (res any, err error)
Session func(ctx context.Context, obj any, next graphql.Resolver, required session.SessionRequirement) (res any, err error)
}
type ComplexityRoot struct {
@@ -187,7 +188,7 @@ type ComplexityRoot struct {
Documents func(childComplexity int, first *int, after *page.CursorKey, last *int, before *page.CursorKey) int
HasAcceptedNonDisclosureAgreement func(childComplexity int) int
ID func(childComplexity int) int
IsUserAuthenticated func(childComplexity int) int
IsViewerMember func(childComplexity int) int
NdaFileName func(childComplexity int) int
NdaFileURL func(childComplexity int) int
Organization func(childComplexity int) int
@@ -304,7 +305,7 @@ type ReportResolver interface {
type TrustCenterResolver interface {
NdaFileURL(ctx context.Context, obj *types.TrustCenter) (*string, error)
Organization(ctx context.Context, obj *types.TrustCenter) (*types.Organization, error)
IsUserAuthenticated(ctx context.Context, obj *types.TrustCenter) (bool, error)
IsViewerMember(ctx context.Context, obj *types.TrustCenter) (bool, error)
HasAcceptedNonDisclosureAgreement(ctx context.Context, obj *types.TrustCenter) (bool, error)
Documents(ctx context.Context, obj *types.TrustCenter, first *int, after *page.CursorKey, last *int, before *page.CursorKey) (*types.DocumentConnection, error)
Audits(ctx context.Context, obj *types.TrustCenter, first *int, after *page.CursorKey, last *int, before *page.CursorKey) (*types.AuditConnection, error)
@@ -803,12 +804,12 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin
}
return e.complexity.TrustCenter.ID(childComplexity), true
case "TrustCenter.isUserAuthenticated":
if e.complexity.TrustCenter.IsUserAuthenticated == nil {
case "TrustCenter.isViewerMember":
if e.complexity.TrustCenter.IsViewerMember == nil {
break
}
return e.complexity.TrustCenter.IsUserAuthenticated(childComplexity), true
return e.complexity.TrustCenter.IsViewerMember(childComplexity), true
case "TrustCenter.ndaFileName":
if e.complexity.TrustCenter.NdaFileName == nil {
break
@@ -1209,6 +1210,8 @@ directive @goModel(
directive @goEnum(value: String) on ENUM_VALUE
directive @membersOnly on FIELD_DEFINITION
enum Role {
NONE
USER
@@ -1692,7 +1695,7 @@ type TrustCenter implements Node {
ndaFileName: String
ndaFileUrl: String @goField(forceResolver: true)
organization: Organization! @goField(forceResolver: true)
isUserAuthenticated: Boolean! @goField(forceResolver: true)
isViewerMember: Boolean! @goField(forceResolver: true)
hasAcceptedNonDisclosureAgreement: Boolean! @goField(forceResolver: true)
documents(
@@ -1807,32 +1810,39 @@ type Query {
type Mutation {
sendMagicLink(input: SendMagicLinkInput!): SendMagicLinkPayload
@session(required: OPTIONAL)
verifyMagicLink(input: VerifyMagicLinkInput!): VerifyMagicLinkPayload
@session(required: OPTIONAL)
requestAllAccesses: RequestAccessesPayload!
requestAllAccesses: RequestAccessesPayload! @session(required: PRESENT)
exportDocumentPDF(input: ExportDocumentPDFInput!): ExportDocumentPDFPayload!
@session(required: NONE)
@session(required: PRESENT)
@membersOnly
exportReportPDF(input: ExportReportPDFInput!): ExportReportPDFPayload!
@session(required: NONE)
@session(required: PRESENT)
@membersOnly
acceptNonDisclosureAgreement: AcceptNonDisclosureAgreementPayload!
@session(required: PRESENT)
@membersOnly
requestDocumentAccess(
input: RequestDocumentAccessInput!
): RequestAccessesPayload!
): RequestAccessesPayload! @session(required: PRESENT)
requestReportAccess(input: RequestReportAccessInput!): RequestAccessesPayload!
requestReportAccess(
input: RequestReportAccessInput!
): RequestAccessesPayload! @session(required: PRESENT)
requestTrustCenterFileAccess(
input: RequestTrustCenterFileAccessInput!
): RequestAccessesPayload!
): RequestAccessesPayload! @session(required: PRESENT)
exportTrustCenterFile(
input: ExportTrustCenterFileInput!
): ExportTrustCenterFilePayload!
): ExportTrustCenterFilePayload! @session(required: PRESENT) @membersOnly
}
`, BuiltIn: false},
{Name: "../../../../gqlutils/directives/session/schema.graphql", Input: `# Session directive for GraphQL APIs
@@ -3136,7 +3146,25 @@ func (ec *executionContext) _Mutation_sendMagicLink(ctx context.Context, field g
fc := graphql.GetFieldContext(ctx)
return ec.resolvers.Mutation().SendMagicLink(ctx, fc.Args["input"].(types.SendMagicLinkInput))
},
nil,
func(ctx context.Context, next graphql.Resolver) graphql.Resolver {
directive0 := next
directive1 := func(ctx context.Context) (any, error) {
required, err := ec.unmarshalNSessionRequirement2goᚗproboᚗincᚋproboᚋpkgᚋserverᚋgqlutilsᚋdirectivesᚋsessionᚐSessionRequirement(ctx, "OPTIONAL")
if err != nil {
var zeroVal *types.SendMagicLinkPayload
return zeroVal, err
}
if ec.directives.Session == nil {
var zeroVal *types.SendMagicLinkPayload
return zeroVal, errors.New("directive session is not implemented")
}
return ec.directives.Session(ctx, nil, directive0, required)
}
next = directive1
return next
},
ec.marshalOSendMagicLinkPayload2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋtrustᚋv1ᚋtypesᚐSendMagicLinkPayload,
true,
false,
@@ -3181,7 +3209,25 @@ func (ec *executionContext) _Mutation_verifyMagicLink(ctx context.Context, field
fc := graphql.GetFieldContext(ctx)
return ec.resolvers.Mutation().VerifyMagicLink(ctx, fc.Args["input"].(types.VerifyMagicLinkInput))
},
nil,
func(ctx context.Context, next graphql.Resolver) graphql.Resolver {
directive0 := next
directive1 := func(ctx context.Context) (any, error) {
required, err := ec.unmarshalNSessionRequirement2goᚗproboᚗincᚋproboᚋpkgᚋserverᚋgqlutilsᚋdirectivesᚋsessionᚐSessionRequirement(ctx, "OPTIONAL")
if err != nil {
var zeroVal *types.VerifyMagicLinkPayload
return zeroVal, err
}
if ec.directives.Session == nil {
var zeroVal *types.VerifyMagicLinkPayload
return zeroVal, errors.New("directive session is not implemented")
}
return ec.directives.Session(ctx, nil, directive0, required)
}
next = directive1
return next
},
ec.marshalOVerifyMagicLinkPayload2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋtrustᚋv1ᚋtypesᚐVerifyMagicLinkPayload,
true,
false,
@@ -3225,7 +3271,25 @@ func (ec *executionContext) _Mutation_requestAllAccesses(ctx context.Context, fi
func(ctx context.Context) (any, error) {
return ec.resolvers.Mutation().RequestAllAccesses(ctx)
},
nil,
func(ctx context.Context, next graphql.Resolver) graphql.Resolver {
directive0 := next
directive1 := func(ctx context.Context) (any, error) {
required, err := ec.unmarshalNSessionRequirement2goᚗproboᚗincᚋproboᚋpkgᚋserverᚋgqlutilsᚋdirectivesᚋsessionᚐSessionRequirement(ctx, "PRESENT")
if err != nil {
var zeroVal *types.RequestAccessesPayload
return zeroVal, err
}
if ec.directives.Session == nil {
var zeroVal *types.RequestAccessesPayload
return zeroVal, errors.New("directive session is not implemented")
}
return ec.directives.Session(ctx, nil, directive0, required)
}
next = directive1
return next
},
ec.marshalNRequestAccessesPayload2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋtrustᚋv1ᚋtypesᚐRequestAccessesPayload,
true,
true,
@@ -3263,7 +3327,7 @@ func (ec *executionContext) _Mutation_exportDocumentPDF(ctx context.Context, fie
directive0 := next
directive1 := func(ctx context.Context) (any, error) {
required, err := ec.unmarshalNSessionRequirement2goᚗproboᚗincᚋproboᚋpkgᚋserverᚋgqlutilsᚋdirectivesᚋsessionᚐSessionRequirement(ctx, "NONE")
required, err := ec.unmarshalNSessionRequirement2goᚗproboᚗincᚋproboᚋpkgᚋserverᚋgqlutilsᚋdirectivesᚋsessionᚐSessionRequirement(ctx, "PRESENT")
if err != nil {
var zeroVal *types.ExportDocumentPDFPayload
return zeroVal, err
@@ -3274,8 +3338,15 @@ func (ec *executionContext) _Mutation_exportDocumentPDF(ctx context.Context, fie
}
return ec.directives.Session(ctx, nil, directive0, required)
}
directive2 := func(ctx context.Context) (any, error) {
if ec.directives.MembersOnly == nil {
var zeroVal *types.ExportDocumentPDFPayload
return zeroVal, errors.New("directive membersOnly is not implemented")
}
return ec.directives.MembersOnly(ctx, nil, directive1)
}
next = directive1
next = directive2
return next
},
ec.marshalNExportDocumentPDFPayload2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋtrustᚋv1ᚋtypesᚐExportDocumentPDFPayload,
@@ -3326,7 +3397,7 @@ func (ec *executionContext) _Mutation_exportReportPDF(ctx context.Context, field
directive0 := next
directive1 := func(ctx context.Context) (any, error) {
required, err := ec.unmarshalNSessionRequirement2goᚗproboᚗincᚋproboᚋpkgᚋserverᚋgqlutilsᚋdirectivesᚋsessionᚐSessionRequirement(ctx, "NONE")
required, err := ec.unmarshalNSessionRequirement2goᚗproboᚗincᚋproboᚋpkgᚋserverᚋgqlutilsᚋdirectivesᚋsessionᚐSessionRequirement(ctx, "PRESENT")
if err != nil {
var zeroVal *types.ExportReportPDFPayload
return zeroVal, err
@@ -3337,8 +3408,15 @@ func (ec *executionContext) _Mutation_exportReportPDF(ctx context.Context, field
}
return ec.directives.Session(ctx, nil, directive0, required)
}
directive2 := func(ctx context.Context) (any, error) {
if ec.directives.MembersOnly == nil {
var zeroVal *types.ExportReportPDFPayload
return zeroVal, errors.New("directive membersOnly is not implemented")
}
return ec.directives.MembersOnly(ctx, nil, directive1)
}
next = directive1
next = directive2
return next
},
ec.marshalNExportReportPDFPayload2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋtrustᚋv1ᚋtypesᚐExportReportPDFPayload,
@@ -3399,8 +3477,15 @@ func (ec *executionContext) _Mutation_acceptNonDisclosureAgreement(ctx context.C
}
return ec.directives.Session(ctx, nil, directive0, required)
}
directive2 := func(ctx context.Context) (any, error) {
if ec.directives.MembersOnly == nil {
var zeroVal *types.AcceptNonDisclosureAgreementPayload
return zeroVal, errors.New("directive membersOnly is not implemented")
}
return ec.directives.MembersOnly(ctx, nil, directive1)
}
next = directive1
next = directive2
return next
},
ec.marshalNAcceptNonDisclosureAgreementPayload2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋtrustᚋv1ᚋtypesᚐAcceptNonDisclosureAgreementPayload,
@@ -3436,7 +3521,25 @@ func (ec *executionContext) _Mutation_requestDocumentAccess(ctx context.Context,
fc := graphql.GetFieldContext(ctx)
return ec.resolvers.Mutation().RequestDocumentAccess(ctx, fc.Args["input"].(types.RequestDocumentAccessInput))
},
nil,
func(ctx context.Context, next graphql.Resolver) graphql.Resolver {
directive0 := next
directive1 := func(ctx context.Context) (any, error) {
required, err := ec.unmarshalNSessionRequirement2goᚗproboᚗincᚋproboᚋpkgᚋserverᚋgqlutilsᚋdirectivesᚋsessionᚐSessionRequirement(ctx, "PRESENT")
if err != nil {
var zeroVal *types.RequestAccessesPayload
return zeroVal, err
}
if ec.directives.Session == nil {
var zeroVal *types.RequestAccessesPayload
return zeroVal, errors.New("directive session is not implemented")
}
return ec.directives.Session(ctx, nil, directive0, required)
}
next = directive1
return next
},
ec.marshalNRequestAccessesPayload2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋtrustᚋv1ᚋtypesᚐRequestAccessesPayload,
true,
true,
@@ -3481,7 +3584,25 @@ func (ec *executionContext) _Mutation_requestReportAccess(ctx context.Context, f
fc := graphql.GetFieldContext(ctx)
return ec.resolvers.Mutation().RequestReportAccess(ctx, fc.Args["input"].(types.RequestReportAccessInput))
},
nil,
func(ctx context.Context, next graphql.Resolver) graphql.Resolver {
directive0 := next
directive1 := func(ctx context.Context) (any, error) {
required, err := ec.unmarshalNSessionRequirement2goᚗproboᚗincᚋproboᚋpkgᚋserverᚋgqlutilsᚋdirectivesᚋsessionᚐSessionRequirement(ctx, "PRESENT")
if err != nil {
var zeroVal *types.RequestAccessesPayload
return zeroVal, err
}
if ec.directives.Session == nil {
var zeroVal *types.RequestAccessesPayload
return zeroVal, errors.New("directive session is not implemented")
}
return ec.directives.Session(ctx, nil, directive0, required)
}
next = directive1
return next
},
ec.marshalNRequestAccessesPayload2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋtrustᚋv1ᚋtypesᚐRequestAccessesPayload,
true,
true,
@@ -3526,7 +3647,25 @@ func (ec *executionContext) _Mutation_requestTrustCenterFileAccess(ctx context.C
fc := graphql.GetFieldContext(ctx)
return ec.resolvers.Mutation().RequestTrustCenterFileAccess(ctx, fc.Args["input"].(types.RequestTrustCenterFileAccessInput))
},
nil,
func(ctx context.Context, next graphql.Resolver) graphql.Resolver {
directive0 := next
directive1 := func(ctx context.Context) (any, error) {
required, err := ec.unmarshalNSessionRequirement2goᚗproboᚗincᚋproboᚋpkgᚋserverᚋgqlutilsᚋdirectivesᚋsessionᚐSessionRequirement(ctx, "PRESENT")
if err != nil {
var zeroVal *types.RequestAccessesPayload
return zeroVal, err
}
if ec.directives.Session == nil {
var zeroVal *types.RequestAccessesPayload
return zeroVal, errors.New("directive session is not implemented")
}
return ec.directives.Session(ctx, nil, directive0, required)
}
next = directive1
return next
},
ec.marshalNRequestAccessesPayload2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋtrustᚋv1ᚋtypesᚐRequestAccessesPayload,
true,
true,
@@ -3571,7 +3710,32 @@ func (ec *executionContext) _Mutation_exportTrustCenterFile(ctx context.Context,
fc := graphql.GetFieldContext(ctx)
return ec.resolvers.Mutation().ExportTrustCenterFile(ctx, fc.Args["input"].(types.ExportTrustCenterFileInput))
},
nil,
func(ctx context.Context, next graphql.Resolver) graphql.Resolver {
directive0 := next
directive1 := func(ctx context.Context) (any, error) {
required, err := ec.unmarshalNSessionRequirement2goᚗproboᚗincᚋproboᚋpkgᚋserverᚋgqlutilsᚋdirectivesᚋsessionᚐSessionRequirement(ctx, "PRESENT")
if err != nil {
var zeroVal *types.ExportTrustCenterFilePayload
return zeroVal, err
}
if ec.directives.Session == nil {
var zeroVal *types.ExportTrustCenterFilePayload
return zeroVal, errors.New("directive session is not implemented")
}
return ec.directives.Session(ctx, nil, directive0, required)
}
directive2 := func(ctx context.Context) (any, error) {
if ec.directives.MembersOnly == nil {
var zeroVal *types.ExportTrustCenterFilePayload
return zeroVal, errors.New("directive membersOnly is not implemented")
}
return ec.directives.MembersOnly(ctx, nil, directive1)
}
next = directive2
return next
},
ec.marshalNExportTrustCenterFilePayload2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋtrustᚋv1ᚋtypesᚐExportTrustCenterFilePayload,
true,
true,
@@ -4045,8 +4209,8 @@ func (ec *executionContext) fieldContext_Query_currentTrustCenter(_ context.Cont
return ec.fieldContext_TrustCenter_ndaFileUrl(ctx, field)
case "organization":
return ec.fieldContext_TrustCenter_organization(ctx, field)
case "isUserAuthenticated":
return ec.fieldContext_TrustCenter_isUserAuthenticated(ctx, field)
case "isViewerMember":
return ec.fieldContext_TrustCenter_isViewerMember(ctx, field)
case "hasAcceptedNonDisclosureAgreement":
return ec.fieldContext_TrustCenter_hasAcceptedNonDisclosureAgreement(ctx, field)
case "documents":
@@ -4550,14 +4714,14 @@ func (ec *executionContext) fieldContext_TrustCenter_organization(_ context.Cont
return fc, nil
}
func (ec *executionContext) _TrustCenter_isUserAuthenticated(ctx context.Context, field graphql.CollectedField, obj *types.TrustCenter) (ret graphql.Marshaler) {
func (ec *executionContext) _TrustCenter_isViewerMember(ctx context.Context, field graphql.CollectedField, obj *types.TrustCenter) (ret graphql.Marshaler) {
return graphql.ResolveField(
ctx,
ec.OperationContext,
field,
ec.fieldContext_TrustCenter_isUserAuthenticated,
ec.fieldContext_TrustCenter_isViewerMember,
func(ctx context.Context) (any, error) {
return ec.resolvers.TrustCenter().IsUserAuthenticated(ctx, obj)
return ec.resolvers.TrustCenter().IsViewerMember(ctx, obj)
},
nil,
ec.marshalNBoolean2bool,
@@ -4566,7 +4730,7 @@ func (ec *executionContext) _TrustCenter_isUserAuthenticated(ctx context.Context
)
}
func (ec *executionContext) fieldContext_TrustCenter_isUserAuthenticated(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
func (ec *executionContext) fieldContext_TrustCenter_isViewerMember(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
fc = &graphql.FieldContext{
Object: "TrustCenter",
Field: field,
@@ -9046,7 +9210,7 @@ func (ec *executionContext) _TrustCenter(ctx context.Context, sel ast.SelectionS
}
out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) })
case "isUserAuthenticated":
case "isViewerMember":
field := field
innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) {
@@ -9055,7 +9219,7 @@ func (ec *executionContext) _TrustCenter(ctx context.Context, sel ast.SelectionS
ec.Error(ctx, ec.Recover(ctx, r))
}
}()
res = ec._TrustCenter_isUserAuthenticated(ctx, field, obj)
res = ec._TrustCenter_isViewerMember(ctx, field, obj)
if res == graphql.Null {
atomic.AddUint32(&fs.Invalids, 1)
}

View File

@@ -177,7 +177,7 @@ type TrustCenter struct {
NdaFileName *string `json:"ndaFileName,omitempty"`
NdaFileURL *string `json:"ndaFileUrl,omitempty"`
Organization *Organization `json:"organization"`
IsUserAuthenticated bool `json:"isUserAuthenticated"`
IsViewerMember bool `json:"isViewerMember"`
HasAcceptedNonDisclosureAgreement bool `json:"hasAcceptedNonDisclosureAgreement"`
Documents *DocumentConnection `json:"documents"`
Audits *AuditConnection `json:"audits"`

View File

@@ -166,11 +166,12 @@ func (r *mutationResolver) SendMagicLink(ctx context.Context, input types.SendMa
customDomain, err := r.trust.GetCustomDomainByOrganizationID(ctx, organization.ID)
if err != nil {
var errNotFound *iam.ErrOrganizationNotFound
if !errors.As(err, &errNotFound) {
r.logger.ErrorCtx(ctx, "cannot get custom domain", log.Error(err))
return nil, gqlutils.Internal(ctx)
if errors.Is(err, trust.ErrCustomDomainNotFound) {
return nil, gqlutils.NotFoundf(ctx, "custom domain not found")
}
r.logger.ErrorCtx(ctx, "cannot get custom domain", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
req := &iam.SendMagicLinkRequest{
@@ -874,11 +875,11 @@ func (r *trustCenterResolver) Organization(ctx context.Context, obj *types.Trust
return obj.Organization, nil
}
// IsUserAuthenticated is the resolver for the isUserAuthenticated field.
func (r *trustCenterResolver) IsUserAuthenticated(ctx context.Context, obj *types.TrustCenter) (bool, error) {
identity := authn.IdentityFromContext(ctx)
// IsViewerMember is the resolver for the isViewerMember field.
func (r *trustCenterResolver) IsViewerMember(ctx context.Context, obj *types.TrustCenter) (bool, error) {
membership := compliancepage.ComplianceMembershipFromContext(ctx)
return identity != nil, nil
return membership != nil, nil
}
// HasAcceptedNonDisclosureAgreement is the resolver for the hasAcceptedNonDisclosureAgreement field.
@@ -985,7 +986,13 @@ func (r *trustCenterResolver) TrustCenterFiles(ctx context.Context, obj *types.T
}
cursor := types.NewCursor(first, after, last, before, pageOrderBy)
trustCenterFilePage, err := trustService.TrustCenterFiles.ListForOrganizationId(ctx, obj.Organization.ID, cursor)
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)