JWT not decoding - authentication

I'm using JWT (the PyJWT library not the flask-jwt) for authentication in my Flask app, but it always returns in the binary form. I use jwt.decode() but to no avail. What am I doing wrong.
Here is the code:
from flask import Flask,render_template,request,redirect,url_for,session
import model
import datetime
import os
from functools import wraps
import jwt
app = Flask(__name__)
app.config["SECRET_KEY"] = os.urandom(16)
def check_for_token(func):
#wraps(func)
def wrapped(*args,**kwargs):
token =request.args.get('token')
if not token:
return("ACCESS DENIED",403)
try:
data = jwt.decode(token,app.config["SECRET_KEY"])
except:
return("INVALID TOKEN",403)
return func
return wrapped
#app.route("/home",methods=["POST"])
def home():
usrname = request.form["username"]
psswrd = request.form["password"]
valid_user = model.username_password_validation(usrname,psswrd)
if not valid_user:
return render_template("login.html",infoMsg="INVALID USERNAME/PASSWORD")
else:
session['username'] = usrname
session['logged_in'] = True
token =jwt.encode({'user':request.form['username'],'exp':datetime.datetime.utcnow() + datetime.timedelta(seconds=3600)},app.config["SECRET_KEY"],algorithm='HS256')
occupied_days = []
user_id=model.get_user_id_from_username(usrname)
tasks = model.get_all_tasks_for_user(user_id)
for task in tasks:
occupied_days.append({"day":task[3].day,"month":task[3].month})
current_month = datetime.datetime.now().month
days = model.get_number_of_days_for_selected_month(current_month)
current_year = datetime.datetime.now().year
return render_template("home.html",username=usrname,tasks=tasks,current_month=current_month,current_year=current_year,days=days,occupied_days=occupied_days,token=token)
#app.route("/<string:username>/tasks?token=<string:token>",methods=["POST","GET"])
#check_for_token
def user_tasks(username,token):
occupied_days= []
token = jwt.decode(token,app.config["SECRET_KEY"],algorithms=['HS256'])
user_id = model.get_user_id_from_username(username)
tasks = model.get_all_tasks_for_user(user_id)
for task in tasks:
occupied_days.append({"day":task[3].day,"month":task[3].month})
current_month = datetime.datetime.now().month
days = model.get_number_of_days_for_selected_month(current_month)
current_year = datetime.datetime.now().year
if request.method=="GET":
return render_template("tasks.html",user_id=user_id,username=username,tasks=tasks,token=token)
else:
task_description=request.form['taskDescription']
task_date=request.form['taskDate']
model.update_existing_task(user_id,task_description,task_date)
return render_template("home.html",infoMsg=f"task for {task_date} updated successfully",tasks=tasks,current_month=current_month,current_year=current_year,days=days,username=username,occupied_days=occupied_days,token=token)
here is the template file:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="/static/style.css">
<link href="https://fonts.googleapis.com/css2?family=Jua&display=swap" rel="stylesheet">
{% block title %}
{% endblock %}
<nav id="navbar">
<ul>
<li> Home </li>
<li>My tasks</li>
<li>Log out</li>
</ul>
</nav>
{% block content %}
{% endblock %}
</head>
<body>
</body>
</html>
Perharps I could pass it in the cookie instead of the query string , but I am not sure how that is done.

Related

user.is_authenticated returns anonymoususer even user already authenticated

main.html
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="{% static 'main/main.css' %}">
</head>
<body>
Welcome to our online store
<div class="account">
<div class="img">
<img src="" alt="">
</div>
<div class="clearfix"></div>
{{ request.user }}
{% if request.user.is_authenticated %}
<p>{{ user.email }}</p>
Settings
Log out
{% else %}
Log in
Sign up
{% endif %}
</div>
</body>
</html>
output
AnonymousUser
authentication/views.py
from django.shortcuts import render, redirect, get_object_or_404
from django.views import View
from django.views.generic import CreateView, ListView, DetailView, DeleteView, UpdateView, RedirectView
from django.http import HttpResponse
from .forms import UserForm, passwordForm, loginForm
from django.contrib.auth import views, forms, logout, login, authenticate
from django.contrib.auth.hashers import make_password, check_password
from django.core.exceptions import ImproperlyConfigured
from django.utils.http import urlsafe_base64_encode
from django.contrib.auth.tokens import default_token_generator
from django.utils.encoding import force_bytes
from .models import Users
from django.contrib import messages
from django.template.loader import render_to_string
from django.contrib.auth.decorators import login_required
from django.contrib.auth.mixins import LoginRequiredMixin
from django.contrib.auth.forms import AuthenticationForm
from django.conf.global_settings import EMAIL_HOST_USER
from django.core.mail import send_mail
from django.contrib.auth.views import LoginView, LogoutView
app_name = 'authentication'
class loginView(View):
template_name = f'{app_name}/login/login.html'
def get(self, *args, **kwargs):
return render(self.request, self.template_name)
def post(self, request, *args, **kwargs):
email = request.POST.get('email')
password = request.POST.get('password1')
user = authenticate(request=request, username=email, password=password)
if user is not None:
login(request, user)
print(user)
print(user.is_authenticated)
return redirect('main:main_page')
else:
return render(request, self.template_name, {
'password_or_email_error': True
})
authentication/urls.py
from django.urls import path
from . import views
app_name = 'auth'
urlpatterns = [
path('login/', views.loginView.as_view(), name='login'),
path('logout/', views.logoutView.as_view(), name='logout'),
path('new/', views.signupView.as_view(), name='signup'),
path('password_reset/', views.passwordResetView.as_view(), name='password_reset'),
path('password_reset/done/', views.passwordResetDoneView.as_view(), name='password_reset_done'),
path('password/reset/<uidb64>/<token>/', views.passwordResetConfirmView.as_view(), name='password_reset_confirm'),
path('password_reset/complete/', views.passwordResetCompleteView.as_view(), name='password_reset_complete')
]
main/views.py
from django.shortcuts import render
from django.views import View
app_name = 'main'
class main_page(View):
template_name = f'{app_name}/main/main.html'
def get(self, request, *args, **kwargs):
print(self.request.user, request.user)
return render(self.request, self.template_name)
main/urls.py
from django.urls import path
from . import views
app_name = 'main'
urlpatterns = [
path('', views.main_page.as_view(), name='main_page'),
]
authentication/models.py
import sys
sys.path.append('..')
from django.contrib.auth.models import UserManager, AbstractUser
from django.db import models
from django.utils.translation import gettext_lazy as _
from config import *
from django.utils import timezone
class Users(AbstractUser):
GENDERS = (
('male', 'Male'),
('female', 'Female'),
('rns', 'Rather not say')
)
first_name = models.CharField(max_length=50, validators=[validate_str, min_length_for_name])
last_name = models.CharField(max_length=50, null=True, blank=True, validators=[validate_str, min_length_for_name])
email = models.EmailField(max_length=100, unique=True, validators=[min_length_for_email])
password1 = models.CharField(max_length=100, validators=[min_length_for_password])
password2 = models.CharField(max_length=100, validators=[min_length_for_password])
birth_date = models.DateField(validators=[min_year, max_year])
gender = models.CharField(max_length=10, choices=GENDERS, validators=[validate_gender])
password = models.CharField(_("password"), max_length=128, null=True, blank=True)
username = models.CharField(
_("username"),
max_length=150,
unique=True,
help_text=_(
"Required. 150 characters or fewer. Letters, digits and #/./+/-/_ only."
),
validators=[AbstractUser.username_validator],
error_messages={
"unique": _("A user with that username already exists."),
},
null=True, blank=True
)
date_joined = models.DateTimeField(_("date joined"), default=timezone.now, null=True, blank=True)
objects = UserManager()
EMAIL_FIELD = 'email'
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['first_name', 'last_name', 'birth_date', 'gender']
class Meta:
verbose_name = 'User'
verbose_name_plural = 'Users'
app_label = 'authentication'
db_table = 'users'
def __str__(self):
return f'{self.first_name} {self.last_name}'
I tried django's login and authenticate function then return redirect to main page but in the main page request.user is anonymous, in the login function user is not anonymous. If i try to check user in login function user.is_authenticated return True but in main page return False

How do you forward a file into s3 from a post request

I am trying to deploy a website that can handle post requests. To do so I have set up an api gateway that invokes a lambda function. The lambda is structured as below:
exports.handler = async (event) => {
// TODO implement
var ht = '<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="Content-Type" content="text/html"/> <meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title> </head> <body><form method = "post"> <input type="file" id="myFile" name="filename"> <input type="submit"> </form></body></html>'
if (JSON.stringify(event['requestContext']['http']['method']) == '"GET"'){
const response = {
"statusCode": 200,
"body": ht,
"headers": {
'Content-Type': 'text/html',
}
}
return response;
}
if (JSON.stringify(event['requestContext']['http']['method']) == '"POST"'){
// forwards the uploaded file into s3
return 1
}
};
Right now upon the get request, the html page rendered contains a button to choose a file and one to submit it. The idea is that upon pressing submit a file is uploaded hence triggering the post request. What I was wondering how exactly can I extract this file from the requests within the 'Post' if statement(where the second comment is) so that I can then send it to an s3 bucket? I was also wondering how instead of having the html being one line, how can I place it into its own index.html file and call it within the lambda function?
Thank you
You can check https://github.com/mmakadiya/aws_lambda-API_gateway-Import-XML-data/tree/main with the code.
event['body'] will have the content of your imported body.
--
import json
import boto3
def lambda_handler(event, context):
# TODO implement
print("V.1")
print("========================")
print(event)
print("========================")
s3 = boto3.resource("s3")
s3.Bucket("my-files-maulik").put_object(Key = "MyFirstFile.xml", Body = event['body'])
print("**********body = " + event['body'])
return {
'statusCode': 200,
'body': json.dumps('Hello from Lambda!')
}

Match html response in karate [duplicate]

This question already has an answer here:
Karate: Match repeating element in xml
(1 answer)
Closed 2 years ago.
I hava a problem in matching my response errors with html.
I tried like this
match $.errors == '#present'
match $.errors == response
Errors:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Error</title>
</head>
<body>
<pre>Error: Unexpected object!</pre>
</body>
</html>
I'm doing it like this and the scnario will be stoped!
When method post
* if (responseStatus == 500 ) karate.abort()
Then status 200
* match $.errors == '#notpresent'
How can I do to get the response match as html text?
Sorry Karate only works with well-formed XML. You can try to replace content in the HTML to clean it up. Or you can just do string contains matches etc. Or you can write some JS or Java code for custom checks.
This will work (after removing the <meta> tag which is not well-formed.
* def response =
"""
<!DOCTYPE html>
<html lang="en">
<head>
<title>Error</title>
</head>
<body>
<pre>Error: Unexpected object!</pre>
</body>
</html>
"""
* match //pre == 'Error: Unexpected object!'

How to upload and create multiple file objects with django

I'm new to Django and I'm on the first stages for writing a web app. One of the features of the app requires users to upload multiple pictures to a database.
I have created an 'image' model for storing the pictures and later manipulate them. The user is supposed to upload more than one image at a time using a POST request (don't even know if that is possible).
Each picture uploaded is supposed to be an image object on the database, but for some reason, I'm failing to upload and also create that object. Nothing happens when I make the POST request. I might be failing at some point and in something simple. I'd appreciate some help.
models.py
from django.db import models
class image(models.Model):
image_field = models.FileField(upload_to='images/')
forms.py
from django import forms
from .models import image
class images_form(forms.ModelForm):
class Meta:
model = image
fields = ['image_field']
widgets = {
'image_field' : forms.ClearableFileInput(
attrs={'class': 'upload ','inputtype':'file','name':'images','multiple':True })}
views.py
from django.shortcuts import render
from django.http import HttpResponse
from .forms import images_form
from .models import image
def upload_files(request):
context = {'images_form': images_form}
if request.method == 'POST':
form_images = images_form(request.POST, request.FILES)
files = request.FILES.getlist('images')
if form_images.is_valid():
for file in files:
newimg = image(image_field = file)
print(newimg.name)
newimg.save()
return HttpResponse('images uploaded')
else:
return render(request, 'master_form/desk.html', context=context)
upload_images.html
<!doctype html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<title>Hello, world!</title>
</head>
<body>
<h1>Django Desk</h1>
<div class="container-fluid">
<h1> images</h1>
<form method = "post" enctype = "multipart/form-data">
{% csrf_token %}
{{ images_form.as_p }}
<button type = "submit"> Upload </button>
</form>
</body>
</html>
I found what the problem was.
files = request.FILES.getlist('images')
Was empty or didn't exist.
You have to use the same name you used when defining your model fields, in my case 'image_field', not 'images'.
The new code looks like this (views.py):
for file in request.FILES.getlist('image_field'):
img = image(image_field=file)
img.save()

PhantomJs can't render a specific page from source

I have been successfully able to take raw html (that has been retrieved with another product) then have phantomjs take that raw html and render the full page including running any/all javascript. I recently encountered a page that was not having its javascript rendered.
This is how I run it...
phantomjs myscript.js > OUTPUT.txt 2>&1
Here is the myscript.js file that demonstrates the issue...
var page = require('webpage').create(),
var system = require('system');
var address = 'http://cloud.firebrandtech.com/#!/login';
var rawHtml = '<!DOCTYPE html>\
<html>\
<head>\
<meta charset="utf-8">\
<meta http-equiv="X-UA-Compatible" content="IE=edge">\
<meta name="viewport" content="width=device-width, initial-scale=1.0">\
<meta name="description" content="Web Portal for managing Cloud Products, Assets, and Distributions">\
<meta name="author" content="Firebrand Technologies">\
<title>Firebrand Cloud</title>\
<link rel="stylesheet" href="/widgets/css/widgets.css">\
<link rel="stylesheet" href="/css/portal.css">\
</head>\
<body ng-app="portal" fc-app="cloud" fc-direct="true" class="fc">\
<div>\
<div data-ng-if="user.isLoaded" data-ng-controller="PortalCtrl">\
<div data-ng-include="getView()"></div>\
<div class="container">\
<div data-ui-view></div>\
</div>\
</div>\
</div>\
<script src="/widgets/js/widgets.js"></script>\
<script src="/js/vendor.js"></script>\
<script src="/js/portal.js"></script>\
</body>\
</html>';
page.settings.resourceTimeout = 5000;
page.settings.loadImages = false;
page.setContent(rawHtml, address);
window.setTimeout(function () {
if(page.content.indexOf('Sign In') > -1)
console.log('YAY!!! Javascript Rendered!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!')
else
console.log('BOO!!! Javascript NOT Rendered!!!!!!!!!!!!!!!!!!!!!!!!!!')
phantom.exit();
}, 5000);
Seems like this page requires some auth/cors to work. I can get it to work if phantomjs makes the actual request (using page.open) to get the source like the following example. However, this solution will not work for me. Phantomjs has to use the source like in the example above (which like I mentioned, has been working great for all other sites).
var page = require('webpage').create(),
var system = require('system');
var address = 'http://cloud.firebrandtech.com/#!/login ';
page.open(address, function(status) {
setTimeout(function(){
if(page.content.indexOf('Sign In') > -1)
console.log('YAY!!! Javascript Rendered!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!')
else
console.log('BOO!!! Javascript NOT Rendered!!!!!!!!!!!!!!!!!!!!!!!!!!')
phantom.exit();
}, 5000)
});
I have already tried using flags like the following but they seem to have no effect...
phantomjs --web-security=false --ignore-ssl-errors=true thefilebelow.js > OUTPUT.txt 2>&1
Finally got this working...
Since I used another product (not phantomjs) to retrieve the page source, I needed to persist the cookies sent back with that request. Then I had to pass in those cookies using addCookie like so...
var page = require('webpage').create(),
var system = require('system');
var address = 'http://cloud.firebrandtech.com/#!/login';
var rawHtml = 'same raw html as above...';
//THE NEXT 3 LINES ARE WHAT CHANGED
var cookiesFromInitialRequest = [{name: 'aaa', value: 'bbb', domain: 'ccc'}, etc...]
for(var i = 0; i < cookiesFromInitialRequest.length; i++)
phantom.addCookie(cookiesFromInitialRequest[i])
page.settings.resourceTimeout = 5000;
page.settings.loadImages = false;
page.setContent(rawHtml, address);
window.setTimeout(function () {
if(page.content.indexOf('Sign In') > -1)
console.log('YAY!!! Javascript Rendered!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!')
else
console.log('BOO!!! Javascript NOT Rendered!!!!!!!!!!!!!!!!!!!!!!!!!!')
phantom.exit();
}, 5000);