Python Forum
Show powershell errors in flask-wtf web form
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Show powershell errors in flask-wtf web form
#1
hi all,

so im really getting along with my flask-wtf form and im nearing its completion

now i want to show if powershell errors, i want it to show on the web form

this is my py script

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

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.domain.com', 'prod'), ('lon-corp-dc01.domain.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 len(field.data) < 12:
            raise ValidationError('New password must be at least 12 characters')
        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 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():
        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}', shell=True)
        return '<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)
    return render_template('password.html', form=form)

if __name__ == '__main__':
    app.run(debug=True)
my html script

{% 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%}
it works well but only problem is if they enter in there old password wrong ie op there not warned about it, it only shows in the cmd part but obviously the end user cant see this and can just see the html form

can i output the error in the same html script?

i want it not to run the subprocess.run command if it errors

thanks,
rob
Reply
#2
If you call subprocess.run() with "capture_output" = True it returns stdout and stderr. You can also check the returncode.

https://docs.python.org/3/library/subprocess.html
robertkwild likes this post
Reply
#3
thanks Dean, i was researching this last night and what you said

https://www.golinuxcloud.com/python-subprocess/

but what about outputting the error on the html form instead of just the console as end users wont see the console they will just have access to the html form
Reply
#4
Can’t you think of a way to return some html that contains the error message.
Reply
#5
Quote:but what about outputting the error on the html form instead of just the console as end users wont see the console they will just have access to the html form

In PHP there is a kind of global array known as $_SESSION with elements like: $_SESSION["any name here"].

Once you start $_SESSION, you can store anything in it, like:

Quote:$_SESSION['isloggedin'] = 'False';
$_SESSION['email_error'] = "This email {$email} is not in the database."
$_SESSION['PWerror'] = '密码不一样 Passwords did not match';
$_SESSION['PWsuccess'] = '改变密码成功了!Password changed for User with email: ' . $email . '!';

The users clicks send and the PHP to evaluate the contents of the form takes over. If an error occurs, the user is bounced back to the form, where the error can be displayed as $_SESSION['any name here'] in a div and the $_SESSION error is unset, ready for the next attempt when the user clicks the send button again:

Quote:<div id="div-blue">
If something is wrong, you will see an error message here. <br>
<?php
if(isset($_SESSION['PWerror'])){
echo "An error occurred: " . $_SESSION['PWerror'] . '<br>';
unset($_SESSION['PWerror']);
}

if(isset($_SESSION['PWsuccess'])){
echo "Result: " . $_SESSION['PWsuccess'] . '<br>';
unset($_SESSION['PWsuccess']);
}
?>
</div><br>

Maybe Flask has something like $_SESSION?
Reply
#6
ok im doing this

@app.route('/password', methods=['GET', 'POST'])
def password():
    form = PasswordForm()
    if request.method == 'POST' and form.validate():
        try:
            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)
            print("STDOUT:", result.stdout)
            print("STDERR:", result.stderr)
        except:
            print("something went wrong")
        return '<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)
    return render_template('password.html', form=form)

if __name__ == '__main__':
    app.run(debug=True)
but when the subprocess command fails its not showing the print message in except

also if the sub process command fails i dont want it to display that return line ie to show what you typed in username old password, new password, domain
Reply
#7
ok got it working, now in cmd i see the print error, now got to figure out how to show the error in html, any takers
try:
            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}', check=True, capture_output=True, text=True, shell=False)
            print("STDOUT:", result.stdout)
            print("STDERR:", result.stderr)
            return '<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)
        except:
            print("something went wrong")
    return render_template('password.html', form=form)
Reply
#8
subprocess.run raises an exception when it cannot start the subprocess. It does not raise an exception when powershell has a problem running a script. That is why you look at stderr and the return code.

You can configure the run() call to raise an exception when the return code is not zero (check).

According to the documentation, your code is wrong.
Quote:args is required for all calls and should be a string, or a sequence of program arguments. Providing a sequence of arguments is generally preferred, as it allows the module to take care of any required escaping and quoting of arguments (e.g. to permit spaces in file names). If passing a single string, either shell must be True (see below) or else the string must simply name the program to be executed without specifying any arguments.
You are passing a single string, but the string is not just the command to be executed.
Reply
#9
alright done
try:
            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}', check=True, capture_output=True, text=True, shell=False)
            return '<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)
        except:
            return 'Something went wrong, Either current password was incorrect or re-using old password history for new password is not allowed, please try again'
    return render_template('password.html', form=form)
but now the stderror could be two things, either
you have enbtered in old password incorrect, or
you cant re-use an old existing password for your new password

so how do i return different errors ie show on the web page depending on what the stderr is
Reply
#10
Have you read through the subprocess.run documentation? A lot of your questions are answered here:

https://docs.python.org/3/library/subprocess.html

You need to check if there was an error. You are using check, but I would just look at the return code. If there was an error, return some markup that contains the error info that can be displayed on the web page.
result = subprocess.run(..., check=False)
if result.returncode != 0:
    return some_markup_containing_result.stderr
elif result.stdout:
    return some_markup_containing_result.stdout
else:
    return something else?
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Cant get powershell script to run with subprocess robertkwild 2 145 Jun-27-2024, 01:23 PM
Last Post: robertkwild
  Running powershell command in flask wtf form robertkwild 10 329 Jun-27-2024, 09:49 AM
Last Post: robertkwild
  Passing web form to powershell robertkwild 1 279 Jun-14-2024, 10:16 AM
Last Post: Akshiya
  using split in my flask wtf form robertkwild 1 191 Jun-11-2024, 05:19 PM
Last Post: deanhystad
  making a form purely with flask-wtf robertkwild 15 839 Jun-01-2024, 11:53 AM
Last Post: robertkwild
  using PowerShell from Python script for mounting shares tester_V 8 851 Mar-12-2024, 06:26 PM
Last Post: tester_V
  PowerShell & Python deep_logic 2 849 Jun-06-2023, 06:34 AM
Last Post: buran
  PIL Image im.show() no show! Pedroski55 2 1,091 Sep-12-2022, 10:19 PM
Last Post: Pedroski55
  How to write a part of powershell command as a variable? ilknurg 2 1,237 Jul-26-2022, 11:31 AM
Last Post: ilknurg
  PIL Image im.show() no show! Pedroski55 6 5,481 Feb-08-2022, 06:32 AM
Last Post: Pedroski55

Forum Jump:

User Panel Messages

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