Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BREAKING] ACL schema change #4725

Merged
merged 16 commits into from
Feb 7, 2020
4 changes: 3 additions & 1 deletion dgraph/cmd/bulk/systest/test-bulk-schema.sh
Original file line number Diff line number Diff line change
Expand Up @@ -191,9 +191,11 @@ EOF
dgraph debug -p out/0/p 2>|/dev/null | grep '{s}' | cut -d' ' -f4 > all_dbs.out
dgraph debug -p out/1/p 2>|/dev/null | grep '{s}' | cut -d' ' -f4 >> all_dbs.out
diff <(LC_ALL=C sort all_dbs.out | uniq -c) - <<EOF
1 dgraph.acl.rule
1 dgraph.graphql.schema
1 dgraph.group.acl
1 dgraph.password
1 dgraph.rule.permission
1 dgraph.rule.predicate
1 dgraph.type
1 dgraph.user.group
1 dgraph.xid
Expand Down
7 changes: 5 additions & 2 deletions edgraph/access_ee.go
Original file line number Diff line number Diff line change
Expand Up @@ -345,9 +345,12 @@ func RefreshAcls(closer *y.Closer) {

const queryAcls = `
{
allAcls(func: has(dgraph.group.acl)) {
allAcls(func: type(Group)) {
dgraph.xid
dgraph.group.acl
dgraph.acl.rule {
dgraph.rule.predicate
dgraph.rule.permission
}
}
}
`
Expand Down
9 changes: 1 addition & 8 deletions edgraph/acl_cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,10 @@
package edgraph

import (
"encoding/json"
"sync"

"github.com/dgraph-io/dgraph/ee/acl"
"github.com/dgraph-io/dgraph/x"
"github.com/golang/glog"
"github.com/pkg/errors"
)

Expand Down Expand Up @@ -51,12 +49,7 @@ func (cache *aclCache) update(groups []acl.Group) {
// predicate to a submap, and the submap maps a group to a permission
predPerms := make(map[string]map[string]int32)
for _, group := range groups {
aclBytes := []byte(group.Acls)
var acls []acl.Acl
if err := json.Unmarshal(aclBytes, &acls); err != nil {
glog.Errorf("Unable to unmarshal the aclBytes: %v", err)
continue
}
acls := group.Rules

for _, acl := range acls {
if len(acl.Predicate) > 0 {
Expand Down
4 changes: 1 addition & 3 deletions edgraph/acl_cache_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
package edgraph

import (
"encoding/json"
"testing"

"github.com/dgraph-io/dgraph/ee/acl"
Expand All @@ -37,11 +36,10 @@ func TestAclCache(t *testing.T) {
Perm: 4,
},
}
aclBytes, _ := json.Marshal(acls)
groups := []acl.Group{
{
GroupID: group,
Acls: string(aclBytes),
Rules: acls,
},
}
aclCachePtr.update(groups)
Expand Down
126 changes: 58 additions & 68 deletions ee/acl/acl.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ package acl

import (
"context"
"encoding/json"
"fmt"
"strings"
"time"
Expand Down Expand Up @@ -406,7 +405,7 @@ func chMod(conf *viper.Viper) error {
return errors.Errorf("the groupid must not be empty")
case len(predicate) == 0:
return errors.Errorf("no predicates specified")
case perm > 7:
case perm > 7: // TODO(Animesh): also check if perm < 0
return errors.Errorf("the perm value must be less than or equal to 7, "+
"the provided value is %d", perm)
}
Expand All @@ -426,59 +425,53 @@ func chMod(conf *viper.Viper) error {
}
}()

group, err := queryGroup(ctx, txn, groupId, "dgraph.group.acl")
if err != nil {
return errors.Wrapf(err, "while querying group")
}
if group == nil || len(group.Uid) == 0 {
return errors.Errorf("unable to change permission for group because it does not exist: %v",
groupId)
}

var currentAcls []Acl
if len(group.Acls) != 0 {
if err := json.Unmarshal([]byte(group.Acls), &currentAcls); err != nil {
return errors.Wrapf(err, "unable to unmarshal the acls associated with the group %v",
groupId)
}
}

var newAcl Acl
if len(predicate) > 0 {
newAcl = Acl{
Predicate: predicate,
Perm: int32(perm),
ruleQuery := fmt.Sprintf(`
{
var(func: eq(dgraph.xid, "%s")) @filter(type(Group)) {
gUID as uid
rUID as dgraph.acl.rule @filter(eq(dgraph.rule.predicate, "%s"))
}
}
newAcls, updated := updateAcl(currentAcls, newAcl)
if !updated {
fmt.Printf("Nothing needs to be changed for the permission of group: %v\n", groupId)
return nil
}

newAclBytes, err := json.Marshal(newAcls)
if err != nil {
return errors.Wrapf(err, "unable to marshal the updated acls")
}

chModNQuads := &api.NQuad{
Subject: group.Uid,
Predicate: "dgraph.group.acl",
ObjectValue: &api.Value{Val: &api.Value_BytesVal{BytesVal: newAclBytes}},
}
mu := &api.Mutation{
}`, groupId, predicate)

updateRule := &api.Mutation{
Set: []*api.NQuad{
{
Subject: "uid(rUID)",
Predicate: "dgraph.rule.permission",
ObjectValue: &api.Value{Val: &api.Value_IntVal{IntVal: int64(perm)}},
},
},
Cond: "@if(eq(len(rUID), 1) AND eq(len(gUID), 1))",
}

createRule := &api.Mutation{
Set: []*api.NQuad{
{
Subject: "_:newrule",
Predicate: "dgraph.rule.permission",
ObjectValue: &api.Value{Val: &api.Value_IntVal{IntVal: int64(perm)}},
},
{
Subject: "_:newrule",
Predicate: "dgraph.rule.predicate",
ObjectValue: &api.Value{Val: &api.Value_StrVal{StrVal: predicate}},
},
{
Subject: "uid(gUID)",
Predicate: "dgraph.acl.rule",
ObjectId: "_:newrule",
},
},
Cond: "@if(eq(len(rUID), 0) AND eq(len(gUID), 1))",
}

_, err = txn.Do(ctx, &api.Request{
Query: ruleQuery,
Mutations: []*api.Mutation{createRule, updateRule},
CommitNow: true,
Set: []*api.NQuad{chModNQuads},
}
})

if _, err = txn.Mutate(ctx, mu); err != nil {
return errors.Wrapf(err, "unable to change mutations for the group %v on predicate %v",
groupId, predicate)
}
fmt.Printf("Successfully changed permission for group %v on predicate %v to %v\n",
groupId, predicate, perm)
fmt.Println("The latest info is:")
return queryAndPrintGroup(ctx, dc.NewReadOnlyTxn(), groupId)
return err
}

func queryUser(ctx context.Context, txn *dgo.Txn, userid string) (user *User, err error) {
Expand Down Expand Up @@ -531,10 +524,13 @@ func queryGroup(ctx context.Context, txn *dgo.Txn, groupid string,
fields ...string) (group *Group, err error) {

// write query header
query := fmt.Sprintf(`query search($groupid: string){
group(func: eq(dgraph.xid, $groupid)) @filter(type(Group)) {
uid
%s }}`, strings.Join(fields, ", "))
query := fmt.Sprintf(`
query search($groupid: string){
group(func: eq(dgraph.xid, $groupid)) @filter(type(Group)) {
uid
%s
}
}`, strings.Join(fields, ", "))

queryVars := map[string]string{
"$groupid": groupid,
Expand Down Expand Up @@ -598,13 +594,14 @@ func queryAndPrintUser(ctx context.Context, txn *dgo.Txn, userId string) error {

func queryAndPrintGroup(ctx context.Context, txn *dgo.Txn, groupId string) error {
group, err := queryGroup(ctx, txn, groupId, "dgraph.xid", "~dgraph.user.group{dgraph.xid}",
"dgraph.group.acl")
"dgraph.acl.rule{dgraph.rule.predicate, dgraph.rule.permission}")
if err != nil {
return err
}
if group == nil {
return errors.Errorf("The group %q does not exist.\n", groupId)
return errors.Errorf("The group %s doesn't exist", groupId)
}

fmt.Printf("Group: %s\n", groupId)
fmt.Printf("UID : %s\n", group.Uid)
fmt.Printf("ID : %s\n", group.GroupID)
Expand All @@ -615,17 +612,10 @@ func queryAndPrintGroup(ctx context.Context, txn *dgo.Txn, groupId string) error
}
fmt.Printf("Users: %s\n", strings.Join(userNames, " "))

var acls []Acl
if len(group.Acls) != 0 {
if err := json.Unmarshal([]byte(group.Acls), &acls); err != nil {
return errors.Wrapf(err, "unable to unmarshal the acls associated with the group %v",
groupId)
}

for _, acl := range acls {
fmt.Printf("ACL : %v\n", acl)
}
for _, acl := range group.Rules {
fmt.Printf("ACL: %v\n", acl)
}

return nil
}

Expand Down
Loading