-
Notifications
You must be signed in to change notification settings - Fork 18
/
Copy pathmain.go
154 lines (128 loc) · 4.56 KB
/
main.go
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
// Copyright (C) 2020 Storj Labs, Inc.
// See LICENSE for copying information.
package main
import (
"bytes"
"context"
"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) 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: %v", 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: %v", err)
}
defer project.Close()
// Ensure the desired Bucket within the Project is created.
_, err = project.EnsureBucket(ctx, bucketName)
if err != nil {
return fmt.Errorf("could not ensure bucket: %v", 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: %v", 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: %v", err)
}
// Commit the uploaded object.
err = upload.Commit()
if err != nil {
return fmt.Errorf("could not commit uploaded object: %v", 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: %v", err)
}
defer download.Close()
// Read everything from the download stream
receivedContents, err := io.ReadAll(download)
if err != nil {
return fmt.Errorf("could not read data: %v", 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
}
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)
}