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
103 changes: 16 additions & 87 deletions package-lock.json

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ dependencies = [
"djangorestframework-simplejwt[crypto]~=5.5.1",
"djangorestframework~=3.17.1",
"django~=5.2.8",
"dj-rest-auth~=7.2.0",
"drf-spectacular[sidecar]~=0.29.0",
"easy-thumbnails~=2.10.1",
"flower~=2.0.1",
Expand Down Expand Up @@ -167,7 +168,7 @@ line-ending = "auto"
src_paths = ["wger", "extras"]

sections = ["FUTURE", "STDLIB", "DJANGO", "THIRDPARTY", "FIRSTPARTY", "LOCALFOLDER"]
skip = ["extras", "build", "dist", "node_modules", "migrations", "docs", "settings", "apps.py"]
skip = ["extras", "build", "dist", "node_modules", "migrations", "docs", "settings", "apps.py", "venv", ".venv", ]
# If set to true - ensures that if a star import is present, nothing else is
# imported from that namespace.
combine_star = false
Expand Down
25 changes: 15 additions & 10 deletions settings/ci.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
# This file is part of wger Workout Manager.
# This file is part of wger Workout Manager <https://github.com/wger-project>.
# Copyright (C) 2013 - 2026 wger Team
#
# wger Workout Manager is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# wger Workout Manager is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# wger Workout Manager is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# wger Workout Manager is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.

# ruff: noqa: F405, F403

Expand All @@ -31,6 +33,9 @@
WGER_SETTINGS['ALLOW_UPLOAD_VIDEOS'] = False
WGER_SETTINGS['MIN_ACCOUNT_AGE_TO_TRUST'] = 21 # in days
WGER_SETTINGS['EXERCISE_CACHE_TTL'] = 3600 # in seconds
WGER_SETTINGS['USE_SOCIAL_AUTH'] = False
WGER_SETTINGS['USE_GITHUB_AUTH'] = False
WGER_SETTINGS['USE_FACEBOOK_AUTH'] = False

DATABASES = {
'default': {
Expand Down
3 changes: 3 additions & 0 deletions settings/local_dev.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@
WGER_SETTINGS['CACHE_API_EXERCISES_CELERY'] = True
WGER_SETTINGS['CACHE_API_EXERCISES_CELERY_FORCE_UPDATE'] = True
WGER_SETTINGS['ROUTINE_CACHE_TTL'] = 500
WGER_SETTINGS['USE_SOCIAL_AUTH'] = True
WGER_SETTINGS['USE_GITHUB_AUTH'] = True
WGER_SETTINGS['USE_FACEBOOK_AUTH'] = True
DEFAULT_FROM_EMAIL = WGER_SETTINGS['EMAIL_FROM']


Expand Down
7 changes: 7 additions & 0 deletions settings/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,13 @@
'AXES_IPWARE_META_PRECEDENCE_ORDER', default=['REMOTE_ADDR']
)

#
# Django-allauth
# Dj-rest-auth
#
WGER_SETTINGS['USE_SOCIAL_AUTH'] = env.bool('USE_SOCIAL_AUTH', False)
WGER_SETTINGS['USE_GITHUB_AUTH'] = env.bool('USE_GITHUB_AUTH', False)
WGER_SETTINGS['USE_FACEBOOK_AUTH'] = env.bool('USE_FACEBOOK_AUTH', False)
#
# Django Rest Framework SimpleJWT
#
Expand Down
65 changes: 65 additions & 0 deletions settings/settings_global.py
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@
'wger.core.backends.AuthProxyUserBackend',
'django.contrib.auth.backends.ModelBackend',
'wger.utils.helpers.EmailAuthBackend',
'allauth.account.auth_backends.AuthenticationBackend',
)

TEMPLATES = [
Expand Down Expand Up @@ -222,6 +223,38 @@
ACCOUNT_EMAIL_CONFIRMATION_EXPIRE_DAYS = 2
ACCOUNT_ADAPTER = 'wger.core.account_adapter.WgerAccountAdapter'

SOCIALACCOUNT_PROVIDERS = {
'google': {
'SCOPE': [
'profile',
'email',
],
'AUTH_PARAMS': {
'access_type': 'online',
},
'OAUTH_PKCE_ENABLED': True,
},
'github': {
'SCOPE': ['user:email'],
'APP': {
'client_id': '',
'secret': '',
'key': '',
},
},
'facebook': {
'METHOD': 'oauth2',
'SCOPE': ['email', 'public_profile'],
'FIELDS': ['id', 'email', 'name', 'first_name', 'last_name'],
'EXCHANGE_TOKEN': True,
'LOCALE_FUNC': lambda request: 'en_US',
'VERSION': 'v18.0',
},
}

ACCOUNT_LOGOUT_ON_GET = True
SOCIALACCOUNT_LOGIN_ON_GET = True

#
# Login
#
Expand Down Expand Up @@ -428,6 +461,11 @@
'UPDATE_LAST_LOGIN': False,
}

#
# Dj-rest-auth
#
REST_USE_JWT = True

#
# CORS headers: allow all hosts to access the API
#
Expand Down Expand Up @@ -489,8 +527,35 @@
# Trophy system settings
'TROPHIES_ENABLED': True,
'TROPHIES_INACTIVE_USER_DAYS': 30, # Days of inactivity before skipping trophy evaluation
# Social authentication/Oauth
'USE_SOCIAL_AUTH': True, # GOOGLE
'USE_GITHUB_AUTH': True,
'USE_FACEBOOK_AUTH': False,
}

#
# Django-allauth
# Dj-rest-auth
#
if WGER_SETTINGS.get('USE_SOCIAL_AUTH', False):
_social_apps = [

'allauth.socialaccount',
'allauth.socialaccount.providers.google',

'dj_rest_auth',
'dj_rest_auth.registration',

]

if WGER_SETTINGS.get('USE_GITHUB_AUTH', False):
_social_apps.append('allauth.socialaccount.providers.github')

if WGER_SETTINGS.get('USE_FACEBOOK_AUTH', False):
_social_apps.append('allauth.socialaccount.providers.facebook')

INSTALLED_APPS += _social_apps

#
# Auth Proxy Authentication
#
Expand Down
12 changes: 12 additions & 0 deletions uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

61 changes: 61 additions & 0 deletions wger/core/api/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
# Django
from django.conf import settings
from django.contrib.auth.models import User
from django.contrib.sites.models import Site
from django.utils.decorators import method_decorator
from django.views.decorators.cache import cache_page

Expand Down Expand Up @@ -51,6 +52,20 @@
)
from rest_framework.response import Response


if settings.WGER_SETTINGS.get('USE_SOCIAL_AUTH'):
# Third Party
from allauth.socialaccount.providers.google.views import GoogleOAuth2Adapter
from allauth.socialaccount.providers.oauth2.client import OAuth2Client
from dj_rest_auth.registration.views import SocialLoginView

if settings.WGER_SETTINGS.get('USE_GITHUB_AUTH'):
# Third Party
from allauth.socialaccount.providers.github.views import GitHubOAuth2Adapter

if settings.WGER_SETTINGS.get('USE_FACEBOOK_AUTH'):
from allauth.socialaccount.providers.facebook.views import FacebookOAuth2Adapter

# wger
from wger.core.api.serializers import (
LanguageCheckSerializer,
Expand Down Expand Up @@ -374,6 +389,52 @@ def post(self, request):
)


if settings.WGER_SETTINGS.get('USE_SOCIAL_AUTH', False):

class GoogleLogin(SocialLoginView):
"""
REST endpoint to exchange a Google Access Token for a wger API JWT.
Flutter sends the Google accessToken here.
"""

adapter_class = GoogleOAuth2Adapter
client_class = OAuth2Client

@property
def callback_url():
base_url = Site.objects.get_current()
return f'http://${base_url.domain}/accounts/google/login/callback/'

if settings.WGER_SETTINGS.get('USE_GITHUB_AUTH', False):
"""
REST endpoint to exchange a GitHub OAuth2 Access Token for a wger API JWT.
Flutter sends the GitHub accessToken here."""

class GithubLogin(SocialLoginView):
adapter_class = GitHubOAuth2Adapter
client_class = OAuth2Client

@property
def callback_url(self):
base_url = Site.objects.get_current()
return f'http://{base_url.domain}/accounts/github/login/callback/'

if settings.WGER_SETTINGS.get('USE_FACEBOOK_AUTH'):

class FacebookLogin(SocialLoginView):
"""
REST endpoint to exchange a Facebook Access Token for a wger API JWT.
Flutter sends the Facebook accessToken here."""

adaptor_class = FacebookOAuth2Adapter
client_class = OAuth2Client

@property
def callback(self):
base_url = Site.objects.get_current()
return f'{base_url.domain}/accounts/facebook/login/callback'


class LanguageViewSet(viewsets.ReadOnlyModelViewSet):
"""
API endpoint for the languages used in the application
Expand Down
Loading
Loading