graphvent/policy.go

153 lines
3.4 KiB
Go

package graphvent
import (
"encoding/json"
)
// A policy represents a set of rules attached to a Node that allow it to preform actions
type Policy interface {
Node
// Returns true if the policy allows the action on the given principal
Allows(action string, principal NodeID) bool
}
type PerNodePolicy struct {
GraphNode
AllowedActions map[NodeID][]string
}
type PerNodePolicyJSON struct {
GraphNodeJSON
AllowedActions map[string][]string `json:"allowed_actions"`
}
func (policy *PerNodePolicy) Type() NodeType {
return NodeType("per_node_policy")
}
func (policy *PerNodePolicy) Serialize() ([]byte, error) {
allowed_actions := map[string][]string{}
for principal, actions := range(policy.AllowedActions) {
allowed_actions[principal.String()] = actions
}
return json.MarshalIndent(&PerNodePolicyJSON{
GraphNodeJSON: NewGraphNodeJSON(&policy.GraphNode),
AllowedActions: allowed_actions,
}, "", " ")
}
func NewPerNodePolicy(id NodeID, allowed_actions map[NodeID][]string) PerNodePolicy {
if allowed_actions == nil {
allowed_actions = map[NodeID][]string{}
}
return PerNodePolicy{
GraphNode: NewGraphNode(id),
AllowedActions: allowed_actions,
}
}
func LoadPerNodePolicy(ctx *Context, id NodeID, data []byte, nodes NodeMap) (Node, error) {
var j PerNodePolicyJSON
err := json.Unmarshal(data, &j)
if err != nil {
return nil, err
}
allowed_actions := map[NodeID][]string{}
for principal_str, actions := range(j.AllowedActions) {
principal_id, err := ParseID(principal_str)
if err != nil {
return nil, err
}
allowed_actions[principal_id] = actions
}
policy := NewPerNodePolicy(id, allowed_actions)
nodes[id] = &policy
err = RestoreGraphNode(ctx, &policy.GraphNode, j.GraphNodeJSON, nodes)
if err != nil {
return nil, err
}
return &policy, nil
}
func (policy *PerNodePolicy) Allows(action string, principal NodeID) bool {
actions, exists := policy.AllowedActions[principal]
if exists == false {
return false
}
for _, a := range(actions) {
if a == action {
return true
}
}
return false
}
type AllNodePolicy struct {
GraphNode
AllowedActions []string
}
type AllNodePolicyJSON struct {
GraphNodeJSON
AllowedActions []string `json:"allowed_actions"`
}
func (policy *AllNodePolicy) Type() NodeType {
return NodeType("all_node_policy")
}
func (policy *AllNodePolicy) Serialize() ([]byte, error) {
return json.MarshalIndent(&AllNodePolicyJSON{
GraphNodeJSON: NewGraphNodeJSON(&policy.GraphNode),
AllowedActions: policy.AllowedActions,
}, "", " ")
}
func NewAllNodePolicy(id NodeID, allowed_actions []string) AllNodePolicy {
if allowed_actions == nil {
allowed_actions = []string{}
}
return AllNodePolicy{
GraphNode: NewGraphNode(id),
AllowedActions: allowed_actions,
}
}
func LoadAllNodePolicy(ctx *Context, id NodeID, data []byte, nodes NodeMap) (Node, error) {
var j AllNodePolicyJSON
err := json.Unmarshal(data, &j)
if err != nil {
return nil, err
}
policy := NewAllNodePolicy(id, j.AllowedActions)
nodes[id] = &policy
err = RestoreGraphNode(ctx, &policy.GraphNode, j.GraphNodeJSON, nodes)
if err != nil {
return nil, err
}
return &policy, nil
}
func (policy *AllNodePolicy) Allows(action string, principal NodeID) bool {
for _, a := range(policy.AllowedActions) {
if a == action {
return true
}
}
return false
}