Skip to content

Commit

Permalink
Merge branch 'develop'
Browse files Browse the repository at this point in the history
  • Loading branch information
xeroc committed Aug 19, 2019
2 parents 944a194 + 7e561b4 commit 5078612
Show file tree
Hide file tree
Showing 20 changed files with 505 additions and 65 deletions.
24 changes: 24 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Read up on pre-commit
# https://ljvmiranda921.github.io/notebook/2018/06/21/precommits-using-black-and-flake8/

repos:

- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v2.0.0
hooks:
- id: trailing-whitespace
- id: check-docstring-first
- id: check-executables-have-shebangs
- id: check-json
- id: check-yaml
- id: end-of-file-fixer
- id: fix-encoding-pragma
- id: no-commit-to-branch
branch: master
- id: flake8

- repo: https://github.com/ambv/black
rev: 18.9b0
hooks:
- id: black
language_version: python3
28 changes: 28 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1 +1,29 @@
# Flask-Beet Extension

[![build status](https://secure.travis-ci.org/blockchainprojects/flask_beet.png?branch=master)](https://travis-ci.org/#!/blockchainprojects/flask_beet)

Flask-beet is a Flask extension for allow login (flask-security/flask-login)
via signed messages and the [Beet app](http://get-beet.io).

The login requires a unique string to be signed and submitted. The signature is
created with the memo key of an account on the BitShares Blockchain,

## Installation

Install the extension with one of the following commands:

$ pip install flask_beet

## Usage

Using SeaSurf is fairly straightforward. Begin by importing the extension and
then passing your application object back to the extension, like this:

from flask import Flask
from flask_beet import Beet
app = Flask(__name__)
beet = Beet(app)

## Documentation

The Sphinx-compiled documentation is available here: [flask-beet.rtfd.io](http://flask-beet.rtfd.io/)
7 changes: 6 additions & 1 deletion docs/conf.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# -*- coding: utf-8 -*-
# Configuration file for the Sphinx documentation builder.
#
# This file only contains a selection of the most common options. For a full
Expand Down Expand Up @@ -44,9 +45,13 @@
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
#
html_theme = "alabaster"
# html_theme = "alabaster"
html_theme = "flask"
html_theme_options = {"github_fork": "blockchainprojects/flask_beet"}

# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ["_static"]

master_doc = "index"
1 change: 1 addition & 0 deletions docs/modules.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ flask_beet
:maxdepth: 6

flask_beet
tests
25 changes: 25 additions & 0 deletions docs/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
bitshares

# Flask
Flask
Flask-Login
Flask-Security
Flask-Session

# Tooling
SQLAlchemy
WTForms
Werkzeug
uuid
blinker

# tests
pytest
pytest-mock
coverage
mock
flask-testing
flask-sqlalchemy

# template
Flask-Sphinx-Themes
17 changes: 17 additions & 0 deletions docs/tests.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
tests package
=============

Submodules
----------

.. toctree::

tests.test_beet

Module contents
---------------

.. automodule:: tests
:members:
:undoc-members:
:show-inheritance:
7 changes: 7 additions & 0 deletions docs/tests.test_beet.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
tests.test\_beet module
=======================

.. automodule:: tests.test_beet
:members:
:undoc-members:
:show-inheritance:
3 changes: 3 additions & 0 deletions flask_beet/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# -*- coding: utf-8 -*-
from pprint import pprint
from flask import current_app, _app_ctx_stack, session
from sqlalchemy import Column, String
Expand All @@ -14,7 +15,9 @@

#: Default configuration
_default_config = {
"APP_NAME": "Flask-Beet",
"LOGIN_ENDOINT": "/login/beet",
"POST_LOGIN_VIEW": "/",
"ONBOARDING_VIEW": "/register",
"INVALID_PAYLOAD_MESSAGE": "Invalid payload!",
"UNIQUE_MESSAGE_GENERATOR": unique_request_id,
Expand Down
File renamed without changes
41 changes: 41 additions & 0 deletions flask_beet/static/js/beet-js.js

Large diffs are not rendered by default.

24 changes: 24 additions & 0 deletions flask_beet/templates/_messages.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{%- with messages = get_flashed_messages(with_categories=true) -%}
{% if messages %}
{% for category, message in messages %}
{% if category == "error" %}
<div class="ui icon error message">
<i class="warning icon"></i>
<div class="content">
<div class="header">
An error occured!
</div>
{% else %}
<div class="ui icon info message">
<i class="info icon"></i>
<div class="content">
<div class="header">
Notice
</div>
{% endif %}
{{ message }}
</div>
</div>
{% endfor %}
{% endif %}
{%- endwith %}
52 changes: 52 additions & 0 deletions flask_beet/templates/beet/login-form.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<script type="text/javascript" src="{{url_for('.beet_js')}}"></script>
<script type="text/javascript">
function connectBeet() {
beet.get("{{app.config.get('BEET_APP_NAME')}}", "BTS").then(beet => {
var payload = "{{signed_message_payload}}";
beet.BTS.signMessage(payload).then(res => {
document.getElementById("signedMessage").value = JSON.stringify(res);
console.log(document.getElementById("signedMessage").value)
document.getElementById("beetLogin").submit();
}).catch((err) => {
console.error(err);
});
}).catch((err) => {
console.error(err);
});
}
</script>

<form class="ui form" id="beetLogin" method="POST">
{{ loginForm.csrf_token }}
<button class="ui basic button" value="Beet" onclick="connectBeet()" type="button">
<h2 class="ui header"><img class="image icon" src="{{url_for('.beet_logo')}}"/>
<div class="content">Login
<div class="sub header">with Beet</div>
</div>
</h2>
</button>
<div class="ui accordion">
<div class="title"><i class="dropdown icon"></i>I don't have Beet installed!</div>
<div class="{% if loginForm.message.errors %}active {% endif %}content">
<p>Please sign the following message</p>
<p class="text centered ui label">{{signed_message_payload}}</p>
<div class="field {% if loginForm.message.errors %} error {% endif %}">
<label>Signed Messaged</label>
<div class="ui input">
{{ loginForm.message()|safe }}
</div>
{% if loginForm.message.errors %}
<div class="ui red message">
<div class="header">Error</div>
<div class="ui list">
{% for error in loginForm.message.errors %}
<div class="item">{{error}}</div>
{% endfor %}
</div>
</div>
{% endif %}
</div>
{{ loginForm.submit()|safe }}
</div>
</div>
</form>
56 changes: 1 addition & 55 deletions flask_beet/templates/beet/login.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,59 +2,5 @@

{% block content %}
{% include "_messages.html" %}
<form class="ui form" id="beetLogin" method="POST">
{{ loginForm.csrf_token }}
<button class="ui basic button" value="Beet" onclick="connectBeet()" type="button">
<h2 class="ui header"><img class="image icon" src="{{url_for('.beet_logo')}}"/>
<div class="content">Login
<div class="sub header">with Beet</div>
</div>
</h2>
</button>
<div class="ui accordion">
<div class="title"><i class="dropdown icon"></i>I don't have Beet installed!</div>
<div class="{% if loginForm.message.errors %}active {% endif %}content">
<p>Please sign the following message</p>
<p class="text centered ui label">{{signed_message_payload}}</p>
<div class="field {% if loginForm.message.errors %} error {% endif %}">
<label>Signed Messaged</label>
<div class="ui input">
{{ loginForm.message()|safe }}
</div>
{% if loginForm.message.errors %}
<div class="ui red message">
<div class="header">Error</div>
<div class="ui list">
{% for error in loginForm.message.errors %}
<div class="item">{{error}}</div>
{% endfor %}
</div>
</div>
{% endif %}
</div>
{{ loginForm.submit()|safe }}
</div>
</div>
</form>

<script type="javascript">

function connectBeet() {
beet.get("workers.bitshares.foundation", "BTS").then(beet => {
var payload = "{{signed_message_payload}}";
beet.BTS.signMessage(payload).then(res => {

document.getElementById("signedMessage").value = JSON.stringify(res);
console.log(document.getElementById("signedMessage").value)
document.getElementById("beetLogin").submit();
}).catch((err) => {
console.error(err);
});
}).catch((err) => {
console.error(err);
});
}

</script>

{% include "beet/login-form.html" %}
{% endblock %}
2 changes: 2 additions & 0 deletions flask_beet/templates/layout.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
{% block content -%}
{%- endblock content %}
28 changes: 19 additions & 9 deletions flask_beet/views.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# -*- coding: utf-8 -*-
import os
from flask import (
Blueprint,
Expand All @@ -10,7 +11,7 @@
render_template,
send_file,
)
from flask_security import url_for_security, login_user
from flask_security import login_user
from werkzeug.local import LocalProxy

from . import forms, signals
Expand All @@ -31,11 +32,12 @@ def login():
"""
loginForm = forms.SignedMessageLoginForm()
if request.method == "POST" and loginForm.validate_on_submit():
if (
loginForm.message.signedMessage.plain_message
!= session[app.config.get("BEET_UNIQUE_MESSAGE_SESSION_KEY")]
if loginForm.message.signedMessage.plain_message != session.get(
app.config.get("BEET_UNIQUE_MESSAGE_SESSION_KEY")
):
flash(app.config.get("BEET_INVALID_PAYLOAD_MESSAGE"), "error")
flash(
app.config.get("BEET_INVALID_PAYLOAD_MESSAGE", "ERRORORORORO"), "error"
)
return redirect(url_for(".login"))

account_name = loginForm.message.signedMessage.signed_by_name
Expand All @@ -46,27 +48,35 @@ def login():
app._get_current_object(), user=user, message=loginForm.message.data
)
return redirect(
request.args.get("next") or app.config.get("SECURITY_POST_LOGIN_VIEW")
request.args.get("next") or app.config.get("BEET_POST_LOGIN_VIEW")
)
else:
session[
app.config.get("BEET_ONBOARDING_MESSAGE_KEY")
] = loginForm.message.data
session[app.config.get("BEET_ONBOARDING_ACCOUNT_NAME_KEY")] = account_name
session["_next"] = request.args.get("next") or app.config.get(
"SECURITY_POST_LOGIN_VIEW"
"BEET_POST_LOGIN_VIEW"
)
signals.beet_onboarding.send(
app._get_current_object(), user=user, message=loginForm.message.data
)
return redirect(app.config.get("BEET_ONBOARDING_VIEW"))

return render_template(app.config.get("BEET_LOGIN_TEMPLATE"), **locals())
return render_template(app.config.get("BEET_LOGIN_TEMPLATE"), **locals(), app=app)


@bp.route("/img/beet.png")
def beet_logo():
""" Return the BEET logo
"""
path = os.path.join(os.path.dirname(__file__), "img", "beet.png")
path = os.path.join(os.path.dirname(__file__), "static", "img", "beet.png")
return send_file(path)


@bp.route("/js/beet.js")
def beet_js():
""" Return the BEET logo
"""
path = os.path.join(os.path.dirname(__file__), "static", "js", "beet-js.js")
return send_file(path)
6 changes: 6 additions & 0 deletions requirements-test.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
pytest
pytest-mock
coverage
mock
flask-testing
flask-sqlalchemy

0 comments on commit 5078612

Please sign in to comment.