fix defaults for running locally and make email server not required.
This commit is contained in:
parent
3cb6992359
commit
bdabd61057
36
README.md
36
README.md
@ -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)
|
||||||
|
|
||||||
|
@ -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']:
|
||||||
|
@ -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)
|
||||||
|
@ -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
|
||||||
)
|
)
|
||||||
|
@ -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 %}
|
Loading…
Reference in New Issue
Block a user