Python Forum
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
final web password form
#1
hi all,

just want to share my final version of my flask-wtf web password form as im going to be working on a new project for myself

password.py

from flask import Flask, render_template, request
from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, BooleanField, DecimalField, RadioField, SelectField, TextAreaField, FileField, SubmitField
from wtforms.validators import InputRequired, Length, DataRequired, EqualTo, Regexp, ValidationError
import re
import logging
from logging.handlers import TimedRotatingFileHandler
from loguru import logger
import os
import sys
import subprocess
import smtplib
from email.mime.text import MIMEText

logger.remove(0)
logger.add("logs\\{time:YYYY-MM-DD-HH-mm-ss}-password.log", format="{time:YYYY-MM-DD-HH-mm-ss} | {level} | {message}", rotation="1 day", retention="90 days", delay=True)

app = Flask(__name__)
app.config['SECRET_KEY'] = 'secretkey'

class PasswordForm(FlaskForm):
    un = StringField('Username', [InputRequired(message='please enter your Username')])
    op = PasswordField('Current Password', [InputRequired(message='please enter your current password')])
    np = PasswordField('New Password', [InputRequired(message='please enter your new password')])
    cnp = PasswordField('Confirm New Password')
    dom = SelectField('Domain', choices=[('lon-prod-dc01.domain1.com', 'prod'), ('lon-corp-dc01.domain2.com', 'corp'), ('dc01.robo84.net', 'robo84')])
    
    def validate_un(form, field):
        if not field.data == form.un.data.lower():
            raise ValidationError('Username needs to be Lowercase')
    
    def validate_np(form, field):
        if form.un.data:
            if any (name in field.data.lower() for name in form.un.data.split(".")):
                raise ValidationError('New password cant contain firstname or lastname')
        if field.data.lower() == form.op.data.lower():
            raise ValidationError('New password cant match Current password')
        if re.search(r"\s", field.data):
            raise ValidationError('New password cant contain any spaces')
        if not re.search(r"[0-9]", field.data):
            raise ValidationError('New password has to contain one number')
        if not re.search(r"[a-z]", field.data):
            raise ValidationError('New password has to contain one lower case character')
        if not re.search(r"[A-Z]", field.data):
            raise ValidationError('New password has to contain one upper case character')
        if not re.search(r"[\`\¬\!\"\£\$\%\^\&\*\(\)\-\_\=\+\\\|\[\]\;\'\#\,\.\/\{\}\:\@\~\<\>\?]", field.data):
            raise ValidationError('New password has to contain one special character')
        if len(field.data) < 12:
            raise ValidationError('New password must be at least 12 characters')
        if not field.data == form.cnp.data:
            raise ValidationError('New password has to match Confirm new password')
        
@app.route('/password', methods=['GET', 'POST'])
def password():
    ip_addr = request.remote_addr
    form = PasswordForm()
    if request.method == 'POST' and form.validate():
        result = subprocess.run(f'powershell.exe $cred = Import-CliXml -Path C:\\python\\venv\\cred.xml; Set-ADAccountPassword -Credential $cred -Identity {form.un.data} -OldPassword (ConvertTo-SecureString -AsPlainText {form.op.data} -Force) -NewPassword (ConvertTo-SecureString -AsPlainText {form.cnp.data} -Force) -Server {form.dom.data}', capture_output=True, text=True, shell=False)
        if 'The specified network password is not correct' in result.stderr:
            logger.warning(f'{ip_addr} {form.un.data} your current password is wrong, please click back and try again')
            return 'your current password is wrong, please click back and try again'
        if 'The password does not meet the length, complexity, or history requirement of the domain' in result.stderr:
            logger.warning(f'{ip_addr} {form.un.data} cant re-use one of your old passwords or cant change password as still less than one day old, please click back and try again')
            return 'cant re-use one of your old passwords or cant change password as still less than one day old, please click back and try again'
        if 'Cannot find an object with identity:' in result.stderr:
            logger.warning(f'{ip_addr} cant find user {form.un.data} on the domain, please click back and try again')
            return f'cant find user {form.un.data} on the domain, please click back and try again'
        if result.returncode == 0:
            try:
                une = subprocess.run(f'powershell.exe $cred = Import-CliXml -Path C:\\python\\venv\\cred.xml; Get-aduser -credential $cred -server {form.dom.data} -identity {form.un.data} -properties * | select-object -expandproperty mail', capture_output=True, text=True, shell=False)
                smtp_server = '172.17.1.5'
                smtp_user = '[email protected]'
                smtp_connection = smtplib.SMTP(smtp_server)
                email_body = f'hello {form.un.data} your new password is {form.cnp.data} for {form.dom.data}'
                email_message = MIMEText(email_body)
                email_message['Subject'] = 'password change'
                email_message['From'] = '[email protected]'
                smtp_connection.sendmail(smtp_user, {une.stdout}, email_message.as_string())
                smtp_connection.quit()
                logger.info(f'{ip_addr} {form.un.data} found an email for your user, please check email for your new password')
                return 'found an email for your user, please check email for your new password'
            except:
                logger.info(f'{ip_addr} {form.un.data} changed your password but could not find an email address for you, please contact IT to add one')
                return 'changed your password but could not find an email address for you, please contact IT to add one'
    return render_template('password.html', form=form)

if __name__ == '__main__':
    app.run(debug=True, ssl_context='adhoc', host='0.0.0.0')
    
#'<h1>The username is {}. The old password is {}. the new password is {}. changing for domain {}'.format(form.un.data, form.op.data, form.cnp.data, form.dom.data)
password.html

{% block content %}
    <h1>Change Password</h1>
    <form method="post" novalidate>
		{{form.hidden_tag()}}
		
		<p>{{ form.un.label }}</p>
		<p>{{ form.un}}</p>
		
		{% if form.un.errors %}
		<ul>
			{% for error in form.un.errors %}
			<li>
				{{error}}
			</li>
			{% endfor %}
		</ul>
		{% endif %}
		
		<p>{{ form.op.label }}</p>
		<p>{{ form.op}}</p>
		
		{% if form.op.errors %}
		<ul>
			{% for error in form.op.errors %}
			<li>
				{{error}}
			</li>
			{% endfor %}
		</ul>
		{% endif %}
		
		<p>{{ form.np.label }}</p>
		<p>{{ form.np}}</p>
		
		{% if form.np.errors %}
		<ul>
			{% for error in form.np.errors %}
			<li>
				{{error}}
			</li>
			{% endfor %}
		</ul>
		{% endif %}
		
		<p>{{ form.cnp.label }}</p>
		<p>{{ form.cnp}}</p>
		
		{% if form.cnp.errors %}
		<ul>
			{% for error in form.cnp.errors %}
			<li>
				{{error}}
			</li>
			{% endfor %}
		</ul>
		{% endif %}
		
		<p>{{ form.dom.label }}</p>
		<p>{{ form.dom}}</p>
		
		<input type="submit" value="Submit">
    </form>
{%endblock%}
just want to shout out to all the people who have helped me on the way, i really appreciate all your help, whether thats positive or negative because i have learnt so much considering this is my very first python code without you this wouldnt have been possible so big thank you!!!

thanks,
rob
snippsat likes this post
Reply
#2
Thanks for sharing :)
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Beta6 of my password flask-wtf web form robertkwild 3 547 Jul-02-2024, 10:30 AM
Last Post: robertkwild
  Blending calculator from final product xerxes106 0 1,814 Dec-05-2019, 10:32 AM
Last Post: xerxes106
  How to Stop Sentinel Value from Entering Final Output ZQ12 3 3,689 Nov-11-2019, 07:25 AM
Last Post: perfringo
  Final exam calculator iliketocode 1 4,202 Jan-08-2017, 07:06 PM
Last Post: ichabod801

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020