Skip to content

Commit

Permalink
feat: Disallow construction of invalid FQMNs (#10)
Browse files Browse the repository at this point in the history
  • Loading branch information
ospencer authored Aug 18, 2022
1 parent 1b0fa92 commit 3dc432f
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 9 deletions.
7 changes: 6 additions & 1 deletion appsource/server/serversource.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,12 @@ func (a *AppSourceVKRouter) GetModuleHandler() vk.HandlerFunc {
namespace := ctx.Params.ByName("namespace")
mod := ctx.Params.ByName("mod")

fqmnString := fqmn.FromParts(ident, namespace, mod, ref)
fqmnString, err := fqmn.FromParts(ident, namespace, mod, ref)
if err != nil {
ctx.Log.Error(errors.Wrap(err, "failed fqmn FromParts"))

return nil, vk.E(http.StatusInternalServerError, "something went wrong")
}

runnable, err := a.appSource.GetModule(fqmnString)
if err != nil {
Expand Down
8 changes: 6 additions & 2 deletions fqmn/fqmn.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ type FQMN struct {
}

var ErrFQMNParseFailure = errors.New("FQMN failed to parse")
var ErrFQMNConstructionFailure = errors.New("All FQMN must be defined")

var errWrongPrefix = errors.Wrap(ErrFQMNParseFailure, "FQMN must begin with 'fqmn://', '/name', or '/ref'")
var errMustBeFullyQualified = errors.Wrap(ErrFQMNParseFailure, "FQMN text format must contain an tenant, ref, namespace, and module name")
Expand Down Expand Up @@ -200,6 +201,9 @@ func (f FQMN) URLPath() string {
}

// FromParts returns an FQMN from the provided parts
func FromParts(tenant, namespace, module, ref string) string {
return fmt.Sprintf("fqmn://%s/%s/%s@%s", tenant, namespace, module, ref)
func FromParts(tenant, namespace, module, ref string) (string, error) {
if tenant == "" || namespace == "" || module == "" || ref == "" {
return "", ErrFQMNConstructionFailure
}
return fmt.Sprintf("fqmn://%s/%s/%s@%s", tenant, namespace, module, ref), nil
}
39 changes: 38 additions & 1 deletion fqmn/fqmn_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -141,9 +141,46 @@ func (s *FQMNSuite) TestFromParts() {
"fqmn://com.suborbital.something/default/foobar@asdf",
nil,
},
{
"",
"default",
"asdf",
"com.suborbital.something",
"",
ErrFQMNConstructionFailure,
},
{
"foobar",
"",
"asdf",
"com.suborbital.something",
"",
ErrFQMNConstructionFailure,
},
{
"foobar",
"default",
"",
"com.suborbital.something",
"",
ErrFQMNConstructionFailure,
},
{
"foobar",
"default",
"asdf",
"",
"",
ErrFQMNConstructionFailure,
},
} {
s.Run(tt.fqmn, func() {
fqmn := FromParts(tt.tenant, tt.namespace, tt.name, tt.ref)
fqmn, err := FromParts(tt.tenant, tt.namespace, tt.name, tt.ref)

if err != nil {
s.Assertions.ErrorIs(err, tt.error)
return
}

s.Assertions.Equal(fqmn, tt.fqmn)
})
Expand Down
7 changes: 5 additions & 2 deletions tenant/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,11 +139,14 @@ func (c *Config) calculateFQMNs() {
mod.Namespace = fqmn.NamespaceDefault
}

c.Modules[i].FQMN = c.FQMNForFunc(mod.Namespace, mod.Name, mod.Ref)
// We deliberately ignore returned errors.
// The module will not be runnable, but it's not a problem for the
// system as a whole.
c.Modules[i].FQMN, _ = c.FQMNForFunc(mod.Namespace, mod.Name, mod.Ref)
}
}

func (c *Config) FQMNForFunc(namespace, fn, ref string) string {
func (c *Config) FQMNForFunc(namespace, fn, ref string) (string, error) {
return fqmn.FromParts(c.Identifier, namespace, fn, ref)
}

Expand Down
6 changes: 3 additions & 3 deletions tenant/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ func TestConfigFQMNs(t *testing.T) {
return
}

FQMN1 := conf.FQMNForFunc(mod1.Namespace, mod1.Name, "asdf")
FQMN1, _ := conf.FQMNForFunc(mod1.Namespace, mod1.Name, "asdf")

if FQMN1 != "fqmn://dev.suborbital.appname/default/getUser@asdf" {
t.Error("FQMN1 should be 'fqmn://dev.suborbital.appname/default/getUser@asdf', got", FQMN1)
Expand All @@ -242,7 +242,7 @@ func TestConfigFQMNs(t *testing.T) {
return
}

FQMN2 := conf.FQMNForFunc(mod2.Namespace, mod2.Name, "asdf")
FQMN2, _ := conf.FQMNForFunc(mod2.Namespace, mod2.Name, "asdf")

if FQMN2 != "fqmn://dev.suborbital.appname/db/getUserDetails@asdf" {
t.Error("FQMN2 should be 'fqmn://dev.suborbital.appname/db/getUserDetails@asdf', got", FQMN2)
Expand All @@ -258,7 +258,7 @@ func TestConfigFQMNs(t *testing.T) {
return
}

FQMN3 := conf.FQMNForFunc(mod3.Namespace, mod3.Name, "asdf")
FQMN3, _ := conf.FQMNForFunc(mod3.Namespace, mod3.Name, "asdf")

if FQMN3 != "fqmn://dev.suborbital.appname/api/returnUser@asdf" {
t.Error("FQMN3 should be 'fqmn://dev.suborbital.appname/api/returnUser@asdf', got", FQMN3)
Expand Down

0 comments on commit 3dc432f

Please sign in to comment.