unknown Claude Opus 5.5 commited on
Commit
690a6a7
·
1 Parent(s): 9471d62

Journal Formatter and Journal Finder locked to signed-in users: each tab shows a sign-in card (what the tool does, free with an account) until the visitor signs in, and the server refuses a run without an account; Pricing and the free-use note say "free with an account"

Browse files
Files changed (3) hide show
  1. app.py +33 -14
  2. plans.py +1 -1
  3. tests/test_auth_outputs.py +8 -0
app.py CHANGED
@@ -82,6 +82,12 @@ def suite_panel(ai_before, ai_after, original, revised, labels=None, extra=None,
82
  EMPTY = """<div class="cs-scores cs-empty"><div>Scores appear here after processing.</div></div>"""
83
 
84
 
 
 
 
 
 
 
85
  def _locked(what):
86
  if what == "dashboard": # not an upload: the customer's own history and files
87
  return ('<div class="cs-lock"><div class="cs-lock-ico">🔒</div>'
@@ -93,6 +99,11 @@ def _locked(what):
93
  '<div class="cs-lock-t">Sign in to get your Turnitin report</div>'
94
  '<div class="cs-lock-s">A free account takes a minute. Then pay for each report with PhonePe (UPI, '
95
  'cards, net banking) right on this page; a report that cannot be produced is refunded.</div></div>')
 
 
 
 
 
96
  return (f'<div class="cs-lock"><div class="cs-lock-ico">{UI.LOCK_ICON}🔒</div>'
97
  f'<div class="cs-lock-t">Sign in to upload {what}</div>'
98
  f'<div class="cs-lock-s">A free account takes a minute, and your first document is free. '
@@ -2542,6 +2553,8 @@ def JOB(status):
2542
  def _run_tool(core, args, n_outputs, status_index, user=None, request=None, tool=""):
2543
  """The Journal Formatter / Finder jobs: like H._run_live, but keyed by visitor + tool + input, so a page that
2544
  reconnects after a dropped connection picks up the running (or finished) job instead of starting it over."""
 
 
2545
  key = _job_key(user, request, tool, args) if tool else None
2546
  with _START_LOCK:
2547
  job = H.find_job(key)
@@ -2558,7 +2571,7 @@ def _run_tool(core, args, n_outputs, status_index, user=None, request=None, tool
2558
  _FREE_NOTE = (f"Free with a free account: pasted text up to {P.PLANS['free']['paste_words']} words "
2559
  f"({P.PLANS['free']['pastes']} a day), {P.FREE_TRIAL_DOCS} trial document up to "
2560
  f"{P.PLANS['free']['doc_words']:,} words and {P.FREE_DETECT_DAY} AI detector reports a day. The Journal "
2561
- "Formatter and the Journal Finder are free. Customers who already have credits or a plan keep using "
2562
  "them until they run out; after that, runs are paid from the wallet.")
2563
  TOOLS_UI = dict(wait=WAIT, hid=HID, job=JOB, run_live=_run_tool, log=DB.log_run, user=None)
2564
 
@@ -2915,20 +2928,26 @@ with gr.Blocks(title=SITE_TITLE, theme=theme, css=CSS + UI.css() + FND.CSS, js=F
2915
  # Both tools run inside this Space (formatter_tab.py / finder_tab.py). TOOLS_EMBED=1 shows the earlier
2916
  # separately hosted apps in a frame instead.
2917
  with gr.Tab("Journal Formatter", id="formatter"):
2918
- if TOOLS_EMBED:
2919
- gr.HTML(companion_tab_html(FORMAT_URL, "Journal Formatter.",
2920
- "Upload your (humanized) manuscript and give a template, the journal's "
2921
- "guidelines or just the journal name: the file is rearranged to that "
2922
- "format (Word and LaTeX)."))
2923
- else:
2924
- FMT.build(TOOLS_UI)
 
 
 
2925
  with gr.Tab("Journal Finder", id="finder"):
2926
- if TOOLS_EMBED:
2927
- gr.HTML(companion_tab_html(FINDER_URL, "Journal Finder.",
2928
- "Enter your paper's title to get matching journals with indexing (Scopus, "
2929
- "PubMed, ABDC), quartile, review time and acceptance odds."))
2930
- else:
2931
- FND.build(TOOLS_UI)
 
 
 
2932
 
2933
  # ============================ PRICING ============================
2934
  with gr.Tab("Pricing", id="pricing") as pricing_tab:
 
82
  EMPTY = """<div class="cs-scores cs-empty"><div>Scores appear here after processing.</div></div>"""
83
 
84
 
85
+ COMPANION_LOCKS = { # the companion tools need a signed-in account
86
+ "Journal Formatter": "Arrange your manuscript to a journal's format, as a Word file and Overleaf-ready LaTeX.",
87
+ "Journal Finder": "Find journals that match your title, with indexing, quartile, review time and acceptance odds.",
88
+ }
89
+
90
+
91
  def _locked(what):
92
  if what == "dashboard": # not an upload: the customer's own history and files
93
  return ('<div class="cs-lock"><div class="cs-lock-ico">🔒</div>'
 
99
  '<div class="cs-lock-t">Sign in to get your Turnitin report</div>'
100
  '<div class="cs-lock-s">A free account takes a minute. Then pay for each report with PhonePe (UPI, '
101
  'cards, net banking) right on this page; a report that cannot be produced is refunded.</div></div>')
102
+ if what in COMPANION_LOCKS: # free with an account (signed-in users only)
103
+ return (f'<div class="cs-lock"><div class="cs-lock-ico">{UI.LOCK_ICON}🔒</div>'
104
+ f'<div class="cs-lock-t">Sign in to use the {what}</div>'
105
+ f'<div class="cs-lock-s">{COMPANION_LOCKS[what]} It is included with your free account; '
106
+ 'sign in or create one in a minute.</div></div>')
107
  return (f'<div class="cs-lock"><div class="cs-lock-ico">{UI.LOCK_ICON}🔒</div>'
108
  f'<div class="cs-lock-t">Sign in to upload {what}</div>'
109
  f'<div class="cs-lock-s">A free account takes a minute, and your first document is free. '
 
2553
  def _run_tool(core, args, n_outputs, status_index, user=None, request=None, tool=""):
2554
  """The Journal Formatter / Finder jobs: like H._run_live, but keyed by visitor + tool + input, so a page that
2555
  reconnects after a dropped connection picks up the running (or finished) job instead of starting it over."""
2556
+ if tool in COMPANION_LOCKS and not user: # (the tab is locked; this stops a direct call too)
2557
+ raise gr.Error(f"Please sign in to use the {tool}.", title="Sign in needed")
2558
  key = _job_key(user, request, tool, args) if tool else None
2559
  with _START_LOCK:
2560
  job = H.find_job(key)
 
2571
  _FREE_NOTE = (f"Free with a free account: pasted text up to {P.PLANS['free']['paste_words']} words "
2572
  f"({P.PLANS['free']['pastes']} a day), {P.FREE_TRIAL_DOCS} trial document up to "
2573
  f"{P.PLANS['free']['doc_words']:,} words and {P.FREE_DETECT_DAY} AI detector reports a day. The Journal "
2574
+ "Formatter and the Journal Finder are free with an account (sign in to use them). Customers who already have credits or a plan keep using "
2575
  "them until they run out; after that, runs are paid from the wallet.")
2576
  TOOLS_UI = dict(wait=WAIT, hid=HID, job=JOB, run_live=_run_tool, log=DB.log_run, user=None)
2577
 
 
2928
  # Both tools run inside this Space (formatter_tab.py / finder_tab.py). TOOLS_EMBED=1 shows the earlier
2929
  # separately hosted apps in a frame instead.
2930
  with gr.Tab("Journal Formatter", id="formatter"):
2931
+ _, fm_open, fm_lockbtn = lock_gate("Journal Formatter") # signed-in users only
2932
+ GOTO_ACCOUNT.append(fm_lockbtn)
2933
+ with fm_open:
2934
+ if TOOLS_EMBED:
2935
+ gr.HTML(companion_tab_html(FORMAT_URL, "Journal Formatter.",
2936
+ "Upload your (humanized) manuscript and give a template, the journal's "
2937
+ "guidelines or just the journal name: the file is rearranged to that "
2938
+ "format (Word and LaTeX)."))
2939
+ else:
2940
+ FMT.build(TOOLS_UI)
2941
  with gr.Tab("Journal Finder", id="finder"):
2942
+ _, fn_open, fn_lockbtn = lock_gate("Journal Finder")
2943
+ GOTO_ACCOUNT.append(fn_lockbtn)
2944
+ with fn_open:
2945
+ if TOOLS_EMBED:
2946
+ gr.HTML(companion_tab_html(FINDER_URL, "Journal Finder.",
2947
+ "Enter your paper's title to get matching journals with indexing "
2948
+ "(Scopus, PubMed, ABDC), quartile, review time and acceptance odds."))
2949
+ else:
2950
+ FND.build(TOOLS_UI)
2951
 
2952
  # ============================ PRICING ============================
2953
  with gr.Tab("Pricing", id="pricing") as pricing_tab:
plans.py CHANGED
@@ -720,7 +720,7 @@ def pricing_html(currency=None, billing="Monthly"):
720
  f'detector reports a day, 1 journal-formatting file a month. '
721
  f'<b>Monthly and yearly plans</b> give the same credits every month; a yearly plan is paid once for '
722
  f'twelve months. '
723
- f'<b>Journal Finder:</b> free for everyone. <b>Journal formatting</b> on its own: '
724
  f'{price_of("format", cur)} per file. <b>Institutions and agencies:</b> from '
725
  f'{price_of("institution", cur)}/month for {PLANS["institution"]["docs_month"]} credits, several logins and '
726
  f'a GST invoice, contact us.'
 
720
  f'detector reports a day, 1 journal-formatting file a month. '
721
  f'<b>Monthly and yearly plans</b> give the same credits every month; a yearly plan is paid once for '
722
  f'twelve months. '
723
+ f'<b>Journal Finder:</b> free with a free account. <b>Journal formatting</b> on its own: '
724
  f'{price_of("format", cur)} per file. <b>Institutions and agencies:</b> from '
725
  f'{price_of("institution", cur)}/month for {PLANS["institution"]["docs_month"]} credits, several logins and '
726
  f'a GST invoice, contact us.'
tests/test_auth_outputs.py CHANGED
@@ -74,3 +74,11 @@ def test_a_recovery_key_is_verified_the_same_way():
74
  assert app.do_check_reset(email, "AAAA-BBBB-CCCC-DDDD")[1]["visible"] is False
75
  assert app.do_check_reset(email, key)[1]["visible"] is True
76
  assert app.do_reset_key(email, key, "brandnewpass1", "brandnewpass1")[0]["email"] == email
 
 
 
 
 
 
 
 
 
74
  assert app.do_check_reset(email, "AAAA-BBBB-CCCC-DDDD")[1]["visible"] is False
75
  assert app.do_check_reset(email, key)[1]["visible"] is True
76
  assert app.do_reset_key(email, key, "brandnewpass1", "brandnewpass1")[0]["email"] == email
77
+
78
+
79
+ def test_journal_formatter_and_finder_need_a_signed_in_account():
80
+ import pytest
81
+ for tool in ("Journal Formatter", "Journal Finder"):
82
+ assert tool in app.COMPANION_LOCKS and f"Sign in to use the {tool}" in app._locked(tool)
83
+ with pytest.raises(app.gr.Error):
84
+ next(app._run_tool(lambda rep: ("x",), (), 1, 0, user=None, request=None, tool=tool))