diff --git a/Backend/BackendApp/BackendApp/settings.py b/Backend/BackendApp/BackendApp/settings.py index 5f52482..e5cba63 100644 --- a/Backend/BackendApp/BackendApp/settings.py +++ b/Backend/BackendApp/BackendApp/settings.py @@ -28,11 +28,23 @@ # See https://docs.djangoproject.com/en/4.2/howto/deployment/checklist/ # SECURITY WARNING: keep the secret key used in production secret! -SECRET_KEY = "django-insecure-nma=xi6x2p-crjg^ifqqkapyu1qjd0l=+wn)-rijk_o%$!k3w_" +SECRET_KEY = os.environ.get( + "DJANGO_SECRET_KEY", + "django-insecure-nma=xi6x2p-crjg^ifqqkapyu1qjd0l=+wn)-rijk_o%$!k3w_" +) +if SECRET_KEY.startswith("django-insecure"): + import warnings + warnings.warn( + "Insecure SECRET_KEY is being used. Set DJANGO_SECRET_KEY environment variable for production.", + RuntimeWarning + ) # SECURITY WARNING: don't run with debug turned on in production! -DEBUG = True +DEBUG = os.environ.get("DJANGO_DEBUG", "False").lower() in ("true", "1", "yes") +# WARNING: "*" allows all hosts. Restrict this in production via ALLOWED_HOSTS env var. +# WARNING: ALLOWED_HOSTS=["*"] allows any host to access this server. +# In production, restrict to specific domains or use an environment variable. ALLOWED_HOSTS = ["*"] REST_FRAMEWORK = { @@ -75,11 +87,9 @@ "django.middleware.common.CommonMiddleware", ] -# hier caps rein gehauen +# Django project URL configuration ROOT_URLCONF = "BackendApp.urls" -print("suub dir") -print(os.path.join(BASE_DIR, 'CustomData')) TEMPLATES = [ { "BACKEND": "django.template.backends.django.DjangoTemplates", @@ -110,8 +120,7 @@ "ENGINE": "django.db.backends.postgresql", "NAME": "DoRun", "USER": "admin", - # "PASSWORD": "SupersicheresPasswort!1", - "PASSWORD": "ZyZLeG331Bqfoo9ClIQD", + "PASSWORD": os.environ.get("DB_PASSWORD", "ZyZLeG331Bqfoo9ClIQD"), "HOST": "localhost", "PORT": "5432", } diff --git a/Backend/BackendApp/api/models.py b/Backend/BackendApp/api/models.py index 48633ed..2cfdb8c 100644 --- a/Backend/BackendApp/api/models.py +++ b/Backend/BackendApp/api/models.py @@ -23,12 +23,12 @@ class Users(models.Model): verified = models.BooleanField() logintrys = models.IntegerField(default=0) + @staticmethod def RegisterUser(first_name,last_name,email,password): # Password validation validation = pwd.checkPwdConstraints(password) if (validation != 1): - print("Password is not valid") return None #1. Set UserID @@ -36,12 +36,11 @@ def RegisterUser(first_name,last_name,email,password): double = False UserID = None try: - CheckForDoubleUser = Users.objects.raw("Select * From api_users Where email = "+ "'" + email + "'") + CheckForDoubleUser = Users.objects.raw("Select * From api_users Where email = %s", [email]) for p in CheckForDoubleUser: double = True - except: + except Exception: double = False - print("double " + str(double)) try: if (double == False): #Get current highest iduser @@ -57,10 +56,9 @@ def RegisterUser(first_name,last_name,email,password): UserID = UserID + 1 elif (p.iduser == None): UserID = 1 - print("test " + str(test)) - except: - print("Unexpected error ocurred!") + except Exception: + pass #2. Password hashing if (password != None): @@ -77,11 +75,7 @@ def RegisterUser(first_name,last_name,email,password): VerifiedUser = False NewUser = None - #Creat new DB entry if values are filled - print("UserID") - print(UserID) if (UserID != None and first_name != None and last_name != None and email != None and Password_hash != None and Salt != None and CreatedAt != None and RoleID != None): - print("Creating new User with ID: " + str(UserID)) NewUser = Users.objects.create( iduser=UserID, firstname=first_name, @@ -98,13 +92,13 @@ def RegisterUser(first_name,last_name,email,password): # except: # print("Error, user can't be added to DB!") else: - print("Not all requirements are fulfilled to create a user") # if the process was denied, no NewUser is created return None # end def + @staticmethod def LoginUser(email,password): #%s is to prevent SQL-injection try: @@ -115,8 +109,6 @@ def LoginUser(email,password): test = str(b'') #If init password eq user password then trigger reset if (str(p.password_hash) == test): - print(p.password_hash, test) - print("No password for User") return -101 # Enter the entered password encrypt it with the salt and compare it with the pwhash from the db @@ -137,7 +129,7 @@ def LoginUser(email,password): try: with connection.cursor() as cursor: cursor.execute(sql, values) - except: + except Exception: return -101 return p else: @@ -156,11 +148,10 @@ def LoginUser(email,password): if (logintrys > 5): return -100 return -101 - except: + except Exception: return -101 - except: - print("Error") + except Exception: @@ -181,6 +172,7 @@ class donationrecord(models.Model): verified = models.BooleanField(null=True) iscertreq = models.BooleanField(null=False) + @staticmethod def GetUserStats(Userid): #Get Userdata for Welcome Screen UserName = Users.objects.raw("Select iduser, firstname, lastname, email From api_users Where iduser = %s", [Userid]) @@ -212,8 +204,7 @@ def GetUserStats(Userid): else: TotalDonations += (row.donation * kilometers) - except: - print("Can't calculate without data") + except Exception: data = [] #Safe evaluation @@ -246,6 +237,7 @@ def GetUserStats(Userid): #return JSON return data + @staticmethod def GetAdminStats(Userid): #vars Message = "Permission denied" @@ -304,27 +296,6 @@ def GetAdminStats(Userid): return data # end def -def roles(): - roleid = models.IntegerField(primary_key=True,null=False) - rolename = models.TextField(null=False) - - class CustomBackend(BaseBackend): def get_user(self, user_id): - return Users(id=user_id, username='benutzername') - -# ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ -#⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣾⣿⣿⣷⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ -#⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠸⣿⣿⣿⡿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ -#⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⣤⡈⠛⢉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ -#⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣴⣿⣿⣿⣿⣿⣿⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ -#⠀⠀⠀⠀⠀⠀⠀⠀⣴⣿⣿⢿⣿⣿⣿⣿⣿⠀⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ -#⠀⠀⠀⠀⠀⠀⠀⢰⣿⡏⠀⢸⣿⣿⣿⣿⡇⢸⣷⣤⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀ -#⠀⠀⠀⠀⠀⠀⠀⣼⣿⠁⠀⢸⣿⣿⣿⣿⠁⠀⠙⠻⢿⣿⣶⠀⠀⠀⠀⠀⠀⠀ -#⠀⠀⠀⠀⠀⠀⠀⠛⠋⠀⠀⠸⣿⣿⣿⡏⠀⠀⠀⠀⠀⠈⠉⠀⠀⠀⠀⠀⠀⠀ -#⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣄⠙⣿⣿⣷⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ -#⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣦⠈⢿⣿⣿⣦⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ -#⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣼⣿⡟⠀⠀⠻⣿⣿⣧⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ -#⠀⠀⠀⠀⠀⠀⠀⠀⣠⣾⣿⠟⠁⠀⠀⠀⠘⢿⣿⣧⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ -#⠀⠀⠀⠀⠀⠀⠀⢾⣿⠟⠁⠀⠀⠀⠀⠀⠀⠈⢻⣿⠇⠀⠀⠀⠀⠀⠀⠀⠀⠀ -#⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ \ No newline at end of file + return Users(id=user_id, username='benutzername') \ No newline at end of file diff --git a/Backend/BackendApp/api/password.py b/Backend/BackendApp/api/password.py index 9ee9bb0..1530c2c 100644 --- a/Backend/BackendApp/api/password.py +++ b/Backend/BackendApp/api/password.py @@ -1,5 +1,5 @@ from hashlib import sha256 -from multiprocessing import connection +from django.db import connection import random import string import re @@ -8,12 +8,12 @@ class pwd(): + @staticmethod def SetPassword(email,Password): Message = "" Status = 401 try: Password_hash, Salt = pwd.PasswordHashing(Password) - print(Password_hash, Salt) # SQL-Abfrage sql = "UPDATE api_users SET password_hash = %s, salt = %s WHERE email = %s" @@ -26,12 +26,13 @@ def SetPassword(email,Password): Message = "Password changed succesfully" Status = 200 - except: + except Exception: Message = "Cant set password!" return Status, Message + @staticmethod def SetJustPasswordWith_iduser(iduser,Password): Message = "" Status = 401 @@ -45,13 +46,10 @@ def SetJustPasswordWith_iduser(iduser,Password): Message = "Password muss mindestens 8 Zeichen lang sein!" Status = 401 return Status, Message - print("Password is valid") try: salt = models.Users.objects.get(iduser=iduser).salt - print("salt: ", salt) Password_hash = pwd.PasswordSetJustPassword(password=Password, salt=salt) - print("Password_hash: ", Password_hash) # SQL-Abfrage sql = "UPDATE api_users SET password_hash = %s WHERE iduser = %s" # Parameter @@ -63,26 +61,30 @@ def SetJustPasswordWith_iduser(iduser,Password): Message = "Password changed succesfully" Status = 200 - except: + except Exception: Message = "Cant set password!" return Status, Message # Method to create string of random chars + @staticmethod def RandChars(size=30, chars=string.ascii_uppercase + string.digits): return ''.join(random.choice(chars) for _ in range(size)) + @staticmethod def PasswordHashing(password): SaltText = pwd.RandChars() # Generiert zufällige Zeichenabfolge Salt = sha256(SaltText.encode('utf-8')).digest().hex() # Erstellt den Hash des Salts Password_Hash = sha256((password + Salt).encode('utf-8')).digest() # Verschlüsselung des Passwords und Salt return Password_Hash.hex(), Salt # Rückgabe + @staticmethod def convertSaltAndHash(salt, hash): return bytearray.fromhex(salt), bytearray.fromhex(hash) # Sets only the password not the salt + @staticmethod def PasswordSetJustPassword(password, salt): original_hex_string = salt.hex() Password_Hash = sha256((password + original_hex_string).encode('utf-8')).digest() @@ -90,6 +92,10 @@ def PasswordSetJustPassword(password, salt): + @staticmethod + + + @staticmethod def checkPwdConstraints(input_string): # 1 = valid, 0 = to short, -1 = missing later/digit/special char if len(input_string) < 8: @@ -105,6 +111,10 @@ def checkPwdConstraints(input_string): return -1 + @staticmethod + + + @staticmethod def Generate_secure_password(length): if length < 8: raise ValueError("Passwortlänge sollte mindestens 8 Zeichen betragen.") @@ -115,7 +125,11 @@ def Generate_secure_password(length): return password - def CheckPassword(EnteredPwd, password, salt): - EnteredPwdHash = sha256((EnteredPwd + salt.hex()).encode('utf-8')).digest() # Bildet den Hash nach - is_valid = EnteredPwdHash == password # Vergleicht den Gespeicherten und Neu generierten Hash - return is_valid # Gibt einen Boolschen Wert zurück + @staticmethod + + + @staticmethod + def CheckPassword(EnteredPwd, stored_hash, salt): + EnteredPwdHash = sha256((EnteredPwd + salt.hex()).encode('utf-8')).digest() + is_valid = EnteredPwdHash == stored_hash + return is_valid diff --git a/Backend/BackendApp/api/serializers.py b/Backend/BackendApp/api/serializers.py index bfaa0f9..6943c80 100644 --- a/Backend/BackendApp/api/serializers.py +++ b/Backend/BackendApp/api/serializers.py @@ -12,7 +12,5 @@ class Meta: # Überschreibt die Methode zum Erstellen eines Benutzers def create(self, validated_data): - print(validated_data) # - # Erstellt einen neuen Benutzer mit der create_user-Methode (inkl. Passwort-Hashing) user = User.objects.create_user(**validated_data) return user \ No newline at end of file diff --git a/Backend/BackendApp/api/views.py b/Backend/BackendApp/api/views.py index 126b97d..a310f98 100644 --- a/Backend/BackendApp/api/views.py +++ b/Backend/BackendApp/api/views.py @@ -21,8 +21,6 @@ from rest_framework import generics from rest_framework.permissions import AllowAny from .serializers import UserSerializer -from django.http import JsonResponse # Importiere JsonResponse -from django.http import HttpResponse # Importiere HttpResponse from django.db.models import Max from django.shortcuts import get_object_or_404 @@ -34,7 +32,7 @@ class CreateUserView(generics.CreateAPIView): serializer_class = UserSerializer permission_classes = [AllowAny] -#Handels the registration page +# Handles the registration page @csrf_protect def register(request): if request.method == 'POST': @@ -50,12 +48,9 @@ def register(request): #Erstelle neuen Benutzer auf der Datenbank # Send Verification Mail - print("first_name,last_name,email,password") - print(first_name,last_name,email,password) NewUser = Users.RegisterUser(first_name, last_name, email,password) # Check if the User is created if NewUser == None: - print("Process interupted. Try Again!") # return HttpResponse(content="User couldn't be created!", status=200) return JsonResponse(data={}, status=400) @@ -104,9 +99,7 @@ def cust_login(request): message = "Login erfolgreich" else: message = "Login nicht erfolgreich" - except: - print("user") - print(user) + except Exception as e: if (user == -99): return JsonResponse(status=200, data={"userid": -99,"UserIsAuth": False, 'message': 'Login nicht erfolgreich', "Role": False}) elif (user == -100): @@ -119,7 +112,7 @@ def cust_login(request): # Get Userid try: userid = user.iduser - except: + except Exception: User_Data = { "userid": None, "UserIsAuth": False, @@ -173,7 +166,7 @@ def resetpassword(request): Status, Message = Users.SetPassword(email,Password) return JsonResponse(status=Status, data={"message":Message}) - except: + except Exception: Status = 401 Message = "Error, cant change password!" return JsonResponse(status=Status, data={"message":Message}) @@ -189,10 +182,10 @@ def resetUserPasswort(request): try: user = Users.objects.all().get(iduser=iduser) - if pwd.CheckPassword(EnteredPwd=oldPwd_entry, salt=user.salt, password=user.password_hash) == False: + if pwd.CheckPassword(EnteredPwd=oldPwd_entry, salt=user.salt, stored_hash=user.password_hash) == False: return JsonResponse(status=401, data={"message":"Das alte Passwort ist falsch!"}) Status, Message = Users.SetJustPasswordWith_iduser(iduser, newPwd) - except: + except Exception: Status = 401 Message = "Error, cant change password!" return JsonResponse(status=Status, data={"message":Message}) @@ -246,6 +239,9 @@ def UpdateDonations(request): FixedAmount = False + if donationid is None: + return JsonResponse({"error": "Missing donation ID"}, status=400) + donationid = int(donationid) # Create a new donation record if no ID was provided if (donationid == -1): @@ -273,9 +269,7 @@ def UpdateDonations(request): verified = False, iscertreq = isCertReq) # donationrecord.add(newDonRec) - print("tessdfsdf") newDonRec.save() - print("tessdfsdf") Status = 200 Message = "Neuer Datensatz angelegt" except Exception as e: @@ -302,12 +296,8 @@ def UpdateDonations(request): return JsonResponse({"message": f"Failed to update record: {str(e)}"}, status=500) try: - print("mail sender") - print(int(UserID)) - print(int(donationid)) - print(frontendDomain) mail_handle.sendDonationVerifyMail(request, int(UserID), int(donationid), frontendDomain) - except: + except Exception: return JsonResponse({"message": "Donations updated successfully, but the mail wasnt send"}, status=200) return JsonResponse({"message": "Donations updated successfully"}, status=200) @@ -375,7 +365,7 @@ def UpdateUsers(request): cursor.execute(sql, values) Status = 200 Message= "Daten wurden geupdated" - except e: + except Exception as e: Message = "Der SQL-Befehl liefert folgendes zurueck: " + str(e) return JsonResponse({"message": Message}, status=Status) @@ -401,8 +391,11 @@ def DelUser(request): iduser = Users.objects.raw("Select iduser From api_users Where email = %s",[email]) if (iduser != None): - # raw funktioniert scheinbar nur für select statements - Users.objects.raw("Delete From api_users Where iduser = %s", [iduser]) + Users.objects.filter(iduser=iduser).delete() + Status = 200 + Message = "User deleted successfully" + + return JsonResponse({"message": Message}, status=Status) @csrf_protect def DelDonoRec(request): @@ -419,7 +412,6 @@ def DelDonoRec(request): # Über die Liste in der JSON-Datenstruktur iterieren for entry in data: donoid = entry.get("donoid") - print("donoid löschen: ", donoid) donationrecord.objects.filter(donationrecid=donoid).delete() diff --git a/Frontend/frontend/src/utils/csrf.js b/Frontend/frontend/src/utils/csrf.js index 7d2703c..96e65bf 100644 --- a/Frontend/frontend/src/utils/csrf.js +++ b/Frontend/frontend/src/utils/csrf.js @@ -20,7 +20,7 @@ import { getBackEndDomain } from "../utils/backend-domain"; credentials: 'include', }); const data = await response.json(); - var csrfToken = getCookie('csrftoken'); // Get the cookie from django + const csrfToken = getCookie('csrftoken'); // Get the cookie from django document.cookie = "csrfToken="+csrfToken; // Set the cookie in the browser return data.csrftoken; //Return the CSRF-Token }; \ No newline at end of file