Эх сурвалжийг харах

perm: optimize policies management

xuxin 1 жил өмнө
parent
commit
dd3a0f5fa6
3 өөрчлөгдсөн 98 нэмэгдсэн , 20 устгасан
  1. 81 13
      perm/builder.go
  2. 5 4
      perm/db_policy.go
  3. 12 3
      perm/policy.go

+ 81 - 13
perm/builder.go

@@ -1,12 +1,12 @@
 package perm
 
 import (
-	"crypto/md5"
 	"errors"
 	"fmt"
 	"net/http"
 	"reflect"
 	"strings"
+	"sync"
 	"time"
 
 	"github.com/iancoleman/strcase"
@@ -57,6 +57,7 @@ func ToPermissionRN(v interface{}) []string {
 }
 
 type Builder struct {
+	m             sync.Mutex
 	policies      []*PolicyBuilder
 	ladon         *ladon.Ladon
 	subjectsFunc  SubjectsFunc
@@ -74,17 +75,63 @@ func New() *Builder {
 }
 
 func (b *Builder) Policies(ps ...*PolicyBuilder) (r *Builder) {
-	b.policies = ps
-	for _, p := range b.policies {
-		if p.policy.ID == "" {
-			p.policy.ID = fmt.Sprintf("%x", md5.Sum(p.Json()))
+	b.DeletePolicies(b.policies...)
+	b.policies = make([]*PolicyBuilder, 0)
+	b.CreatePolicies(ps...)
+	return b
+}
+
+func (b *Builder) createPolicy(p *PolicyBuilder) {
+	p.SetIDIfEmpty()
+	err := b.ladon.Manager.Create(p.policy)
+	if err != nil {
+		panic(err)
+	}
+	b.policies = append(b.policies, p)
+}
+
+func (b *Builder) updatePolicy(p *PolicyBuilder) {
+	i := b.findPolicyIndex(p.GetID())
+	if i < 0 {
+		return
+	}
+
+	err := b.ladon.Manager.Update(p.policy)
+	if err != nil {
+		panic(err)
+	}
+	b.policies[i] = p
+}
+
+func (b *Builder) findPolicyIndex(id string) int {
+	for i, p := range b.policies {
+		if p.GetID() == id {
+			return i
 		}
-		err := b.ladon.Manager.Create(p.policy)
-		if err != nil {
-			panic(err)
+	}
+	return -1
+}
+
+func (b *Builder) updateOrCreatePolicy(p *PolicyBuilder) {
+	i := b.findPolicyIndex(p.GetID())
+	if i < 0 {
+		b.createPolicy(p)
+	} else {
+		b.updatePolicy(p)
+	}
+}
+
+func (b *Builder) deletePolicy(p *PolicyBuilder) {
+	for i, ep := range b.policies {
+		if ep.GetID() == p.GetID() {
+			err := b.ladon.Manager.Delete(p.GetID())
+			if err != nil {
+				panic(err)
+			}
+			b.policies = append(b.policies[:i], b.policies[1+1:]...)
+			break
 		}
 	}
-	return b
 }
 
 func (b *Builder) SubjectsFunc(v SubjectsFunc) (r *Builder) {
@@ -108,22 +155,42 @@ func (b *Builder) EnableDBPolicy(db *gorm.DB, dbPolicyModel DBPolicy, loadDurati
 	return b
 }
 
+func (b *Builder) CreatePolicies(ps ...*PolicyBuilder) {
+	b.m.Lock()
+	defer b.m.Unlock()
+	for _, p := range ps {
+		b.createPolicy(p)
+	}
+}
+
 func (b *Builder) UpdatePolicies(toUpdate ...*PolicyBuilder) {
+	b.m.Lock()
+	defer b.m.Unlock()
+	for _, p := range toUpdate {
+		b.updatePolicy(p)
+	}
+}
+
+func (b *Builder) UpdateOrCreatePolicies(toUpdate ...*PolicyBuilder) {
+	b.m.Lock()
+	defer b.m.Unlock()
 	for _, p := range toUpdate {
-		b.ladon.Manager.Update(p.policy)
+		b.updateOrCreatePolicy(p)
 	}
 }
 
 func (b *Builder) DeletePolicies(toDelete ...*PolicyBuilder) {
+	b.m.Lock()
+	defer b.m.Unlock()
 	for _, p := range toDelete {
-		b.ladon.Manager.Delete(p.GetID())
+		b.deletePolicy(p)
 	}
 }
 
 func (b *Builder) LoadDBPoliciesToMemory(db *gorm.DB, startFrom *time.Time) {
-	toUpdate, toDelete := b.dbPolicyModel.LoadDBPolicies(db, startFrom)
+	toUpdateOrCreate, toDelete := b.dbPolicyModel.LoadDBPolicies(db, startFrom)
 	b.DeletePolicies(toDelete...)
-	b.UpdatePolicies(toUpdate...)
+	b.UpdateOrCreatePolicies(toUpdateOrCreate...)
 	if Verbose {
 		b.printPolices()
 	}
@@ -141,6 +208,7 @@ func (b *Builder) loopLoadDBPolicies(db *gorm.DB, duration time.Duration) {
 
 func (b *Builder) printPolices() {
 	allp, _ := b.ladon.Manager.GetAll(100, 0)
+	fmt.Printf("all permission policies: \n")
 	for _, p := range allp {
 		fmt.Printf("%+v \n", p)
 	}

+ 5 - 4
perm/db_policy.go

@@ -1,11 +1,12 @@
 package perm
 
 import (
-	"github.com/lib/pq"
-	"gorm.io/gorm"
 	"strconv"
 	"strings"
 	"time"
+
+	"github.com/lib/pq"
+	"gorm.io/gorm"
 )
 
 type DefaultDBPolicy struct {
@@ -18,7 +19,7 @@ type DefaultDBPolicy struct {
 	Resources pq.StringArray `gorm:"type:text[]"`
 }
 
-func (p DefaultDBPolicy) LoadDBPolicies(db *gorm.DB, startFrom *time.Time) (toUpdate []*PolicyBuilder, toDelete []*PolicyBuilder) {
+func (p DefaultDBPolicy) LoadDBPolicies(db *gorm.DB, startFrom *time.Time) (toUpdateOrCreate []*PolicyBuilder, toDelete []*PolicyBuilder) {
 	var ps []DefaultDBPolicy
 	if startFrom == nil || startFrom.IsZero() {
 		db.Find(&ps)
@@ -30,7 +31,7 @@ func (p DefaultDBPolicy) LoadDBPolicies(db *gorm.DB, startFrom *time.Time) (toUp
 		if p.DeletedAt.Valid {
 			toDelete = append(toDelete, p.ToPolicy())
 		} else {
-			toUpdate = append(toUpdate, p.ToPolicy())
+			toUpdateOrCreate = append(toUpdateOrCreate, p.ToPolicy())
 		}
 	}
 	return

+ 12 - 3
perm/policy.go

@@ -1,7 +1,9 @@
 package perm
 
 import (
+	"crypto/md5"
 	"encoding/json"
+	"fmt"
 	"strings"
 
 	"github.com/ory/ladon"
@@ -59,9 +61,16 @@ func (b *PolicyBuilder) Given(conditions Conditions) (r *PolicyBuilder) {
 	return b
 }
 
-func (b PolicyBuilder) Json() []byte {
-	str, _ := json.Marshal(b.policy)
-	return str
+func (b *PolicyBuilder) SetIDIfEmpty() {
+	if b.policy.ID != "" {
+		return
+	}
+
+	bs, err := json.Marshal(b.policy)
+	if err != nil {
+		panic(err)
+	}
+	b.policy.ID = fmt.Sprintf("%x", md5.Sum(bs))
 }
 
 func (b *PolicyBuilder) GetID() string {