Skip to content

Commit

Permalink
add bfs search
Browse files Browse the repository at this point in the history
  • Loading branch information
imtbkcat committed Apr 19, 2019
1 parent a6856df commit dc0d793
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 6 deletions.
42 changes: 36 additions & 6 deletions privilege/privileges/cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ type defaultRoleRecord struct {

// roleGraphEdgesTable is used to cache relationship between and role.
type roleGraphEdgesTable struct {
roleList map[string]bool
roleList map[string]*auth.RoleIdentity
}

// Find method is used to find role from table
Expand All @@ -145,6 +145,33 @@ type MySQLPrivilege struct {
RoleGraph map[string]roleGraphEdgesTable
}

// FindAllRole is used to find all roles grant to this user.
func (p *MySQLPrivilege) FindAllRole(activeRoles []*auth.RoleIdentity) []*auth.RoleIdentity {
queue, head := make([]*auth.RoleIdentity, 0, len(activeRoles)), 0
for _, r := range activeRoles {
queue = append(queue, r)
}
// Using breadth first search to find all roles grant to this user.
visited, ret := make(map[string]bool), make([]*auth.RoleIdentity, 0)
for head < len(queue) {
role := queue[head]
if _, ok := visited[role.String()]; !ok {
visited[role.String()] = true
ret = append(ret, role)
key := role.Username + "@" + role.Hostname
if edgeTable, ok := p.RoleGraph[key]; ok {
for _, v := range edgeTable.roleList {
if _, ok := visited[v.String()]; !ok {
queue = append(queue, v)
}
}
}
}
head += 1
}
return ret
}

// FindRole is used to detect whether there is edges between users and roles.
func (p *MySQLPrivilege) FindRole(user string, host string, role *auth.RoleIdentity) bool {
rec := p.matchUser(user, host)
Expand Down Expand Up @@ -474,10 +501,10 @@ func (p *MySQLPrivilege) decodeRoleEdgesTable(row chunk.Row, fs []*ast.ResultFie
toKey := toUser + "@" + toHost
roleGraph, ok := p.RoleGraph[toKey]
if !ok {
roleGraph = roleGraphEdgesTable{roleList: make(map[string]bool)}
roleGraph = roleGraphEdgesTable{roleList: make(map[string]*auth.RoleIdentity)}
p.RoleGraph[toKey] = roleGraph
}
roleGraph.roleList[fromKey] = true
roleGraph.roleList[fromKey] = &auth.RoleIdentity{Username: fromUser, Hostname: fromHost}
return nil
}

Expand Down Expand Up @@ -703,6 +730,9 @@ func (p *MySQLPrivilege) DBIsVisible(user, host, db string) bool {
func (p *MySQLPrivilege) showGrants(user, host string, roles []*auth.RoleIdentity) []string {
var gs []string
var hasGlobalGrant bool = false
// Some privileges may granted from role inheritance.
// We should find these inheritance relationship.
allRoles := p.FindAllRole(roles)
// Show global grants.
var currentPriv mysql.PrivilegeType
var g string
Expand All @@ -711,7 +741,7 @@ func (p *MySQLPrivilege) showGrants(user, host string, roles []*auth.RoleIdentit
hasGlobalGrant = true
currentPriv |= record.Privileges
} else {
for _, r := range roles {
for _, r := range allRoles {
if record.User == r.Username && record.Host == r.Hostname {
hasGlobalGrant = true
currentPriv |= record.Privileges
Expand Down Expand Up @@ -741,7 +771,7 @@ func (p *MySQLPrivilege) showGrants(user, host string, roles []*auth.RoleIdentit
dbPrivTable[record.DB] = record.Privileges
}
} else {
for _, r := range roles {
for _, r := range allRoles {
if record.User == r.Username && record.Host == r.Hostname {
if _, ok := dbPrivTable[record.DB]; ok {
dbPrivTable[record.DB] |= record.Privileges
Expand Down Expand Up @@ -771,7 +801,7 @@ func (p *MySQLPrivilege) showGrants(user, host string, roles []*auth.RoleIdentit
tablePrivTable[recordKey] = record.TablePriv
}
} else {
for _, r := range roles {
for _, r := range allRoles {
if record.User == r.Username && record.Host == r.Hostname {
if _, ok := dbPrivTable[record.DB]; ok {
tablePrivTable[recordKey] |= record.TablePriv
Expand Down
13 changes: 13 additions & 0 deletions privilege/privileges/privileges_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,19 @@ func (s *testPrivilegeSuite) TestShowGrants(c *C) {
c.Assert(gs, HasLen, 5)
mustExec(c, se, `DROP ROLE 'r1', 'r2'`)
mustExec(c, se, `DROP USER 'testrole'@'localhost'`)
mustExec(c, se, `CREATE ROLE 'r1', 'r2'`)
mustExec(c, se, `GRANT SELECT ON test.* TO 'r2'`)
mustExec(c, se, `CREATE USER 'testrole'@'localhost' IDENTIFIED BY 'u1pass'`)
mustExec(c, se, `GRANT 'r1' TO 'testrole'@'localhost'`)
mustExec(c, se, `GRANT 'r2' TO 'r1'`)
gs, err = pc.ShowGrants(se, &auth.UserIdentity{Username: "testrole", Hostname: "localhost"}, nil)
c.Assert(err, IsNil)
c.Assert(gs, HasLen, 2)
roles = make([]*auth.RoleIdentity, 0)
roles = append(roles, &auth.RoleIdentity{Username: "r1", Hostname: "%"})
gs, err = pc.ShowGrants(se, &auth.UserIdentity{Username: "testrole", Hostname: "localhost"}, roles)
c.Assert(err, IsNil)
c.Assert(gs, HasLen, 3)
}

func (s *testPrivilegeSuite) TestDropTablePriv(c *C) {
Expand Down

0 comments on commit dc0d793

Please sign in to comment.