@@ -1567,6 +1567,119 @@ async def api_form_read_all_needing_action(
1567
1567
return {"documents" : dict_of_return_values }
1568
1568
1569
1569
1570
+ # Read all forms that reference the given form_name and document_id
1571
+ @app .get ("/api/form/get_linked_refs/{form_name}/{document_id}" , dependencies = [Depends (api_key_auth )])
1572
+ async def api_form_read_all_needing_action (
1573
+ form_name : str ,
1574
+ document_id : str ,
1575
+ background_tasks : BackgroundTasks ,
1576
+ request : Request ,
1577
+ config = Depends (get_config_depends ),
1578
+ mailer = Depends (get_mailer ),
1579
+ doc_db = Depends (get_doc_db ),
1580
+ session : SessionLocal = Depends (get_db ),
1581
+ key : str = Depends (X_API_KEY ),
1582
+
1583
+ ):
1584
+ """
1585
+ This method returns a list of forms that reference the given form_name and document_id
1586
+ in one of their fields. These are sometimes called linked references, or backrefs. It
1587
+ returns full records in a flat format by default.
1588
+ """
1589
+
1590
+ if not config .API_ENABLED :
1591
+ raise HTTPException (status_code = 404 , detail = "This page does not exist" )
1592
+
1593
+ if form_name not in get_form_names (config_path = config .FORM_CONFIG_PATH ):
1594
+ raise HTTPException (status_code = 404 , detail = f"Form '{ form_name } ' not found" )
1595
+
1596
+ # Ugh, I'd like to find a more efficient way to get the user data. But alas, that
1597
+ # the sqlalchemy-signing table is not optimized alongside the user model...
1598
+ user = session .query (User ).filter_by (api_key = key ).first ()
1599
+
1600
+ # Here we build a full structure containing all the form field links for each form
1601
+ dict_of_fields_linked_to_forms = {} # This might not be relevant ... We will see.
1602
+
1603
+ # Now we build a dict for linked fields _applicable_ to the given form_name
1604
+ dict_of_relevant_links = {}
1605
+
1606
+ for _form_name in get_form_names (config_path = config .FORM_CONFIG_PATH ):
1607
+
1608
+ dict_of_relevant_links [_form_name ] = []
1609
+
1610
+ __form_model = get_form_model (
1611
+ form_name = _form_name ,
1612
+ config_path = config .FORM_CONFIG_PATH ,
1613
+ session = session ,
1614
+ User = User ,
1615
+ Group = Group ,
1616
+ doc_db = __doc_db ,
1617
+ )
1618
+
1619
+ dict_of_fields_linked_to_forms [_form_name ] = __form_model .form_fields
1620
+
1621
+ for field_name , linked_form in __form_model .form_fields .items ():
1622
+ # If this field links to the form that this query is concerned with, then add it to the list
1623
+ if linked_form == form_name :
1624
+ dict_of_relevant_links [_form_name ].append (field_name )
1625
+
1626
+
1627
+ # read_all IS THE HIGHER PRIVILEGE OF THE TWO - SO WE SHOULD CHECK FOR THAT FIRST, AS IT
1628
+ # INCLUDES read_own. https://github.com/signebedi/libreforms-fastapi/issues/307.
1629
+ try :
1630
+ user .validate_permission (form_name = form_name , required_permission = "read_all" )
1631
+ limit_query_to = False
1632
+ except Exception as e :
1633
+
1634
+ try :
1635
+ user .validate_permission (form_name = form_name , required_permission = "read_own" )
1636
+ limit_query_to = user .username
1637
+
1638
+ except Exception as e :
1639
+ raise HTTPException (status_code = 403 , detail = f"{ e } " )
1640
+
1641
+
1642
+ documents = []
1643
+
1644
+ for _form_name , _linked_fields in dict_of_relevant_links .items ():
1645
+ for _linked_field in _linked_fields :
1646
+ _documents = []
1647
+ # This query param will only return that matches the given document_id
1648
+ query_params = {"data" :{_linked_field : {"operator" : "==" ,"value" : document_id }}}
1649
+
1650
+ _documents = doc_db .get_all_documents (
1651
+ form_name = _form_name ,
1652
+ limit_users = limit_query_to ,
1653
+ exclude_journal = True ,
1654
+ collapse_data = True ,
1655
+ # sort_by_last_edited=True,
1656
+ # newest_first=True,
1657
+ query_params = query_params ,
1658
+ )
1659
+
1660
+ documents .extend (_documents )
1661
+
1662
+ # Placeholder: drop duplicates and sort!
1663
+
1664
+ # Write this query to the TransactionLog
1665
+ if config .COLLECT_USAGE_STATISTICS :
1666
+
1667
+ endpoint = request .url .path
1668
+ remote_addr = request .client .host
1669
+
1670
+ background_tasks .add_task (
1671
+ write_api_call_to_transaction_log ,
1672
+ api_key = key ,
1673
+ endpoint = endpoint ,
1674
+ remote_addr = remote_addr ,
1675
+ query_params = {},
1676
+ )
1677
+
1678
+ return {"documents" : documents }
1679
+
1680
+
1681
+
1682
+
1570
1683
# Read one form
1571
1684
@app .get ("/api/form/read_one/{form_name}/{document_id}" , dependencies = [Depends (api_key_auth )])
1572
1685
async def api_form_read_one (
0 commit comments