浏览代码

Merge branch 'feat/permset' into dev

Mustafa Arici 8 年之前
父节点
当前提交
aee1140730
共有 3 个文件被更改,包括 321 次插入0 次删除
  1. 13 0
      perms.go
  2. 102 0
      permset/permset.go
  3. 206 0
      permset/permset_test.go

+ 13 - 0
perms.go

@@ -0,0 +1,13 @@
+package ovpm
+
+import "github.com/cad/ovpm/permset"
+
+// OVPM defined permissions.
+const (
+	CreateUserPerm permset.Perm = iota
+	GetAnyUserPerm
+	GetSelfPerm
+	UpdateAnyUserPerm
+	UpdateSelfPerm
+	DeleteAnyUserPerm
+)

+ 102 - 0
permset/permset.go

@@ -0,0 +1,102 @@
+package permset
+
+import (
+	"context"
+	"fmt"
+)
+
+// Perm is a permission to do some action.
+type Perm int
+
+// Permset represents a set of permissions.
+type Permset struct {
+	permset map[Perm]bool
+}
+
+// New receives permissions to contain and returns a permset from it.
+func New(perms ...Perm) Permset {
+	permset := Permset{permset: make(map[Perm]bool)}
+	permset.Add(perms...)
+	return permset
+}
+
+// Add adds the received perms to the permset.
+func (ps *Permset) Add(perms ...Perm) {
+	for _, perm := range perms {
+		ps.permset[perm] = true
+	}
+}
+
+// Remove removes the received perms from the permset.
+func (ps *Permset) Remove(perms ...Perm) {
+	for _, perm := range perms {
+		if _, ok := ps.permset[perm]; ok {
+			delete(ps.permset, perm)
+		}
+	}
+}
+
+// Perms returns the permissions contained within the permset.
+func (ps *Permset) Perms() []Perm {
+	var perms []Perm
+	for k := range ps.permset {
+		perms = append(perms, k)
+	}
+	return perms
+}
+
+// Contains receives single Perm and returns true if the permset contains it.
+func (ps *Permset) Contains(perm Perm) bool {
+	if _, ok := ps.permset[perm]; !ok {
+		return false
+	}
+	return true
+}
+
+// ContainsAll returns true if the permset contains all received Perms.
+func (ps *Permset) ContainsAll(perms ...Perm) bool {
+	for _, perm := range perms {
+		if _, ok := ps.permset[perm]; !ok {
+			return false
+		}
+	}
+	return true
+}
+
+// ContainsSome returns true if the permset contains any one or more of the received Perms.
+func (ps *Permset) ContainsSome(perms ...Perm) bool {
+	for _, perm := range perms {
+		if _, ok := ps.permset[perm]; ok {
+			return true
+		}
+	}
+	return false
+}
+
+// ContainsNone returns true if the permset contains none one of the received Perms.
+func (ps *Permset) ContainsNone(perms ...Perm) bool {
+	for _, perm := range perms {
+		if _, ok := ps.permset[perm]; ok {
+			return false
+		}
+	}
+	return true
+}
+
+type permsetKeyType int
+
+const permsetKey permsetKeyType = iota
+
+// NewContext receives perms and returns a context with the received perms are the value of the context.
+func NewContext(ctx context.Context, permset Permset) context.Context {
+	return context.WithValue(ctx, permsetKey, permset)
+}
+
+// FromContext receives a context and returns the permset in it.
+func FromContext(ctx context.Context) (Permset, error) {
+	permset, ok := ctx.Value(permsetKey).(Permset)
+	if !ok {
+		return Permset{}, fmt.Errorf("cannot get context value")
+	}
+	return permset, nil
+}

+ 206 - 0
permset/permset_test.go

@@ -0,0 +1,206 @@
+package permset
+
+import (
+	"context"
+	"testing"
+)
+
+const (
+	TestPerm1 Perm = iota
+	TestPerm2
+	TestPerm3
+)
+
+func TestNew(t *testing.T) {
+	var newtests = []struct {
+		perms []Perm
+	}{
+		{[]Perm{TestPerm1}},
+		{[]Perm{TestPerm1, TestPerm2}},
+		{[]Perm{TestPerm3, TestPerm2}},
+		{[]Perm{TestPerm2, TestPerm2}},
+		{[]Perm{TestPerm3, TestPerm2, TestPerm3}},
+	}
+
+	for _, tt := range newtests {
+		permset := New(tt.perms...)
+
+		// See if perms within the permset checks out with the ones provided to the New().
+		for _, perm := range tt.perms {
+			if _, ok := permset.permset[perm]; !ok {
+				t.Fatalf("perm should exist in the permset: %v", perm)
+			}
+		}
+
+		// See if there are any extra perms in the permset that is not provided to the New().
+		for perm := range permset.permset {
+			var found bool
+			for _, ttPerm := range tt.perms {
+				if ttPerm == perm {
+					found = true
+				}
+			}
+
+			if !found {
+				t.Fatalf("perm should not exist in the permset: %v", perm)
+			}
+		}
+	}
+}
+
+func TestAdd(t *testing.T) {
+	permset := New(TestPerm2)
+	permset.Add(TestPerm3)
+
+	if _, ok := permset.permset[TestPerm3]; !ok {
+		t.Fatal("perm TestPerm3 should exist in the permset")
+	}
+	if _, ok := permset.permset[TestPerm2]; !ok {
+		t.Fatal("perm TestPerm2 should exist in the permset")
+	}
+
+}
+
+func TestRemove(t *testing.T) {
+	// See if remove works OK.
+	permset := New(TestPerm2, TestPerm3)
+	permset.Remove(TestPerm3)
+
+	if _, ok := permset.permset[TestPerm3]; ok {
+		t.Fatal("perm TestPerm3 should not exist in the permset")
+	}
+	if _, ok := permset.permset[TestPerm2]; !ok {
+		t.Fatal("perm TestPerm2 should exist in the permset")
+	}
+
+	// See if double remove breaks it.
+	permset = New(TestPerm2, TestPerm3)
+	permset.Remove(TestPerm3)
+	permset.Remove(TestPerm3)
+
+	if _, ok := permset.permset[TestPerm3]; ok {
+		t.Fatal("perm TestPerm3 should not exist in the permset")
+	}
+	if _, ok := permset.permset[TestPerm2]; !ok {
+		t.Fatal("perm TestPerm2 should exist in the permset")
+	}
+
+}
+
+func TestPerms(t *testing.T) {
+	permset := New(TestPerm2, TestPerm3)
+	perms := permset.Perms()
+
+	var found bool
+	for _, perm := range perms {
+		if perm == TestPerm2 {
+			found = true
+		}
+	}
+
+	if !found {
+		t.Fatal("Perms() should return all the perms within the permset")
+	}
+}
+
+func TestContains(t *testing.T) {
+	permset := New(TestPerm2, TestPerm3)
+
+	if !permset.Contains(TestPerm2) {
+		t.Fatal("permset should contain TestPerm2")
+	}
+
+	if !permset.Contains(TestPerm3) {
+		t.Fatal("permset should contain TestPerm3")
+	}
+
+	if permset.Contains(TestPerm1) {
+		t.Fatal("permset should  not contain TestPerm1")
+	}
+}
+
+func TestContainsAll(t *testing.T) {
+	permset := New(TestPerm2, TestPerm3)
+
+	if !permset.ContainsAll(TestPerm2) {
+		t.Fatal("permset should contain TestPerm2")
+	}
+
+	if !permset.ContainsAll(TestPerm3) {
+		t.Fatal("permset should contain TestPerm3")
+	}
+
+	if permset.ContainsAll(TestPerm1) {
+		t.Fatal("permset should  not contain TestPerm1")
+	}
+
+	if !permset.ContainsAll(TestPerm2, TestPerm3) {
+		t.Fatal("permset should contain TestPerm2 and TestPerm3")
+	}
+
+	if !permset.ContainsAll(TestPerm3, TestPerm2) {
+		t.Fatal("permset should contain TestPerm2 and TestPerm3")
+	}
+
+	if permset.ContainsAll(TestPerm1, TestPerm2) {
+		t.Fatal("permset should not contain TestPerm1 and TestPerm3")
+	}
+
+}
+
+func TestContainsSome(t *testing.T) {
+	permset := New(TestPerm2, TestPerm3)
+
+	if !permset.ContainsSome(TestPerm2) {
+		t.Fatal("permset should contain TestPerm2")
+	}
+
+	if !permset.ContainsSome(TestPerm1, TestPerm3) {
+		t.Fatal("permset should contain TestPerm1 and TestPerm3")
+	}
+
+	if permset.ContainsSome(TestPerm1) {
+		t.Fatal("permset should contain TestPerm1")
+	}
+
+}
+
+func TestContainsNone(t *testing.T) {
+	permset := New(TestPerm2, TestPerm3)
+
+	if !permset.ContainsNone(TestPerm1) {
+		t.Fatal("ContainsNone should return true")
+	}
+
+	if permset.ContainsNone(TestPerm2) {
+		t.Fatal("ContainsNone should return false")
+	}
+}
+
+func TestNewContext(t *testing.T) {
+	permset := New(TestPerm2, TestPerm3)
+	ctx := NewContext(context.Background(), permset)
+
+	permsetFromCtx, ok := ctx.Value(permsetKey).(Permset)
+	if !ok {
+		t.Fatal("can't extract permset from ctx")
+	}
+
+	if !permset.ContainsAll(permsetFromCtx.Perms()...) {
+		t.Fatal("permsets should match")
+	}
+}
+
+func TestFromContext(t *testing.T) {
+	permset := New(TestPerm2, TestPerm3)
+	ctx := NewContext(context.Background(), permset)
+
+	permsetFromCtx, err := FromContext(ctx)
+	if err != nil {
+		t.Fatalf("error is not expected here: %v", err)
+	}
+
+	if !permset.ContainsAll(permsetFromCtx.Perms()...) {
+		t.Fatal("permsets should match")
+	}
+}