12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271 |
- package access
- import (
- "encoding/json"
- "fmt"
- "io/ioutil"
- "os"
- "testing"
- "time"
- "devt.de/krotik/common/fileutil"
- )
- func TestPersistedACLTable(t *testing.T) {
- testACLFile := "persist_tester.acl"
- defer func() {
- os.Remove(testACLFile)
- }()
- // Test the most basic start and stop
- pt, err := NewPersistedACLTable(testACLFile, time.Millisecond)
- if err != nil {
- t.Error(err)
- return
- }
- if _, _, err := pt.IsPermitted("", "", &Rights{}); err == nil || err.Error() != "Unknown user: " {
- t.Error("Unexpected result:", err)
- return
- }
- if err := pt.Close(); err != nil {
- t.Error(err)
- return
- }
- // Check that we get an error back when trying to close a thing twice or we try any other operation
- if _, _, err := pt.IsPermitted("", "", &Rights{}); err == nil || err.Error() != "ACL table was closed" {
- t.Error("Unexpected result:", err)
- return
- }
- if err := pt.Close(); err == nil || err.Error() != "ACL table was closed" {
- t.Error("Unexpected result:", err)
- return
- }
- // Create communication channel which can be used to trigger the watch thread
- watchToggle := make(chan bool)
- watchSleep = func(t time.Duration) {
- <-watchToggle
- }
- // Now test again but with some data
- pt, err = NewPersistedACLTable(testACLFile, time.Millisecond)
- if err != nil {
- t.Error(err)
- return
- }
- time.Sleep(50 * time.Millisecond)
- if pt.String() != `
- ACLTable
- ========
- Users:
- `[1:] {
- t.Error("Unexpected result:", pt.String())
- return
- }
- // Add the fi
- if err := pt.AddGroup("foo"); err != nil {
- t.Error(err)
- return
- }
- if res, _ := ioutil.ReadFile(testACLFile); string(res) != `
- {
- "groups": {
- "foo": {}
- },
- "users": {}
- }`[1:] {
- t.Error("Unexpected result:", string(res))
- return
- }
- if err := ioutil.WriteFile(testACLFile, []byte(`
- {
- "groups": {
- "bar": {
- "/bla": "CRUD",
- "/blatest*": "-R-D"
- },
- "public": {
- "/special": "-R-D",
- "/test*": "-R-D"
- }
- },
- "users": {
- "hans": [
- "public"
- ]
- }
- }`), 0666); err != nil {
- t.Error(err)
- return
- }
- watchToggle <- true
- time.Sleep(50 * time.Millisecond)
- // Check the new configuration has been loaded from disk
- if pt.String() != `
- ACLTable
- ========
- Users:
- hans : public
- Group: bar
- ====
- /bla : CRUD
- /blatest : -R-D
- Group: public
- ====
- /special : -R-D
- /test : -R-D
- `[1:] {
- t.Error("Unexpected result:", pt.String())
- return
- }
- // Produce some faulty disk configuration and see that it is rewritten
- // after PersistedACLTableErrRetries
- PersistedACLTableErrRetries = 2
- if err := ioutil.WriteFile(testACLFile, []byte(`
- {
- "groups": {
- "bar": {
- `), 0666); err != nil {
- t.Error(err)
- return
- }
- watchToggle <- true
- time.Sleep(time.Millisecond)
- watchToggle <- true
- time.Sleep(time.Millisecond)
- if err := pt.(*PersistedACLTable).SyncError; err == nil ||
- err.Error() != "Could not sync ACL table config from disk: unexpected end of JSON input" {
- t.Error("Unexpected result:", err)
- return
- }
- watchToggle <- true
- time.Sleep(50 * time.Millisecond)
- if err := pt.(*PersistedACLTable).SyncError; err != nil {
- t.Error("Unexpected result:", err)
- return
- }
- if res, _ := ioutil.ReadFile(testACLFile); string(res) != `{
- "groups": {
- "bar": {
- "/bla": "CRUD",
- "/blatest*": "-R-D"
- },
- "public": {
- "/special": "-R-D",
- "/test*": "-R-D"
- }
- },
- "users": {
- "hans": [
- "public"
- ]
- }
- }` {
- t.Error("Unexpected result:", string(res))
- return
- }
- if pt.String() != `
- ACLTable
- ========
- Users:
- hans : public
- Group: bar
- ====
- /bla : CRUD
- /blatest : -R-D
- Group: public
- ====
- /special : -R-D
- /test : -R-D
- `[1:] {
- t.Error("Unexpected result:", pt.String())
- return
- }
- // Test the various access functions
- if res, err := pt.GroupNames(); fmt.Sprint(res) != "[bar public]" {
- t.Error("Unexpected result:", res, err)
- return
- }
- if res, err := pt.UserNames(); fmt.Sprint(res) != "[hans]" {
- t.Error("Unexpected result:", res, err)
- return
- }
- if res, err := pt.GroupsOfUser("hans"); fmt.Sprint(res) != "[public]" {
- t.Error("Unexpected result:", res, err)
- return
- }
- if err := pt.AddPermission("public", "woo", &Rights{}); err != nil {
- t.Error("Unexpected result:", err)
- return
- }
- if res, _ := ioutil.ReadFile(testACLFile); string(res) != `{
- "groups": {
- "bar": {
- "/bla": "CRUD",
- "/blatest*": "-R-D"
- },
- "public": {
- "/special": "-R-D",
- "/test*": "-R-D",
- "woo": "----"
- }
- },
- "users": {
- "hans": [
- "public"
- ]
- }
- }` {
- t.Error("Unexpected result:", string(res))
- return
- }
- if err := pt.AddUserToGroup("hans", "bar"); err != nil {
- t.Error("Unexpected result:", err)
- return
- }
- if res, _ := ioutil.ReadFile(testACLFile); string(res) != `{
- "groups": {
- "bar": {
- "/bla": "CRUD",
- "/blatest*": "-R-D"
- },
- "public": {
- "/special": "-R-D",
- "/test*": "-R-D",
- "woo": "----"
- }
- },
- "users": {
- "hans": [
- "bar",
- "public"
- ]
- }
- }` {
- t.Error("Unexpected result:", string(res))
- return
- }
- conf, err := pt.GetConfig()
- if err != nil {
- t.Error(err)
- return
- }
- res, err := json.MarshalIndent(conf, "", " ")
- if err != nil || string(res) != `
- {
- "groups": {
- "bar": {
- "/bla": "CRUD",
- "/blatest*": "-R-D"
- },
- "public": {
- "/special": "-R-D",
- "/test*": "-R-D",
- "woo": "----"
- }
- },
- "users": {
- "hans": [
- "bar",
- "public"
- ]
- }
- }`[1:] {
- t.Error("Unexpected result:", string(res), err)
- return
- }
- if err := pt.RemoveUserFromGroup("hans", "bar"); err != nil {
- t.Error("Unexpected result:", err)
- return
- }
- if res, _ := ioutil.ReadFile(testACLFile); string(res) != `{
- "groups": {
- "bar": {
- "/bla": "CRUD",
- "/blatest*": "-R-D"
- },
- "public": {
- "/special": "-R-D",
- "/test*": "-R-D",
- "woo": "----"
- }
- },
- "users": {
- "hans": [
- "public"
- ]
- }
- }` {
- t.Error("Unexpected result:", string(res))
- return
- }
- if err := pt.RemoveGroup("public"); err != nil {
- t.Error("Unexpected result:", err)
- return
- }
- if res, _ := ioutil.ReadFile(testACLFile); string(res) != `{
- "groups": {
- "bar": {
- "/bla": "CRUD",
- "/blatest*": "-R-D"
- }
- },
- "users": {}
- }` {
- t.Error("Unexpected result:", string(res))
- return
- }
- if err := pt.ClearPermissions("bar"); err != nil {
- t.Error("Unexpected result:", err)
- return
- }
- if res, err := pt.Permissions("bar"); fmt.Sprint(res) != "map[]" || err != nil {
- t.Error("Unexpected result:", res, err)
- return
- }
- // Test that a sync failure blocks the whole object
- testerror := fmt.Errorf("Testerror")
- pt.(*PersistedACLTable).SyncError = testerror
- if _, err := pt.GroupNames(); err != testerror {
- t.Error("Unexpected result:", err)
- return
- }
- if _, err := pt.UserNames(); err != testerror {
- t.Error("Unexpected result:", err)
- return
- }
- if _, err := pt.GroupsOfUser(""); err != testerror {
- t.Error("Unexpected result:", err)
- return
- }
- if err := pt.AddPermission("", "", nil); err != testerror {
- t.Error("Unexpected result:", err)
- return
- }
- if _, err := pt.Permissions(""); err != testerror {
- t.Error("Unexpected result:", err)
- return
- }
- if err := pt.ClearPermissions(""); err != testerror {
- t.Error("Unexpected result:", err)
- return
- }
- if err := pt.AddGroup(""); err != testerror {
- t.Error("Unexpected result:", err)
- return
- }
- if err := pt.RemoveGroup(""); err != testerror {
- t.Error("Unexpected result:", err)
- return
- }
- if err := pt.AddUserToGroup("", ""); err != testerror {
- t.Error("Unexpected result:", err)
- return
- }
- if err := pt.RemoveUserFromGroup("", ""); err != testerror {
- t.Error("Unexpected result:", err)
- return
- }
- if _, err := pt.GetConfig(); err != testerror {
- t.Error("Unexpected result:", err)
- return
- }
- // Toggle the watch routine and close
- pt.(*PersistedACLTable).SyncError = ErrClosed
- watchToggle <- true
- err = pt.Close()
- // Error is preserved by by Close since it was set before it was called
- if err != ErrClosed {
- t.Error(err)
- }
- }
- func TestPersistedACLTableSync(t *testing.T) {
- testACLFile := "sycn_tester.acl"
- defer func() {
- os.Remove(testACLFile)
- }()
- pt := &PersistedACLTable{}
- pt.filename = testACLFile
- // We start with no file and no table
- if ok, _ := fileutil.PathExists(testACLFile); ok {
- t.Error("Unexpected result:", ok)
- return
- }
- // This should create an empty table in memory and on disk
- if err := pt.sync(true); err != nil {
- t.Error(err)
- return
- }
- if ok, _ := fileutil.PathExists(testACLFile); !ok {
- t.Error("Unexpected result:", ok)
- return
- }
- if pt.table.String() != `
- ACLTable
- ========
- Users:
- `[1:] {
- t.Error("Unexpected result:", pt.table.String())
- return
- }
- if res, _ := ioutil.ReadFile(testACLFile); string(res) != `{
- "groups": {},
- "users": {}
- }` {
- t.Error("Unexpected result:", string(res))
- return
- }
- os.Remove(testACLFile)
- if ok, _ := fileutil.PathExists(testACLFile); ok {
- t.Error("Unexpected result:", ok)
- return
- }
- pt.table = nil
- // Now do the same exercise again but with syncing from memory
- if err := pt.sync(false); err != nil {
- t.Error(err)
- return
- }
- if ok, _ := fileutil.PathExists(testACLFile); !ok {
- t.Error("Unexpected result:", ok)
- return
- }
- if pt.table.String() != `
- ACLTable
- ========
- Users:
- `[1:] {
- t.Error("Unexpected result:", pt.table.String())
- return
- }
- if res, _ := ioutil.ReadFile(testACLFile); string(res) != `{
- "groups": {},
- "users": {}
- }` {
- t.Error("Unexpected result:", string(res))
- return
- }
- // Fill up the memory but sync from disk
- pt.table.AddGroup("foo")
- if pt.table.String() != `
- ACLTable
- ========
- Users:
- Group: foo
- ====
- `[1:] {
- t.Error("Unexpected result:", pt.table.String())
- return
- }
- if res, err := pt.table.GetConfig(); fmt.Sprint(res["groups"]) != `map[foo:map[]]` || err != nil {
- t.Error("Unexpected result:", res["groups"], err)
- return
- }
- if err := pt.sync(true); err != nil {
- t.Error(err)
- return
- }
- if pt.table.String() != `
- ACLTable
- ========
- Users:
- `[1:] {
- t.Error("Unexpected result:", pt.table.String())
- return
- }
- // Fill up the memory and sync to disk
- pt.table.AddGroup("foo")
- if pt.table.String() != `
- ACLTable
- ========
- Users:
- Group: foo
- ====
- `[1:] {
- t.Error("Unexpected result:", pt.table.String())
- return
- }
- if err := pt.sync(false); err != nil {
- t.Error(err)
- return
- }
- if pt.table.String() != `
- ACLTable
- ========
- Users:
- Group: foo
- ====
- `[1:] {
- t.Error("Unexpected result:", pt.table.String())
- return
- }
- if res, _ := ioutil.ReadFile(testACLFile); string(res) != `
- {
- "groups": {
- "foo": {}
- },
- "users": {}
- }`[1:] {
- t.Error("Unexpected result:", string(res))
- return
- }
- // Write some rules to disk and load them into memory
- if err := ioutil.WriteFile(testACLFile, []byte(`
- {
- "groups": {
- "bar": {
- "/bla": "CRUD",
- "/blatest*": "-R-D"
- },
- "public": {
- "/special": "-R-D",
- "/test*": "-R-D"
- }
- },
- "users": {
- "hans": [
- "public"
- ]
- }
- }`), 0666); err != nil {
- t.Error(err)
- return
- }
- if err := pt.sync(true); err != nil {
- t.Error(err)
- return
- }
- if pt.table.String() != `
- ACLTable
- ========
- Users:
- hans : public
- Group: bar
- ====
- /bla : CRUD
- /blatest : -R-D
- Group: public
- ====
- /special : -R-D
- /test : -R-D
- `[1:] {
- t.Error("Unexpected result:", pt.table.String())
- return
- }
- }
- func TestRigths(t *testing.T) {
- r1 := &Rights{}
- r1.Create = true
- r1.Delete = true
- r2 := &Rights{
- Create: true,
- Delete: true,
- Update: true,
- }
- if res := r2.String(); res != "C-UD" {
- t.Error("Unexpected result:", res)
- return
- }
- if res := r2.IsAllowed(r1); !res {
- t.Error("Unexpected result:", res)
- return
- }
- if res := r1.IsAllowed(r2); res {
- t.Error("Unexpected result:", res)
- return
- }
- r1 = &Rights{}
- if res := r1.IsAllowed(&Rights{Read: true}); res {
- t.Error("Unexpected result:", res)
- return
- }
- if res := r1.IsAllowed(&Rights{Create: true}); res {
- t.Error("Unexpected result:", res)
- return
- }
- if res := r1.IsAllowed(&Rights{Update: true}); res {
- t.Error("Unexpected result:", res)
- return
- }
- if res := r1.IsAllowed(&Rights{Delete: true}); res {
- t.Error("Unexpected result:", res)
- return
- }
- if res, err := RightsFromString("C-U"); res != nil || err == nil || err.Error() != "Rigths string must be 4 characters" {
- t.Error("Unexpected result:", res, err)
- return
- }
- if res, err := RightsFromString("C0UD"); res != nil || err == nil || err.Error() != "Read permission in rights string must be either 'r' or '-'" {
- t.Error("Unexpected result:", res, err)
- return
- }
- }
- func TestMemoryACLTable(t *testing.T) {
- tab := NewMemoryACLTable()
- tab.Close() // Test NOP
- tableconfig, _ := tab.GetConfig()
- if res, err := json.MarshalIndent(tableconfig, "", " "); err != nil || string(res) != `
- {
- "groups": {},
- "users": {}
- }`[1:] {
- t.Error("Unexpected result:", string(res), err)
- return
- }
- // Test empty table operations
- if res, _ := tab.GroupNames(); fmt.Sprint(res) != "[]" {
- t.Error("Unexpected result:", res)
- return
- }
- if res, _ := tab.UserNames(); fmt.Sprint(res) != "[]" {
- t.Error("Unexpected result:", res)
- return
- }
- if res, err := tab.GroupsOfUser("hans"); err == nil || err.Error() != "Unknown user: hans" {
- t.Error("Unexpected result:", res, err)
- return
- }
- if err := tab.AddPermission("public", "", nil); err == nil || err.Error() != "Group public does not exist" {
- t.Error("Unexpected result:", err)
- return
- }
- if err := tab.RemoveGroup("foo"); err == nil || err.Error() != "Group foo does not exist" {
- t.Error("Unexpected result:", err)
- return
- }
- if err := tab.RemoveUserFromGroup("hans", "foo"); err == nil || err.Error() != "User hans does not exist" {
- t.Error("Unexpected result:", err)
- return
- }
- if _, _, err := tab.IsPermitted("hans", "", &Rights{}); err == nil || err.Error() != "Unknown user: hans" {
- t.Error("Unexpected result:", err)
- return
- }
- // Manually fill up the table
- if err := tab.AddGroup("public"); err != nil {
- t.Error("Unexpected result:", err)
- return
- }
- if res, err := tab.Permissions("public"); fmt.Sprint(res) != "map[]" || err != nil {
- t.Error("Unexpected result: ", res, err)
- return
- }
- if res, err := tab.Permissions("public2"); err == nil || err.Error() != "Group public2 does not exist" {
- t.Error("Unexpected result: ", res, err)
- return
- }
- if err := tab.ClearPermissions("public2"); err == nil || err.Error() != "Group public2 does not exist" {
- t.Error("Unexpected result: ", err)
- return
- }
- if err := tab.AddGroup("public"); err == nil || err.Error() != "Group public added twice" {
- t.Error("Unexpected result:", err)
- return
- }
- if res, _ := tab.GroupNames(); fmt.Sprint(res) != "[public]" {
- t.Error("Unexpected result:", res)
- return
- }
- if err := tab.AddGroup("bar"); err != nil {
- t.Error("Unexpected result:", err)
- return
- }
- if err := tab.AddUserToGroup("hans", "foo"); err == nil || err.Error() != "Group foo does not exist" {
- t.Error("Unexpected result:", err)
- return
- }
- if res, _ := tab.UserNames(); fmt.Sprint(res) != "[]" {
- t.Error("Unexpected result:", res)
- return
- }
- if err := tab.AddUserToGroup("hans", "public"); err != nil {
- t.Error("Unexpected result:", err)
- return
- }
- if err := tab.RemoveUserFromGroup("hans", "foo"); err == nil || err.Error() != "User hans is not in group foo" {
- t.Error("Unexpected result:", err)
- return
- }
- if err := tab.AddUserToGroup("hans", "bar"); err != nil {
- t.Error("Unexpected result:", err)
- return
- }
- if res, _ := tab.UserNames(); fmt.Sprint(res) != "[hans]" {
- t.Error("Unexpected result:", res)
- return
- }
- if res, _, err := tab.IsPermitted("hans", "/test", &Rights{}); err != nil || res {
- t.Error("Unexpected result:", res, err)
- return
- }
- if res, err := tab.GroupsOfUser("hans"); err != nil || fmt.Sprint(res) != "[bar public]" {
- t.Error("Unexpected result:", res, err)
- return
- }
- if err := tab.RemoveUserFromGroup("hans", "bar"); err != nil {
- t.Error("Unexpected result:", err)
- return
- }
- if res, err := tab.GroupsOfUser("hans"); err != nil || fmt.Sprint(res) != "[public]" {
- t.Error("Unexpected result:", res, err)
- return
- }
- // Finally add some permissions
- if err := tab.AddPermission("public", "/special", &Rights{
- Read: true,
- Delete: true,
- }); err != nil {
- t.Error("Unexpected result:", err)
- return
- }
- if res, err := tab.Permissions("public"); fmt.Sprint(res) != "map[/special:-R-D]" || err != nil {
- t.Error("Unexpected result: ", res, err)
- return
- }
- if err := tab.ClearPermissions("public"); err != nil {
- t.Error("Unexpected result: ", err)
- return
- }
- if res, err := tab.Permissions("public"); fmt.Sprint(res) != "map[]" || err != nil {
- t.Error("Unexpected result: ", res, err)
- return
- }
- if err := tab.AddPermission("public", "/special", &Rights{
- Read: true,
- Delete: true,
- }); err != nil {
- t.Error("Unexpected result:", err)
- return
- }
- if res, err := tab.Permissions("public"); fmt.Sprint(res) != "map[/special:-R-D]" || err != nil {
- t.Error("Unexpected result: ", res, err)
- return
- }
- if err := tab.AddPermission("public", "/special", &Rights{}); err == nil || err.Error() != "Resource access for /special registered twice" {
- t.Error("Unexpected result:", err)
- return
- }
- if err := tab.AddPermission("public", "/test*", &Rights{
- Read: true,
- Delete: true,
- }); err != nil {
- t.Error("Unexpected result:", err)
- return
- }
- if err := tab.AddPermission("public", "/test*", &Rights{}); err == nil || err.Error() != "Resource access wildcard for /test* registered twice" {
- t.Error("Unexpected result:", err)
- return
- }
- // Check permissions
- if res, _, err := tab.IsPermitted("hans", "/test", &Rights{}); err != nil || !res {
- t.Error("Unexpected result:", res, err)
- return
- }
- if res, _, err := tab.IsPermitted("hans", "/special", &Rights{}); err != nil || !res {
- t.Error("Unexpected result:", res, err)
- return
- }
- if res, _, err := tab.IsPermitted("hans", "/special1", &Rights{}); err != nil || res {
- t.Error("Unexpected result:", res, err)
- return
- }
- // Test no access in sub category
- if res, _, err := tab.IsPermitted("hans", "/test1", &Rights{}); err != nil || !res {
- t.Error("Unexpected result:", res, err)
- return
- }
- // Test read access in sub category
- if res, _, err := tab.IsPermitted("hans", "/test1", &Rights{Read: true}); err != nil || !res {
- t.Error("Unexpected result:", res, err)
- return
- }
- if res, _, err := tab.IsPermitted("hans", "/special", &Rights{Read: true}); err != nil || !res {
- t.Error("Unexpected result:", res, err)
- return
- }
- // Test no update access
- if res, _, err := tab.IsPermitted("hans", "/test1", &Rights{Read: true, Update: true}); err != nil || res {
- t.Error("Unexpected result:", res, err)
- return
- }
- if res, _, err := tab.IsPermitted("hans", "/special", &Rights{Read: true, Update: true}); err != nil || res {
- t.Error("Unexpected result:", res, err)
- return
- }
- // This should now be cached
- if res, _, err := tab.IsPermitted("hans", "/test1", &Rights{Read: true}); err != nil || !res {
- t.Error("Unexpected result:", res, err)
- return
- }
- if res, _, err := tab.IsPermitted("hans", "/test1", &Rights{Read: true, Update: true}); err != nil || res {
- t.Error("Unexpected result:", res, err)
- return
- }
- // Check a non-permitted access request
- if res, _, err := tab.IsPermitted("hans", "/tes", &Rights{}); err != nil || res {
- t.Error("Unexpected result:", res, err)
- return
- }
- // Check cache contents
- if res := tab.(*MemoryACLTable).PermissionCache.String(); res != `
- [hans /special ----]:true
- [hans /special -R--]:true
- [hans /special -RU-]:false
- [hans /special1 ----]:false
- [hans /tes ----]:false
- [hans /test ----]:true
- [hans /test1 ----]:true
- [hans /test1 -R--]:true
- [hans /test1 -RU-]:false
- `[1:] {
- t.Error("Unexpected result:", res)
- return
- }
- // Print current table
- if res := tab.String(); res != `
- ACLTable
- ========
- Users:
- hans : public
- Group: bar
- ====
- Group: public
- ====
- /special : -R-D
- /test : -R-D
- `[1:] {
- t.Error("Unexpected result:", res)
- return
- }
- if err := tab.AddPermission("bar", "/blatest*", &Rights{
- Read: true,
- Delete: true,
- }); err != nil {
- t.Error("Unexpected result:", err)
- return
- }
- if err := tab.AddPermission("bar", "/bla", &Rights{
- Read: true,
- Create: true,
- Update: true,
- Delete: true,
- }); err != nil {
- t.Error("Unexpected result:", err)
- return
- }
- if res := tab.String(); res != `
- ACLTable
- ========
- Users:
- hans : public
- Group: bar
- ====
- /bla : CRUD
- /blatest : -R-D
- Group: public
- ====
- /special : -R-D
- /test : -R-D
- `[1:] {
- t.Error("Unexpected result:", res)
- return
- }
- conf, err := tab.GetConfig()
- if err != nil {
- t.Error(err)
- return
- }
- res, err := json.MarshalIndent(conf, "", " ")
- if err != nil || string(res) != `
- {
- "groups": {
- "bar": {
- "/bla": "CRUD",
- "/blatest*": "-R-D"
- },
- "public": {
- "/special": "-R-D",
- "/test*": "-R-D"
- }
- },
- "users": {
- "hans": [
- "public"
- ]
- }
- }`[1:] {
- t.Error("Unexpected result:", string(res), err)
- return
- }
- // Duplicate the table
- tab2, err := NewMemoryACLTableFromConfig(conf)
- if err != nil {
- t.Error(err)
- return
- }
- if res := tab2.String(); res != `
- ACLTable
- ========
- Users:
- hans : public
- Group: bar
- ====
- /bla : CRUD
- /blatest : -R-D
- Group: public
- ====
- /special : -R-D
- /test : -R-D
- `[1:] {
- t.Error("Unexpected result:", res)
- return
- }
- // Destroy group public
- if err := tab.RemoveGroup("public"); err != nil {
- t.Error("Unexpected result:", err)
- return
- }
- if res, err := tab.GroupsOfUser("hans"); err == nil || err.Error() != "Unknown user: hans" {
- t.Error("Unexpected result:", res, err)
- return
- }
- // All permissions should be gone now
- if res, _, err := tab.IsPermitted("hans", "/test1", &Rights{Read: true}); err == nil || err.Error() != "Unknown user: hans" {
- t.Error("Unexpected result:", res, err)
- return
- }
- if res, _ := tab.GroupNames(); fmt.Sprint(res) != "[bar]" {
- t.Error("Unexpected result:", res)
- return
- }
- if res, _ := tab.UserNames(); fmt.Sprint(res) != "[]" {
- t.Error("Unexpected result:", res)
- return
- }
- if res, err := tab.GroupsOfUser("hans"); err == nil || err.Error() != "Unknown user: hans" {
- t.Error("Unexpected result:", res, err)
- return
- }
- if res, _, err := tab.IsPermitted("hans", "/test", &Rights{}); err == nil || err.Error() != "Unknown user: hans" {
- t.Error("Unexpected result:", res, err)
- return
- }
- if res, _, err := tab.IsPermitted("hans", "/tes", &Rights{}); err == nil || err.Error() != "Unknown user: hans" {
- t.Error("Unexpected result:", res, err)
- return
- }
- // Test error cases
- tab2 = nil
- var nullTable *MemoryACLTable
- if res := nullTable.String(); res != `
- ACLTable
- ========
- Users:
- `[1:] {
- t.Error("Unexpected result:", res)
- return
- }
- tab2 = NewMemoryACLTable()
- if res := tab2.String(); res != `
- ACLTable
- ========
- Users:
- `[1:] {
- t.Error("Unexpected result:", res)
- return
- }
- tab, err = NewMemoryACLTableFromConfig(map[string]interface{}{})
- if tab != nil || err == nil || err.Error() != "Entry 'users' is missing from ACL table config" {
- t.Error("Unexpected results:", tab, err)
- return
- }
- tab, err = NewMemoryACLTableFromConfig(map[string]interface{}{
- "users": "foo",
- })
- if tab != nil || err == nil || err.Error() != "Entry 'users' is not of the expected format" {
- t.Error("Unexpected results:", tab, err)
- return
- }
- tab, err = NewMemoryACLTableFromConfig(map[string]interface{}{
- "users": map[string][]string{},
- })
- if tab != nil || err == nil || err.Error() != "Entry 'groups' is missing from ACL table config" {
- t.Error("Unexpected results:", tab, err)
- return
- }
- tab, err = NewMemoryACLTableFromConfig(map[string]interface{}{
- "users": map[string][]string{},
- "groups": "foo",
- })
- if tab != nil || err == nil || err.Error() != "Entry 'groups' is not of the expected format" {
- t.Error("Unexpected results:", tab, err)
- return
- }
- tab, err = NewMemoryACLTableFromConfig(map[string]interface{}{
- "users": map[string][]string{},
- "groups": map[string]string{
- "foo": "bar",
- },
- })
- if tab != nil || err == nil || err.Error() != "Entries in 'groups' are not of the expected format" {
- t.Error("Unexpected results:", tab, err)
- return
- }
- tab, err = NewMemoryACLTableFromConfig(map[string]interface{}{
- "users": map[string]string{
- "foo": "bar",
- },
- "groups": map[string]string{},
- })
- if tab != nil || err == nil || err.Error() != "Entries in 'users' are not of the expected format" {
- t.Error("Unexpected results:", tab, err)
- return
- }
- tab, err = NewMemoryACLTableFromConfig(map[string]interface{}{
- "users": map[string][]string{},
- "groups": map[string]map[string]string{
- "foogroup": {
- "/fooresource": "a---",
- },
- },
- })
- if tab != nil || err == nil ||
- err.Error() != "Error adding resource /fooresource of group foogroup: Create permission in rights string must be either 'c' or '-'" {
- t.Error("Unexpected results:", tab, err)
- return
- }
- tab, err = NewMemoryACLTableFromConfig(map[string]interface{}{
- "users": map[string][]string{
- "hans": {"bargroup"},
- },
- "groups": map[string]map[string]string{
- "foogroup": {
- "/fooresource": "C---",
- },
- },
- })
- if tab != nil || err == nil ||
- err.Error() != "Error adding user hans to group bargroup: Group bargroup does not exist" {
- t.Error("Unexpected results:", tab, err)
- return
- }
- }
|