diff --git a/context.go b/context.go index b51d62b..668315a 100644 --- a/context.go +++ b/context.go @@ -203,11 +203,15 @@ func NewContext(db * badger.DB, log Logger) * Context { if err != nil { panic(err) } - err = ctx.RegisterNodeType(NewNodeDef((*PerTagPolicy)(nil), LoadPerTagPolicy, GQLTypeSimpleNode.Type)) + err = ctx.RegisterNodeType(NewNodeDef((*DependencyPolicy)(nil), LoadSimplePolicy, GQLTypeSimpleNode.Type)) if err != nil { panic(err) } - err = ctx.RegisterNodeType(NewNodeDef((*DependencyPolicy)(nil), LoadSimplePolicy, GQLTypeSimpleNode.Type)) + err = ctx.RegisterNodeType(NewNodeDef((*ParentPolicy)(nil), LoadSimplePolicy, GQLTypeSimpleNode.Type)) + if err != nil { + panic(err) + } + err = ctx.RegisterNodeType(NewNodeDef((*ChildrenPolicy)(nil), LoadSimplePolicy, GQLTypeSimpleNode.Type)) if err != nil { panic(err) } diff --git a/gql.go b/gql.go index 8c29570..d047a1b 100644 --- a/gql.go +++ b/gql.go @@ -203,7 +203,7 @@ func AuthHandler(ctx *Context, server *GQLThread) func(http.ResponseWriter, *htt } else { ctx.Log.Logf("gql", "AUTHORIZING NEW USER %s - %s", key_id, shared) - new_user := NewUser(fmt.Sprintf("GQL_USER %s", key_id.String()), time.Now(), remote_id, shared, []string{"gql"}) + new_user := NewUser(fmt.Sprintf("GQL_USER %s", key_id.String()), time.Now(), remote_id, shared) context := NewWriteContext(ctx) err := UpdateStates(context, server, NewLockMap(LockMap{ server.ID(): LockInfo{ diff --git a/gql_test.go b/gql_test.go index f56a040..480333a 100644 --- a/gql_test.go +++ b/gql_test.go @@ -31,7 +31,7 @@ func TestGQLDBLoad(t * testing.T) { u1_key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) fatalErr(t, err) - u1 := NewUser("Test User", time.Now(), &u1_key.PublicKey, []byte{}, []string{"gql"}) + u1 := NewUser("Test User", time.Now(), &u1_key.PublicKey, []byte{}) ctx.Log.Logf("test", "U1_ID: %s", u1.ID().String()) key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) @@ -137,13 +137,12 @@ func TestGQLAuth(t * testing.T) { key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) fatalErr(t, err) - p1 := NewPerTagPolicy(RandID(), map[string]NodeActions{"gql": NewNodeActions(nil, []string{"read"})}) p2 := NewSimplePolicy(RandID(), NewNodeActions(NodeActions{ "signal": []string{"status"}, }, nil)) l1 := NewListener(RandID(), "GQL Thread") - err = AttachPolicies(ctx, &l1, &p1, &p2) + err = AttachPolicies(ctx, &l1, &p2) fatalErr(t, err) p3 := NewPerNodePolicy(RandID(), map[NodeID]NodeActions{ @@ -151,7 +150,7 @@ func TestGQLAuth(t * testing.T) { }) gql := NewGQLThread(RandID(), "GQL Thread", "init", ":0", ecdh.P256(), key, nil, nil) - err = AttachPolicies(ctx, &gql, &p1, &p2, &p3) + err = AttachPolicies(ctx, &gql, &p2, &p3) context := NewWriteContext(ctx) err = LinkLockables(context, &l1, &l1, []LockableNode{&gql}) diff --git a/policy.go b/policy.go index 904b91e..534767b 100644 --- a/policy.go +++ b/policy.go @@ -175,106 +175,123 @@ func (policy *SimplePolicy) Allows(node Node, resource string, action string, pr return policy.Actions.Allows(resource, action) } -type PerTagPolicy struct { - SimpleNode - Actions map[string]NodeActions + +type DependencyPolicy struct { + SimplePolicy } -type PerTagPolicyJSON struct { - SimpleNodeJSON - Actions map[string]map[string][]string `json:"json"` + +func (policy *DependencyPolicy) Type() NodeType { + return NodeType("dependency_policy") } -func (policy *PerTagPolicy) Type() NodeType { - return NodeType("per_tag_policy") +func NewDependencyPolicy(id NodeID, actions NodeActions) DependencyPolicy { + return DependencyPolicy{ + SimplePolicy: NewSimplePolicy(id, actions), + } } -func (policy *PerTagPolicy) Serialize() ([]byte, error) { - actions := map[string]map[string][]string{} - for tag, tag_actions := range(policy.Actions) { - actions[tag] = tag_actions +func (policy *DependencyPolicy) Allows(node Node, resource string, action string, principal Node) bool { + lockable, ok := node.(LockableNode) + if ok == false { + return false } - return json.MarshalIndent(&PerTagPolicyJSON{ - SimpleNodeJSON: NewSimpleNodeJSON(&policy.SimpleNode), - Actions: actions, - }, "", " ") + for _, dep := range(lockable.LockableHandle().Dependencies) { + if dep.ID() == principal.ID() { + return policy.Actions.Allows(resource, action) + } + } + + return false } -func NewPerTagPolicy(id NodeID, actions map[string]NodeActions) PerTagPolicy { - if actions == nil { - actions = map[string]NodeActions{} - } +type RequirementPolicy struct { + SimplePolicy +} - return PerTagPolicy{ - SimpleNode: NewSimpleNode(id), - Actions: actions, + +func (policy *RequirementPolicy) Type() NodeType { + return NodeType("dependency_policy") +} + +func NewRequirementPolicy(id NodeID, actions NodeActions) RequirementPolicy { + return RequirementPolicy{ + SimplePolicy: NewSimplePolicy(id, actions), } } -func LoadPerTagPolicy(ctx *Context, id NodeID, data []byte, nodes NodeMap) (Node, error) { - var j PerTagPolicyJSON - err := json.Unmarshal(data, &j) - if err != nil { - return nil, err +func (policy *RequirementPolicy) Allows(node Node, resource string, action string, principal Node) bool { + lockable_node, ok := node.(LockableNode) + if ok == false { + return false } + lockable := lockable_node.LockableHandle() - actions := map[string]NodeActions{} - for tag, tag_actions := range(j.Actions) { - actions[tag] = tag_actions + for _, req := range(lockable.Requirements) { + if req.ID() == principal.ID() { + return policy.Actions.Allows(resource, action) + } } - policy := NewPerTagPolicy(id, actions) - nodes[id] = &policy + return false +} - err = RestoreSimpleNode(ctx, &policy.SimpleNode, j.SimpleNodeJSON, nodes) - if err != nil { - return nil, err - } +type ParentPolicy struct { + SimplePolicy +} - return &policy, nil + +func (policy *ParentPolicy) Type() NodeType { + return NodeType("parent_policy") +} + +func NewParentPolicy(id NodeID, actions NodeActions) ParentPolicy { + return ParentPolicy{ + SimplePolicy: NewSimplePolicy(id, actions), + } } -func (policy *PerTagPolicy) Allows(node Node, resource string, action string, principal Node) bool { - user, ok := principal.(*User) +func (policy *ParentPolicy) Allows(node Node, resource string, action string, principal Node) bool { + thread_node, ok := node.(ThreadNode) if ok == false { return false } + thread := thread_node.ThreadHandle() - for _, tag := range(user.Tags) { - tag_actions, exists := policy.Actions[tag] - if exists == true { - if tag_actions.Allows(resource, action) == true { - return true - } + if thread.Owner != nil { + if thread.Owner.ID() == principal.ID() { + return policy.Actions.Allows(resource, action) } } + return false } -type DependencyPolicy struct { +type ChildrenPolicy struct { SimplePolicy } -func (policy *DependencyPolicy) Type() NodeType { - return NodeType("parent_policy") +func (policy *ChildrenPolicy) Type() NodeType { + return NodeType("children_policy") } -func NewDependencyPolicy(id NodeID, actions NodeActions) DependencyPolicy { - return DependencyPolicy{ +func NewChildrenPolicy(id NodeID, actions NodeActions) ChildrenPolicy { + return ChildrenPolicy{ SimplePolicy: NewSimplePolicy(id, actions), } } -func (policy *DependencyPolicy) Allows(node Node, resource string, action string, principal Node) bool { - lockable, ok := node.(LockableNode) +func (policy *ChildrenPolicy) Allows(node Node, resource string, action string, principal Node) bool { + thread_node, ok := node.(ThreadNode) if ok == false { return false } + thread := thread_node.ThreadHandle() - for _, dep := range(lockable.LockableHandle().Dependencies) { - if dep.ID() == principal.ID() { + for _, info := range(thread.Children) { + if info.Child.ID() == principal.ID() { return policy.Actions.Allows(resource, action) } } diff --git a/user.go b/user.go index aa322d0..02ac745 100644 --- a/user.go +++ b/user.go @@ -22,7 +22,6 @@ type UserJSON struct { Granted time.Time `json:"granted"` Pubkey []byte `json:"pubkey"` Shared []byte `json:"shared"` - Tags []string `json:"tags"` } func (user *User) Type() NodeType { @@ -41,7 +40,6 @@ func (user *User) Serialize() ([]byte, error) { Granted: user.Granted, Shared: user.Shared, Pubkey: pubkey, - Tags: user.Tags, }, "", " ") } @@ -66,7 +64,7 @@ func LoadUser(ctx *Context, id NodeID, data []byte, nodes NodeMap) (Node, error) return nil, fmt.Errorf("Invalid key type") } - user := NewUser(j.Name, j.Granted, pubkey, j.Shared, j.Tags) + user := NewUser(j.Name, j.Granted, pubkey, j.Shared) nodes[id] = &user err = RestoreLockable(ctx, &user.Lockable, j.LockableJSON, nodes) @@ -77,13 +75,12 @@ func LoadUser(ctx *Context, id NodeID, data []byte, nodes NodeMap) (Node, error) return &user, nil } -func NewUser(name string, granted time.Time, pubkey *ecdsa.PublicKey, shared []byte, tags []string) User { +func NewUser(name string, granted time.Time, pubkey *ecdsa.PublicKey, shared []byte) User { id := KeyID(pubkey) return User{ Lockable: NewLockable(id, name), Granted: granted, Pubkey: pubkey, Shared: shared, - Tags: tags, } }