forked from 3wordchant/capsul-flask
136 lines
3.7 KiB
Python
136 lines
3.7 KiB
Python
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") |