1717_logger = logging .getLogger (__name__ )
1818
1919
20+ class HasuraError (RuntimeError ):
21+ ...
22+
23+
2024def _is_model_class (obj ) -> bool :
2125 """Is subclass of tortoise.Model, but not the base class"""
2226 return isinstance (obj , type ) and issubclass (obj , Model ) and obj != Model and not getattr (obj .Meta , 'abstract' , False )
@@ -51,11 +55,11 @@ def _format_object_relationship(name: str, column: str) -> Dict[str, Any]:
5155 }
5256
5357
54- def _format_select_permissions (columns : List [ str ] ) -> Dict [str , Any ]:
58+ def _format_select_permissions () -> Dict [str , Any ]:
5559 return {
5660 "role" : "user" ,
5761 "permission" : {
58- "columns" : sorted ( columns ) ,
62+ "columns" : "*" ,
5963 "filter" : {},
6064 "allow_aggregations" : True ,
6165 },
@@ -90,11 +94,13 @@ def _iter_models(*modules) -> Iterator[Tuple[str, Type[Model]]]:
9094 yield app , model
9195
9296
93- async def generate_hasura_metadata (config : DipDupConfig ) -> Dict [str , Any ]:
97+ async def generate_hasura_metadata (config : DipDupConfig , views : List [ str ] ) -> Dict [str , Any ]:
9498 """Generate metadata based on dapp models.
9599
96100 Includes tables and their relations (but not entities created during execution of snippets from `sql` package directory)
97101 """
102+ if not isinstance (config .database , PostgresDatabaseConfig ):
103+ raise RuntimeError
98104 _logger .info ('Generating Hasura metadata' )
99105 metadata_tables = {}
100106 model_tables = {}
@@ -105,24 +111,31 @@ async def generate_hasura_metadata(config: DipDupConfig) -> Dict[str, Any]:
105111 for app , model in _iter_models (models , int_models ):
106112 table_name = model ._meta .db_table or pascal_to_snake (model .__name__ ) # pylint: disable=protected-access
107113 model_tables [f'{ app } .{ model .__name__ } ' ] = table_name
108-
109- table = _format_table (
114+ metadata_tables [table_name ] = _format_table (
110115 name = table_name ,
111- schema = config .database .schema_name if isinstance (config .database , PostgresDatabaseConfig ) else 'public' ,
116+ schema = config .database .schema_name ,
117+ )
118+
119+ for view in views :
120+ metadata_tables [view ] = _format_table (
121+ name = view ,
122+ schema = config .database .schema_name ,
123+ )
124+ metadata_tables [view ]['select_permissions' ].append (
125+ _format_select_permissions (),
112126 )
113- metadata_tables [table_name ] = table
114127
115128 for app , model in _iter_models (models , int_models ):
116129 table_name = model_tables [f'{ app } .{ model .__name__ } ' ]
117130
118131 metadata_tables [table_name ]['select_permissions' ].append (
119- _format_select_permissions (list ( model . _meta . db_fields ) ),
132+ _format_select_permissions (),
120133 )
121134
122135 for field in model ._meta .fields_map .values ():
123136 if isinstance (field , fields .relational .ForeignKeyFieldInstance ):
124137 if not isinstance (field .related_name , str ):
125- raise Exception (f'`related_name` of `{ field } ` must be set' )
138+ raise HasuraError (f'`related_name` of `{ field } ` must be set' )
126139 related_table_name = model_tables [field .model_name ]
127140 metadata_tables [table_name ]['object_relationships' ].append (
128141 _format_object_relationship (
@@ -135,7 +148,7 @@ async def generate_hasura_metadata(config: DipDupConfig) -> Dict[str, Any]:
135148 related_name = field .related_name ,
136149 table = table_name ,
137150 column = field .model_field_name + '_id' ,
138- schema = config .database .schema_name if isinstance ( config . database , PostgresDatabaseConfig ) else 'public' ,
151+ schema = config .database .schema_name ,
139152 )
140153 )
141154
@@ -152,7 +165,16 @@ async def configure_hasura(config: DipDupConfig):
152165
153166 _logger .info ('Configuring Hasura' )
154167 url = config .hasura .url .rstrip ("/" )
155- hasura_metadata = await generate_hasura_metadata (config )
168+ views = [
169+ row [0 ]
170+ for row in (
171+ await get_connection (None ).execute_query (
172+ f"SELECT table_name FROM information_schema.views WHERE table_schema = '{ config .database .schema_name } '"
173+ )
174+ )[1 ]
175+ ]
176+
177+ hasura_metadata = await generate_hasura_metadata (config , views )
156178
157179 async with aiohttp .ClientSession () as session :
158180 _logger .info ('Waiting for Hasura instance to be healthy' )
@@ -163,8 +185,7 @@ async def configure_hasura(config: DipDupConfig):
163185 break
164186 await asyncio .sleep (1 )
165187 else :
166- _logger .error ('Hasura instance not responding for 60 seconds' )
167- return
188+ raise HasuraError ('Hasura instance not responding for 60 seconds' )
168189
169190 headers = {}
170191 if config .hasura .admin_secret :
@@ -178,7 +199,7 @@ async def configure_hasura(config: DipDupConfig):
178199 data = json .dumps (
179200 {
180201 "type" : "export_metadata" ,
181- "args" : hasura_metadata ,
202+ "args" : {} ,
182203 },
183204 ),
184205 headers = headers ,
@@ -204,29 +225,6 @@ async def configure_hasura(config: DipDupConfig):
204225 headers = headers ,
205226 )
206227 if result .get ('message' ) != 'success' :
207- _logger .error ('Can\' t configure Hasura instance: %s' , result )
208- return
209-
210- views = await get_connection (None ).execute_query (
211- f"SELECT table_name FROM information_schema.views WHERE table_schema = '{ config .database .schema_name } '"
212- )
213- for view in views [1 ]:
214- result = await http_request (
215- session ,
216- 'post' ,
217- url = f'{ url } /v1/query' ,
218- data = json .dumps (
219- {
220- "type" : "add_existing_table_or_view" ,
221- "args" : {
222- "name" : view [0 ],
223- "schema" : config .database .schema_name ,
224- },
225- },
226- ),
227- headers = headers ,
228- )
229- if result .get ('message' ) != 'success' and result .get ('code' ) != 'already-tracked' :
230- _logger .error ('Can\' t configure Hasura instance: %s' , result )
228+ raise HasuraError ('Can\' t configure Hasura instance' , result )
231229
232230 _logger .info ('Hasura instance has been configured' )
0 commit comments