integrate docker to wallet creation and connection
This commit is contained in:
parent
e260b8f269
commit
1cecd043e4
|
@ -6,6 +6,7 @@ from wowstash.blueprints.auth import auth_bp
|
||||||
from wowstash.forms import Register, Login
|
from wowstash.forms import Register, Login
|
||||||
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
|
||||||
|
|
||||||
|
|
||||||
@auth_bp.route("/register", methods=["GET", "POST"])
|
@auth_bp.route("/register", methods=["GET", "POST"])
|
||||||
|
@ -69,7 +70,7 @@ def login():
|
||||||
@auth_bp.route("/logout")
|
@auth_bp.route("/logout")
|
||||||
def logout():
|
def logout():
|
||||||
if current_user.is_authenticated:
|
if current_user.is_authenticated:
|
||||||
current_user.kill_wallet()
|
docker.stop_container(current_user.wallet_container)
|
||||||
current_user.clear_wallet_data()
|
current_user.clear_wallet_data()
|
||||||
logout_user()
|
logout_user()
|
||||||
return redirect(url_for('meta.index'))
|
return redirect(url_for('meta.index'))
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import subprocess
|
from time import sleep
|
||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
from base64 import b64encode
|
from base64 import b64encode
|
||||||
from qrcode import make as qrcode_make
|
from qrcode import make as qrcode_make
|
||||||
|
@ -9,6 +9,7 @@ from flask_login import login_required, current_user
|
||||||
from socket import socket
|
from socket import socket
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from wowstash.blueprints.wallet import wallet_bp
|
from wowstash.blueprints.wallet import wallet_bp
|
||||||
|
from wowstash.library.docker import docker
|
||||||
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
|
||||||
|
@ -21,6 +22,7 @@ from wowstash import config
|
||||||
@login_required
|
@login_required
|
||||||
def loading():
|
def loading():
|
||||||
if current_user.wallet_connected and current_user.wallet_created:
|
if current_user.wallet_connected and current_user.wallet_created:
|
||||||
|
sleep(1)
|
||||||
return redirect(url_for('wallet.dashboard'))
|
return redirect(url_for('wallet.dashboard'))
|
||||||
return render_template('wallet/loading.html')
|
return render_template('wallet/loading.html')
|
||||||
|
|
||||||
|
@ -46,7 +48,7 @@ def dashboard():
|
||||||
for tx in transfers[type]:
|
for tx in transfers[type]:
|
||||||
all_transfers.append(tx)
|
all_transfers.append(tx)
|
||||||
balances = wallet.get_balances()
|
balances = wallet.get_balances()
|
||||||
qr_uri = f'wownero:{address}?tx_description="{current_user.email}"'
|
qr_uri = f'wownero:{address}?tx_description={current_user.email}'
|
||||||
address_qr = qrcode_make(qr_uri).save(_address_qr)
|
address_qr = qrcode_make(qr_uri).save(_address_qr)
|
||||||
qrcode = b64encode(_address_qr.getvalue()).decode()
|
qrcode = b64encode(_address_qr.getvalue()).decode()
|
||||||
return render_template(
|
return render_template(
|
||||||
|
@ -63,42 +65,33 @@ def dashboard():
|
||||||
@login_required
|
@login_required
|
||||||
def connect():
|
def connect():
|
||||||
if current_user.wallet_connected is False:
|
if current_user.wallet_connected is False:
|
||||||
tcp = socket()
|
wallet = docker.start_wallet(current_user.id)
|
||||||
tcp.bind(('', 0))
|
port = docker.get_port(wallet)
|
||||||
_, port = tcp.getsockname()
|
current_user.wallet_connected = docker.container_exists(wallet)
|
||||||
tcp.close()
|
current_user.wallet_port = port
|
||||||
command = f"""wownero-wallet-rpc \
|
current_user.wallet_container = wallet
|
||||||
--detach \
|
db.session.commit()
|
||||||
--non-interactive \
|
|
||||||
--rpc-bind-port {port} \
|
|
||||||
--wallet-file {config.WALLET_DIR}/{current_user.id}.wallet \
|
|
||||||
--rpc-login {current_user.id}:{current_user.wallet_password} \
|
|
||||||
--password {current_user.wallet_password} \
|
|
||||||
--daemon-address {config.DAEMON_PROTO}://{config.DAEMON_HOST}:{config.DAEMON_PORT} \
|
|
||||||
--daemon-login {config.DAEMON_USER}:{config.DAEMON_PASS} \
|
|
||||||
--log-file {config.WALLET_DIR}/{current_user.id}.log
|
|
||||||
"""
|
|
||||||
proc = subprocess.Popen(command.split(), stdout=subprocess.PIPE)
|
|
||||||
outs, errs = proc.communicate()
|
|
||||||
# print(outs)
|
|
||||||
if proc.returncode == 0:
|
|
||||||
print(f'Successfully started RPC for {current_user}!')
|
|
||||||
current_user.wallet_connected = True
|
|
||||||
current_user.wallet_port = port
|
|
||||||
current_user.wallet_pid = proc.pid
|
|
||||||
current_user.wallet_connect_date = datetime.now()
|
|
||||||
db.session.commit()
|
|
||||||
|
|
||||||
return "ok"
|
return 'ok'
|
||||||
|
|
||||||
|
@wallet_bp.route('/wallet/create')
|
||||||
|
@login_required
|
||||||
|
def create():
|
||||||
|
if current_user.wallet_created is False:
|
||||||
|
docker.create_wallet(current_user.id)
|
||||||
|
current_user.wallet_created = True
|
||||||
|
db.session.commit()
|
||||||
|
|
||||||
|
return 'ok'
|
||||||
|
|
||||||
@wallet_bp.route('/wallet/status')
|
@wallet_bp.route('/wallet/status')
|
||||||
@login_required
|
@login_required
|
||||||
def status():
|
def status():
|
||||||
data = {
|
data = {
|
||||||
"created": current_user.wallet_created,
|
'created': current_user.wallet_created,
|
||||||
"connected": current_user.wallet_connected,
|
'connected': current_user.wallet_connected,
|
||||||
"port": current_user.wallet_port,
|
'port': current_user.wallet_port,
|
||||||
"date": current_user.wallet_connect_date
|
'container': current_user.wallet_container
|
||||||
}
|
}
|
||||||
return jsonify(data)
|
return jsonify(data)
|
||||||
|
|
||||||
|
|
|
@ -57,6 +57,7 @@ def create_app():
|
||||||
login_manager = LoginManager()
|
login_manager = LoginManager()
|
||||||
login_manager.init_app(app)
|
login_manager.init_app(app)
|
||||||
login_manager.login_view = 'auth.login'
|
login_manager.login_view = 'auth.login'
|
||||||
|
login_manager.logout_view = 'auth.logout'
|
||||||
|
|
||||||
@login_manager.user_loader
|
@login_manager.user_loader
|
||||||
def load_user(user_id):
|
def load_user(user_id):
|
||||||
|
@ -73,7 +74,16 @@ def create_app():
|
||||||
@app.template_filter('from_atomic')
|
@app.template_filter('from_atomic')
|
||||||
def from_atomic(a):
|
def from_atomic(a):
|
||||||
from wowstash.library.jsonrpc import from_atomic
|
from wowstash.library.jsonrpc import from_atomic
|
||||||
return from_atomic(a)
|
atomic = from_atomic(a)
|
||||||
|
if atomic == 0:
|
||||||
|
return 0
|
||||||
|
else:
|
||||||
|
return float(atomic)
|
||||||
|
|
||||||
|
@app.cli.command('clean_containers')
|
||||||
|
def clean_containers():
|
||||||
|
from wowstash.library.docker import docker
|
||||||
|
docker.cleanup()
|
||||||
|
|
||||||
# Routes
|
# Routes
|
||||||
from wowstash.blueprints.auth import auth_bp
|
from wowstash.blueprints.auth import auth_bp
|
||||||
|
|
|
@ -9,7 +9,7 @@ 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', './data/wallets')
|
self.wallet_dir = getattr(config, 'WALLET_DIR', '/tmp/wallets')
|
||||||
self.listen_port = 34569
|
self.listen_port = 34569
|
||||||
|
|
||||||
def create_wallet(self, user_id):
|
def create_wallet(self, user_id):
|
||||||
|
@ -45,6 +45,8 @@ class Docker(object):
|
||||||
command = f"""wownero-wallet-rpc \
|
command = f"""wownero-wallet-rpc \
|
||||||
--non-interactive \
|
--non-interactive \
|
||||||
--rpc-bind-port {self.listen_port} \
|
--rpc-bind-port {self.listen_port} \
|
||||||
|
--rpc-bind-ip 0.0.0.0 \
|
||||||
|
--confirm-external-bind \
|
||||||
--wallet-file /wallet/{u.id}.wallet \
|
--wallet-file /wallet/{u.id}.wallet \
|
||||||
--rpc-login {u.id}:{u.wallet_password} \
|
--rpc-login {u.id}:{u.wallet_password} \
|
||||||
--password {u.wallet_password} \
|
--password {u.wallet_password} \
|
||||||
|
@ -60,7 +62,7 @@ class Docker(object):
|
||||||
remove=True,
|
remove=True,
|
||||||
detach=True,
|
detach=True,
|
||||||
ports={
|
ports={
|
||||||
f'{self.listen_port}/tcp': None
|
f'{self.listen_port}/tcp': ('127.0.0.1', None)
|
||||||
},
|
},
|
||||||
volumes={
|
volumes={
|
||||||
f'{self.wallet_dir}/{u.id}': {
|
f'{self.wallet_dir}/{u.id}': {
|
||||||
|
@ -83,3 +85,18 @@ class Docker(object):
|
||||||
return True
|
return True
|
||||||
except NotFound:
|
except NotFound:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
def stop_container(self, container_id):
|
||||||
|
if self.container_exists(container_id):
|
||||||
|
c = self.client.containers.get(container_id)
|
||||||
|
c.stop()
|
||||||
|
|
||||||
|
def cleanup(self):
|
||||||
|
users = User.query.all()
|
||||||
|
for u in users:
|
||||||
|
if u.wallet_container:
|
||||||
|
if not self.container_exists(u.wallet_container):
|
||||||
|
u.clear_wallet_data()
|
||||||
|
|
||||||
|
|
||||||
|
docker = Docker()
|
||||||
|
|
|
@ -18,8 +18,7 @@ class User(db.Model):
|
||||||
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)
|
||||||
wallet_pid = db.Column(db.Integer, nullable=True)
|
wallet_container = db.Column(db.String(30), nullable=True)
|
||||||
wallet_connect_date = db.Column(db.DateTime, nullable=True)
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_authenticated(self):
|
def is_authenticated(self):
|
||||||
|
@ -40,17 +39,10 @@ class User(db.Model):
|
||||||
def get_id(self):
|
def get_id(self):
|
||||||
return self.id
|
return self.id
|
||||||
|
|
||||||
def kill_wallet(self):
|
|
||||||
try:
|
|
||||||
kill(self.wallet_pid, 9)
|
|
||||||
except Exception as e:
|
|
||||||
print('could kill:', e)
|
|
||||||
|
|
||||||
def clear_wallet_data(self):
|
def clear_wallet_data(self):
|
||||||
self.wallet_connected = False
|
self.wallet_connected = False
|
||||||
self.wallet_port = None
|
self.wallet_port = None
|
||||||
self.wallet_pid = None
|
self.wallet_container = None
|
||||||
self.wallet_connect_date = None
|
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
|
|
|
@ -41,7 +41,7 @@
|
||||||
xhr.send();
|
xhr.send();
|
||||||
}
|
}
|
||||||
|
|
||||||
{% if current_user.wallet_connected == False %}
|
{% if current_user.wallet_connected == False and current_user.wallet_created == True %}
|
||||||
document.addEventListener("DOMContentLoaded", function(){
|
document.addEventListener("DOMContentLoaded", function(){
|
||||||
var xhr = new XMLHttpRequest();
|
var xhr = new XMLHttpRequest();
|
||||||
xhr.open('GET', '{{ url_for("wallet.connect") }}');
|
xhr.open('GET', '{{ url_for("wallet.connect") }}');
|
||||||
|
@ -49,6 +49,14 @@
|
||||||
});
|
});
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
{% if current_user.wallet_connected == False and current_user.wallet_created == False %}
|
||||||
|
document.addEventListener("DOMContentLoaded", function(){
|
||||||
|
var xhr = new XMLHttpRequest();
|
||||||
|
xhr.open('GET', '{{ url_for("wallet.create") }}');
|
||||||
|
xhr.send();
|
||||||
|
});
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
window.setInterval(function(){
|
window.setInterval(function(){
|
||||||
{% if current_user.wallet_connected == False %}
|
{% if current_user.wallet_connected == False %}
|
||||||
check_wallet_status('connected');
|
check_wallet_status('connected');
|
||||||
|
|
Loading…
Reference in New Issue