segunda-feira, 27 de maio de 2019

FlaskBB - Python Anywhere

O FlaskBB é um fórum construído com Flask (um framework em Python). O tutorial simplificado cria um fórum rodando em localhost:5000 facilmente, principalmente porque se você falhar em criar um arquivo de configuração flaskbb.cfg, o comando run irá criar o servidor com as configurações padrão ao invés de falhar.

A coisa complica quando você tenta subir o fórum no PythonAnywhere (um site de hospedagem, assim como Heroku e outros).

A documentação de instalação mais extensa do FlaskBB inclui um mini tutorial enviado por usuários para instalar o FlaskBB no pythonanywhere:

Here’s what to do:

  • Sign up for a PythonAnywhere account at https://www.pythonanywhere.com/.
  • On the “Consoles” tab, start a Bash console and install/configure FlaskBB like this

git clone https://github.com/sh4nks/flaskbb.git
cd flaskbb
Before continuing the installation it is advised to create a virtualenv as is described in section Virtualenv Setup.
Finish the installation of FlaskBB by executing following commands:

pip3.5 install --user -r requirements.txt
pip3.5 install --user -e .
flaskbb makeconfig
flaskbb install

  • Click the PythonAnywhere logo to go back to the dashboard, then go to the “Web” tab, and click the “Add a new web app” button.
  • Just click “Next” on the first page.
  • On the next page, click “Flask”
  • On the next page, click “Python 3.5”
  • On the next page, just accept the default and click next
  • Wait while the website is created.
  • Click on the “Source code” link, and in the input that appears, replace the mysite at the end with flaskbb
  • Click on the “WSGI configuration file” filename, and wait for an editor to load.
  • Change the line that sets project_home to replace mysite with flaskbb again.
  • Change the line that says

from flask_app import app as application
to say

from flaskbb import create_app
application = create_app("/path/to/your/configuration/file")

  • Click the green “Save” button near the top right.
  • Go back to the “Web” tab.
  • Click the green “Reload…” button.
  • Click the link to visit the site – you’ll have a new FlaskBB install!

 Recomendo alguns cuidados para aqueles que são iniciantes como eu, pois sofri bastante para conseguir rodar:

  • Pode ser melhor prática, bonito, etc... mas NÃO utilizem um ambiente virtual, se você é iniciante como eu poderá ter problemas ao tentar rodar o servidor. No meu caso, em uma das vezes, as instalações não eram encontradas na subida do servidor, tive que instalar tudo novamente fora do ambiente virtual e agora tenho espaço desperdiçado no limitadíssimo (500MB) diretório fornecido (até descobrir se posso apagar a pasta .venv sem problemas);
  • Preste atenção no resultado do makeconfig, é possível que o arquivo flaskbb.cfg não tenha sido criado (ele deveria estar visível na pasta raiz). Isso pode influenciar no flaskbb install (usando flaskbb --config flaskbb.cfg install), em uma das vezes a instalação não encontrou o arquivo, o que resultou em um flaskbb.sqllite vazio, e consequentemente em falha ao subir o servidor;
  • Preste atenção também no arquivo de configuração WSGI, tenha certeza de que ele aponta para as pastas e arquivos corretos na estrutura do seu aplicativo.

Abaixo deixo exemplos de como deve estar um arquivo de configuração WSGI e FlaskBB (pode ser necessário incluir o flaskbb.cfg manualmente):

  • WSGI

import sys

# add your project directory to the sys.path
project_home = u'/home/yourname/flaskbb'
if project_home not in sys.path:
    sys.path = [project_home] + sys.path

# import flask app but need to call it "application" for WSGI to work
from flaskbb import create_app
application = create_app("/home/yourname/flaskbb/flaskbb.cfg")  # noqa 


  • FlaskBB


# Feel free to adjust it as needed.

import os

import datetime

from flaskbb.configs.default import DefaultConfig





# Flask Settings

# ------------------------------

# There is a whole bunch of more settings available here:

# http://flask.pocoo.org/docs/0.11/config/#builtin-configuration-values

DEBUG = False

TESTING = False



# Server Name - REQUIRED for Celery/Mailing

# The name and port number of the server.

# Required for subdomain support (e.g.: 'myapp.dev:5000') and

# URL generation without a request context but with an application context

# which we need in order to generate URLs (with the celery application)

# Note that localhost does not support subdomains so setting this to

# “localhost” does not help.

# Example for the FlaskBB forums: SERVER_NAME = "forums.flaskbb.org"

SERVER_NAME = "yourname.pythonanywhere.com"



# Prefer HTTPS over HTTP

PREFERRED_URL_SCHEME = "https"



# Don't send secure cookies over an unencrypted connection ()

SESSION_COOKIE_SECURE = True

# Don't make cookies available to JS (XSS) - browsers hide httpOnly cookies from JS

SESSION_COOKIE_HTTPONLY = True





# Database

# ------------------------------

# For PostgresSQL:

#SQLALCHEMY_DATABASE_URI = "postgresql://flaskbb@localhost:5432/flaskbb"

# For SQLite:

SQLALCHEMY_DATABASE_URI = "sqlite:////home/yourname/flaskbb/flaskbb.sqlite"



# This option will be removed as soon as Flask-SQLAlchemy removes it.

# At the moment it is just used to suppress the super annoying warning

SQLALCHEMY_TRACK_MODIFICATIONS = False

# This will print all SQL statements

SQLALCHEMY_ECHO = False





# Security - IMPORTANT

# ------------------------------

# This is the secret key that is used for session signing.

# You can generate a secure key with os.urandom(24)

SECRET_KEY = "4f173d40bb47af9463b9d03fdd6683b69ab5f223bf3cc958"



# You can generate the WTF_CSRF_SECRET_KEY the same way as you have

# generated the SECRET_KEY. If no WTF_CSRF_SECRET_KEY is provided, it will

# use the SECRET_KEY.

WTF_CSRF_ENABLED = True

WTF_CSRF_SECRET_KEY = "75e0569325b2e4545a7e6d45b282767303a77e6416fb963a"





# Auth

# ------------------------------

LOGIN_VIEW = "auth.login"

REAUTH_VIEW = "auth.reauth"

LOGIN_MESSAGE_CATEGORY = "info"

REFRESH_MESSAGE_CATEGORY = "info"



# The name of the cookie to store the “remember me” information in.

REMEMBER_COOKIE_NAME = "remember_token"

# The amount of time before the cookie expires, as a datetime.timedelta object.

# Default: 365 days (1 non-leap Gregorian year)

REMEMBER_COOKIE_DURATION = datetime.timedelta(days=365)

# If the “Remember Me” cookie should cross domains,

# set the domain value here (i.e. .example.com would allow the cookie

# to be used on all subdomains of example.com).

REMEMBER_COOKIE_DOMAIN = None

# Limits the “Remember Me” cookie to a certain path.

REMEMBER_COOKIE_PATH = "/"

# Restricts the “Remember Me” cookie’s scope to secure channels (typically HTTPS).

REMEMBER_COOKIE_SECURE = True

# Prevents the “Remember Me” cookie from being accessed by client-side scripts.

REMEMBER_COOKIE_HTTPONLY = True





# Full-Text-Search

# ------------------------------

# This will use the "whoosh_index" directory to store the search indexes

WHOOSHEE_DIR = os.path.join(DefaultConfig.basedir, "whoosh_index", DefaultConfig.py_version)

# How long should whooshee try to acquire write lock? (defaults to 2)

WHOOSHEE_WRITER_TIMEOUT = 2

# Minimum number of characters for the search (defaults to 3)

WHOOSHEE_MIN_STRING_LEN = 3





# Redis

# ------------------------------

# If redis is enabled, it can be used for:

#   - Sending non blocking emails via Celery (Task Queue)

#   - Caching

#   - Rate Limiting

REDIS_ENABLED = False

REDIS_URL = "redis://localhost:6379"

REDIS_DATABASE = 0





# Celery

# ------------------------------

CELERY_BROKER_URL = "redis://localhost:6379"

CELERY_RESULT_BACKEND = "redis://localhost:6379"





# Rate Limiting

# -------------------------------

# A full list with configuration values is available at the flask-limiter

# docs, but you actually just need those settings below.

# You can disabled the Rate Limiter here as well - it will overwrite

# the setting from the admin panel!

# RATELIMIT_ENABLED = True

# You can choose from:

#   memory:// (default)

#   redis://host:port

#   memcached://host:port

# Using the redis storage requires the installation of the redis package,

# which will be installed if you enable REDIS_ENABLE while memcached

# relies on the pymemcache package.

RATELIMIT_STORAGE_URL = "memory://"





# Caching

# ------------------------------

# For all available caching types, have a look at the Flask-Cache docs

# https://pythonhosted.org/Flask-Caching/#configuring-flask-caching

CACHE_TYPE = "simple"

CACHE_DEFAULT_TIMEOUT = 60





# Mail

# ------------------------------

# Google Mail Example

# https://support.google.com/mail/answer/7126229?hl=en

#MAIL_SERVER = "smtp.gmail.com"

#MAIL_PORT = 587

#MAIL_USE_TLS = True

#MAIL_USE_SSL = True

#MAIL_USERNAME = "your_username@gmail.com"

#MAIL_PASSWORD = "your_password"

#MAIL_DEFAULT_SENDER = ("Your Name", "your_username@gmail.com")



# Local SMTP Server

MAIL_SERVER = "smtp.gmail.com"

MAIL_PORT = 465

MAIL_USE_SSL = True

MAIL_USE_TLS = True

MAIL_USERNAME = "yourname@gmail.com"

MAIL_PASSWORD = "xyz#321"

MAIL_DEFAULT_SENDER = ("Your Name Mailer", "yourname@gmail.com")

# Where to logger should send the emails to

ADMINS = ["yourname@gmail.com"]





# Logging Settings

# ------------------------------

# This config section will deal with the logging settings

# for FlaskBB, adjust as needed.



# Logging Config Path

# see https://docs.python.org/library/logging.config.html#logging.config.fileConfig

# for more details. Should either be None or a path to a file

# If this is set to a path, consider setting USE_DEFAULT_LOGGING to False

# otherwise there may be interactions between the log configuration file

# and the default logging setting.

#

# If set to a file path, this should be an absolute file path



LOG_CONF_FILE = None





# Path to store the INFO and ERROR logs

# If None this defaults to flaskbb/logs

#

# If set to a file path, this should be an absolute path

LOG_PATH = os.path.join(DefaultConfig.basedir, 'logs')



# The default logging configuration that will be used when

# USE_DEFAULT_LOGGING is set to True

LOG_DEFAULT_CONF = {

    'version': 1,

    'disable_existing_loggers': False,



    'formatters': {

        'standard': {

            'format': '%(asctime)s %(levelname)-7s %(name)-25s %(message)s'

        },

        'advanced': {

            'format': '%(asctime)s %(levelname)s: %(message)s [in %(pathname)s:%(lineno)d]'

        }

    },



    'handlers': {

        'console': {

            'level': 'NOTSET',

            'formatter': 'standard',

            'class': 'logging.StreamHandler',

        },

        'flaskbb': {

            'level': 'DEBUG',

            'formatter': 'standard',

            'class': 'logging.handlers.RotatingFileHandler',

            'filename': os.path.join(LOG_PATH, 'flaskbb.log'),

            'mode': 'a',

            'maxBytes': 10485760,  # 10MB

            'backupCount': 5,

        },



        'infolog': {

            'level': 'INFO',

            'formatter': 'standard',

            'class': 'logging.handlers.RotatingFileHandler',

            'filename': os.path.join(LOG_PATH, 'info.log'),

            'mode': 'a',

            'maxBytes': 10485760,  # 10MB

            'backupCount': 5,

        },

        'errorlog': {

            'level': 'ERROR',

            'formatter': 'standard',

            'class': 'logging.handlers.RotatingFileHandler',

            'filename': os.path.join(LOG_PATH, 'error.log'),

            'mode': 'a',

            'maxBytes': 10485760,  # 10MB

            'backupCount': 5,

        }

    },



    'loggers': {

        'flask.app': {

            'handlers': ['infolog', 'errorlog'],

            'level': 'INFO',

            'propagate': True

        },

        'flaskbb': {

            'handlers': ['console', 'flaskbb'],

            'level': 'WARNING',

            'propagate': True

        },

    }

}



# When set to True this will enable the default

# FlaskBB logging configuration which uses the settings

# below to determine logging

USE_DEFAULT_LOGGING = True



# If SEND_LOGS is set to True, the admins (see the mail configuration) will

# recieve the error logs per email.

SEND_LOGS = False





# FlaskBB Settings

# ------------------------------ #

# URL Prefixes

FORUM_URL_PREFIX = ""

USER_URL_PREFIX = "/user"

MESSAGE_URL_PREFIX = "/message"

AUTH_URL_PREFIX = "/auth"

ADMIN_URL_PREFIX = "/admin"

# Remove dead plugins - useful if you want to migrate your instance

# somewhere else and forgot to reinstall the plugins.

# If set to `False` it will NOT remove plugins that are NOT installed on

# the filesystem (virtualenv, site-packages).

REMOVE_DEAD_PLUGINS = False



# determines the warning level for FlaskBB Deprecations

DEPRECATION_LEVEL = "default"


Preste atenção no segundo trecho, na variável SERVER_NAME, ela deve apontar para seu domínio no pythonanywhere.

Use https://yourname.pythonanywhere.com.error.log para visualizar eventuais mensagens de erro e identificar o que pode ter dado errado durante a instalação/configuração e boa sorte.

P.S.: Ao tentar fazer login ou registrar uma conta depois de clicar no link sugerido pelo pythonanywhere eu tive erros de CSRF. O link fornecido utiliza http, se você trocar por https o erro não ocorre.