Update trust center handler
Signed-off-by: Bryan Frimin <bryan@getprobo.com>
This commit is contained in:
@@ -98,11 +98,8 @@ type (
|
|||||||
Snapshots *SnapshotService
|
Snapshots *SnapshotService
|
||||||
ContinualImprovements *ContinualImprovementService
|
ContinualImprovements *ContinualImprovementService
|
||||||
ProcessingActivities *ProcessingActivityService
|
ProcessingActivities *ProcessingActivityService
|
||||||
<<<<<<< HEAD
|
|
||||||
Files *FileService
|
Files *FileService
|
||||||
=======
|
|
||||||
CustomDomains *CustomDomainService
|
CustomDomains *CustomDomainService
|
||||||
>>>>>>> 087e86b5 (Add service impl)
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -213,7 +210,7 @@ func (s *Service) WithTenant(tenantID gid.TenantID) *TenantService {
|
|||||||
acmeService: s.acmeService,
|
acmeService: s.acmeService,
|
||||||
logger: s.logger.Named("custom_domains"),
|
logger: s.logger.Named("custom_domains"),
|
||||||
}
|
}
|
||||||
|
|
||||||
return tenantService
|
return tenantService
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -359,3 +356,29 @@ func (s *Service) LoadOrganizationByDomain(ctx context.Context, domain string) (
|
|||||||
|
|
||||||
return organizationID, err
|
return organizationID, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type TrustCenterInfo struct {
|
||||||
|
ID gid.GID
|
||||||
|
OrganizationID gid.GID
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Service) LoadTrustCenterBySlug(ctx context.Context, slug string) (*TrustCenterInfo, error) {
|
||||||
|
var info TrustCenterInfo
|
||||||
|
|
||||||
|
err := s.pg.WithConn(
|
||||||
|
ctx,
|
||||||
|
func(conn pg.Conn) error {
|
||||||
|
var trustCenter coredata.TrustCenter
|
||||||
|
if err := trustCenter.LoadBySlug(ctx, conn, slug); err != nil {
|
||||||
|
return fmt.Errorf("cannot load trust center: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
info.ID = trustCenter.ID
|
||||||
|
info.OrganizationID = trustCenter.OrganizationID
|
||||||
|
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
return &info, err
|
||||||
|
}
|
||||||
|
|||||||
@@ -392,7 +392,7 @@ func (impl *Implm) Run(
|
|||||||
defer stopTrustCenterServer()
|
defer stopTrustCenterServer()
|
||||||
wg.Go(
|
wg.Go(
|
||||||
func() {
|
func() {
|
||||||
if err := impl.runTrustCenterServer(trustCenterServerCtx, l, r, tp, pgClient, serverHandler, acmeService); err != nil {
|
if err := impl.runTrustCenterServer(trustCenterServerCtx, l, r, tp, pgClient, serverHandler.TrustCenterHandler(), acmeService); err != nil {
|
||||||
cancel(fmt.Errorf("trust center server crashed: %w", err))
|
cancel(fmt.Errorf("trust center server crashed: %w", err))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -53,20 +53,21 @@ type (
|
|||||||
}
|
}
|
||||||
|
|
||||||
Config struct {
|
Config struct {
|
||||||
AllowedOrigins []string
|
AllowedOrigins []string
|
||||||
Probo *probo.Service
|
Probo *probo.Service
|
||||||
Usrmgr *usrmgr.Service
|
Usrmgr *usrmgr.Service
|
||||||
Trust *trust.Service
|
Trust *trust.Service
|
||||||
Auth ConsoleAuthConfig
|
Auth ConsoleAuthConfig
|
||||||
TrustAuth TrustAuthConfig
|
TrustAuth TrustAuthConfig
|
||||||
ConnectorRegistry *connector.ConnectorRegistry
|
ConnectorRegistry *connector.ConnectorRegistry
|
||||||
SafeRedirect *saferedirect.SafeRedirect
|
SafeRedirect *saferedirect.SafeRedirect
|
||||||
CustomDomainCname string
|
CustomDomainCname string
|
||||||
Logger *log.Logger
|
Logger *log.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
Server struct {
|
Server struct {
|
||||||
cfg Config
|
cfg Config
|
||||||
|
trustAPIHandler http.Handler
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -108,11 +109,39 @@ func NewServer(cfg Config) (*Server, error) {
|
|||||||
return nil, ErrMissingUsrmgrService
|
return nil, ErrMissingUsrmgrService
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create trust API handler once
|
||||||
|
trustAPIHandler := trust_v1.NewMux(
|
||||||
|
cfg.Logger.Named("trust.v1"),
|
||||||
|
cfg.Usrmgr,
|
||||||
|
cfg.Trust,
|
||||||
|
console_v1.AuthConfig{
|
||||||
|
CookieName: cfg.Auth.CookieName,
|
||||||
|
CookieDomain: cfg.Auth.CookieDomain,
|
||||||
|
SessionDuration: cfg.Auth.SessionDuration,
|
||||||
|
CookieSecret: cfg.Auth.CookieSecret,
|
||||||
|
},
|
||||||
|
trust_v1.TrustAuthConfig{
|
||||||
|
CookieName: cfg.TrustAuth.CookieName,
|
||||||
|
CookieDomain: cfg.TrustAuth.CookieDomain,
|
||||||
|
CookieDuration: cfg.TrustAuth.CookieDuration,
|
||||||
|
TokenDuration: cfg.TrustAuth.TokenDuration,
|
||||||
|
ReportURLDuration: cfg.TrustAuth.ReportURLDuration,
|
||||||
|
TokenSecret: cfg.TrustAuth.TokenSecret,
|
||||||
|
Scope: cfg.TrustAuth.Scope,
|
||||||
|
TokenType: cfg.TrustAuth.TokenType,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
return &Server{
|
return &Server{
|
||||||
cfg: cfg,
|
cfg: cfg,
|
||||||
|
trustAPIHandler: trustAPIHandler,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Server) TrustAPIHandler() http.Handler {
|
||||||
|
return s.trustAPIHandler
|
||||||
|
}
|
||||||
|
|
||||||
func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
corsOpts := cors.Options{
|
corsOpts := cors.Options{
|
||||||
AllowedOrigins: s.cfg.AllowedOrigins,
|
AllowedOrigins: s.cfg.AllowedOrigins,
|
||||||
@@ -160,30 +189,7 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||||||
)
|
)
|
||||||
|
|
||||||
// Mount the trust API with authentication
|
// Mount the trust API with authentication
|
||||||
router.Mount(
|
router.Mount("/trust/v1", s.trustAPIHandler)
|
||||||
"/trust/v1",
|
|
||||||
trust_v1.NewMux(
|
|
||||||
s.cfg.Logger.Named("trust.v1"),
|
|
||||||
s.cfg.Usrmgr,
|
|
||||||
s.cfg.Trust,
|
|
||||||
console_v1.AuthConfig{
|
|
||||||
CookieName: s.cfg.Auth.CookieName,
|
|
||||||
CookieDomain: s.cfg.Auth.CookieDomain,
|
|
||||||
SessionDuration: s.cfg.Auth.SessionDuration,
|
|
||||||
CookieSecret: s.cfg.Auth.CookieSecret,
|
|
||||||
},
|
|
||||||
trust_v1.TrustAuthConfig{
|
|
||||||
CookieName: s.cfg.TrustAuth.CookieName,
|
|
||||||
CookieDomain: s.cfg.TrustAuth.CookieDomain,
|
|
||||||
CookieDuration: s.cfg.TrustAuth.CookieDuration,
|
|
||||||
TokenDuration: s.cfg.TrustAuth.TokenDuration,
|
|
||||||
ReportURLDuration: s.cfg.TrustAuth.ReportURLDuration,
|
|
||||||
TokenSecret: s.cfg.TrustAuth.TokenSecret,
|
|
||||||
Scope: s.cfg.TrustAuth.Scope,
|
|
||||||
TokenType: s.cfg.TrustAuth.TokenType,
|
|
||||||
},
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
router.ServeHTTP(w, r)
|
router.ServeHTTP(w, r)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -71,7 +71,6 @@ type DocumentEdge {
|
|||||||
node: Document!
|
node: Document!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
type Framework implements Node {
|
type Framework implements Node {
|
||||||
id: ID!
|
id: ID!
|
||||||
name: String!
|
name: String!
|
||||||
@@ -572,20 +571,18 @@ type AcceptNonDisclosureAgreementPayload {
|
|||||||
type Query {
|
type Query {
|
||||||
node(id: ID!): Node!
|
node(id: ID!): Node!
|
||||||
trustCenterBySlug(slug: String!): TrustCenter @mustBeAuthenticated(role: NONE)
|
trustCenterBySlug(slug: String!): TrustCenter @mustBeAuthenticated(role: NONE)
|
||||||
|
currentTrustCenter: TrustCenter @mustBeAuthenticated(role: NONE)
|
||||||
}
|
}
|
||||||
|
|
||||||
type Mutation {
|
type Mutation {
|
||||||
requestAllAccesses(
|
requestAllAccesses(input: RequestAllAccessesInput!): RequestAccessesPayload!
|
||||||
input: RequestAllAccessesInput!
|
@mustBeAuthenticated(role: NONE)
|
||||||
): RequestAccessesPayload! @mustBeAuthenticated(role: NONE)
|
|
||||||
|
|
||||||
exportDocumentPDF(
|
exportDocumentPDF(input: ExportDocumentPDFInput!): ExportDocumentPDFPayload!
|
||||||
input: ExportDocumentPDFInput!
|
@mustBeAuthenticated(role: NONE)
|
||||||
): ExportDocumentPDFPayload! @mustBeAuthenticated(role: NONE)
|
|
||||||
|
|
||||||
exportReportPDF(
|
exportReportPDF(input: ExportReportPDFInput!): ExportReportPDFPayload!
|
||||||
input: ExportReportPDFInput!
|
@mustBeAuthenticated(role: NONE)
|
||||||
): ExportReportPDFPayload! @mustBeAuthenticated(role: NONE)
|
|
||||||
|
|
||||||
acceptNonDisclosureAgreement(
|
acceptNonDisclosureAgreement(
|
||||||
input: AcceptNonDisclosureAgreementInput!
|
input: AcceptNonDisclosureAgreementInput!
|
||||||
|
|||||||
@@ -137,8 +137,9 @@ type ComplexityRoot struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Query struct {
|
Query struct {
|
||||||
Node func(childComplexity int, id gid.GID) int
|
CurrentTrustCenter func(childComplexity int) int
|
||||||
TrustCenterBySlug func(childComplexity int, slug string) int
|
Node func(childComplexity int, id gid.GID) int
|
||||||
|
TrustCenterBySlug func(childComplexity int, slug string) int
|
||||||
}
|
}
|
||||||
|
|
||||||
Report struct {
|
Report struct {
|
||||||
@@ -235,6 +236,7 @@ type OrganizationResolver interface {
|
|||||||
type QueryResolver interface {
|
type QueryResolver interface {
|
||||||
Node(ctx context.Context, id gid.GID) (types.Node, error)
|
Node(ctx context.Context, id gid.GID) (types.Node, error)
|
||||||
TrustCenterBySlug(ctx context.Context, slug string) (*types.TrustCenter, error)
|
TrustCenterBySlug(ctx context.Context, slug string) (*types.TrustCenter, error)
|
||||||
|
CurrentTrustCenter(ctx context.Context) (*types.TrustCenter, error)
|
||||||
}
|
}
|
||||||
type ReportResolver interface {
|
type ReportResolver interface {
|
||||||
IsUserAuthorized(ctx context.Context, obj *types.Report) (bool, error)
|
IsUserAuthorized(ctx context.Context, obj *types.Report) (bool, error)
|
||||||
@@ -569,6 +571,13 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin
|
|||||||
|
|
||||||
return e.complexity.PageInfo.StartCursor(childComplexity), true
|
return e.complexity.PageInfo.StartCursor(childComplexity), true
|
||||||
|
|
||||||
|
case "Query.currentTrustCenter":
|
||||||
|
if e.complexity.Query.CurrentTrustCenter == nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
return e.complexity.Query.CurrentTrustCenter(childComplexity), true
|
||||||
|
|
||||||
case "Query.node":
|
case "Query.node":
|
||||||
if e.complexity.Query.Node == nil {
|
if e.complexity.Query.Node == nil {
|
||||||
break
|
break
|
||||||
@@ -1084,7 +1093,6 @@ type DocumentEdge {
|
|||||||
node: Document!
|
node: Document!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
type Framework implements Node {
|
type Framework implements Node {
|
||||||
id: ID!
|
id: ID!
|
||||||
name: String!
|
name: String!
|
||||||
@@ -1585,20 +1593,18 @@ type AcceptNonDisclosureAgreementPayload {
|
|||||||
type Query {
|
type Query {
|
||||||
node(id: ID!): Node!
|
node(id: ID!): Node!
|
||||||
trustCenterBySlug(slug: String!): TrustCenter @mustBeAuthenticated(role: NONE)
|
trustCenterBySlug(slug: String!): TrustCenter @mustBeAuthenticated(role: NONE)
|
||||||
|
currentTrustCenter: TrustCenter @mustBeAuthenticated(role: NONE)
|
||||||
}
|
}
|
||||||
|
|
||||||
type Mutation {
|
type Mutation {
|
||||||
requestAllAccesses(
|
requestAllAccesses(input: RequestAllAccessesInput!): RequestAccessesPayload!
|
||||||
input: RequestAllAccessesInput!
|
@mustBeAuthenticated(role: NONE)
|
||||||
): RequestAccessesPayload! @mustBeAuthenticated(role: NONE)
|
|
||||||
|
|
||||||
exportDocumentPDF(
|
exportDocumentPDF(input: ExportDocumentPDFInput!): ExportDocumentPDFPayload!
|
||||||
input: ExportDocumentPDFInput!
|
@mustBeAuthenticated(role: NONE)
|
||||||
): ExportDocumentPDFPayload! @mustBeAuthenticated(role: NONE)
|
|
||||||
|
|
||||||
exportReportPDF(
|
exportReportPDF(input: ExportReportPDFInput!): ExportReportPDFPayload!
|
||||||
input: ExportReportPDFInput!
|
@mustBeAuthenticated(role: NONE)
|
||||||
): ExportReportPDFPayload! @mustBeAuthenticated(role: NONE)
|
|
||||||
|
|
||||||
acceptNonDisclosureAgreement(
|
acceptNonDisclosureAgreement(
|
||||||
input: AcceptNonDisclosureAgreementInput!
|
input: AcceptNonDisclosureAgreementInput!
|
||||||
@@ -4391,6 +4397,100 @@ func (ec *executionContext) fieldContext_Query_trustCenterBySlug(ctx context.Con
|
|||||||
return fc, nil
|
return fc, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ec *executionContext) _Query_currentTrustCenter(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {
|
||||||
|
fc, err := ec.fieldContext_Query_currentTrustCenter(ctx, field)
|
||||||
|
if err != nil {
|
||||||
|
return graphql.Null
|
||||||
|
}
|
||||||
|
ctx = graphql.WithFieldContext(ctx, fc)
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
ec.Error(ctx, ec.Recover(ctx, r))
|
||||||
|
ret = graphql.Null
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) {
|
||||||
|
directive0 := func(rctx context.Context) (any, error) {
|
||||||
|
ctx = rctx // use context from middleware stack in children
|
||||||
|
return ec.resolvers.Query().CurrentTrustCenter(rctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
directive1 := func(ctx context.Context) (any, error) {
|
||||||
|
role, err := ec.unmarshalORole2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋserverᚋapiᚋtrustᚋv1ᚋtypesᚐRole(ctx, "NONE")
|
||||||
|
if err != nil {
|
||||||
|
var zeroVal *types.TrustCenter
|
||||||
|
return zeroVal, err
|
||||||
|
}
|
||||||
|
if ec.directives.MustBeAuthenticated == nil {
|
||||||
|
var zeroVal *types.TrustCenter
|
||||||
|
return zeroVal, errors.New("directive mustBeAuthenticated is not implemented")
|
||||||
|
}
|
||||||
|
return ec.directives.MustBeAuthenticated(ctx, nil, directive0, role)
|
||||||
|
}
|
||||||
|
|
||||||
|
tmp, err := directive1(rctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, graphql.ErrorOnPath(ctx, err)
|
||||||
|
}
|
||||||
|
if tmp == nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
if data, ok := tmp.(*types.TrustCenter); ok {
|
||||||
|
return data, nil
|
||||||
|
}
|
||||||
|
return nil, fmt.Errorf(`unexpected type %T from directive, should be *github.com/getprobo/probo/pkg/server/api/trust/v1/types.TrustCenter`, tmp)
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
ec.Error(ctx, err)
|
||||||
|
return graphql.Null
|
||||||
|
}
|
||||||
|
if resTmp == nil {
|
||||||
|
return graphql.Null
|
||||||
|
}
|
||||||
|
res := resTmp.(*types.TrustCenter)
|
||||||
|
fc.Result = res
|
||||||
|
return ec.marshalOTrustCenter2ᚖgithubᚗcomᚋgetproboᚋproboᚋpkgᚋserverᚋapiᚋtrustᚋv1ᚋtypesᚐTrustCenter(ctx, field.Selections, res)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ec *executionContext) fieldContext_Query_currentTrustCenter(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
|
||||||
|
fc = &graphql.FieldContext{
|
||||||
|
Object: "Query",
|
||||||
|
Field: field,
|
||||||
|
IsMethod: true,
|
||||||
|
IsResolver: true,
|
||||||
|
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
|
||||||
|
switch field.Name {
|
||||||
|
case "id":
|
||||||
|
return ec.fieldContext_TrustCenter_id(ctx, field)
|
||||||
|
case "active":
|
||||||
|
return ec.fieldContext_TrustCenter_active(ctx, field)
|
||||||
|
case "slug":
|
||||||
|
return ec.fieldContext_TrustCenter_slug(ctx, field)
|
||||||
|
case "ndaFileName":
|
||||||
|
return ec.fieldContext_TrustCenter_ndaFileName(ctx, field)
|
||||||
|
case "ndaFileUrl":
|
||||||
|
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 "hasAcceptedNonDisclosureAgreement":
|
||||||
|
return ec.fieldContext_TrustCenter_hasAcceptedNonDisclosureAgreement(ctx, field)
|
||||||
|
case "documents":
|
||||||
|
return ec.fieldContext_TrustCenter_documents(ctx, field)
|
||||||
|
case "audits":
|
||||||
|
return ec.fieldContext_TrustCenter_audits(ctx, field)
|
||||||
|
case "vendors":
|
||||||
|
return ec.fieldContext_TrustCenter_vendors(ctx, field)
|
||||||
|
case "references":
|
||||||
|
return ec.fieldContext_TrustCenter_references(ctx, field)
|
||||||
|
}
|
||||||
|
return nil, fmt.Errorf("no field named %q was found under type TrustCenter", field.Name)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
return fc, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (ec *executionContext) _Query___type(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {
|
func (ec *executionContext) _Query___type(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {
|
||||||
fc, err := ec.fieldContext_Query___type(ctx, field)
|
fc, err := ec.fieldContext_Query___type(ctx, field)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -9559,6 +9659,25 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr
|
|||||||
func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) })
|
func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) })
|
||||||
|
case "currentTrustCenter":
|
||||||
|
field := field
|
||||||
|
|
||||||
|
innerFunc := func(ctx context.Context, _ *graphql.FieldSet) (res graphql.Marshaler) {
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
ec.Error(ctx, ec.Recover(ctx, r))
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
res = ec._Query_currentTrustCenter(ctx, field)
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
rrm := func(ctx context.Context) graphql.Marshaler {
|
||||||
|
return ec.OperationContext.RootResolverMiddleware(ctx,
|
||||||
|
func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) })
|
||||||
|
}
|
||||||
|
|
||||||
out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) })
|
out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) })
|
||||||
case "__type":
|
case "__type":
|
||||||
out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) {
|
out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) {
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/getprobo/probo/pkg/gid"
|
||||||
"github.com/getprobo/probo/pkg/probo"
|
"github.com/getprobo/probo/pkg/probo"
|
||||||
console_v1 "github.com/getprobo/probo/pkg/server/api/console/v1"
|
console_v1 "github.com/getprobo/probo/pkg/server/api/console/v1"
|
||||||
"github.com/getprobo/probo/pkg/server/session"
|
"github.com/getprobo/probo/pkg/server/session"
|
||||||
@@ -29,6 +30,21 @@ import (
|
|||||||
"go.gearno.de/kit/httpserver"
|
"go.gearno.de/kit/httpserver"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
CustomDomainTenantIDKey = &ctxKey{name: "custom_domain_tenant_id"}
|
||||||
|
CustomDomainOrganizationIDKey = &ctxKey{name: "custom_domain_organization_id"}
|
||||||
|
)
|
||||||
|
|
||||||
|
func GetCustomDomainTenantID(ctx context.Context) (gid.TenantID, bool) {
|
||||||
|
tenantID, ok := ctx.Value(CustomDomainTenantIDKey).(gid.TenantID)
|
||||||
|
return tenantID, ok
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetCustomDomainOrganizationID(ctx context.Context) (gid.GID, bool) {
|
||||||
|
organizationID, ok := ctx.Value(CustomDomainOrganizationIDKey).(gid.GID)
|
||||||
|
return organizationID, ok
|
||||||
|
}
|
||||||
|
|
||||||
type (
|
type (
|
||||||
AuthTokenRequest struct {
|
AuthTokenRequest struct {
|
||||||
Token string `json:"token"`
|
Token string `json:"token"`
|
||||||
|
|||||||
@@ -547,6 +547,45 @@ func (r *queryResolver) TrustCenterBySlug(ctx context.Context, slug string) (*ty
|
|||||||
return response, nil
|
return response, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CurrentTrustCenter is the resolver for the currentTrustCenter field.
|
||||||
|
func (r *queryResolver) CurrentTrustCenter(ctx context.Context) (*types.TrustCenter, error) {
|
||||||
|
// Get organization and tenant from custom domain context
|
||||||
|
organizationID, ok := GetCustomDomainOrganizationID(ctx)
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("organization not found for custom domain")
|
||||||
|
}
|
||||||
|
|
||||||
|
tenantID, ok := GetCustomDomainTenantID(ctx)
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("tenant not found for custom domain")
|
||||||
|
}
|
||||||
|
|
||||||
|
publicTrustService := r.PublicTrustService(ctx, tenantID)
|
||||||
|
|
||||||
|
trustCenter, err := publicTrustService.TrustCenters.GetByOrganizationID(ctx, organizationID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("cannot load trust center: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !trustCenter.Active {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
trustCenter, file, err := publicTrustService.TrustCenters.Get(ctx, trustCenter.ID)
|
||||||
|
if err != nil {
|
||||||
|
panic(fmt.Errorf("cannot get trust center: %w", err))
|
||||||
|
}
|
||||||
|
|
||||||
|
org, err := publicTrustService.Organizations.Get(ctx, organizationID)
|
||||||
|
if err != nil {
|
||||||
|
panic(fmt.Errorf("cannot get organization: %w", err))
|
||||||
|
}
|
||||||
|
response := types.NewTrustCenter(trustCenter, file)
|
||||||
|
response.Organization = types.NewOrganization(org)
|
||||||
|
|
||||||
|
return response, nil
|
||||||
|
}
|
||||||
|
|
||||||
// IsUserAuthorized is the resolver for the isUserAuthorized field.
|
// IsUserAuthorized is the resolver for the isUserAuthorized field.
|
||||||
func (r *reportResolver) IsUserAuthorized(ctx context.Context, obj *types.Report) (bool, error) {
|
func (r *reportResolver) IsUserAuthorized(ctx context.Context, obj *types.Report) (bool, error) {
|
||||||
publicTrustService := r.PublicTrustService(ctx, obj.ID.TenantID())
|
publicTrustService := r.PublicTrustService(ctx, obj.ID.TenantID())
|
||||||
|
|||||||
@@ -16,14 +16,15 @@
|
|||||||
package server
|
package server
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/getprobo/probo/pkg/agents"
|
"github.com/getprobo/probo/pkg/agents"
|
||||||
"github.com/getprobo/probo/pkg/connector"
|
"github.com/getprobo/probo/pkg/connector"
|
||||||
"github.com/getprobo/probo/pkg/probo"
|
"github.com/getprobo/probo/pkg/probo"
|
||||||
"github.com/getprobo/probo/pkg/saferedirect"
|
"github.com/getprobo/probo/pkg/saferedirect"
|
||||||
"github.com/getprobo/probo/pkg/server/api"
|
"github.com/getprobo/probo/pkg/server/api"
|
||||||
|
trust_v1 "github.com/getprobo/probo/pkg/server/api/trust/v1"
|
||||||
"github.com/getprobo/probo/pkg/server/trust"
|
"github.com/getprobo/probo/pkg/server/trust"
|
||||||
"github.com/getprobo/probo/pkg/server/web"
|
"github.com/getprobo/probo/pkg/server/web"
|
||||||
trust_pkg "github.com/getprobo/probo/pkg/trust"
|
trust_pkg "github.com/getprobo/probo/pkg/trust"
|
||||||
@@ -55,6 +56,8 @@ type Server struct {
|
|||||||
trustServer *trust.Server
|
trustServer *trust.Server
|
||||||
router *chi.Mux
|
router *chi.Mux
|
||||||
extraHeaderFields map[string]string
|
extraHeaderFields map[string]string
|
||||||
|
proboService *probo.Service
|
||||||
|
logger *log.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewServer creates a new server instance
|
// NewServer creates a new server instance
|
||||||
@@ -98,6 +101,8 @@ func NewServer(cfg Config) (*Server, error) {
|
|||||||
trustServer: trustServer,
|
trustServer: trustServer,
|
||||||
router: router,
|
router: router,
|
||||||
extraHeaderFields: cfg.ExtraHeaderFields,
|
extraHeaderFields: cfg.ExtraHeaderFields,
|
||||||
|
proboService: cfg.Probo,
|
||||||
|
logger: cfg.Logger,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set up routes
|
// Set up routes
|
||||||
@@ -108,36 +113,139 @@ func NewServer(cfg Config) (*Server, error) {
|
|||||||
|
|
||||||
// setupRoutes configures the routing for the server
|
// setupRoutes configures the routing for the server
|
||||||
func (s *Server) setupRoutes() {
|
func (s *Server) setupRoutes() {
|
||||||
// API routes under /api
|
// API routes
|
||||||
s.router.Mount("/api", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
s.router.Mount("/api", s.apiServer)
|
||||||
// Strip the /api prefix from the path
|
|
||||||
r.URL.Path = strings.TrimPrefix(r.URL.Path, "/api")
|
|
||||||
if r.URL.Path == "" {
|
|
||||||
r.URL.Path = "/"
|
|
||||||
}
|
|
||||||
s.apiServer.ServeHTTP(w, r)
|
|
||||||
}))
|
|
||||||
|
|
||||||
// Trust routes go to the trust SPA
|
// Trust center routes by slug
|
||||||
s.router.Route("/trust", func(r chi.Router) {
|
s.router.Route("/trust/{slug}", func(r chi.Router) {
|
||||||
r.Mount("/", http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
r.Use(s.loadTrustCenterBySlug)
|
||||||
req.URL.Path = strings.TrimPrefix(req.URL.Path, "/trust")
|
r.Mount("/", s.trustCenterRouter())
|
||||||
if req.URL.Path == "" {
|
|
||||||
req.URL.Path = "/"
|
|
||||||
}
|
|
||||||
s.trustServer.ServeHTTP(w, req)
|
|
||||||
}))
|
|
||||||
})
|
})
|
||||||
|
|
||||||
// All other routes go to the console SPA frontend
|
// Console SPA (catch-all)
|
||||||
s.router.Mount("/", s.webServer)
|
s.router.Mount("/", s.webServer)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ServeHTTP implements the http.Handler interface
|
// ServeHTTP implements the http.Handler interface
|
||||||
func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
|
s.setExtraHeaders(w)
|
||||||
|
s.router.ServeHTTP(w, r)
|
||||||
|
}
|
||||||
|
|
||||||
|
// setExtraHeaders adds configured extra headers to the response
|
||||||
|
func (s *Server) setExtraHeaders(w http.ResponseWriter) {
|
||||||
for key, value := range s.extraHeaderFields {
|
for key, value := range s.extraHeaderFields {
|
||||||
w.Header().Set(key, value)
|
w.Header().Set(key, value)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
s.router.ServeHTTP(w, r)
|
|
||||||
|
// loadTrustCenterBySlug middleware loads trust center info from slug and adds to context
|
||||||
|
func (s *Server) loadTrustCenterBySlug(next http.Handler) http.Handler {
|
||||||
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
ctx := r.Context()
|
||||||
|
slug := chi.URLParam(r, "slug")
|
||||||
|
|
||||||
|
s.logger.InfoCtx(ctx, "loading trust center by slug",
|
||||||
|
log.String("slug", slug),
|
||||||
|
log.String("path", r.URL.Path),
|
||||||
|
)
|
||||||
|
|
||||||
|
trustCenter, err := s.proboService.LoadTrustCenterBySlug(ctx, slug)
|
||||||
|
if err != nil {
|
||||||
|
s.logger.WarnCtx(ctx, "trust center not found",
|
||||||
|
log.String("slug", slug),
|
||||||
|
log.Error(err),
|
||||||
|
)
|
||||||
|
http.Error(w, "Trust center not found", http.StatusNotFound)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
s.logger.InfoCtx(ctx, "trust center loaded",
|
||||||
|
log.String("slug", slug),
|
||||||
|
log.String("trust_center_id", trustCenter.ID.String()),
|
||||||
|
log.String("organization_id", trustCenter.OrganizationID.String()),
|
||||||
|
)
|
||||||
|
|
||||||
|
ctx = s.addTrustCenterToContext(ctx, trustCenter.ID.TenantID(), trustCenter.OrganizationID)
|
||||||
|
next.ServeHTTP(w, r.WithContext(ctx))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// loadTrustCenterByDomain middleware loads trust center info from custom domain and adds to context
|
||||||
|
func (s *Server) loadTrustCenterByDomain(next http.Handler) http.Handler {
|
||||||
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
ctx := r.Context()
|
||||||
|
|
||||||
|
if r.TLS == nil || r.TLS.ServerName == "" {
|
||||||
|
next.ServeHTTP(w, r)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
domain := r.TLS.ServerName
|
||||||
|
|
||||||
|
s.logger.InfoCtx(ctx, "loading organization by custom domain",
|
||||||
|
log.String("domain", domain),
|
||||||
|
log.String("path", r.URL.Path),
|
||||||
|
)
|
||||||
|
|
||||||
|
organizationID, err := s.proboService.LoadOrganizationByDomain(ctx, domain)
|
||||||
|
if err != nil {
|
||||||
|
s.logger.WarnCtx(ctx, "organization not found for domain",
|
||||||
|
log.String("domain", domain),
|
||||||
|
log.Error(err),
|
||||||
|
)
|
||||||
|
next.ServeHTTP(w, r)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
s.logger.InfoCtx(ctx, "organization loaded",
|
||||||
|
log.String("domain", domain),
|
||||||
|
log.String("organization_id", organizationID.String()),
|
||||||
|
)
|
||||||
|
|
||||||
|
ctx = s.addTrustCenterToContext(ctx, organizationID.TenantID(), organizationID)
|
||||||
|
next.ServeHTTP(w, r.WithContext(ctx))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// addTrustCenterToContext adds trust center identification to context
|
||||||
|
func (s *Server) addTrustCenterToContext(ctx context.Context, tenantID, organizationID interface{}) context.Context {
|
||||||
|
ctx = context.WithValue(ctx, trust_v1.CustomDomainTenantIDKey, tenantID)
|
||||||
|
ctx = context.WithValue(ctx, trust_v1.CustomDomainOrganizationIDKey, organizationID)
|
||||||
|
return ctx
|
||||||
|
}
|
||||||
|
|
||||||
|
// trustCenterRouter returns a router for trust center content (API + frontend)
|
||||||
|
func (s *Server) trustCenterRouter() chi.Router {
|
||||||
|
r := chi.NewRouter()
|
||||||
|
|
||||||
|
// Trust API routes
|
||||||
|
r.Mount("/api/trust/v1", s.apiServer.TrustAPIHandler())
|
||||||
|
|
||||||
|
// Trust center frontend (catch-all)
|
||||||
|
r.Handle("/*", s.trustServer)
|
||||||
|
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
// TrustCenterHandler returns an HTTP handler for serving trust centers on custom domains
|
||||||
|
func (s *Server) TrustCenterHandler() http.Handler {
|
||||||
|
r := chi.NewRouter()
|
||||||
|
|
||||||
|
// Set security headers
|
||||||
|
r.Use(func(next http.Handler) http.Handler {
|
||||||
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
w.Header().Set("Strict-Transport-Security", "max-age=31536000; preload")
|
||||||
|
s.setExtraHeaders(w)
|
||||||
|
next.ServeHTTP(w, r)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
// Load organization by custom domain
|
||||||
|
r.Use(s.loadTrustCenterByDomain)
|
||||||
|
|
||||||
|
// Mount trust center content
|
||||||
|
r.Mount("/", s.trustCenterRouter())
|
||||||
|
|
||||||
|
return r
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -89,6 +89,31 @@ func (s TrustCenterService) Get(
|
|||||||
return trustCenter, file, nil
|
return trustCenter, file, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s TrustCenterService) GetByOrganizationID(
|
||||||
|
ctx context.Context,
|
||||||
|
organizationID gid.GID,
|
||||||
|
) (*coredata.TrustCenter, error) {
|
||||||
|
trustCenter := &coredata.TrustCenter{}
|
||||||
|
|
||||||
|
err := s.svc.pg.WithConn(
|
||||||
|
ctx,
|
||||||
|
func(conn pg.Conn) error {
|
||||||
|
err := trustCenter.LoadByOrganizationID(ctx, conn, s.svc.scope, organizationID)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("cannot load trust center: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return trustCenter, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (s TrustCenterService) GenerateNDAFileURL(
|
func (s TrustCenterService) GenerateNDAFileURL(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
trustCenterID gid.GID,
|
trustCenterID gid.GID,
|
||||||
|
|||||||
Reference in New Issue
Block a user