cmd/uplinkng: fix linkshare bugs

Fix various bugs by remove superflous steps and letting libuplink
build the url.

$ uplinkng share --not-after +1h --url sj://mybucket/myprefix/

before: https://link.us1.storjshare.io/s/jxcvcme2xkb44xsec235xb2ccmbq//myprefix//
after: https://link.us1.storjshare.io/s/jxcvcme2xkb44xsec235xb2ccmbq/mybucket/myprefix/

$ uplinkng share --not-after +1h --url $(printf "sj://waterbear/aa\x03bb")

before: https://link.us1.storjshare.io/s/jwbcxjiv4ept7t2g3qmxfb73ljga//aabb
after: https://link.us1.storjshare.io/s/jvod7pixige62yrp5tubn4ct47yq/waterbear/aa%03bb

$ uplinkng share --not-after +1h --url

before: no url generated, no error
after: error "Need at least a bucket to create a working linkshare URL"
Change-Id: Ibca6847f8fc5d5fad9ee4642d11d3081d75d77ca
This commit is contained in:
Erik van Velzen 2022-01-27 20:50:12 +01:00 committed by Michał Niewrzał
parent 64176aaca4
commit b4e42ceb23
2 changed files with 58 additions and 24 deletions

View File

@ -18,7 +18,6 @@ import (
"github.com/zeebo/errs" "github.com/zeebo/errs"
"storj.io/storj/cmd/uplink/ulext" "storj.io/storj/cmd/uplink/ulext"
"storj.io/storj/cmd/uplink/ulloc"
"storj.io/uplink" "storj.io/uplink"
"storj.io/uplink/edge" "storj.io/uplink/edge"
) )
@ -79,9 +78,11 @@ func (c *cmdShare) Execute(ctx clingy.Context) error {
return err return err
} }
isPublic := c.public || c.url || c.dns != "" c.public = c.public || c.url || c.dns != ""
if c.public {
c.register = true
if isPublic {
if c.ap.notAfter.String() == "" { if c.ap.notAfter.String() == "" {
fmt.Fprintf(ctx, "It's not recommended to create a shared Access without an expiration date.") fmt.Fprintf(ctx, "It's not recommended to create a shared Access without an expiration date.")
fmt.Fprintf(ctx, "If you wish to do so anyway, please run this command with --not-after=none.") fmt.Fprintf(ctx, "If you wish to do so anyway, please run this command with --not-after=none.")
@ -110,8 +111,8 @@ func (c *cmdShare) Execute(ctx clingy.Context) error {
fmt.Fprintf(ctx, "=========== SERIALIZED ACCESS WITH THE ABOVE RESTRICTIONS TO SHARE WITH OTHERS ===========\n") fmt.Fprintf(ctx, "=========== SERIALIZED ACCESS WITH THE ABOVE RESTRICTIONS TO SHARE WITH OTHERS ===========\n")
fmt.Fprintf(ctx, "Access : %s\n", newAccessData) fmt.Fprintf(ctx, "Access : %s\n", newAccessData)
if c.register || c.url || c.dns != "" { if c.register {
credentials, err := RegisterAccess(ctx, access, c.authService, isPublic, c.caCert) credentials, err := RegisterAccess(ctx, access, c.authService, c.public, c.caCert)
if err != nil { if err != nil {
return err return err
} }
@ -119,21 +120,30 @@ func (c *cmdShare) Execute(ctx clingy.Context) error {
if err != nil { if err != nil {
return err return err
} }
_, err = fmt.Fprintln(ctx, "Public Access: ", isPublic) _, err = fmt.Fprintln(ctx, "Public Access: ", c.public)
if err != nil { if err != nil {
return err return err
} }
if len(c.ap.prefixes) == 1 && !c.ap.AllowUpload() && !c.ap.disallowDeletes { if c.url {
if c.url { if c.ap.AllowUpload() || c.ap.AllowDelete() {
if err = createURL(ctx, credentials.AccessKeyID, c.ap.prefixes[0], c.baseURL, c.ap.prefixes); err != nil { return errs.New("will only generate linksharing URL with readonly restrictions")
return err
}
} }
if c.dns != "" {
if err = createDNS(ctx, credentials.AccessKeyID, c.ap.prefixes[0], c.baseURL, c.dns); err != nil { err = createURL(ctx, credentials.AccessKeyID, c.ap.prefixes, c.baseURL)
return err if err != nil {
} return err
}
}
if c.dns != "" {
if c.ap.AllowUpload() || c.ap.AllowDelete() {
return errs.New("will only generate DNS entries with readonly restrictions")
}
err = createDNS(ctx, credentials.AccessKeyID, c.ap.prefixes, c.baseURL, c.dns)
if err != nil {
return err
} }
} }
} }
@ -216,26 +226,47 @@ func RegisterAccess(ctx context.Context, access *uplink.Access, authService stri
} }
// Creates linksharing url for allowed path prefixes. // Creates linksharing url for allowed path prefixes.
func createURL(ctx clingy.Context, newAccessData string, prefix uplink.SharePrefix, baseURL string, sharePrefixes []uplink.SharePrefix) (err error) { func createURL(ctx clingy.Context, accessKeyID string, prefixes []uplink.SharePrefix, baseURL string) (err error) {
loc := ulloc.NewRemote(prefix.Bucket, prefix.Prefix) if len(prefixes) == 0 {
bucket, key, _ := loc.RemoteParts() return errs.New("need at least a bucket to create a working linkshare URL")
}
bucket := prefixes[0].Bucket
key := prefixes[0].Prefix
url, err := edge.JoinShareURL(baseURL, accessKeyID, bucket, key, nil)
if err != nil {
return err
}
fmt.Fprintf(ctx, "=========== BROWSER URL ==================================================================\n") fmt.Fprintf(ctx, "=========== BROWSER URL ==================================================================\n")
fmt.Fprintf(ctx, "REMINDER : Object key must end in '/' when trying to share recursively\n") if key != "" && key[len(key)-1:] != "/" {
fmt.Fprintf(ctx, "URL : %s/s/%s/%s/%s\n", baseURL, url.PathEscape(newAccessData), bucket, key) fmt.Fprintf(ctx, "REMINDER : Object key must end in '/' when trying to share a prefix\n")
}
fmt.Fprintf(ctx, "URL : %s\n", url)
return nil return nil
} }
// Creates dns record info for allowed path prefixes. // Creates dns record info for allowed path prefixes.
func createDNS(ctx clingy.Context, accessKey string, prefix uplink.SharePrefix, baseURL, dns string) (err error) { func createDNS(ctx clingy.Context, accessKey string, prefixes []uplink.SharePrefix, baseURL, dns string) (err error) {
if len(prefixes) == 0 {
return errs.New("need at least a bucket to create DNS records")
}
bucket := prefixes[0].Bucket
key := prefixes[0].Prefix
CNAME, err := url.Parse(baseURL) CNAME, err := url.Parse(baseURL)
if err != nil { if err != nil {
return err return err
} }
rootString := ulloc.NewRemote(prefix.Bucket, prefix.Prefix).String()[5:] var printStorjRoot string
printStorjRoot := fmt.Sprintf("txt-%s\tIN\tTXT \tstorj-root:%s", dns, rootString) if key == "" {
printStorjRoot = fmt.Sprintf("txt-%s\tIN\tTXT \tstorj-root:%s", dns, bucket)
} else {
printStorjRoot = fmt.Sprintf("txt-%s\tIN\tTXT \tstorj-root:%s/%s", dns, bucket, key)
}
fmt.Fprintf(ctx, "=========== DNS INFO =====================================================================\n") fmt.Fprintf(ctx, "=========== DNS INFO =====================================================================\n")
fmt.Fprintf(ctx, "Remember to update the $ORIGIN with your domain name. You may also change the $TTL.\n") fmt.Fprintf(ctx, "Remember to update the $ORIGIN with your domain name. You may also change the $TTL.\n")

View File

@ -97,6 +97,9 @@ func TestShare(t *testing.T) {
}) })
t.Run("share access with --public", func(t *testing.T) { t.Run("share access with --public", func(t *testing.T) {
// Can't run this scenario because AuthService is not running in testplanet.
// If necessary we can mock AuthService like in https://github.com/storj/uplink/blob/main/testsuite/edge_test.go
t.Skip("No AuthService available in testplanet")
state := ultest.Setup(commands) state := ultest.Setup(commands)
state.Succeed(t, "share", "--public", "--not-after=none", "sj://some/prefix").RequireStdoutGlob(t, ` state.Succeed(t, "share", "--public", "--not-after=none", "sj://some/prefix").RequireStdoutGlob(t, `