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

This commit is contained in:
forest 2021-07-07 13:47:21 -05:00
parent 3cb6992359
commit bdabd61057
5 changed files with 45 additions and 26 deletions

View File

@ -31,19 +31,6 @@ 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 docker run --rm -it -e POSTGRES_PASSWORD=dev -p 5432:5432 postgres
``` ```
Create a `.env` file to set up the application configuration:
```
nano .env
```
Enter your SMTP credentials like this:
```
MAIL_USERNAME=forest@nullhex.com
MAIL_DEFAULT_SENDER=forest@nullhex.com
MAIL_PASSWORD=**************
```
Run the app Run the app
``` ```
@ -56,6 +43,23 @@ Run the app in gunicorn:
pipenv run gunicorn --bind 127.0.0.1:5000 -k gevent --worker-connections 1000 app:app pipenv run gunicorn --bind 127.0.0.1:5000 -k gevent --worker-connections 1000 app:app
``` ```
## configuration:
Create a `.env` file to set up the application configuration:
```
nano .env
```
You can enter any environment variables referenced in `__init__.py` to this file.
For example you may enter your SMTP credentials like this:
```
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) ## how to view the logs on the database server (legion.cyberia.club)
`sudo -u postgres pg_dump capsul-flask | gzip -9 > capsul-backup-2021-02-15.gz` `sudo -u postgres pg_dump capsul-flask | gzip -9 > capsul-backup-2021-02-15.gz`
@ -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), 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. 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 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 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) ![](readme/hub-and-spoke2.png)

View File

@ -10,7 +10,7 @@ import sys
import stripe import stripe
from dotenv import load_dotenv, find_dotenv from dotenv import load_dotenv, find_dotenv
from flask import Flask from flask import Flask
from flask_mail import Mail from flask_mail import Mail, Message
from flask import render_template from flask import render_template
from flask import url_for from flask import url_for
from flask import current_app 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.btcpay import client as btcpay
from capsulflask.http_client import MyHTTPClient 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()) load_dotenv(find_dotenv())
@ -31,10 +34,10 @@ app.config.from_mapping(
BASE_URL=os.environ.get("BASE_URL", default="http://localhost:5000"), BASE_URL=os.environ.get("BASE_URL", default="http://localhost:5000"),
SECRET_KEY=os.environ.get("SECRET_KEY", default="dev"), 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'], 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"), 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"), SPOKE_MODEL=os.environ.get("SPOKE_MODEL", default="mock"),
LOG_LEVEL=os.environ.get("LOG_LEVEL", default="INFO"), LOG_LEVEL=os.environ.get("LOG_LEVEL", default="INFO"),
SPOKE_HOST_ID=os.environ.get("SPOKE_HOST_ID", default="default"), 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"), 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_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_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_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"), 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"), 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_key = app.config['STRIPE_SECRET_KEY']
stripe.api_version = app.config['STRIPE_API_VERSION'] 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'])) app.config['HTTP_CLIENT'] = MyHTTPClient(timeout_seconds=int(app.config['INTERNAL_HTTP_TIMEOUT_SECONDS']))
try: try:
app.config['BTCPAY_CLIENT'] = btcpay.Client(api_uri=app.config['BTCPAY_URL'], pem=app.config['BTCPAY_PRIVATE_KEY']) app.config['BTCPAY_CLIENT'] = btcpay.Client(api_uri=app.config['BTCPAY_URL'], pem=app.config['BTCPAY_PRIVATE_KEY'])
except: 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']: if app.config['HUB_MODE_ENABLED']:

View File

@ -64,12 +64,13 @@ def login():
current_app.config["FLASK_MAIL_INSTANCE"].send( current_app.config["FLASK_MAIL_INSTANCE"].send(
Message( Message(
"Click This Link to Login to Capsul", "Click This Link to Login to Capsul",
sender=current_app.config["MAIL_DEFAULT_SENDER"],
body=message, body=message,
recipients=[email] 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: for error in errors:
flash(error) flash(error)

View File

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

View File

@ -3,7 +3,11 @@
{% block title %}check your email{% endblock %} {% block title %}check your email{% endblock %}
{% block content %} {% block content %}
{% if has_smtp %}
<div class="row full-margin">Check your email. A login link has been sent to {{ email }}</div> <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 %} {% endblock %}
{% block pagesource %}/templates/login-landing.html{% endblock %} {% block pagesource %}/templates/login-landing.html{% endblock %}