Check tenant access
Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
This commit is contained in:
@@ -129,11 +129,14 @@ function PublicTrustCenterContent() {
|
|||||||
})
|
})
|
||||||
.then(response => response.json())
|
.then(response => response.json())
|
||||||
.then((result: GraphQLResponse<PublicTrustCenterData>) => {
|
.then((result: GraphQLResponse<PublicTrustCenterData>) => {
|
||||||
if (result.errors && result.errors.some((error: GraphQLError) =>
|
const nonAuthErrors = result.errors?.filter((error: GraphQLError) =>
|
||||||
!error.message.includes('access denied: authentication required')
|
!error.message.includes('access denied')
|
||||||
)) {
|
) || [];
|
||||||
throw new Error(result.errors[0].message);
|
|
||||||
|
if (nonAuthErrors.length > 0) {
|
||||||
|
throw new Error(nonAuthErrors[0].message);
|
||||||
}
|
}
|
||||||
|
|
||||||
setData(result.data || null);
|
setData(result.data || null);
|
||||||
})
|
})
|
||||||
.catch(setError)
|
.catch(setError)
|
||||||
|
|||||||
@@ -36,6 +36,33 @@ type ContextAccessor interface {
|
|||||||
TokenAccessFromContext(ctx context.Context) *TokenAccessData
|
TokenAccessFromContext(ctx context.Context) *TokenAccessData
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ValidateTenantAccess(ctx context.Context, accessor ContextAccessor, userTenantContextKey interface{}, resourceTenantID gid.TenantID) error {
|
||||||
|
tokenAccess := accessor.TokenAccessFromContext(ctx)
|
||||||
|
if tokenAccess != nil {
|
||||||
|
if tokenAccess.TenantID != resourceTenantID {
|
||||||
|
return fmt.Errorf("access denied: token not authorized for this organization")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
user := accessor.UserFromContext(ctx)
|
||||||
|
if user != nil {
|
||||||
|
userTenants, ok := ctx.Value(userTenantContextKey).(*[]gid.TenantID)
|
||||||
|
if !ok || userTenants == nil {
|
||||||
|
return fmt.Errorf("access denied: no tenant information available")
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tenantID := range *userTenants {
|
||||||
|
if tenantID == resourceTenantID {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return fmt.Errorf("access denied: not authorized for this organization")
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Errorf("access denied: authentication required")
|
||||||
|
}
|
||||||
|
|
||||||
func GetCurrentUserRole(ctx context.Context, accessor ContextAccessor) types.Role {
|
func GetCurrentUserRole(ctx context.Context, accessor ContextAccessor) types.Role {
|
||||||
user := accessor.UserFromContext(ctx)
|
user := accessor.UserFromContext(ctx)
|
||||||
tokenAccess := accessor.TokenAccessFromContext(ctx)
|
tokenAccess := accessor.TokenAccessFromContext(ctx)
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import (
|
|||||||
"github.com/getprobo/probo/pkg/coredata"
|
"github.com/getprobo/probo/pkg/coredata"
|
||||||
"github.com/getprobo/probo/pkg/gid"
|
"github.com/getprobo/probo/pkg/gid"
|
||||||
"github.com/getprobo/probo/pkg/page"
|
"github.com/getprobo/probo/pkg/page"
|
||||||
|
"github.com/getprobo/probo/pkg/server/api/trust/v1/auth"
|
||||||
"github.com/getprobo/probo/pkg/server/api/trust/v1/schema"
|
"github.com/getprobo/probo/pkg/server/api/trust/v1/schema"
|
||||||
"github.com/getprobo/probo/pkg/server/api/trust/v1/types"
|
"github.com/getprobo/probo/pkg/server/api/trust/v1/types"
|
||||||
)
|
)
|
||||||
@@ -57,6 +58,10 @@ func (r *auditResolver) Report(ctx context.Context, obj *types.Audit) (*types.Re
|
|||||||
|
|
||||||
// ReportURL is the resolver for the reportUrl field.
|
// ReportURL is the resolver for the reportUrl field.
|
||||||
func (r *auditResolver) ReportURL(ctx context.Context, obj *types.Audit) (*string, error) {
|
func (r *auditResolver) ReportURL(ctx context.Context, obj *types.Audit) (*string, error) {
|
||||||
|
if err := auth.ValidateTenantAccess(ctx, r, userTenantContextKey, obj.ID.TenantID()); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
trust := r.TrustService(ctx, obj.ID.TenantID())
|
trust := r.TrustService(ctx, obj.ID.TenantID())
|
||||||
|
|
||||||
audit, err := trust.Audits.Get(ctx, obj.ID)
|
audit, err := trust.Audits.Get(ctx, obj.ID)
|
||||||
@@ -78,6 +83,10 @@ func (r *auditResolver) ReportURL(ctx context.Context, obj *types.Audit) (*strin
|
|||||||
|
|
||||||
// ExportDocumentPDF is the resolver for the exportDocumentPDF field.
|
// ExportDocumentPDF is the resolver for the exportDocumentPDF field.
|
||||||
func (r *mutationResolver) ExportDocumentPDF(ctx context.Context, input types.ExportDocumentPDFInput) (*types.ExportDocumentPDFPayload, error) {
|
func (r *mutationResolver) ExportDocumentPDF(ctx context.Context, input types.ExportDocumentPDFInput) (*types.ExportDocumentPDFPayload, error) {
|
||||||
|
if err := auth.ValidateTenantAccess(ctx, r, userTenantContextKey, input.DocumentID.TenantID()); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
trust := r.trustCenterSvc.WithTenant(input.DocumentID.TenantID())
|
trust := r.trustCenterSvc.WithTenant(input.DocumentID.TenantID())
|
||||||
|
|
||||||
pdf, err := trust.Documents.ExportPDF(ctx, input.DocumentID)
|
pdf, err := trust.Documents.ExportPDF(ctx, input.DocumentID)
|
||||||
@@ -99,9 +108,9 @@ func (r *organizationResolver) LogoURL(ctx context.Context, obj *types.Organizat
|
|||||||
|
|
||||||
// TrustCenterBySlug is the resolver for the trustCenterBySlug field.
|
// TrustCenterBySlug is the resolver for the trustCenterBySlug field.
|
||||||
func (r *queryResolver) TrustCenterBySlug(ctx context.Context, slug string) (*types.TrustCenter, error) {
|
func (r *queryResolver) TrustCenterBySlug(ctx context.Context, slug string) (*types.TrustCenter, error) {
|
||||||
trust := r.trustCenterSvc.WithTenant(gid.NewTenantID())
|
publicTrust := r.trustCenterSvc.WithTenant(gid.NewTenantID())
|
||||||
|
|
||||||
trustCenter, err := trust.TrustCenters.GetBySlug(ctx, slug)
|
trustCenter, err := publicTrust.TrustCenters.GetBySlug(ctx, slug)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
@@ -125,6 +134,10 @@ func (r *queryResolver) TrustCenterBySlug(ctx context.Context, slug string) (*ty
|
|||||||
|
|
||||||
// DownloadURL is the resolver for the downloadUrl field.
|
// DownloadURL is the resolver for the downloadUrl field.
|
||||||
func (r *reportResolver) DownloadURL(ctx context.Context, obj *types.Report) (*string, error) {
|
func (r *reportResolver) DownloadURL(ctx context.Context, obj *types.Report) (*string, error) {
|
||||||
|
if err := auth.ValidateTenantAccess(ctx, r, userTenantContextKey, obj.ID.TenantID()); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
trust := r.TrustService(ctx, obj.ID.TenantID())
|
trust := r.TrustService(ctx, obj.ID.TenantID())
|
||||||
|
|
||||||
url, err := trust.Reports.GenerateDownloadURL(ctx, obj.ID, 5*time.Minute)
|
url, err := trust.Reports.GenerateDownloadURL(ctx, obj.ID, 5*time.Minute)
|
||||||
|
|||||||
Reference in New Issue
Block a user