diff --git a/requirements/base.in b/requirements/base.in index adb572227b7d9c760872e3ece624430d1ef2f2f9..cd4092b59be37f9e690b940b8172f59dbad8ef47 100644 --- a/requirements/base.in +++ b/requirements/base.in @@ -3,4 +3,8 @@ djangorestframework~=3.14 django-solo~=2.0 django-import-export~=3.1 celery~=5.2 -social-auth-app-django~=5.0 \ No newline at end of file +django-health-check +sentry-sdk[django] +django-extensions +drf-oidc-auth +django-minio-backend \ No newline at end of file diff --git a/src/authsch/__init__.py b/src/authsch/__init__.py deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/src/authsch/apps.py b/src/authsch/apps.py deleted file mode 100644 index 13882bac31bad2b60b80e7ab11c2e860621bfcd0..0000000000000000000000000000000000000000 --- a/src/authsch/apps.py +++ /dev/null @@ -1,6 +0,0 @@ -# Original: https://git.sch.bme.hu/kszk/devteam/django-authsch -from django.apps import AppConfig - - -class AuthschConfig(AppConfig): - name = 'authsch' diff --git a/src/authsch/authentication.py b/src/authsch/authentication.py deleted file mode 100644 index 86d633478edb207219b12f991a41c0398e5d1580..0000000000000000000000000000000000000000 --- a/src/authsch/authentication.py +++ /dev/null @@ -1,35 +0,0 @@ -# Original: https://git.sch.bme.hu/kszk/devteam/django-authsch -# store schacc in username field -from social_core.backends.oauth import BaseOAuth2 - - -class AuthSCHOAuth2(BaseOAuth2): - """AuthSCH OAuth2 authentication backend""" - name = 'authsch' - ID_KEY = 'internal_id' - AUTHORIZATION_URL = 'https://auth.sch.bme.hu/site/login' - ACCESS_TOKEN_URL = 'https://auth.sch.bme.hu/oauth2/token' - ACCESS_TOKEN_METHOD = 'POST' - REFRESH_TOKEN_URL = 'https://auth.sch.bme.hu/oauth2/token' - DEFAULT_SCOPE = ['basic', 'mail', 'givenName', 'sn', 'linkedAccounts'] - EXTRA_DATA = [ - ('internal_id', 'id'), - ('expires_in', 'expires'), - ('refresh_token', 'refresh_token'), - ] - - def get_user_details(self, response): - """Return user details from AuthSCH account""" - return { - 'username': response.get('linkedAccounts').get('schacc'), - 'email': response.get('mail'), - 'first_name': response.get('givenName'), - 'last_name': response.get('sn') - } - - def user_data(self, access_token, *args, **kwargs): - """Loads user data from service""" - return self.get_json( - 'https://auth.sch.bme.hu/api/profile/', - params={'access_token': access_token} - ) diff --git a/src/kszkepzes/oidc_auth.py b/src/kszkepzes/oidc_auth.py new file mode 100644 index 0000000000000000000000000000000000000000..97dc54b0526a57441112b9c5f567e5f04237a8cf --- /dev/null +++ b/src/kszkepzes/oidc_auth.py @@ -0,0 +1,20 @@ +from mozilla_django_oidc.auth import OIDCAuthenticationBackend + + +class JSOIDCAuthBackend(OIDCAuthenticationBackend): + def create_user(self, claims): + user = super(JSOIDCAuthBackend, self).create_user(claims) + user.first_name = claims.get('given_name', '') + user.last_name = claims.get('family_name', '') + user.save() + return user + + def update_user(self, user, claims): + user.first_name = claims.get('given_name', '') + user.last_name = claims.get('family_name', '') + user.save() + return user + + +def generate_username(email: str): + return email.split('@')[0] diff --git a/src/kszkepzes/settings/base.py b/src/kszkepzes/settings/base.py index b84b0721e5370b8d149606acacc17d56f86e0055..019c7d09c7dbf4283ef8f2adcd8811e69c3216bf 100644 --- a/src/kszkepzes/settings/base.py +++ b/src/kszkepzes/settings/base.py @@ -43,9 +43,11 @@ INSTALLED_APPS = [ 'import_export', 'rest_framework', "rest_framework_api_key", - 'social_django', + "rest_framework.authtoken", 'solo', - 'authsch', + 'oidc_auth', + 'mozilla_django_oidc', + 'django_minio_backend.apps.DjangoMinioBackendConfig', 'homework', 'account', 'stats', @@ -55,6 +57,12 @@ INSTALLED_APPS = [ 'images', 'groups', 'drf_yasg', + 'health_check', # required + 'health_check.contrib.migrations', + 'health_check.contrib.redis', # requires Redis broker + 'health_check.db', # stock Django health checkers + 'health_check.contrib.celery', # requires celery + 'health_check.contrib.celery_ping', # requires celery ] MIDDLEWARE = [ @@ -65,6 +73,7 @@ MIDDLEWARE = [ 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', + 'mozilla_django_oidc.middleware.SessionRefresh', ] ROOT_URLCONF = 'kszkepzes.urls' @@ -117,31 +126,39 @@ AUTH_PASSWORD_VALIDATORS = [ }, ] -SOCIAL_AUTH_URL_NAMESPACE = 'social' AUTHENTICATION_BACKENDS = [ - 'authsch.authentication.AuthSCHOAuth2', - 'django.contrib.auth.backends.ModelBackend', + 'backend.oidc_auth.JSOIDCAuthBackend', ] -SOCIAL_AUTH_PIPELINE = ( - 'social_core.pipeline.social_auth.social_details', - 'social_core.pipeline.social_auth.social_uid', - 'social_core.pipeline.social_auth.auth_allowed', - 'social_core.pipeline.social_auth.social_user', - 'social_core.pipeline.user.get_username', - 'social_core.pipeline.user.create_user', - 'account.auth_pipeline.create_profile', - 'social_core.pipeline.social_auth.associate_user', - 'social_core.pipeline.social_auth.load_extra_data', - 'social_core.pipeline.user.user_details', -) - -SOCIAL_AUTH_AUTHSCH_KEY = os.getenv('AUTHSCH_KEY') -SOCIAL_AUTH_AUTHSCH_SECRET = os.getenv('AUTHSCH_SECRET') -SOCIAL_AUTH_LOGIN_REDIRECT_URL = '/' -LOGIN_URL = "login/authsch/" -LOGOUT_REDIRECT_URL = '/' + +REST_FRAMEWORK = { + 'DEFAULT_RENDERER_CLASSES': ( + 'rest_framework.renderers.JSONRenderer', + ), + 'DEFAULT_PARSER_CLASSES': ( + 'rest_framework.parsers.JSONParser', + ), + 'DEFAULT_SCHEMA_CLASS': 'drf_spectacular.openapi.AutoSchema', + 'DEFAULT_AUTHENTICATION_CLASSES': [ + 'mozilla_django_oidc.contrib.drf.OIDCAuthentication', + 'rest_framework.authentication.SessionAuthentication', + ], +} + + +OIDC_RP_CLIENT_ID = os.environ.get('OIDC_CLIENT_ID') +OIDC_RP_CLIENT_SECRET = os.environ.get('OIDC_CLIENT_SECRET') +OIDC_OP_AUTHORIZATION_ENDPOINT = os.environ.get('OIDC_AUTHORIZATION_ENDPOINT') +OIDC_OP_TOKEN_ENDPOINT = os.environ.get('OIDC_TOKEN_ENDPOINT') +OIDC_OP_USER_ENDPOINT = os.environ.get('OIDC_USERINFO_ENDPOINT') +OIDC_OP_JWKS_ENDPOINT = os.environ.get('OIDC_JWKS_ENDPOINT') +OIDC_RP_SIGN_ALGO = os.environ.get('OIDC_SIGN_ALGO', 'RS256') +OIDC_EXEMPT_URLS = ["/healthz/", "/admin/", "/oidc/"] +LOGIN_REDIRECT_URL = "/" +LOGOUT_REDIRECT_URL = "/" +OIDC_USERNAME_ALGO = 'backend.oidc_auth.generate_username' + # Internationalization # https://docs.djangoproject.com/en/1.11/topics/i18n/ @@ -165,3 +182,4 @@ STATIC_ROOT = os.path.join(BASE_DIR, "staticfiles") MEDIA_URL = "/mediafiles/" MEDIA_ROOT = os.path.join(BASE_DIR, "mediafiles") + diff --git a/src/kszkepzes/settings/production.py b/src/kszkepzes/settings/production.py index 37fa5eb19ff3ca8e3f663283087127e4ac24dcf5..82c7207b4f9b6a0def59b1d9ce4b7c3f2954c94a 100644 --- a/src/kszkepzes/settings/production.py +++ b/src/kszkepzes/settings/production.py @@ -15,15 +15,6 @@ DATABASES = { } } -REST_FRAMEWORK = { - 'DEFAULT_RENDERER_CLASSES': ( - 'rest_framework.renderers.JSONRenderer', - ), - 'DEFAULT_PARSER_CLASSES': ( - 'rest_framework.parsers.JSONParser', - ) -} - EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend' EMAIL_HOST = os.getenv('SMTP_HOST', 'smtp.office365.com') EMAIL_PORT = 587 @@ -35,3 +26,27 @@ CELERY_BROKER_URL = os.getenv('CELERY_BROKER_URL') CELERY_RESULT_BACKEND = os.getenv('CELERY_BROKER_URL') CSRF_TRUSTED_ORIGINS = [os.getenv('CSRF_TRUSTED_ORIGINS')] + +FILE_UPLOAD_DIR = os.environ.get("FILE_UPLOAD_DIR") + +#Minio Stuff +MINIO_CONSISTENCY_CHECK_ON_START = True +MINIO_EXTERNAL_ENDPOINT = os.environ.get("MINIO_EXTERNAL_ENDPOINT") +MINIO_EXTERNAL_ENDPOINT_USE_HTTPS = True +MINIO_ENDPOINT = os.environ.get("MINIO_ACCESS_ENDPOINT") +MINIO_USE_HTTPS = False +MINIO_REGION = 'us-east-1' +MINIO_ACCESS_KEY = os.environ.get("MINIO_ACCESS_KEY") +MINIO_SECRET_KEY = os.environ.get("MINIO_SECRET_KEY") +MINIO_URL_EXPIRY_HOURS = timedelta(hours=2) +MINIO_CONSISTENCY_CHECK_ON_START = True +MINIO_PUBLIC_BUCKETS = [ + os.environ.get('MINIO_STATIC_BUCKET'), + os.environ.get('MINIO_MEDIA_BUCKET') +] +MINIO_POLICY_HOOKS: List[Tuple[str, dict]] = [] +MINIO_MEDIA_FILES_BUCKET = os.environ.get('MINIO_MEDIA_BUCKET') +MINIO_STATIC_FILES_BUCKET = os.environ.get('MINIO_STATIC_BUCKET') +MINIO_BUCKET_CHECK_ON_SAVE = True +DEFAULT_FILE_STORAGE = 'django_minio_backend.models.MinioBackend' +STATICFILES_STORAGE = 'django_minio_backend.models.MinioBackendStatic' diff --git a/src/kszkepzes/urls.py b/src/kszkepzes/urls.py index ff01eab0b222a59e74c79672a1e875d010a54e7f..89b5af48b3991556131b92132955469b48554185 100644 --- a/src/kszkepzes/urls.py +++ b/src/kszkepzes/urls.py @@ -29,7 +29,6 @@ urlpatterns = [ re_path(r'^api/v1/redoc/$', schema_view.with_ui('redoc', cache_timeout=0), name='schema-redoc'), re_path(r'^admin/', admin.site.urls), - re_path(r'^api/v1/', include('social_django.urls', namespace='social')), re_path(r'^api/v1/homework/', include('homework.urls')), re_path(r'^api/v1/', include('stats.urls')), re_path(r'^api/v1/', include('account.urls')), @@ -38,7 +37,9 @@ urlpatterns = [ re_path(r'^api/v1/', include('groups.urls')), re_path(r'^api/v1/', include('mentors.urls')), re_path(r'^api/v1/', include('images.urls')), - re_path(r'^api/v1/logout/$', auth_views.LogoutView.as_view(), name='logout'), + re_path(r'^healthz/', include('health_check.urls')), + re_path(r'^oidc/', include('mozilla_django_oidc.urls')), + ] if settings.DEBUG: