Skip to content

Commit

Permalink
feat(permission): support permission setting, sharing public, sharing…
Browse files Browse the repository at this point in the history
… by code(link) (#256)

Because

- we need to support public sharing for pipeline and sharing by link

This commit

- support permission setting
- support sharing pipeline public
- support sharing pipeline by code(link)
  • Loading branch information
donch1989 authored Sep 25, 2023
1 parent e78b74b commit a9e42e2
Show file tree
Hide file tree
Showing 11 changed files with 250 additions and 52 deletions.
2 changes: 1 addition & 1 deletion config/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ database:
host: pg-sql
port: 5432
name: pipeline
version: 4
version: 5
timezone: Etc/UTC
pool:
idleconnections: 5
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ require (
github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0
github.com/iancoleman/strcase v0.2.0
github.com/influxdata/influxdb-client-go/v2 v2.12.3
github.com/instill-ai/protogen-go v0.3.3-alpha.0.20230914101327-aa4d53e6c5fc
github.com/instill-ai/protogen-go v0.3.3-alpha.0.20230925031115-0d2b2294c423
github.com/instill-ai/usage-client v0.2.4-alpha.0.20230814155646-874e57a1e4b0
github.com/instill-ai/x v0.3.0-alpha
github.com/knadh/koanf v1.5.0
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -1076,8 +1076,8 @@ github.com/influxdata/influxdb-client-go/v2 v2.12.3 h1:28nRlNMRIV4QbtIUvxhWqaxn0
github.com/influxdata/influxdb-client-go/v2 v2.12.3/go.mod h1:IrrLUbCjjfkmRuaCiGQg4m2GbkaeJDcuWoxiWdQEbA0=
github.com/influxdata/line-protocol v0.0.0-20200327222509-2487e7298839 h1:W9WBk7wlPfJLvMCdtV4zPulc4uCPrlywQOmbFOhgQNU=
github.com/influxdata/line-protocol v0.0.0-20200327222509-2487e7298839/go.mod h1:xaLFMmpvUxqXtVkUJfg9QmT88cDaCJ3ZKgdZ78oO8Qo=
github.com/instill-ai/protogen-go v0.3.3-alpha.0.20230914101327-aa4d53e6c5fc h1:RGrUkr9dnUxQs74/x1lWdLhIODnr6m6dZ/6UY+n08qw=
github.com/instill-ai/protogen-go v0.3.3-alpha.0.20230914101327-aa4d53e6c5fc/go.mod h1:z/L84htamlJ4QOR4jtJOaa+y3Hihu7WEqOipW0LEkmc=
github.com/instill-ai/protogen-go v0.3.3-alpha.0.20230925031115-0d2b2294c423 h1:xS/TVO8C4emley5/E6wkbzl69GlVTd2EBNbLIqIqSbI=
github.com/instill-ai/protogen-go v0.3.3-alpha.0.20230925031115-0d2b2294c423/go.mod h1:z/L84htamlJ4QOR4jtJOaa+y3Hihu7WEqOipW0LEkmc=
github.com/instill-ai/usage-client v0.2.4-alpha.0.20230814155646-874e57a1e4b0 h1:9QoCxaktvqGJYGjN8KhkWsv1DVfwbt5G1d/Ycx1kJxo=
github.com/instill-ai/usage-client v0.2.4-alpha.0.20230814155646-874e57a1e4b0/go.mod h1:SELFgirs+28Wfnh0kGw02zttit4pUeKLKp17zGsTu6g=
github.com/instill-ai/x v0.3.0-alpha h1:z9fedROOG2dVHhswBfVwU/hzHuq8/JKSUON7inF+FH8=
Expand Down
1 change: 1 addition & 0 deletions pkg/constant/constant.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ const MaxPayloadSize = 1024 * 1024 * 32
// Constants for resource owner
const DefaultUserID string = "admin"
const HeaderUserUIDKey = "jwt-sub"
const HeaderInstillCodeKey = "instill-code"
const StartConnectorId = "start-operator"
const EndConnectorId = "end-operator"
const ReturnTracesKey = "instill-return-traces"
96 changes: 87 additions & 9 deletions pkg/datamodel/datamodel.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ type Pipeline struct {
Description sql.NullString
Recipe *Recipe `gorm:"type:jsonb"`
DefaultReleaseUID uuid.UUID
Visibility PipelineVisibility `sql:"type:valid_visibility"`
Permission *Permission `gorm:"type:jsonb"`
ShareCode string
}

// PipelineRelease is the data model of the pipeline release table
Expand All @@ -50,8 +51,7 @@ type PipelineRelease struct {
ID string
PipelineUID uuid.UUID
Description sql.NullString
Recipe *Recipe `gorm:"type:jsonb"`
Visibility PipelineVisibility `sql:"type:valid_visibility"`
Recipe *Recipe `gorm:"type:jsonb"`
}

// Recipe is the data model of the pipeline recipe
Expand All @@ -67,8 +67,26 @@ type Component struct {
Configuration *structpb.Struct `json:"configuration"`
}

// PipelineVisibility is an alias type for Protobuf enum ConnectorType
type PipelineVisibility pipelinePB.Visibility
type Permission struct {
Users map[string]*PermissionUser `json:"users,omitempty"`
ShareCode *PermissionCode `json:"share_code,omitempty"`
}

// Permission
type PermissionUser struct {
Enabled bool `json:"enabled,omitempty"`
Role string `json:"role,omitempty"`
}

type PermissionCode struct {
User string `json:"user"`
Code string `json:"code"`
Enabled bool `json:"enabled,omitempty"`
Role string `json:"role,omitempty"`
}

// PipelineRole is an alias type for Protobuf enum
type PipelineRole pipelinePB.Role

// Scan function for custom GORM type Recipe
func (r *Recipe) Scan(value interface{}) error {
Expand All @@ -90,13 +108,73 @@ func (r *Recipe) Value() (driver.Value, error) {
return string(valueString), err
}

// Scan function for custom GORM type Recipe
func (p *Permission) Scan(value interface{}) error {
bytes, ok := value.([]byte)
if !ok {
return errors.New(fmt.Sprint("Failed to unmarshal value:", value))
}

if err := json.Unmarshal(bytes, &p); err != nil {
return err
}

return nil
}

// Value function for custom GORM type Recipe
func (p *Permission) Value() (driver.Value, error) {
valueString, err := json.Marshal(p)
return string(valueString), err
}

// Scan function for custom GORM type Recipe
func (p *PermissionUser) Scan(value interface{}) error {
bytes, ok := value.([]byte)
if !ok {
return errors.New(fmt.Sprint("Failed to unmarshal value:", value))
}

if err := json.Unmarshal(bytes, &p); err != nil {
return err
}

return nil
}

// Value function for custom GORM type Recipe
func (p *PermissionUser) Value() (driver.Value, error) {
valueString, err := json.Marshal(p)
return string(valueString), err
}

// Scan function for custom GORM type Recipe
func (p *PermissionCode) Scan(value interface{}) error {
bytes, ok := value.([]byte)
if !ok {
return errors.New(fmt.Sprint("Failed to unmarshal value:", value))
}

if err := json.Unmarshal(bytes, &p); err != nil {
return err
}

return nil
}

// Value function for custom GORM type Recipe
func (p *PermissionCode) Value() (driver.Value, error) {
valueString, err := json.Marshal(p)
return string(valueString), err
}

// Scan function for custom GORM type ReleaseStage
func (p *PipelineVisibility) Scan(value interface{}) error {
*p = PipelineVisibility(pipelinePB.Visibility_value[value.(string)])
func (p *PipelineRole) Scan(value interface{}) error {
*p = PipelineRole(pipelinePB.Role_value[value.(string)])
return nil
}

// Value function for custom GORM type ReleaseStage
func (p PipelineVisibility) Value() (driver.Value, error) {
return pipelinePB.Visibility(p).String(), nil
func (p PipelineRole) Value() (driver.Value, error) {
return pipelinePB.Role(p).String(), nil
}
Empty file.
6 changes: 6 additions & 0 deletions pkg/db/migration/000005_init.up.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
BEGIN;

ALTER TABLE public.pipeline ADD COLUMN "permission" JSONB DEFAULT NULL;
ALTER TABLE public.pipeline ADD COLUMN "share_code" VARCHAR(255) DEFAULT '' NOT NULL;

COMMIT;
2 changes: 1 addition & 1 deletion pkg/middleware/misc.go
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ func CustomMatcher(key string) (string, bool) {
switch key {
case "request-id":
return key, true
case "Instill-Return-Traces":
case "Instill-Return-Traces", "Instill-Code":
return key, true
case "X-B3-Traceid", "X-B3-Spanid", "X-B3-Sampled":
return key, true
Expand Down
28 changes: 12 additions & 16 deletions pkg/repository/repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,6 @@ import (
"github.com/instill-ai/pipeline-backend/pkg/logger"
"github.com/instill-ai/x/paginate"
"github.com/instill-ai/x/sterr"

pipelinePB "github.com/instill-ai/protogen-go/vdp/pipeline/v1alpha"
)

// TODO: in the repository, we'd better use uid as our function params
Expand All @@ -31,16 +29,14 @@ const DefaultPageSize = 10
// MaxPageSize is the maximum pagination page size if the assigned value is over this number
const MaxPageSize = 100

const VisibilityPublic = datamodel.PipelineVisibility(pipelinePB.Visibility_VISIBILITY_PUBLIC)

// Repository interface
type Repository interface {
ListPipelines(ctx context.Context, userPermalink string, pageSize int64, pageToken string, isBasicView bool, filter filtering.Filter, showDeleted bool) ([]*datamodel.Pipeline, int64, string, error)
GetPipelineByUID(ctx context.Context, userPermalink string, uid uuid.UUID, isBasicView bool) (*datamodel.Pipeline, error)
GetPipelineByUID(ctx context.Context, userPermalink string, uid uuid.UUID, isBasicView bool, code string) (*datamodel.Pipeline, error)

CreateUserPipeline(ctx context.Context, ownerPermalink string, userPermalink string, pipeline *datamodel.Pipeline) error
ListUserPipelines(ctx context.Context, ownerPermalink string, userPermalink string, pageSize int64, pageToken string, isBasicView bool, filter filtering.Filter, showDeleted bool) ([]*datamodel.Pipeline, int64, string, error)
GetUserPipelineByID(ctx context.Context, ownerPermalink string, userPermalink string, id string, isBasicView bool) (*datamodel.Pipeline, error)
GetUserPipelineByID(ctx context.Context, ownerPermalink string, userPermalink string, id string, isBasicView bool, code string) (*datamodel.Pipeline, error)

UpdateUserPipelineByID(ctx context.Context, ownerPermalink string, userPermalink string, id string, pipeline *datamodel.Pipeline) error
DeleteUserPipelineByID(ctx context.Context, ownerPermalink string, userPermalink string, id string) error
Expand Down Expand Up @@ -215,14 +211,14 @@ func (r *repository) listPipelines(ctx context.Context, where string, whereArgs

func (r *repository) ListPipelines(ctx context.Context, userPermalink string, pageSize int64, pageToken string, isBasicView bool, filter filtering.Filter, showDeleted bool) ([]*datamodel.Pipeline, int64, string, error) {
return r.listPipelines(ctx,
"(owner = ? OR visibility = ?)",
[]interface{}{userPermalink, VisibilityPublic},
"(owner = ? OR (permission @> '{\"users\":{\"users/*\":{\"role\": \"ROLE_VIEWER\", \"enabled\": true}}}'))",
[]interface{}{userPermalink},
pageSize, pageToken, isBasicView, filter, showDeleted)
}
func (r *repository) ListUserPipelines(ctx context.Context, ownerPermalink string, userPermalink string, pageSize int64, pageToken string, isBasicView bool, filter filtering.Filter, showDeleted bool) ([]*datamodel.Pipeline, int64, string, error) {
return r.listPipelines(ctx,
"(owner = ? AND (visibility = ? OR ? = ?))",
[]interface{}{ownerPermalink, VisibilityPublic, ownerPermalink, userPermalink},
"(owner = ? AND ((permission @> '{\"users\":{\"users/*\":{\"role\": \"ROLE_VIEWER\", \"enabled\": true}}}') OR ? = ?))",
[]interface{}{ownerPermalink, ownerPermalink, userPermalink},
pageSize, pageToken, isBasicView, filter, showDeleted)
}

Expand Down Expand Up @@ -258,18 +254,18 @@ func (r *repository) getUserPipeline(ctx context.Context, where string, whereArg
return &pipeline, nil
}

func (r *repository) GetUserPipelineByID(ctx context.Context, ownerPermalink string, userPermalink string, id string, isBasicView bool) (*datamodel.Pipeline, error) {
func (r *repository) GetUserPipelineByID(ctx context.Context, ownerPermalink string, userPermalink string, id string, isBasicView bool, code string) (*datamodel.Pipeline, error) {
return r.getUserPipeline(ctx,
"(id = ? AND (owner = ? AND (visibility = ? OR ? = ?)))",
[]interface{}{id, ownerPermalink, VisibilityPublic, ownerPermalink, userPermalink},
"(id = ? AND owner = ? AND ((permission @> '{\"users\":{\"users/*\":{\"role\": \"ROLE_VIEWER\", \"enabled\": true}}}') OR (permission @> '{\"share_code\":{\"user\":\"users/*\", \"role\": \"ROLE_VIEWER\", \"enabled\": true}}' AND share_code = ?) OR ? = ?))",
[]interface{}{id, ownerPermalink, code, ownerPermalink, userPermalink},
isBasicView)
}

func (r *repository) GetPipelineByUID(ctx context.Context, userPermalink string, uid uuid.UUID, isBasicView bool) (*datamodel.Pipeline, error) {
func (r *repository) GetPipelineByUID(ctx context.Context, userPermalink string, uid uuid.UUID, isBasicView bool, code string) (*datamodel.Pipeline, error) {
// TODO: ACL
return r.getUserPipeline(ctx,
"(uid = ? AND (visibility = ? OR owner = ?))",
[]interface{}{uid, VisibilityPublic, userPermalink},
"(uid = ? AND ((permission @> '{\"users\":{\"users/*\":{\"role\": \"ROLE_VIEWER\", \"enabled\": true}}}') OR (permission @> '{\"share_code\":{\"user\":\"users/*\", \"role\": \"ROLE_VIEWER\", \"enabled\": true}}' AND share_code = ?) OR owner = ?))",
[]interface{}{uid, code, userPermalink},
isBasicView)
}

Expand Down
38 changes: 34 additions & 4 deletions pkg/service/convert.go
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,23 @@ func (s *service) PBToDBPipeline(ctx context.Context, userUid uuid.UUID, pbPipel

}

dbPermission := &datamodel.Permission{}
if pbPipeline.GetPermission() != nil {

if err != nil {
return nil, err
}

b, err := protojson.MarshalOptions{UseProtoNames: true}.Marshal(pbPipeline.GetPermission())
if err != nil {
return nil, err
}
if err := json.Unmarshal(b, &dbPermission); err != nil {
return nil, err
}

}

return &datamodel.Pipeline{
Owner: owner,
ID: pbPipeline.GetId(),
Expand Down Expand Up @@ -407,7 +424,7 @@ func (s *service) PBToDBPipeline(ctx context.Context, userUid uuid.UUID, pbPipel
},

Recipe: recipe,
Visibility: datamodel.PipelineVisibility(pbPipeline.Visibility),
Permission: dbPermission,
}, nil
}

Expand Down Expand Up @@ -475,6 +492,21 @@ func (s *service) DBToPBPipeline(ctx context.Context, dbPipeline *datamodel.Pipe
}
}

pbPermission := &pipelinePB.Permission{}

b, err := json.Marshal(dbPipeline.Permission)
if err != nil {
return nil, err
}

err = protojson.Unmarshal(b, pbPermission)
if err != nil {
return nil, err
}
if pbPermission != nil && pbPermission.ShareCode != nil {
pbPermission.ShareCode.Code = dbPipeline.ShareCode
}

pbPipeline := pipelinePB.Pipeline{
Name: fmt.Sprintf("%s/pipelines/%s", owner, dbPipeline.ID),
Uid: dbPipeline.BaseDynamic.UID.String(),
Expand All @@ -489,8 +521,8 @@ func (s *service) DBToPBPipeline(ctx context.Context, dbPipeline *datamodel.Pipe
}
}(),
Description: &dbPipeline.Description.String,
Visibility: pipelinePB.Visibility(dbPipeline.Visibility),
Recipe: pbRecipe,
Permission: pbPermission,
}

if pbRecipe != nil && view == pipelinePB.View_VIEW_FULL && startComp != nil && endComp != nil {
Expand Down Expand Up @@ -584,7 +616,6 @@ func (s *service) PBToDBPipelineRelease(ctx context.Context, userUid uuid.UUID,

Recipe: recipe,
PipelineUID: pipelineUid,
Visibility: datamodel.PipelineVisibility(pbPipelineRelease.Visibility),
}, nil
}

Expand Down Expand Up @@ -656,7 +687,6 @@ func (s *service) DBToPBPipelineRelease(ctx context.Context, dbPipelineRelease *
}
}(),
Description: &dbPipelineRelease.Description.String,
Visibility: pipelinePB.Visibility(dbPipeline.Visibility),
Recipe: pbRecipe,
}

Expand Down
Loading

0 comments on commit a9e42e2

Please sign in to comment.