Skip to content

Commit bdcc99b

Browse files
committed
feat(passport): add google reCAPTCHA
1 parent fa288b8 commit bdcc99b

16 files changed

Lines changed: 114 additions & 54 deletions

rootfs/api/context_processors.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
from django.conf import settings
2+
3+
4+
def legal(request):
5+
return {
6+
'LEGAL_ENABLED': settings.LEGAL_ENABLED,
7+
}

rootfs/api/forms.py

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,15 @@
1+
import requests
2+
from django import forms
3+
from django.conf import settings
14
from django.utils.translation import gettext_lazy as _
25
from django.core.exceptions import ValidationError
3-
from django.contrib.auth.forms import AuthenticationForm as _AuthenticationForm
6+
from django.contrib.auth import get_user_model
7+
from django.contrib.auth.forms import UserCreationForm, AuthenticationForm as _AuthenticationForm
48

59
from api.utils import send_activation_email
610

11+
User = get_user_model()
12+
713

814
class AuthenticationForm(_AuthenticationForm):
915

@@ -15,3 +21,32 @@ def confirm_login_allowed(self, user):
1521
code="inactive",
1622
)
1723
return super().confirm_login_allowed(user)
24+
25+
26+
class RegistrationForm(UserCreationForm):
27+
28+
recaptcha_token = forms.CharField(
29+
label=_("reCAPTCHA token"),
30+
widget=forms.HiddenInput(attrs={"name": "g-recaptcha-response"}),
31+
strip=False,
32+
required=False,
33+
help_text=_("Google recaptcha token hidden field"),
34+
)
35+
36+
def clean_recaptcha_token(self):
37+
recaptcha_token = self.data.get("g-recaptcha-response")
38+
if settings.GOOGLE_RE_CAPTCHA_KEY and settings.GOOGLE_RE_CAPTCHA_SECRET:
39+
success = requests.post('https://www.recaptcha.net/recaptcha/api/siteverify', data={
40+
'secret': settings.GOOGLE_RE_CAPTCHA_SECRET,
41+
'response': recaptcha_token,
42+
}).json()["success"]
43+
if not success:
44+
raise ValidationError(
45+
_('Error verifying reCAPTCHA, please try again.'),
46+
code="captcha_invalid",
47+
)
48+
return recaptcha_token
49+
50+
class Meta(UserCreationForm.Meta):
51+
model = User
52+
fields = ('username', 'email', 'password1', 'password2')

rootfs/api/oauth2_validators.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
from oauth2_provider.oauth2_validators import OAuth2Validator
2+
3+
4+
class CustomOAuth2Validator(OAuth2Validator):
5+
6+
def get_additional_claims(self, request):
7+
claims = super().get_additional_claims(request)
8+
claims["id"] = request.user.id
9+
claims["name"] = request.user.username
10+
claims["username"] = request.user.username
11+
claims["email"] = request.user.email
12+
claims["first_name"] = request.user.first_name
13+
claims["last_name"] = request.user.last_name
14+
claims["is_staff"] = request.user.is_staff
15+
claims["is_active"] = request.user.is_active
16+
claims["is_superuser"] = request.user.is_superuser
17+
return claims

rootfs/api/serializers.py

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,8 @@
44
import logging
55

66
from django.contrib.admin.models import LogEntry
7-
from django.contrib.auth.forms import UserCreationForm
87
from django.contrib.auth import get_user_model
98
from oauth2_provider.models import Grant, AccessToken
10-
from oauth2_provider.oauth2_validators import OAuth2Validator
119
from rest_framework import serializers
1210

1311
from api.utils import timestamp2datetime
@@ -16,12 +14,6 @@
1614
logger = logging.getLogger(__name__)
1715

1816

19-
class RegistrationForm(UserCreationForm):
20-
class Meta(UserCreationForm.Meta):
21-
model = User
22-
fields = ('username', 'email', 'password1', 'password2')
23-
24-
2517
class UserSerializer(serializers.ModelSerializer):
2618
class Meta:
2719
model = User
@@ -81,19 +73,3 @@ class Meta:
8173
fields = '__all__'
8274
read_only_fields = ['action_time', 'user', 'content_type', 'object_id',
8375
'object_repr', 'action_flag', 'change_message']
84-
85-
86-
class CustomOAuth2Validator(OAuth2Validator):
87-
88-
def get_additional_claims(self, request):
89-
claims = super().get_additional_claims(request)
90-
claims["id"] = request.user.id
91-
claims["name"] = request.user.username
92-
claims["username"] = request.user.username
93-
claims["email"] = request.user.email
94-
claims["first_name"] = request.user.first_name
95-
claims["last_name"] = request.user.last_name
96-
claims["is_staff"] = request.user.is_staff
97-
claims["is_active"] = request.user.is_active
98-
claims["is_superuser"] = request.user.is_superuser
99-
return claims

rootfs/api/settings/production.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@
2020
# will be suppressed, and exceptions will propagate upwards
2121
# https://docs.djangoproject.com/en/2.2/ref/settings/#debug-propagate-exceptions
2222
DEBUG_PROPAGATE_EXCEPTIONS = True
23+
24+
# Enable Legal
25+
LEGAL_ENABLED = bool(strtobool(os.environ.get('LEGAL_ENABLED', 'false')))
2326
# Enable Django admin
2427
ADMIN_ENABLED = bool(strtobool(os.environ.get('ADMIN_ENABLED', 'false')))
2528
# Enable Registration
@@ -64,6 +67,7 @@
6467
'APP_DIRS': True,
6568
'OPTIONS': {
6669
'context_processors': [
70+
"api.context_processors.legal",
6771
"django.contrib.auth.context_processors.auth",
6872
"django.template.context_processors.debug",
6973
"django.template.context_processors.i18n",
@@ -285,7 +289,7 @@
285289
OAUTH2_PROVIDER = {
286290
"OIDC_ENABLED": True,
287291
"OIDC_RSA_PRIVATE_KEY": OIDC_RSA_PRIVATE_KEY,
288-
"OAUTH2_VALIDATOR_CLASS": "api.serializers.CustomOAuth2Validator",
292+
"OAUTH2_VALIDATOR_CLASS": "api.oauth2_validators.CustomOAuth2Validator",
289293
"PKCE_REQUIRED": False,
290294
"ALLOWED_REDIRECT_URI_SCHEMES": ["http", "https"],
291295
"ACCESS_TOKEN_EXPIRE_SECONDS": int(os.environ.get('ACCESS_TOKEN_EXPIRE_SECONDS', 30 * 86400)), # noqa
@@ -386,4 +390,4 @@
386390
EMAIL_USE_SSL = bool(strtobool(os.environ.get('EMAIL_USE_SSL', 'false')))
387391

388392
GOOGLE_RE_CAPTCHA_KEY = os.environ.get("GOOGLE_RE_CAPTCHA_KEY")
389-
GOOGLE_RE_CAPTCHA_SECRET = os.environ.get("GOOGLE_RE_CAPTCHA_SECRET")
393+
GOOGLE_RE_CAPTCHA_SECRET = os.environ.get("GOOGLE_RE_CAPTCHA_SECRET")

rootfs/api/static/css/main.css

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ body {
2727
position: relative;
2828
height: 100%;
2929
text-align: center;
30-
padding-top: 10%;
30+
padding-top: 2%;
3131
}
3232

3333
h1.logo {
@@ -62,10 +62,6 @@ h1.logo a:before {
6262
border-image: initial;
6363
}
6464

65-
.panel div {
66-
margin-top: 30px
67-
}
68-
6965
.panel .h3 {
7066
margin: 40px 20px 0;
7167
line-height: 1.5;
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<footer class="logo-sfdc">
2+
<ul class="legal">
3+
{% if LEGAL_ENABLED %}
4+
<li><a href="https://drycc.cc" rel="nofollow">Drycc Documents</a></li>
5+
<li><a href="https://legal.doopai.com/#/cloud-services-terms" rel="nofollow">Terms of Service</a></li>
6+
<li><a href="https://legal.doopai.com/#/doopai-privacy-policy" rel="nofollow">Privacy</a></li>
7+
<li><a href="https://legal.doopai.com/#/doopai-cookie-policy" rel="nofollow">Cookies</a></li>
8+
<li>© {% now 'Y' %} drycc.com</li>
9+
{% else %}
10+
<li><a href="https://drycc.cc" rel="nofollow">Drycc Documents</a></li>
11+
<li><a href="https://github.com/drycc" rel="nofollow">Open Source</a></li>
12+
<li><a href="https://drycc.slack.com/" rel="nofollow">Community</a></li>
13+
<li><a href="https://github.com/drycc/workflow/issues" rel="nofollow">Support</a></li>
14+
<li>© {% now 'Y' %} drycc.cc</li>
15+
{% endif %}
16+
</ul>
17+
</footer>

rootfs/api/templates/oauth2_provider/authorize.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,5 +39,6 @@ <h2 class="h3">{{ error.error }}</h2>
3939
{% endif %}
4040
</div>
4141
</div>
42+
{% include "base/footer.html" %}
4243
</div>
4344
</body>

rootfs/api/templates/user/footer.html

Lines changed: 0 additions & 8 deletions
This file was deleted.

rootfs/api/templates/user/login.html

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,14 @@ <h2 class="h3">Log in to your account</h2>
2929
<input type="hidden" name="next" value={{ next }}>
3030
</form>
3131
{% if registration_enabled %}
32-
<a class="panel-footer" href="/user/registration/"><span>Sign Up</span></a>
32+
<a class="panel-footer" href="/user/registration/">New to Drycc? <span>Sign Up</span></a>
3333
{% endif %}
3434
</div>
3535
{% if password_reset_enabled %}
36-
<a href="/user/password_reset/" class="white-link">Forgot your password?</a>
36+
<div>
37+
<a href="/user/password_reset/" class="white-link">Forgot your password?</a>
38+
</div>
3739
{% endif %}
3840
</div>
39-
{% include "user/footer.html" %}
41+
{% include "base/footer.html" %}
4042
</div>

0 commit comments

Comments
 (0)