Ko-TTS-Arena Contributors commited on
Commit
c741502
·
1 Parent(s): 8878a7e

feat: Remove login requirement - allow anonymous TTS generation and voting

Browse files
Files changed (3) hide show
  1. app.py +6 -12
  2. security.py +2 -1
  3. templates/arena.html +2 -70
app.py CHANGED
@@ -587,10 +587,6 @@ def generate_tts():
587
  if app.config["TURNSTILE_ENABLED"] and not session.get("turnstile_verified"):
588
  return jsonify({"error": "Turnstile verification required"}), 403
589
 
590
- # Require user to be logged in to generate audio
591
- if not current_user.is_authenticated:
592
- return jsonify({"error": "You must be logged in to generate audio"}), 401
593
-
594
  data = request.json
595
  text = data.get("text", "").strip() # Ensure text is stripped
596
 
@@ -776,16 +772,14 @@ def submit_vote():
776
  if app.config["TURNSTILE_ENABLED"] and not session.get("turnstile_verified"):
777
  return jsonify({"error": "Turnstile verification required"}), 403
778
 
779
- # Require user to be logged in to vote
780
- if not current_user.is_authenticated:
781
- return jsonify({"error": "You must be logged in to vote"}), 401
782
-
783
  # Security checks for vote manipulation prevention
784
  client_ip = get_client_ip()
785
- vote_allowed, security_reason, security_score = is_vote_allowed(current_user.id, client_ip)
 
786
 
787
  if not vote_allowed:
788
- app.logger.warning(f"Vote blocked for user {current_user.username} (ID: {current_user.id}): {security_reason} (Score: {security_score})")
 
789
  return jsonify({"error": f"Vote not allowed: {security_reason}"}), 403
790
 
791
  data = request.json
@@ -832,7 +826,7 @@ def submit_vote():
832
 
833
  # Record vote in database with analytics data
834
  vote, error = record_vote(
835
- current_user.id,
836
  session_data["text"],
837
  chosen_id,
838
  rejected_id,
@@ -871,7 +865,7 @@ def submit_vote():
871
  "rejected_model_id": rejected_model_obj.id if rejected_model_obj else "Unknown",
872
  "session_id": session_id,
873
  "timestamp": datetime.utcnow().isoformat(),
874
- "username": current_user.username,
875
  "model_type": "TTS"
876
  }
877
  with open(os.path.join(vote_dir, "metadata.json"), "w") as f:
 
587
  if app.config["TURNSTILE_ENABLED"] and not session.get("turnstile_verified"):
588
  return jsonify({"error": "Turnstile verification required"}), 403
589
 
 
 
 
 
590
  data = request.json
591
  text = data.get("text", "").strip() # Ensure text is stripped
592
 
 
772
  if app.config["TURNSTILE_ENABLED"] and not session.get("turnstile_verified"):
773
  return jsonify({"error": "Turnstile verification required"}), 403
774
 
 
 
 
 
775
  # Security checks for vote manipulation prevention
776
  client_ip = get_client_ip()
777
+ user_id = current_user.id if current_user.is_authenticated else None
778
+ vote_allowed, security_reason, security_score = is_vote_allowed(user_id, client_ip)
779
 
780
  if not vote_allowed:
781
+ username = current_user.username if current_user.is_authenticated else "anonymous"
782
+ app.logger.warning(f"Vote blocked for user {username} (ID: {user_id}): {security_reason} (Score: {security_score})")
783
  return jsonify({"error": f"Vote not allowed: {security_reason}"}), 403
784
 
785
  data = request.json
 
826
 
827
  # Record vote in database with analytics data
828
  vote, error = record_vote(
829
+ user_id,
830
  session_data["text"],
831
  chosen_id,
832
  rejected_id,
 
865
  "rejected_model_id": rejected_model_obj.id if rejected_model_obj else "Unknown",
866
  "session_id": session_id,
867
  "timestamp": datetime.utcnow().isoformat(),
868
+ "username": current_user.username if current_user.is_authenticated else "anonymous",
869
  "model_type": "TTS"
870
  }
871
  with open(os.path.join(vote_dir, "metadata.json"), "w") as f:
security.py CHANGED
@@ -406,8 +406,9 @@ def is_vote_allowed(user_id, ip_address=None):
406
  Check if a vote should be allowed based on security factors.
407
  Returns (allowed, reason, security_score)
408
  """
 
409
  if not user_id:
410
- return False, "User not authenticated", 0
411
 
412
  # Check if user is currently timed out
413
  try:
 
406
  Check if a vote should be allowed based on security factors.
407
  Returns (allowed, reason, security_score)
408
  """
409
+ # Allow anonymous voting when user is not authenticated
410
  if not user_id:
411
+ return True, "Anonymous vote allowed", 50
412
 
413
  # Check if user is currently timed out
414
  try:
templates/arena.html CHANGED
@@ -5,23 +5,6 @@
5
  {% block current_page %}Arena{% endblock %}
6
 
7
  {% block content %}
8
- <!-- Authentication status for JavaScript -->
9
- <div id="auth-status" data-authenticated="{% if current_user.is_authenticated %}true{% else %}false{% endif %}" style="display: none;"></div>
10
-
11
- {% if not current_user.is_authenticated %}
12
- <!-- Login prompt overlay -->
13
- <div id="login-prompt-overlay" class="login-prompt-overlay" style="display: none;">
14
- <div class="login-prompt-content">
15
- <h3>로그인 필요</h3>
16
- <p>TTS Arena를 사용하려면 로그인이 필요합니다. 로그인하여 음성을 생성하고 투표하세요!</p>
17
- <div class="login-prompt-actions">
18
- <button class="login-prompt-close">나중에</button>
19
- <a href="{{ url_for('auth.login', next=request.path) }}" class="login-prompt-btn">Hugging Face로 로그인</a>
20
- </div>
21
- </div>
22
- </div>
23
- {% endif %}
24
-
25
  <div id="tts-tab" class="tab-content active">
26
  <form class="input-container">
27
  <div class="input-group">
@@ -691,40 +674,6 @@
691
  <script src="{{ url_for('static', filename='js/waveplayer.js') }}"></script>
692
  <script>
693
  document.addEventListener('DOMContentLoaded', function() {
694
- // Check authentication status
695
- const authStatus = document.getElementById('auth-status');
696
- const isAuthenticated = authStatus ? authStatus.dataset.authenticated === 'true' : false;
697
- const loginPromptOverlay = document.getElementById('login-prompt-overlay');
698
- const loginPromptClose = document.querySelector('.login-prompt-close');
699
-
700
- // Function to show login prompt
701
- function showLoginPrompt() {
702
- if (loginPromptOverlay) {
703
- loginPromptOverlay.style.display = 'flex';
704
- }
705
- }
706
-
707
- // Function to hide login prompt
708
- function hideLoginPrompt() {
709
- if (loginPromptOverlay) {
710
- loginPromptOverlay.style.display = 'none';
711
- }
712
- }
713
-
714
- // Add event listener to close button
715
- if (loginPromptClose) {
716
- loginPromptClose.addEventListener('click', hideLoginPrompt);
717
- }
718
-
719
- // Close prompt when clicking outside
720
- if (loginPromptOverlay) {
721
- loginPromptOverlay.addEventListener('click', function(e) {
722
- if (e.target === loginPromptOverlay) {
723
- hideLoginPrompt();
724
- }
725
- });
726
- }
727
-
728
  const synthForm = document.querySelector('.input-container');
729
  const synthBtn = document.querySelector('.synth-btn');
730
  const mobileSynthBtn = document.querySelector('.mobile-synth-btn');
@@ -786,12 +735,6 @@
786
  e.preventDefault();
787
  }
788
 
789
- // Check authentication first
790
- if (!isAuthenticated) {
791
- showLoginPrompt();
792
- return;
793
- }
794
-
795
  const text = textInput.value.trim();
796
  if (!text) {
797
  openToast("텍스트를 입력해주세요", "warning");
@@ -883,13 +826,7 @@
883
  })
884
  .catch(error => {
885
  loadingContainer.style.display = 'none';
886
-
887
- // Handle authentication errors specially
888
- if (error.message.includes('logged in to generate') || error.message.includes('logged in to vote')) {
889
- openToast("로그인이 필요합니다. <a href='{{ url_for('auth.login', next=request.path) }}' style='color: white; text-decoration: underline;'>지금 로그인</a>", "error");
890
- } else {
891
- openToast(error.message, "error");
892
- }
893
  console.error('Error:', error);
894
  });
895
  }
@@ -962,12 +899,7 @@
962
  btn.querySelector('.vote-loader').style.display = 'none';
963
  });
964
 
965
- // Handle authentication errors specially
966
- if (error.message.includes('logged in to vote')) {
967
- openToast("로그인이 필요합니다. <a href='{{ url_for('auth.login', next=request.path) }}' style='color: white; text-decoration: underline;'>지금 로그인</a>", "error");
968
- } else {
969
- openToast(error.message, "error");
970
- }
971
  console.error('Error:', error);
972
  });
973
  }
 
5
  {% block current_page %}Arena{% endblock %}
6
 
7
  {% block content %}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8
  <div id="tts-tab" class="tab-content active">
9
  <form class="input-container">
10
  <div class="input-group">
 
674
  <script src="{{ url_for('static', filename='js/waveplayer.js') }}"></script>
675
  <script>
676
  document.addEventListener('DOMContentLoaded', function() {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
677
  const synthForm = document.querySelector('.input-container');
678
  const synthBtn = document.querySelector('.synth-btn');
679
  const mobileSynthBtn = document.querySelector('.mobile-synth-btn');
 
735
  e.preventDefault();
736
  }
737
 
 
 
 
 
 
 
738
  const text = textInput.value.trim();
739
  if (!text) {
740
  openToast("텍스트를 입력해주세요", "warning");
 
826
  })
827
  .catch(error => {
828
  loadingContainer.style.display = 'none';
829
+ openToast(error.message, "error");
 
 
 
 
 
 
830
  console.error('Error:', error);
831
  });
832
  }
 
899
  btn.querySelector('.vote-loader').style.display = 'none';
900
  });
901
 
902
+ openToast(error.message, "error");
 
 
 
 
 
903
  console.error('Error:', error);
904
  });
905
  }