Skip to content

Commit

Permalink
add authorisation to schema changes
Browse files Browse the repository at this point in the history
  • Loading branch information
Southclaws committed Feb 7, 2025
1 parent 0f227d7 commit 85f636c
Show file tree
Hide file tree
Showing 5 changed files with 139 additions and 43 deletions.
3 changes: 2 additions & 1 deletion app/services/library/library.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (

"github.com/Southclaws/storyden/app/services/library/node_fill"
"github.com/Southclaws/storyden/app/services/library/node_mutate"
"github.com/Southclaws/storyden/app/services/library/node_property_schema"
"github.com/Southclaws/storyden/app/services/library/node_read"
"github.com/Southclaws/storyden/app/services/library/node_semdex"
"github.com/Southclaws/storyden/app/services/library/node_visibility"
Expand All @@ -13,7 +14,7 @@ import (

func Build() fx.Option {
return fx.Options(
fx.Provide(node_read.New, node_mutate.New, nodetree.New, node_visibility.New, node_fill.New),
fx.Provide(node_read.New, node_mutate.New, nodetree.New, node_visibility.New, node_fill.New, node_property_schema.New),
node_semdex.Build(),
)
}
60 changes: 60 additions & 0 deletions app/services/library/node_property_schema/schema.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package node_property_schema

import (
"context"

"github.com/Southclaws/fault"
"github.com/Southclaws/fault/fctx"
"github.com/Southclaws/storyden/app/resources/account/account_querier"
"github.com/Southclaws/storyden/app/resources/library"
"github.com/Southclaws/storyden/app/resources/library/node_properties"
"github.com/Southclaws/storyden/app/resources/library/node_querier"
"github.com/Southclaws/storyden/app/services/authentication/session"
"github.com/Southclaws/storyden/app/services/library/node_auth"
)

type Updater struct {
accountQuery *account_querier.Querier
nodeQuerier *node_querier.Querier
nsr *node_properties.SchemaWriter
}

func New(
accountQuery *account_querier.Querier,
nodeQuerier *node_querier.Querier,
nsr *node_properties.SchemaWriter,
) *Updater {
return &Updater{
accountQuery: accountQuery,
nodeQuerier: nodeQuerier,
nsr: nsr,
}
}

func (u *Updater) UpdateChildren(ctx context.Context, qk library.QueryKey, schemas node_properties.FieldSchemaMutations) (*library.PropertySchema, error) {
accountID, err := session.GetAccountID(ctx)
if err != nil {
return nil, fault.Wrap(err, fctx.With(ctx))
}

acc, err := u.accountQuery.GetByID(ctx, accountID)
if err != nil {
return nil, fault.Wrap(err, fctx.With(ctx))
}

n, err := u.nodeQuerier.Get(ctx, qk)
if err != nil {
return nil, fault.Wrap(err, fctx.With(ctx))
}

if err := node_auth.AuthoriseNodeMutation(ctx, acc, n); err != nil {
return nil, fault.Wrap(err, fctx.With(ctx))
}

schema, err := u.nsr.UpdateChildren(ctx, qk, schemas)
if err != nil {
return nil, fault.Wrap(err, fctx.With(ctx))
}

return schema, nil
}
34 changes: 17 additions & 17 deletions app/transports/http/bindings/nodes.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (
"github.com/Southclaws/storyden/app/resources/visibility"
"github.com/Southclaws/storyden/app/services/authentication/session"
"github.com/Southclaws/storyden/app/services/library/node_mutate"
"github.com/Southclaws/storyden/app/services/library/node_property_schema"
"github.com/Southclaws/storyden/app/services/library/node_read"
"github.com/Southclaws/storyden/app/services/library/node_visibility"
"github.com/Southclaws/storyden/app/services/library/nodetree"
Expand All @@ -32,13 +33,13 @@ import (
)

type Nodes struct {
accountQuery *account_querier.Querier
nodeMutator *node_mutate.Manager
nodeReader *node_read.HydratedQuerier
nv *node_visibility.Controller
ntree nodetree.Graph
ntr node_traversal.Repository
nsr *node_properties.SchemaWriter
accountQuery *account_querier.Querier
nodeMutator *node_mutate.Manager
nodeReader *node_read.HydratedQuerier
nv *node_visibility.Controller
ntree nodetree.Graph
ntr node_traversal.Repository
schemaUpdater *node_property_schema.Updater
}

func NewNodes(
Expand All @@ -48,16 +49,16 @@ func NewNodes(
nv *node_visibility.Controller,
ntree nodetree.Graph,
ntr node_traversal.Repository,
nsr *node_properties.SchemaWriter,
schemaUpdater *node_property_schema.Updater,
) Nodes {
return Nodes{
accountQuery: accountQuery,
nodeMutator: nodeMutator,
nodeReader: nodeReader,
nv: nv,
ntree: ntree,
ntr: ntr,
nsr: nsr,
accountQuery: accountQuery,
nodeMutator: nodeMutator,
nodeReader: nodeReader,
nv: nv,
ntree: ntree,
ntr: ntr,
schemaUpdater: schemaUpdater,
}
}

Expand Down Expand Up @@ -330,8 +331,7 @@ func (c *Nodes) NodeUpdateChildrenPropertySchema(ctx context.Context, request op
}
})

// TODO: Authentication check for ownership/visibility/etc
updated, err := c.nsr.UpdateChildren(ctx, deserialiseNodeMark(request.NodeSlug), schemas)
updated, err := c.schemaUpdater.UpdateChildren(ctx, deserialiseNodeMark(request.NodeSlug), schemas)
if err != nil {
return nil, fault.Wrap(err, fctx.With(ctx))
}
Expand Down
6 changes: 3 additions & 3 deletions tests/library/properties/property_schema_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ func TestNodesPropertySchemas_Create(t *testing.T) {

res, err := cl.NodeUpdateChildrenPropertySchemaWithResponse(ctx, parent.JSON200.Slug, openapi.NodeUpdateChildrenPropertySchemaJSONRequestBody{
{Name: "weight", Type: "number", Sort: "1"},
})
}, session)
tests.Ok(t, err, res)

parent, err := cl.NodeGetWithResponse(ctx, parent.JSON200.Slug, session)
Expand All @@ -93,7 +93,7 @@ func TestNodesPropertySchemas_Create(t *testing.T) {
{Fid: &weightField.Fid, Name: "weight", Type: "number", Sort: "1"},
{Name: "kind", Type: "string", Sort: "2"},
{Name: "added", Type: "timestamp", Sort: "3"},
})
}, session)
tests.Ok(t, err, res)

parent, err = cl.NodeGetWithResponse(ctx, parent.JSON200.Slug, session)
Expand All @@ -107,7 +107,7 @@ func TestNodesPropertySchemas_Create(t *testing.T) {

// Delete the schema

res, err = cl.NodeUpdateChildrenPropertySchemaWithResponse(ctx, parent.JSON200.Slug, openapi.NodeUpdateChildrenPropertySchemaJSONRequestBody{})
res, err = cl.NodeUpdateChildrenPropertySchemaWithResponse(ctx, parent.JSON200.Slug, openapi.NodeUpdateChildrenPropertySchemaJSONRequestBody{}, session)
tests.Ok(t, err, res)

parent, err = cl.NodeGetWithResponse(ctx, parent.JSON200.Slug, session)
Expand Down
79 changes: 57 additions & 22 deletions tests/library/properties/property_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,18 +24,21 @@ func TestNodesProperty(t *testing.T) {

integration.Test(t, nil, e2e.Setup(), fx.Invoke(func(
lc fx.Lifecycle,
ctx context.Context,
root context.Context,
cl *openapi.ClientWithResponses,
cj *session_cookie.Jar,
aw *account_writer.Writer,
) {
lc.Append(fx.StartHook(func() {
ctx, _ := e2e.WithAccount(ctx, aw, seed.Account_001_Odin)
session := e2e.WithSession(ctx, cj)
ctx1, _ := e2e.WithAccount(root, aw, seed.Account_001_Odin)
session := e2e.WithSession(ctx1, cj)

ctx2, _ := e2e.WithAccount(root, aw, seed.Account_007_Freyr)
randomUser := e2e.WithSession(ctx2, cj)

parentname := "parent"
parentslug := parentname + uuid.NewString()
parent, err := cl.NodeCreateWithResponse(ctx, openapi.NodeInitialProps{
parent, err := cl.NodeCreateWithResponse(root, openapi.NodeInitialProps{
Name: parentname,
Slug: &parentslug,
}, session)
Expand All @@ -45,7 +48,7 @@ func TestNodesProperty(t *testing.T) {

name1 := "child-1"
slug1 := name1 + uuid.NewString()
node1, err := cl.NodeCreateWithResponse(ctx, openapi.NodeInitialProps{
node1, err := cl.NodeCreateWithResponse(root, openapi.NodeInitialProps{
Name: name1,
Slug: &slug1,
Parent: &parent.JSON200.Slug,
Expand All @@ -54,7 +57,7 @@ func TestNodesProperty(t *testing.T) {

name2 := "child-2"
slug2 := name2 + uuid.NewString()
node2, err := cl.NodeCreateWithResponse(ctx, openapi.NodeInitialProps{
node2, err := cl.NodeCreateWithResponse(root, openapi.NodeInitialProps{
Name: name2,
Slug: &slug2,
Parent: &parent.JSON200.Slug,
Expand All @@ -63,7 +66,7 @@ func TestNodesProperty(t *testing.T) {

name3 := "child-3"
slug3 := name3 + uuid.NewString()
node3, err := cl.NodeCreateWithResponse(ctx, openapi.NodeInitialProps{
node3, err := cl.NodeCreateWithResponse(root, openapi.NodeInitialProps{
Name: name3,
Slug: &slug3,
Parent: &parent.JSON200.Slug,
Expand All @@ -74,7 +77,7 @@ func TestNodesProperty(t *testing.T) {

name34 := "child-3-4"
slug34 := name34 + uuid.NewString()
node34, err := cl.NodeCreateWithResponse(ctx, openapi.NodeInitialProps{
node34, err := cl.NodeCreateWithResponse(root, openapi.NodeInitialProps{
Name: name34,
Slug: &slug34,
Parent: &node3.JSON200.Slug,
Expand All @@ -83,31 +86,63 @@ func TestNodesProperty(t *testing.T) {

name35 := "child-3-5"
slug35 := name35 + uuid.NewString()
node35, err := cl.NodeCreateWithResponse(ctx, openapi.NodeInitialProps{
node35, err := cl.NodeCreateWithResponse(root, openapi.NodeInitialProps{
Name: name35,
Slug: &slug35,
Parent: &node3.JSON200.Slug,
}, session)
tests.Ok(t, err, node35)

res, err := cl.NodeUpdateChildrenPropertySchemaWithResponse(ctx, parentslug, openapi.NodeUpdateChildrenPropertySchemaJSONRequestBody{
res, err := cl.NodeUpdateChildrenPropertySchemaWithResponse(root, parentslug, openapi.NodeUpdateChildrenPropertySchemaJSONRequestBody{
{Name: "weight", Type: "number", Sort: "1"},
{Name: "kind", Type: "string", Sort: "2"},
{Name: "added", Type: "timestamp", Sort: "3"},
})
}, session)
tests.Ok(t, err, res)

res, err = cl.NodeUpdateChildrenPropertySchemaWithResponse(ctx, slug3, openapi.NodeUpdateChildrenPropertySchemaJSONRequestBody{
res, err = cl.NodeUpdateChildrenPropertySchemaWithResponse(root, slug3, openapi.NodeUpdateChildrenPropertySchemaJSONRequestBody{
{Name: "size", Type: "number", Sort: "1"},
{Name: "brand", Type: "string", Sort: "2"},
})
}, session)
tests.Ok(t, err, res)

t.Run("fail_unauthenticated", func(t *testing.T) {
r := require.New(t)
a := assert.New(t)

update, err := cl.NodeUpdatePropertiesWithResponse(root, slug1, openapi.NodeUpdatePropertiesJSONRequestBody{
Properties: openapi.PropertyMutationList{
{Name: "weight", Value: "5"},
{Name: "kind", Value: "mythical"},
{Name: "added", Value: "2025-01-01T12:59:21Z"},
{Name: "new", Value: "prop"},
},
})
r.NoError(err)
a.Equal(403, update.StatusCode())
})

t.Run("fail_no_permission", func(t *testing.T) {
r := require.New(t)
a := assert.New(t)

update, err := cl.NodeUpdatePropertiesWithResponse(root, slug1, openapi.NodeUpdatePropertiesJSONRequestBody{
Properties: openapi.PropertyMutationList{
{Name: "weight", Value: "5"},
{Name: "kind", Value: "mythical"},
{Name: "added", Value: "2025-01-01T12:59:21Z"},
{Name: "new", Value: "prop"},
},
}, randomUser)
r.NoError(err)
a.Equal(401, update.StatusCode())
})

t.Run("fail_missing_new_property_type", func(t *testing.T) {
r := require.New(t)
a := assert.New(t)

update, err := cl.NodeUpdatePropertiesWithResponse(ctx, slug1, openapi.NodeUpdatePropertiesJSONRequestBody{
update, err := cl.NodeUpdatePropertiesWithResponse(root, slug1, openapi.NodeUpdatePropertiesJSONRequestBody{
Properties: openapi.PropertyMutationList{
{Name: "weight", Value: "5"},
{Name: "kind", Value: "mythical"},
Expand All @@ -123,7 +158,7 @@ func TestNodesProperty(t *testing.T) {
r := require.New(t)
a := assert.New(t)

update, err := cl.NodeUpdatePropertiesWithResponse(ctx, slug1, openapi.NodeUpdatePropertiesJSONRequestBody{
update, err := cl.NodeUpdatePropertiesWithResponse(root, slug1, openapi.NodeUpdatePropertiesJSONRequestBody{
Properties: openapi.PropertyMutationList{
{Name: "weight", Value: "4"},
{Name: "kind", Value: "legendary"},
Expand All @@ -140,7 +175,7 @@ func TestNodesProperty(t *testing.T) {

ptype := "string"

update, err := cl.NodeUpdatePropertiesWithResponse(ctx, slug1, openapi.NodeUpdatePropertiesJSONRequestBody{
update, err := cl.NodeUpdatePropertiesWithResponse(root, slug1, openapi.NodeUpdatePropertiesJSONRequestBody{
Properties: openapi.PropertyMutationList{
{Name: "weight", Value: "5"},
{Name: "kind", Value: "mythical"},
Expand Down Expand Up @@ -210,7 +245,7 @@ func TestNodesPropertyFieldOrdering(t *testing.T) {
{Name: "weight", Type: "number", Sort: "1"},
{Name: "kind", Type: "string", Sort: "2"},
{Name: "added", Type: "timestamp", Sort: "3"},
})
}, session)
tests.Ok(t, err, res)

t.Run("sort_fields", func(t *testing.T) {
Expand Down Expand Up @@ -248,7 +283,7 @@ func TestNodesPropertyFieldOrdering(t *testing.T) {
{Fid: field1ID, Name: "weight", Type: "number", Sort: "3"},
{Fid: field2ID, Name: "kind", Type: "string", Sort: "1"},
{Fid: field3ID, Name: "added", Type: "timestamp", Sort: "2"},
})
}, session)
tests.Ok(t, err, res)

updatedFields := dt.Map(schemaUpdate.JSON200.Properties, func(p openapi.PropertySchema) string {
Expand Down Expand Up @@ -339,13 +374,13 @@ func TestNodesPropertySchemaOnParentAndChildNodes(t *testing.T) {
{Name: "weight", Type: "number", Sort: "1"},
{Name: "kind", Type: "string", Sort: "2"},
{Name: "added", Type: "timestamp", Sort: "3"},
})
}, session)
tests.Ok(t, err, res)

res, err = cl.NodeUpdateChildrenPropertySchemaWithResponse(ctx, slug3, openapi.NodeUpdateChildrenPropertySchemaJSONRequestBody{
{Name: "size", Type: "number", Sort: "1"},
{Name: "brand", Type: "string", Sort: "2"},
})
}, session)
tests.Ok(t, err, res)

update, err := cl.NodeUpdatePropertiesWithResponse(ctx, slug1, openapi.NodeUpdatePropertiesJSONRequestBody{
Expand Down Expand Up @@ -382,7 +417,7 @@ func TestNodesPropertySchemaOnParentAndChildNodes(t *testing.T) {
}))
}

func matchSchemaToProperties(t *testing.T, schema openapi.PropertySchemaList, properties []openapi.Property) bool {
func matchSchemaToProperties(t *testing.T, schema openapi.PropertySchemaList, properties []openapi.Property) {
a := assert.New(t)

for i := range schema {
Expand All @@ -394,5 +429,5 @@ func matchSchemaToProperties(t *testing.T, schema openapi.PropertySchemaList, pr
a.Equal(schemaField.Type, propertyField.Type)
a.Equal(schemaField.Sort, propertyField.Sort)
}
return false
return
}

0 comments on commit 85f636c

Please sign in to comment.