Python Forum
Beta6 of my password flask-wtf web form
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Beta6 of my password flask-wtf web form
#1
hi all

so im pretty much done with making my flask-wtf password web form, may add other bits to it but what you think

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 subprocess
import smtplib
from email.mime.text import MIMEText

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():
    form = PasswordForm()
    if request.method == 'POST' and form.validate():
        result = subprocess.run(f'powershell.exe $cred = Import-CliXml -Path C:\\python\\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:
            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:
            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 result.returncode == 0:
            try:
                une = subprocess.run(f'powershell.exe $cred = Import-CliXml -Path C:\\python\\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()
                return 'found an email for your user, please check email for your new password'
            except:
                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')
    
#'<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)
thanks,
rob
Reply
#2
Good job as it works,but could clean stuff like the 371 long line with subprocces call.
To give a example.
def change_password(username, old_password, new_password, domain):
    '''Change the password for a user in Active Directory'''
    command = (
        f'powershell.exe $cred = Import-CliXml -Path C:\\python\\cred.xml; '
        f'Set-ADAccountPassword -Credential $cred -Identity {username} '
        f'-OldPassword (ConvertTo-SecureString -AsPlainText {old_password} -Force) '
        f'-NewPassword (ConvertTo-SecureString -AsPlainText {new_password} -Force) '
        f'-Server {domain}'
    )
    result = subprocess.run(command, capture_output=True, text=True, shell=False)
    return result
Then call in password() function would be.
result = change_password(form.un.data, form.op.data, form.cnp.data, form.dom.data)
Then same refactor can be done for email code.
Reply
#3
is it easy to add a re capcha to the form even if its hosted internally not public

and maybe an eye icon so you can see the password
Reply
#4
(6 hours ago)snippsat Wrote: Good job as it works,but could clean stuff like the 371 long line with subprocces call.
To give a example.
def change_password(username, old_password, new_password, domain):
    '''Change the password for a user in Active Directory'''
    command = (
        f'powershell.exe $cred = Import-CliXml -Path C:\\python\\cred.xml; '
        f'Set-ADAccountPassword -Credential $cred -Identity {username} '
        f'-OldPassword (ConvertTo-SecureString -AsPlainText {old_password} -Force) '
        f'-NewPassword (ConvertTo-SecureString -AsPlainText {new_password} -Force) '
        f'-Server {domain}'
    )
    result = subprocess.run(command, capture_output=True, text=True, shell=False)
    return result
Then call in password() function would be.
result = change_password(form.un.data, form.op.data, form.cnp.data, form.dom.data)
Then same refactor can be done for email code.

thanks, il try it out but tbh i want to put all this in a powershell script, just finding it hard to pass the python vars to the ps1 script
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Show powershell errors in flask-wtf web form robertkwild 14 435 Jun-30-2024, 03:15 PM
Last Post: robertkwild
  Running powershell command in flask wtf form robertkwild 10 368 Jun-27-2024, 09:49 AM
Last Post: robertkwild
  using split in my flask wtf form robertkwild 1 202 Jun-11-2024, 05:19 PM
Last Post: deanhystad
  making a form purely with flask-wtf robertkwild 15 848 Jun-01-2024, 11:53 AM
Last Post: robertkwild
  error while inserting values into a table from form in flask in postgreSQL sahilsiddharth 3 7,352 Jun-05-2017, 07:49 PM
Last Post: sahilsiddharth

Forum Jump:

User Panel Messages

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