Skip to content

[PLAT-54] filter open mode for reports #7683

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 14 additions & 3 deletions admin/server/reports.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ func (s *Server) GetReportMeta(ctx context.Context, req *adminv1.GetReportMetaRe
attribute.Bool("args.anon_recipients", req.AnonRecipients),
attribute.String("args.owner_id", req.OwnerId),
attribute.String("args.web_open_mode", req.WebOpenMode),
attribute.String("args.where_filter_json", req.WhereFilterJson),
attribute.StringSlice("args.accessible_fields", req.AccessibleFields),
)

proj, err := s.admin.DB.FindProject(ctx, req.ProjectId)
Expand Down Expand Up @@ -71,7 +73,14 @@ func (s *Server) GetReportMeta(ctx context.Context, req *adminv1.GetReportMetaRe
recipients = append(recipients, "")
}

tokens, ownerEmail, err := s.createMagicTokens(ctx, proj.OrganizationID, proj.ID, req.Report, req.OwnerId, recipients, req.Resources)
filterJSON := req.WhereFilterJson
accessibleFields := req.AccessibleFields
if webOpenMode != WebOpenModeFiltered {
// If web open mode is not filtered, we don't need to apply where filter or accessible fields
filterJSON = ""
accessibleFields = nil
}
tokens, ownerEmail, err := s.createMagicTokens(ctx, proj.OrganizationID, proj.ID, req.Report, req.OwnerId, filterJSON, accessibleFields, recipients, req.Resources)
if err != nil {
return nil, fmt.Errorf("failed to issue magic auth tokens: %w", err)
}
Expand Down Expand Up @@ -115,7 +124,7 @@ func (s *Server) GetReportMeta(ctx context.Context, req *adminv1.GetReportMetaRe
ExportUrl: s.admin.URLs.WithCustomDomain(org.CustomDomain).ReportExport(org.Name, proj.Name, req.Report, tokens[recipient]),
UnsubscribeUrl: s.admin.URLs.WithCustomDomain(org.CustomDomain).ReportUnsubscribe(org.Name, proj.Name, req.Report, tokens[recipient], recipient),
}
if webOpenMode == WebOpenModeCreator {
if webOpenMode == WebOpenModeCreator || webOpenMode == WebOpenModeFiltered {
urls[recipient].OpenUrl = s.admin.URLs.WithCustomDomain(org.CustomDomain).ReportOpen(org.Name, proj.Name, req.Report, tokens[recipient], req.ExecutionTime.AsTime())
} else if webOpenMode == WebOpenModeRecipient && canOpenReport[recipient] {
urls[recipient].OpenUrl = s.admin.URLs.WithCustomDomain(org.CustomDomain).ReportOpen(org.Name, proj.Name, req.Report, "", req.ExecutionTime.AsTime())
Expand Down Expand Up @@ -605,7 +614,7 @@ func (s *Server) generateReportName(ctx context.Context, depl *database.Deployme
return uuid.New().String(), nil
}

func (s *Server) createMagicTokens(ctx context.Context, orgID, projectID, reportName, ownerID string, emails []string, resources []*adminv1.ResourceName) (map[string]string, string, error) {
func (s *Server) createMagicTokens(ctx context.Context, orgID, projectID, reportName, ownerID, whereFilterJSON string, accessibleFields, emails []string, resources []*adminv1.ResourceName) (map[string]string, string, error) {
var createdByUserID *string
if ownerID != "" {
createdByUserID = &ownerID
Expand All @@ -614,6 +623,8 @@ func (s *Server) createMagicTokens(ctx context.Context, orgID, projectID, report
mgcOpts := &admin.IssueMagicAuthTokenOptions{
ProjectID: projectID,
CreatedByUserID: createdByUserID,
FilterJSON: whereFilterJSON,
Fields: accessibleFields,
Internal: true,
TTL: &ttl,
}
Expand Down
6 changes: 6 additions & 0 deletions proto/gen/rill/admin/v1/admin.swagger.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3608,6 +3608,12 @@ paths:
$ref: '#/definitions/v1ResourceName'
webOpenMode:
type: string
whereFilterJson:
type: string
accessibleFields:
type: array
items:
type: string
tags:
- AdminService
/v1/roles:
Expand Down
5,456 changes: 2,739 additions & 2,717 deletions proto/gen/rill/admin/v1/api.pb.go

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions proto/gen/rill/admin/v1/api.pb.validate.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions proto/rill/admin/v1/api.proto
Original file line number Diff line number Diff line change
Expand Up @@ -2374,6 +2374,8 @@ message GetReportMetaRequest {
bool anon_recipients = 8;
repeated ResourceName resources = 9;
string web_open_mode = 10;
string where_filter_json = 11;
repeated string accessible_fields = 12;
reserved 2, 4;
}

Expand Down
2 changes: 1 addition & 1 deletion runtime/drivers/admin.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import (
)

type AdminService interface {
GetReportMetadata(ctx context.Context, reportName, ownerID, explore, canvas, webOpenMode string, emailRecipients []string, anonRecipients bool, executionTime time.Time) (*ReportMetadata, error)
GetReportMetadata(ctx context.Context, reportName, ownerID, explore, canvas, webOpenMode, whereFilterJSON string, accessibleFields, emailRecipients []string, anonRecipients bool, executionTime time.Time) (*ReportMetadata, error)
GetAlertMetadata(ctx context.Context, alertName string, annotations map[string]string, queryForUserID, queryForUserEmail string) (*AlertMetadata, error)
ProvisionConnector(ctx context.Context, name, driver string, args map[string]any) (map[string]any, error)
}
Expand Down
20 changes: 11 additions & 9 deletions runtime/drivers/admin/admin_store.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import (
"google.golang.org/protobuf/types/known/timestamppb"
)

func (h *Handle) GetReportMetadata(ctx context.Context, reportName, ownerID, explore, canvas, webOpenMode string, emailRecipients []string, anonRecipients bool, executionTime time.Time) (*drivers.ReportMetadata, error) {
func (h *Handle) GetReportMetadata(ctx context.Context, reportName, ownerID, explore, canvas, webOpenMode, whereFilterJSON string, accessibleFields, emailRecipients []string, anonRecipients bool, executionTime time.Time) (*drivers.ReportMetadata, error) {
var resources []*adminv1.ResourceName
resources = append(resources, &adminv1.ResourceName{
Type: runtime.ResourceKindReport,
Expand All @@ -33,14 +33,16 @@ func (h *Handle) GetReportMetadata(ctx context.Context, reportName, ownerID, exp
}

res, err := h.admin.GetReportMeta(ctx, &adminv1.GetReportMetaRequest{
ProjectId: h.config.ProjectID,
Report: reportName,
OwnerId: ownerID,
EmailRecipients: emailRecipients,
AnonRecipients: anonRecipients,
ExecutionTime: timestamppb.New(executionTime),
Resources: resources,
WebOpenMode: webOpenMode,
ProjectId: h.config.ProjectID,
Report: reportName,
OwnerId: ownerID,
EmailRecipients: emailRecipients,
AnonRecipients: anonRecipients,
ExecutionTime: timestamppb.New(executionTime),
Resources: resources,
WebOpenMode: webOpenMode,
WhereFilterJson: whereFilterJSON,
AccessibleFields: accessibleFields,
})
if err != nil {
return nil, err
Expand Down
84 changes: 83 additions & 1 deletion runtime/metricsview/query_expression_pb.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package metricsview

import runtimev1 "github.com/rilldata/rill/proto/gen/rill/runtime/v1"
import (
runtimev1 "github.com/rilldata/rill/proto/gen/rill/runtime/v1"
"google.golang.org/protobuf/types/known/structpb"
)

func NewExpressionFromProto(expr *runtimev1.Expression) *Expression {
if expr == nil {
Expand Down Expand Up @@ -70,3 +73,82 @@ func NewExpressionFromProto(expr *runtimev1.Expression) *Expression {

return res
}

func ExpressionToProto(expr *Expression) *runtimev1.Expression {
if expr == nil {
return nil
}

res := &runtimev1.Expression{}
if expr.Name != "" {
res.Expression = &runtimev1.Expression_Ident{Ident: expr.Name}
} else if expr.Value != nil {
val, err := structpb.NewValue(expr.Value)
if err != nil {
// If we can't convert the value, return nil
return nil
}

res.Expression = &runtimev1.Expression_Val{Val: val}
} else if expr.Condition != nil {
var op runtimev1.Operation
switch expr.Condition.Operator {
case OperatorUnspecified:
op = runtimev1.Operation_OPERATION_UNSPECIFIED
case OperatorEq:
op = runtimev1.Operation_OPERATION_EQ
case OperatorNeq:
op = runtimev1.Operation_OPERATION_NEQ
case OperatorLt:
op = runtimev1.Operation_OPERATION_LT
case OperatorLte:
op = runtimev1.Operation_OPERATION_LTE
case OperatorGt:
op = runtimev1.Operation_OPERATION_GT
case OperatorGte:
op = runtimev1.Operation_OPERATION_GTE
case OperatorOr:
op = runtimev1.Operation_OPERATION_OR
case OperatorAnd:
op = runtimev1.Operation_OPERATION_AND
case OperatorIn:
op = runtimev1.Operation_OPERATION_IN
case OperatorNin:
op = runtimev1.Operation_OPERATION_NIN
case OperatorIlike:
op = runtimev1.Operation_OPERATION_LIKE
case OperatorNilike:
op = runtimev1.Operation_OPERATION_NLIKE
}
exprs := make([]*runtimev1.Expression, 0, len(expr.Condition.Expressions))
for _, e := range expr.Condition.Expressions {
protoExpr := ExpressionToProto(e)
if protoExpr != nil {
exprs = append(exprs, protoExpr)
}
}

res.Expression = &runtimev1.Expression_Cond{
Cond: &runtimev1.Condition{
Op: op,
Exprs: exprs,
},
}
} else if expr.Subquery != nil {
measures := make([]string, 0, len(expr.Subquery.Measures))
for _, m := range expr.Subquery.Measures {
measures = append(measures, m.Name)
}

res.Expression = &runtimev1.Expression_Subquery{
Subquery: &runtimev1.Subquery{
Dimension: expr.Subquery.Dimension.Name,
Measures: measures,
Where: ExpressionToProto(expr.Subquery.Where),
Having: ExpressionToProto(expr.Subquery.Having),
},
}
}

return res
}
Loading
Loading