Merry Christmas! I AM READY I love you all! new file: .gitignore new file: MANIFEST.in new file: Makefile new file: README.rst new file: development.ini new file: index.html new file: index2.html new file: journal.rst new file: readme-postgres-notes.rst new file: readme-themes.rst new file: remarkbox/__init__.py new file: remarkbox/lib/__init__.py new file: remarkbox/lib/mail.py new file: remarkbox/lib/mail_messages.py new file: remarkbox/lib/notify.py new file: remarkbox/lib/render.py new file: remarkbox/lib/svgtar/__init__.py new file: remarkbox/lib/svgtar/svg.py new file: remarkbox/models/__init__.py new file: remarkbox/models/event.py new file: remarkbox/models/meta.py new file: remarkbox/models/namespace.py new file: remarkbox/models/namespace_request.py new file: remarkbox/models/namespace_user.py new file: remarkbox/models/node.py new file: remarkbox/models/node_cache.py new file: remarkbox/models/notification.py new file: remarkbox/models/oauth.py new file: remarkbox/models/pay_what_you_can.py new file: remarkbox/models/uri.py new file: remarkbox/models/user.py new file: remarkbox/models/vote.py new file: remarkbox/models/watcher.py new file: remarkbox/routes.py new file: remarkbox/scripts/__init__.py new file: remarkbox/scripts/alembic/README new file: remarkbox/scripts/alembic/env.py new file: remarkbox/scripts/alembic/script.py.mako new file: remarkbox/scripts/alembic/versions/00211ed642cc_add_ip_address_column_to_rb_node.py new file: remarkbox/scripts/alembic/versions/0208c10ea67f_create_new_node_cache_table.py new file: remarkbox/scripts/alembic/versions/04e52337756e_autogenerated_indicies.py new file: remarkbox/scripts/alembic/versions/051f8b810f26_namespace_ignore_query_string.py new file: remarkbox/scripts/alembic/versions/1040ee4836af_namespace_description.py new file: remarkbox/scripts/alembic/versions/184a349cd589_uri_accessed_timestamp.py new file: remarkbox/scripts/alembic/versions/256468780798_root_nodes_to_namespace_.py new file: remarkbox/scripts/alembic/versions/2e00b92495e4_node_disabled_timestamp.py new file: remarkbox/scripts/alembic/versions/3ee195d142fb_add_subscription_type_to_namespace.py new file: remarkbox/scripts/alembic/versions/40ded1163f95_add_user_surrogate_columns.py new file: remarkbox/scripts/alembic/versions/43c1e5a99d4e_new_namespace_column_3.py new file: remarkbox/scripts/alembic/versions/4aeda8e797ab_new_namespace_column_for_stylesheet_uris.py new file: remarkbox/scripts/alembic/versions/503a2cef2378_root_stats.py new file: remarkbox/scripts/alembic/versions/591800942adf_node_data_html_column.py new file: remarkbox/scripts/alembic/versions/59592cf325fb_stylesheet_timestamp.py new file: remarkbox/scripts/alembic/versions/5a5d0b68db78_add_root_id_field.py new file: remarkbox/scripts/alembic/versions/6a440d3921d2_added_email_id_column_to_user_table.py new file: remarkbox/scripts/alembic/versions/6bbc92ccc112_add_changed_column_to_node_table.py new file: remarkbox/scripts/alembic/versions/6db39621f46c_namespace_group_conversations.py new file: remarkbox/scripts/alembic/versions/6fc1d0cf350c_notification_columns_to_rb_user_table.py new file: remarkbox/scripts/alembic/versions/76deff88cfd6_create_graph_depth_column_on_node_model.py new file: remarkbox/scripts/alembic/versions/771ef7c868de_added_created_timestamp_column_to_.py new file: remarkbox/scripts/alembic/versions/7a3a4755b4a8_add_hide_unless_approved_column.py new file: remarkbox/scripts/alembic/versions/87fbd2b4e06e_namespace_theme_embed_column.py new file: remarkbox/scripts/alembic/versions/953d42406dbb_namespace_public_column.py new file: remarkbox/scripts/alembic/versions/98a90d2add21_namespace_model.py new file: remarkbox/scripts/alembic/versions/98ced5f6ff36_stripe_id_for_user.py new file: remarkbox/scripts/alembic/versions/a26302bcfa25_add_created_timestamp_column_to_oauth_.py new file: remarkbox/scripts/alembic/versions/a38c12eeff2d_locked_rb_node.py new file: remarkbox/scripts/alembic/versions/a738d6859f18_new_namespace_columns_2.py new file: remarkbox/scripts/alembic/versions/aa2dfb4decda_hide_powered_by_column.py new file: remarkbox/scripts/alembic/versions/b132ec968f0c_pay_what_you_can_table.py new file: remarkbox/scripts/alembic/versions/ba8e83a3b8fd_namespace_stylesheet_embed_column.py new file: remarkbox/scripts/alembic/versions/c9793937e756_make_all_verified_namespace_request_.py new file: remarkbox/scripts/alembic/versions/c97ddfcbc406_approve_column.py new file: remarkbox/scripts/alembic/versions/cbdf3cd4ccba_avatar_size_in_namespace.py new file: remarkbox/scripts/alembic/versions/d1a0ab4f617f_add_has_uri_to_node.py new file: remarkbox/scripts/alembic/versions/f5f88293428a_add_mathjax_column_to_rb_namespace.py new file: remarkbox/scripts/alembic/versions/f7b42b2024fb_namespace_reverse_node_order.py new file: remarkbox/scripts/alembic/versions/fa8402aa1a00_add_link_protection_column_to_namespace.py new file: remarkbox/scripts/dump_sqlite3_to_csv.sh new file: remarkbox/scripts/init_db.py new file: remarkbox/scripts/invalidate_node_cache.py new file: remarkbox/scripts/json_import.py new file: remarkbox/scripts/load_csv_into_postgres.sh new file: remarkbox/scripts/merge_dupes.py new file: remarkbox/scripts/modify_namespace.py new file: remarkbox/scripts/modify_node.py new file: remarkbox/scripts/modify_uris.py new file: remarkbox/scripts/modify_user.py new file: remarkbox/scripts/recompute_node_depths.py new file: remarkbox/scripts/safe_approve_all_nodes.py new file: remarkbox/scripts/send_node_digest_notifications.py new file: remarkbox/static/css/common.css new file: remarkbox/static/css/embed.css new file: remarkbox/static/css/pygments.css new file: remarkbox/static/favicon.ico new file: remarkbox/static/img/remarkbox-logo.png new file: remarkbox/static/img/remarkbox-minified.png new file: remarkbox/static/js/custom.js new file: remarkbox/static/js/iframe-resizer/ie8.polyfils.map new file: remarkbox/static/js/iframe-resizer/ie8.polyfils.min.js new file: remarkbox/static/js/iframe-resizer/iframeResizer.contentWindow.js new file: remarkbox/static/js/iframe-resizer/iframeResizer.contentWindow.map new file: remarkbox/static/js/iframe-resizer/iframeResizer.contentWindow.min.js new file: remarkbox/static/js/iframe-resizer/iframeResizer.js new file: remarkbox/static/js/iframe-resizer/iframeResizer.map new file: remarkbox/static/js/iframe-resizer/iframeResizer.min.js new file: remarkbox/static/js/iframe-resizer/index.js new file: remarkbox/static/js/iframe-resizer/readme.rst new file: remarkbox/static/js/jquery-2.1.3.min.js new file: remarkbox/static/theme/readme.rst new file: remarkbox/templates/base.j2 new file: remarkbox/templates/billing.j2 new file: remarkbox/templates/dynamic-remarkbox.css.j2 new file: remarkbox/templates/edit-node.j2 new file: remarkbox/templates/embed-iframe.txt.j2 new file: remarkbox/templates/home.j2 new file: remarkbox/templates/join-or-log-in.j2 new file: remarkbox/templates/list-namespace-owners.j2 new file: remarkbox/templates/list-namespace-requests.j2 new file: remarkbox/templates/list-nodes.j2 new file: remarkbox/templates/list-notifications.j2 new file: remarkbox/templates/mail_digest_html.j2 new file: remarkbox/templates/mail_digest_text.j2 new file: remarkbox/templates/mail_immediate_html.j2 new file: remarkbox/templates/mail_immediate_text.j2 new file: remarkbox/templates/mail_snippet_html.j2 new file: remarkbox/templates/mail_snippet_text.j2 new file: remarkbox/templates/namespace-settings.j2 new file: remarkbox/templates/new.j2 new file: remarkbox/templates/rss.xml.j2 new file: remarkbox/templates/setup-namespace.j2 new file: remarkbox/templates/show-count.j2 new file: remarkbox/templates/show-node.j2 new file: remarkbox/templates/show-node2.j2 new file: remarkbox/templates/sitemap.xml.j2 new file: remarkbox/templates/snippets/add-to-slack.j2 new file: remarkbox/templates/snippets/create.j2 new file: remarkbox/templates/snippets/csrf.j2 new file: remarkbox/templates/snippets/email.j2 new file: remarkbox/templates/snippets/flash-alerts.j2 new file: remarkbox/templates/snippets/forms.j2 new file: remarkbox/templates/snippets/google-analytics.j2 new file: remarkbox/templates/snippets/javascript-includes.j2 new file: remarkbox/templates/snippets/owner-key-comment.j2 new file: remarkbox/templates/snippets/phone-menu.j2 new file: remarkbox/templates/snippets/powered-by.j2 new file: remarkbox/templates/snippets/search.j2 new file: remarkbox/templates/snippets/snippets.j2 new file: remarkbox/templates/snippets/stripe.j2 new file: remarkbox/templates/snippets/stylesheet-includes.j2 new file: remarkbox/templates/snippets/submit.j2 new file: remarkbox/templates/update-card.j2 new file: remarkbox/templates/user-settings.j2 new file: remarkbox/templates/user-watching.j2 new file: remarkbox/tests/test_models.py new file: remarkbox/tests/test_render.py new file: remarkbox/tests/test_views.py new file: remarkbox/views/__init__.py new file: remarkbox/views/authenticated/__init__.py new file: remarkbox/views/authenticated/authenticated.py new file: remarkbox/views/authenticated/lock.py new file: remarkbox/views/authenticated/notifications.py new file: remarkbox/views/authenticated/oauth.py new file: remarkbox/views/authenticated/stripe.py new file: remarkbox/views/authenticated/topsecret.py new file: remarkbox/views/authenticated/watch.py new file: remarkbox/views/authentication.py new file: remarkbox/views/list_nodes.py new file: remarkbox/views/misc.py new file: remarkbox/views/modify_node.py new file: remarkbox/views/new_thread.py new file: remarkbox/views/reply_node.py new file: requirements-dev.txt new file: requirements-prod.txt new file: requirements-test.txt new file: requirements.py3.txt new file: requirements.txt new file: setup.py new file: test.ini
198 lines
5.1 KiB
ReStructuredText
198 lines
5.1 KiB
ReStructuredText
Remarkbox
|
|
#########
|
|
|
|
What is RemarkBox?:
|
|
A stand alone question and answer site (forum) or an embedded comments or product reviews service.
|
|
Works anywhere that supports HTML.
|
|
|
|
Original Developer:
|
|
Russell Ballestrini (https://russell.ballestrini.net)
|
|
|
|
Project Goals
|
|
=============
|
|
|
|
Note:
|
|
These goals are not in priority order.
|
|
|
|
#. To be a suitable for:
|
|
|
|
* question and answer sites (StackOverflow)
|
|
* embedded comment system for static sites
|
|
* forums
|
|
* product review sections of e-commerce sites
|
|
|
|
|
|
|
|
|
#. To choose popular libraries instead of proper libraries, for example:
|
|
|
|
* Github over Bitbucket (seriously considering GitLab)
|
|
* Git over HG Mercurial
|
|
* Jinja2 templates over Mako templates
|
|
* Markdown over ReStructuredText
|
|
* etc
|
|
|
|
|
|
|
|
|
Basically I have been burned too many times trying to pick the proper
|
|
library or tool for the job, so this time around, I will make effort
|
|
to choose solutions that the majority uses.
|
|
|
|
#. To be popular
|
|
|
|
#. To be safe from spammers
|
|
|
|
#. To be easy to manage and clean up spam if it happens
|
|
|
|
#. To be passwordless. Registration, verification and authentication happen via one-time-password links sent via email.
|
|
|
|
#. To scale horizontally
|
|
|
|
#. To be multitenant
|
|
|
|
#. To have low friction for new users to join (posters and commenters)
|
|
|
|
#. To be engaging for users (posters and commenters)
|
|
|
|
#. To be search engine optimized
|
|
|
|
#. To have great test coverage
|
|
|
|
|
|
Local Installation
|
|
==================
|
|
|
|
We utilize a ``Makefile`` to capture targets for building a local Remarkbox environment. Please make sure you have ``make`` installed.
|
|
|
|
#. ``make dev``
|
|
#. ``make test``
|
|
|
|
|
|
Functional testing environment
|
|
-------------------------------
|
|
|
|
To setup a "functional testing" environment on your personal workstation, open three terminal shells.
|
|
|
|
In the first shell, run a copy of remarkbox using:
|
|
|
|
.. code-block:: bash
|
|
|
|
make serve
|
|
|
|
In the second shell, run a "mock" simple HTTP webserver to serve index.html:
|
|
|
|
.. code-block:: bash
|
|
|
|
make http
|
|
|
|
In the third shell, run a "mock" SMTP server to catch log in emails:
|
|
|
|
.. code-block:: bash
|
|
|
|
make smtp
|
|
|
|
Now browse to http://127.0.0.1:8000 and index.html will load and will have an embeded copy of Remarkbox which running on localhost.
|
|
If you attempt to log in, your third shell will capture the email and you can copy / paste the verification link to log in!
|
|
|
|
|
|
|
|
SQL Migrations
|
|
===============
|
|
|
|
If your deployment is brand new, you don't need to run any migrations.
|
|
You should however run this to stamp the database as ready:
|
|
|
|
.. code-block:: bash
|
|
|
|
alembic -c development.ini stamp head
|
|
|
|
Otherwise, it should be safe to run this at anytime to catch your database up:
|
|
|
|
.. code-block:: bash
|
|
|
|
alembic -c development.ini upgrade head
|
|
|
|
To look at the current revision and the history run these:
|
|
|
|
.. code-block:: bash
|
|
|
|
alembic -c development.ini history
|
|
alembic -c development.ini current
|
|
|
|
If you ever want to cut a new migration script, you can run this:
|
|
|
|
.. code-block:: bash
|
|
|
|
alembic -c development.ini revision -m "Added email_id column to User table."
|
|
|
|
Then you can edit / modify the generated ``.py`` file with your changes.
|
|
|
|
You can also autogenerate a new migration script using `--autogenerate`.
|
|
Alembic will prepare a migration script by comparing the state of the
|
|
database with the state of the model:
|
|
|
|
.. code-block:: bash
|
|
|
|
alembic -c development.ini revision --autogenerate -m "autogenerated indicies."
|
|
|
|
You should review the recommended migration script before `upgrade`.
|
|
|
|
|
|
Cleaning the homepage
|
|
========================
|
|
|
|
Sometimes (all the times) it's nice to clear all the test comments from the
|
|
the homepage of our marketing site. Use this query.
|
|
|
|
.. code-block:: sql
|
|
|
|
sqlite> UPDATE rb_uri SET data = "https://www.remarkbox.com/?cleaned=2018-09-28" WHERE data = "https://www.remarkbox.com/";
|
|
|
|
sqlite> SELECT * FROM rb_uri WHERE data LIKE "%https://www.remarkbox.com/?cleaned%";
|
|
1e631dd85d104555b41b300961d2f909|82008b2b178f4daab64c35ab5c5f9b56|https://www.remarkbox.com/?cleaned=2017-11-01
|
|
6b2a4772679611e8ad95040140774501|6b2a42ae679611e8ad95040140774501|https://www.remarkbox.com/?cleaned=2018-09-28
|
|
|
|
|
|
|
|
Looking up paying customers
|
|
==============================
|
|
|
|
.. code-block:: sql
|
|
|
|
|
|
SELECT * FROM rb_pay_what_you_can
|
|
INNER JOIN rb_user ON rb_user.id = rb_pay_what_you_can.user_id
|
|
WHERE amount > 0 and rb_user.stripe_id is not null;
|
|
|
|
|
|
|
|
Python Pyramid Shell
|
|
==========================
|
|
|
|
If you want to use an interactive Python interpreter to interact with the Remarkbox app/models and database:
|
|
|
|
.. code-block:: bash
|
|
|
|
pshell development.ini
|
|
|
|
Here is a full `pshell` script to modify every `Node` who has a `Uri`:
|
|
|
|
.. code-block:: python
|
|
|
|
# begin the database transaction.
|
|
request.tm.begin()
|
|
|
|
# get all Uri objects.
|
|
uris = m.uri.get_all_uris(request.dbsession)
|
|
|
|
# interate over all Uri objects.
|
|
for uri in uris:
|
|
# modify the Uri's related Node.
|
|
uri.node.has_uri = True
|
|
# add the related Node object to the sqlalchemy session.
|
|
request.dbsession.add(uri.node)
|
|
|
|
# flush / commit all changes stored the the sqlachemy session.
|
|
request.dbsession.flush()
|
|
|
|
# commit/close the database transaction to really make changes.
|
|
request.tm.commit()
|