Skip to content

Commit

Permalink
more
Browse files Browse the repository at this point in the history
Signed-off-by: Sarah Funkhouser <147884153+golanglemonade@users.noreply.github.com>
  • Loading branch information
golanglemonade committed Nov 19, 2024
1 parent d2deb85 commit 4d123a2
Show file tree
Hide file tree
Showing 17 changed files with 168 additions and 119 deletions.
10 changes: 7 additions & 3 deletions fga/model/model.fga
Original file line number Diff line number Diff line change
Expand Up @@ -133,12 +133,14 @@ type control_objective
# groups can be used to give edit (or delete) access to users
type internalpolicy
relations
define admin: [user]
define can_view: ([user] and member from parent) or admin or (can_view from parent but not blocked)
define can_create: can_edit from parent
define can_edit: ([user] and member from parent) or admin or (member from editor but not blocked)
define can_delete: ([user] and member from parent) or admin or can_delete from parent or (member from editor but not blocked)
define parent: [organization]
# the parent of the policy will be the organization, not all permissions will be inherited
define parent: [organization, user]
# allow a user or service to be assigned to add edit permissions
define admin: [user,service]
# allow a group to be assigned to add edit permissions for a set of users
define editor: [group]
# allow users or groups to be blocked from view + edit access
Expand All @@ -148,12 +150,14 @@ type internalpolicy
# groups can be used to give edit (or delete) access to users
type procedure
relations
define admin: [user]
define can_view: ([user] and member from parent) or admin or (can_view from parent but not blocked)
define can_create: can_edit from parent
define can_edit: ([user] and member from parent) or admin or (member from editor but not blocked)
define can_delete: ([user] and member from parent) or admin or can_delete from parent or (member from editor but not blocked)
# the parent of the procedure will be the organization, not all permissions will be inherited
define parent: [organization]
# allow a user or service to be assigned to add edit permissions
define admin: [user,service]
# allow a group to be assigned to add edit permissions for a set of users
define editor: [group]
# allow users or groups to be blocked from view + edit access
Expand Down
4 changes: 1 addition & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@ module github.com/theopenlane/core

go 1.23.3

replace gitub.com/theopenlane/utils => ../utils

require (
ariga.io/entcache v0.1.0
dario.cat/mergo v1.0.1
Expand Down Expand Up @@ -70,7 +68,7 @@ require (
github.com/theopenlane/iam v0.3.1
github.com/theopenlane/newman v0.1.1
github.com/theopenlane/riverboat v0.0.7
github.com/theopenlane/utils v0.3.1
github.com/theopenlane/utils v0.3.1-0.20241119175435-11d8950b990a
github.com/vektah/gqlparser/v2 v2.5.19
github.com/wk8/go-ordered-map/v2 v2.1.8
github.com/wundergraph/graphql-go-tools v1.67.4
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -632,8 +632,8 @@ github.com/theopenlane/newman v0.1.1 h1:pxGPRcy8kXQplfv4Sp1N3XUkWmx/scZvp7oj+y2l
github.com/theopenlane/newman v0.1.1/go.mod h1:A37pInKEYsdvUmjQzTDv7x5T4KhMxoFW105DA3XvH4Y=
github.com/theopenlane/riverboat v0.0.7 h1:zT/H6ipMRLVYQEGLGgwUI6B1wXEBS0ARhkfzv+Pekwg=
github.com/theopenlane/riverboat v0.0.7/go.mod h1:ke4bnkUNiqsQs7arZlIynAbDsy8uqY6yUSRUD1bmrBg=
github.com/theopenlane/utils v0.3.1 h1:CCRre2rpuj35Qij2hWgro0Urg94KJq6aAo2pdaWkziI=
github.com/theopenlane/utils v0.3.1/go.mod h1:sAvism3Vv8pb0kRj2lYQBYUaAKKRJSwULYoQzzLTTJw=
github.com/theopenlane/utils v0.3.1-0.20241119175435-11d8950b990a h1:D6Jq4JL/bxho7Zhg4HZMiQK6jOgRtzG4mIn+6J0VRMA=
github.com/theopenlane/utils v0.3.1-0.20241119175435-11d8950b990a/go.mod h1:8/Dv4B2VPZ1HnRaRS977XmJnvDjphXS/6adLpYKsyD4=
github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/gjson v1.18.0 h1:FIDeeyB800efLX89e5a8Y0BNH+LOngJyGrIWxG2FKQY=
github.com/tidwall/gjson v1.18.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
Expand Down
2 changes: 2 additions & 0 deletions internal/ent/generated/internalpolicy/internalpolicy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions internal/ent/generated/internalpolicy_create.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions internal/ent/generated/internalpolicy_update.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions internal/ent/generated/runtime/runtime.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

32 changes: 32 additions & 0 deletions internal/ent/hooks/mutationhelpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,38 @@ func getTuplesToAdd(ctx context.Context, m ent.Mutation, objectID string, parent
return addTuples, nil
}

// createOrgOwnerParentTuple creates the tuple for the parent org owner relationship
func createOrgOwnerParentTuple(ctx context.Context, m ent.Mutation, objectID string) ([]fgax.TupleKey, error) {
var addTuples []fgax.TupleKey

parentField := "owner_id"
subjectType := "organization"

subjectIDs, err := getAddedParentIDsFromEntMutation(ctx, m, parentField)
if err != nil {
return nil, err
}

// edge is not set, no need to add a tuple
if len(subjectIDs) == 0 {
return nil, nil
}

for _, subjectID := range subjectIDs {
parentTuple := fgax.GetTupleKey(fgax.TupleRequest{
SubjectID: subjectID,
SubjectType: subjectType,
ObjectID: objectID, // this is the object id being created
ObjectType: m.Type(), // this is the object type being created
Relation: fgax.ParentRelation,
})

addTuples = append(addTuples, parentTuple)
}

return addTuples, nil
}

// getTuplesToRemove gets the tuples that need to be removed from the authz service based on the edges that were removed
func getTuplesToRemove(ctx context.Context, m ent.Mutation, objectID string, parents []string) ([]fgax.TupleKey, error) {
var removeTuples []fgax.TupleKey
Expand Down
77 changes: 77 additions & 0 deletions internal/ent/hooks/orgownedtuples.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package hooks

import (
"context"

"entgo.io/ent"
"github.com/rs/zerolog/log"
"github.com/theopenlane/iam/auth"
"github.com/theopenlane/iam/fgax"

"github.com/theopenlane/core/internal/ent/generated"
)

// HookOrgOwnedTuples is a hook that adds organization owned tuples for the object being created
// it will add the user and parent (organization owner_id) permissions to the object
// on creation
// by default, it will always add an admin user permission to the object
func HookOrgOwnedTuples(skipUser bool) ent.Hook {
return func(next ent.Mutator) ent.Mutator {
return ent.MutateFunc(func(ctx context.Context, m ent.Mutation) (ent.Value, error) {
retVal, err := next.Mutate(ctx, m)
if err != nil {
return nil, err
}

objectID, err := getObjectIDFromEntValue(retVal)
if err != nil {
return nil, err
}

var addTuples []fgax.TupleKey

// add user permissions to the object on creation
if !skipUser && m.Op() == ent.OpCreate {
a, err := auth.GetAuthenticatedUserContext(ctx)
if err != nil {
return nil, err
}

subject := "user"
if a.AuthenticationType == auth.APITokenAuthentication {
subject = "service"
}

// add user permissions to the object as the parent on creation
userTuple := fgax.GetTupleKey(fgax.TupleRequest{
SubjectID: a.SubjectID,
SubjectType: subject,
ObjectID: objectID, // this is the object id being created
ObjectType: m.Type(), // this is the object type being created
Relation: fgax.AdminRelation,
})

addTuples = append(addTuples, userTuple)
}

additionalAddTuples, err := createOrgOwnerParentTuple(ctx, m, objectID)
if err != nil {
return nil, err
}

addTuples = append(addTuples, additionalAddTuples...)

// write the tuples to the authz service
if len(addTuples) != 0 {
if _, err := generated.FromContext(ctx).Authz.WriteTupleKeys(ctx, addTuples, nil); err != nil {
return nil, err
}
}

log.Debug().Interface("tuples", addTuples).Msg("added organization permissions")

return retVal, err
},
)
}
}
97 changes: 0 additions & 97 deletions internal/ent/hooks/procedure.go

This file was deleted.

5 changes: 3 additions & 2 deletions internal/ent/schema/internalpolicy.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ type InternalPolicy struct {
func (InternalPolicy) Fields() []ent.Field {
return []ent.Field{
field.String("name").
Comment("the name of the policy"),
Comment("the name of the policy").
NotEmpty(),
field.Text("description").
Optional().
Comment("description of the policy"),
Expand Down Expand Up @@ -96,7 +97,7 @@ func (InternalPolicy) Annotations() []schema.Annotation {
func (InternalPolicy) Hooks() []ent.Hook {
return []ent.Hook{
hook.On(
hooks.HookObjectOwnedTuples([]string{"owner_id"}, false),
hooks.HookOrgOwnedTuples(false),
ent.OpCreate|ent.OpUpdateOne|ent.OpUpdateOne,
)}
}
Expand Down
7 changes: 5 additions & 2 deletions internal/ent/schema/procedure.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"github.com/theopenlane/iam/entfga"

"github.com/theopenlane/core/internal/ent/generated"
"github.com/theopenlane/core/internal/ent/generated/hook"
"github.com/theopenlane/core/internal/ent/generated/privacy"
"github.com/theopenlane/core/internal/ent/hooks"
"github.com/theopenlane/core/internal/ent/interceptors"
Expand Down Expand Up @@ -99,8 +100,10 @@ func (Procedure) Annotations() []schema.Annotation {
// Hooks of the Procedure
func (Procedure) Hooks() []ent.Hook {
return []ent.Hook{
hooks.HookProcedureAuthz(),
}
hook.On(
hooks.HookOrgOwnedTuples(false),
ent.OpCreate|ent.OpUpdateOne|ent.OpUpdateOne,
)}
}

// Interceptors of the Procedure
Expand Down
4 changes: 3 additions & 1 deletion internal/entdb/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,9 @@ func NewTestFixture() *testutils.TestFixture {
panic(fmt.Sprintf("failed to convert TEST_DB_CONTAINER_EXPIRY to int: %v", err))
}

return testutils.GetTestURI(testDBURI, expiry)
return testutils.GetTestURI(testutils.WithImage(testDBURI),
testutils.WithExpiryMinutes(expiry),
testutils.WithMaxConn(200)) // nolint:mnd
}

// NewTestClient creates a entdb client that can be used for TEST purposes ONLY
Expand Down
Loading

0 comments on commit 4d123a2

Please sign in to comment.