add user wallet deletion

mm-logging
lza_menace 4 years ago
parent 86fd1ecbcc
commit c379ae9bc9

@ -1,9 +1,8 @@
from os import kill from os import kill
from flask import request, render_template, session, redirect, url_for, flash from flask import request, render_template, session, redirect, url_for, flash
from flask_login import login_user, logout_user, current_user from flask_login import login_user, logout_user, current_user, login_required
from secrets import token_urlsafe
from wowstash.blueprints.auth import auth_bp from wowstash.blueprints.auth import auth_bp
from wowstash.forms import Register, Login from wowstash.forms import Register, Login, Delete
from wowstash.models import User from wowstash.models import User
from wowstash.factory import db, bcrypt from wowstash.factory import db, bcrypt
from wowstash.library.docker import docker from wowstash.library.docker import docker
@ -28,7 +27,6 @@ def register():
user = User( user = User(
email=form.email.data, email=form.email.data,
password=bcrypt.generate_password_hash(form.password.data).decode('utf8'), password=bcrypt.generate_password_hash(form.password.data).decode('utf8'),
wallet_password=token_urlsafe(16),
) )
db.session.add(user) db.session.add(user)
db.session.commit() db.session.commit()
@ -76,6 +74,22 @@ def logout():
docker.stop_container(current_user.wallet_container) docker.stop_container(current_user.wallet_container)
send_es({'type': 'stop_container', 'user': current_user.email}) send_es({'type': 'stop_container', 'user': current_user.email})
current_user.clear_wallet_data() current_user.clear_wallet_data()
send_es({'type': 'logout', 'user': current_user.email}) send_es({'type': 'logout', 'user': current_user.email})
logout_user() logout_user()
return redirect(url_for('meta.index')) return redirect(url_for('meta.index'))
@auth_bp.route("/delete", methods=["GET", "POST"])
@login_required
def delete():
form = Delete()
if form.validate_on_submit():
docker.stop_container(current_user.wallet_container)
send_es({'type': 'stop_container', 'user': current_user.email})
docker.delete_wallet_data(current_user.id)
send_es({'type': 'delete_wallet', 'user': current_user.email})
current_user.clear_wallet_data(reset_password=True, reset_wallet=True)
flash('Successfully deleted wallet data')
return redirect(url_for('meta.index'))
else:
flash('Please confirm deletion of the account')
return redirect(url_for('wallet.dashboard'))

@ -13,7 +13,7 @@ from wowstash.library.docker import docker
from wowstash.library.elasticsearch import send_es from wowstash.library.elasticsearch import send_es
from wowstash.library.jsonrpc import Wallet, to_atomic from wowstash.library.jsonrpc import Wallet, to_atomic
from wowstash.library.cache import cache from wowstash.library.cache import cache
from wowstash.forms import Send from wowstash.forms import Send, Delete
from wowstash.factory import db from wowstash.factory import db
from wowstash.models import User from wowstash.models import User
from wowstash import config from wowstash import config
@ -31,6 +31,7 @@ def loading():
@login_required @login_required
def dashboard(): def dashboard():
send_form = Send() send_form = Send()
delete_form = Delete()
_address_qr = BytesIO() _address_qr = BytesIO()
all_transfers = list() all_transfers = list()
wallet = Wallet( wallet = Wallet(
@ -67,6 +68,7 @@ def dashboard():
address=address, address=address,
qrcode=qrcode, qrcode=qrcode,
send_form=send_form, send_form=send_form,
delete_form=delete_form,
user=current_user, user=current_user,
seed=seed, seed=seed,
spend_key=spend_key, spend_key=spend_key,

@ -17,3 +17,6 @@ class Login(FlaskForm):
class Send(FlaskForm): class Send(FlaskForm):
address = StringField('Destination Address:', validators=[DataRequired()], render_kw={"placeholder": "Wownero address", "class": "form-control"}) address = StringField('Destination Address:', validators=[DataRequired()], render_kw={"placeholder": "Wownero address", "class": "form-control"})
amount = StringField('Amount:', validators=[DataRequired()], render_kw={"placeholder": "Amount to send or \"all\"", "class": "form-control"}) amount = StringField('Amount:', validators=[DataRequired()], render_kw={"placeholder": "Amount to send or \"all\"", "class": "form-control"})
class Delete(FlaskForm):
confirm = BooleanField('Confirm Account and Wallet Deletion:', validators=[DataRequired()], render_kw={"class": "form-control-span"})

@ -1,8 +1,12 @@
from docker import from_env, APIClient from docker import from_env, APIClient
from docker.errors import NotFound, NullResource, APIError from docker.errors import NotFound, NullResource, APIError
from socket import socket from socket import socket
from shutil import rmtree
from os.path import expanduser
from secrets import token_urlsafe
from wowstash import config from wowstash import config
from wowstash.models import User from wowstash.models import User
from wowstash.factory import db
from wowstash.library.jsonrpc import daemon from wowstash.library.jsonrpc import daemon
from wowstash.library.elasticsearch import send_es from wowstash.library.elasticsearch import send_es
@ -11,11 +15,13 @@ class Docker(object):
def __init__(self): def __init__(self):
self.client = from_env() self.client = from_env()
self.wownero_image = getattr(config, 'WOWNERO_IMAGE', 'lalanza808/wownero') self.wownero_image = getattr(config, 'WOWNERO_IMAGE', 'lalanza808/wownero')
self.wallet_dir = getattr(config, 'WALLET_DIR', '/tmp/wallets') self.wallet_dir = expanduser(getattr(config, 'WALLET_DIR', '~/data/wallets'))
self.listen_port = 34569 self.listen_port = 8888
def create_wallet(self, user_id): def create_wallet(self, user_id):
u = User.query.get(user_id) u = User.query.get(user_id)
u.wallet_password = token_urlsafe(12)
db.session.commit()
command = f"""wownero-wallet-cli \ command = f"""wownero-wallet-cli \
--generate-new-wallet /wallet/{u.id}.wallet \ --generate-new-wallet /wallet/{u.id}.wallet \
--restore-height {daemon.info()['height']} \ --restore-height {daemon.info()['height']} \
@ -103,6 +109,11 @@ class Docker(object):
c = self.client.containers.get(container_id) c = self.client.containers.get(container_id)
c.stop() c.stop()
def delete_wallet_data(self, user_id):
user_dir = f'{self.wallet_dir}/{user_id}'
res = rmtree(user_dir)
return res
def cleanup(self): def cleanup(self):
users = User.query.all() users = User.query.all()
for u in users: for u in users:

@ -14,7 +14,7 @@ class User(db.Model):
email = db.Column(db.String(50), unique=True, index=True) email = db.Column(db.String(50), unique=True, index=True)
password = db.Column(db.String(120)) password = db.Column(db.String(120))
register_date = db.Column(db.DateTime, server_default=func.now()) register_date = db.Column(db.DateTime, server_default=func.now())
wallet_password = db.Column(db.String(120)) wallet_password = db.Column(db.String(120), nullable=True)
wallet_created = db.Column(db.Boolean, default=False) wallet_created = db.Column(db.Boolean, default=False)
wallet_connected = db.Column(db.Boolean, default=False) wallet_connected = db.Column(db.Boolean, default=False)
wallet_port = db.Column(db.Integer, nullable=True) wallet_port = db.Column(db.Integer, nullable=True)
@ -39,10 +39,14 @@ class User(db.Model):
def get_id(self): def get_id(self):
return self.id return self.id
def clear_wallet_data(self): def clear_wallet_data(self, reset_password=False, reset_wallet=False):
self.wallet_connected = False self.wallet_connected = False
self.wallet_port = None self.wallet_port = None
self.wallet_container = None self.wallet_container = None
if reset_password:
self.wallet_password = None
if reset_wallet:
self.wallet_created = False
db.session.commit() db.session.commit()
def __repr__(self): def __repr__(self):

@ -14,7 +14,7 @@
<div class="header-content mx-auto"> <div class="header-content mx-auto">
<h1 class="mb-5">Manage your Wownero funds securely and anonymously.</h1> <h1 class="mb-5">Manage your Wownero funds securely and anonymously.</h1>
{% if current_user.is_authenticated %} {% if current_user.is_authenticated %}
<a href="{{ url_for('wallet.dashboard') }}" class="btn btn-outline btn-xl">Wallet Dashboard</a> <a href="{{ url_for('wallet.dashboard') }}" class="btn btn-outline btn-xl">{% if current_user.wallet_created %}Wallet Dashboard{% else %}Create Wallet{% endif %}</a>
{% else %} {% else %}
<a href="{{ url_for('auth.register') }}" class="btn btn-outline btn-xl">Register</a> <a href="{{ url_for('auth.register') }}" class="btn btn-outline btn-xl">Register</a>
<a href="{{ url_for('auth.login') }}" class="btn btn-outline btn-xl">Login</a> <a href="{{ url_for('auth.login') }}" class="btn btn-outline btn-xl">Login</a>

@ -69,14 +69,6 @@
<div class="container-slim"> <div class="container-slim">
<div class="section-heading text-center"> <div class="section-heading text-center">
<h2>Send</h2> <h2>Send</h2>
{% if current_user.funds_locked %}
<p>Sending funds is currently locked due to a transfer already in progress. Please try again in a few minutes. Pending transfers:</p>
<ul>
{% for tx in txs_queued %}
<li class="slim small">{{ tx.amount | from_atomic }} - {{ tx.address }}</li>
{% endfor %}
</ul>
{% else %}
<form method="POST" action="{{ url_for('wallet.send') }}" class="send-form"> <form method="POST" action="{{ url_for('wallet.send') }}" class="send-form">
{{ send_form.csrf_token }} {{ send_form.csrf_token }}
{% for f in send_form %} {% for f in send_form %}
@ -94,7 +86,6 @@
</ul> </ul>
<input type="submit" value="Send" class="btn btn-link btn-outline btn-xl"> <input type="submit" value="Send" class="btn btn-link btn-outline btn-xl">
</form> </form>
{% endif %}
</div> </div>
</div> </div>
</section> </section>
@ -117,6 +108,32 @@
</div> </div>
</section> </section>
<section class="section2" id="send">
<div class="container-slim">
<div class="section-heading text-center">
<h2>Delete Account</h2>
<p>You can and should delete your wallet from the server. Please ensure you have copied the mnemonic seed from the secrets above if there are still funds associated with the keys.</p>
<form method="POST" action="{{ url_for('auth.delete') }}" class="send-form">
{{ delete_form.csrf_token }}
{% for f in delete_form %}
{% if f.name != 'csrf_token' %}
<div class="form-group">
{{ f.label }}
{{ f }}
</div>
{% endif %}
{% endfor %}
<ul>
{% for field, errors in delete_form.errors.items() %}
<li>{{ send_form[field].label }}: {{ ', '.join(errors) }}</li>
{% endfor %}
</ul>
<input type="submit" value="Delete" class="btn btn-link btn-outline btn-xl">
</form>
</div>
</div>
</section>
{% include 'footer.html' %} {% include 'footer.html' %}
{% include 'scripts.html' %} {% include 'scripts.html' %}

Loading…
Cancel
Save