@@ -39,7 +39,9 @@ type Referrer struct {
3939 Kind string
4040 // Wether the item is downloadable from CAS or not
4141 Downloadable bool
42- References []* Referrer
42+ // If this referrer is part of a public workflow
43+ InPublicWorkflow bool
44+ References []* Referrer
4345}
4446
4547// Actual referrer stored in the DB which includes a nested list of storedReferences
@@ -48,53 +50,75 @@ type StoredReferrer struct {
4850 ID uuid.UUID
4951 CreatedAt * time.Time
5052 // Fully expanded list of 1-level off references
51- References []* StoredReferrer
52- OrgIDs []uuid.UUID
53+ References []* StoredReferrer
54+ OrgIDs , WorkflowIDs []uuid.UUID
5355}
5456
5557type ReferrerRepo interface {
56- Save (ctx context.Context , input []* Referrer , orgID uuid.UUID ) error
58+ Save (ctx context.Context , input []* Referrer , workflowID uuid.UUID ) error
5759 // GetFromRoot returns the referrer identified by the provided content digest, including its first-level references
5860 // For example if sha:deadbeef represents an attestation, the result will contain the attestation + materials associated to it
5961 // OrgIDs represent an allowList of organizations where the referrers should be looked for
60- GetFromRoot (ctx context.Context , digest , kind string , orgIDS []uuid.UUID ) (* StoredReferrer , error )
62+ GetFromRoot (ctx context.Context , digest string , orgIDS []uuid.UUID , filters ... GetFromRootFilter ) (* StoredReferrer , error )
63+ }
64+
65+ type GetFromRootFilters struct {
66+ // RootKind is the kind of the root referrer, i.e ATTESTATION
67+ RootKind * string
68+ // Wether to filter by visibility or not
69+ Public * bool
70+ }
71+
72+ type GetFromRootFilter func (* GetFromRootFilters )
73+
74+ func WithKind (kind string ) func (* GetFromRootFilters ) {
75+ return func (o * GetFromRootFilters ) {
76+ o .RootKind = & kind
77+ }
78+ }
79+
80+ func WithPublicVisibility (public bool ) func (* GetFromRootFilters ) {
81+ return func (o * GetFromRootFilters ) {
82+ o .Public = & public
83+ }
6184}
6285
6386type ReferrerUseCase struct {
6487 repo ReferrerRepo
65- orgRepo OrganizationRepo
6688 membershipRepo MembershipRepo
89+ workflowRepo WorkflowRepo
6790 logger * log.Helper
6891}
6992
70- func NewReferrerUseCase (repo ReferrerRepo , orgRepo OrganizationRepo , mRepo MembershipRepo , l log.Logger ) * ReferrerUseCase {
93+ func NewReferrerUseCase (repo ReferrerRepo , wfRepo WorkflowRepo , mRepo MembershipRepo , l log.Logger ) * ReferrerUseCase {
7194 if l == nil {
7295 l = log .NewStdLogger (io .Discard )
7396 }
7497
75- return & ReferrerUseCase {repo , orgRepo , mRepo , servicelogger .ScopedHelper (l , "biz/Referrer" )}
98+ return & ReferrerUseCase {repo , mRepo , wfRepo , servicelogger .ScopedHelper (l , "biz/Referrer" )}
7699}
77100
78101// ExtractAndPersist extracts the referrers (subject + materials) from the given attestation
79102// and store it as part of the referrers index table
80- func (s * ReferrerUseCase ) ExtractAndPersist (ctx context.Context , att * dsse.Envelope , orgID string ) error {
81- orgUUID , err := uuid .Parse (orgID )
103+ func (s * ReferrerUseCase ) ExtractAndPersist (ctx context.Context , att * dsse.Envelope , workflowID string ) error {
104+ workflowUUID , err := uuid .Parse (workflowID )
82105 if err != nil {
83106 return NewErrInvalidUUID (err )
84107 }
85108
86- if org , err := s .orgRepo .FindByID (ctx , orgUUID ); err != nil {
87- return fmt .Errorf ("finding organization: %w" , err )
88- } else if org == nil {
89- return NewErrNotFound ("organization" )
109+ // Check that the workflow belongs to the organization
110+ if wf , err := s .workflowRepo .FindByID (ctx , workflowUUID ); err != nil {
111+ return fmt .Errorf ("finding workflow: %w" , err )
112+ } else if wf == nil {
113+ return NewErrNotFound ("workflow" )
90114 }
91115
92116 m , err := extractReferrers (att )
93117 if err != nil {
94118 return fmt .Errorf ("extracting referrers: %w" , err )
95119 }
96120
97- if err := s .repo .Save (ctx , m , orgUUID ); err != nil {
121+ if err := s .repo .Save (ctx , m , workflowUUID ); err != nil {
98122 return fmt .Errorf ("saving referrers: %w" , err )
99123 }
100124
@@ -110,6 +134,10 @@ func (s *ReferrerUseCase) GetFromRoot(ctx context.Context, digest string, rootKi
110134 return nil , NewErrInvalidUUID (err )
111135 }
112136
137+ if _ , err = cr_v1 .NewHash (digest ); err != nil {
138+ return nil , NewErrValidation (fmt .Errorf ("invalid digest format: %w" , err ))
139+ }
140+
113141 // We pass the list of organizationsIDs from where to look for the referrer
114142 // For now we just pass the list of organizations the user is member of
115143 // in the future we will expand this to publicly available orgs and so on.
@@ -123,7 +151,12 @@ func (s *ReferrerUseCase) GetFromRoot(ctx context.Context, digest string, rootKi
123151 orgIDs = append (orgIDs , m .OrganizationID )
124152 }
125153
126- ref , err := s .repo .GetFromRoot (ctx , digest , rootKind , orgIDs )
154+ filters := make ([]GetFromRootFilter , 0 )
155+ if rootKind != "" {
156+ filters = append (filters , WithKind (rootKind ))
157+ }
158+
159+ ref , err := s .repo .GetFromRoot (ctx , digest , orgIDs , filters ... )
127160 if err != nil {
128161 if errors .As (err , & ErrAmbiguousReferrer {}) {
129162 return nil , NewErrValidation (fmt .Errorf ("please provide the referrer kind: %w" , err ))
0 commit comments