| package backup_test |
| |
| import ( |
| "database/sql" |
| "fmt" |
| |
| "github.com/DATA-DOG/go-sqlmock" |
| "github.com/apache/cloudberry-backup/backup" |
| "github.com/apache/cloudberry-backup/testutils" |
| "github.com/apache/cloudberry-backup/toc" |
| "github.com/apache/cloudberry-go-libs/structmatcher" |
| "github.com/apache/cloudberry-go-libs/testhelper" |
| |
| . "github.com/onsi/ginkgo/v2" |
| . "github.com/onsi/gomega" |
| ) |
| |
| var _ = Describe("backup/predata_acl tests", func() { |
| BeforeEach(func() { |
| tocfile, backupfile = testutils.InitializeTestTOC(buffer, "predata") |
| }) |
| Describe("PrintObjectMetadata", func() { |
| table := backup.Table{Relation: backup.Relation{Schema: "public", Name: "tablename"}} |
| hasAllPrivileges := testutils.DefaultACLForType("anothertestrole", toc.OBJ_TABLE) |
| hasMostPrivileges := testutils.DefaultACLForType("testrole", toc.OBJ_TABLE) |
| hasMostPrivileges.Trigger = false |
| hasSinglePrivilege := backup.ACL{Grantee: "", Trigger: true} |
| hasAllPrivilegesWithGrant := testutils.DefaultACLForTypeWithGrant("anothertestrole", toc.OBJ_TABLE) |
| hasMostPrivilegesWithGrant := testutils.DefaultACLForTypeWithGrant("testrole", toc.OBJ_TABLE) |
| hasMostPrivilegesWithGrant.TriggerWithGrant = false |
| hasSinglePrivilegeWithGrant := backup.ACL{Grantee: "", TriggerWithGrant: true} |
| privileges := []backup.ACL{hasAllPrivileges, hasMostPrivileges, hasSinglePrivilege} |
| privilegesWithGrant := []backup.ACL{hasAllPrivilegesWithGrant, hasMostPrivilegesWithGrant, hasSinglePrivilegeWithGrant} |
| It("prints a block with a table comment", func() { |
| tableMetadata := backup.ObjectMetadata{Comment: "This is a table comment."} |
| backup.PrintObjectMetadata(backupfile, tocfile, tableMetadata, table, "", []uint32{0, 0}) |
| testhelper.ExpectRegexp(buffer, ` |
| |
| COMMENT ON TABLE public.tablename IS 'This is a table comment.';`) |
| }) |
| It("prints a block with a table comment with special characters", func() { |
| tableMetadata := backup.ObjectMetadata{Comment: `This is a ta'ble 1+=;,./\>,<@\\n^comment.`} |
| backup.PrintObjectMetadata(backupfile, tocfile, tableMetadata, table, "", []uint32{0, 0}) |
| testhelper.ExpectRegexp(buffer, ` |
| |
| COMMENT ON TABLE public.tablename IS 'This is a ta''ble 1+=;,./\>,<@\\n^comment.';`) |
| }) |
| It("prints an ALTER TABLE ... OWNER TO statement to set the table owner", func() { |
| tableMetadata := backup.ObjectMetadata{Owner: "testrole"} |
| backup.PrintObjectMetadata(backupfile, tocfile, tableMetadata, table, "", []uint32{0, 0}) |
| testhelper.ExpectRegexp(buffer, ` |
| |
| ALTER TABLE public.tablename OWNER TO testrole;`) |
| }) |
| It("prints a block of REVOKE and GRANT statements", func() { |
| tableMetadata := backup.ObjectMetadata{Privileges: privileges} |
| backup.PrintObjectMetadata(backupfile, tocfile, tableMetadata, table, "", []uint32{0, 0}) |
| testhelper.ExpectRegexp(buffer, ` |
| |
| REVOKE ALL ON TABLE public.tablename FROM PUBLIC; |
| GRANT ALL ON TABLE public.tablename TO anothertestrole; |
| GRANT SELECT,INSERT,UPDATE,DELETE,TRUNCATE,REFERENCES ON TABLE public.tablename TO testrole; |
| GRANT TRIGGER ON TABLE public.tablename TO PUBLIC;`) |
| }) |
| It("prints a block of REVOKE and GRANT statements WITH GRANT OPTION", func() { |
| tableMetadata := backup.ObjectMetadata{Privileges: privilegesWithGrant} |
| backup.PrintObjectMetadata(backupfile, tocfile, tableMetadata, table, "", []uint32{0, 0}) |
| testhelper.ExpectRegexp(buffer, ` |
| |
| REVOKE ALL ON TABLE public.tablename FROM PUBLIC; |
| GRANT ALL ON TABLE public.tablename TO anothertestrole WITH GRANT OPTION; |
| GRANT SELECT,INSERT,UPDATE,DELETE,TRUNCATE,REFERENCES ON TABLE public.tablename TO testrole WITH GRANT OPTION; |
| GRANT TRIGGER ON TABLE public.tablename TO PUBLIC WITH GRANT OPTION;`) |
| }) |
| It("prints a block of REVOKE and GRANT statements, some with WITH GRANT OPTION, some without", func() { |
| tableMetadata := backup.ObjectMetadata{Privileges: []backup.ACL{hasAllPrivileges, hasMostPrivilegesWithGrant}} |
| backup.PrintObjectMetadata(backupfile, tocfile, tableMetadata, table, "", []uint32{0, 0}) |
| testhelper.ExpectRegexp(buffer, ` |
| |
| REVOKE ALL ON TABLE public.tablename FROM PUBLIC; |
| GRANT ALL ON TABLE public.tablename TO anothertestrole; |
| GRANT SELECT,INSERT,UPDATE,DELETE,TRUNCATE,REFERENCES ON TABLE public.tablename TO testrole WITH GRANT OPTION;`) |
| }) |
| It("prints both an ALTER TABLE ... OWNER TO statement and a table comment", func() { |
| tableMetadata := backup.ObjectMetadata{Comment: "This is a table comment.", Owner: "testrole"} |
| backup.PrintObjectMetadata(backupfile, tocfile, tableMetadata, table, "", []uint32{0, 0}) |
| testhelper.ExpectRegexp(buffer, ` |
| |
| COMMENT ON TABLE public.tablename IS 'This is a table comment.'; |
| |
| |
| ALTER TABLE public.tablename OWNER TO testrole;`) |
| }) |
| It("prints both a block of REVOKE and GRANT statements and an ALTER TABLE ... OWNER TO statement", func() { |
| tableMetadata := backup.ObjectMetadata{Privileges: privileges, Owner: "testrole"} |
| backup.PrintObjectMetadata(backupfile, tocfile, tableMetadata, table, "", []uint32{0, 0}) |
| testhelper.ExpectRegexp(buffer, ` |
| |
| ALTER TABLE public.tablename OWNER TO testrole; |
| |
| |
| REVOKE ALL ON TABLE public.tablename FROM PUBLIC; |
| REVOKE ALL ON TABLE public.tablename FROM testrole; |
| GRANT ALL ON TABLE public.tablename TO anothertestrole; |
| GRANT SELECT,INSERT,UPDATE,DELETE,TRUNCATE,REFERENCES ON TABLE public.tablename TO testrole; |
| GRANT TRIGGER ON TABLE public.tablename TO PUBLIC;`) |
| }) |
| It("prints both a block of REVOKE and GRANT statements and a table comment", func() { |
| tableMetadata := backup.ObjectMetadata{Privileges: privileges, Comment: "This is a table comment."} |
| backup.PrintObjectMetadata(backupfile, tocfile, tableMetadata, table, "", []uint32{0, 0}) |
| testhelper.ExpectRegexp(buffer, ` |
| |
| COMMENT ON TABLE public.tablename IS 'This is a table comment.'; |
| |
| |
| REVOKE ALL ON TABLE public.tablename FROM PUBLIC; |
| GRANT ALL ON TABLE public.tablename TO anothertestrole; |
| GRANT SELECT,INSERT,UPDATE,DELETE,TRUNCATE,REFERENCES ON TABLE public.tablename TO testrole; |
| GRANT TRIGGER ON TABLE public.tablename TO PUBLIC;`) |
| }) |
| It("prints REVOKE and GRANT statements, an ALTER TABLE ... OWNER TO statement, and comments", func() { |
| tableMetadata := backup.ObjectMetadata{Privileges: privileges, Owner: "testrole", Comment: "This is a table comment."} |
| backup.PrintObjectMetadata(backupfile, tocfile, tableMetadata, table, "", []uint32{0, 0}) |
| testhelper.ExpectRegexp(buffer, ` |
| |
| COMMENT ON TABLE public.tablename IS 'This is a table comment.'; |
| |
| |
| ALTER TABLE public.tablename OWNER TO testrole; |
| |
| |
| REVOKE ALL ON TABLE public.tablename FROM PUBLIC; |
| REVOKE ALL ON TABLE public.tablename FROM testrole; |
| GRANT ALL ON TABLE public.tablename TO anothertestrole; |
| GRANT SELECT,INSERT,UPDATE,DELETE,TRUNCATE,REFERENCES ON TABLE public.tablename TO testrole; |
| GRANT TRIGGER ON TABLE public.tablename TO PUBLIC;`) |
| }) |
| It("prints SERVER for ALTER and FOREIGN SERVER for GRANT/REVOKE for a foreign server", func() { |
| server := backup.ForeignServer{Name: "foreignserver"} |
| serverPrivileges := testutils.DefaultACLForType("testrole", toc.OBJ_FOREIGN_SERVER) |
| serverMetadata := backup.ObjectMetadata{Privileges: []backup.ACL{serverPrivileges}, Owner: "testrole"} |
| backup.PrintObjectMetadata(backupfile, tocfile, serverMetadata, server, "", []uint32{0, 0}) |
| testhelper.ExpectRegexp(buffer, ` |
| |
| ALTER SERVER foreignserver OWNER TO testrole; |
| |
| |
| REVOKE ALL ON FOREIGN SERVER foreignserver FROM PUBLIC; |
| REVOKE ALL ON FOREIGN SERVER foreignserver FROM testrole; |
| GRANT ALL ON FOREIGN SERVER foreignserver TO testrole;`) |
| }) |
| It("prints FUNCTION for GRANT/REVOKE and AGGREGATE for ALTER for an aggregate function", func() { |
| aggregate := backup.Aggregate{Schema: "public", Name: "testagg"} |
| aggregatePrivileges := testutils.DefaultACLForType("testrole", toc.OBJ_AGGREGATE) |
| aggregateMetadata := backup.ObjectMetadata{Privileges: []backup.ACL{aggregatePrivileges}, Owner: "testrole"} |
| backup.PrintObjectMetadata(backupfile, tocfile, aggregateMetadata, aggregate, "", []uint32{0, 0}) |
| testhelper.ExpectRegexp(buffer, ` |
| |
| ALTER AGGREGATE public.testagg(*) OWNER TO testrole; |
| |
| |
| REVOKE ALL ON FUNCTION public.testagg(*) FROM PUBLIC; |
| REVOKE ALL ON FUNCTION public.testagg(*) FROM testrole; |
| GRANT ALL ON FUNCTION public.testagg(*) TO testrole;`) |
| }) |
| It("prints TABLE for a block of REVOKE and GRANT statements for a foreign table", func() { |
| table := backup.Table{Relation: backup.Relation{Schema: "public", Name: "foreigntablename"}} |
| foreignDef := backup.ForeignTableDefinition{Oid: 23, Options: "", Server: "fs"} |
| table.ForeignDef = foreignDef |
| tableMetadata := backup.ObjectMetadata{Privileges: privileges} |
| backup.PrintObjectMetadata(backupfile, tocfile, tableMetadata, table, "", []uint32{0, 0}) |
| testhelper.ExpectRegexp(buffer, ` |
| |
| REVOKE ALL ON TABLE public.foreigntablename FROM PUBLIC; |
| GRANT ALL ON TABLE public.foreigntablename TO anothertestrole; |
| GRANT SELECT,INSERT,UPDATE,DELETE,TRUNCATE,REFERENCES ON TABLE public.foreigntablename TO testrole; |
| GRANT TRIGGER ON TABLE public.foreigntablename TO PUBLIC;`) |
| }) |
| It("prints TABLE for a block of REVOKE and GRANT statements for a view", func() { |
| view := backup.View{Schema: "public", Name: "viewname"} |
| viewMetadata := backup.ObjectMetadata{Privileges: privileges} |
| backup.PrintObjectMetadata(backupfile, tocfile, viewMetadata, view, "", []uint32{0, 0}) |
| testhelper.ExpectRegexp(buffer, ` |
| |
| REVOKE ALL ON TABLE public.viewname FROM PUBLIC; |
| GRANT ALL ON TABLE public.viewname TO anothertestrole; |
| GRANT SELECT,INSERT,UPDATE,DELETE,TRUNCATE,REFERENCES ON TABLE public.viewname TO testrole; |
| GRANT TRIGGER ON TABLE public.viewname TO PUBLIC;`) |
| }) |
| It("prints TABLE for a block of REVOKE and GRANT statements for a materialized view", func() { |
| view := backup.View{Schema: "public", Name: "matviewname", IsMaterialized: true} |
| viewMetadata := backup.ObjectMetadata{Privileges: privileges} |
| backup.PrintObjectMetadata(backupfile, tocfile, viewMetadata, view, "", []uint32{0, 0}) |
| testhelper.ExpectRegexp(buffer, ` |
| |
| REVOKE ALL ON TABLE public.matviewname FROM PUBLIC; |
| GRANT ALL ON TABLE public.matviewname TO anothertestrole; |
| GRANT SELECT,INSERT,UPDATE,DELETE,TRUNCATE,REFERENCES ON TABLE public.matviewname TO testrole; |
| GRANT TRIGGER ON TABLE public.matviewname TO PUBLIC;`) |
| }) |
| Context("Views and sequences have owners", func() { |
| view := backup.View{Schema: "public", Name: "viewname"} |
| sequence := backup.Sequence{Relation: backup.Relation{Schema: "public", Name: "sequencename"}} |
| objectMetadata := backup.ObjectMetadata{Owner: "testrole"} |
| |
| It("prints an ALTER TABLE ... OWNER TO statement to set the owner for a sequence", func() { |
| expectedKeyword := `TABLE` |
| if (connectionPool.Version.IsGPDB() && connectionPool.Version.AtLeast("6")) || connectionPool.Version.IsCBDB() { |
| expectedKeyword = `SEQUENCE` |
| } |
| |
| backup.PrintObjectMetadata(backupfile, tocfile, objectMetadata, sequence, "public.sequencename", []uint32{0, 0}) |
| testhelper.ExpectRegexp(buffer, fmt.Sprintf(` |
| |
| ALTER %s public.sequencename OWNER TO testrole;`, expectedKeyword)) |
| }) |
| It("prints an ALTER TABLE ... OWNER TO statement to set the owner for a view", func() { |
| expectedKeyword := `TABLE` |
| if (connectionPool.Version.IsGPDB() && connectionPool.Version.AtLeast("6")) || connectionPool.Version.IsCBDB() { |
| expectedKeyword = `VIEW` |
| } |
| |
| backup.PrintObjectMetadata(backupfile, tocfile, objectMetadata, view, "public.viewname", []uint32{0, 0}) |
| testhelper.ExpectRegexp(buffer, fmt.Sprintf(` |
| |
| ALTER %s public.viewname OWNER TO testrole;`, expectedKeyword)) |
| }) |
| }) |
| }) |
| Describe("PrintDefaultPrivilegeStatements", func() { |
| privs := []backup.ACL{{Grantee: "", Usage: true}} |
| It("prints ALTER DEFAULT PRIVILEGES statement for relation", func() { |
| defaultPrivileges := []backup.DefaultPrivileges{{Owner: "testrole", Schema: "", Privileges: privs, ObjectType: "r"}} |
| backup.PrintDefaultPrivilegesStatements(backupfile, tocfile, defaultPrivileges) |
| testhelper.ExpectRegexp(buffer, ` |
| ALTER DEFAULT PRIVILEGES FOR ROLE testrole REVOKE ALL ON TABLES FROM PUBLIC; |
| ALTER DEFAULT PRIVILEGES FOR ROLE testrole REVOKE ALL ON TABLES FROM testrole; |
| ALTER DEFAULT PRIVILEGES FOR ROLE testrole GRANT USAGE ON TABLES TO PUBLIC; |
| `) |
| }) |
| It("prints ALTER DEFAULT PRIVILEGES statement for sequence", func() { |
| defaultPrivileges := []backup.DefaultPrivileges{{Owner: "testrole", Schema: "", Privileges: privs, ObjectType: "S"}} |
| backup.PrintDefaultPrivilegesStatements(backupfile, tocfile, defaultPrivileges) |
| testhelper.ExpectRegexp(buffer, ` |
| ALTER DEFAULT PRIVILEGES FOR ROLE testrole REVOKE ALL ON SEQUENCES FROM PUBLIC; |
| ALTER DEFAULT PRIVILEGES FOR ROLE testrole REVOKE ALL ON SEQUENCES FROM testrole; |
| ALTER DEFAULT PRIVILEGES FOR ROLE testrole GRANT USAGE ON SEQUENCES TO PUBLIC; |
| `) |
| }) |
| It("prints ALTER DEFAULT PRIVILEGES statement for function", func() { |
| defaultPrivileges := []backup.DefaultPrivileges{{Owner: "testrole", Schema: "", Privileges: privs, ObjectType: "f"}} |
| backup.PrintDefaultPrivilegesStatements(backupfile, tocfile, defaultPrivileges) |
| testhelper.ExpectRegexp(buffer, ` |
| ALTER DEFAULT PRIVILEGES FOR ROLE testrole REVOKE ALL ON FUNCTIONS FROM PUBLIC; |
| ALTER DEFAULT PRIVILEGES FOR ROLE testrole REVOKE ALL ON FUNCTIONS FROM testrole; |
| ALTER DEFAULT PRIVILEGES FOR ROLE testrole GRANT USAGE ON FUNCTIONS TO PUBLIC; |
| `) |
| }) |
| It("prints ALTER DEFAULT PRIVILEGES statement for type", func() { |
| defaultPrivileges := []backup.DefaultPrivileges{{Owner: "testrole", Schema: "", Privileges: privs, ObjectType: "T"}} |
| backup.PrintDefaultPrivilegesStatements(backupfile, tocfile, defaultPrivileges) |
| testhelper.ExpectRegexp(buffer, ` |
| ALTER DEFAULT PRIVILEGES FOR ROLE testrole REVOKE ALL ON TYPES FROM PUBLIC; |
| ALTER DEFAULT PRIVILEGES FOR ROLE testrole REVOKE ALL ON TYPES FROM testrole; |
| ALTER DEFAULT PRIVILEGES FOR ROLE testrole GRANT ALL ON TYPES TO PUBLIC; |
| `) |
| }) |
| It("prints ALTER DEFAULT PRIVILEGES statement for role", func() { |
| localPrivs := []backup.ACL{{Grantee: "somerole", Usage: true}} |
| defaultPrivileges := []backup.DefaultPrivileges{{Schema: "", Owner: "somerole", Privileges: localPrivs, ObjectType: "r"}} |
| backup.PrintDefaultPrivilegesStatements(backupfile, tocfile, defaultPrivileges) |
| testhelper.ExpectRegexp(buffer, ` |
| ALTER DEFAULT PRIVILEGES FOR ROLE somerole REVOKE ALL ON TABLES FROM PUBLIC; |
| ALTER DEFAULT PRIVILEGES FOR ROLE somerole REVOKE ALL ON TABLES FROM somerole; |
| ALTER DEFAULT PRIVILEGES FOR ROLE somerole GRANT USAGE ON TABLES TO somerole; |
| `) |
| }) |
| It("prints ALTER DEFAULT PRIVILEGES statement in schema", func() { |
| defaultPrivileges := []backup.DefaultPrivileges{{Owner: "testrole", Schema: "myschema", Privileges: privs, ObjectType: "r"}} |
| backup.PrintDefaultPrivilegesStatements(backupfile, tocfile, defaultPrivileges) |
| testhelper.ExpectRegexp(buffer, ` |
| ALTER DEFAULT PRIVILEGES FOR ROLE testrole IN SCHEMA myschema REVOKE ALL ON TABLES FROM PUBLIC; |
| ALTER DEFAULT PRIVILEGES FOR ROLE testrole IN SCHEMA myschema REVOKE ALL ON TABLES FROM testrole; |
| ALTER DEFAULT PRIVILEGES FOR ROLE testrole IN SCHEMA myschema GRANT USAGE ON TABLES TO PUBLIC; |
| `) |
| }) |
| It("prints ALTER DEFAULT PRIVILEGES statement for role in schema", func() { |
| localPrivs := []backup.ACL{{Grantee: "somerole", Usage: true}} |
| defaultPrivileges := []backup.DefaultPrivileges{{Schema: "myschema", Owner: "somerole", Privileges: localPrivs, ObjectType: "r"}} |
| backup.PrintDefaultPrivilegesStatements(backupfile, tocfile, defaultPrivileges) |
| testhelper.ExpectRegexp(buffer, ` |
| ALTER DEFAULT PRIVILEGES FOR ROLE somerole IN SCHEMA myschema REVOKE ALL ON TABLES FROM PUBLIC; |
| ALTER DEFAULT PRIVILEGES FOR ROLE somerole IN SCHEMA myschema REVOKE ALL ON TABLES FROM somerole; |
| ALTER DEFAULT PRIVILEGES FOR ROLE somerole IN SCHEMA myschema GRANT USAGE ON TABLES TO somerole; |
| `) |
| }) |
| It("prints ALTER DEFAULT PRIVILEGES statement with grant option", func() { |
| localPrivs := []backup.ACL{{Grantee: "somerole", Usage: true, UsageWithGrant: true}} |
| defaultPrivileges := []backup.DefaultPrivileges{{Owner: "testrole", Schema: "", Privileges: localPrivs, ObjectType: "r"}} |
| backup.PrintDefaultPrivilegesStatements(backupfile, tocfile, defaultPrivileges) |
| testhelper.ExpectRegexp(buffer, ` |
| ALTER DEFAULT PRIVILEGES FOR ROLE testrole REVOKE ALL ON TABLES FROM PUBLIC; |
| ALTER DEFAULT PRIVILEGES FOR ROLE testrole REVOKE ALL ON TABLES FROM testrole; |
| ALTER DEFAULT PRIVILEGES FOR ROLE testrole GRANT USAGE ON TABLES TO somerole; |
| ALTER DEFAULT PRIVILEGES FOR ROLE testrole GRANT USAGE ON TABLES TO somerole WITH GRANT OPTION; |
| `) |
| }) |
| }) |
| Describe("ConstructMetadataMap", func() { |
| object1A := backup.MetadataQueryStruct{UniqueID: backup.UniqueID{Oid: 1}, Privileges: sql.NullString{String: "gpadmin=r/gpadmin", Valid: true}, Kind: "", Owner: "testrole", Comment: ""} |
| object1B := backup.MetadataQueryStruct{UniqueID: backup.UniqueID{Oid: 1}, Privileges: sql.NullString{String: "testrole=r/testrole", Valid: true}, Kind: "", Owner: "testrole", Comment: ""} |
| object2 := backup.MetadataQueryStruct{UniqueID: backup.UniqueID{Oid: 2}, Privileges: sql.NullString{String: "testrole=r/testrole", Valid: true}, Kind: "", Owner: "testrole", Comment: "this is a comment", SecurityLabelProvider: "some_provider", SecurityLabel: "some_label"} |
| objectDefaultKind := backup.MetadataQueryStruct{UniqueID: backup.UniqueID{Oid: 3}, Privileges: sql.NullString{String: "", Valid: false}, Kind: "Default", Owner: "testrole", Comment: ""} |
| objectEmptyKind := backup.MetadataQueryStruct{UniqueID: backup.UniqueID{Oid: 4}, Privileges: sql.NullString{String: "", Valid: false}, Kind: "Empty", Owner: "testrole", Comment: ""} |
| var metadataList []backup.MetadataQueryStruct |
| BeforeEach(func() { |
| rolnames := sqlmock.NewRows([]string{"rolename", "quotedrolename"}). |
| AddRow("gpadmin", "gpadmin"). |
| AddRow("testrole", "testrole") |
| mock.ExpectQuery("SELECT rolname (.*)"). |
| WillReturnRows(rolnames) |
| metadataList = []backup.MetadataQueryStruct{} |
| }) |
| It("No objects", func() { |
| metadataMap := backup.ConstructMetadataMap(metadataList) |
| Expect(metadataMap).To(BeEmpty()) |
| }) |
| It("One object", func() { |
| metadataList = []backup.MetadataQueryStruct{object2} |
| metadataMap := backup.ConstructMetadataMap(metadataList) |
| expectedObjectMetadata := backup.ObjectMetadata{Privileges: []backup.ACL{{Grantee: "testrole", Select: true}}, Owner: "testrole", Comment: "this is a comment", SecurityLabelProvider: "some_provider", SecurityLabel: "some_label"} |
| Expect(metadataMap).To(HaveLen(1)) |
| Expect(metadataMap[backup.UniqueID{Oid: 2}]).To(Equal(expectedObjectMetadata)) |
| |
| }) |
| It("One object with two ACL entries", func() { |
| metadataList = []backup.MetadataQueryStruct{object1A, object1B} |
| metadataMap := backup.ConstructMetadataMap(metadataList) |
| expectedObjectMetadata := backup.ObjectMetadata{Privileges: []backup.ACL{{Grantee: "gpadmin", Select: true}, {Grantee: "testrole", Select: true}}, Owner: "testrole"} |
| Expect(metadataMap).To(HaveLen(1)) |
| Expect(metadataMap[backup.UniqueID{Oid: 1}]).To(Equal(expectedObjectMetadata)) |
| }) |
| It("Multiple objects", func() { |
| metadataList = []backup.MetadataQueryStruct{object1A, object1B, object2} |
| metadataMap := backup.ConstructMetadataMap(metadataList) |
| expectedObjectMetadataOne := backup.ObjectMetadata{Privileges: []backup.ACL{{Grantee: "gpadmin", Select: true}, {Grantee: "testrole", Select: true}}, Owner: "testrole"} |
| expectedObjectMetadataTwo := backup.ObjectMetadata{Privileges: []backup.ACL{{Grantee: "testrole", Select: true}}, Owner: "testrole", Comment: "this is a comment", SecurityLabelProvider: "some_provider", SecurityLabel: "some_label"} |
| Expect(metadataMap).To(HaveLen(2)) |
| Expect(metadataMap[backup.UniqueID{Oid: 1}]).To(Equal(expectedObjectMetadataOne)) |
| Expect(metadataMap[backup.UniqueID{Oid: 2}]).To(Equal(expectedObjectMetadataTwo)) |
| }) |
| It("Default Kind", func() { |
| metadataList = []backup.MetadataQueryStruct{objectDefaultKind} |
| metadataMap := backup.ConstructMetadataMap(metadataList) |
| expectedObjectMetadata := backup.ObjectMetadata{Privileges: []backup.ACL{}, Owner: "testrole"} |
| Expect(metadataMap).To(HaveLen(1)) |
| Expect(metadataMap[backup.UniqueID{Oid: 3}]).To(Equal(expectedObjectMetadata)) |
| }) |
| It("'Empty' Kind", func() { |
| metadataList = []backup.MetadataQueryStruct{objectEmptyKind} |
| metadataMap := backup.ConstructMetadataMap(metadataList) |
| expectedObjectMetadata := backup.ObjectMetadata{Privileges: []backup.ACL{{Grantee: "GRANTEE"}}, Owner: "testrole"} |
| Expect(metadataMap).To(HaveLen(1)) |
| Expect(metadataMap[backup.UniqueID{Oid: 4}]).To(Equal(expectedObjectMetadata)) |
| }) |
| }) |
| Describe("ParseACL", func() { |
| var quotedRoleNames map[string]string |
| BeforeEach(func() { |
| quotedRoleNames = map[string]string{ |
| "testrole": "testrole", |
| "Test|role": `"Test|role"`, |
| } |
| backup.SetQuotedRoleNames(quotedRoleNames) |
| }) |
| It("parses an ACL string representing default privileges", func() { |
| aclStr := "" |
| result := backup.ParseACL(aclStr) |
| Expect(result).To(BeNil()) |
| }) |
| It("parses an ACL string representing no privileges", func() { |
| aclStr := "GRANTEE=/GRANTOR" |
| expected := backup.ACL{Grantee: "GRANTEE"} |
| result := backup.ParseACL(aclStr) |
| structmatcher.ExpectStructsToMatch(&expected, result) |
| }) |
| It("parses an ACL string containing a role with multiple privileges", func() { |
| aclStr := "testrole=arwdDxt/gpadmin" |
| expected := testutils.DefaultACLForType("testrole", toc.OBJ_TABLE) |
| result := backup.ParseACL(aclStr) |
| structmatcher.ExpectStructsToMatch(&expected, result) |
| }) |
| It("parses an ACL string containing a role with one privilege", func() { |
| aclStr := "testrole=a/gpadmin" |
| expected := backup.ACL{Grantee: "testrole", Insert: true} |
| result := backup.ParseACL(aclStr) |
| structmatcher.ExpectStructsToMatch(&expected, result) |
| }) |
| It("parses an ACL string containing a role name with special characters", func() { |
| aclStr := `Test|role=a/gpadmin` |
| expected := backup.ACL{Grantee: `"Test|role"`, Insert: true} |
| result := backup.ParseACL(aclStr) |
| structmatcher.ExpectStructsToMatch(&expected, result) |
| }) |
| It("parses an ACL string containing a role with some privileges with GRANT and some without including GRANT", func() { |
| aclStr := "testrole=ar*w*d*tXUCTc/gpadmin" |
| expected := backup.ACL{Grantee: "testrole", Insert: true, SelectWithGrant: true, UpdateWithGrant: true, |
| DeleteWithGrant: true, Trigger: true, Execute: true, Usage: true, Create: true, Temporary: true, Connect: true} |
| result := backup.ParseACL(aclStr) |
| structmatcher.ExpectStructsToMatch(&expected, result) |
| }) |
| It("parses an ACL string containing a role with all privileges including GRANT", func() { |
| aclStr := "testrole=a*D*x*t*X*U*C*T*c*/gpadmin" |
| expected := backup.ACL{Grantee: "testrole", InsertWithGrant: true, TruncateWithGrant: true, ReferencesWithGrant: true, |
| TriggerWithGrant: true, ExecuteWithGrant: true, UsageWithGrant: true, CreateWithGrant: true, TemporaryWithGrant: true, ConnectWithGrant: true} |
| result := backup.ParseACL(aclStr) |
| structmatcher.ExpectStructsToMatch(&expected, result) |
| }) |
| It("parses an ACL string granting privileges to PUBLIC", func() { |
| aclStr := "=a/gpadmin" |
| expected := backup.ACL{Grantee: "", Insert: true} |
| result := backup.ParseACL(aclStr) |
| structmatcher.ExpectStructsToMatch(&expected, result) |
| }) |
| }) |
| Describe("ConstructDefaultPrivileges", func() { |
| object1A := backup.DefaultPrivilegesQueryStruct{Oid: 1, Owner: "testrole", Schema: "myschema", Kind: "", ObjectType: "r", Privileges: sql.NullString{String: "gpadmin=r/gpadmin", Valid: true}} |
| object1B := backup.DefaultPrivilegesQueryStruct{Oid: 1, Owner: "testrole", Schema: "myschema", Kind: "", ObjectType: "r", Privileges: sql.NullString{String: "testrole=r/testrole", Valid: true}} |
| object2 := backup.DefaultPrivilegesQueryStruct{Oid: 2, Owner: "testrole", Schema: "myschema", Kind: "", ObjectType: "S", Privileges: sql.NullString{String: "testrole=r/testrole", Valid: true}} |
| objectDefaultKind := backup.DefaultPrivilegesQueryStruct{Oid: 3, Owner: "testrole", Schema: "", Kind: "Default", ObjectType: "T", Privileges: sql.NullString{String: "", Valid: false}} |
| objectEmptyKind := backup.DefaultPrivilegesQueryStruct{Oid: 4, Owner: "testrole", Schema: "", Kind: "Empty", ObjectType: "f", Privileges: sql.NullString{String: "", Valid: false}} |
| var privilegesQuerylist []backup.DefaultPrivilegesQueryStruct |
| BeforeEach(func() { |
| rolnames := sqlmock.NewRows([]string{"rolename", "quotedrolename"}). |
| AddRow("gpadmin", "gpadmin"). |
| AddRow("testrole", "testrole") |
| mock.ExpectQuery("SELECT rolname (.*)"). |
| WillReturnRows(rolnames) |
| privilegesQuerylist = []backup.DefaultPrivilegesQueryStruct{} |
| }) |
| It("returns no privileges when no default privileges exist", func() { |
| privilegesList := backup.ConstructDefaultPrivileges(privilegesQuerylist) |
| Expect(privilegesList).To(BeEmpty()) |
| }) |
| It("constructs a single sequence default privilege in a specific schema", func() { |
| privilegesQuerylist = []backup.DefaultPrivilegesQueryStruct{object2} |
| privilegesList := backup.ConstructDefaultPrivileges(privilegesQuerylist) |
| expectedDefaultPrivileges := backup.DefaultPrivileges{Privileges: []backup.ACL{{Grantee: "testrole", Select: true}}, Owner: "testrole", Schema: "myschema", ObjectType: "S"} |
| Expect(privilegesList).To(HaveLen(1)) |
| Expect(privilegesList[0]).To(Equal(expectedDefaultPrivileges)) |
| }) |
| It("constructs multiple default privileges on a single relation in a specific schema", func() { |
| privilegesQuerylist = []backup.DefaultPrivilegesQueryStruct{object1A, object1B} |
| privilegesList := backup.ConstructDefaultPrivileges(privilegesQuerylist) |
| expectedObjectMetadata := backup.DefaultPrivileges{Privileges: []backup.ACL{{Grantee: "gpadmin", Select: true}, {Grantee: "testrole", Select: true}}, Owner: "testrole", Schema: "myschema", ObjectType: "r"} |
| Expect(privilegesList).To(HaveLen(1)) |
| Expect(privilegesList[0]).To(Equal(expectedObjectMetadata)) |
| }) |
| It("constructs multiple default privileges on multiple objects in a specific schema", func() { |
| privilegesQuerylist = []backup.DefaultPrivilegesQueryStruct{object1A, object1B, object2} |
| privilegesList := backup.ConstructDefaultPrivileges(privilegesQuerylist) |
| expectedObjectMetadataOne := backup.DefaultPrivileges{Privileges: []backup.ACL{{Grantee: "gpadmin", Select: true}, {Grantee: "testrole", Select: true}}, Owner: "testrole", Schema: "myschema", ObjectType: "r"} |
| expectedObjectMetadataTwo := backup.DefaultPrivileges{Privileges: []backup.ACL{{Grantee: "testrole", Select: true}}, Owner: "testrole", Schema: "myschema", ObjectType: "S"} |
| Expect(privilegesList).To(HaveLen(2)) |
| Expect(privilegesList[0]).To(Equal(expectedObjectMetadataOne)) |
| Expect(privilegesList[1]).To(Equal(expectedObjectMetadataTwo)) |
| }) |
| It("constructs a default privilege for a type with a 'Default' kind", func() { |
| privilegesQuerylist = []backup.DefaultPrivilegesQueryStruct{objectDefaultKind} |
| privilegesList := backup.ConstructDefaultPrivileges(privilegesQuerylist) |
| expectedObjectMetadata := backup.DefaultPrivileges{Privileges: []backup.ACL{}, Owner: "testrole", Schema: "", ObjectType: "T"} |
| Expect(privilegesList).To(HaveLen(1)) |
| Expect(privilegesList[0]).To(Equal(expectedObjectMetadata)) |
| }) |
| It("constructs a default privilege for a function with an 'Empty' kind", func() { |
| privilegesQuerylist = []backup.DefaultPrivilegesQueryStruct{objectEmptyKind} |
| privilegesList := backup.ConstructDefaultPrivileges(privilegesQuerylist) |
| expectedObjectMetadata := backup.DefaultPrivileges{Privileges: []backup.ACL{{Grantee: "GRANTEE"}}, Owner: "testrole", Schema: "", ObjectType: "f"} |
| Expect(privilegesList).To(HaveLen(1)) |
| Expect(privilegesList[0]).To(Equal(expectedObjectMetadata)) |
| }) |
| }) |
| }) |