@@ -932,6 +932,30 @@ def test_edit_author_without_name_raises(self):
932932 with self .assertRaises (ValueError ):
933933 create_token ("tok-project" , "edit_author" )
934934
935+ def test_create_multi_author_token (self ):
936+ token = create_token ("tok-project" , "multi_author" )
937+ record = lookup_token ("tok-project" , token )
938+ self .assertIsNotNone (record )
939+ self .assertEqual (record ["token_type" ], "multi_author" )
940+ self .assertIsNone (record ["author_name" ])
941+
942+ def test_multi_author_expires_capped_at_7_days (self ):
943+ from datetime import datetime , timezone
944+ token = create_token ("tok-project" , "multi_author" , expires_days = 9999 )
945+ record = lookup_token ("tok-project" , token )
946+ expires = datetime .fromisoformat (record ["expires_at" ])
947+ delta = expires - datetime .now (timezone .utc )
948+ self .assertLessEqual (delta .days , 7 )
949+
950+ def test_multi_author_expires_custom_within_7_days (self ):
951+ from datetime import datetime , timezone
952+ token = create_token ("tok-project" , "multi_author" , expires_days = 3 )
953+ record = lookup_token ("tok-project" , token )
954+ expires = datetime .fromisoformat (record ["expires_at" ])
955+ delta = expires - datetime .now (timezone .utc )
956+ self .assertLessEqual (delta .days , 3 )
957+ self .assertGreater (delta .days , 1 )
958+
935959 def test_lookup_unknown_token_returns_none (self ):
936960 self .assertIsNone (lookup_token ("tok-project" , "notavalidtoken" ))
937961
@@ -1155,6 +1179,34 @@ def test_invalid_type_returns_400(self):
11551179 resp = self .fetch ("/contributions/token?doi=10.1/x&type=bad_type" )
11561180 self .assertEqual (resp .code , 400 )
11571181
1182+ def test_multi_author_token_created (self ):
1183+ pc = _make_project ("tok-project" )
1184+ with self ._patch_contributions_by_doi (pc ), self ._patch_verify (True ), \
1185+ self ._patch_create_token ("ccddee11" * 4 ):
1186+ resp = self .fetch ("/contributions/token?doi=10.1/x&type=multi_author" )
1187+ self .assertEqual (resp .code , 200 )
1188+ body = json .loads (resp .body )
1189+ self .assertEqual (body ["type" ], "multi_author" )
1190+ self .assertEqual (body ["token" ], "ccddee11" * 4 )
1191+
1192+ def test_multi_author_expires_days_capped_at_7 (self ):
1193+ pc = _make_project ("tok-project" )
1194+ with self ._patch_contributions_by_doi (pc ), self ._patch_verify (True ), \
1195+ self ._patch_create_token ():
1196+ resp = self .fetch ("/contributions/token?doi=10.1/x&type=multi_author&days=9999" )
1197+ self .assertEqual (resp .code , 200 )
1198+ body = json .loads (resp .body )
1199+ self .assertEqual (body ["expires_days" ], 7 )
1200+
1201+ def test_multi_author_custom_days_within_cap (self ):
1202+ pc = _make_project ("tok-project" )
1203+ with self ._patch_contributions_by_doi (pc ), self ._patch_verify (True ), \
1204+ self ._patch_create_token ():
1205+ resp = self .fetch ("/contributions/token?doi=10.1/x&type=multi_author&days=3" )
1206+ self .assertEqual (resp .code , 200 )
1207+ body = json .loads (resp .body )
1208+ self .assertEqual (body ["expires_days" ], 3 )
1209+
11581210 def test_edit_author_without_author_param_returns_400 (self ):
11591211 resp = self .fetch ("/contributions/token?doi=10.1/x&type=edit_author" )
11601212 self .assertEqual (resp .code , 400 )
@@ -1339,6 +1391,22 @@ def test_valid_edit_author_token_not_consumed(self):
13391391 self .assertEqual (resp .code , 200 )
13401392 mock_consume .assert_not_called ()
13411393
1394+ def test_valid_multi_author_token_not_consumed (self ):
1395+ record = {"token_id" : "tok4" , "token_type" : "multi_author" , "author_name" : None }
1396+ body = to_json (self ._make_project_with_two_authors ())
1397+ mock_consume = MagicMock ()
1398+ with self ._patch_store (), self ._patch_lookup_token (record ), \
1399+ self ._patch_validate_scope ((True , None )), \
1400+ patch ("aind_metadata_viz.contributions.handlers.consume_token" , mock_consume ):
1401+ resp = self .fetch (
1402+ "/contributions/post?project=tok-post-project&password=tok4" ,
1403+ method = "POST" ,
1404+ body = body ,
1405+ headers = {"Content-Type" : "application/json" },
1406+ )
1407+ self .assertEqual (resp .code , 200 )
1408+ mock_consume .assert_not_called ()
1409+
13421410 def test_out_of_scope_token_returns_403 (self ):
13431411 record = {"token_id" : "tok1" , "token_type" : "add_author" , "author_name" : None }
13441412 body = to_json (self ._make_project_with_two_authors ())
0 commit comments