Repository: prest/prest
Pull request #482 (2020-12-11 17:50:45)

access ignore table configuration
if permission system is active it was obliging to create configuration for all tables, if it doesn't have configuration for the table it will have access normally - obliging to write configuration for the table that wants to change the behavior



Patch:
diff --git a/adapters/postgres/postgres.go b/adapters/postgres/postgres.go
index 3152648..b56ad14 100644
--- a/adapters/postgres/postgres.go
+++ b/adapters/postgres/postgres.go
@@ -1065,10 +1065,18 @@ func GetQueryOperator(op string) (string, error) {
 }
 
 // TablePermissions get tables permissions based in prest configuration
-func (adapter *Postgres) TablePermissions(table string, op string) bool {
+func (adapter *Postgres) TablePermissions(table string, op string) (access bool) {
+	access = false
 	restrict := config.PrestConf.AccessConf.Restrict
 	if !restrict {
-		return true
+		access = true
+	}
+
+	// ignore table loop
+	for _, ignoreT := range config.PrestConf.AccessConf.IgnoreTable {
+		if ignoreT == table {
+			access = true
+		}
 	}
 
 	tables := config.PrestConf.AccessConf.Tables
@@ -1076,12 +1084,12 @@ func (adapter *Postgres) TablePermissions(table string, op string) bool {
 		if t.Name == table {
 			for _, p := range t.Permissions {
 				if p == op {
-					return true
+					access = true
 				}
 			}
 		}
 	}
-	return false
+	return
 }
 
 func fieldsByPermission(table, op string) (fields []string) {
@@ -1095,6 +1103,9 @@ func fieldsByPermission(table, op string) (fields []string) {
 			}
 		}
 	}
+	if len(fields) == 0 {
+		fields = []string{"*"}
+	}
 	return
 }
 
@@ -1135,8 +1146,7 @@ func (adapter *Postgres) FieldsPermissions(r *http.Request, table string, op str
 	}
 	allowedFields := fieldsByPermission(table, op)
 	if len(allowedFields) == 0 {
-		err = errors.New("there's no configured field for this table")
-		return
+		allowedFields = []string{"*"}
 	}
 	if containsAsterisk(allowedFields) {
 		fields = []string{"*"}
@@ -1404,8 +1414,8 @@ func (adapter *Postgres) ShowTable(schema, table string) adapters.Scanner {
 			  	is_nullable,
 			  	is_generated,
 			  	is_updatable,
-			  	column_default as default_value 
-			 FROM information_schema.columns 
+			  	column_default as default_value
+			 FROM information_schema.columns
 			 WHERE table_name=$1 AND table_schema=$2
 			 ORDER BY table_schema, table_name, ordinal_position`
 	return adapter.Query(query, table, schema)
diff --git a/config/config.go b/config/config.go
index 6031f9e..d71fac3 100644
--- a/config/config.go
+++ b/config/config.go
@@ -23,8 +23,9 @@ type TablesConf struct {
 
 // AccessConf informations
 type AccessConf struct {
-	Restrict bool
-	Tables   []TablesConf
+	Restrict    bool
+	IgnoreTable []string
+	Tables      []TablesConf
 }
 
 // Prest basic config
@@ -186,6 +187,7 @@ func Parse(cfg *Prest) (err error) {
 	cfg.JWTWhiteList = viper.GetStringSlice("jwt.whitelist")
 	cfg.MigrationsPath = viper.GetString("migrations")
 	cfg.AccessConf.Restrict = viper.GetBool("access.restrict")
+	cfg.AccessConf.IgnoreTable = viper.GetStringSlice("access.ignore_table")
 	cfg.QueriesPath = viper.GetString("queries.location")
 	cfg.CORSAllowOrigin = viper.GetStringSlice("cors.alloworigin")
 	cfg.CORSAllowHeaders = viper.GetStringSlice("cors.allowheaders")
diff --git a/docs/permissions/_index.en.md b/docs/permissions/_index.en.md
index d50f560..a19fa90 100644
--- a/docs/permissions/_index.en.md
+++ b/docs/permissions/_index.en.md
@@ -17,6 +17,18 @@ restrict = true  # can access only the tables listed below
 
 `restrict = true`: you need configure the permissions of all tables.
 
+### Ignore table
+
+If you need to ignore restricted access mode for some table you can use the `ignore_table` option, it receives a string list with the names of the tables to be _"ignored"_.
+
+by **default** is an empty list `[]`.
+
+```
+[access]
+restrict = true
+ignore_table = ["news"]
+```
+
 ### Table permissions
 
 Example:
@@ -34,22 +46,21 @@ Multiple configurations for the same table:
 [access]
 restrict = true  # can access only the tables listed below
 
-    [[access.tables]]
-    name = "test"
-    permissions = ["read"]
-    fields = ["id", "name"]
-
-    [[access.tables]]
-    name = "test"
-    permissions = ["write"]
-    fields = ["name"]
+[[access.tables]]
+name = "test"
+permissions = ["read"]
+fields = ["id", "name"]
+[[access.tables]]
+name = "test"
+permissions = ["write"]
+fields = ["name"]
 ```
 
-|attribute|description|
-|---|---|
-|name|Table name|
-|permissions|Table permissions. Options: `read`, `write` and `delete`|
-|fields|Fields permitted for operations|
+| attribute   | description                                              |
+| ----------- | -------------------------------------------------------- |
+| name        | Table name                                               |
+| permissions | Table permissions. Options: `read`, `write` and `delete` |
+| fields      | Fields permitted for operations                          |
 
 
 Configuration example: [prest.toml](https://github.com/prest/prest/blob/master/testdata/prest.toml)


Test patch:
diff --git a/adapters/postgres/postgres_test.go b/adapters/postgres/postgres_test.go
index d6c8b79..66d2b8c 100644
--- a/adapters/postgres/postgres_test.go
+++ b/adapters/postgres/postgres_test.go
@@ -872,6 +872,7 @@ func TestTablePermissions(t *testing.T) {
 		{"Try to write without permission", "test_readonly_access", "write", false},
 		{"Delete", "test_write_and_delete_access", "delete", true},
 		{"Try to delete without permission", "test_readonly_access", "delete", false},
+		{"Try config does not write", "test_permission_does_not_exist", "read", true},
 	}
 
 	for _, tc := range testCases {
diff --git a/adapters/testdata/prest.toml b/adapters/testdata/prest.toml
index 465cad4..f0334ba 100644
--- a/adapters/testdata/prest.toml
+++ b/adapters/testdata/prest.toml
@@ -12,6 +12,7 @@ database = "prest"
 
 [access]
 restrict = true  # can access only the tables listed below
+ignore_table = ["test_permission_does_not_exist"]
 
     [[access.tables]]
     name = "test"
@@ -70,4 +71,4 @@ restrict = true  # can access only the tables listed below
     [[access.tables]]
     name = "test_group_by_table"
     permissions = ["read"]
-    fields = ["id", "name", "age", "salary"]
\ No newline at end of file
+    fields = ["id", "name", "age", "salary"]
diff --git a/adapters/testdata/schema.sql b/adapters/testdata/schema.sql
index 6d8cf10..3d8b0d6 100644
--- a/adapters/testdata/schema.sql
+++ b/adapters/testdata/schema.sql
@@ -18,6 +18,7 @@ CREATE TABLE testarray(id serial, data character varying(250)[]);
 CREATE TABLE test_empty_table(id serial, data character varying(250)[]);
 CREATE TABLE test_group_by_table(id serial, name text, age integer, salary int);
 CREATE TABLE test_multiple_fields(created_at timestamp);
+CREATE TABLE test_permission_does_not_exist(created_at timestamp);
 
 -- Inserts
 INSERT INTO test (name) VALUES ('prest tester');
@@ -42,6 +43,8 @@ INSERT INTO test_group_by_table(name, age, salary) VALUES ('guitarra humana', 19
 
 INSERT INTO test_multiple_fields(created_at) VALUES ('1997-12-17 07:37:16-08');
 
+INSERT INTO test_permission_does_not_exist(created_at) VALUES ('2020-12-11 14:42:16-08');
+
 -- Views
 CREATE TABLE table_to_view(id serial, name text, celphone text);
 INSERT INTO table_to_view (name, celphone) VALUES ('gopher', '8888888');
diff --git a/config/config_test.go b/config/config_test.go
index 805f76a..b4158e4 100644
--- a/config/config_test.go
+++ b/config/config_test.go
@@ -15,6 +15,13 @@ func TestLoad(t *testing.T) {
 		t.Errorf("expected > 2, got: %d", len(PrestConf.AccessConf.Tables))
 	}
 
+	Load()
+	for _, ignoretable := range PrestConf.AccessConf.IgnoreTable {
+		if ignoretable != "test_permission_does_not_exist" {
+			t.Error("expected ['test_permission_does_not_exist'], but got another result")
+		}
+	}
+
 	Load()
 	if !PrestConf.AccessConf.Restrict {
 		t.Error("expected true, but got false")