2323from ..common .dependencies import get_settings , role_required
2424from ..common .auth import (
2525 get_account_id_or_none ,
26+ get_client_role ,
2627)
2728from ..common .prio import generate_test_list
2829from ..common .dependencies import ClickhouseDep , PostgresDep
@@ -38,6 +39,11 @@ def utcnow_seconds():
3839 return datetime .now (timezone .utc ).replace (microsecond = 0 )
3940
4041
42+ # We use this string when the oonirun link is setup to not be shared.
43+ # We use it so that the UI in old clients won't break
44+ PRIVATE_EMAIL_PLACEHOLDER = "[private email]"
45+
46+
4147NETWORK_TYPES = [
4248 "vpn" ,
4349 "wifi" ,
@@ -135,7 +141,7 @@ class OONIRunLinkBase(BaseModel):
135141 description : str = Field (
136142 title = "full description of the ooni run link" , min_length = 2
137143 )
138- author : str = Field (
144+ author : str | None = Field (
139145 title = "public email address of the author name of the ooni run link" ,
140146 min_length = 2 ,
141147 max_length = 100 ,
@@ -180,6 +186,9 @@ def validate_intl(cls, v: Dict[str, str]):
180186 default_factory = lambda : utcnow_seconds () + timedelta (days = 30 * 6 ),
181187 description = "future time after which the ooni run link will be considered expired and no longer editable or usable (defaults to 6 months from now)" ,
182188 )
189+ publish_email : bool = Field (
190+ description = "Whether to publish this email to other users" ,
191+ )
183192
184193
185194class OONIRunLink (OONIRunLinkBase ):
@@ -253,6 +262,7 @@ def create_oonirun_link(
253262 icon = create_request .icon ,
254263 color = create_request .color ,
255264 expiration_date = create_request .expiration_date ,
265+ publish_email = create_request .publish_email ,
256266 date_created = now ,
257267 date_updated = now ,
258268 )
@@ -291,6 +301,7 @@ def create_oonirun_link(
291301 icon = db_oonirun_link .icon ,
292302 color = db_oonirun_link .color ,
293303 expiration_date = db_oonirun_link .expiration_date ,
304+ publish_email = db_oonirun_link .publish_email ,
294305 date_created = db_oonirun_link .date_created ,
295306 date_updated = db_oonirun_link .date_updated ,
296307 nettests = nettest_list ,
@@ -309,7 +320,9 @@ def edit_oonirun_link(
309320 db : PostgresDep ,
310321 token = Depends (role_required (["admin" , "user" ])),
311322):
312- """Edit an existing OONI Run link"""
323+ """
324+ Edit an existing OONI Run link
325+ """
313326 log .debug (f"edit oonirun { oonirun_link_id } " )
314327 account_id = token ["account_id" ]
315328
@@ -392,6 +405,7 @@ def edit_oonirun_link(
392405 oonirun_link .color = edit_request .color
393406 oonirun_link .expiration_date = edit_request .expiration_date
394407 oonirun_link .date_updated = now
408+ oonirun_link .publish_email = edit_request .publish_email
395409 db .commit ()
396410
397411 return OONIRunLink (
@@ -406,6 +420,7 @@ def edit_oonirun_link(
406420 icon = oonirun_link .icon ,
407421 color = oonirun_link .color ,
408422 expiration_date = oonirun_link .expiration_date ,
423+ publish_email = oonirun_link .publish_email ,
409424 oonirun_link_id = oonirun_link .oonirun_link_id ,
410425 date_created = oonirun_link .date_created ,
411426 date_updated = oonirun_link .date_updated ,
@@ -506,6 +521,7 @@ def make_oonirun_link(
506521 oonirun_link_id : str ,
507522 account_id : Optional [str ],
508523 revision : Optional [int ] = None ,
524+ is_admin : bool = False ,
509525):
510526 q = db .query (models .OONIRunLink ).filter (
511527 models .OONIRunLink .oonirun_link_id == oonirun_link_id
@@ -524,6 +540,7 @@ def make_oonirun_link(
524540 assert isinstance (revision , int )
525541
526542 nettests , date_created = get_nettests (res , revision )
543+ is_mine = account_id == res .creator_account_id
527544 return OONIRunLink (
528545 oonirun_link_id = res .oonirun_link_id ,
529546 name = res .name ,
@@ -538,9 +555,14 @@ def make_oonirun_link(
538555 nettests = nettests ,
539556 date_created = date_created ,
540557 date_updated = res .date_updated ,
541- is_mine = account_id == res .creator_account_id ,
542- author = res .author ,
558+ is_mine = is_mine ,
559+ author = (
560+ res .author
561+ if is_mine or is_admin or res .publish_email
562+ else PRIVATE_EMAIL_PLACEHOLDER
563+ ),
543564 revision = str (revision ),
565+ publish_email = res .publish_email
544566 )
545567
546568
@@ -678,12 +700,20 @@ def get_oonirun_link_revision(
678700 authorization : str = Header ("authorization" ),
679701 settings = Depends (get_settings ),
680702):
681- """Fetch an OONI Run link by specifying the revision number"""
703+ """
704+ Fetch an OONI Run link by specifying the revision number
705+
706+ Note that the author field is replaced with the placeholder "[private email]" for other users
707+ if the author has set publish_email to False.
708+ """
682709 # Return the latest version of the translations
683710 log .debug ("fetching oonirun" )
684711 account_id = get_account_id_or_none (
685712 authorization , jwt_encryption_key = settings .jwt_encryption_key
686713 )
714+ is_admin = (
715+ get_client_role (authorization , settings .jwt_encryption_key ) == "admin"
716+ )
687717
688718 try :
689719 revision = int (revision_number )
@@ -693,7 +723,11 @@ def get_oonirun_link_revision(
693723 revision = None
694724
695725 oonirun_link = make_oonirun_link (
696- db = db , oonirun_link_id = oonirun_link_id , account_id = account_id , revision = revision
726+ db = db ,
727+ oonirun_link_id = oonirun_link_id ,
728+ account_id = account_id ,
729+ revision = revision ,
730+ is_admin = is_admin ,
697731 )
698732 return oonirun_link
699733
@@ -706,16 +740,27 @@ def get_latest_oonirun_link(
706740 db : PostgresDep ,
707741 authorization : str = Header ("authorization" ),
708742 settings = Depends (get_settings ),
709- ):
710- """Fetch OONIRun descriptor by creation time or the newest one"""
743+ ) -> OONIRunLink :
744+ """
745+ Fetch OONIRun descriptor by creation time or the newest one
746+
747+ Note that the author field is replaced with the placeholder "[private email]" for other users
748+ if the author has set publish_email to False.
749+ """
711750 # Return the latest version of the translations
712751 log .debug ("fetching oonirun" )
713752 account_id = get_account_id_or_none (
714753 authorization , jwt_encryption_key = settings .jwt_encryption_key
715754 )
755+ is_admin = (
756+ get_client_role (authorization , settings .jwt_encryption_key ) == "admin"
757+ )
716758
717759 oonirun_link = make_oonirun_link (
718- db = db , oonirun_link_id = oonirun_link_id , account_id = account_id
760+ db = db ,
761+ oonirun_link_id = oonirun_link_id ,
762+ account_id = account_id ,
763+ is_admin = is_admin ,
719764 )
720765 return oonirun_link
721766
@@ -738,9 +783,17 @@ def list_oonirun_links(
738783 authorization : str = Header ("authorization" ),
739784 settings = Depends (get_settings ),
740785) -> OONIRunLinkList :
741- """List OONIRun descriptors"""
786+ """
787+ List OONIRun descriptors
788+
789+ Note that the author field is replaced with the placeholder "[private email]" for other users
790+ if the author has set publish_email to False.
791+ """
742792 log .debug ("list oonirun" )
743793 account_id = get_account_id_or_none (authorization , settings .jwt_encryption_key )
794+ is_admin = (
795+ get_client_role (authorization , settings .jwt_encryption_key ) == "admin"
796+ )
744797
745798 q = db .query (models .OONIRunLink )
746799 if not is_expired :
@@ -766,14 +819,19 @@ def list_oonirun_links(
766819 short_description_intl = row .short_description_intl ,
767820 description = row .description ,
768821 description_intl = row .description_intl ,
769- author = row .author ,
822+ author = (
823+ row .author
824+ if account_id == row .creator_account_id or is_admin or row .publish_email
825+ else PRIVATE_EMAIL_PLACEHOLDER
826+ ),
770827 nettests = nettests ,
771828 icon = row .icon ,
772829 expiration_date = row .expiration_date ,
773830 revision = str (revision ),
774831 date_created = row .date_created ,
775832 date_updated = row .date_updated ,
776833 is_mine = account_id == row .creator_account_id ,
834+ publish_email = row .publish_email
777835 )
778836 links .append (oonirun_link )
779837 log .debug (f"Returning { len (links )} ooni run links" )
0 commit comments