forked from storj/uplink
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.go
More file actions
164 lines (138 loc) · 4.82 KB
/
main.go
File metadata and controls
164 lines (138 loc) · 4.82 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
// Copyright (C) 2020 Storj Labs, Inc.
// See LICENSE for copying information.
package main
import (
"bytes"
"context"
"errors"
"flag"
"fmt"
"io"
"os"
"time"
"storj.io/uplink"
"storj.io/uplink/edge"
)
const defaultExpiration = 7 * 24 * time.Hour
// UploadAndDownloadData uploads the specified data to the specified key in the
// specified bucket, using the specified Satellite, API key, and passphrase.
func UploadAndDownloadData(ctx context.Context,
accessGrant, bucketName, uploadKey string, dataToUpload []byte) (err error) {
// Parse access grant, which contains necessary credentials and permissions.
access, err := uplink.ParseAccess(accessGrant)
if err != nil {
return fmt.Errorf("could not request access grant: %w", err)
}
// Open up the Project we will be working with.
project, err := uplink.OpenProject(ctx, access)
if err != nil {
return fmt.Errorf("could not open project: %w", err)
}
defer func() {
if closeErr := project.Close(); closeErr != nil {
err = errors.Join(err, closeErr)
}
}()
// Ensure the desired Bucket within the Project is created.
_, err = project.EnsureBucket(ctx, bucketName)
if err != nil {
return fmt.Errorf("could not ensure bucket: %w", err)
}
// Intitiate the upload of our Object to the specified bucket and key.
upload, err := project.UploadObject(ctx, bucketName, uploadKey, &uplink.UploadOptions{
// It's possible to set an expiration date for data.
Expires: time.Now().Add(defaultExpiration),
})
if err != nil {
return fmt.Errorf("could not initiate upload: %w", err)
}
// Copy the data to the upload.
buf := bytes.NewBuffer(dataToUpload)
_, err = io.Copy(upload, buf)
if err != nil {
_ = upload.Abort()
return fmt.Errorf("could not upload data: %w", err)
}
// Commit the uploaded object.
err = upload.Commit()
if err != nil {
return fmt.Errorf("could not commit uploaded object: %w", err)
}
// Initiate a download of the same object again
download, err := project.DownloadObject(ctx, bucketName, uploadKey, nil)
if err != nil {
return fmt.Errorf("could not open object: %w", err)
}
defer func() {
if closeErr := download.Close(); closeErr != nil {
err = errors.Join(err, closeErr)
}
}()
// Read everything from the download stream
receivedContents, err := io.ReadAll(download)
if err != nil {
return fmt.Errorf("could not read data: %w", err)
}
// Check that the downloaded data is the same as the uploaded data.
if !bytes.Equal(receivedContents, dataToUpload) {
return fmt.Errorf("got different object back: %q != %q", dataToUpload, receivedContents)
}
return nil
}
// CreatePublicSharedLink demonstrates how to create a public shareable link.
func CreatePublicSharedLink(ctx context.Context, accessGrant, bucketName, objectKey string) (string, error) {
// Define configuration for the storj sharing site.
config := edge.Config{
AuthServiceAddress: "auth.storjshare.io:7777",
}
// Parse access grant, which contains necessary credentials and permissions.
access, err := uplink.ParseAccess(accessGrant)
if err != nil {
return "", fmt.Errorf("could not parse access grant: %w", err)
}
// Restrict access to the specified paths.
restrictedAccess, err := access.Share(
uplink.Permission{
// only allow downloads
AllowDownload: true,
// this allows to automatically cleanup the access grants
NotAfter: time.Now().Add(defaultExpiration),
}, uplink.SharePrefix{
Bucket: bucketName,
Prefix: objectKey,
})
if err != nil {
return "", fmt.Errorf("could not restrict access grant: %w", err)
}
// RegisterAccess registers the credentials to the linksharing and s3 sites.
// This makes the data publicly accessible, see the security implications in https://docs.storj.io/dcs/concepts/access/access-management-at-the-edge.
credentials, err := config.RegisterAccess(ctx, restrictedAccess, &edge.RegisterAccessOptions{Public: true})
if err != nil {
return "", fmt.Errorf("could not register access: %w", err)
}
// Create a public link that is served by linksharing service.
url, err := edge.JoinShareURL("https://link.storjshare.io", credentials.AccessKeyID, bucketName, objectKey, nil)
if err != nil {
return "", fmt.Errorf("could not create a shared link: %w", err)
}
return url, nil
}
func main() {
ctx := context.Background()
accessGrant := flag.String("access", os.Getenv("ACCESS_GRANT"), "access grant from satellite")
flag.Parse()
bucketName := "my-first-bucket"
objectKey := "foo/bar/baz"
err := UploadAndDownloadData(ctx, *accessGrant, bucketName, objectKey, []byte("one fish two fish red fish blue fish"))
if err != nil {
fmt.Fprintln(os.Stderr, "upload failed:", err)
os.Exit(1)
}
url, err := CreatePublicSharedLink(ctx, *accessGrant, bucketName, objectKey)
if err != nil {
fmt.Fprintln(os.Stderr, "creating public link failed:", err)
os.Exit(1)
}
fmt.Println("success!")
fmt.Println("public link:", url)
}