diff --git a/context.go b/context.go index 5512e69..071b31f 100644 --- a/context.go +++ b/context.go @@ -195,6 +195,10 @@ func NewContext(db * badger.DB, log Logger) * Context { if err != nil { panic(err) } + err = ctx.RegisterNodeType(NewNodeDef((*Group)(nil), LoadGroup, GQLTypeSimpleLockable.Type)) + if err != nil { + panic(err) + } err = ctx.RegisterNodeType(NewNodeDef((*PerNodePolicy)(nil), LoadPerNodePolicy, GQLTypeSimpleNode.Type)) if err != nil { panic(err) diff --git a/gql_resolvers.go b/gql_resolvers.go index ea3fb8d..fb2200e 100644 --- a/gql_resolvers.go +++ b/gql_resolvers.go @@ -289,13 +289,13 @@ func GQLLockableOwner(p graphql.ResolveParams) (interface{}, error) { return owner, nil } -func GQLUserNodeUsers(p graphql.ResolveParams) (interface{}, error) { +func GQLGroupNodeUsers(p graphql.ResolveParams) (interface{}, error) { ctx, err := PrepResolve(p) if err != nil { return nil, err } - node, ok := p.Source.(NodeWithUsers) + node, ok := p.Source.(GroupNode) if ok == false || node == nil { return nil, fmt.Errorf("Failed to cast source to GQLThread") } diff --git a/gql_types.go b/gql_types.go index f921278..53fad30 100644 --- a/gql_types.go +++ b/gql_types.go @@ -92,7 +92,7 @@ var GQLTypeGQLThread = NewSingleton(func() *graphql.Object { gql_type_gql_thread.AddFieldConfig("Users", &graphql.Field{ Type: GQLTypeUser.List, - Resolve: GQLUserNodeUsers, + Resolve: GQLGroupNodeUsers, }) gql_type_gql_thread.AddFieldConfig("Listen", &graphql.Field{ diff --git a/policy.go b/policy.go index 54a794d..03f6be4 100644 --- a/policy.go +++ b/policy.go @@ -284,7 +284,7 @@ func (policy *ChildrenPolicy) Allows(context *StateContext, node Node, resource type UserOfPolicy struct { SimplePolicy - Target NodeWithUsers + Target GroupNode } type UserOfPolicyJSON struct { @@ -329,9 +329,9 @@ var LoadUserOfPolicy = LoadJSONNode(func(id NodeID, j UserOfPolicyJSON) (Node, e return err } - target, ok := target_node.(NodeWithUsers) + target, ok := target_node.(GroupNode) if ok == false { - return fmt.Errorf("%s is not a NodeWithUsers", target_node.ID()) + return fmt.Errorf("%s is not a GroupNode", target_node.ID()) } policy.Target = target return nil diff --git a/user.go b/user.go index 7839281..80b85d1 100644 --- a/user.go +++ b/user.go @@ -8,7 +8,7 @@ import ( "crypto/x509" ) -type NodeWithUsers interface { +type GroupNode interface { Node Users() map[NodeID]*User } @@ -48,14 +48,7 @@ func (user *User) Serialize() ([]byte, error) { }, "", " ") } -func LoadUser(ctx *Context, id NodeID, data []byte, nodes NodeMap) (Node, error) { - ctx.Log.Logf("test", "LOADING_USER: %s", id) - var j UserJSON - err := json.Unmarshal(data, &j) - if err != nil { - return nil, err - } - +var LoadUser = LoadJSONNode(func(id NodeID, j UserJSON) (Node, error) { pub, err := x509.ParsePKIXPublicKey(j.Pubkey) if err != nil { return nil, err @@ -70,15 +63,10 @@ func LoadUser(ctx *Context, id NodeID, data []byte, nodes NodeMap) (Node, error) } user := NewUser(j.Name, j.Granted, pubkey, j.Shared) - nodes[id] = &user - - err = RestoreLockable(ctx, &user.Lockable, j.LockableJSON, nodes) - if err != nil { - return nil, err - } - return &user, nil -} +}, func(ctx *Context, user *User, j UserJSON, nodes NodeMap) error { + return RestoreLockable(ctx, user, j.LockableJSON, nodes) +}) func NewUser(name string, granted time.Time, pubkey *ecdsa.PublicKey, shared []byte) User { id := KeyID(pubkey) @@ -89,3 +77,65 @@ func NewUser(name string, granted time.Time, pubkey *ecdsa.PublicKey, shared []b Shared: shared, } } + +type Group struct { + Lockable + + UserMap map[NodeID]*User +} + +func NewGroup(id NodeID, name string) Group { + return Group{ + Lockable: NewLockable(id, name), + UserMap: map[NodeID]*User{}, + } +} + +type GroupJSON struct { + LockableJSON + Users []string `json:"users"` +} + +func (group *Group) Type() NodeType { + return NodeType("group") +} + +func (group *Group) Serialize() ([]byte, error) { + users := make([]string, len(group.UserMap)) + i := 0 + for id, _ := range(group.UserMap) { + users[i] = id.String() + i += 1 + } + + return json.MarshalIndent(&GroupJSON{ + LockableJSON: NewLockableJSON(&group.Lockable), + Users: users, + }, "", " ") +} + +var LoadGroup = LoadJSONNode(func(id NodeID, j GroupJSON) (Node, error) { + group := NewGroup(id, j.Name) + return &group, nil +}, func(ctx *Context, group *Group, j GroupJSON, nodes NodeMap) error { + for _, id_str := range(j.Users) { + id, err := ParseID(id_str) + if err != nil { + return err + } + + user_node, err := LoadNodeRecurse(ctx, id, nodes) + if err != nil { + return err + } + + user, ok := user_node.(*User) + if ok == false { + return fmt.Errorf("%s is not a *User", id_str) + } + + group.UserMap[id] = user + } + + return RestoreLockable(ctx, group, j.LockableJSON, nodes) +})