Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions forums/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))


# reCAPTCHA Settings
RECAPTCHA_SITE_KEY = os.getenv("RECAPTCHA_SITE_KEY")
RECAPTCHA_SECRET_KEY = os.getenv("RECAPTCHA_SECRET_KEY")

# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/1.11/howto/deployment/checklist/

Expand Down Expand Up @@ -108,8 +112,8 @@
'ENGINE': 'django.db.backends.mysql', # Add 'postgresql_psycopg2', 'mysql', 'sqlite3' or 'oracle'.
'NAME': os.getenv("SPOKEN_DB"), # Or path to database file if using sqlite3.
# The following settings are not used with sqlite3:
'USER': os.getenv("DB_USER"),
'PASSWORD': os.getenv("DB_PASSWORD"),
'USER': os.getenv("SPOKEN_DB_USER"),
'PASSWORD': os.getenv("SPOKEN_DB_PASSWORD"),
# Empty for localhost through domain sockets or '127.0.0.1' for localhost through TCP.
'HOST': '',
'PORT': '', # Set to empty string for default.
Expand Down Expand Up @@ -150,7 +154,7 @@

LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'Asia/Calcutta'
TIME_ZONE = 'Asia/Kolkata'

USE_I18N = True

Expand Down
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,4 @@ django-debug-toolbar==1.4
python-dotenv==0.10.3
nltk==3.5
sklearn==0.0
requests>=2.25.0
8 changes: 8 additions & 0 deletions static/website/templates/new-question.html
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,13 @@ <h4>
<label for="id_body">Question:</label>
{% render_field form.body class+="form-control" %}
</div>

<!-- reCAPTCHA widget, only for users without a role -->
{% if require_recaptcha %}
<div class="form-group" style="margin-top: 20px; margin-bottom: 15px;">
<div class="g-recaptcha" data-sitekey="{{ recaptcha_site_key }}"></div>
</div>
{% endif %}
</div>
</div>
<input class="btn btn-success" type="submit" value="Submit Question">
Expand All @@ -76,6 +83,7 @@ <h4 class="modal-title" id="myModalLabel">Similar Questions</h4>
</div><!-- /.modal -->

<script src="{% static 'website/js/nicEdit.js' %}" type="text/javascript"></script>
<script src="https://www.google.com/recaptcha/api.js" async defer></script>
<script type="text/javascript">
bkLib.onDomLoaded(function() {
new nicEditor({
Expand Down
3 changes: 1 addition & 2 deletions website/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,7 @@

class NewQuestionForm(forms.Form):
category = forms.ChoiceField(choices=[('', 'Select a Category'), ] + list(TutorialResources.objects.filter(
Q(status=1) | Q(status=2), language__name='English',tutorial_detail__foss__show_on_homepage=1).values('tutorial_detail__foss__foss').order_by(
'tutorial_detail__foss__foss').values_list('tutorial_detail__foss__foss',
Q(status=1) | Q(status=2), language__name='English',tutorial_detail__foss__show_on_homepage=1).values_list('tutorial_detail__foss__foss',
'tutorial_detail__foss__foss').distinct()),
widget=forms.Select(attrs={}), required=True, error_messages={'required': 'State field is required.'})
title = forms.CharField(max_length=200)
Expand Down
129 changes: 99 additions & 30 deletions website/views.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import json
import requests

from django.http import HttpResponse, HttpResponseRedirect, HttpResponseForbidden
from django.shortcuts import render, get_object_or_404
from django.template.context_processors import csrf
from django.contrib.auth.decorators import login_required
from django.contrib import messages
from django.db.models import Q, OuterRef, Subquery, Max, Count
from django.core.mail import EmailMultiAlternatives
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
Expand Down Expand Up @@ -318,6 +320,53 @@ def filter(request, category=None, tutorial=None, minute_range=None, second_rang
def new_question(request):
context = {}
if request.method == 'POST':
# check if user has a role
user_has_role = request.user.is_authenticated and request.user.groups.exists()

# only require captcha for users without a role
if not user_has_role:

recaptcha_response = request.POST.get('g-recaptcha-response', '')

if not recaptcha_response:
messages.error(request, "Please complete the reCAPTCHA verification.")
form = NewQuestionForm(request.POST)
context['form'] = form
context['recaptcha_site_key'] = settings.RECAPTCHA_SITE_KEY
context['require_recaptcha'] = True
context.update(csrf(request))
return render(request, 'website/templates/new-question.html', context)

# verify with google
recaptcha_verification_url = "https://www.google.com/recaptcha/api/siteverify"
recaptcha_data = {
'secret': settings.RECAPTCHA_SECRET_KEY,
'response': recaptcha_response
}

try:
recaptcha_result = requests.post(recaptcha_verification_url, data=recaptcha_data, timeout=5)
recaptcha_result.raise_for_status()
recaptcha_json = recaptcha_result.json()
except requests.RequestException as e:
messages.error(request, "Error verifying reCAPTCHA. Please try again.")
form = NewQuestionForm(request.POST)
context['form'] = form
context['recaptcha_site_key'] = settings.RECAPTCHA_SITE_KEY
context['require_recaptcha'] = True
context.update(csrf(request))
return render(request, 'website/templates/new-question.html', context)

# check if verification was successful
if not recaptcha_json.get('success', False):
messages.error(request, "reCAPTCHA verification failed. Please try again.")
form = NewQuestionForm(request.POST)
context['form'] = form
context['recaptcha_site_key'] = settings.RECAPTCHA_SITE_KEY
context['require_recaptcha'] = True
context.update(csrf(request))
return render(request, 'website/templates/new-question.html', context)

form = NewQuestionForm(request.POST)
if form.is_valid():
cleaned_data = form.cleaned_data
Expand All @@ -331,35 +380,52 @@ def new_question(request):
question.body = cleaned_data['body']
question.views = 1
question.save()
# Run spam detection
action = handle_spam(question, request.user)

if action == "AUTO_DELETE":
messages.error(request, " Your question is being marked as spam and your account has been deactivated.")
user_logout(request)
return HttpResponseRedirect('/')

elif action == "FLAGGED":
messages.warning(request, " Your question is pending moderator review.")
# Don’t send email for flagged content
return HttpResponseRedirect('/')

else: # APPROVED

subject = 'New Forum Question'
message = f"""
The following new question has been posted in the Spoken Tutorial Forum: <br>
Title: <b>{question.title}</b><br>
Category: <b>{question.category}</b><br>
Tutorial: <b>{question.tutorial}</b><br>
Link: <a href="http://forums.spoken-tutorial.org/question/{question.id}">
http://forums.spoken-tutorial.org/question/{question.id}
</a><br>
Question: <b>{question.body}</b><br>
"""
email = EmailMultiAlternatives(
subject, '', 'forums',
['team@spoken-tutorial.org', 'team@fossee.in'],
headers={"Content-type": "text/html;charset=iso-8859-1"}
)
email.attach_alternative(message, "text/html")
email.send(fail_silently=True)
return HttpResponseRedirect('/')

# Sending email when a new question is asked
subject = 'New Forum Question'
message = """
The following new question has been posted in the Spoken Tutorial Forum: <br>
Title: <b>{0}</b><br>
Category: <b>{1}</b><br>
Tutorial: <b>{2}</b><br>
Link: <a href="{3}">{3}</a><br>
Question: <b>{4}</b><br>
""".format(
question.title,
question.category,
question.tutorial,
'http://forums.spoken-tutorial.org/question/' + str(question.id),
question.body
)
email = EmailMultiAlternatives(
subject, '', 'forums',
['team@spoken-tutorial.org', 'team@fossee.in'],
headers={"Content-type": "text/html;charset=iso-8859-1"}
)
email.attach_alternative(message, "text/html")
email.send(fail_silently=True)
# End of email send
# If form not valid -> re-render with errors
context['form'] = form
context['recaptcha_site_key'] = settings.RECAPTCHA_SITE_KEY
# check if user needs to complete captcha
user_has_role = request.user.is_authenticated and request.user.groups.exists()
context['require_recaptcha'] = not user_has_role
context.update(csrf(request))
return render(request, 'website/templates/new-question.html', context)

return HttpResponseRedirect('/')
else:
# get values from URL.
# GET request -> render empty form
category = request.GET.get('category', None)
tutorial = request.GET.get('tutorial', None)
minute_range = request.GET.get('minute_range', None)
Expand All @@ -368,10 +434,13 @@ def new_question(request):
form = NewQuestionForm(category=category, tutorial=tutorial,
minute_range=minute_range, second_range=second_range)
context['category'] = category

context['form'] = form
context.update(csrf(request))
return render(request, 'website/templates/new-question.html', context)
context['form'] = form
context['recaptcha_site_key'] = settings.RECAPTCHA_SITE_KEY
# check if user needs to complete captcha
user_has_role = request.user.is_authenticated and request.user.groups.exists()
context['require_recaptcha'] = not user_has_role
context.update(csrf(request))
return render(request, 'website/templates/new-question.html', context)

# Notification Section

Expand Down