import re from flask import Blueprint from flask import flash from flask import current_app from flask import g from flask import redirect from flask import url_for from flask import request from flask import session from flask import render_template from flask_mail import Message from werkzeug.exceptions import abort from nanoid import generate from capsulflask.auth import account_required from capsulflask.db import get_model bp = Blueprint("console", __name__, url_prefix="/console") def makeCapsulId(): lettersAndNumbers = generate(alphabet="1234567890qwertyuiopasdfghjklzxcvbnm", size=10) return f"capsul-{lettersAndNumbers}" @bp.route("/") @account_required def index(): return render_template("capsuls.html", vms=get_model().list_vms_for_account(session["account"])) @bp.route("/ssh", methods=("GET", "POST")) @account_required def ssh_public_keys(): db_model = get_model() error = None if request.method == "POST": method = request.form["method"] name = request.form["name"] if not name or len(name.strip()) < 1: error = "Name is required" elif not re.match(r"^[0-9A-Za-z_ -]+$", name): error = "Name must match \"^[0-9A-Za-z_ -]+$\"" if method == "POST": content = request.form["content"] if not content or len(content.strip()) < 1: error = "Content is required" else: content = content.replace("\r", "").replace("\n", "") if not re.match(r"^(ssh|ecdsa)-[0-9A-Za-z+/_=@ -]+$", content): error = "Content must match \"^(ssh|ecdsa)-[0-9A-Za-z+/_=@ -]+$\"" if db_model.ssh_public_key_name_exists(session["account"], name): error = "A key with that name already exists" if error is None: db_model.create_ssh_public_key(session["account"], name, content) elif method == "DELETE": if error is None: db_model.delete_ssh_public_key(session["account"], name) if error: flash(error) # keys_list= # for key in keys_list: # if len(key['content']) > 40: # print(key['content']) # print(f"{key['content'][:20]}...{key['content'][len(key['content'])-20:]}") # key["content"] = # return return render_template( "ssh-public-keys.html", ssh_public_keys=map( lambda x: dict(name=x['name'], content=f"{x['content'][:20]}...{x['content'][len(x['content'])-20:]}"), db_model.list_ssh_public_keys_for_account(session["account"]) ) ) @bp.route("/create", methods=("GET", "POST")) @account_required def create(): db_model = get_model() vm_sizes = db_model.vm_sizes_dict() operating_systems = db_model.operating_systems_dict() ssh_public_keys = db_model.list_ssh_public_keys_for_account(session["account"]) error = None if request.method == "POST": size = request.form["size"] os = request.form["os"] if not size: error = "Size is required" elif size not in vm_sizes: error = f"Invalid size {size}" if not os: error = "OS is required" elif os not in operating_systems: error = f"Invalid os {os}" if error is None: id = makeCapsulId() db_model.create_vm( email=session["account"], id=id, size=size, os=os ) current_app.config["VIRTUALIZATION_MODEL"].create( email = session["account"], id=id, template_image_file_name=operating_systems[os].template_image_file_name, vcpus=vm_sizes[size].vcpus, memory=vm_sizes[size].memory ) if error: flash(error) return render_template( "create-capsul.html", ssh_public_keys=ssh_public_keys, operating_systems=operating_systems, vm_sizes=vm_sizes ) @bp.route("/billing") @account_required def faq(): return render_template("billing.html")