Browse Source

fix defaults for running locally and make email server not required.

asd
forest 7 months ago
parent
commit
bdabd61057
  1. 30
      README.md
  2. 24
      capsulflask/__init__.py
  3. 3
      capsulflask/auth.py
  4. 2
      capsulflask/cli.py
  5. 6
      capsulflask/templates/login-landing.html

30
README.md

@ -31,29 +31,33 @@ Run an instance of Postgres (I used docker for this, you can use whatever you wa
docker run --rm -it -e POSTGRES_PASSWORD=dev -p 5432:5432 postgres
```
Create a `.env` file to set up the application configuration:
Run the app
```
nano .env
pipenv run flask run
```
Enter your SMTP credentials like this:
Run the app in gunicorn:
```
MAIL_USERNAME=forest@nullhex.com
MAIL_DEFAULT_SENDER=forest@nullhex.com
MAIL_PASSWORD=**************
pipenv run gunicorn --bind 127.0.0.1:5000 -k gevent --worker-connections 1000 app:app
```
Run the app
## configuration:
Create a `.env` file to set up the application configuration:
```
pipenv run flask run
nano .env
```
Run the app in gunicorn:
You can enter any environment variables referenced in `__init__.py` to this file.
For example you may enter your SMTP credentials like this:
```
pipenv run gunicorn --bind 127.0.0.1:5000 -k gevent --worker-connections 1000 app:app
MAIL_USERNAME=forest@nullhex.com
MAIL_DEFAULT_SENDER=forest@nullhex.com
MAIL_PASSWORD=**************
```
## how to view the logs on the database server (legion.cyberia.club)
@ -127,10 +131,10 @@ right now I have 2 types of operations, immediate mode and async.
both types of operations do assignment synchronously. so if the system cant assign the operation to one or more hosts (spokes),
or whatever the operation requires, then it will fail.
some operations tolerate partial failures, like, capacity_avaliable will succeed if at least one spoke succeeds
for immediate mode, assignment and completion of the operation (like `list`, `capacity_avaliable`, `destroy`) are the same thing
some operations tolerate partial failures, like, `capacity_avaliable` will succeed if at least one spoke succeeds.
for immediate mode requests (like `list`, `capacity_avaliable`, `destroy`), assignment and completion of the operation are the same thing.
for async ones, they can be assigned without knowing whether or not they succeeded (`create`)
for async ones, they can be assigned without knowing whether or not they succeeded (`create`).
![](readme/hub-and-spoke2.png)

24
capsulflask/__init__.py

@ -10,7 +10,7 @@ import sys
import stripe
from dotenv import load_dotenv, find_dotenv
from flask import Flask
from flask_mail import Mail
from flask_mail import Mail, Message
from flask import render_template
from flask import url_for
from flask import current_app
@ -22,6 +22,9 @@ from capsulflask import hub_model, spoke_model, cli
from capsulflask.btcpay import client as btcpay
from capsulflask.http_client import MyHTTPClient
class StdoutMockFlaskMail:
def send(self, message: Message):
current_app.logger.info(f"Email would have been sent if configured:\n\nto: {','.join(message.recipients)}\nsubject: {message.subject}\nbody:\n\n{message.body}\n\n")
load_dotenv(find_dotenv())
@ -31,10 +34,10 @@ app.config.from_mapping(
BASE_URL=os.environ.get("BASE_URL", default="http://localhost:5000"),
SECRET_KEY=os.environ.get("SECRET_KEY", default="dev"),
HUB_MODE_ENABLED=os.environ.get("HUB_MODE_ENABLED", default="False").lower() in ['true', '1', 't', 'y', 'yes'],
HUB_MODE_ENABLED=os.environ.get("HUB_MODE_ENABLED", default="True").lower() in ['true', '1', 't', 'y', 'yes'],
SPOKE_MODE_ENABLED=os.environ.get("SPOKE_MODE_ENABLED", default="True").lower() in ['true', '1', 't', 'y', 'yes'],
INTERNAL_HTTP_TIMEOUT_SECONDS=os.environ.get("INTERNAL_HTTP_TIMEOUT_SECONDS", default="300"),
HUB_MODEL=os.environ.get("HUB_MODEL", default="mock"),
HUB_MODEL=os.environ.get("HUB_MODEL", default="capsul-flask"),
SPOKE_MODEL=os.environ.get("SPOKE_MODEL", default="mock"),
LOG_LEVEL=os.environ.get("LOG_LEVEL", default="INFO"),
SPOKE_HOST_ID=os.environ.get("SPOKE_HOST_ID", default="default"),
@ -51,12 +54,12 @@ app.config.from_mapping(
DATABASE_SCHEMA=os.environ.get("DATABASE_SCHEMA", default="public"),
MAIL_SERVER=os.environ.get("MAIL_SERVER", default="smtp.nullhex.com"),
MAIL_SERVER=os.environ.get("MAIL_SERVER", default=""),
MAIL_PORT=os.environ.get("MAIL_PORT", default="465"),
MAIL_USE_TLS=os.environ.get("MAIL_USE_TLS", default="True").lower() in ['true', '1', 't', 'y', 'yes'],
MAIL_USERNAME=os.environ.get("MAIL_USERNAME", default="forest@nullhex.com"),
MAIL_USERNAME=os.environ.get("MAIL_USERNAME", default=""),
MAIL_PASSWORD=os.environ.get("MAIL_PASSWORD", default=""),
MAIL_DEFAULT_SENDER=os.environ.get("MAIL_DEFAULT_SENDER", default="forest@nullhex.com"),
MAIL_DEFAULT_SENDER=os.environ.get("MAIL_DEFAULT_SENDER", default="no-reply@capsul.org"),
ADMIN_EMAIL_ADDRESSES=os.environ.get("ADMIN_EMAIL_ADDRESSES", default="ops@cyberia.club"),
PROMETHEUS_URL=os.environ.get("PROMETHEUS_URL", default="https://prometheus.cyberia.club"),
@ -127,13 +130,18 @@ logging_dict_config({
stripe.api_key = app.config['STRIPE_SECRET_KEY']
stripe.api_version = app.config['STRIPE_API_VERSION']
app.config['FLASK_MAIL_INSTANCE'] = Mail(app)
if app.config['MAIL_SERVER'] != "":
app.config['FLASK_MAIL_INSTANCE'] = Mail(app)
else:
app.logger.warning("No MAIL_SERVER configured. capsul will simply print emails to stdout.")
app.config['FLASK_MAIL_INSTANCE'] = StdoutMockFlaskMail()
app.config['HTTP_CLIENT'] = MyHTTPClient(timeout_seconds=int(app.config['INTERNAL_HTTP_TIMEOUT_SECONDS']))
try:
app.config['BTCPAY_CLIENT'] = btcpay.Client(api_uri=app.config['BTCPAY_URL'], pem=app.config['BTCPAY_PRIVATE_KEY'])
except:
app.logger.warning("unable to create btcpay client: " + my_exec_info_message(sys.exc_info()))
app.logger.warning("unable to create btcpay client. Capsul will work fine except cryptocurrency payments will not work. The error was: " + my_exec_info_message(sys.exc_info()))
if app.config['HUB_MODE_ENABLED']:

3
capsulflask/auth.py

@ -64,12 +64,13 @@ def login():
current_app.config["FLASK_MAIL_INSTANCE"].send(
Message(
"Click This Link to Login to Capsul",
sender=current_app.config["MAIL_DEFAULT_SENDER"],
body=message,
recipients=[email]
)
)
return render_template("login-landing.html", email=email)
return render_template("login-landing.html", email=email, has_smtp=(current_app.config["MAIL_SERVER"] != ""))
for error in errors:
flash(error)

2
capsulflask/cli.py

@ -243,6 +243,7 @@ def notify_users_about_account_balance():
Message(
get_subject(pluralize_capsul),
body=get_body(current_app.config['BASE_URL'], pluralize_capsul),
sender=current_app.config["MAIL_DEFAULT_SENDER"],
recipients=[account['email']]
)
)
@ -288,6 +289,7 @@ def ensure_vms_and_db_are_synced():
current_app.config["FLASK_MAIL_INSTANCE"].send(
Message(
"Capsul Consistency Check Failed",
sender=current_app.config["MAIL_DEFAULT_SENDER"],
body="\n".join(errors),
recipients=email_addresses
)

6
capsulflask/templates/login-landing.html

@ -3,7 +3,11 @@
{% block title %}check your email{% endblock %}
{% block content %}
<div class="row full-margin">Check your email. A login link has been sent to {{ email }}</div>
{% if has_smtp %}
<div class="row full-margin">Check your email. A login link has been sent to {{ email }}</div>
{% else %}
<div class="row full-margin">No SMTP server configured. A login link has been printed to stdout.</div>
{% endif %}
{% endblock %}
{% block pagesource %}/templates/login-landing.html{% endblock %}
Loading…
Cancel
Save