Skip to content

Commit

Permalink
added user management and guest users.
Browse files Browse the repository at this point in the history
  • Loading branch information
William Hahn committed Dec 14, 2023
1 parent 0916496 commit 54f0333
Show file tree
Hide file tree
Showing 10 changed files with 546 additions and 78 deletions.
1 change: 1 addition & 0 deletions app/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ def login_post():
# if the above check passes, then we know the user has the right credentials
login_user(user, remember=remember)
session['name'] = user.name
session['email'] = user.email

return redirect(url_for('main.index'))

Expand Down
91 changes: 89 additions & 2 deletions app/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,15 +49,32 @@ def index():
# plot cash flow results
minbalance, graphJSON = plot_cash()

return render_template('index.html', title='Index', todaydate=todaydate, balance=balance.amount,
user = User.query.filter_by(id=current_user.get_id()).first()

if user.admin:
return render_template('index.html', title='Index', todaydate=todaydate, balance=balance.amount,
minbalance=minbalance, graphJSON=graphJSON)
else:
return render_template('index_guest.html', title='Index', todaydate=todaydate, balance=balance.amount,
minbalance=minbalance, graphJSON=graphJSON)


@main.route('/profile')
@login_required
def profile():
user = User.query.filter_by(id=current_user.get_id()).first()

if user.admin:
return render_template('profile.html')
else:
return render_template('profile_guest.html')


@main.route('/settings')
@login_required
def settings_page():

return render_template('profile.html')
return render_template('settings.html')


@main.route('/schedule')
Expand Down Expand Up @@ -347,6 +364,76 @@ def email():
return redirect(url_for('main.profile'))


@main.route('/users_table')
@login_required
def users():
users = User.query

return render_template('users_table.html', title='Users Table', users=users)


@main.route('/update_user', methods=['GET', 'POST'])
@login_required
def update_user():
# update an existing user

if request.method == 'POST':
current = User.query.filter_by(id=request.form['id']).first()
existing = User.query.filter_by(email=request.form['email']).first()
if existing:
if current.email != request.form['email']:
flash("Email already exists")
return redirect(url_for('main.users'))
my_data = User.query.get(request.form.get('id'))
my_data.name = request.form['name']
my_data.email = request.form['email']
my_data.admin = eval(request.form['admin'])
db.session.commit()
flash("Updated Successfully")

return redirect(url_for('main.users'))

return redirect(url_for('main.users'))


@main.route('/delete_user/<id>')
@login_required
def delete_user(id):
# delete a schedule item
user = User.query.filter_by(id=id).first()

if user:
db.session.delete(user)
db.session.commit()
flash("Deleted Successfully")

return redirect(url_for('main.users'))


@main.route('/create_user', methods=('GET', 'POST'))
@login_required
def create_user():
# create a new user

if request.method == 'POST':
name = request.form['name']
email = request.form['email']
admin = eval(request.form['admin'])
password = generate_password_hash(request.form['password'], method='scrypt')
user = User(name=name, email=email, admin=admin, password=password)
existing = User.query.filter_by(email=email).first()
if existing:
flash("User already exists")
return redirect(url_for('main.users'))
db.session.add(user)
db.session.commit()
flash("Added Successfully")

return redirect(url_for('main.users'))

return redirect(url_for('main.users'))


@main.route('/manifest.json')
def serve_manifest():
return send_file('manifest.json', mimetype='application/manifest+json')
Expand Down
1 change: 1 addition & 0 deletions app/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ class User(UserMixin, db.Model):
email = db.Column(db.String(100), unique=True)
password = db.Column(db.String(100))
name = db.Column(db.String(1000))
admin = db.Column(db.Boolean)


class Schedule(db.Model):
Expand Down
1 change: 1 addition & 0 deletions app/templates/base.html
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
<a href="/transactions">Transactions </a>
<a href="/holds">Holds/Skips </a>
<a href="/profile">Profile </a>
<a href="/settings">Settings </a>
<a href="/logout">Log Out </a>
</div>
</div>
Expand Down
126 changes: 126 additions & 0 deletions app/templates/index_guest.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
<!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">
<title>PyCashFlow</title>
<link rel="shortcut icon" href="{{ url_for('main.favicon') }}">
<link rel="apple-touch-icon" href="{{ url_for('main.appleicon') }}">
<link rel="icon" href="./static/favicon.ico">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.7.2/css/bulma.min.css" />
<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
<link rel=”stylesheet” href=”https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<link rel="stylesheet" href="./static/css/style.css"/>
<link rel="stylesheet" href="./static/css/dark.css"/>
<link rel="stylesheet" href="./static/css/normalize.css"/>
<link rel="stylesheet" href="./static/css/skeleton.css"/>
<link rel="icon" href="{{url_for('static', filename='icons/icon_144x144.png')}}" type="image/png">
<link rel="icon" href="{{url_for('static', filename='icons/icon_192x192.png')}}" type="image/png">
<link rel="icon" href="{{url_for('static', filename='icons/icon_512x512.png')}}" type="image/png">
<link rel="apple-touch-icon" href="{{url_for('static', filename='icons/icon_144x144.png')}}" type="image/png">
<link rel="apple-touch-icon" href="{{url_for('static', filename='icons/icon_192x192.png')}}" type="image/png">
<link rel="apple-touch-icon" href="{{url_for('static', filename='icons/icon_512x512.png')}}" type="image/png">
<link rel="manifest" href="/manifest.json">
<script>
if ('serviceWorker' in navigator) {
window.addEventListener('load', function() {
navigator.serviceWorker.register("/sw.js").then(function(registration) {
console.log('ServiceWorker registration successful with scope: ', registration.scope);
}, function(err) {
console.log('ServiceWorker registration failed: ', err);
});
});
}
</script>
<meta name="viewport" content="width=device-width, initial-scale=0.65">
</head>

<body>
<div class="container">
<div class="topnav1" id="myTopnav">
<a href="/" class="active">PyCashFlow</a>
<div class="dropdown1">
<button class="dropbtn">Menu
<i class="fa fa-caret-down"></i>
</button>
<div class="dropdown-content1">
<a href="/profile">Profile </a>
<a href="/logout">Log Out </a>
</div>
</div>
</div>

<div style="clear: both">
&nbsp;

<h1 class="title" style="color:white">
<p style="font-size:20px; float: center; text-align: center"><span style="color:white; font-weight:bold">{{ todaydate }}</span></p>
<p style="font-size:20px"><span style="color:white">Balance: {{ balance }}</span></p>
<p style="font-size:20px">Lowest Balance: <span style="color:white; font-weight:bold">${{ minbalance }}</span></p>
</h1>
<head>
<script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script>
function cb(selection) {
$.getJSON({
url: "/callback", data: { 'data': selection }, success: function (result) {
Plotly.newPlot('chart', result, {staticPlot: true});;
}
});
}
</script>
</head>

<body style="font-family:arial, sans-serif">
<div id="chart" class="chart"></div>
</body>

<script>
d = {{ graphJSON | safe }};
d.config={responsive: true};
Plotly.newPlot('chart', d, {});

</script>
<div id = "balancemodal" class = "modal fade" role="dialog">
<div class = "modal-dialog">
<div class="modal-content">
<div class = "modal-header">
<h4 class = "modal-title" style="color:black">Update Balance</h4>
</div>

<div class = "modal-body">
<form action = "{{url_for('main.balance')}}" method="POST">
<div class = "form-group">
<label style="color:black"> Balance:</label>
<input type="number" step="0.01" class="form-control" name="amount" required = "True">
</div>
<div class = "form-group">
<label style="color:black"> Date:</label>
<input type="date" class="form-control" name="date" required = "True" max="3000-01-01" onfocus="this.max=new Date().toISOString().split('T')[0]" />
</div>
<div class = "form-group">
<button class="btn btn-primary" type = "submit" name="schedule">Update Balance</button>
</div>

<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
</div>

</form>
</div>

</div>
</div>
</div>

</div>
</div>
</body>
</html>


76 changes: 1 addition & 75 deletions app/templates/profile.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,7 @@ <h1 class="title" style="color:white">
</h1>
<p><b style="color:white"><button type="button" style="font-size : 20px" class="btn btn-success float-center"
data-toggle="modal" data-target="#pwmodal">Change Password</button></b></p>
<p><b style="color:white"><button type="button" style="font-size : 20px" class="btn btn-success float-center"
data-toggle="modal" data-target="#emailmodal">Configure Email</button></b></p>
<p><b style="color:white"><button type="button" style="font-size : 20px" class="btn btn-success float-center"
data-toggle="modal" data-target="#settingsmodal">Settings</button></b></p>

<div id = "pwmodal" class = "modal fade" role="dialog">
<div class = "modal-dialog">
<div class="modal-content">
Expand All @@ -35,75 +32,4 @@ <h4 class = "modal-title" style="color:black">Change Password</h4>
</div>
</div>
</div>

<div id = "settingsmodal" class = "modal fade" role="dialog">
<div class = "modal-dialog">
<div class="modal-content">
<div class = "modal-header">
<h4 class = "modal-title" style="color:black">Settings</h4>
</div>

<div class = "modal-body">
<form action = "{{url_for('main.settings')}}" method="POST">
<div class="form-group">
<label style="color:black">Disable Sign-Ups:</label>
<select name="signupvalue" class="selectpicker form-control" style="width: 150px;">
<option value="True">On</option>
<option value="False">Off</option>
</select>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
</div>
<button type="submit" class="btn btn-success float-center">Go</button>
</form>
</div>

</div>
</div>
</div>

<div id = "emailmodal" class = "modal fade" role="dialog">
<div class = "modal-dialog">
<div class="modal-content">
<div class = "modal-header">
<h4 class = "modal-title" style="color:black">Configure Email</h4>
</div>

<div class = "modal-body">
<form action = "{{url_for('main.email')}}" method="POST">
<div class = "form-group">
<label style="color:black"> Email:</label>
<input class="input is-large" type="email" name="email" >
</div>
<div class = "form-group">
<label style="color:black"> Password:</label>
<input class="input is-large" type="password" name="password" >
</div>
<div class = "form-group">
<label style="color:black"> Server:</label>
<input class="input is-large" type="text" name="server" >
</div>
<div class = "form-group">
<label style="color:black"> Email Subject String:</label>
<input class="input is-large" type="text" name="subject_str" >
</div>
<div class = "form-group">
<label style="color:black"> String before balance:</label>
<input class="input is-large" type="text" name="start_str" >
</div>
<div class = "form-group">
<label style="color:black"> String after balance:</label>
<input class="input is-large" type="text" name="end_str" >
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
</div>
<button type="submit" class="btn btn-success float-center">Go</button>
</form>
</div>

</div>
</div>
</div>
{% endblock %}
Loading

0 comments on commit 54f0333

Please sign in to comment.