This part takes care of sending the link to the user. So far it does the job perfectly and I always get the email
app = Flask(__name__)
app.secret_key = 'b11223344AaadD$$r.,IIr]]tP[tu#urr'
app.config.from_pyfile('config.cfg')
mail = Mail(app)
s = URLSafeTimedSerializer(app.config['SECRET_KEY'])
engine = create_engine("postgresql://postgres:andersen23#localhost:5432/test")
db = scoped_session(sessionmaker(bind=engine))
#app.route('/recover', methods=['POST', 'GET'])
def recover():
headline = 'Recover Your Password'
alert = 'Type Your Email'
alert_ = ''
if request.method == 'GET':
return render_template('recover.html', headline=headline, alert1=alert, alert=alert_)
email = request.form.get('email')
session['email'] = email
mail1 = db.execute("SELECT contact0.email FROM person JOIN contact0 ON contact0.id = person.id
WHERE email = :email",
{"email": email}).fetchone()
token = s.dumps(email, salt='confirm')
link = url_for('confirm', token=token, _external=True)
msg = Message('Confirm Email', sender='esdavitnem#gmail.com', recipients=[email])
name = db.execute(
"SELECT person.first_name FROM person JOIN contact0 ON contact0.id = person.id WHERE email =
:username",
{"username": email}).fetchone()
if not isinstance(mail1, type(None)):
alert_ = f"Link Sent to {email}! \n Expires in 5 minutes!"
msg.body = f"Dear {name[0]}, \n\nYour link is {link} \n\nBest,\nDavid from Drunkify"
mail.send(msg)
return render_template('recover.html', headline=headline, alert1=alert, alert=alert_)
if isinstance(mail1, type(None)):
alert_ = f"No user exists with {email} email"
return render_template('recover.html', headline=headline, alert1=alert, alert=alert_)
This part takes care of opening the token and showing an html code to the user.
My main issue is that render_template only works with one html file in my templates.
register1.html is a page for my user to change their password. But the code error message keeps suggesting me to redirect them to register.html
#app.route('/confirm_email/<token>')
def confirm(token):
headline = 'Type Your New Password'
try:
email = s.loads(token, salt='confirm', max_age=300)
except SignatureExpired:
return 'The Token Expired'
return render_template('register1.html', headline=headline)
Register1.html
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Title Page-->
<title>Recover Your Password</title>
<link href="../static/main.css" rel="stylesheet" media="all">
</head>
<body>
<div class="page-wrapper bg-gra-01 p-t-180 p-b-100 font-poppins">
<div class="wrapper wrapper--w780">
<div class="card card-3">
<div class="card-heading"></div>
<div class="card-body">
<h2 class="title">Change Your Password</h2>
<form action = "{{ url_for('confirm') }}" method="post">
<div class="form-group">
<input class="form-control" type="password"
placeholder="New Password" name="password" required>
<div class="help-block with-errors"></div>
</div>
<div class="p-t-10">
<button type="submit" class="btn btn--pill btn--green">
Submit
</button>
</div>
</form>
</div>
</div>
</div>
</div>
</body>
</html>
What you're seeing is a mismatch in expectations between
def confirm(token):
which expects an argument, and
{{ url_for('confirm') }}
which isn't providing one, but lives in a form that does provide password as part of the POST parameters (a different mechanism). I'm wondering if you didn't intend to do
{{ url_for('recover') }}
instead.
Related
I have the following views:
def device_port(request):
devices = Device.objects.all()
if request.method == "POST":
selected=request.POST.get('device')
devices = Device.objects.get(pk=selected)
tablename = 'dev_interface_'+selected
print("tablename: " +tablename)
cursor=connection.cursor()
cursor.execute(f"SELECT interface FROM {tablename} WHERE id >=2")
righttable = cursor.fetchall()
return redirect('/device/port/selected',{'devices':devices, 'selected': selected, 'righttable':righttable} )
return render(request, 'interface/device_port.html',{'devices':devices})
def device_port_selected(request, pk):
if request.method == "POST":
job = JobForm(request.POST)
device = devices.hostname
print(devices)
#job.associateddevice = devices.hostname
try:
selection=request.POST.get('portrange')
except:
selection = ""
messages.warning(request, "Please select the ports")
print(selection)
#job.associatedinterface = selection
return render(request, 'interface/device/port/selected/'+device+'.html',{'devices':devices, 'righttable':righttable} )
return render(request, 'interface/device_port_selected.html',{'devices':devices, 'selected': selected, 'righttable':righttable} )
urls.py
urlpatterns = [
path('', views.home, name='interface-home'),
path('device/', DeviceListView.as_view(), name='interface-device'),
path('device_edit/<int:pk>/', views.device_edit, name='device-edit'),
path('device_delete/<int:pk>/', views.device_delete, name = 'device-delete'),
path('device_add/', views.device_add, name='device-add'),
path('device/port/', views.device_port, name='device-port'),
path('device/port/selected/', views.device_port_selected, name='device-port-selected'),
path('device/routeport/', views.device_routeport, name='device-routeport'),
path('interface/', views.interface_list, name='interface-list')
]
device_port.html
<form method="POST">
<div class="form-row align-items-center">
<div class="col-md-5 my-1">
{% csrf_token %}
<label for="Hostname">Hostname</label>
<div class="input-group">
<select id = "list" class="custom-select mr-sm-2" onchange="getSelectValue();">
<option selected>Select</option>
{% for device in devices %}
<option value={{device.id}}>{{device.hostname}}</option>
{%endfor%}
</select>
<div class="input-group-append">
<button class="btn btn-outline-secondary" type="submit">Go</button>
</div>
</div>
</div>
</div>
<input type ="text" name="device" id= "txtvalues" style="display:none">
</form>
So there are 2 page I am dealing with over here (/device/port and /device/port/selected). In this first page /device/port, user is required to pick a value from the drop down box and press the button Go. From here, it is intended to go to the next page which is /device/port/selected with the selected value in the first page pass to the next page.
But with the following code, I receive the error of
device_port_selected() missing 1 required positional argument: 'pk'
when moving from the first page to the next page.
You can't pass a context dictionary to a redirect. The second argument should be the URL arguments, not a context. So change the following line:
return redirect('/device/port/selected',{'devices':devices, 'selected': selected, 'righttable':righttable} )
to
return redirect('device-port-selected', pk=selected)
Note that it is better to use the name of the URL (i.e. device-port-selected) instead of the whole path as you can change paths in the future without affecting the rest of your code.
I have an issue with the program am trying to develop. I have a function that will send OTP code to user when they request to login. the OTP code should be sent through email to the registered users. the problem is that my code now accepts every email and it doesn't validate the users from the database. How can I do this?
UPDATED the new code!
I updated my code that i previously posted because initially I had issue in getting the OTP also. Someone helped me to point my mistake and I corrected them. But still the existing email verification has no luck. Please help!
this is my updated script
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.min.js" type='text/javascript'>
{% block title %}
{% endblock %}
{% block content %}
<h1>OTP Verification Page</h1>
<br>
<br>
<p>
</script>
<div id="email_div" style="display: block;" >
<label for="email">Email</label>
<input type="text" name="email" id="email">
<button onclick="ajax_send_otp()">Send OTP</button>
</div>
<div id="verify_text_div"></div>
<div id="otp_div" style="display: none;" >
<label for="email">OTP</label>
<input type="text" name="otp" id="otp">
<button onclick="verify_otp()">Verify</button>
</div>
</p>
{% endblock %}
<script>
var otp_from_back="";
function ajax_send_otp(){
document.getElementById("email_div").style.display='none';
email = document.getElementById("email");
$.post("/send_otp",
{
"email":email.value,
"csrfmiddlewaretoken":"{{csrf_token}}"
},
function(data, status){
if(status=="success"){
otp_from_back = data;
document.getElementById("otp_div").style.display='block';
}
}
);
}
function verify_otp(){
var user_otp=document.getElementById("otp").value;
if (user_otp==otp_from_back){
document.getElementById("verify_text_div").style.color="green";
document.getElementById("verify_text_div").innerHTML="OTP Verified";
setTimeout(window.location.assign("http://127.0.0.1:8000/login/"),2000);
document.getElementById("otp_div").style.display="none";
document.getElementById("form_div").style.display="block";
}
else{
document.getElementById("verify_text_div").style.color="red";
document.getElementById("verify_text_div").innerHTML="Try Again!!";
}
}
</script>
and this is my updated views.py file
def otp_verification(request):
return render(request, 'otp.html')
def generateOTP():
digits = "0123456789"
OTP = ""
for i in range(4):
OTP += digits[math.floor(random.random() * 10)]
return OTP
def send_otp(request):
email = request.GET.get("email")
print(email)
o = generateOTP()
#email = EmailMessage(
# subject='Nithya FYP OTP',
# body= ('OTP request', o),
# from_email=EMAIL_HOST_USER,
#to=[email],
#)
#mail.send()
print(o)
return HttpResponse(o)
Try validating your email and checking if the email exists in your database.
email = request.POST['email']
if validate_email(email) and User.objects.filter(email=email).exists():
...
else:
...
I am only trying to test the default user profile update through UserChangeForm. Just the email field. So below are the code snippet.
views.py
#login_required(login_url="/login/")
def editUserProfile(request):
if request.method == "POST":
form = UserProfileUpdateForm(request.POST, instance=request.user)
if form.is_valid():
form = UserProfileUpdateForm(request.POST)
form.save()
return redirect('thank_you')
else:
messages.error(request, f'Please correct the error below.')
else:
form = UserProfileUpdateForm(instance=request.user)
return render(request, "authenticate\\editProfilePage.html", {'form': form})
forms.py
class UserProfileUpdateForm(UserChangeForm):
email = forms.EmailField()
class Meta:
model = User
fields = ('email', )
HTML
<div class="container h-100">
<div class="d-flex justify-content-center h-100">
<div class="user_card">
<div class="d-flex justify-content-center">
<h3 id="form-title">Update Profile</h3>
</div>
<div class="d-flex justify-content-center form_container">
<form method="POST" action="{% url 'editUserProfile' %}">
{% csrf_token %}
<div class="input-group mb-2">
<div class="input-group-append">
<span class="input-group-text"><i class="fas fa-envelope-square"></i></span>
</div>
{{form.email}}
</div>
<div class="d-flex justify-content-center mt-3 login_container">
<input class="btn login_btn" type="update" value="update">
</div>
</form>
</div>
{{form.errors}}
<script>
/* Because i didnt set placeholder values in forms.py they will be set here using vanilla Javascript
//We start indexing at one because CSRF_token is considered and input field
*/
//Query All input fields
var form_fields = document.getElementsByTagName('input')
form_fields[4].placeholder='email';
for (var field in form_fields){
form_fields[field].className += ' form-control'
}
</script>
</body>
In the user profile page, I could see the update button, and when I click on it I am redirected to the edit profile page, and I am also able to see the old email address mentioed in the email field. So far so good.
However, when I replace the old email with new one and click on the "update" button nothing happens. No error, no redirection. Nothing. The page remains there.
There were sytax errors in my HTML code, so I re-wrote the entire HTML again. That resolved the issue. Thank you
I'm working on a simple flask application that displays a basic form with user, pass, verify pass, and email. The way I have it right now, if there are no errors, instead of going to the page i tell it to (welcome.html), it just goes back to my home page (index.html). There are comments in the code to guide you through it. Please help I've been racking my brain and the internet and trying lots and lots of things for the past week, and i need this for school or else im gonna fail. Here is my application code:
from flask import Flask, request, redirect, render_template
import jinja2
import cgi
app = Flask(__name__)
app.config['DEBUG'] = True
#app.route("/", methods=['GET'])
def index():
return render_template("index.html")
#if my form makes a post request at the route / (as defined in the form in the index page), then go to index again, or welcome page
#app.route("/", methods=['POST'])
def welcome():
username = str(request.form.get('username-actual'))
password = str(request.form.get('password-actual'))
verifiedpassword = str(request.form.get('verifedpassword-actual'))
email = str(request.form.get('email-actual'))
#if (not username) or len(username) < 3 or len(username) > 20 or ' ' in username: IGNORE THIS
#If any of the fields have any of these conditions, fill the error message with the message. otherwise, empty
if username == '' or len(username) < 3 or len(username) > 20 or ' ' in username:
usererror = "Invalid username lol"
else:
usererror = ""
if password == '' or len(password) < 3 or len(password) > 20 or ' ' in password:
passworderror = "Invalid password lol"
else:
passworderror = ""
if verifiedpassword != password:
verifiedpassworderror = "Passwords dont match lol"
else:
verifiedpassworderror = ""
if email == '' or len(email) < 3 or len(email) > 20 or ' ' in email or '#' not in email:
emailerror = "Invalid email lol"
else:
emailerror = ""
#if any of the error messages are not empty (meaning there are error messages), render the home page again, with the necessary strings provided for jinja
if len(usererror) > 0 or len(passworderror) > 0 or len(verifiedpassworderror) > 0 or len(emailerror) > 0:
return render_template("index",usererror=usererror,
passworderror=passworderror,
verifiedpassworderror=verifiedpassworderror,
emailerror=emailerror,
username=username,
email=email,)
#otherwise, go to the welcome page, with the necessary username
else:
return render_template("welcome.html",username=username)
app.run()
and here is my two form, index.html and welcome.html, respectively:
<!doctype html>
<html>
<head>
<title>
User Sign-up
</title>
<style>
.error { color:red; }
</style>
</head>
<body>
<h1>Sign-up</h1>
<br>
<form action="/" method="post">
<div>
<label>Username: <input type="text" name="username-actual" value="{{username}}"></label>
<p class="error">{{usererror}}</p>
</div>
<div>
<label>Password: <input type="password" name="password-actual"></label>
<p class="error">{{passworderror}}</p>
</div>
<div>
<label>Verify Password: <input type="password" name="verifiedpassword-actual"></label>
<p class="error">{{verifypassworderror}}</p>
</div>
<div>
<label>Email (optional): <input type="text" name="email-actual" value="{{email}}"></label>
<p class="error">{{emailerror}}</p>
</div>
<div>
<input type="submit" name="sign-up-submit" value="Sign Up!">
</div>
</form>
</body>
</html> <p></p>
Here is my welcome.html:
Welcome, {{username}}!
I am sending a Username and password from my HTML form to django backend .
<html>
<style type="text/css">
#center_align{
width: 200px;
margin: 10px auto;
}
</style>
<head>
<title>Login Form</title>
</head>
<body>
<div id = "center_align">
<h1>Login</h1>
<form method = "GET" action="http://127.0.0.1:8000/login/" >
Username :<input type ="text" name = "username"><br>
Password :<input type ="password" name = "password"><br>
<input type="submit" value="Submit">
</form>
</div>
</body>
</html>
In my django , i have wrote a class in my Views
class Login(APIView):
global User_Grps
def get(request,self):
state = ""
username = "Gauss"
password = settings.AUTH_LDAP_BIND_PASSWORD
oLdap = LDAPBackend()
try:
User = oLdap.authenticate(username=username,password=password)
print User.ldap_user.group_dns
if User is not None:
User_Grps = User.ldap_user.group_dns
else:
User_Grps = "Invalid Group"
except Exception as e:
User_Grps = "Error"
return HttpResponse(User_Grps)
How would i retrieve my username and password from the request object ? Like i need to get the data from the request parameter of the method .
Instead of doing that, you should write a custom Django authentication backend which would let you use the default login views from DRF and/or other Django 3rd parties.