irregular arbitrarily Cross-Origin request blocked error in Django on Ionos hosting - reactjs

I am currently making a quiz project for school. The quiz is supposed to evaluate in the front-end, which works perfectly fine, and after that it should send the information to the backend. The backend should save the details to the database and after that it should send the information back to the front-end. The front-end should show a message with some details about how you performed compared to all the others, the information is gotten from the database.
So, the weird thing about all that is that it works sometimes and sometimes not. If I test it on localhost, the code works perfectly fine. The error only occurs on the Ionos server (I got a hosting contract so I do not have access to the console).
Here is the link to my website: https://tor-netzwerk-seminarfach2024.com/ . If you click on the upper left corner and then on the quiz button, you will get to the quiz. If I look at the console and network analytics, when the error occurs, the following message shows up:
Cross-Origin request blocked: The same source rule prohibits reading
the external resource on https://api. tor-netzwerk-seminarfach2024.
com/apache-test/. (Reason: CORS request failed).
https://api.tor-netzwerk-seminarfach2024.com/apache-test/ is my backend and https://tor-netzwerk-seminarfach2024.com/ is my front-end.
The settings file in Django is not the problem. To make it clear, the error does not occur always. Sometimes you have to go again to the website and try it one a few more times until you get the error.
If I look at the network analytics, then I see that the client request works as usual, but the answer field from the server is completely empty. Let's move on to the weirdest part of all: the Data actually gets saved in the Database, there is just sometimes no response?
It would be way to much for a minimum working product but here is the most important code. If you want to test it you can just visit the link to my Website:https://tor-netzwerk-seminarfach2024.com/
Server side with Django
from rest_framework.response import Response
from .models import Lead
import json
from .serializer import TestingSerializer
def updateDigits():
leadObj = Lead.objects.all()
currentScore = leadObj[0].sumScore; currentRequests = leadObj[0].sumRequests
valueBtnOne = leadObj[0].buttonOne; valueBtnTwo = leadObj[0].buttonTwo;
valueBtnThree = leadObj[0].buttonThree; valueBtnFour = leadObj[0].buttonFour;
valueBtnFive = leadObj[0].buttonFive; valueBtnSix = leadObj[0].buttonSix;
valueBtnSeven = leadObj[0].buttonSeven; valueBtnEight = leadObj[0].buttonEight;
valueBtnNine = leadObj[0].buttonNine;
return [valueBtnOne,valueBtnTwo,valueBtnThree,valueBtnFour,valueBtnFive,valueBtnSix,valueBtnSeven,valueBtnEight,valueBtnNine,currentScore,currentRequests]
#api_view(["POST"])
def home(request):
body_unicode = request.body.decode('utf-8')
body = json.loads(body_unicode)
result = body["Result"]
isItRight = body["whichOnesRight"]
ip_adress = get_client_ip(request)
queryset = Lead.objects.all()
if Lead.objects.all().exists():
currentValues = updateDigits()
queryset.update(
sumScore = result + currentValues[9],
sumRequests = 1 + currentValues[10],
buttonOne = currentValues[0] + isItRight[0],
buttonTwo = currentValues[1] + isItRight[1],
buttonThree = currentValues[2] + isItRight[2],
buttonFour = currentValues[3] + isItRight[3],
buttonFive = currentValues[4] + isItRight[4],
buttonSix = currentValues[5] + isItRight[5],
buttonSeven = currentValues[6] + isItRight[6],
buttonEight = currentValues[7] + isItRight[7],
buttonNine = currentValues[8] + isItRight[8],
)
currentValues = updateDigits()
else:
obj = Lead()
obj.save()
serializer = TestingSerializer(queryset[0], many =False)
return Response({**serializer.data, "myResult": result})
The Django model
from django.db import models
class Lead(models.Model):
sumScore = models.IntegerField(default=0)
sumRequests = models.IntegerField(default=0)
buttonOne = models.IntegerField(default=0)
buttonTwo = models.IntegerField(default=0)
buttonThree = models.IntegerField(default=0)
buttonFour = models.IntegerField(default=0)
buttonFive = models.IntegerField(default=0)
buttonSix = models.IntegerField(default=0)
buttonSeven = models.IntegerField(default=0)
buttonEight = models.IntegerField(default=0)
buttonNine = models.IntegerField(default=0)
serializer just serializes _ _ all _ _ ...
Front end with React
function evaluateAndCheckQuiz(){
let countNotChosen = howManyNotChosen()
if(countNotChosen){ answerQuestions(countNotChosen); return }
let points = evaluateQuiz()
document.getElementById("scoreText").style.display = "block"
document.getElementById("scoreNumber").textContent = points
return points
}
Calling sendAndGetQuizAverage with evaluateAndCheckQuiz as a parameter
function sendAndGetQuizAverage(points){
const myPostRequest = {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({"Result":points, "whichOnesRight": whichOnesRight}),
};
let data
fetch('https://api.tor-netzwerk-seminarfach2024.com/apache-test/', myPostRequest).then(
(response) => data = response.json()).then(
(data) => {showResultAnalyse(data)})
}
function showResultAnalyse(data){
console.log(data)
let averageScore = (data["sumScore"] / data["sumRequests"]).toFixed(2)
let myResult = data["myResult"]
changeLinksToStatistics([
data["buttonOne"],data["buttonTwo"],data["buttonThree"],
data["buttonFour"],data["buttonFive"],data["buttonSix"],
data["buttonSeven"],data["buttonEight"],data["buttonNine"]
],
data["sumRequests"]
)
swal(
{
text:`${checkWhichText(myResult,averageScore,data["sumRequests"] )}`,
icon: myResult > averageScore ?"success": "error",
button:"Oki doki",
}
);
}

Related

Google Registration, jwt staying logged in

I just added a feature to be able to register with Google. For security reasons I added a field in the db that is false if the user is registered the usal way(Username & PW) and true if he is registered with google.
class CustomUser(AbstractUser):
objects = UserManager()
REQUIRED_FIELDS = []
USERNAME_FIELD = 'email'
username = models.CharField(max_length=40, unique=False,null=True, blank=True)
email = models.EmailField(_('email address'), unique=True)
profile_image = models.ImageField(null=True,blank=True,default = "users.png",upload_to='',)
created = models.DateTimeField(auto_now_add=True)
id = models.UUIDField(default=uuid.uuid4, unique=True,primary_key=True, editable=False)
telephone = models.CharField(blank=True, max_length=20, null=True)
email_is_verified = models.BooleanField(default = False, null=False, blank = False)
currentVerificationToken = models.CharField(max_length = 6, default="000000")
withGoogleRegistered = models.BooleanField(default = False)
def __str__(self):
return self.email
So if you try to login the usal way but the email adress is bounded to an google registered account, you wont be able to. If you try to login with a usal way bounded email adress, but its connected to a google bounded account , you wont be able to. So, I made this in order to seperate betweena accounts with a password and accounts without a password... But there is a little problem now. In Order to obtain an refresh token (JWT) I have to give a username and a password, otherwise I wont be able to get one in the first place...
function fetchToken() {
if (user && !Object.hasOwn(user, "fromBackend")) {
fetch("http://127.0.0.1:8000/token/", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
email: user.email,
password: user.password,
}),
})
.then((response) => response.json())
.then((data) => {
if (data.access) {
setRemoveTokens(data);
updateUser();
}
});
} else if (localStorage.getItem("refreshToken-allkids") != null) {
getNewTokens();
updateUser();
}
For this I am using rest_framework_simplejw
from django.contrib import admin
from django.urls import path, include
from rest_framework_simplejwt.views import (
TokenObtainPairView,
TokenRefreshView,
)
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
path('admin/', admin.site.urls),
path("user/", include("User.urls")),
path("token/", TokenObtainPairView.as_view(), name="obtain_token"),
path("token/refresh/", TokenRefreshView.as_view(), name="refresh_token"),
]
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
So that beeing said, lets move on to the question: how can I obtain a refresh token for Google registered Accounts without having a Password?
Here is the way I create a google registered account:
#api_view(["POST"])
def googleRegistrationOrLogin(request):
body = request.body.decode('utf-8')
token = json.loads(body)
CLIENT_ID = "591603096190-1fv6asqdpmm6td8t66as5temri420j8b.apps.googleusercontent.com"
try:
idinfo = id_token.verify_oauth2_token(token, requests.Request(), CLIENT_ID)
except:
print("Failure")
return Response("Failure")
try:
user = CustomUser.objects.get(email = idinfo["email"])
if user.withGoogleRegistered:
login(request, user)
user = CustomUserLoggedSerializer(user, many = False)
return Response(user.data)
else:
return Response("Email already in use, please create an account the usal way.")
except:
randomEmailToken = random.randrange(100000,999999)
try:
user = CustomUser.objects.create(username = idinfo["name"],profile_image = idinfo["picture"],withGoogleRegistered = True,password="GoogleRegistered", email = idinfo["email"],currentVerificationToken=randomEmailToken, email_is_verified = True if idinfo["email_verified"] else False)
except:
return Response("Fatal Error")
user = CustomUserLoggedSerializer(user, many = False)
return Response(user.data)
I know its currently not clean, but fair enough for now.

post xlsx file to flask route with React async/await

I have a project where I was originally using fetch for all of my requests, and my excel upload function was working fine. I recently made a lot of changes to my application because I added user login and authentication, so I am now trying to reconfigure my routes using async await in React. I am getting different errors that I don't know how to solve. Sometimes when I try to submit the uploaded file I get a 400 error for a bad request, usually saying ""The browser (or proxy) sent a request that this server could not understand.\nKeyError: 'project'". Or I am getting an error on the back-end that says "ValueError: Excel file format cannot be determined, you must specify an engine manually."
I am really confused about where the error is actually occurring because it seems to be reaching the Flask route and then failing.
This is my current request on the front-end:
const onSubmit = async (ev) => {
ev.preventDefault();
let formData = new FormData();
formData.append("project", selectedFile);
// let status = 0;
const data = await api.post("/projects", {
body: formData,
});
if (!data.ok) {
console.log(data);
console.log("error");
} else {
console.log(data);
console.log("uploaded");
}
};
and the back-end route:
#projects.route('/projects', methods=['POST'])
#authenticate(token_auth)
def request_load_pickle_sim():
fn = save_file(None, "project", "xlsx")
print(fn)
request.files["project"].save(fn)
result = process_raw_util_xl_file(fn)
claims = result['claims']
print(claims)
utilities = result['utilities']
weights = result['weights']
maxdiff_scores = result['maxdiff_scores']
data = jsonify(claims)
print(data)
mdp = MaxDiffProject()
mdp.config = MutableDict({
'claims': claims,
'utilities': utilities,
'weights': weights,
'maxdiff_scores': maxdiff_scores
})
print(mdp.config)
db.session.add(mdp)
db.session.commit()
mdp = MaxDiffProject().query.first()
project_config = mdp.config
claims = project_config['claims']
print(claims)
data = jsonify(claims)
return data
My debugger is printing the instance of the file, so it seems like the backend is receiving the file? But after that nothing is working. The file is passed to the process_raw_util_xl_file function (which is where the ValueError error is coming from). I can't figure out what the core issue is because I'm getting conflicting errors. I guess I'm just confused because it was all working fine when I had fetch requests.
The function on the backend is breaking here:
def process_raw_util_xl_file(xl_fn):
# df = pd.read_csv(xl_fn.read())
df = pd.read_excel(xl_fn) # read the excel file
print(df)
row = df.shape[0] # df.shape[0] = Number of rows, df.shape[1] = number of columns
index_col = [col for col in df if 'id' in col.lower()][0]
print(index_col)
df.set_index(index_col, inplace=True) # Setting the ID as the index
# weights = df['Weights'] if 'Weights' in df else pd.Series([1]*row) # Creating the weights array if there are weights , otherwise an array of 1's with # of rows
if 'Weights' not in df:
df['Weights'] = 1
weights = df['Weights']
df.drop('Weights', axis=1, inplace=True)
sum = weights.values.sum() # Sum of the weights
# if 'Weights' in df: df = df.drop('Weights', axis=1) # removing weights from df if they are there
rlh_cols = [col for col in df if 'rlh' in col.lower()][:1]
df = df.drop(rlh_cols, axis=1) # removing RLH from df if they are there
max_diff_scores = (e ** df) / (1 + e ** df) * 100 # exp the values of the dataframe with
utils = df
return {
"utilities": utils,
"claims": [col for col in utils],
"maxdiff_scores": max_diff_scores,
"weights": weights
}
You are posting an object as a body paramter to the server which has a content type as application/json whereas according the HTTP protocol, to post form-data the content type must be multipart/form-data. Here's how you are doing it,
let formData = new FormData();
formData.append("project", selectedFile);
// let status = 0;
const data = await api.post("/projects", {
body: formData,
});
According to the docs (at page end) you must post form data like this,
let formData = new FormData();
formData.append("project", selectedFile);
// let status = 0;
const data = await api.post("/projects", formData);
Also you cannot post body and form data at a same time within single request.

obfuscated page content while using output cache in mvc 5

I'm developing a web application using MVC5 and I use output cache attribute on one of my actions.
the problem is after multiple page visits, my page will have binary content that looks like this:
page screenshot
there's my source:
[OutputCache(Duration = 86400, Location = OutputCacheLocation.ServerAndClient,VaryByParam = "ID;slug")]
[SeoOptionsFilter]
public ActionResult CourseDetail(int ID, string slug)
{
var courseComplexObject =
_courseRepository.GetCourseDetail(ID, slug);
var course = courseComplexObject.Model;
TempData["breadcrumb"] = BreadcrumbViewBuilder
.New().Home().Courses()
.AddMore(course.CategoryName, "/Category/" + course.CategoryId.ToString() + "/" + course.CategorySlug)
.AddMore(course.Name, "/CourseDetails/" + course.CourceId.ToString() + "/" + course.Slug + ".aspx",
true)
.Build();
//TODO: What if course is null
SetViewBagIfUserIsRegistered(course, ID);
TempData["CourseVideoCatOn"] = GetCourseVideoCategory(ID);
TempData["CourseID"] = ID;
TempData.Keep();
// Response.Cache.SetOmitVaryStar(true);
return View(courseComplexObject.Model);
}
I commented my custom action filter [SeoOptionsFilter]
but the result already has errors.
this error occurs randomly in page visits

"'Image' object is not callable" when posting API object

Update 2, 13th Jan: After doing some bug searching and trying to post the object directly in the root API using json, I've come to the realisation that the image is what's giving me the posting error.
I used the HTML form to post an object and it gave me this error:
TypeError at /rats/
'Image' object is not callable
For context, I uploaded an image. Here are my serialisers for creating the object (rat) and for images:
class ImageSerializer(FlexFieldsModelSerializer):
image = VersatileImageFieldSerializer(
sizes='rat_headshot'
)
class Meta:
model = Image
fields = ['name', 'image']
class RatSerializer(FlexFieldsModelSerializer):
user = serializers.CharField(source='user.username', required=False)
userid = serializers.CharField(source='user.id', required=False)
body_colour = BodyColourSerializer()
eye_colour = EyeColourSerializer()
image = ImageSerializer(required=False)
class Meta:
model = rat
exclude = ['bio']
def create(self, data):
request = self.context.get("request")
print("I was here", data, request)
return rat.objects.create(
name = data["name"],
body_colour = BodyColour(name=data["body_colour"]["name"]),
eye_colour = EyeColour(name=data["eye_colour"]["name"]),
# bio = data["bio"],
image = Image(name=data["image"]["name"])(required=False),
user = request.user,
)
I've updated the title. Original title was "Can't manage to post an object via axios to django - possibly due to AnonymousUser object?", now it's " "'Image' object is not callable" when posting API object "
Update 8th Jan: I fixed the AnonymousUser error. Django wanted an ID but was instead getting the user class, I fixed it by changing user = request.user into user = request.user.id
However, I'm still unable to post the object. I'm getting the same res.data error as below. So now I'm not sure what's causing the error.
I'm trying to add a button in React which posts an object to django via axios when a user clicks on it. However, it seems like something's wrong backend.
Here's the button:
<button
id="add-rat"
type="button"
className="btn homeButton"
onClick={
(e) => submit(e)
}
>
Add rat
</button>
And here's the axios, in the same page:
const submit = (e) => {
const name = "namee";
const eyeColour = "Red";
const bodyColour = "White";
const bio = "hfff";
const image = "lineart.PNG";
const data = {
name: name,
eye_colour: eyeColour,
body_colour: bodyColour,
bio: bio,
image: image,
};
e.preventDefault();
console.log(data);
const token = localStorage.getItem("token");
axios
.post("http://127.0.0.1:8000/api/addObject", data, {
headers: {
Authorization: `Bearer ${token}`,
"Content-Type": "application/json",
},
})
.then((res) => {
console.log(res.data);
})
.catch((err) => console.log(err));
};
This is my console output:
{name: 'namee',
eye_colour: 'Red', body_colour: 'White', bio: 'hfff', image: 'lineart.PNG'}
myRats.js:86 {res: 'Error Accured'}
(myRats.js:86 btw, is console.log(res.data); )
Here's my view for the object:
class AddRat(APIView):
def post(self,request):
data = request.data
user = request.user
print(data)
try:
user = rat( name = data['name'] , body_colour = data['bodyColour'] , eye_colour = data['eyeColour'],user= user, bio = data['bio'] , image = data['image'])
user.save()
return Response({'res':"Rat Saved Successfully"})
except:
return Response({'res':"Error Accured"})
def get(self,request):
user = request.user
data = rat.objects.filter(user = user)
data = RatSerializer(data, many = True)
return Response({'data':data.data})
When I go to the url it's posting to, I get this error:
TypeError at /api/addObject
Field 'id' expected a number but got <django.contrib.auth.models.AnonymousUser object at 0x0000014641FD85B0>.
Could it possibly be due to that? What could be wrong?
The Anonymous User issue was solved by changing user = request.user into user = request.user.id
And my second issue, "'Image' object is not callable" was due to me putting (required=False) in another set of parenthesis, as if I was calling an Image as a function.
So I changed
image = Image(name=data["image"]["name"])(required=False)
into
image = Image(name=data["image"]["name"], required=False)

GAE python: Get and post request working without submitting a post request through a form

This is a continuation of this question
What follows is an abbreviated version of the original code. I tried to include the most relevant parts and left out the part of the script used by a cron job which updates the Datastore with values.
Then, in the sendFollowUp() handler, a second cron job queries the Datastore for these values, then uses a push task queue to send these values as parameters which are ultimately used in a REST API call to another service that sends people(entities) in the Datastore an email.
What I can't figure out is how to follow-up a get request with a post request in the same handler without submitting a post request through a form. This needs to happen within the sendFollowUp handler. Most of the examples I have found include submitting a form. However, I don't want to do that. I just want it to work automatically with the cron job and task queue.
import webapp2
import datetime
from google.appengine.ext import db
from google.appengine.api import users
from google.appengine.api import taskqueue
import jinja2
import os
jinja_environment = jinja2.Environment(loader=jinja2.FileSystemLoader(os.path.dirname(__file__)))
class emailJobs(db.Model):
""" Models an a list of email jobs for each user """
triggerid = db.StringProperty() #Trig id
recipientid_po = db.StringProperty() # id
recipientlang = db.StringProperty() #Language
fu_email_sent = db.DateTimeProperty()
fuperiod = db.IntegerProperty() # (0 - 13)
fu1 = db.DateTimeProperty()
fu2 = db.DateTimeProperty()
#classmethod
def update_fusent(cls, key_name, senddate):
""" Class method that updates fu messages sent in the GAE Datastore """
emailsjobs = cls.get_by_key_name(key_name)
if emailsjobs is None:
emailsjobs = cls(key_name=key_name)
emailsjobs.fu_email_sent = senddate
emailsjobs.put()
def timeStampFM(now):
d = now.date()
year = d.year
month = d.month
day = d.day
t = now.time()
hour = t.hour
minute = t.minute + 5
second = t.second
today_datetime = datetime.datetime(year, month, day, hour, minute, second)
return today_datetime
class MainPage(webapp2.RequestHandler):
""" Main admin login page """
def get(self):
if users.get_current_user():
url = users.create_logout_url(self.request.uri)
url_linktext = 'Logout'
urla = '/'
url_admin = ""
if users.is_current_user_admin():
url = users.create_logout_url(self.request.uri)
urla = "_ah/admin/"
url_admin = 'Go to admin pages'
url_linktext = 'Logout'
else:
url = users.create_login_url(self.request.uri)
url_linktext = 'Login'
template_values = {
'url': url,
'url_linktext': url_linktext,
'url_admin': url_admin,
'urla': urla,
}
template = jinja_environment.get_template('index.html')
self.response.out.write(template.render(template_values))
class sendFollowUp(webapp2.RequestHandler):
""" Queries Datastore for fu dates that match today's date, then adds them to a task queue """
def get(self):
now = datetime.datetime.now()
now_dt = now.date() #today's date to compare with fu dates
q = emailJobs.all()
q.filter('fuperiod >', 0)
q.filter('fuperiod <', 99)
for part in q:
guid = str(part.recipientid_po)
lang = str(part.recipientlang)
trigid = str(part.triggerid)
if part.fuperiod == 1:
fu1rawdt = part.fu1
fu1dt = fu1rawdt.date()
if fu1dt == now_dt:
follow_up = '1'
if part.fuperiod == 2: # the values go up to 12 in the original code
fu2rawdt = part.fu2
fu2dt = fu2rawdt.date()
if fu2dt == now_dt:
follow_up = '2'
if follow_up != None:
taskqueue.add(queue_name='emailworker', url='/emailworker', params={'guid': guid,
'fu': follow_up,
'lang': lang,
'trigid': trigid,
})
self.redirect('/emailworker')
class pushQueue(webapp2.RequestHandler):
""" Sends fu emails, updates the Datastore with datetime sent """
def store_emails(self, trigid, senddate):
db.run_in_transaction(emailJobs.update_fusent, trigid, senddate)
def get(self):
fu_messages = {'1': 'MS_x01',
'2': 'MS_x02',
# the values go up to 12 in the original code
}
langs = {'EN': 'English subject',
'ES': 'Spanish subject',
}
fu = str(self.request.get('fu'))
messageid = fu_messages[fu]
lang = str(self.request.get('lang'))
subject = langs[lang]
now = datetime.datetime.now()
senddate = timeStampFM(now)
guid = str(self.request.get('guid'))
trigid = str(self.request.get('trigid'))
data = {}
data['Subject'] = subject
data['MessageID'] = messageid
data['SendDate'] = senddate
data['RecipientID'] = guid
# Here I do something with data = {}
self.store_emails(trigid, senddate)
app = webapp2.WSGIApplication([('/', MainPage),
('/cron/sendfu', sendFollowUp),
('/emailworker', pushQueue)],
debug=True)
I'm not sure I really understand your question, but can't you just create a POST request with the requests module?
Post Requests
>>> payload = {'key1': 'value1', 'key2': 'value2'}
>>> r = requests.post("http://httpbin.org/post", data=payload)
Also for easy task use have you seen the deferred library?
The deferred library lets you bypass all the work of setting up dedicated task handlers and serializing and deserializing your parameters by exposing a simple function, deferred.defer(). To call a function later, simply pass the function and its arguments to deferred.defer
Link

Resources