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