17755: Merge branch 'main' into 17755-add-singularity-to-compute-image
[arvados.git] / lib / controller / localdb / collection.go
1 // Copyright (C) The Arvados Authors. All rights reserved.
2 //
3 // SPDX-License-Identifier: AGPL-3.0
4
5 package localdb
6
7 import (
8         "context"
9         "time"
10
11         "git.arvados.org/arvados.git/sdk/go/arvados"
12         "git.arvados.org/arvados.git/sdk/go/auth"
13 )
14
15 // CollectionGet defers to railsProxy for everything except blob
16 // signatures.
17 func (conn *Conn) CollectionGet(ctx context.Context, opts arvados.GetOptions) (arvados.Collection, error) {
18         if len(opts.Select) > 0 {
19                 // We need to know IsTrashed and TrashAt to implement
20                 // signing properly, even if the caller doesn't want
21                 // them.
22                 opts.Select = append([]string{"is_trashed", "trash_at"}, opts.Select...)
23         }
24         resp, err := conn.railsProxy.CollectionGet(ctx, opts)
25         if err != nil {
26                 return resp, err
27         }
28         conn.signCollection(ctx, &resp)
29         return resp, nil
30 }
31
32 // CollectionList defers to railsProxy for everything except blob
33 // signatures.
34 func (conn *Conn) CollectionList(ctx context.Context, opts arvados.ListOptions) (arvados.CollectionList, error) {
35         if len(opts.Select) > 0 {
36                 // We need to know IsTrashed and TrashAt to implement
37                 // signing properly, even if the caller doesn't want
38                 // them.
39                 opts.Select = append([]string{"is_trashed", "trash_at"}, opts.Select...)
40         }
41         resp, err := conn.railsProxy.CollectionList(ctx, opts)
42         if err != nil {
43                 return resp, err
44         }
45         for i := range resp.Items {
46                 conn.signCollection(ctx, &resp.Items[i])
47         }
48         return resp, nil
49 }
50
51 // CollectionCreate defers to railsProxy for everything except blob
52 // signatures.
53 func (conn *Conn) CollectionCreate(ctx context.Context, opts arvados.CreateOptions) (arvados.Collection, error) {
54         if len(opts.Select) > 0 {
55                 // We need to know IsTrashed and TrashAt to implement
56                 // signing properly, even if the caller doesn't want
57                 // them.
58                 opts.Select = append([]string{"is_trashed", "trash_at"}, opts.Select...)
59         }
60         resp, err := conn.railsProxy.CollectionCreate(ctx, opts)
61         if err != nil {
62                 return resp, err
63         }
64         conn.signCollection(ctx, &resp)
65         return resp, nil
66 }
67
68 // CollectionUpdate defers to railsProxy for everything except blob
69 // signatures.
70 func (conn *Conn) CollectionUpdate(ctx context.Context, opts arvados.UpdateOptions) (arvados.Collection, error) {
71         if len(opts.Select) > 0 {
72                 // We need to know IsTrashed and TrashAt to implement
73                 // signing properly, even if the caller doesn't want
74                 // them.
75                 opts.Select = append([]string{"is_trashed", "trash_at"}, opts.Select...)
76         }
77         resp, err := conn.railsProxy.CollectionUpdate(ctx, opts)
78         if err != nil {
79                 return resp, err
80         }
81         conn.signCollection(ctx, &resp)
82         return resp, nil
83 }
84
85 func (conn *Conn) signCollection(ctx context.Context, coll *arvados.Collection) {
86         if coll.IsTrashed || coll.ManifestText == "" || !conn.cluster.Collections.BlobSigning {
87                 return
88         }
89         var token string
90         if creds, ok := auth.FromContext(ctx); ok && len(creds.Tokens) > 0 {
91                 token = creds.Tokens[0]
92         }
93         if token == "" {
94                 return
95         }
96         ttl := conn.cluster.Collections.BlobSigningTTL.Duration()
97         exp := time.Now().Add(ttl)
98         if coll.TrashAt != nil && !coll.TrashAt.IsZero() && coll.TrashAt.Before(exp) {
99                 exp = *coll.TrashAt
100         }
101         coll.ManifestText = arvados.SignManifest(coll.ManifestText, token, exp, ttl, []byte(conn.cluster.Collections.BlobSigningKey))
102 }