Skip to content

Commit

Permalink
Add CRUD App
Browse files Browse the repository at this point in the history
  • Loading branch information
Jcharis committed Jul 9, 2022
1 parent ffc0bb8 commit 0fa0427
Show file tree
Hide file tree
Showing 9 changed files with 291 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ celerybeat.pid
.venv
env/
venv/
myvenv/
ENV/
env.bak/
venv.bak/
Expand Down
19 changes: 19 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,21 @@
# password-manager-app
Password Manager App with Flask and Python CRUD

#### Aim
Explore the concept of CRUD using Flask and Flask SQLAlchemy
+ Create
+ Read
+ Update
+ Delete

#### To Do
+ Add Exporting of password as json,csv
+ Add importing of json or csv to app
+ Encrypting of Password with Symmetric Encryption


#### .
+ By Jesse E. Agbe(JCharis)
+ Jesus Saves @ JCharisTech


103 changes: 103 additions & 0 deletions app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
from flask import Flask,render_template,request,url_for,flash,redirect,send_file
from flask_sqlalchemy import SQLAlchemy
from cryptography.fernet import Fernet
import csv
import time
timestr = time.strftime("%Y%m%d-%H%M%S")


app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///data.db'
app.config['SECRET_KEY'] = 'the random string'
db = SQLAlchemy(app)

# Model
class PasswordManager(db.Model):
id = db.Column(db.Integer, primary_key=True)
email = db.Column(db.String(520), nullable=False)
site_url = db.Column(db.String(520), nullable=False)
site_password = db.Column(db.String(520), nullable=False)

def __repr__(self):
return '<PasswordManager %r>' % self.email

# from cryptography.fernet import Fernet
# key = Fernet.generate_key()
# with open("secret_key.txt","wb") as f:
# f.write(key)

with open("secret_key.txt","rb") as f:
key = f.read()


def encrypt_password(key,data):
f = Fernet(key)
encrypted_token = f.encrypt(str(data).encode())
return encrypted_token




@app.route("/")
def index():
passwordlist = PasswordManager.query.all()
return render_template('index.html', passwordlist=passwordlist)

@app.route("/add",methods=["GET","POST"])
def add_password():
if request.method == 'POST':
email = request.form['email']
site_url = request.form['site_url']
site_password = request.form['site_password']
new_password_details = PasswordManager(email=email,site_url=site_url,site_password=site_password)
db.session.add(new_password_details)
db.session.commit()
flash("Password Added")
return redirect('/')


@app.route('/delete/<int:id>')
def delete(id):
new_password_to_delete = PasswordManager.query.get_or_404(id)

try:
db.session.delete(new_password_to_delete)
db.session.commit()
return redirect('/')
except:
return 'There was a problem deleting that task'

@app.route('/update/<int:id>', methods=['GET', 'POST'])
def update(id):
task = PasswordManager.query.get_or_404(id)

if request.method == 'POST':
task.email = request.form['email']
task.site_url = request.form['site_url']
task.site_password = request.form['site_password']
try:
db.session.commit()
flash("Password Updated")
return redirect('/')
except:
return 'There was an issue updating your task'

else:
return render_template('update.html', task=task)


@app.route('/export')
def export_data():
with open('dump.csv', 'w') as f:
out = csv.writer(f)
out.writerow(['id', 'email','site_url','site_password'])
for item in PasswordManager.query.all():
out.writerow([item.id, item.email,item.site_url,item.site_password])
return send_file('dump.csv',
mimetype='text/csv',
download_name=f"Export_Password_{timestr}.csv",
as_attachment=True)


if __name__ == "__main__":
app.run(debug=True)
Binary file added data.db
Binary file not shown.
3 changes: 3 additions & 0 deletions dump.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
id,email,site_url,site_password
1,[email protected],facebook.com,facebookhjhj
2,[email protected],jch.com,12345678
Expand Down
Binary file added requirements.txt
Binary file not shown.
1 change: 1 addition & 0 deletions secret_key.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
TaGi6wX2Qic-S0WyhG5vtdHLxtApO_Wq7hvIbgeKNZM=
103 changes: 103 additions & 0 deletions templates/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
<!DOCTYPE html>
<html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Password Master</title>
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-0evHe/X+R7YkIZDRvuzKMRqM+OrBnVFBL6DOitfPri4tjfHxaWutUpFmBp4vmVor" crossorigin="anonymous">

</head>

<body>
<div>
<h3 class="display-3 text-center my-3">Password Manager</h3>
</div>

<div class="container">
<!-- RESPONSIVE CLASSES -->
<div class="row">
<!-- stacks the columns on small screen sizes -->
<div class="col-md-6">
<h3></h3>
<p></p>
</div>
<!--FORMS HERE-->
<div class="col-md-4">
<h3>Password Register</h3>
<!--FORMS HERE-->
<form method="POST" action="/add">
<label for="profile-url">Email</label>
<div class="input-group">
<input type="email" class="form-control" name="email" placeholder="Email">
</div>
<label for="profile-url">Site URL</label>
<div class="input-group">
<input type="text" class="form-control" name="site_url" placeholder="Site URL">
</div>
<label for="site_password">Password</label>
<div class="input-group">
<input type="password" class="form-control" name="site_password" id="profile-url">
</div>
<br>
<button type="submit" class="btn btn-primary mb-3">Add Password</button>
</form>
<!--FORMS HERE-->

</div>

</div>



<div class="container">
<table class="table">
<!-- gives only the heading a black background -->
<thead class="thead-inverse">
<tr>
<th>Email</th>
<th>Site Address</th>
<th>Site Password</th>
<th>Actions</th>
<th>Visibility</th>

</tr>
</thead>
<tbody>
{% for task in passwordlist %}
<tr>
<td>{{ task.email }}</td>
<td>{{ task.site_url }}</td>
<td><input type="password" value="{{ task.site_password }}" id="{{ task.id}}"></td>
<td>
<a class="btn btn-outline-danger btn-sm" role="button" href="/delete/{{task.id}}">Delete</a>
<br>
<a class="btn btn-outline-success btn-sm" role="button" href="/update/{{task.id}}">Update</a>
</td>
<td>
<input type="checkbox" onclick="myFunction({{ task.id}})">Show Password
</td>
</tr>
</tbody>
{% endfor %}
</table>
</div>
<div class="container">
<a href="{{url_for('export_data')}}" type="button" class="btn btn-primary mb-3">Export as CSV</a>
</div>
</div>

<script>
function myFunction(pid) {
var x = document.getElementById(pid);
if (x.type === "password") {
x.type = "text";
} else {
x.type = "password";
}
}
</script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js" integrity="sha384-pprn3073KE6tl6bjs2QrFaJGz5/SUsLqktiwsUTF55Jfv3qYSDhgCecCxMW52nD2" crossorigin="anonymous"></script>

</body>
</html>
61 changes: 61 additions & 0 deletions templates/update.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
<!DOCTYPE html>
<html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Password Master</title>
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-0evHe/X+R7YkIZDRvuzKMRqM+OrBnVFBL6DOitfPri4tjfHxaWutUpFmBp4vmVor" crossorigin="anonymous">

</head>

<body>
<div>
<h3 class="display-3 text-center my-3">Password Manager</h3>

</div>

<div class="container">

<a href="{{url_for('index')}}" type="button" class="btn btn-primary mb-3">Back</a>


<!--FORMS HERE-->
<form class="row g-3" method="POST" action="/update/{{task.id}}">
<div class="col-auto">
<label for="inputEmail" class="visually-hidden">Email</label>
<input type="email" name="email" class="form-control" id="inputEmail" placeholder="Email" value="{{ task.email}}">
</div>
<div class="col-auto">
<label for="inputURL" class="visually-hidden">Site URL</label>
<input type="text" class="form-control" id="inputURL" name="site_url" placeholder="Site URL" value="{{ task.site_url}}">
</div>
<div class="col-auto">
<label for="inputPassword2" class="visually-hidden">Password</label>
<input type="password" class="form-control" id="inputPassword2" placeholder="Password" name="site_password" value="{{ task.site_password}}">
</div>
<div class="col-auto">
<input type="checkbox" onclick="myFunction()">Show Password
</div>

<div class="col-auto">
<button type="submit" class="btn btn-primary mb-3">Save Details</button>
</div>
</form>
</div>


<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js" integrity="sha384-pprn3073KE6tl6bjs2QrFaJGz5/SUsLqktiwsUTF55Jfv3qYSDhgCecCxMW52nD2" crossorigin="anonymous"></script>
<script>
function myFunction() {
var x = document.getElementById("inputPassword2");
if (x.type === "password") {
x.type = "text";
} else {
x.type = "password";
}
}
</script>

</body>
</html>

0 comments on commit 0fa0427

Please sign in to comment.