diff --git a/api/urls.py b/api/urls.py index 987d2ed..e3740d6 100644 --- a/api/urls.py +++ b/api/urls.py @@ -11,4 +11,6 @@ urlpatterns = [ path('getchatrooms/', views.getchatrooms, name='api-getchatrooms'), path('getsinglechat/', views.getsinglechat, name='api-getsinglechat'), path('chatnewmessage/', views.savenewchatmessage, name='api-savechatmessage'), + # MIGRATION + path('migrateagencyusers/', views.migrateAgencyUsers, name="api-migrateagencyusers") ] \ No newline at end of file diff --git a/api/views.py b/api/views.py index a7037f8..daa15b5 100644 --- a/api/views.py +++ b/api/views.py @@ -1,6 +1,6 @@ from rest_framework.views import APIView from rest_framework.response import Response -from rest_framework.permissions import IsAuthenticated # <-- Here +#from rest_framework.permissions import IsAuthenticated # <-- Here import json from standards.models import Standards from rest_framework import serializers @@ -14,36 +14,37 @@ from django.http import HttpResponseRedirect,HttpResponse, JsonResponse from timemanagement.models import Absence + class GetUserId(APIView): - permission_classes = (IsAuthenticated,) # <-- And here + #permission_classes = (IsAuthenticated,) # <-- And here def post(self, request): return Response({"userid" : self.request.user.pk}) @api_view(['POST', ]) -@permission_classes((IsAuthenticated,)) +#@permission_classes((IsAuthenticated,)) def getStandardList(request): standards = Standards.objects.filter(agency=request.user.profile.agency) ser = StandardsSerializer(standards, many=True) return Response(ser.data, status=status.HTTP_200_OK) @api_view(['POST', ]) -@permission_classes((IsAuthenticated,)) +#@permission_classes((IsAuthenticated,)) def getSingleStandard(request, pk): standard = Standards.objects.get(pk=int(pk)) ser = StandardsSerializer(standard, many=False) return Response(ser.data, status=status.HTTP_200_OK) @api_view(['POST', ]) -@permission_classes((IsAuthenticated,)) +#@permission_classes((IsAuthenticated,)) def logoutByToken(request): print(request) request.user.auth_token.delete() return Response(status=status.HTTP_200_OK) @api_view(['POST', ]) -@permission_classes((IsAuthenticated,)) +#@permission_classes((IsAuthenticated,)) def getchatrooms(request): chatrooms = ChatRoom.objects.filter(creator=request.user) | ChatRoom.objects.filter(chatmember_single=request.user) chatrooms_ser = ChatRoomSerializer(chatrooms, many=True) @@ -51,7 +52,7 @@ def getchatrooms(request): @api_view(['POST', ]) -@permission_classes((IsAuthenticated,)) +#@permission_classes((IsAuthenticated,)) def getsinglechat(request, pk): chatroom = ChatRoom.objects.get(pk=pk) if chatroom.creator == request.user or chatroom.chatmember_single == request.user or (request.user in chatroom.chatmembers.all()): @@ -62,7 +63,7 @@ def getsinglechat(request, pk): @api_view(['POST', ]) -@permission_classes((IsAuthenticated,)) +#@permission_classes((IsAuthenticated,)) def savenewchatmessage(request): room = ChatRoom.objects.get(pk=request.POST["room"]) if(request.user == room.creator or request.user == room.chatmember_single): @@ -74,4 +75,15 @@ def savenewchatmessage(request): else: return Response(status=status.HTTP_403_FORBIDDEN) - +# IMPORTED MODELS FOR MIGRATION +from users.models import Agency +from django.contrib.auth.models import User + +@api_view(['GET', ]) +def migrateAgencyUsers(request, pk): + datapackage = {} + Ag = Agency.objects.get(pk=pk) + for user in User.objects.filter(profile__agency=Ag): + if(len(user.email) > 0 and len(user.first_name) > 0 and len(user.last_name) > 0): + datapackage.update({str(user.pk) : {"userid" : user.email, "displayname" : user.first_name + " " + user.last_name}}) + return JsonResponse(datapackage) \ No newline at end of file diff --git a/digitaleagentur/__pycache__/settings.cpython-38.pyc b/digitaleagentur/__pycache__/settings.cpython-38.pyc index 28f5167..c2a23f5 100644 Binary files a/digitaleagentur/__pycache__/settings.cpython-38.pyc and b/digitaleagentur/__pycache__/settings.cpython-38.pyc differ diff --git a/digitaleagentur/settings.py b/digitaleagentur/settings.py index 3eafca2..b057e85 100644 --- a/digitaleagentur/settings.py +++ b/digitaleagentur/settings.py @@ -109,7 +109,8 @@ MIDDLEWARE = [ 'django.middleware.clickjacking.XFrameOptionsMiddleware', 'django_user_agents.middleware.UserAgentMiddleware', 'simple_history.middleware.HistoryRequestMiddleware', - 'auditlog.middleware.AuditlogMiddleware' + 'auditlog.middleware.AuditlogMiddleware', + 'users.middleware.oauth.OAuthMiddleware' ] ROOT_URLCONF = 'digitaleagentur.urls' @@ -132,15 +133,18 @@ TEMPLATES = [ REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': ( - 'rest_framework.authentication.TokenAuthentication', + #'rest_framework.authentication.TokenAuthentication', + #'rest_framework.permissions.AllowAny', ), - 'DEFAULT_PERMISSION_CLASSES': [ - 'rest_framework.permissions.IsAuthenticated', - ], + #'DEFAULT_PERMISSION_CLASSES': [ + # 'rest_framework.permissions.IsAuthenticated', + #], } #WSGI_APPLICATION = 'digitaleagentur.wsgi.application' ASGI_APPLICATION = "digitaleagentur.routing.application" + + CHANNEL_LAYERS = { 'default': { 'BACKEND': 'channels_redis.core.RedisChannelLayer', @@ -152,6 +156,7 @@ CHANNEL_LAYERS = { + # Password validation # https://docs.djangoproject.com/en/2.2/ref/settings/#auth-password-validators diff --git a/requirements.txt b/requirements.txt index 684c26e..fe94bb4 100644 --- a/requirements.txt +++ b/requirements.txt @@ -36,3 +36,4 @@ xhtml2pdf==0.2.5 django-simple-captcha==0.5.13 auditlog3==1.0.1 filetype==1.0.7 +Authlib==0.15.3 \ No newline at end of file diff --git a/users/mainwebsocket.py b/users/mainwebsocket.py index aa843ab..ecd02c2 100644 --- a/users/mainwebsocket.py +++ b/users/mainwebsocket.py @@ -9,7 +9,7 @@ from django.contrib.auth.models import User from rest_framework.authtoken.models import Token class UsersConsumer(WebsocketConsumer): - + appconnect = False ''' diff --git a/users/middleware/__init__.py b/users/middleware/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/users/middleware/__pycache__/__init__.cpython-38.pyc b/users/middleware/__pycache__/__init__.cpython-38.pyc new file mode 100644 index 0000000..d713153 Binary files /dev/null and b/users/middleware/__pycache__/__init__.cpython-38.pyc differ diff --git a/users/middleware/__pycache__/oauth.cpython-38.pyc b/users/middleware/__pycache__/oauth.cpython-38.pyc new file mode 100644 index 0000000..dd9f9b0 Binary files /dev/null and b/users/middleware/__pycache__/oauth.cpython-38.pyc differ diff --git a/users/middleware/oauth.py b/users/middleware/oauth.py new file mode 100644 index 0000000..00bbfe4 --- /dev/null +++ b/users/middleware/oauth.py @@ -0,0 +1,108 @@ +from authlib.integrations.base_client import OAuthError +from authlib.integrations.django_client import OAuth +from authlib.oauth2.rfc6749 import OAuth2Token +from django.shortcuts import redirect +from django.utils.deprecation import MiddlewareMixin +from users.models import Agency, Profile +from django.contrib.auth.models import User +from django.contrib.auth import login +from digitaleagentur import settings + +class OAuthMiddleware(MiddlewareMixin): + + def __init__(self, get_response=None): + super().__init__(get_response) + self.oauth = OAuth() + + def process_request(self, request): + if settings.OAUTH_URL_WHITELISTS is not None: + for w in settings.OAUTH_URL_WHITELISTS: + if request.path.startswith(w): + return self.get_response(request) + + def update_token(token, refresh_token, access_token): + request.session['token'] = token + return None + + # Check, if logged user is in Database - if not, create and save by SUB + def checkUserInDatabase(userdata): + # Get sub of current user + sub = userdata + activeuser = None + # Check in Database, if user exist - if not, create new user + if not User.objects.filter(username = sub).exists(): + pr = Profile(user=None, agency=Agency.objects.get(pk=1)) + pr.save() + print(pr) + activeuser = User.objects.create(username=sub, profile=pr) + pr.user = activeuser + pr.save() + else: + activeuser = User.objects.get(username=sub) + + if activeuser is not None: + login(request, activeuser) + + sso_client = self.oauth.register( + settings.OAUTH_CLIENT_NAME, overwrite=True, **settings.OAUTH_CLIENT, update_token=update_token + ) + if request.path.startswith('/users/oauth/callback'): + self.clear_session(request) + request.session['token'] = sso_client.authorize_access_token(request) + if self.get_current_user(sso_client, request) is not None: + redirect_uri = request.session.pop('redirect_uri', None) + if redirect_uri is not None: + return redirect(redirect_uri) + return redirect('users-dashboard') + + if request.session.get('token', None) is not None: + #current_user = self.get_current_user(sso_client, request) + current_user = request.session.get('token').get('user_id') + if current_user is not None: + checkUserInDatabase(current_user) + return self.get_response(request) + + # remember redirect URI for redirecting to the original URL. + request.session['redirect_uri'] = request.path + return sso_client.authorize_redirect(request, settings.OAUTH_CLIENT['redirect_uri']) + + # fetch current login user info + # 1. check if it's in cache + # 2. fetch from remote API when it's not in cache + @staticmethod + def get_current_user(sso_client, request): + token = request.session.get('token', None) + if token is None or 'access_token' not in token: + return None + + if not OAuth2Token.from_dict(token).is_expired() and 'user' in request.session: + return request.session['user'] + + try: + res = sso_client.get(settings.OAUTH_CLIENT['userinfo_endpoint'], token=OAuth2Token(token)) + if res.ok: + print("OK WE ARE HERE!") + print(res) + #request.session['user'] = res.json() + #request.session['user'] = res + return True + #return res.json() + else: + print(res) + except OAuthError as e: + print(e) + + return None + + @staticmethod + def clear_session(request): + try: + del request.session['user'] + del request.session['token'] + except KeyError: + pass + + def __del__(self): + print('destroyed') + + diff --git a/users/templates/users/base.html b/users/templates/users/base.html index a591827..a6ca51e 100644 --- a/users/templates/users/base.html +++ b/users/templates/users/base.html @@ -875,7 +875,7 @@ $(document).on('click', function (e) { diff --git a/users/urls.py b/users/urls.py index fcf564b..07909f7 100644 --- a/users/urls.py +++ b/users/urls.py @@ -18,17 +18,11 @@ urlpatterns = [ path('logout/', auth_views.LogoutView.as_view(template_name='users/logout.html'), name='users-logout'), path('usersman/', permission_required('users.usermanager')(UsersManagement.as_view(template_name="users/users_management.html")), name='users-management'), path('usersman/adduser/', permission_required('users.usermanager')(UsersCreateUser.as_view(template_name="users/users_adduser.html")), name='users-adduser'), - #path('usersman/profile/', views.profile, name='users-profile'), - #path('usersman//', views.ProfileUpdateView, name='users-update'), - #path('usersman//', permission_required('users.usermanager')(ProfileUpdateView.as_view()), name='users-update'), path('usersman//perms', permission_required('users.usermanager')(UsersPermUpdateView.as_view()), name='users-perm-update'), path('usersman//delete', permission_required('users.usermanager')(ProfileDeleteView.as_view()), name='users-delete'), path('usersman/gd/', views.getDataFromToDelUser, name="users-delete-getdata"), path('userlog/', views.showUserLog, name="users-log"), - #path('agencyinfo/', views.agency, name='agencyinfo'), - #path('agencyinfo//', permission_required('users.agency_change')(AgencyUpdateView.as_view()), name='agency-manage'), path('usersman//prio', views.UsersPrio, name='users-prio'), - #path('prioupdate/', views.UsersPrioUpdate, name="users-prioupdate"), path('areataskupdate//', views.UsersAreaTaskUpdate, name="users-areataskupdate"), path('globalsearch/', views.GlobalSearch, name="globalsearch"), path('standardrout/', views.searchStandardRouter, name="standardrouter"), @@ -46,9 +40,9 @@ urlpatterns = [ path('icsall/', views.getICSFileAll, name="geticsall"), path('icspublic//', views.getICSFileEx, name="getics"), path('icspublicall//', views.getICSFileExAll, name="geticsall"), - path('updateuserorga/', views.UpdateUserOrga, name="update-user-orga") - #path('recalculateabsence/', views.recalculateAbsence, name="recalculateabsence"), - + path('updateuserorga/', views.UpdateUserOrga, name="update-user-orga"), + # OAUTH + path('oauth/callback', views.oauthCallBack, name="oauthcallback"), ]